diff options
Diffstat (limited to 'arch/arm/mach-imx/imx8m.c')
-rw-r--r-- | arch/arm/mach-imx/imx8m.c | 154 |
1 files changed, 136 insertions, 18 deletions
diff --git a/arch/arm/mach-imx/imx8m.c b/arch/arm/mach-imx/imx8m.c index d044531520..d2ed7d52a9 100644 --- a/arch/arm/mach-imx/imx8m.c +++ b/arch/arm/mach-imx/imx8m.c @@ -22,6 +22,9 @@ #include <mach/imx8m-ccm-regs.h> #include <mach/reset-reason.h> #include <mach/ocotp.h> +#include <mach/imx8mq-regs.h> +#include <mach/imx8m-ccm-regs.h> +#include <soc/imx8m/clk-early.h> #include <linux/iopoll.h> #include <linux/arm-smccc.h> @@ -52,18 +55,61 @@ void imx8m_ccgr_clock_disable(int index) ccm + IMX8M_CCM_CCGRn_CLR(index)); } -u64 imx8mq_uid(void) +u64 imx8m_uid(void) { - return imx_ocotp_read_uid(IOMEM(MX8MQ_OCOTP_BASE_ADDR)); + return imx_ocotp_read_uid(IOMEM(MX8M_OCOTP_BASE_ADDR)); +} + +static int imx8m_init(const char *cputypestr) +{ + void __iomem *src = IOMEM(MX8M_SRC_BASE_ADDR); + struct arm_smccc_res res; + + /* + * Reset reasons seem to be identical to that of i.MX7 + */ + imx_set_reset_reason(src + IMX7_SRC_SRSR, imx7_reset_reasons); + pr_info("%s unique ID: %llx\n", cputypestr, imx8m_uid()); + + if (IS_ENABLED(CONFIG_ARM_SMCCC) && + IS_ENABLED(CONFIG_FIRMWARE_IMX8MQ_ATF)) { + arm_smccc_smc(FSL_SIP_BUILDINFO, + FSL_SIP_BUILDINFO_GET_COMMITHASH, + 0, 0, 0, 0, 0, 0, &res); + pr_info("i.MX ARM Trusted Firmware: %s\n", (char *)&res.a0); + } + + return 0; +} + +int imx8mm_init(void) +{ + void __iomem *anatop = IOMEM(MX8M_ANATOP_BASE_ADDR); + uint32_t type = FIELD_GET(DIGPROG_MAJOR, + readl(anatop + MX8MM_ANATOP_DIGPROG)); + const char *cputypestr; + + imx8mm_boot_save_loc(); + + switch (type) { + case IMX8M_CPUTYPE_IMX8MM: + cputypestr = "i.MX8MM"; + break; + default: + cputypestr = "unknown i.MX8M"; + break; + }; + + imx_set_silicon_revision(cputypestr, imx8mm_cpu_revision()); + + return imx8m_init(cputypestr); } int imx8mq_init(void) { - void __iomem *anatop = IOMEM(MX8MQ_ANATOP_BASE_ADDR); - void __iomem *src = IOMEM(MX8MQ_SRC_BASE_ADDR); + void __iomem *anatop = IOMEM(MX8M_ANATOP_BASE_ADDR); uint32_t type = FIELD_GET(DIGPROG_MAJOR, readl(anatop + MX8MQ_ANATOP_DIGPROG)); - struct arm_smccc_res res; const char *cputypestr; imx8mq_boot_save_loc(); @@ -78,21 +124,93 @@ int imx8mq_init(void) }; imx_set_silicon_revision(cputypestr, imx8mq_cpu_revision()); - /* - * Reset reasons seem to be identical to that of i.MX7 - */ - imx_set_reset_reason(src + IMX7_SRC_SRSR, imx7_reset_reasons); - pr_info("%s unique ID: %llx\n", cputypestr, imx8mq_uid()); - if (IS_ENABLED(CONFIG_ARM_SMCCC) && - IS_ENABLED(CONFIG_FIRMWARE_IMX8MQ_ATF)) { - arm_smccc_smc(FSL_SIP_BUILDINFO, - FSL_SIP_BUILDINFO_GET_COMMITHASH, - 0, 0, 0, 0, 0, 0, &res); - pr_info("i.MX ARM Trusted Firmware: %s\n", (char *)&res.a0); - } + return imx8m_init(cputypestr); +} - return 0; +#define INTPLL_DIV20_CLKE_MASK BIT(27) +#define INTPLL_DIV10_CLKE_MASK BIT(25) +#define INTPLL_DIV8_CLKE_MASK BIT(23) +#define INTPLL_DIV6_CLKE_MASK BIT(21) +#define INTPLL_DIV5_CLKE_MASK BIT(19) +#define INTPLL_DIV4_CLKE_MASK BIT(17) +#define INTPLL_DIV3_CLKE_MASK BIT(15) +#define INTPLL_DIV2_CLKE_MASK BIT(13) +#define INTPLL_CLKE_MASK BIT(11) + +#define CCM_TARGET_ROOT0_DIV GENMASK(1, 0) + +#define IMX8MM_CCM_ANALOG_ARM_PLL_GEN_CTRL 0x84 +#define IMX8MM_CCM_ANALOG_SYS_PLL1_GEN_CTRL 0x94 +#define IMX8MM_CCM_ANALOG_SYS_PLL2_GEN_CTRL 0x104 +#define IMX8MM_CCM_ANALOG_SYS_PLL3_GEN_CTRL 0x114 + +void imx8mm_early_clock_init(void) +{ + void __iomem *ana = IOMEM(MX8M_ANATOP_BASE_ADDR); + void __iomem *ccm = IOMEM(MX8M_CCM_BASE_ADDR); + u32 val; + + imx8m_ccgr_clock_disable(IMX8M_CCM_CCGR_DDR1); + + imx8m_clock_set_target_val(IMX8M_DRAM_ALT_CLK_ROOT, + IMX8M_CCM_TARGET_ROOTn_ENABLE | + IMX8M_CCM_TARGET_ROOTn_MUX(1)); + + /* change the clock source of dram_apb_clk_root: source 4 800MHz /4 = 200MHz */ + imx8m_clock_set_target_val(IMX8M_DRAM_APB_CLK_ROOT, + IMX8M_CCM_TARGET_ROOTn_ENABLE | + IMX8M_CCM_TARGET_ROOTn_MUX(4) | + IMX8M_CCM_TARGET_ROOTn_POST_DIV(4 - 1)); + + imx8m_ccgr_clock_enable(IMX8M_CCM_CCGR_DDR1); + + val = readl(ana + IMX8MM_CCM_ANALOG_SYS_PLL1_GEN_CTRL); + val |= 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, ana + IMX8MM_CCM_ANALOG_SYS_PLL1_GEN_CTRL); + + val = readl(ana + IMX8MM_CCM_ANALOG_SYS_PLL2_GEN_CTRL); + val |= 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, ana + IMX8MM_CCM_ANALOG_SYS_PLL2_GEN_CTRL); + + /* config GIC to sys_pll2_100m */ + imx8m_ccgr_clock_disable(IMX8M_CCM_CCGR_GIC); + imx8m_clock_set_target_val(IMX8M_GIC_CLK_ROOT, + IMX8M_CCM_TARGET_ROOTn_ENABLE | + IMX8M_CCM_TARGET_ROOTn_MUX(3)); + imx8m_ccgr_clock_enable(IMX8M_CCM_CCGR_GIC); + + /* Configure SYS_PLL3 to 750MHz */ + clk_pll1416x_early_set_rate(ana + IMX8MM_CCM_ANALOG_SYS_PLL3_GEN_CTRL, + 750000000UL, 25000000UL); + + clrsetbits_le32(ccm + IMX8M_CCM_TARGET_ROOTn(IMX8M_ARM_A53_CLK_ROOT), + IMX8M_CCM_TARGET_ROOTn_MUX(7), + IMX8M_CCM_TARGET_ROOTn_MUX(2)); + + /* Configure ARM PLL to 1.2GHz */ + clk_pll1416x_early_set_rate(ana + IMX8MM_CCM_ANALOG_ARM_PLL_GEN_CTRL, + 1200000000UL, 25000000UL); + + clrsetbits_le32(ana + IMX8MM_CCM_ANALOG_ARM_PLL_GEN_CTRL, 0, + INTPLL_CLKE_MASK); + + clrsetbits_le32(ccm + IMX8M_CCM_TARGET_ROOTn(IMX8M_ARM_A53_CLK_ROOT), + IMX8M_CCM_TARGET_ROOTn_MUX(7), + IMX8M_CCM_TARGET_ROOTn_MUX(1)); + + /* Configure DIV to 1.2GHz */ + clrsetbits_le32(ccm + IMX8M_CCM_TARGET_ROOTn(IMX8M_ARM_A53_CLK_ROOT), + CCM_TARGET_ROOT0_DIV, + FIELD_PREP(CCM_TARGET_ROOT0_DIV, 0)); } #define KEEP_ALIVE 0x18 |