common: Drop linux/delay.h from common header
[oweals/u-boot.git] / arch / arm / mach-imx / mx6 / soc.c
index 760745656feb9fa80f5d27d39e21669bc8529953..19ca3826495de4d57424e5075bce624b8b1225b0 100644 (file)
@@ -1,18 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * (C) Copyright 2007
  * Sascha Hauer, Pengutronix
  *
  * (C) Copyright 2009 Freescale Semiconductor, Inc.
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
+#include <init.h>
+#include <linux/delay.h>
 #include <linux/errno.h>
 #include <asm/io.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/sys_proto.h>
+#include <asm/bootm.h>
 #include <asm/mach-imx/boot_mode.h>
 #include <asm/mach-imx/dma.h>
 #include <asm/mach-imx/hab.h>
 #include <imx_thermal.h>
 #include <mmc.h>
 
-enum ldo_reg {
-       LDO_ARM,
-       LDO_SOC,
-       LDO_PU,
-};
-
 struct scu_regs {
        u32     ctrl;
        u32     config;
@@ -50,7 +46,7 @@ U_BOOT_DEVICE(imx6_thermal) = {
 };
 #endif
 
-#if defined(CONFIG_SECURE_BOOT)
+#if defined(CONFIG_IMX_HAB)
 struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
        .bank = 0,
        .word = 6,
@@ -85,6 +81,10 @@ u32 get_cpu_rev(void)
                                type = MXC_CPU_MX6D;
                }
 
+               if (type == MXC_CPU_MX6ULL) {
+                       if (readl(SRC_BASE_ADDR + 0x1c) & (1 << 6))
+                               type = MXC_CPU_MX6ULZ;
+               }
        }
        major = ((reg >> 8) & 0xff);
        if ((major >= 1) &&
@@ -95,6 +95,11 @@ u32 get_cpu_rev(void)
                        type = MXC_CPU_MX6DP;
        }
        reg &= 0xff;            /* mx6 silicon revision */
+
+       /* For 6DQ, the value 0x00630005 is Silicon revision 1.3*/
+       if (((type == MXC_CPU_MX6Q) || (type == MXC_CPU_MX6D)) && (reg == 0x5))
+               reg = 0x3;
+
        return (type << 12) | (reg + (0x10 * (major + 1)));
 }
 
@@ -114,6 +119,12 @@ u32 get_cpu_rev(void)
 #define OCOTP_CFG3_SPEED_528MHZ 1
 #define OCOTP_CFG3_SPEED_696MHZ 2
 
+/*
+ * For i.MX6ULL
+ */
+#define OCOTP_CFG3_SPEED_792MHZ 2
+#define OCOTP_CFG3_SPEED_900MHZ 3
+
 u32 get_cpu_speed_grade_hz(void)
 {
        struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
@@ -126,7 +137,7 @@ u32 get_cpu_speed_grade_hz(void)
        val >>= OCOTP_CFG3_SPEED_SHIFT;
        val &= 0x3;
 
-       if (is_mx6ul() || is_mx6ull()) {
+       if (is_mx6ul()) {
                if (val == OCOTP_CFG3_SPEED_528MHZ)
                        return 528000000;
                else if (val == OCOTP_CFG3_SPEED_696MHZ)
@@ -135,6 +146,17 @@ u32 get_cpu_speed_grade_hz(void)
                        return 0;
        }
 
+       if (is_mx6ull()) {
+               if (val == OCOTP_CFG3_SPEED_528MHZ)
+                       return 528000000;
+               else if (val == OCOTP_CFG3_SPEED_792MHZ)
+                       return 792000000;
+               else if (val == OCOTP_CFG3_SPEED_900MHZ)
+                       return 900000000;
+               else
+                       return 0;
+       }
+
        switch (val) {
        /* Valid for IMX6DQ */
        case OCOTP_CFG3_SPEED_1P2GHZ:
@@ -228,12 +250,16 @@ static void clear_ldo_ramp(void)
  * Possible values are from 0.725V to 1.450V in steps of
  * 0.025V (25mV).
  */
-static int set_ldo_voltage(enum ldo_reg ldo, u32 mv)
+int set_ldo_voltage(enum ldo_reg ldo, u32 mv)
 {
        struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
        u32 val, step, old, reg = readl(&anatop->reg_core);
        u8 shift;
 
+       /* No LDO_SOC/PU/ARM */
+       if (is_mx6sll())
+               return 0;
+
        if (mv < 725)
                val = 0x00;     /* Power gated off */
        else if (mv > 1450)
@@ -293,7 +319,7 @@ static void clear_mmdc_ch_mask(void)
        reg = readl(&mxc_ccm->ccdr);
 
        /* Clear MMDC channel mask */
-       if (is_mx6sx() || is_mx6ul() || is_mx6ull() || is_mx6sl())
+       if (is_mx6sx() || is_mx6ul() || is_mx6ull() || is_mx6sl() || is_mx6sll())
                reg &= ~(MXC_CCM_CCDR_MMDC_CH1_HS_MASK);
        else
                reg &= ~(MXC_CCM_CCDR_MMDC_CH1_HS_MASK | MXC_CCM_CCDR_MMDC_CH0_HS_MASK);
@@ -344,20 +370,41 @@ static void init_bandgap(void)
        }
 }
 
-#ifdef CONFIG_MX6SL
-static void set_preclk_from_osc(void)
+#if defined(CONFIG_MX6Q) || defined(CONFIG_MX6QDL)
+static void noc_setup(void)
 {
-       struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
-       u32 reg;
-
-       reg = readl(&mxc_ccm->cscmr1);
-       reg |= MXC_CCM_CSCMR1_PER_CLK_SEL_MASK;
-       writel(reg, &mxc_ccm->cscmr1);
+       enable_ipu_clock();
+
+       writel(0x80000201, 0xbb0608);
+       /* Bypass IPU1 QoS generator */
+       writel(0x00000002, 0x00bb048c);
+       /* Bypass IPU2 QoS generator */
+       writel(0x00000002, 0x00bb050c);
+       /* Bandwidth THR for of PRE0 */
+       writel(0x00000200, 0x00bb0690);
+       /* Bandwidth THR for of PRE1 */
+       writel(0x00000200, 0x00bb0710);
+       /* Bandwidth THR for of PRE2 */
+       writel(0x00000200, 0x00bb0790);
+       /* Bandwidth THR for of PRE3 */
+       writel(0x00000200, 0x00bb0810);
+       /* Saturation THR for of PRE0 */
+       writel(0x00000010, 0x00bb0694);
+       /* Saturation THR for of PRE1 */
+       writel(0x00000010, 0x00bb0714);
+       /* Saturation THR for of PRE2 */
+       writel(0x00000010, 0x00bb0794);
+       /* Saturation THR for of PRE */
+       writel(0x00000010, 0x00bb0814);
+
+       disable_ipu_clock();
 }
 #endif
 
 int arch_cpu_init(void)
 {
+       struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
        init_aips();
 
        /* Need to clear MMDC_CHx_MASK to make warm reset work. */
@@ -421,14 +468,20 @@ int arch_cpu_init(void)
        }
 
        /* Set perclk to source from OSC 24MHz */
-#if defined(CONFIG_MX6SL)
-       set_preclk_from_osc();
-#endif
+       if (is_mx6sl())
+               setbits_le32(&ccm->cscmr1, MXC_CCM_CSCMR1_PER_CLK_SEL_MASK);
+
+       imx_wdog_disable_powerdown(); /* Disable PDE bit of WMCR register */
 
-       imx_set_wdog_powerdown(false); /* Disable PDE bit of WMCR register */
+       if (is_mx6sx())
+               setbits_le32(&ccm->cscdr1, MXC_CCM_CSCDR1_UART_CLK_SEL);
 
        init_src();
 
+#if defined(CONFIG_MX6Q) || defined(CONFIG_MX6QDL)
+       if (is_mx6dqp())
+               noc_setup();
+#endif
        return 0;
 }
 
@@ -495,45 +548,16 @@ uint mmc_get_env_part(struct mmc *mmc)
 
 int board_postclk_init(void)
 {
+       /* NO LDO SOC on i.MX6SLL */
+       if (is_mx6sll())
+               return 0;
+
        set_ldo_voltage(LDO_SOC, 1175); /* Set VDDSOC to 1.175V */
 
        return 0;
 }
 
-#if defined(CONFIG_FEC_MXC)
-void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
-{
-       struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
-       struct fuse_bank *bank = &ocotp->bank[4];
-       struct fuse_bank4_regs *fuse =
-                       (struct fuse_bank4_regs *)bank->fuse_regs;
-
-       if ((is_mx6sx() || is_mx6ul() || is_mx6ull()) && dev_id == 1) {
-               u32 value = readl(&fuse->mac_addr2);
-               mac[0] = value >> 24 ;
-               mac[1] = value >> 16 ;
-               mac[2] = value >> 8 ;
-               mac[3] = value ;
-
-               value = readl(&fuse->mac_addr1);
-               mac[4] = value >> 24 ;
-               mac[5] = value >> 16 ;
-               
-       } else {
-               u32 value = readl(&fuse->mac_addr1);
-               mac[0] = (value >> 8);
-               mac[1] = value ;
-
-               value = readl(&fuse->mac_addr0);
-               mac[2] = value >> 24 ;
-               mac[3] = value >> 16 ;
-               mac[4] = value >> 8 ;
-               mac[5] = value ;
-       }
-
-}
-#endif
-
+#ifndef CONFIG_SPL_BUILD
 /*
  * cfg_val will be used for
  * Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0]
@@ -560,12 +584,15 @@ const struct boot_mode soc_boot_modes[] = {
        {"esdhc4",      MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)},
        {NULL,          0},
 };
+#endif
 
 void reset_misc(void)
 {
-#ifdef CONFIG_VIDEO_MXS
+#ifndef CONFIG_SPL_BUILD
+#if defined(CONFIG_VIDEO_MXS) && !defined(CONFIG_DM_VIDEO)
        lcdif_power_down();
 #endif
+#endif
 }
 
 void s_init(void)
@@ -576,7 +603,7 @@ void s_init(void)
        u32 mask528;
        u32 reg, periph1, periph2;
 
-       if (is_mx6sx() || is_mx6ul() || is_mx6ull())
+       if (is_mx6sx() || is_mx6ul() || is_mx6ull() || is_mx6sll())
                return;
 
        /* Due to hardware limitation, on MX6Q we need to gate/ungate all PFDs
@@ -664,40 +691,32 @@ void imx_setup_hdmi(void)
 }
 #endif
 
-#ifdef CONFIG_IMX_BOOTAUX
-int arch_auxiliary_core_up(u32 core_id, u32 boot_private_data)
-{
-       struct src *src_reg;
-       u32 stack, pc;
-
-       if (!boot_private_data)
-               return -EINVAL;
-
-       stack = *(u32 *)boot_private_data;
-       pc = *(u32 *)(boot_private_data + 4);
 
-       /* Set the stack and pc to M4 bootROM */
-       writel(stack, M4_BOOTROM_BASE_ADDR);
-       writel(pc, M4_BOOTROM_BASE_ADDR + 4);
-
-       /* Enable M4 */
-       src_reg = (struct src *)SRC_BASE_ADDR;
-       clrsetbits_le32(&src_reg->scr, SRC_SCR_M4C_NON_SCLR_RST_MASK,
-                       SRC_SCR_M4_ENABLE_MASK);
-
-       return 0;
-}
-
-int arch_auxiliary_core_check_up(u32 core_id)
+/*
+ * gpr_init() function is common for boards using MX6S, MX6DL, MX6D,
+ * MX6Q and MX6QP processors
+ */
+void gpr_init(void)
 {
-       struct src *src_reg = (struct src *)SRC_BASE_ADDR;
-       unsigned val;
+       struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
 
-       val = readl(&src_reg->scr);
-
-       if (val & SRC_SCR_M4C_NON_SCLR_RST_MASK)
-               return 0;  /* assert in reset */
+       /*
+        * If this function is used in a common MX6 spl implementation
+        * we have to ensure that it is only called for suitable cpu types,
+        * otherwise it breaks hardware parts like enet1, can1, can2, etc.
+        */
+       if (!is_mx6dqp() && !is_mx6dq() && !is_mx6sdl())
+               return;
 
-       return 1;
+       /* enable AXI cache for VDOA/VPU/IPU */
+       writel(0xF00000CF, &iomux->gpr[4]);
+       if (is_mx6dqp()) {
+               /* set IPU AXI-id1 Qos=0x1 AXI-id0/2/3 Qos=0x7 */
+               writel(0x77177717, &iomux->gpr[6]);
+               writel(0x77177717, &iomux->gpr[7]);
+       } else {
+               /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
+               writel(0x007F007F, &iomux->gpr[6]);
+               writel(0x007F007F, &iomux->gpr[7]);
+       }
 }
-#endif