diff options
Diffstat (limited to 'cpu/mpc83xx/cpu.c')
-rw-r--r-- | cpu/mpc83xx/cpu.c | 273 |
1 files changed, 265 insertions, 8 deletions
diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c index 1b5107881ed..e934ba638fe 100644 --- a/cpu/mpc83xx/cpu.c +++ b/cpu/mpc83xx/cpu.c @@ -30,8 +30,14 @@ #include <watchdog.h> #include <command.h> #include <mpc83xx.h> -#include <ft_build.h> #include <asm/processor.h> +#if defined(CONFIG_OF_FLAT_TREE) +#include <ft_build.h> +#endif +#if defined(CONFIG_OF_LIBFDT) +#include <libfdt.h> +#include <libfdt_env.h> +#endif DECLARE_GLOBAL_DATA_PTR; @@ -56,49 +62,78 @@ int checkcpu(void) switch(spridr) { case SPR_8349E_REV10: case SPR_8349E_REV11: + case SPR_8349E_REV31: puts("MPC8349E, "); break; case SPR_8349_REV10: case SPR_8349_REV11: + case SPR_8349_REV31: puts("MPC8349, "); break; case SPR_8347E_REV10_TBGA: case SPR_8347E_REV11_TBGA: + case SPR_8347E_REV31_TBGA: case SPR_8347E_REV10_PBGA: case SPR_8347E_REV11_PBGA: + case SPR_8347E_REV31_PBGA: puts("MPC8347E, "); break; case SPR_8347_REV10_TBGA: case SPR_8347_REV11_TBGA: + case SPR_8347_REV31_TBGA: case SPR_8347_REV10_PBGA: case SPR_8347_REV11_PBGA: + case SPR_8347_REV31_PBGA: puts("MPC8347, "); break; case SPR_8343E_REV10: case SPR_8343E_REV11: + case SPR_8343E_REV31: puts("MPC8343E, "); break; case SPR_8343_REV10: case SPR_8343_REV11: + case SPR_8343_REV31: puts("MPC8343, "); break; case SPR_8360E_REV10: case SPR_8360E_REV11: case SPR_8360E_REV12: + case SPR_8360E_REV20: puts("MPC8360E, "); break; case SPR_8360_REV10: case SPR_8360_REV11: case SPR_8360_REV12: + case SPR_8360_REV20: puts("MPC8360, "); break; + case SPR_8323E_REV10: + case SPR_8323E_REV11: + puts("MPC8323E, "); + break; + case SPR_8323_REV10: + case SPR_8323_REV11: + puts("MPC8323, "); + break; + case SPR_8321E_REV10: + case SPR_8321E_REV11: + puts("MPC8321E, "); + break; + case SPR_8321_REV10: + case SPR_8321_REV11: + puts("MPC8321, "); + break; default: - puts("Rev: Unknown\n"); - return -1; /* Not sure what this is */ + puts("Rev: Unknown revision number.\nWarning: Unsupported cpu revision!\n"); + return 0; } -#if defined(CONFIG_MPC8349) - printf("Rev: %02x at %s MHz\n", (spridr & 0x0000FFFF)>>4 |(spridr & 0x0000000F), strmhz(buf, clock)); +#if defined(CONFIG_MPC834X) + /* Multiple revisons of 834x processors may have the same SPRIDR value. + * So use PVR to identify the revision number. + */ + printf("Rev: %02x at %s MHz\n", PVR_MAJ(pvr)<<4 | PVR_MIN(pvr), strmhz(buf, clock)); #else printf("Rev: %02x at %s MHz\n", spridr & 0x0000FFFF, strmhz(buf, clock)); #endif @@ -250,7 +285,6 @@ unsigned long get_tbclk(void) #if defined(CONFIG_WATCHDOG) void watchdog_reset (void) { -#ifdef CONFIG_MPC834X int re_enable = disable_interrupts(); /* Reset the 83xx watchdog */ @@ -260,9 +294,182 @@ void watchdog_reset (void) if (re_enable) enable_interrupts (); -#else - hang(); +} #endif + +#if defined(CONFIG_OF_LIBFDT) + +/* + * "Setter" functions used to add/modify FDT entries. + */ +static int fdt_set_eth0(void *fdt, int nodeoffset, const char *name, bd_t *bd) +{ + /* + * Fix it up if it exists, don't create it if it doesn't exist. + */ + if (fdt_get_property(fdt, nodeoffset, name, 0)) { + return fdt_setprop(fdt, nodeoffset, name, bd->bi_enetaddr, 6); + } + return -FDT_ERR_NOTFOUND; +} +#ifdef CONFIG_HAS_ETH1 +/* second onboard ethernet port */ +static int fdt_set_eth1(void *fdt, int nodeoffset, const char *name, bd_t *bd) +{ + /* + * Fix it up if it exists, don't create it if it doesn't exist. + */ + if (fdt_get_property(fdt, nodeoffset, name, 0)) { + return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet1addr, 6); + } + return -FDT_ERR_NOTFOUND; +} +#endif +#ifdef CONFIG_HAS_ETH2 +/* third onboard ethernet port */ +static int fdt_set_eth2(void *fdt, int nodeoffset, const char *name, bd_t *bd) +{ + /* + * Fix it up if it exists, don't create it if it doesn't exist. + */ + if (fdt_get_property(fdt, nodeoffset, name, 0)) { + return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet2addr, 6); + } + return -FDT_ERR_NOTFOUND; +} +#endif +#ifdef CONFIG_HAS_ETH3 +/* fourth onboard ethernet port */ +static int fdt_set_eth3(void *fdt, int nodeoffset, const char *name, bd_t *bd) +{ + /* + * Fix it up if it exists, don't create it if it doesn't exist. + */ + if (fdt_get_property(fdt, nodeoffset, name, 0)) { + return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet3addr, 6); + } + return -FDT_ERR_NOTFOUND; +} +#endif + +static int fdt_set_busfreq(void *fdt, int nodeoffset, const char *name, bd_t *bd) +{ + u32 tmp; + /* + * Create or update the property. + */ + tmp = cpu_to_be32(bd->bi_busfreq); + return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/* + * Fixups to the fdt. If "create" is TRUE, the node is created + * unconditionally. If "create" is FALSE, the node is updated + * only if it already exists. + */ +static const struct { + char *node; + char *prop; + int (*set_fn)(void *fdt, int nodeoffset, const char *name, bd_t *bd); +} fixup_props[] = { + { "/cpus/" OF_CPU, + "bus-frequency", + fdt_set_busfreq + }, + { "/cpus/" OF_SOC, + "bus-frequency", + fdt_set_busfreq + }, + { "/" OF_SOC "/serial@4500/", + "clock-frequency", + fdt_set_busfreq + }, + { "/" OF_SOC "/serial@4600/", + "clock-frequency", + fdt_set_busfreq + }, +#ifdef CONFIG_MPC83XX_TSEC1 + { "/" OF_SOC "/ethernet@24000, + "mac-address", + fdt_set_eth0 + }, + { "/" OF_SOC "/ethernet@24000, + "local-mac-address", + fdt_set_eth0 + }, +#endif +#ifdef CONFIG_MPC83XX_TSEC2 + { "/" OF_SOC "/ethernet@25000, + "mac-address", + fdt_set_eth1 + }, + { "/" OF_SOC "/ethernet@25000, + "local-mac-address", + fdt_set_eth1 + }, +#endif +#ifdef CONFIG_UEC_ETH1 +#if CFG_UEC1_UCC_NUM == 0 /* UCC1 */ + { "/" OF_QE "/ucc@2000/mac-address", + "mac-address", + fdt_set_eth0 + }, + { "/" OF_QE "/ucc@2000/mac-address", + "local-mac-address", + fdt_set_eth0 + }, +#elif CFG_UEC1_UCC_NUM == 2 /* UCC3 */ + { "/" OF_QE "/ucc@2200/mac-address", + "mac-address", + fdt_set_eth0 + }, + { "/" OF_QE "/ucc@2200/mac-address", + "local-mac-address", + fdt_set_eth0 + }, +#endif +#endif +#ifdef CONFIG_UEC_ETH2 +#if CFG_UEC2_UCC_NUM == 1 /* UCC2 */ + { "/" OF_QE "/ucc@3000/mac-address", + "mac-address", + fdt_set_eth1 + }, + { "/" OF_QE "/ucc@3000/mac-address", + "local-mac-address", + fdt_set_eth1 + }, +#elif CFG_UEC1_UCC_NUM == 3 /* UCC4 */ + { "/" OF_QE "/ucc@3200/mac-address", + "mac-address", + fdt_set_eth1 + }, + { "/" OF_QE "/ucc@3200/mac-address", + "local-mac-address", + fdt_set_eth1 + }, +#endif +#endif +}; + +void +ft_cpu_setup(void *blob, bd_t *bd) +{ + int nodeoffset; + int err; + int j; + + for (j = 0; j < (sizeof(fixup_props) / sizeof(fixup_props[0])); j++) { + nodeoffset = fdt_path_offset(fdt, fixup_props[j].node); + if (nodeoffset >= 0) { + err = (*fixup_props[j].set_fn)(blob, nodeoffset, fixup_props[j].prop, bd); + if (err < 0) + printf("set_fn/libfdt: %s %s returned %s\n", + fixup_props[j].node, + fixup_props[j].prop, + fdt_strerror(err)); + } + } } #endif @@ -292,13 +499,63 @@ ft_cpu_setup(void *blob, bd_t *bd) *p = cpu_to_be32(clock); #ifdef CONFIG_MPC83XX_TSEC1 + p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/mac-address", &len); + if (p != NULL) + memcpy(p, bd->bi_enetaddr, 6); + p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/local-mac-address", &len); + if (p != NULL) memcpy(p, bd->bi_enetaddr, 6); #endif #ifdef CONFIG_MPC83XX_TSEC2 + p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/mac-address", &len); + if (p != NULL) + memcpy(p, bd->bi_enet1addr, 6); + p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/local-mac-address", &len); + if (p != NULL) + memcpy(p, bd->bi_enet1addr, 6); +#endif + +#ifdef CONFIG_UEC_ETH1 +#if CFG_UEC1_UCC_NUM == 0 /* UCC1 */ + p = ft_get_prop(blob, "/" OF_QE "/ucc@2000/mac-address", &len); + if (p != NULL) + memcpy(p, bd->bi_enetaddr, 6); + + p = ft_get_prop(blob, "/" OF_QE "/ucc@2000/local-mac-address", &len); + if (p != NULL) + memcpy(p, bd->bi_enetaddr, 6); +#elif CFG_UEC1_UCC_NUM == 2 /* UCC3 */ + p = ft_get_prop(blob, "/" OF_QE "/ucc@2200/mac-address", &len); + if (p != NULL) + memcpy(p, bd->bi_enetaddr, 6); + + p = ft_get_prop(blob, "/" OF_QE "/ucc@2200/local-mac-address", &len); + if (p != NULL) + memcpy(p, bd->bi_enetaddr, 6); +#endif +#endif + +#ifdef CONFIG_UEC_ETH2 +#if CFG_UEC2_UCC_NUM == 1 /* UCC2 */ + p = ft_get_prop(blob, "/" OF_QE "/ucc@3000/mac-address", &len); + if (p != NULL) + memcpy(p, bd->bi_enet1addr, 6); + + p = ft_get_prop(blob, "/" OF_QE "/ucc@3000/local-mac-address", &len); + if (p != NULL) memcpy(p, bd->bi_enet1addr, 6); +#elif CFG_UEC2_UCC_NUM == 3 /* UCC4 */ + p = ft_get_prop(blob, "/" OF_QE "/ucc@3200/mac-address", &len); + if (p != NULL) + memcpy(p, bd->bi_enet1addr, 6); + + p = ft_get_prop(blob, "/" OF_QE "/ucc@3200/local-mac-address", &len); + if (p != NULL) + memcpy(p, bd->bi_enet1addr, 6); +#endif #endif } #endif |