diff options
Diffstat (limited to 'arch/arm/mach-imx/imx8m')
-rw-r--r-- | arch/arm/mach-imx/imx8m/Kconfig | 17 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx8m/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx8m/clock_imx8mm.c | 306 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx8m/clock_imx8mq.c (renamed from arch/arm/mach-imx/imx8m/clock.c) | 5 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx8m/clock_slice.c | 63 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx8m/imximage-8mm-lpddr4.cfg | 16 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx8m/soc.c | 131 |
7 files changed, 515 insertions, 27 deletions
diff --git a/arch/arm/mach-imx/imx8m/Kconfig b/arch/arm/mach-imx/imx8m/Kconfig index 317dee9bc1..f520075875 100644 --- a/arch/arm/mach-imx/imx8m/Kconfig +++ b/arch/arm/mach-imx/imx8m/Kconfig @@ -4,6 +4,14 @@ config IMX8M bool select ROM_UNIFIED_SECTIONS +config IMX8MQ + bool + select IMX8M + +config IMX8MM + bool + select IMX8M + config SYS_SOC default "imx8m" @@ -13,11 +21,18 @@ choice config TARGET_IMX8MQ_EVK bool "imx8mq_evk" - select IMX8M + select IMX8MQ + select IMX8M_LPDDR4 + +config TARGET_IMX8MM_EVK + bool "imx8mm LPDDR4 EVK board" + select IMX8MM + select SUPPORT_SPL select IMX8M_LPDDR4 endchoice source "board/freescale/imx8mq_evk/Kconfig" +source "board/freescale/imx8mm_evk/Kconfig" endif diff --git a/arch/arm/mach-imx/imx8m/Makefile b/arch/arm/mach-imx/imx8m/Makefile index feff4941c1..92184f3135 100644 --- a/arch/arm/mach-imx/imx8m/Makefile +++ b/arch/arm/mach-imx/imx8m/Makefile @@ -3,4 +3,6 @@ # Copyright 2017 NXP obj-y += lowlevel_init.o -obj-y += clock.o clock_slice.o soc.o +obj-y += clock_slice.o soc.o +obj-$(CONFIG_IMX8MQ) += clock_imx8mq.o +obj-$(CONFIG_IMX8MM) += clock_imx8mm.o diff --git a/arch/arm/mach-imx/imx8m/clock_imx8mm.c b/arch/arm/mach-imx/imx8m/clock_imx8mm.c new file mode 100644 index 0000000000..ee44ba75fe --- /dev/null +++ b/arch/arm/mach-imx/imx8m/clock_imx8mm.c @@ -0,0 +1,306 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018-2019 NXP + * + * Peng Fan <peng.fan@nxp.com> + */ + +#include <common.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h> +#include <asm/io.h> +#include <clk.h> +#include <clk-uclass.h> +#include <dt-bindings/clock/imx8mm-clock.h> +#include <div64.h> +#include <errno.h> + +DECLARE_GLOBAL_DATA_PTR; + +static struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR; + +void enable_ocotp_clk(unsigned char enable) +{ + struct clk *clkp; + int ret; + + ret = clk_get_by_id(IMX8MM_CLK_OCOTP_ROOT, &clkp); + if (ret) { + printf("%s: err: %d\n", __func__, ret); + return; + } + + enable ? clk_enable(clkp) : clk_disable(clkp); +} + +int enable_i2c_clk(unsigned char enable, unsigned i2c_num) +{ + struct clk *clkp; + int ret; + + ret = clk_get_by_id(IMX8MM_CLK_I2C1_ROOT + i2c_num, &clkp); + if (ret) { + printf("%s: err: %d\n", __func__, ret); + return ret; + } + + return enable ? clk_enable(clkp) : clk_disable(clkp); +} + +#ifdef CONFIG_SPL_BUILD +static struct imx_int_pll_rate_table imx8mm_fracpll_tbl[] = { + PLL_1443X_RATE(800000000U, 300, 9, 0, 0), + PLL_1443X_RATE(750000000U, 250, 8, 0, 0), + PLL_1443X_RATE(650000000U, 325, 3, 2, 0), + PLL_1443X_RATE(600000000U, 300, 3, 2, 0), + PLL_1443X_RATE(594000000U, 99, 1, 2, 0), + PLL_1443X_RATE(400000000U, 300, 9, 1, 0), + PLL_1443X_RATE(266666667U, 400, 9, 2, 0), + PLL_1443X_RATE(167000000U, 334, 3, 4, 0), + PLL_1443X_RATE(100000000U, 300, 9, 3, 0), +}; + +int fracpll_configure(enum pll_clocks pll, u32 freq) +{ + int i; + u32 tmp, div_val; + void *pll_base; + struct imx_int_pll_rate_table *rate; + + for (i = 0; i < ARRAY_SIZE(imx8mm_fracpll_tbl); i++) { + if (freq == imx8mm_fracpll_tbl[i].rate) + break; + } + + if (i == ARRAY_SIZE(imx8mm_fracpll_tbl)) { + printf("No matched freq table %u\n", freq); + return -EINVAL; + } + + rate = &imx8mm_fracpll_tbl[i]; + + switch (pll) { + case ANATOP_DRAM_PLL: + setbits_le32(GPC_BASE_ADDR + 0xEC, 1 << 7); + setbits_le32(GPC_BASE_ADDR + 0xF8, 1 << 5); + writel(SRC_DDR1_ENABLE_MASK, SRC_BASE_ADDR + 0x1004); + + pll_base = &ana_pll->dram_pll_gnrl_ctl; + break; + case ANATOP_VIDEO_PLL: + pll_base = &ana_pll->video_pll1_gnrl_ctl; + break; + default: + return 0; + } + /* Bypass clock and set lock to pll output lock */ + tmp = readl(pll_base); + tmp |= BYPASS_MASK; + writel(tmp, pll_base); + + /* Enable RST */ + tmp &= ~RST_MASK; + writel(tmp, pll_base); + + div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) | + (rate->sdiv << SDIV_SHIFT); + writel(div_val, pll_base + 4); + writel(rate->kdiv << KDIV_SHIFT, pll_base + 8); + + __udelay(100); + + /* Disable RST */ + tmp |= RST_MASK; + writel(tmp, pll_base); + + /* Wait Lock*/ + while (!(readl(pll_base) & LOCK_STATUS)) + ; + + /* Bypass */ + tmp &= ~BYPASS_MASK; + writel(tmp, pll_base); + + return 0; +} + +void dram_pll_init(ulong pll_val) +{ + fracpll_configure(ANATOP_DRAM_PLL, pll_val); +} + +static struct dram_bypass_clk_setting imx8mm_dram_bypass_tbl[] = { + DRAM_BYPASS_ROOT_CONFIG(MHZ(100), 2, CLK_ROOT_PRE_DIV1, 2, + CLK_ROOT_PRE_DIV2), + DRAM_BYPASS_ROOT_CONFIG(MHZ(250), 3, CLK_ROOT_PRE_DIV2, 2, + CLK_ROOT_PRE_DIV2), + DRAM_BYPASS_ROOT_CONFIG(MHZ(400), 1, CLK_ROOT_PRE_DIV2, 3, + CLK_ROOT_PRE_DIV2), +}; + +void dram_enable_bypass(ulong clk_val) +{ + int i; + struct dram_bypass_clk_setting *config; + + for (i = 0; i < ARRAY_SIZE(imx8mm_dram_bypass_tbl); i++) { + if (clk_val == imx8mm_dram_bypass_tbl[i].clk) + break; + } + + if (i == ARRAY_SIZE(imx8mm_dram_bypass_tbl)) { + printf("No matched freq table %lu\n", clk_val); + return; + } + + config = &imx8mm_dram_bypass_tbl[i]; + + clock_set_target_val(DRAM_ALT_CLK_ROOT, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(config->alt_root_sel) | + CLK_ROOT_PRE_DIV(config->alt_pre_div)); + clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(config->apb_root_sel) | + CLK_ROOT_PRE_DIV(config->apb_pre_div)); + clock_set_target_val(DRAM_SEL_CFG, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(1)); +} + +void dram_disable_bypass(void) +{ + clock_set_target_val(DRAM_SEL_CFG, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(0)); + clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(4) | + CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV5)); +} +#endif + +void init_uart_clk(u32 index) +{ + /* + * set uart clock root + * 24M OSC + */ + switch (index) { + case 0: + clock_enable(CCGR_UART1, 0); + clock_set_target_val(UART1_CLK_ROOT, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(0)); + clock_enable(CCGR_UART1, 1); + return; + case 1: + clock_enable(CCGR_UART2, 0); + clock_set_target_val(UART2_CLK_ROOT, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(0)); + clock_enable(CCGR_UART2, 1); + return; + case 2: + clock_enable(CCGR_UART3, 0); + clock_set_target_val(UART3_CLK_ROOT, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(0)); + clock_enable(CCGR_UART3, 1); + return; + case 3: + clock_enable(CCGR_UART4, 0); + clock_set_target_val(UART4_CLK_ROOT, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(0)); + clock_enable(CCGR_UART4, 1); + return; + default: + printf("Invalid uart index\n"); + return; + } +} + +void init_wdog_clk(void) +{ + clock_enable(CCGR_WDOG1, 0); + clock_enable(CCGR_WDOG2, 0); + clock_enable(CCGR_WDOG3, 0); + clock_set_target_val(WDOG_CLK_ROOT, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(0)); + clock_enable(CCGR_WDOG1, 1); + clock_enable(CCGR_WDOG2, 1); + clock_enable(CCGR_WDOG3, 1); +} + +int clock_init(void) +{ + u32 val_cfg0; + + /* + * The gate is not exported to clk tree, so configure them here. + * According to ANAMIX SPEC + * sys pll1 fixed at 800MHz + * sys pll2 fixed at 1GHz + * Here we only enable the outputs. + */ + val_cfg0 = readl(&ana_pll->sys_pll1_gnrl_ctl); + val_cfg0 |= INTPLL_CLKE_MASK | INTPLL_DIV2_CLKE_MASK | + INTPLL_DIV3_CLKE_MASK | INTPLL_DIV4_CLKE_MASK | + INTPLL_DIV5_CLKE_MASK | INTPLL_DIV6_CLKE_MASK | + INTPLL_DIV8_CLKE_MASK | INTPLL_DIV10_CLKE_MASK | + INTPLL_DIV20_CLKE_MASK; + writel(val_cfg0, &ana_pll->sys_pll1_gnrl_ctl); + + val_cfg0 = readl(&ana_pll->sys_pll2_gnrl_ctl); + val_cfg0 |= INTPLL_CLKE_MASK | INTPLL_DIV2_CLKE_MASK | + INTPLL_DIV3_CLKE_MASK | INTPLL_DIV4_CLKE_MASK | + INTPLL_DIV5_CLKE_MASK | INTPLL_DIV6_CLKE_MASK | + INTPLL_DIV8_CLKE_MASK | INTPLL_DIV10_CLKE_MASK | + INTPLL_DIV20_CLKE_MASK; + writel(val_cfg0, &ana_pll->sys_pll2_gnrl_ctl); + + /* config GIC to sys_pll2_100m */ + clock_enable(CCGR_GIC, 0); + clock_set_target_val(GIC_CLK_ROOT, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(3)); + clock_enable(CCGR_GIC, 1); + + clock_set_target_val(NAND_USDHC_BUS_CLK_ROOT, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(1)); + + clock_enable(CCGR_DDR1, 0); + clock_set_target_val(DRAM_ALT_CLK_ROOT, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(1)); + clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | + CLK_ROOT_SOURCE_SEL(1)); + clock_enable(CCGR_DDR1, 1); + + init_wdog_clk(); + + clock_enable(CCGR_TEMP_SENSOR, 1); + + clock_enable(CCGR_SEC_DEBUG, 1); + + return 0; +}; + +u32 imx_get_uartclk(void) +{ + return 24000000U; +} + +u32 mxc_get_clock(enum mxc_clock clk) +{ + struct clk *clkp; + int ret; + + switch (clk) { + case MXC_IPG_CLK: + ret = clk_get_by_id(IMX8MM_CLK_IPG_ROOT, &clkp); + if (ret) + return 0; + return clk_get_rate(clkp); + case MXC_ARM_CLK: + ret = clk_get_by_id(IMX8MM_CLK_A53_DIV, &clkp); + if (ret) + return 0; + return clk_get_rate(clkp); + default: + printf("%s: %d not supported\n", __func__, clk); + } + + return 0; +} diff --git a/arch/arm/mach-imx/imx8m/clock.c b/arch/arm/mach-imx/imx8m/clock_imx8mq.c index 289b9417aa..feecdb50f6 100644 --- a/arch/arm/mach-imx/imx8m/clock.c +++ b/arch/arm/mach-imx/imx8m/clock_imx8mq.c @@ -322,13 +322,10 @@ int enable_i2c_clk(unsigned char enable, unsigned int i2c_num) return 0; } -unsigned int mxc_get_clock(enum clk_root_index clk) +unsigned int mxc_get_clock(enum mxc_clock clk) { u32 val; - if (clk >= CLK_ROOT_MAX) - return 0; - if (clk == MXC_ARM_CLK) return get_root_clk(ARM_A53_CLK_ROOT); diff --git a/arch/arm/mach-imx/imx8m/clock_slice.c b/arch/arm/mach-imx/imx8m/clock_slice.c index 1a67c626f1..780f64314d 100644 --- a/arch/arm/mach-imx/imx8m/clock_slice.c +++ b/arch/arm/mach-imx/imx8m/clock_slice.c @@ -13,6 +13,7 @@ static struct ccm_reg *ccm_reg = (struct ccm_reg *)CCM_BASE_ADDR; +#ifdef CONFIG_IMX8MQ static struct clk_root_map root_array[] = { {ARM_A53_CLK_ROOT, CORE_CLOCK_SLICE, 0, {OSC_25M_CLK, ARM_PLL_CLK, SYSTEM_PLL2_500M_CLK, @@ -474,6 +475,68 @@ static struct clk_root_map root_array[] = { {DRAM_PLL1_CLK} }, }; +#elif defined(CONFIG_IMX8MM) +static struct clk_root_map root_array[] = { + {NAND_USDHC_BUS_CLK_ROOT, BUS_CLOCK_SLICE, 2, + {OSC_24M_CLK, SYSTEM_PLL1_266M_CLK, SYSTEM_PLL1_800M_CLK, + SYSTEM_PLL2_200M_CLK, SYSTEM_PLL1_133M_CLK, + SYSTEM_PLL3_CLK, SYSTEM_PLL2_250M_CLK, AUDIO_PLL1_CLK} + }, + {NOC_CLK_ROOT, BUS_CLOCK_SLICE, 10, + {OSC_24M_CLK, SYSTEM_PLL1_800M_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_1000M_CLK, SYSTEM_PLL2_500M_CLK, + AUDIO_PLL1_CLK, VIDEO_PLL_CLK, AUDIO_PLL2_CLK} + }, + {NOC_APB_CLK_ROOT, BUS_CLOCK_SLICE, 11, + {OSC_24M_CLK, SYSTEM_PLL1_400M_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_333M_CLK, SYSTEM_PLL2_200M_CLK, + SYSTEM_PLL1_800M_CLK, AUDIO_PLL1_CLK, VIDEO_PLL_CLK} + }, + {DRAM_ALT_CLK_ROOT, IP_CLOCK_SLICE, 0, + {OSC_24M_CLK, SYSTEM_PLL1_800M_CLK, SYSTEM_PLL1_100M_CLK, + SYSTEM_PLL2_500M_CLK, SYSTEM_PLL2_1000M_CLK, + SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, SYSTEM_PLL1_266M_CLK} + }, + {DRAM_APB_CLK_ROOT, IP_CLOCK_SLICE, 1, + {OSC_24M_CLK, SYSTEM_PLL2_200M_CLK, SYSTEM_PLL1_40M_CLK, + SYSTEM_PLL1_160M_CLK, SYSTEM_PLL1_800M_CLK, + SYSTEM_PLL3_CLK, SYSTEM_PLL2_250M_CLK, AUDIO_PLL2_CLK} + }, + {UART1_CLK_ROOT, IP_CLOCK_SLICE, 30, + {OSC_24M_CLK, SYSTEM_PLL1_80M_CLK, SYSTEM_PLL2_200M_CLK, + SYSTEM_PLL2_100M_CLK, SYSTEM_PLL3_CLK, + EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK} + }, + {UART2_CLK_ROOT, IP_CLOCK_SLICE, 31, + {OSC_24M_CLK, SYSTEM_PLL1_80M_CLK, SYSTEM_PLL2_200M_CLK, + SYSTEM_PLL2_100M_CLK, SYSTEM_PLL3_CLK, + EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK} + }, + {UART3_CLK_ROOT, IP_CLOCK_SLICE, 32, + {OSC_24M_CLK, SYSTEM_PLL1_80M_CLK, SYSTEM_PLL2_200M_CLK, + SYSTEM_PLL2_100M_CLK, SYSTEM_PLL3_CLK, + EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK} + }, + {UART4_CLK_ROOT, IP_CLOCK_SLICE, 33, + {OSC_24M_CLK, SYSTEM_PLL1_80M_CLK, SYSTEM_PLL2_200M_CLK, + SYSTEM_PLL2_100M_CLK, SYSTEM_PLL3_CLK, + EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK} + }, + {GIC_CLK_ROOT, IP_CLOCK_SLICE, 36, + {OSC_24M_CLK, SYSTEM_PLL2_200M_CLK, SYSTEM_PLL1_40M_CLK, + SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_800M_CLK, + EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK} + }, + {WDOG_CLK_ROOT, IP_CLOCK_SLICE, 50, + {OSC_24M_CLK, SYSTEM_PLL1_133M_CLK, SYSTEM_PLL1_160M_CLK, + VPU_PLL_CLK, SYSTEM_PLL2_125M_CLK, + SYSTEM_PLL3_CLK, SYSTEM_PLL1_80M_CLK, SYSTEM_PLL2_166M_CLK} + }, + {DRAM_SEL_CFG, DRAM_SEL_CLOCK_SLICE, 0, + {DRAM_PLL1_CLK} + }, +}; +#endif static int select(enum clk_root_index clock_id) { diff --git a/arch/arm/mach-imx/imx8m/imximage-8mm-lpddr4.cfg b/arch/arm/mach-imx/imx8m/imximage-8mm-lpddr4.cfg new file mode 100644 index 0000000000..1a2e43e671 --- /dev/null +++ b/arch/arm/mach-imx/imx8m/imximage-8mm-lpddr4.cfg @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2019 NXP + */ + +#define __ASSEMBLY__ + +FIT +BOOT_FROM sd +LOADER spl/u-boot-spl-ddr.bin 0x7E1000 +SECOND_LOADER u-boot.itb 0x40200000 0x60000 + +DDR_FW lpddr4_pmu_train_1d_imem.bin +DDR_FW lpddr4_pmu_train_1d_dmem.bin +DDR_FW lpddr4_pmu_train_2d_imem.bin +DDR_FW lpddr4_pmu_train_2d_dmem.bin diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index 7ec39b3e47..aeca82cdbf 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -14,6 +14,7 @@ #include <asm/mach-imx/boot_mode.h> #include <asm/mach-imx/syscounter.h> #include <asm/armv8/mmu.h> +#include <dm/uclass.h> #include <errno.h> #include <fdt_support.h> #include <fsl_wdog.h> @@ -21,7 +22,7 @@ DECLARE_GLOBAL_DATA_PTR; -#if defined(CONFIG_SECURE_BOOT) +#if defined(CONFIG_IMX_HAB) struct imx_sec_config_fuse_t const imx_sec_config_fuse = { .bank = 1, .word = 3, @@ -55,6 +56,14 @@ void enable_tzc380(void) /* Enable TZASC and lock setting */ setbits_le32(&gpr->gpr[10], GPR_TZASC_EN); setbits_le32(&gpr->gpr[10], GPR_TZASC_EN_LOCK); + if (IS_ENABLED(CONFIG_IMX8MM)) + setbits_le32(&gpr->gpr[10], BIT(1)); + /* + * set Region 0 attribute to allow secure and non-secure + * read/write permission. Found some masters like usb dwc3 + * controllers can't work with secure memory. + */ + writel(0xf0000000, TZASC_BASE_ADDR + 0x108); } void set_wdog_reset(struct wdog_regs *wdog) @@ -112,16 +121,18 @@ static struct mm_region imx8m_mem_map[] = { /* DRAM1 */ .virt = 0x40000000UL, .phys = 0x40000000UL, - .size = 0xC0000000UL, + .size = PHYS_SDRAM_SIZE, .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE +#ifdef PHYS_SDRAM_2_SIZE }, { /* DRAM2 */ .virt = 0x100000000UL, .phys = 0x100000000UL, - .size = 0x040000000UL, + .size = PHYS_SDRAM_2_SIZE, .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE +#endif }, { /* List terminator */ 0, @@ -130,25 +141,76 @@ static struct mm_region imx8m_mem_map[] = { struct mm_region *mem_map = imx8m_mem_map; +void enable_caches(void) +{ + /* + * If OPTEE runs, remove OPTEE memory from MMU table to + * avoid speculative prefetch. OPTEE runs at the top of + * the first memory bank + */ + if (rom_pointer[1]) + imx8m_mem_map[5].size -= rom_pointer[1]; + + icache_enable(); + dcache_enable(); +} + +static u32 get_cpu_variant_type(u32 type) +{ + 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; + + u32 value = readl(&fuse->tester4); + + if (type == MXC_CPU_IMX8MM) { + switch (value & 0x3) { + case 2: + if (value & 0x1c0000) + return MXC_CPU_IMX8MMDL; + else + return MXC_CPU_IMX8MMD; + case 3: + if (value & 0x1c0000) + return MXC_CPU_IMX8MMSL; + else + return MXC_CPU_IMX8MMS; + default: + if (value & 0x1c0000) + return MXC_CPU_IMX8MML; + break; + } + } + + return type; +} + u32 get_cpu_rev(void) { struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR; u32 reg = readl(&ana_pll->digprog); u32 type = (reg >> 16) & 0xff; + u32 major_low = (reg >> 8) & 0xff; u32 rom_version; reg &= 0xff; - if (reg == CHIP_REV_1_0) { - /* - * For B0 chip, the DIGPROG is not updated, still TO1.0. - * we have to check ROM version further - */ - rom_version = readl((void __iomem *)ROM_VERSION_A0); - if (rom_version != CHIP_REV_1_0) { - rom_version = readl((void __iomem *)ROM_VERSION_B0); - if (rom_version >= CHIP_REV_2_0) - reg = CHIP_REV_2_0; + /* i.MX8MM */ + if (major_low == 0x41) { + type = get_cpu_variant_type(MXC_CPU_IMX8MM); + } else { + if (reg == CHIP_REV_1_0) { + /* + * For B0 chip, the DIGPROG is not updated, still TO1.0. + * we have to check ROM version further + */ + rom_version = readl((void __iomem *)ROM_VERSION_A0); + if (rom_version != CHIP_REV_1_0) { + rom_version = readl((void __iomem *)ROM_VERSION_B0); + if (rom_version >= CHIP_REV_2_0) + reg = CHIP_REV_2_0; + } } } @@ -167,10 +229,32 @@ static void imx_set_wdog_powerdown(bool enable) writew(enable, &wdog3->wmcr); } +int arch_cpu_init_dm(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_name(UCLASS_CLK, + "clock-controller@30380000", + &dev); + if (ret < 0) { + printf("Failed to find clock node. Check device tree\n"); + return ret; + } + + return 0; +} + int arch_cpu_init(void) { struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; /* + * ROM might disable clock for SCTR, + * enable the clock before timer_init. + */ + if (IS_ENABLED(CONFIG_SPL_BUILD)) + clock_enable(CCGR_SCTR, 1); + /* * Init timer at very early state, because sscg pll setting * will use it */ @@ -234,16 +318,21 @@ int ft_system_setup(void *blob, bd_t *bd) } #endif +#if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_SYSRESET) void reset_cpu(ulong addr) { - struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR; + struct watchdog_regs *wdog = (struct watchdog_regs *)addr; - /* Clear WDA to trigger WDOG_B immediately */ - writew((WCR_WDE | WCR_SRS), &wdog->wcr); + if (!addr) + wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR; - while (1) { - /* - * spin for .5 seconds before reset - */ - } + /* Clear WDA to trigger WDOG_B immediately */ + writew((WCR_WDE | WCR_SRS), &wdog->wcr); + + while (1) { + /* + * spin for .5 seconds before reset + */ + } } +#endif |