]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - arch/arm/cpu/armv7/mx7/soc.c
mx7: Fix speed grade entry
[people/ms/u-boot.git] / arch / arm / cpu / armv7 / mx7 / soc.c
index 1d8e4709713ef9a7ae7ec9e9a137f97d07314fd8..b9fb97bdb6a3c838e56f09af6755481da819a979 100644 (file)
@@ -12,6 +12,8 @@
 #include <asm/imx-common/boot_mode.h>
 #include <asm/imx-common/dma.h>
 #include <asm/imx-common/hab.h>
+#include <asm/imx-common/rdc-sema.h>
+#include <asm/arch/imx-rdc.h>
 #include <asm/arch/crm_regs.h>
 #include <dm.h>
 #include <imx_thermal.h>
@@ -29,6 +31,65 @@ U_BOOT_DEVICE(imx7_thermal) = {
 };
 #endif
 
+#ifdef CONFIG_IMX_RDC
+/*
+ * In current design, if any peripheral was assigned to both A7 and M4,
+ * it will receive ipg_stop or ipg_wait when any of the 2 platforms enter
+ * low power mode. So M4 sleep will cause some peripherals fail to work
+ * at A7 core side. At default, all resources are in domain 0 - 3.
+ *
+ * There are 26 peripherals impacted by this IC issue:
+ * SIM2(sim2/emvsim2)
+ * SIM1(sim1/emvsim1)
+ * UART1/UART2/UART3/UART4/UART5/UART6/UART7
+ * SAI1/SAI2/SAI3
+ * WDOG1/WDOG2/WDOG3/WDOG4
+ * GPT1/GPT2/GPT3/GPT4
+ * PWM1/PWM2/PWM3/PWM4
+ * ENET1/ENET2
+ * Software Workaround:
+ * Here we setup some resources to domain 0 where M4 codes will move
+ * the M4 out of this domain. Then M4 is not able to access them any longer.
+ * This is a workaround for ic issue. So the peripherals are not shared
+ * by them. This way requires the uboot implemented the RDC driver and
+ * set the 26 IPs above to domain 0 only. M4 code will assign resource
+ * to its own domain, if it want to use the resource.
+ */
+static rdc_peri_cfg_t const resources[] = {
+       (RDC_PER_SIM1 | RDC_DOMAIN(0)),
+       (RDC_PER_SIM2 | RDC_DOMAIN(0)),
+       (RDC_PER_UART1 | RDC_DOMAIN(0)),
+       (RDC_PER_UART2 | RDC_DOMAIN(0)),
+       (RDC_PER_UART3 | RDC_DOMAIN(0)),
+       (RDC_PER_UART4 | RDC_DOMAIN(0)),
+       (RDC_PER_UART5 | RDC_DOMAIN(0)),
+       (RDC_PER_UART6 | RDC_DOMAIN(0)),
+       (RDC_PER_UART7 | RDC_DOMAIN(0)),
+       (RDC_PER_SAI1 | RDC_DOMAIN(0)),
+       (RDC_PER_SAI2 | RDC_DOMAIN(0)),
+       (RDC_PER_SAI3 | RDC_DOMAIN(0)),
+       (RDC_PER_WDOG1 | RDC_DOMAIN(0)),
+       (RDC_PER_WDOG2 | RDC_DOMAIN(0)),
+       (RDC_PER_WDOG3 | RDC_DOMAIN(0)),
+       (RDC_PER_WDOG4 | RDC_DOMAIN(0)),
+       (RDC_PER_GPT1 | RDC_DOMAIN(0)),
+       (RDC_PER_GPT2 | RDC_DOMAIN(0)),
+       (RDC_PER_GPT3 | RDC_DOMAIN(0)),
+       (RDC_PER_GPT4 | RDC_DOMAIN(0)),
+       (RDC_PER_PWM1 | RDC_DOMAIN(0)),
+       (RDC_PER_PWM2 | RDC_DOMAIN(0)),
+       (RDC_PER_PWM3 | RDC_DOMAIN(0)),
+       (RDC_PER_PWM4 | RDC_DOMAIN(0)),
+       (RDC_PER_ENET1 | RDC_DOMAIN(0)),
+       (RDC_PER_ENET2 | RDC_DOMAIN(0)),
+};
+
+static void isolate_resource(void)
+{
+       imx_rdc_setup_peripherals(resources, ARRAY_SIZE(resources));
+}
+#endif
+
 #if defined(CONFIG_SECURE_BOOT)
 struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
        .bank = 1,
@@ -42,7 +103,7 @@ struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
  */
 #define OCOTP_TESTER3_SPEED_SHIFT      8
 #define OCOTP_TESTER3_SPEED_800MHZ     0
-#define OCOTP_TESTER3_SPEED_850MHZ     1
+#define OCOTP_TESTER3_SPEED_500MHZ     1
 #define OCOTP_TESTER3_SPEED_1GHZ       2
 
 u32 get_cpu_speed_grade_hz(void)
@@ -60,8 +121,8 @@ u32 get_cpu_speed_grade_hz(void)
        switch(val) {
        case OCOTP_TESTER3_SPEED_800MHZ:
                return 792000000;
-       case OCOTP_TESTER3_SPEED_850MHZ:
-               return 852000000;
+       case OCOTP_TESTER3_SPEED_500MHZ:
+               return 500000000;
        case OCOTP_TESTER3_SPEED_1GHZ:
                return 996000000;
        }
@@ -104,6 +165,21 @@ u32 get_cpu_temp_grade(int *minc, int *maxc)
        return val;
 }
 
+static bool is_mx7d(void)
+{
+       struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
+       struct fuse_bank *bank = &ocotp->bank[1];
+       struct fuse_bank1_regs *fuse =
+               (struct fuse_bank1_regs *)bank->fuse_regs;
+       int val;
+
+       val = readl(&fuse->tester4);
+       if (val & 1)
+               return false;
+       else
+               return true;
+}
+
 u32 get_cpu_rev(void)
 {
        struct mxc_ccm_anatop_reg *ccm_anatop = (struct mxc_ccm_anatop_reg *)
@@ -111,6 +187,9 @@ u32 get_cpu_rev(void)
        u32 reg = readl(&ccm_anatop->digprog);
        u32 type = (reg >> 16) & 0xff;
 
+       if (!is_mx7d())
+               type = MXC_CPU_MX7S;
+
        reg &= 0xff;
        return (type << 12) | reg;
 }
@@ -163,9 +242,26 @@ int arch_cpu_init(void)
        mxs_dma_init();
 #endif
 
+       if (IS_ENABLED(CONFIG_IMX_RDC))
+               isolate_resource();
+
        return 0;
 }
 
+#ifdef CONFIG_ARCH_MISC_INIT
+int arch_misc_init(void)
+{
+#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+       if (is_mx7d())
+               setenv("soc", "imx7d");
+       else
+               setenv("soc", "imx7s");
+#endif
+
+       return 0;
+}
+#endif
+
 #ifdef CONFIG_SERIAL_TAG
 void get_board_serial(struct tag_serialnr *serialnr)
 {
@@ -211,6 +307,42 @@ void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
 }
 #endif
 
+#ifdef CONFIG_IMX_BOOTAUX
+int arch_auxiliary_core_up(u32 core_id, u32 boot_private_data)
+{
+       u32 stack, pc;
+       struct src *src_reg = (struct src *)SRC_BASE_ADDR;
+
+       if (!boot_private_data)
+               return 1;
+
+       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 */
+       clrsetbits_le32(&src_reg->m4rcr, SRC_M4RCR_M4C_NON_SCLR_RST_MASK,
+                       SRC_M4RCR_ENABLE_M4_MASK);
+
+       return 0;
+}
+
+int arch_auxiliary_core_check_up(u32 core_id)
+{
+       uint32_t val;
+       struct src *src_reg = (struct src *)SRC_BASE_ADDR;
+
+       val = readl(&src_reg->m4rcr);
+       if (val & 0x00000001)
+               return 0; /* assert in reset */
+
+       return 1;
+}
+#endif
+
 void set_wdog_reset(struct wdog_regs *wdog)
 {
        u32 reg = readw(&wdog->wcr);
@@ -288,6 +420,27 @@ enum boot_device get_boot_device(void)
        return boot_dev;
 }
 
+#ifdef CONFIG_ENV_IS_IN_MMC
+__weak int board_mmc_get_env_dev(int devno)
+{
+       return CONFIG_SYS_MMC_ENV_DEV;
+}
+
+int mmc_get_env_dev(void)
+{
+       struct bootrom_sw_info **p =
+               (struct bootrom_sw_info **)ROM_SW_INFO_ADDR;
+       int devno = (*p)->boot_dev_instance;
+       u8 boot_type = (*p)->boot_dev_type;
+
+       /* If not boot from sd/mmc, use default value */
+       if ((boot_type != BOOT_TYPE_SD) && (boot_type != BOOT_TYPE_MMC))
+               return CONFIG_SYS_MMC_ENV_DEV;
+
+       return board_mmc_get_env_dev(devno);
+}
+#endif
+
 void s_init(void)
 {
 #if !defined CONFIG_SPL_BUILD
@@ -302,3 +455,11 @@ void s_init(void)
 
        return;
 }
+
+void reset_misc(void)
+{
+#ifdef CONFIG_VIDEO_MXS
+       lcdif_power_down();
+#endif
+}
+