Message ID | 1482833066-29291-6-git-send-email-peng.fan@nxp.com |
---|---|
State | Changes Requested |
Delegated to: | Stefano Babic |
Headers | show |
Hi Peng, On 27/12/2016 11:04, Peng Fan wrote: > Implement soc level functions to get cpu rev, reset cause, enable cache, > etc. We will disable the wdog and init clocks in s_init at very early u-boot > phase. > > Since the we are seeking the way to get chip id for mx7ulp, the get_cpu_rev > is hard coded to a fixed value. This may change in future. > ok, understood, noted > Reuse some code in imx-common. > > Signed-off-by: Peng Fan <peng.fan@nxp.com> > Signed-off-by: Ye Li <ye.li@nxp.com> > Cc: Stefano Babic <sbabic@denx.de> > --- > > V2: > Reuse code in imx-common > > arch/arm/Makefile | 2 +- > arch/arm/cpu/armv7/mx7ulp/Makefile | 2 +- > arch/arm/cpu/armv7/mx7ulp/soc.c | 274 +++++++++++++++++++++++++++ > arch/arm/imx-common/Makefile | 4 + > arch/arm/include/asm/arch-imx/cpu.h | 2 + > arch/arm/include/asm/arch-mx7ulp/imx-regs.h | 5 + > arch/arm/include/asm/arch-mx7ulp/sys_proto.h | 21 ++ > 7 files changed, 308 insertions(+), 2 deletions(-) > create mode 100644 arch/arm/cpu/armv7/mx7ulp/soc.c > create mode 100644 arch/arm/include/asm/arch-mx7ulp/sys_proto.h > > diff --git a/arch/arm/Makefile b/arch/arm/Makefile > index ef4f69d..0921a66 100644 > --- a/arch/arm/Makefile > +++ b/arch/arm/Makefile > @@ -99,7 +99,7 @@ ifneq (,$(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_MX35)$(filter $(SOC), mx25 mx27 mx5 > libs-y += arch/arm/imx-common/ > endif > else > -ifneq (,$(filter $(SOC), mx25 mx27 mx5 mx6 mx7 mx31 mx35 mxs vf610)) > +ifneq (,$(filter $(SOC), mx25 mx27 mx5 mx6 mx7 mx7ulp mx31 mx35 mxs vf610)) > libs-y += arch/arm/imx-common/ > endif > endif > diff --git a/arch/arm/cpu/armv7/mx7ulp/Makefile b/arch/arm/cpu/armv7/mx7ulp/Makefile > index 6f37e8c..0248ea8 100644 > --- a/arch/arm/cpu/armv7/mx7ulp/Makefile > +++ b/arch/arm/cpu/armv7/mx7ulp/Makefile > @@ -5,4 +5,4 @@ > # > # > > -obj-y := clock.o iomux.o pcc.o scg.o > +obj-y := soc.o clock.o iomux.o pcc.o scg.o > diff --git a/arch/arm/cpu/armv7/mx7ulp/soc.c b/arch/arm/cpu/armv7/mx7ulp/soc.c > new file mode 100644 > index 0000000..d04edc5 > --- /dev/null > +++ b/arch/arm/cpu/armv7/mx7ulp/soc.c > @@ -0,0 +1,274 @@ > +/* > + * Copyright (C) 2016 Freescale Semiconductor, Inc. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > +#include <asm/io.h> > +#include <asm/arch/clock.h> > +#include <asm/arch/imx-regs.h> > +#include <asm/arch/sys_proto.h> > + > +static char *get_reset_cause(char *); > + > +u32 get_cpu_rev(void) > +{ > + /* Temporally hard code the CPU rev to 0x73, rev 1.0. Fix it later */ > + return (MXC_CPU_MX7ULP << 12) | (1 << 4); > +} > + > +#ifdef CONFIG_REVISION_TAG > +u32 __weak get_board_rev(void) > +{ > + return get_cpu_rev(); > +} > +#endif > + > +enum bt_mode get_boot_mode(void) > +{ > + u32 bt0_cfg = 0; > + > + bt0_cfg = readl(CMC0_RBASE + 0x40); > + bt0_cfg &= (BT0CFG_LPBOOT_MASK | BT0CFG_DUALBOOT_MASK); > + > + if (!(bt0_cfg & BT0CFG_LPBOOT_MASK)) { > + /* No low power boot */ > + if (bt0_cfg & BT0CFG_DUALBOOT_MASK) > + return DUAL_BOOT; > + else > + return SINGLE_BOOT; > + } > + > + return LOW_POWER_BOOT; > +} > + > +int arch_cpu_init(void) > +{ > + return 0; > +} > + > +#ifdef CONFIG_BOARD_POSTCLK_INIT > +int board_postclk_init(void) > +{ > + return 0; > +} > +#endif > + > +#define UNLOCK_WORD0 0xC520 /* 1st unlock word */ > +#define UNLOCK_WORD1 0xD928 /* 2nd unlock word */ > +#define REFRESH_WORD0 0xA602 /* 1st refresh word */ > +#define REFRESH_WORD1 0xB480 /* 2nd refresh word */ > + > +static void disable_wdog(u32 wdog_base) > +{ > + writel(UNLOCK_WORD0, (wdog_base + 0x04)); > + writel(UNLOCK_WORD1, (wdog_base + 0x04)); > + writel(0x0, (wdog_base + 0x0C)); /* Set WIN to 0 */ > + writel(0x400, (wdog_base + 0x08)); /* Set timeout to default 0x400 */ > + writel(0x120, (wdog_base + 0x00)); /* Disable it and set update */ > + > + writel(REFRESH_WORD0, (wdog_base + 0x04)); /* Refresh the CNT */ > + writel(REFRESH_WORD1, (wdog_base + 0x04)); > +} > + > +void init_wdog(void) > +{ > + /* > + * ROM will configure WDOG1, disable it or enable it > + * depending on FUSE. The update bit is set for reconfigurable. > + * We have to use unlock sequence to reconfigure it. > + * WDOG2 is not touched by ROM, so it will have default value > + * which is enabled. We can directly configure it. > + * To simplify the codes, we still use same reconfigure > + * process as WDOG1. Because the update bit is not set for > + * WDOG2, the unlock sequence won't take effect really. > + * It actually directly configure the wdog. > + * In this function, we will disable both WDOG1 and WDOG2, > + * and set update bit for both. So that kernel can reconfigure them. > + */ > + disable_wdog(WDG1_RBASE); > + disable_wdog(WDG2_RBASE); > +} > + > + > +void s_init(void) > +{ > + /* Disable wdog */ > + init_wdog(); > + > + /* clock configuration. */ > + clock_init(); > + > + return; > +} > + > +#ifndef CONFIG_ULP_WATCHDOG > +void reset_cpu(ulong addr) > +{ > + setbits_le32(SIM0_RBASE, SIM_SOPT1_A7_SW_RESET); > + while (1) > + ; > +} > +#endif > + > +#if defined(CONFIG_DISPLAY_CPUINFO) > +const char *get_imx_type(u32 imxtype) > +{ > +#ifdef CONFIG_MXC_OCOTP > + > + u8 uid[8]; > + u32 val; > + > + struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; > + struct fuse_bank *bank = &ocotp->bank[0]; > + struct fuse_bank1_regs *fuse = > + (struct fuse_bank1_regs *)bank->fuse_regs; > + > + val = readl(&fuse->cfg0); > + *uid = val & 0xFF; > + *(uid + 1) = (val & 0xFF00) >> 8; > + > + val = readl(&fuse->cfg1); > + *(uid + 2) = val & 0xFF; > + *(uid + 3) = (val & 0xFF00) >> 8; > + > + val = readl(&fuse->cfg2); > + *(uid + 4) = val & 0xFF; > + *(uid + 5) = (val & 0xFF00) >> 8; > + > + val = readl(&fuse->cfg3); > + *(uid + 6) = val & 0xFF; > + *(uid + 7) = (val & 0xFF00) >> 8; I think it can be better described here, at least what you want to read for fuse->cfg0..cfg3. > + > + debug("UID = %02X %02X %02X %02X %02X %02X %02X %02X\r\n", > + uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]); > + > +#endif > + return "7ULP"; > +} > + > +int print_cpuinfo(void) > +{ > + u32 cpurev; > + char cause[18]; > + > + cpurev = get_cpu_rev(); > + > + printf("CPU: Freescale i.MX%s rev%d.%d at %d MHz\n", > + get_imx_type((cpurev & 0xFF000) >> 12), > + (cpurev & 0x000F0) >> 4, (cpurev & 0x0000F) >> 0, > + mxc_get_clock(MXC_ARM_CLK) / 1000000); > + > + printf("Reset cause: %s\n", get_reset_cause(cause)); > + > + printf("Boot mode: "); > + switch (get_boot_mode()) { > + case LOW_POWER_BOOT: > + printf("Low power boot\n"); > + break; > + case DUAL_BOOT: > + printf("Dual boot\n"); > + break; > + case SINGLE_BOOT: > + default: > + printf("Single boot\n"); > + break; > + } > + > + return 0; > +} > +#endif > + > +#define CMC_SRS_TAMPER (1 << 31) > +#define CMC_SRS_SECURITY (1 << 30) > +#define CMC_SRS_TZWDG (1 << 29) > +#define CMC_SRS_JTAG_RST (1 << 28) > +#define CMC_SRS_CORE1 (1 << 16) > +#define CMC_SRS_LOCKUP (1 << 15) > +#define CMC_SRS_SW (1 << 14) > +#define CMC_SRS_WDG (1 << 13) > +#define CMC_SRS_PIN_RESET (1 << 8) > +#define CMC_SRS_WARM (1 << 4) > +#define CMC_SRS_HVD (1 << 3) > +#define CMC_SRS_LVD (1 << 2) > +#define CMC_SRS_POR (1 << 1) > +#define CMC_SRS_WUP (1 << 0) > + > +static u32 reset_cause = -1; > + > +static char *get_reset_cause(char *ret) > +{ > + u32 cause1, cause = 0, srs = 0; > + u32 *reg_ssrs = (u32 *)(SRC_BASE_ADDR + 0x28); > + u32 *reg_srs = (u32 *)(SRC_BASE_ADDR + 0x20); > + > + if (!ret) > + return "null"; > + > + srs = readl(reg_srs); > + cause1 = readl(reg_ssrs); > + writel(cause1, reg_ssrs); > + > + reset_cause = cause1; > + > + cause = cause1 & (CMC_SRS_POR | CMC_SRS_WUP | CMC_SRS_WARM); > + > + switch (cause) { > + case CMC_SRS_POR: > + sprintf(ret, "%s", "POR"); > + break; > + case CMC_SRS_WUP: > + sprintf(ret, "%s", "WUP"); > + break; > + case CMC_SRS_WARM: > + cause = cause1 & (CMC_SRS_WDG | CMC_SRS_SW | > + CMC_SRS_JTAG_RST); > + switch (cause) { > + case CMC_SRS_WDG: > + sprintf(ret, "%s", "WARM-WDG"); > + break; > + case CMC_SRS_SW: > + sprintf(ret, "%s", "WARM-SW"); > + break; > + case CMC_SRS_JTAG_RST: > + sprintf(ret, "%s", "WARM-JTAG"); > + break; > + default: > + sprintf(ret, "%s", "WARM-UNKN"); > + break; > + } > + break; > + default: > + sprintf(ret, "%s-%X", "UNKN", cause1); > + break; > + } > + > + debug("[%X] SRS[%X] %X - ", cause1, srs, srs^cause1); > + return ret; > +} > + > +u32 get_imx_reset_cause(void) > +{ > + return reset_cause; Why do you stored it ain a static variable ? Is it read just once from registers ? > +} > + > +#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) > +{ > + int devno = 0; > + u32 bt1_cfg = 0; > + > + /* If not boot from sd/mmc, use default value */ > + if (get_boot_mode() == LOW_POWER_BOOT) > + return CONFIG_SYS_MMC_ENV_DEV; > + > + bt1_cfg = readl(CMC1_RBASE + 0x40); > + devno = (bt1_cfg >> 9) & 0x7; > + > + return board_mmc_get_env_dev(devno); > +} > +#endif > diff --git a/arch/arm/imx-common/Makefile b/arch/arm/imx-common/Makefile > index 1873185..68ee60f 100644 > --- a/arch/arm/imx-common/Makefile > +++ b/arch/arm/imx-common/Makefile > @@ -31,6 +31,10 @@ obj-$(CONFIG_IMX_RDC) += rdc-sema.o > obj-$(CONFIG_IMX_BOOTAUX) += imx_bootaux.o > obj-$(CONFIG_SECURE_BOOT) += hab.o > endif > +ifeq ($(SOC),$(filter $(SOC),mx7ulp)) > +obj-y += cache.o > +obj-$(CONFIG_SECURE_BOOT) += hab.o > +endif > ifeq ($(SOC),$(filter $(SOC),vf610)) > obj-y += ddrmc-vf610.o > endif > diff --git a/arch/arm/include/asm/arch-imx/cpu.h b/arch/arm/include/asm/arch-imx/cpu.h > index 8bd1421..b052406 100644 > --- a/arch/arm/include/asm/arch-imx/cpu.h > +++ b/arch/arm/include/asm/arch-imx/cpu.h > @@ -25,10 +25,12 @@ > #define MXC_CPU_MX6QP 0x69 > #define MXC_CPU_MX7S 0x71 /* dummy ID */ > #define MXC_CPU_MX7D 0x72 > +#define MXC_CPU_MX7ULP 0x81 /* Temporally hard code */ ok > #define MXC_CPU_VF610 0xF6 /* dummy ID */ > > #define MXC_SOC_MX6 0x60 > #define MXC_SOC_MX7 0x70 > +#define MXC_SOC_MX7ULP 0x80 /* dummy */ > > #define CHIP_REV_1_0 0x10 > #define CHIP_REV_1_1 0x11 > diff --git a/arch/arm/include/asm/arch-mx7ulp/imx-regs.h b/arch/arm/include/asm/arch-mx7ulp/imx-regs.h > index 30d0ba4..cdfbe2e 100644 > --- a/arch/arm/include/asm/arch-mx7ulp/imx-regs.h > +++ b/arch/arm/include/asm/arch-mx7ulp/imx-regs.h > @@ -97,6 +97,11 @@ > #define CORE_B_ROM_SIZE (SZ_32K + SZ_64K) > #define CORE_B_ROM_BASE (0x00000000) > > +#define ROMCP_ARB_BASE_ADDR CORE_B_ROM_BASE > +#define ROMCP_ARB_END_ADDR CORE_B_ROM_SIZE > +#define IRAM_BASE_ADDR OCRAM_0_BASE > +#define IRAM_SIZE (SZ_128K + SZ_128K) > + Why is it here and not in Patch 2/20 ? > #define IOMUXC_PCR_MUX_ALT0 (0<<8) > #define IOMUXC_PCR_MUX_ALT1 (1<<8) > #define IOMUXC_PCR_MUX_ALT2 (2<<8) > diff --git a/arch/arm/include/asm/arch-mx7ulp/sys_proto.h b/arch/arm/include/asm/arch-mx7ulp/sys_proto.h > new file mode 100644 > index 0000000..d01748f > --- /dev/null > +++ b/arch/arm/include/asm/arch-mx7ulp/sys_proto.h > @@ -0,0 +1,21 @@ > +/* > + * Copyright (C) 2016 Freescale Semiconductor, Inc. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#ifndef _SYS_PROTO_MX7ULP_H_ > +#define _SYS_PROTO_MX7ULP_H_ > + > +#include <asm/imx-common/sys_proto.h> > + > +#define BT0CFG_LPBOOT_MASK 0x1 > +#define BT0CFG_DUALBOOT_MASK 0x2 > + > +enum bt_mode { > + LOW_POWER_BOOT, /* LP_BT = 1 */ > + DUAL_BOOT, /* LP_BT = 0, DUAL_BT = 1 */ > + SINGLE_BOOT /* LP_BT = 0, DUAL_BT = 0 */ > +}; > + > +#endif > Best regards, Stefano Babic
On Sun, Feb 12, 2017 at 10:19:41AM +0100, Stefano Babic wrote: >Hi Peng, > >On 27/12/2016 11:04, Peng Fan wrote: >> Implement soc level functions to get cpu rev, reset cause, enable cache, >> etc. We will disable the wdog and init clocks in s_init at very early u-boot >> phase. >> >> Since the we are seeking the way to get chip id for mx7ulp, the get_cpu_rev >> is hard coded to a fixed value. This may change in future. >> > >ok, understood, noted > >> Reuse some code in imx-common. >> >> Signed-off-by: Peng Fan <peng.fan@nxp.com> >> Signed-off-by: Ye Li <ye.li@nxp.com> >> Cc: Stefano Babic <sbabic@denx.de> >> --- >> [.......] >> + >> +#if defined(CONFIG_DISPLAY_CPUINFO) >> +const char *get_imx_type(u32 imxtype) >> +{ >> +#ifdef CONFIG_MXC_OCOTP >> + >> + u8 uid[8]; >> + u32 val; >> + >> + struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; >> + struct fuse_bank *bank = &ocotp->bank[0]; >> + struct fuse_bank1_regs *fuse = >> + (struct fuse_bank1_regs *)bank->fuse_regs; >> + >> + val = readl(&fuse->cfg0); >> + *uid = val & 0xFF; >> + *(uid + 1) = (val & 0xFF00) >> 8; >> + >> + val = readl(&fuse->cfg1); >> + *(uid + 2) = val & 0xFF; >> + *(uid + 3) = (val & 0xFF00) >> 8; >> + >> + val = readl(&fuse->cfg2); >> + *(uid + 4) = val & 0xFF; >> + *(uid + 5) = (val & 0xFF00) >> 8; >> + >> + val = readl(&fuse->cfg3); >> + *(uid + 6) = val & 0xFF; >> + *(uid + 7) = (val & 0xFF00) >> 8; > >I think it can be better described here, at least what you want to read >for fuse->cfg0..cfg3. Discard in V3. > >> + >> + debug("UID = %02X %02X %02X %02X %02X %02X %02X %02X\r\n", >> + uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]); >> + >> +#endif >> + return "7ULP"; >> +} >> + [.....] >> + >> +u32 get_imx_reset_cause(void) >> +{ >> + return reset_cause; > >Why do you stored it ain a static variable ? Is it read just once from >registers ? This function could be removed, it reuses the one in imx-common.c > >> +} >> + >> +#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) >> +{ >> + int devno = 0; >> + u32 bt1_cfg = 0; >> + >> + /* If not boot from sd/mmc, use default value */ >> + if (get_boot_mode() == LOW_POWER_BOOT) >> + return CONFIG_SYS_MMC_ENV_DEV; >> + >> + bt1_cfg = readl(CMC1_RBASE + 0x40); >> + devno = (bt1_cfg >> 9) & 0x7; >> + >> + return board_mmc_get_env_dev(devno); >> +} >> +#endif >> diff --git a/arch/arm/imx-common/Makefile b/arch/arm/imx-common/Makefile >> index 1873185..68ee60f 100644 >> --- a/arch/arm/imx-common/Makefile >> +++ b/arch/arm/imx-common/Makefile >> @@ -31,6 +31,10 @@ obj-$(CONFIG_IMX_RDC) += rdc-sema.o >> obj-$(CONFIG_IMX_BOOTAUX) += imx_bootaux.o >> obj-$(CONFIG_SECURE_BOOT) += hab.o >> endif >> +ifeq ($(SOC),$(filter $(SOC),mx7ulp)) >> +obj-y += cache.o >> +obj-$(CONFIG_SECURE_BOOT) += hab.o >> +endif >> ifeq ($(SOC),$(filter $(SOC),vf610)) >> obj-y += ddrmc-vf610.o >> endif >> diff --git a/arch/arm/include/asm/arch-imx/cpu.h b/arch/arm/include/asm/arch-imx/cpu.h >> index 8bd1421..b052406 100644 >> --- a/arch/arm/include/asm/arch-imx/cpu.h >> +++ b/arch/arm/include/asm/arch-imx/cpu.h >> @@ -25,10 +25,12 @@ >> #define MXC_CPU_MX6QP 0x69 >> #define MXC_CPU_MX7S 0x71 /* dummy ID */ >> #define MXC_CPU_MX7D 0x72 >> +#define MXC_CPU_MX7ULP 0x81 /* Temporally hard code */ > >ok > >> #define MXC_CPU_VF610 0xF6 /* dummy ID */ >> >> #define MXC_SOC_MX6 0x60 >> #define MXC_SOC_MX7 0x70 >> +#define MXC_SOC_MX7ULP 0x80 /* dummy */ >> >> #define CHIP_REV_1_0 0x10 >> #define CHIP_REV_1_1 0x11 >> diff --git a/arch/arm/include/asm/arch-mx7ulp/imx-regs.h b/arch/arm/include/asm/arch-mx7ulp/imx-regs.h >> index 30d0ba4..cdfbe2e 100644 >> --- a/arch/arm/include/asm/arch-mx7ulp/imx-regs.h >> +++ b/arch/arm/include/asm/arch-mx7ulp/imx-regs.h >> @@ -97,6 +97,11 @@ >> #define CORE_B_ROM_SIZE (SZ_32K + SZ_64K) >> #define CORE_B_ROM_BASE (0x00000000) >> >> +#define ROMCP_ARB_BASE_ADDR CORE_B_ROM_BASE >> +#define ROMCP_ARB_END_ADDR CORE_B_ROM_SIZE >> +#define IRAM_BASE_ADDR OCRAM_0_BASE >> +#define IRAM_SIZE (SZ_128K + SZ_128K) >> + > >Why is it here and not in Patch 2/20 ? Move the 2/20 in V3. Thanks, Peng.
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index ef4f69d..0921a66 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -99,7 +99,7 @@ ifneq (,$(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_MX35)$(filter $(SOC), mx25 mx27 mx5 libs-y += arch/arm/imx-common/ endif else -ifneq (,$(filter $(SOC), mx25 mx27 mx5 mx6 mx7 mx31 mx35 mxs vf610)) +ifneq (,$(filter $(SOC), mx25 mx27 mx5 mx6 mx7 mx7ulp mx31 mx35 mxs vf610)) libs-y += arch/arm/imx-common/ endif endif diff --git a/arch/arm/cpu/armv7/mx7ulp/Makefile b/arch/arm/cpu/armv7/mx7ulp/Makefile index 6f37e8c..0248ea8 100644 --- a/arch/arm/cpu/armv7/mx7ulp/Makefile +++ b/arch/arm/cpu/armv7/mx7ulp/Makefile @@ -5,4 +5,4 @@ # # -obj-y := clock.o iomux.o pcc.o scg.o +obj-y := soc.o clock.o iomux.o pcc.o scg.o diff --git a/arch/arm/cpu/armv7/mx7ulp/soc.c b/arch/arm/cpu/armv7/mx7ulp/soc.c new file mode 100644 index 0000000..d04edc5 --- /dev/null +++ b/arch/arm/cpu/armv7/mx7ulp/soc.c @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h> + +static char *get_reset_cause(char *); + +u32 get_cpu_rev(void) +{ + /* Temporally hard code the CPU rev to 0x73, rev 1.0. Fix it later */ + return (MXC_CPU_MX7ULP << 12) | (1 << 4); +} + +#ifdef CONFIG_REVISION_TAG +u32 __weak get_board_rev(void) +{ + return get_cpu_rev(); +} +#endif + +enum bt_mode get_boot_mode(void) +{ + u32 bt0_cfg = 0; + + bt0_cfg = readl(CMC0_RBASE + 0x40); + bt0_cfg &= (BT0CFG_LPBOOT_MASK | BT0CFG_DUALBOOT_MASK); + + if (!(bt0_cfg & BT0CFG_LPBOOT_MASK)) { + /* No low power boot */ + if (bt0_cfg & BT0CFG_DUALBOOT_MASK) + return DUAL_BOOT; + else + return SINGLE_BOOT; + } + + return LOW_POWER_BOOT; +} + +int arch_cpu_init(void) +{ + return 0; +} + +#ifdef CONFIG_BOARD_POSTCLK_INIT +int board_postclk_init(void) +{ + return 0; +} +#endif + +#define UNLOCK_WORD0 0xC520 /* 1st unlock word */ +#define UNLOCK_WORD1 0xD928 /* 2nd unlock word */ +#define REFRESH_WORD0 0xA602 /* 1st refresh word */ +#define REFRESH_WORD1 0xB480 /* 2nd refresh word */ + +static void disable_wdog(u32 wdog_base) +{ + writel(UNLOCK_WORD0, (wdog_base + 0x04)); + writel(UNLOCK_WORD1, (wdog_base + 0x04)); + writel(0x0, (wdog_base + 0x0C)); /* Set WIN to 0 */ + writel(0x400, (wdog_base + 0x08)); /* Set timeout to default 0x400 */ + writel(0x120, (wdog_base + 0x00)); /* Disable it and set update */ + + writel(REFRESH_WORD0, (wdog_base + 0x04)); /* Refresh the CNT */ + writel(REFRESH_WORD1, (wdog_base + 0x04)); +} + +void init_wdog(void) +{ + /* + * ROM will configure WDOG1, disable it or enable it + * depending on FUSE. The update bit is set for reconfigurable. + * We have to use unlock sequence to reconfigure it. + * WDOG2 is not touched by ROM, so it will have default value + * which is enabled. We can directly configure it. + * To simplify the codes, we still use same reconfigure + * process as WDOG1. Because the update bit is not set for + * WDOG2, the unlock sequence won't take effect really. + * It actually directly configure the wdog. + * In this function, we will disable both WDOG1 and WDOG2, + * and set update bit for both. So that kernel can reconfigure them. + */ + disable_wdog(WDG1_RBASE); + disable_wdog(WDG2_RBASE); +} + + +void s_init(void) +{ + /* Disable wdog */ + init_wdog(); + + /* clock configuration. */ + clock_init(); + + return; +} + +#ifndef CONFIG_ULP_WATCHDOG +void reset_cpu(ulong addr) +{ + setbits_le32(SIM0_RBASE, SIM_SOPT1_A7_SW_RESET); + while (1) + ; +} +#endif + +#if defined(CONFIG_DISPLAY_CPUINFO) +const char *get_imx_type(u32 imxtype) +{ +#ifdef CONFIG_MXC_OCOTP + + u8 uid[8]; + u32 val; + + struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; + struct fuse_bank *bank = &ocotp->bank[0]; + struct fuse_bank1_regs *fuse = + (struct fuse_bank1_regs *)bank->fuse_regs; + + val = readl(&fuse->cfg0); + *uid = val & 0xFF; + *(uid + 1) = (val & 0xFF00) >> 8; + + val = readl(&fuse->cfg1); + *(uid + 2) = val & 0xFF; + *(uid + 3) = (val & 0xFF00) >> 8; + + val = readl(&fuse->cfg2); + *(uid + 4) = val & 0xFF; + *(uid + 5) = (val & 0xFF00) >> 8; + + val = readl(&fuse->cfg3); + *(uid + 6) = val & 0xFF; + *(uid + 7) = (val & 0xFF00) >> 8; + + debug("UID = %02X %02X %02X %02X %02X %02X %02X %02X\r\n", + uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]); + +#endif + return "7ULP"; +} + +int print_cpuinfo(void) +{ + u32 cpurev; + char cause[18]; + + cpurev = get_cpu_rev(); + + printf("CPU: Freescale i.MX%s rev%d.%d at %d MHz\n", + get_imx_type((cpurev & 0xFF000) >> 12), + (cpurev & 0x000F0) >> 4, (cpurev & 0x0000F) >> 0, + mxc_get_clock(MXC_ARM_CLK) / 1000000); + + printf("Reset cause: %s\n", get_reset_cause(cause)); + + printf("Boot mode: "); + switch (get_boot_mode()) { + case LOW_POWER_BOOT: + printf("Low power boot\n"); + break; + case DUAL_BOOT: + printf("Dual boot\n"); + break; + case SINGLE_BOOT: + default: + printf("Single boot\n"); + break; + } + + return 0; +} +#endif + +#define CMC_SRS_TAMPER (1 << 31) +#define CMC_SRS_SECURITY (1 << 30) +#define CMC_SRS_TZWDG (1 << 29) +#define CMC_SRS_JTAG_RST (1 << 28) +#define CMC_SRS_CORE1 (1 << 16) +#define CMC_SRS_LOCKUP (1 << 15) +#define CMC_SRS_SW (1 << 14) +#define CMC_SRS_WDG (1 << 13) +#define CMC_SRS_PIN_RESET (1 << 8) +#define CMC_SRS_WARM (1 << 4) +#define CMC_SRS_HVD (1 << 3) +#define CMC_SRS_LVD (1 << 2) +#define CMC_SRS_POR (1 << 1) +#define CMC_SRS_WUP (1 << 0) + +static u32 reset_cause = -1; + +static char *get_reset_cause(char *ret) +{ + u32 cause1, cause = 0, srs = 0; + u32 *reg_ssrs = (u32 *)(SRC_BASE_ADDR + 0x28); + u32 *reg_srs = (u32 *)(SRC_BASE_ADDR + 0x20); + + if (!ret) + return "null"; + + srs = readl(reg_srs); + cause1 = readl(reg_ssrs); + writel(cause1, reg_ssrs); + + reset_cause = cause1; + + cause = cause1 & (CMC_SRS_POR | CMC_SRS_WUP | CMC_SRS_WARM); + + switch (cause) { + case CMC_SRS_POR: + sprintf(ret, "%s", "POR"); + break; + case CMC_SRS_WUP: + sprintf(ret, "%s", "WUP"); + break; + case CMC_SRS_WARM: + cause = cause1 & (CMC_SRS_WDG | CMC_SRS_SW | + CMC_SRS_JTAG_RST); + switch (cause) { + case CMC_SRS_WDG: + sprintf(ret, "%s", "WARM-WDG"); + break; + case CMC_SRS_SW: + sprintf(ret, "%s", "WARM-SW"); + break; + case CMC_SRS_JTAG_RST: + sprintf(ret, "%s", "WARM-JTAG"); + break; + default: + sprintf(ret, "%s", "WARM-UNKN"); + break; + } + break; + default: + sprintf(ret, "%s-%X", "UNKN", cause1); + break; + } + + debug("[%X] SRS[%X] %X - ", cause1, srs, srs^cause1); + return ret; +} + +u32 get_imx_reset_cause(void) +{ + return reset_cause; +} + +#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) +{ + int devno = 0; + u32 bt1_cfg = 0; + + /* If not boot from sd/mmc, use default value */ + if (get_boot_mode() == LOW_POWER_BOOT) + return CONFIG_SYS_MMC_ENV_DEV; + + bt1_cfg = readl(CMC1_RBASE + 0x40); + devno = (bt1_cfg >> 9) & 0x7; + + return board_mmc_get_env_dev(devno); +} +#endif diff --git a/arch/arm/imx-common/Makefile b/arch/arm/imx-common/Makefile index 1873185..68ee60f 100644 --- a/arch/arm/imx-common/Makefile +++ b/arch/arm/imx-common/Makefile @@ -31,6 +31,10 @@ obj-$(CONFIG_IMX_RDC) += rdc-sema.o obj-$(CONFIG_IMX_BOOTAUX) += imx_bootaux.o obj-$(CONFIG_SECURE_BOOT) += hab.o endif +ifeq ($(SOC),$(filter $(SOC),mx7ulp)) +obj-y += cache.o +obj-$(CONFIG_SECURE_BOOT) += hab.o +endif ifeq ($(SOC),$(filter $(SOC),vf610)) obj-y += ddrmc-vf610.o endif diff --git a/arch/arm/include/asm/arch-imx/cpu.h b/arch/arm/include/asm/arch-imx/cpu.h index 8bd1421..b052406 100644 --- a/arch/arm/include/asm/arch-imx/cpu.h +++ b/arch/arm/include/asm/arch-imx/cpu.h @@ -25,10 +25,12 @@ #define MXC_CPU_MX6QP 0x69 #define MXC_CPU_MX7S 0x71 /* dummy ID */ #define MXC_CPU_MX7D 0x72 +#define MXC_CPU_MX7ULP 0x81 /* Temporally hard code */ #define MXC_CPU_VF610 0xF6 /* dummy ID */ #define MXC_SOC_MX6 0x60 #define MXC_SOC_MX7 0x70 +#define MXC_SOC_MX7ULP 0x80 /* dummy */ #define CHIP_REV_1_0 0x10 #define CHIP_REV_1_1 0x11 diff --git a/arch/arm/include/asm/arch-mx7ulp/imx-regs.h b/arch/arm/include/asm/arch-mx7ulp/imx-regs.h index 30d0ba4..cdfbe2e 100644 --- a/arch/arm/include/asm/arch-mx7ulp/imx-regs.h +++ b/arch/arm/include/asm/arch-mx7ulp/imx-regs.h @@ -97,6 +97,11 @@ #define CORE_B_ROM_SIZE (SZ_32K + SZ_64K) #define CORE_B_ROM_BASE (0x00000000) +#define ROMCP_ARB_BASE_ADDR CORE_B_ROM_BASE +#define ROMCP_ARB_END_ADDR CORE_B_ROM_SIZE +#define IRAM_BASE_ADDR OCRAM_0_BASE +#define IRAM_SIZE (SZ_128K + SZ_128K) + #define IOMUXC_PCR_MUX_ALT0 (0<<8) #define IOMUXC_PCR_MUX_ALT1 (1<<8) #define IOMUXC_PCR_MUX_ALT2 (2<<8) diff --git a/arch/arm/include/asm/arch-mx7ulp/sys_proto.h b/arch/arm/include/asm/arch-mx7ulp/sys_proto.h new file mode 100644 index 0000000..d01748f --- /dev/null +++ b/arch/arm/include/asm/arch-mx7ulp/sys_proto.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _SYS_PROTO_MX7ULP_H_ +#define _SYS_PROTO_MX7ULP_H_ + +#include <asm/imx-common/sys_proto.h> + +#define BT0CFG_LPBOOT_MASK 0x1 +#define BT0CFG_DUALBOOT_MASK 0x2 + +enum bt_mode { + LOW_POWER_BOOT, /* LP_BT = 1 */ + DUAL_BOOT, /* LP_BT = 0, DUAL_BT = 1 */ + SINGLE_BOOT /* LP_BT = 0, DUAL_BT = 0 */ +}; + +#endif