From: Peng Fan <peng....@nxp.com> Add CPU_IMX Kconfig Support imx8_cpu driver for i.MX9
Signed-off-by: Peng Fan <peng....@nxp.com> --- drivers/cpu/Kconfig | 6 +++ drivers/cpu/Makefile | 1 + drivers/cpu/imx8_cpu.c | 83 ++++++++++++++++++++++++++++-------------- 3 files changed, 62 insertions(+), 28 deletions(-) diff --git a/drivers/cpu/Kconfig b/drivers/cpu/Kconfig index 3bf04105e5e..1c3c810651e 100644 --- a/drivers/cpu/Kconfig +++ b/drivers/cpu/Kconfig @@ -7,6 +7,12 @@ config CPU they can work correctly in the OS. This provides a framework for finding out information about available CPUs and making changes. +config CPU_IMX + bool "Enable i.MX CPU driver" + depends on CPU && ARM64 + help + Support CPU cores for SoCs of the i.MX series. + config CPU_MPC83XX bool "Enable MPC83xx CPU driver" depends on CPU && MPC83xx diff --git a/drivers/cpu/Makefile b/drivers/cpu/Makefile index 3b38ba9c589..d4bbf6fa5e0 100644 --- a/drivers/cpu/Makefile +++ b/drivers/cpu/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o obj-$(CONFIG_ARCH_IMX8) += imx8_cpu.o obj-$(CONFIG_ARCH_AT91) += at91_cpu.o obj-$(CONFIG_ARCH_MEDIATEK) += mtk_cpu.o +obj-$(CONFIG_CPU_IMX) += imx8_cpu.o obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o obj-$(CONFIG_CPU_RISCV) += riscv_cpu.o obj-$(CONFIG_CPU_MICROBLAZE) += microblaze_cpu.o diff --git a/drivers/cpu/imx8_cpu.c b/drivers/cpu/imx8_cpu.c index e7f45e60dbd..2d3df419f1c 100644 --- a/drivers/cpu/imx8_cpu.c +++ b/drivers/cpu/imx8_cpu.c @@ -14,6 +14,7 @@ #include <asm/arch-imx/cpu.h> #include <asm/armv8/cpu.h> #include <linux/bitops.h> +#include <linux/clk-provider.h> DECLARE_GLOBAL_DATA_PTR; @@ -27,30 +28,43 @@ struct cpu_imx_plat { u32 mpidr; }; -static const char *get_imx8_type(u32 imxtype) +static const char *get_imx_type_str(u32 imxtype) { switch (imxtype) { case MXC_CPU_IMX8QXP: case MXC_CPU_IMX8QXP_A0: - return "QXP"; + return "8QXP"; case MXC_CPU_IMX8QM: - return "QM"; + return "8QM"; + case MXC_CPU_IMX93: + return "93(52)";/* iMX93 Dual core with NPU */ default: return "??"; } } -static const char *get_imx8_rev(u32 rev) +static const char *get_imx_rev_str(u32 rev) { - switch (rev) { - case CHIP_REV_A: - return "A"; - case CHIP_REV_B: - return "B"; - case CHIP_REV_C: - return "C"; - default: - return "?"; + static char revision[4]; + + if (IS_ENABLED(CONFIG_IMX8)) { + switch (rev) { + case CHIP_REV_A: + return "A"; + case CHIP_REV_B: + return "B"; + case CHIP_REV_C: + return "C"; + default: + return "?"; + } + } else { + revision[0] = '1' + (((rev & 0xf0) - CHIP_REV_1_0) >> 4); + revision[1] = '.'; + revision[2] = '0' + (rev & 0xf); + revision[3] = '\0'; + + return revision; } } @@ -67,6 +81,8 @@ static void set_core_data(struct udevice *dev) } else if (device_is_compatible(dev, "arm,cortex-a72")) { plat->cpu_rsrc = SC_R_A72; plat->name = "A72"; + } else if (device_is_compatible(dev, "arm,cortex-a55")) { + plat->name = "A55"; } else { plat->cpu_rsrc = SC_R_A53; plat->name = "?"; @@ -109,7 +125,7 @@ static int cpu_imx_get_desc(const struct udevice *dev, char *buf, int size) if (size < 100) return -ENOSPC; - ret = snprintf(buf, size, "NXP i.MX8%s Rev%s %s at %u MHz", + ret = snprintf(buf, size, "NXP i.MX%s Rev%s %s at %u MHz", plat->type, plat->rev, plat->name, plat->freq_mhz); if (IS_ENABLED(CONFIG_IMX_SCU_THERMAL)) { @@ -174,7 +190,7 @@ static int cpu_imx_is_current(struct udevice *dev) return 0; } -static const struct cpu_ops cpu_imx8_ops = { +static const struct cpu_ops cpu_imx_ops = { .get_desc = cpu_imx_get_desc, .get_info = cpu_imx_get_info, .get_count = cpu_imx_get_count, @@ -182,21 +198,32 @@ static const struct cpu_ops cpu_imx8_ops = { .is_current = cpu_imx_is_current, }; -static const struct udevice_id cpu_imx8_ids[] = { +static const struct udevice_id cpu_imx_ids[] = { { .compatible = "arm,cortex-a35" }, { .compatible = "arm,cortex-a53" }, + { .compatible = "arm,cortex-a55" }, { .compatible = "arm,cortex-a72" }, { } }; -static ulong imx8_get_cpu_rate(struct udevice *dev) +static ulong imx_get_cpu_rate(struct udevice *dev) { struct cpu_imx_plat *plat = dev_get_plat(dev); + struct clk clk; ulong rate; int ret; - ret = sc_pm_get_clock_rate(-1, plat->cpu_rsrc, SC_PM_CLK_CPU, - (sc_pm_clock_rate_t *)&rate); + if (IS_ENABLED(CONFIG_IMX8)) { + ret = sc_pm_get_clock_rate(-1, plat->cpu_rsrc, SC_PM_CLK_CPU, + (sc_pm_clock_rate_t *)&rate); + } else { + ret = clk_get_by_index(dev, 0, &clk); + if (!ret) { + rate = clk_get_rate(&clk); + if (!rate) + ret = -EOPNOTSUPP; + } + } if (ret) { printf("Could not read CPU frequency: %d\n", ret); return 0; @@ -205,7 +232,7 @@ static ulong imx8_get_cpu_rate(struct udevice *dev) return rate; } -static int imx8_cpu_probe(struct udevice *dev) +static int imx_cpu_probe(struct udevice *dev) { struct cpu_imx_plat *plat = dev_get_plat(dev); u32 cpurev; @@ -213,9 +240,9 @@ static int imx8_cpu_probe(struct udevice *dev) set_core_data(dev); cpurev = get_cpu_rev(); plat->cpurev = cpurev; - plat->rev = get_imx8_rev(cpurev & 0xFFF); - plat->type = get_imx8_type((cpurev & 0xFF000) >> 12); - plat->freq_mhz = imx8_get_cpu_rate(dev) / 1000000; + plat->rev = get_imx_rev_str(cpurev & 0xFFF); + plat->type = get_imx_type_str((cpurev & 0xFF000) >> 12); + plat->freq_mhz = imx_get_cpu_rate(dev) / 1000000; plat->mpidr = dev_read_addr(dev); if (plat->mpidr == FDT_ADDR_T_NONE) { printf("%s: Failed to get CPU reg property\n", __func__); @@ -225,12 +252,12 @@ static int imx8_cpu_probe(struct udevice *dev) return 0; } -U_BOOT_DRIVER(cpu_imx8_drv) = { - .name = "imx8x_cpu", +U_BOOT_DRIVER(cpu_imx_drv) = { + .name = "imx_cpu", .id = UCLASS_CPU, - .of_match = cpu_imx8_ids, - .ops = &cpu_imx8_ops, - .probe = imx8_cpu_probe, + .of_match = cpu_imx_ids, + .ops = &cpu_imx_ops, + .probe = imx_cpu_probe, .plat_auto = sizeof(struct cpu_imx_plat), .flags = DM_FLAG_PRE_RELOC, }; -- 2.40.0