
Add a CPU driver for the MPC83xx architecture.
Signed-off-by: Mario Six mario.six@gdsys.cc
---
v2 -> v3: * Added driver files to MAINTAINERS
v1 -> v2: * Removed cpu_print_info * Fixed CPU info printing * Removed usage of uclass_{first,next}_device_compat * Removed printing of reset status
--- MAINTAINERS | 2 + arch/powerpc/cpu/mpc83xx/cpu.c | 2 + arch/powerpc/cpu/mpc83xx/cpu_init.c | 2 + arch/powerpc/include/asm/processor.h | 2 + drivers/cpu/Kconfig | 7 + drivers/cpu/Makefile | 1 + drivers/cpu/mpc83xx_cpu.c | 265 +++++++++++++++++++++++++++++++++++ drivers/cpu/mpc83xx_cpu.h | 172 +++++++++++++++++++++++ include/cpu.h | 1 + 9 files changed, 454 insertions(+) create mode 100644 drivers/cpu/mpc83xx_cpu.c create mode 100644 drivers/cpu/mpc83xx_cpu.h
diff --git a/MAINTAINERS b/MAINTAINERS index f03cfcc73b0..11965be1402 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -475,6 +475,8 @@ F: drivers/clk/mpc83xx_clk.c F: drivers/clk/mpc83xx_clk.h F: include/dt-bindings/clk/mpc83xx-clk.h F: drivers/timer/mpc83xx_timer.c +F: drivers/cpu/mpc83xx_cpu.c +F: drivers/cpu/mpc83xx_cpu.h F: arch/powerpc/cpu/mpc83xx/ F: arch/powerpc/include/asm/arch-mpc83xx/
diff --git a/arch/powerpc/cpu/mpc83xx/cpu.c b/arch/powerpc/cpu/mpc83xx/cpu.c index ffb42415feb..b29f271e9bc 100644 --- a/arch/powerpc/cpu/mpc83xx/cpu.c +++ b/arch/powerpc/cpu/mpc83xx/cpu.c @@ -25,6 +25,7 @@
DECLARE_GLOBAL_DATA_PTR;
+#ifndef CONFIG_CPU_MPC83XX int checkcpu(void) { volatile immap_t *immr; @@ -114,6 +115,7 @@ int checkcpu(void)
return 0; } +#endif
#ifndef CONFIG_SYSRESET int diff --git a/arch/powerpc/cpu/mpc83xx/cpu_init.c b/arch/powerpc/cpu/mpc83xx/cpu_init.c index fcac9f63a81..1555205e069 100644 --- a/arch/powerpc/cpu/mpc83xx/cpu_init.c +++ b/arch/powerpc/cpu/mpc83xx/cpu_init.c @@ -464,6 +464,7 @@ static int print_83xx_arb_event(int force) } #endif /* CONFIG_DISPLAY_AER_xxxx */
+#ifndef CONFIG_CPU_MPC83XX /* * Figure out the cause of the reset */ @@ -505,3 +506,4 @@ int prt_83xx_rsr(void)
return 0; } +#endif diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 6fbe8c46b31..f97ce48cc27 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -1325,7 +1325,9 @@ void ll_puts(const char *); /* In misc.c */ void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
+#ifndef CONFIG_CPU_MPC83XX int prt_83xx_rsr(void); +#endif
#endif /* ndef ASSEMBLY*/
diff --git a/drivers/cpu/Kconfig b/drivers/cpu/Kconfig index 0d1424d38e9..d4052005e24 100644 --- a/drivers/cpu/Kconfig +++ b/drivers/cpu/Kconfig @@ -6,3 +6,10 @@ config CPU multiple CPUs, then normally have to be set up in U-Boot so that they can work correctly in the OS. This provides a framework for finding out information about available CPUs and making changes. + +config CPU_MPC83XX + bool "Enable MPC83xx CPU driver" + depends on CPU + select CLK_MPC83XX + help + Support CPU cores for SoCs of the MPC83xx series. diff --git a/drivers/cpu/Makefile b/drivers/cpu/Makefile index db515f6f177..29d7da42fad 100644 --- a/drivers/cpu/Makefile +++ b/drivers/cpu/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_CPU) += cpu-uclass.o
obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o +obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o diff --git a/drivers/cpu/mpc83xx_cpu.c b/drivers/cpu/mpc83xx_cpu.c new file mode 100644 index 00000000000..550a7ad89f1 --- /dev/null +++ b/drivers/cpu/mpc83xx_cpu.c @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2018 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +#include <common.h> +#include <dm.h> +#include <cpu.h> +#include <clk.h> +#include <asm/immap_83xx.h> + +#include "mpc83xx_cpu.h" + +struct mpc83xx_cpu_priv { + struct mpc83xx_cpu_info info; +}; + +int checkcpu(void) +{ + struct udevice *cpu; + + for (uclass_first_device(UCLASS_CPU, &cpu); + cpu; + uclass_next_device(&cpu)) { + } + + return 0; +} + +static inline u32 get_spridr(void) +{ + immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; + + return in_be32(&immr->sysconf.spridr); +} + +static inline void determine_family(struct udevice *dev) +{ + struct mpc83xx_cpu_priv *priv = dev_get_priv(dev); + + switch ((get_spridr() & 0xFFFE0000) >> 16) { + case 0x80B: + priv->info.family = FAMILY_831X; + break; + case 0x806: + priv->info.family = FAMILY_832X; + break; + case 0x803: + priv->info.family = FAMILY_834X; + break; + case 0x804: + priv->info.family = FAMILY_836X; + break; + case 0x80C: + priv->info.family = FAMILY_837X; + break; + default: + priv->info.family = FAMILY_UNKNOWN; + } +} + +static inline void determine_type(struct udevice *dev) +{ + struct mpc83xx_cpu_priv *priv = dev_get_priv(dev); + + switch ((get_spridr() & 0xFFFE0000) >> 16) { + case 0x8100: + priv->info.type = TYPE_8308; + break; + case 0x8110: + priv->info.type = TYPE_8309; + break; + case 0x80B2: + priv->info.type = TYPE_8311; + break; + case 0x80B0: + priv->info.type = TYPE_8313; + break; + case 0x80B6: + priv->info.type = TYPE_8314; + break; + case 0x80B4: + priv->info.type = TYPE_8315; + break; + case 0x8066: + priv->info.type = TYPE_8321; + break; + case 0x8062: + priv->info.type = TYPE_8323; + break; + case 0x8036: + priv->info.type = TYPE_8343; + break; + case 0x8032: + priv->info.type = TYPE_8347_TBGA; + break; + case 0x8034: + priv->info.type = TYPE_8347_PBGA; + break; + case 0x8030: + priv->info.type = TYPE_8349; + break; + case 0x804A: + priv->info.type = TYPE_8358_TBGA; + break; + case 0x804E: + priv->info.type = TYPE_8358_PBGA; + break; + case 0x8048: + priv->info.type = TYPE_8360; + break; + case 0x80C6: + priv->info.type = TYPE_8377; + break; + case 0x80C4: + priv->info.type = TYPE_8378; + break; + case 0x80C2: + priv->info.type = TYPE_8379; + break; + default: + priv->info.type = TYPE_UNKNOWN; + } +} + +static inline void determine_e300_type(struct udevice *dev) +{ + struct mpc83xx_cpu_priv *priv = dev_get_priv(dev); + u32 pvr = get_pvr(); + + switch (pvr & 0xffff0000) { + case 0x80830000: + priv->info.e300_type = E300C1; + break; + case 0x80840000: + priv->info.e300_type = E300C2; + break; + case 0x80850000: + priv->info.e300_type = E300C3; + break; + case 0x80860000: + priv->info.e300_type = E300C4; + break; + default: + priv->info.e300_type = E300_UNKNOWN; + } +} + +static inline void determine_revid_other(struct udevice *dev) +{ + struct mpc83xx_cpu_priv *priv = dev_get_priv(dev); + u32 spridr = get_spridr(); + + priv->info.revid.major = (spridr & 0x000000F0) >> 4; + priv->info.revid.minor = spridr & 0x0000000F; +} + +static inline void determine_revid_mpc834x(struct udevice *dev) +{ + struct mpc83xx_cpu_priv *priv = dev_get_priv(dev); + u32 spridr = get_spridr(); + + priv->info.revid.major = (spridr & 0x0000FF00) >> 8; + priv->info.revid.minor = spridr & 0x000000FF; +} + +static void determine_cpu_data(struct udevice *dev) +{ + struct mpc83xx_cpu_priv *priv = dev_get_priv(dev); + u32 spridr = get_spridr(); + + determine_family(dev); + determine_type(dev); + determine_e300_type(dev); + + if (priv->info.family == FAMILY_834X) + determine_revid_mpc834x(dev); + else + determine_revid_other(dev); + + if ((priv->info.family == FAMILY_834X || + priv->info.family == FAMILY_836X) && priv->info.revid.major >= 2) + priv->info.is_a_variant = true; + + priv->info.is_e_processor = !(spridr & 0x00010000); +} + +static int mpc83xx_cpu_get_desc(struct udevice *dev, char *buf, int size) +{ + struct mpc83xx_cpu_priv *priv = dev_get_priv(dev); + struct clk core_clk; + struct clk csb_clk; + char core_freq[32]; + char csb_freq[32]; + + clk_get_by_index(dev, 0, &core_clk); + clk_get_by_index(dev, 1, &csb_clk); + + determine_cpu_data(dev); + + snprintf(buf, size, "CPU: %s, MPC%s%s%s, Rev: %d.%d at %s MHz, CSB: %s MHz\n", + e300_names[priv->info.e300_type], + cpu_type_names[priv->info.type], + priv->info.is_e_processor ? "E" : "", + priv->info.is_a_variant ? "A" : "", + priv->info.revid.major, + priv->info.revid.minor, + strmhz(core_freq, clk_get_rate(&core_clk)), + strmhz(csb_freq, clk_get_rate(&csb_clk))); + + return 0; +} + +static int mpc83xx_cpu_get_info(struct udevice *dev, struct cpu_info *info) +{ + struct clk clock; + + clk_get_by_index(dev, 0, &clock); + + info->cpu_freq = clk_get_rate(&clock); + info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU); + + return 0; +} + +static int mpc83xx_cpu_get_count(struct udevice *dev) +{ + /* TODO(mario.six@gdsys.cc): Replace this with real number of cores */ + return 1; +} + +static int mpc83xx_cpu_get_vendor(struct udevice *dev, char *buf, int size) +{ + snprintf(buf, size, "NXP"); + + return 0; +} + +static const struct cpu_ops mpc83xx_cpu_ops = { + .get_desc = mpc83xx_cpu_get_desc, + .get_info = mpc83xx_cpu_get_info, + .get_count = mpc83xx_cpu_get_count, + .get_vendor = mpc83xx_cpu_get_vendor, +}; + +int mpc83xx_cpu_probe(struct udevice *dev) +{ + return 0; +} + +static const struct udevice_id mpc83xx_cpu_ids[] = { + { .compatible = "fsl,mpc8308", }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(mpc83xx_cpu) = { + .name = "mpc83xx_cpu", + .id = UCLASS_CPU, + .of_match = mpc83xx_cpu_ids, + .probe = mpc83xx_cpu_probe, + .priv_auto_alloc_size = sizeof(struct mpc83xx_cpu_priv), + .ops = &mpc83xx_cpu_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/cpu/mpc83xx_cpu.h b/drivers/cpu/mpc83xx_cpu.h new file mode 100644 index 00000000000..0f9926d1877 --- /dev/null +++ b/drivers/cpu/mpc83xx_cpu.h @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2018 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +#ifndef _MPC83XX_CPU_H_ +#define _MPC83XX_CPU_H_ + +enum e300_type { + E300C1, + E300C2, + E300C3, + E300C4, + E300_UNKNOWN, +}; + +static const char * const e300_names[] = { + [E300C1] = "e300c1", + [E300C2] = "e300c2", + [E300C3] = "e300c3", + [E300C4] = "e300c4", + [E300_UNKNOWN] = "Unknown e300", +}; + +enum mpc83xx_cpu_family { + FAMILY_831X, + FAMILY_832X, + FAMILY_834X, + FAMILY_836X, + FAMILY_837X, + FAMILY_UNKNOWN, +}; + +enum mpc83xx_cpu_type { + TYPE_8308, + TYPE_8309, + TYPE_8311, + TYPE_8313, + TYPE_8314, + TYPE_8315, + TYPE_8321, + TYPE_8323, + TYPE_8343, + TYPE_8347_TBGA, + TYPE_8347_PBGA, + TYPE_8349, + TYPE_8358_TBGA, + TYPE_8358_PBGA, + TYPE_8360, + TYPE_8377, + TYPE_8378, + TYPE_8379, + TYPE_UNKNOWN, +}; + +static const char * const cpu_type_names[] = { + [TYPE_8308] = "8308", + [TYPE_8309] = "8309", + [TYPE_8311] = "8311", + [TYPE_8313] = "8313", + [TYPE_8314] = "8314", + [TYPE_8315] = "8315", + [TYPE_8321] = "8321", + [TYPE_8323] = "8323", + [TYPE_8343] = "8343", + [TYPE_8347_TBGA] = "8347_TBGA", + [TYPE_8347_PBGA] = "8347_PBGA", + [TYPE_8349] = "8349", + [TYPE_8358_TBGA] = "8358_TBGA", + [TYPE_8358_PBGA] = "8358_PBGA", + [TYPE_8360] = "8360", + [TYPE_8377] = "8377", + [TYPE_8378] = "8378", + [TYPE_8379] = "8379", + [TYPE_UNKNOWN] = "Unknown CPU", +}; + +struct mpc83xx_cpu_info { + enum e300_type e300_type; + enum mpc83xx_cpu_family family; + enum mpc83xx_cpu_type type; + bool is_e_processor; + bool is_a_variant; + struct { + uint major; + uint minor; + } revid; +}; + +static const char * const event[] = { + "Address Time Out", + "Data Time Out", + "Address Only Transfer Type", + "External Control Word Transfer Type", + "Reserved Transfer Type", + "Transfer Error", + "reserved", + "reserved" +}; + +static const char * const master[] = { + "e300 Core Data Transaction", + "reserved", + "e300 Core Instruction Fetch", + "reserved", + "TSEC1", + "TSEC2", + "USB MPH", + "USB DR", + "Encryption Core", + "I2C Boot Sequencer", + "JTAG", + "reserved", + "eSDHC", + "PCI1", + "PCI2", + "DMA", + "QUICC Engine 00", + "QUICC Engine 01", + "QUICC Engine 10", + "QUICC Engine 11", + "reserved", + "reserved", + "reserved", + "reserved", + "SATA1", + "SATA2", + "SATA3", + "SATA4", + "reserved", + "PCI Express 1", + "PCI Express 2", + "TDM-DMAC" +}; + +static const char * const transfer[] = { + "Address-only, Clean Block", + "Address-only, lwarx reservation set", + "Single-beat or Burst write", + "reserved", + "Address-only, Flush Block", + "reserved", + "Burst write", + "reserved", + "Address-only, sync", + "Address-only, tlbsync", + "Single-beat or Burst read", + "Single-beat or Burst read", + "Address-only, Kill Block", + "Address-only, icbi", + "Burst read", + "reserved", + "Address-only, eieio", + "reserved", + "Single-beat write", + "reserved", + "ecowx - Illegal single-beat write", + "reserved", + "reserved", + "reserved", + "Address-only, TLB Invalidate", + "reserved", + "Single-beat or Burst read", + "reserved", + "eciwx - Illegal single-beat read", + "reserved", + "Burst read", + "reserved" +}; + +#endif /* !_MPC83XX_CPU_H_ */ diff --git a/include/cpu.h b/include/cpu.h index 5cc7c5abd72..e1de356b543 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -43,6 +43,7 @@ enum { struct cpu_info { ulong cpu_freq; ulong features; + void *specific_info; };
struct cpu_ops { -- 2.11.0