Add a CPU driver for the MPC83xx architecture. Signed-off-by: Mario Six <mario....@gdsys.cc> --- 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 | 358 +++++++++++++++++++++++++++++++++++ drivers/cpu/mpc83xx_cpu.h | 173 +++++++++++++++++ include/cpu.h | 1 + 8 files changed, 546 insertions(+) create mode 100644 drivers/cpu/mpc83xx_cpu.c create mode 100644 drivers/cpu/mpc83xx_cpu.h
diff --git a/arch/powerpc/cpu/mpc83xx/cpu.c b/arch/powerpc/cpu/mpc83xx/cpu.c index d25a935297..f8da3f3d49 100644 --- a/arch/powerpc/cpu/mpc83xx/cpu.c +++ b/arch/powerpc/cpu/mpc83xx/cpu.c @@ -26,6 +26,7 @@ DECLARE_GLOBAL_DATA_PTR; +#ifndef CONFIG_CPU_MPC83XX int checkcpu(void) { volatile immap_t *immr; @@ -115,6 +116,7 @@ int checkcpu(void) return 0; } +#endif int do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) diff --git a/arch/powerpc/cpu/mpc83xx/cpu_init.c b/arch/powerpc/cpu/mpc83xx/cpu_init.c index 2a9db0c51b..afbfa9e9b0 100644 --- a/arch/powerpc/cpu/mpc83xx/cpu_init.c +++ b/arch/powerpc/cpu/mpc83xx/cpu_init.c @@ -465,6 +465,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 */ @@ -506,3 +507,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 57b11b8365..1c9386e503 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -1327,7 +1327,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 0d1424d38e..d4052005e2 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 db515f6f17..29d7da42fa 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 0000000000..2a7de10e53 --- /dev/null +++ b/drivers/cpu/mpc83xx_cpu.c @@ -0,0 +1,358 @@ +/* + * (C) Copyright 2018 + * Mario Six, Guntermann & Drunck GmbH, mario....@gdsys.cc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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_compat(UCLASS_CPU, &cpu, "fsl,mpc8308"); + cpu; + uclass_next_device_compat(&cpu, "fsl,mpc8308")) { + } + + return 0; +} + +#if defined(CONFIG_DISPLAY_AER_FULL) +static int print_83xx_arb_event(int force) +{ + int etype = (gd->arch.arbiter_event_attributes & AEATR_EVENT) + >> AEATR_EVENT_SHIFT; + int mstr_id = (gd->arch.arbiter_event_attributes & AEATR_MSTR_ID) + >> AEATR_MSTR_ID_SHIFT; + int tbst = (gd->arch.arbiter_event_attributes & AEATR_TBST) + >> AEATR_TBST_SHIFT; + int tsize = (gd->arch.arbiter_event_attributes & AEATR_TSIZE) + >> AEATR_TSIZE_SHIFT; + int ttype = (gd->arch.arbiter_event_attributes & AEATR_TTYPE) + >> AEATR_TTYPE_SHIFT; + + if (!force && !gd->arch.arbiter_event_address) + return 0; + + puts("Arbiter Event Status:\n"); + printf(" Event Address: 0x%08lX\n", + gd->arch.arbiter_event_address); + printf(" Event Type: 0x%1x = %s\n", etype, event[etype]); + printf(" Master ID: 0x%02x = %s\n", mstr_id, master[mstr_id]); + printf(" Transfer Size: 0x%1x = %d bytes\n", (tbst << 3) | tsize, + tbst ? (tsize ? tsize : 8) : 16 + 8 * tsize); + printf(" Transfer Type: 0x%02x = %s\n", ttype, transfer[ttype]); + + return gd->arch.arbiter_event_address; +} + +#elif defined(CONFIG_DISPLAY_AER_BRIEF) + +static int print_83xx_arb_event(int force) +{ + if (!force && !gd->arch.arbiter_event_address) + return 0; + + printf("Arbiter Event Status: AEATR=0x%08lX, AEADR=0x%08lX\n", + gd->arch.arbiter_event_attributes, + gd->arch.arbiter_event_address); + + return gd->arch.arbiter_event_address; +} +#endif /* CONFIG_DISPLAY_AER_xxxx */ + +void prt_83xx_rsr(void) +{ + static const struct { + ulong mask; + char *desc; + } bits[] = { + { + RSR_SWSR, "Software Soft"}, { + RSR_SWHR, "Software Hard"}, { + RSR_JSRS, "JTAG Soft"}, { + RSR_CSHR, "Check Stop"}, { + RSR_SWRS, "Software Watchdog"}, { + RSR_BMRS, "Bus Monitor"}, { + RSR_SRS, "External/Internal Soft"}, { + RSR_HRS, "External/Internal Hard"} + }; + static int n = ARRAY_SIZE(bits); + ulong rsr = gd->arch.reset_status; + int i; + char *sep; + + printf("Reset Status:"); + + puts(""); + + sep = " "; + for (i = 0; i < n; i++) + if (rsr & bits[i].mask) { + printf("%s%s%s", sep, bits[i].desc, (i == n - 1) ? "\n" : ""); + sep = ", "; + } +#if defined(CONFIG_DISPLAY_AER_FULL) || defined(CONFIG_DISPLAY_AER_BRIEF) + print_83xx_arb_event(rsr & RSR_BMRS); +#endif + printf("\n"); +} + +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) +{ + 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: Fix */ + return 42; +} + +static int mpc83xx_cpu_get_vendor(struct udevice *dev, char *buf, int size) +{ + snprintf(buf, size, "NXP"); + + return 0; +} + +static int mpc83xx_cpu_print_info(struct udevice *dev) +{ + 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); + + prt_83xx_rsr(); + + printf("CPU: %s, MPC%s%s%s, Rev: %d.%d at %s MHz, CSB: %s MHz", + 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 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, + .print_info = mpc83xx_cpu_print_info, +}; + +int mpc83xx_cpu_probe(struct udevice *dev) +{ + cpu_print_info(dev); + printf("\n"); + + 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 0000000000..f4a256eaf6 --- /dev/null +++ b/drivers/cpu/mpc83xx_cpu.h @@ -0,0 +1,173 @@ +/* + * (C) Copyright 2018 + * Mario Six, Guntermann & Drunck GmbH, mario....@gdsys.cc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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 37ff000bf9..eb521e4e66 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -44,6 +44,7 @@ enum { struct cpu_info { ulong cpu_freq; ulong features; + void *specific_info; }; struct cpu_ops { -- 2.16.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot