X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=arch%2Farm%2Fmach-imx%2Fcpu.c;h=6b83f926623366cda86b14a2ec1c855046ba491a;hb=88d5ab3d67c7507160792991e99bda9fff34d106;hp=1017eb84f95ad028acd7bab274ec226ae7452267;hpb=7e0712b26ee877ca46cc7ba9978c52a9c3f40dc4;p=oweals%2Fu-boot.git diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c index 1017eb84f9..6b83f92662 100644 --- a/arch/arm/mach-imx/cpu.c +++ b/arch/arm/mach-imx/cpu.c @@ -1,10 +1,9 @@ +// 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 @@ -16,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -25,19 +25,27 @@ #include #endif -#if defined(CONFIG_DISPLAY_CPUINFO) static u32 reset_cause = -1; -static char *get_reset_cause(void) +u32 get_imx_reset_cause(void) { - u32 cause; struct src *src_regs = (struct src *)SRC_BASE_ADDR; - cause = readl(&src_regs->srsr); - writel(cause, &src_regs->srsr); - reset_cause = cause; + if (reset_cause == -1) { + reset_cause = readl(&src_regs->srsr); +/* preserve the value for U-Boot proper */ +#if !defined(CONFIG_SPL_BUILD) + writel(reset_cause, &src_regs->srsr); +#endif + } + + return reset_cause; +} - switch (cause) { +#if defined(CONFIG_DISPLAY_CPUINFO) && !defined(CONFIG_SPL_BUILD) +static char *get_reset_cause(void) +{ + switch (get_imx_reset_cause()) { case 0x00001: case 0x00011: return "POR"; @@ -62,6 +70,11 @@ static char *get_reset_cause(void) return "WDOG4"; case 0x00200: return "TEMPSENSE"; +#elif defined(CONFIG_IMX8M) + case 0x00100: + return "WDOG2"; + case 0x00200: + return "TEMPSENSE"; #else case 0x00100: return "TEMPSENSE"; @@ -72,11 +85,6 @@ static char *get_reset_cause(void) return "unknown reset"; } } - -u32 get_imx_reset_cause(void) -{ - return reset_cause; -} #endif #if defined(CONFIG_MX53) || defined(CONFIG_MX6) @@ -132,11 +140,13 @@ unsigned imx_ddr_size(void) } #endif -#if defined(CONFIG_DISPLAY_CPUINFO) +#if defined(CONFIG_DISPLAY_CPUINFO) && !defined(CONFIG_SPL_BUILD) const char *get_imx_type(u32 imxtype) { switch (imxtype) { + case MXC_CPU_IMX8MQ: + return "8MQ"; /* Quad-core version of the imx8m */ case MXC_CPU_MX7S: return "7S"; /* Single-core version of the mx7 */ case MXC_CPU_MX7D: @@ -259,7 +269,7 @@ int cpu_mmc_init(bd_t *bis) } #endif -#ifndef CONFIG_MX7 +#if !(defined(CONFIG_MX7) || defined(CONFIG_IMX8M)) u32 get_ahb_clk(void) { struct mxc_ccm_reg *imx_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; @@ -293,6 +303,7 @@ void arch_preboot_os(void) #endif } +#ifndef CONFIG_IMX8M void set_chipselect_size(int const cs_size) { unsigned int reg; @@ -323,3 +334,147 @@ void set_chipselect_size(int const cs_size) writel(reg, &iomuxc_regs->gpr[1]); } +#endif + +#if defined(CONFIG_MX7) || defined(CONFIG_IMX8M) +/* + * OCOTP_TESTER3[9:8] (see Fusemap Description Table offset 0x440) + * defines a 2-bit SPEED_GRADING + */ +#define OCOTP_TESTER3_SPEED_SHIFT 8 +enum cpu_speed { + OCOTP_TESTER3_SPEED_GRADE0, + OCOTP_TESTER3_SPEED_GRADE1, + OCOTP_TESTER3_SPEED_GRADE2, + OCOTP_TESTER3_SPEED_GRADE3, +}; + +u32 get_cpu_speed_grade_hz(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; + uint32_t val; + + val = readl(&fuse->tester3); + val >>= OCOTP_TESTER3_SPEED_SHIFT; + val &= 0x3; + + switch(val) { + case OCOTP_TESTER3_SPEED_GRADE0: + return 800000000; + case OCOTP_TESTER3_SPEED_GRADE1: + return is_mx7() ? 500000000 : 1000000000; + case OCOTP_TESTER3_SPEED_GRADE2: + return is_mx7() ? 1000000000 : 1300000000; + case OCOTP_TESTER3_SPEED_GRADE3: + return is_mx7() ? 1200000000 : 1500000000; + } + + return 0; +} + +/* + * OCOTP_TESTER3[7:6] (see Fusemap Description Table offset 0x440) + * defines a 2-bit SPEED_GRADING + */ +#define OCOTP_TESTER3_TEMP_SHIFT 6 + +u32 get_cpu_temp_grade(int *minc, int *maxc) +{ + 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; + uint32_t val; + + val = readl(&fuse->tester3); + val >>= OCOTP_TESTER3_TEMP_SHIFT; + val &= 0x3; + + if (minc && maxc) { + if (val == TEMP_AUTOMOTIVE) { + *minc = -40; + *maxc = 125; + } else if (val == TEMP_INDUSTRIAL) { + *minc = -40; + *maxc = 105; + } else if (val == TEMP_EXTCOMMERCIAL) { + *minc = -20; + *maxc = 105; + } else { + *minc = 0; + *maxc = 95; + } + } + return val; +} +#endif + +#if defined(CONFIG_MX7) || defined(CONFIG_IMX8M) +enum boot_device get_boot_device(void) +{ + struct bootrom_sw_info **p = + (struct bootrom_sw_info **)(ulong)ROM_SW_INFO_ADDR; + + enum boot_device boot_dev = SD1_BOOT; + u8 boot_type = (*p)->boot_dev_type; + u8 boot_instance = (*p)->boot_dev_instance; + + switch (boot_type) { + case BOOT_TYPE_SD: + boot_dev = boot_instance + SD1_BOOT; + break; + case BOOT_TYPE_MMC: + boot_dev = boot_instance + MMC1_BOOT; + break; + case BOOT_TYPE_NAND: + boot_dev = NAND_BOOT; + break; + case BOOT_TYPE_QSPI: + boot_dev = QSPI_BOOT; + break; + case BOOT_TYPE_WEIM: + boot_dev = WEIM_NOR_BOOT; + break; + case BOOT_TYPE_SPINOR: + boot_dev = SPI_NOR_BOOT; + break; +#ifdef CONFIG_IMX8M + case BOOT_TYPE_USB: + boot_dev = USB_BOOT; + break; +#endif + default: + break; + } + + return boot_dev; +} +#endif + +#ifdef CONFIG_NXP_BOARD_REVISION +int nxp_board_rev(void) +{ + /* + * Get Board ID information from OCOTP_GP1[15:8] + * RevA: 0x1 + * RevB: 0x2 + * RevC: 0x3 + */ + 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; + + return (readl(&fuse->gp1) >> 8 & 0x0F); +} + +char nxp_board_rev_string(void) +{ + const char *rev = "A"; + + return (*rev + nxp_board_rev() - 1); +} +#endif