summaryrefslogtreecommitdiff
path: root/arch/powerpc/cpu/mpc85xx
diff options
context:
space:
mode:
authorWolfgang Denk <wd@denx.de>2011-12-01 23:58:11 +0100
committerWolfgang Denk <wd@denx.de>2011-12-01 23:58:11 +0100
commitd51e6d6de2b7dcba43fadcae2c89f7346d8bc301 (patch)
tree49bedf2073e031a421c89644f62134bf9ee4f44b /arch/powerpc/cpu/mpc85xx
parent22e0f5a9ecab85f36a0fe69892d950c1ac212c91 (diff)
parent9839709ea3df89f6021034508f48b97cab33ebb8 (diff)
Merge branch 'master' of git://git.denx.de/u-boot-mpc85xx
* 'master' of git://git.denx.de/u-boot-mpc85xx: mpc85xx: support for Freescale COM Express P2020 arch/powerpc/cpu/mpc8xxx/ddr/interactive.c: Fix GCC 4.6 build warning mpc85xx: support board-specific reset function powerpc/85xx: verify the localbus device tree address before booting the OS mpc8xxx: update module_type values from JEDEC DDR3 SPD Specification powerpc/p3060qds: Add board related support for P3060QDS platform powerpc/85xx: clean up and document the QE/FMAN microcode macros powerpc/85xx: always implement the work-around for Erratum SATA_A001 powerpc/85xx: CONFIG_FSL_SATA_V2 should be defined in config_mpc85xx.h powerpc/85xx: Add workaround for erratum A-003474 powerpc/85xx: fixup flexcan device tree clock-frequency powerpc/85xx: Add workaround for erratum CPU-A003999
Diffstat (limited to 'arch/powerpc/cpu/mpc85xx')
-rw-r--r--arch/powerpc/cpu/mpc85xx/cmd_errata.c6
-rw-r--r--arch/powerpc/cpu/mpc85xx/cpu.c17
-rw-r--r--arch/powerpc/cpu/mpc85xx/cpu_init.c49
-rw-r--r--arch/powerpc/cpu/mpc85xx/ddr-gen3.c5
-rw-r--r--arch/powerpc/cpu/mpc85xx/fdt.c63
-rw-r--r--arch/powerpc/cpu/mpc85xx/release.S6
-rw-r--r--arch/powerpc/cpu/mpc85xx/start.S6
7 files changed, 130 insertions, 22 deletions
diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
index 253bf08b6a..2ed5a98424 100644
--- a/arch/powerpc/cpu/mpc85xx/cmd_errata.c
+++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
@@ -53,6 +53,12 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#if defined(CONFIG_SYS_P4080_ERRATUM_CPU22)
puts("Work-around for Erratum CPU22 enabled\n");
#endif
+#if defined(CONFIG_SYS_FSL_ERRATUM_CPU_A003999)
+ puts("Work-around for Erratum CPU-A003999 enabled\n");
+#endif
+#if defined(CONFIG_SYS_FSL_ERRATUM_DDR_A003474)
+ puts("Work-around for Erratum DDR-A003473 enabled\n");
+#endif
#if defined(CONFIG_SYS_FSL_ERRATUM_DDR_MSYNC_IN)
puts("Work-around for DDR MSYNC_IN Erratum enabled\n");
#endif
diff --git a/arch/powerpc/cpu/mpc85xx/cpu.c b/arch/powerpc/cpu/mpc85xx/cpu.c
index 49c0551692..c1815e8860 100644
--- a/arch/powerpc/cpu/mpc85xx/cpu.c
+++ b/arch/powerpc/cpu/mpc85xx/cpu.c
@@ -42,6 +42,16 @@
DECLARE_GLOBAL_DATA_PTR;
+/*
+ * Default board reset function
+ */
+static void
+__board_reset(void)
+{
+ /* Do nothing */
+}
+void board_reset(void) __attribute__((weak, alias("__board_reset")));
+
int checkcpu (void)
{
sys_info_t sysinfo;
@@ -215,7 +225,12 @@ int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
mtspr(DBCR0,val);
#else
volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
- out_be32(&gur->rstcr, 0x2); /* HRESET_REQ */
+
+ /* Attempt board-specific reset */
+ board_reset();
+
+ /* Next try asserting HRESET_REQ */
+ out_be32(&gur->rstcr, 0x2);
udelay(100);
#endif
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c b/arch/powerpc/cpu/mpc85xx/cpu_init.c
index b9a8193759..2e4a06c35a 100644
--- a/arch/powerpc/cpu/mpc85xx/cpu_init.c
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c
@@ -37,12 +37,15 @@
#include <asm/mmu.h>
#include <asm/fsl_law.h>
#include <asm/fsl_serdes.h>
+#include <linux/compiler.h>
#include "mp.h"
-#ifdef CONFIG_SYS_QE_FW_IN_NAND
+#ifdef CONFIG_SYS_QE_FMAN_FW_IN_NAND
#include <nand.h>
#include <errno.h>
#endif
+#include "../../../../drivers/block/fsl_sata.h"
+
DECLARE_GLOBAL_DATA_PTR;
extern void srio_init(void);
@@ -301,6 +304,7 @@ __attribute__((weak, alias("__fsl_serdes__init"))) void fsl_serdes_init(void);
*/
int cpu_init_r(void)
{
+ __maybe_unused u32 svr = get_svr();
#ifdef CONFIG_SYS_LBC_LCRR
volatile fsl_lbc_t *lbc = LBC_BASE_ADDR;
#endif
@@ -316,10 +320,9 @@ int cpu_init_r(void)
#if defined(CONFIG_L2_CACHE)
volatile ccsr_l2cache_t *l2cache = (void *)CONFIG_SYS_MPC85xx_L2_ADDR;
volatile uint cache_ctl;
- uint svr, ver;
+ uint ver;
u32 l2siz_field;
- svr = get_svr();
ver = SVR_SOC_VER(svr);
asm("msync;isync");
@@ -401,8 +404,8 @@ int cpu_init_r(void)
puts("enabled\n");
}
#elif defined(CONFIG_BACKSIDE_L2_CACHE)
- if ((SVR_SOC_VER(get_svr()) == SVR_P2040) ||
- (SVR_SOC_VER(get_svr()) == SVR_P2040_E)) {
+ if ((SVR_SOC_VER(svr) == SVR_P2040) ||
+ (SVR_SOC_VER(svr) == SVR_P2040_E)) {
puts("N/A\n");
goto skip_l2;
}
@@ -488,6 +491,32 @@ skip_l2:
fman_enet_init();
#endif
+#if defined(CONFIG_FSL_SATA_V2) && defined(CONFIG_FSL_SATA_ERRATUM_A001)
+ /*
+ * For P1022/1013 Rev1.0 silicon, after power on SATA host
+ * controller is configured in legacy mode instead of the
+ * expected enterprise mode. Software needs to clear bit[28]
+ * of HControl register to change to enterprise mode from
+ * legacy mode. We assume that the controller is offline.
+ */
+ if (IS_SVR_REV(svr, 1, 0) &&
+ ((SVR_SOC_VER(svr) == SVR_P1022) ||
+ (SVR_SOC_VER(svr) == SVR_P1022_E) ||
+ (SVR_SOC_VER(svr) == SVR_P1013) ||
+ (SVR_SOC_VER(svr) == SVR_P1013_E))) {
+ fsl_sata_reg_t *reg;
+
+ /* first SATA controller */
+ reg = (void *)CONFIG_SYS_MPC85xx_SATA1_ADDR;
+ clrbits_le32(&reg->hcontrol, HCONTROL_ENTERPRISE_EN);
+
+ /* second SATA controller */
+ reg = (void *)CONFIG_SYS_MPC85xx_SATA2_ADDR;
+ clrbits_le32(&reg->hcontrol, HCONTROL_ENTERPRISE_EN);
+ }
+#endif
+
+
return 0;
}
@@ -523,17 +552,17 @@ void cpu_secondary_init_r(void)
{
#ifdef CONFIG_QE
uint qe_base = CONFIG_SYS_IMMR + 0x00080000; /* QE immr base */
-#ifdef CONFIG_SYS_QE_FW_IN_NAND
+#ifdef CONFIG_SYS_QE_FMAN_FW_IN_NAND
int ret;
- size_t fw_length = CONFIG_SYS_QE_FW_LENGTH;
+ size_t fw_length = CONFIG_SYS_QE_FMAN_FW_LENGTH;
/* load QE firmware from NAND flash to DDR first */
- ret = nand_read(&nand_info[0], (loff_t)CONFIG_SYS_QE_FW_IN_NAND,
- &fw_length, (u_char *)CONFIG_SYS_QE_FW_ADDR);
+ ret = nand_read(&nand_info[0], (loff_t)CONFIG_SYS_QE_FMAN_FW_IN_NAND,
+ &fw_length, (u_char *)CONFIG_SYS_QE_FMAN_FW_ADDR);
if (ret && ret == -EUCLEAN) {
printf ("NAND read for QE firmware at offset %x failed %d\n",
- CONFIG_SYS_QE_FW_IN_NAND, ret);
+ CONFIG_SYS_QE_FMAN_FW_IN_NAND, ret);
}
#endif
qe_init(qe_base);
diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
index c8c84a1f7e..18e9cc5b8b 100644
--- a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
@@ -115,6 +115,11 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
for (i = 0; i < 32; i++)
out_be32(&ddr->debug[i], regs->debug[i]);
+#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003474
+ out_be32(&ddr->debug[12], 0x00000015);
+ out_be32(&ddr->debug[21], 0x24000000);
+#endif /* CONFIG_SYS_FSL_ERRATUM_DDR_A003474 */
+
/* Set, but do not enable the memory */
temp_sdram_cfg = regs->ddr_sdram_cfg;
temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN);
diff --git a/arch/powerpc/cpu/mpc85xx/fdt.c b/arch/powerpc/cpu/mpc85xx/fdt.c
index 9d31568412..977770e99d 100644
--- a/arch/powerpc/cpu/mpc85xx/fdt.c
+++ b/arch/powerpc/cpu/mpc85xx/fdt.c
@@ -466,7 +466,7 @@ void fdt_fixup_fman_firmware(void *blob)
return;
}
- if (length > CONFIG_SYS_FMAN_FW_LENGTH) {
+ if (length > CONFIG_SYS_QE_FMAN_FW_LENGTH) {
printf("Fman firmware at %p is too large (size=%u)\n",
fmanfw, length);
return;
@@ -660,8 +660,19 @@ void ft_cpu_setup(void *blob, bd_t *bd)
do_fixup_by_compat_u32(blob, "fsl,gianfar-ptp-timer",
"timer-frequency", gd->bus_clk/2, 1);
+ /*
+ * clock-freq should change to clock-frequency and
+ * flexcan-v1.0 should change to p1010-flexcan respectively
+ * in the future.
+ */
do_fixup_by_compat_u32(blob, "fsl,flexcan-v1.0",
- "clock_freq", gd->bus_clk, 1);
+ "clock_freq", gd->bus_clk/2, 1);
+
+ do_fixup_by_compat_u32(blob, "fsl,flexcan-v1.0",
+ "clock-frequency", gd->bus_clk/2, 1);
+
+ do_fixup_by_compat_u32(blob, "fsl,p1010-flexcan",
+ "clock-frequency", gd->bus_clk/2, 1);
fdt_fixup_usb(blob);
}
@@ -677,6 +688,12 @@ void ft_cpu_setup(void *blob, bd_t *bd)
#define CCSR_VIRT_TO_PHYS(x) \
(CONFIG_SYS_CCSRBAR_PHYS + ((x) - CONFIG_SYS_CCSRBAR))
+static void msg(const char *name, uint64_t uaddr, uint64_t daddr)
+{
+ printf("Warning: U-Boot configured %s at address %llx,\n"
+ "but the device tree has it at %llx\n", name, uaddr, daddr);
+}
+
/*
* Verify the device tree
*
@@ -692,33 +709,32 @@ void ft_cpu_setup(void *blob, bd_t *bd)
*/
int ft_verify_fdt(void *fdt)
{
- uint64_t ccsr = 0;
+ uint64_t addr = 0;
int aliases;
int off;
/* First check the CCSR base address */
off = fdt_node_offset_by_prop_value(fdt, -1, "device_type", "soc", 4);
if (off > 0)
- ccsr = fdt_get_base_address(fdt, off);
+ addr = fdt_get_base_address(fdt, off);
- if (!ccsr) {
+ if (!addr) {
printf("Warning: could not determine base CCSR address in "
"device tree\n");
/* No point in checking anything else */
return 0;
}
- if (ccsr != CONFIG_SYS_CCSRBAR_PHYS) {
- printf("Warning: U-Boot configured CCSR at address %llx,\n"
- "but the device tree has it at %llx\n",
- (uint64_t) CONFIG_SYS_CCSRBAR_PHYS, ccsr);
+ if (addr != CONFIG_SYS_CCSRBAR_PHYS) {
+ msg("CCSR", CONFIG_SYS_CCSRBAR_PHYS, addr);
/* No point in checking anything else */
return 0;
}
/*
- * Get the 'aliases' node. If there isn't one, then there's nothing
- * left to do.
+ * Check some nodes via aliases. We assume that U-Boot and the device
+ * tree enumerate the devices equally. E.g. the first serial port in
+ * U-Boot is the same as "serial0" in the device tree.
*/
aliases = fdt_path_offset(fdt, "/aliases");
if (aliases > 0) {
@@ -735,5 +751,30 @@ int ft_verify_fdt(void *fdt)
#endif
}
+ /*
+ * The localbus node is typically a root node, even though the lbc
+ * controller is part of CCSR. If we were to put the lbc node under
+ * the SOC node, then the 'ranges' property in the lbc node would
+ * translate through the 'ranges' property of the parent SOC node, and
+ * we don't want that. Since it's a separate node, it's possible for
+ * the 'reg' property to be wrong, so check it here. For now, we
+ * only check for "fsl,elbc" nodes.
+ */
+#ifdef CONFIG_SYS_LBC_ADDR
+ off = fdt_node_offset_by_compatible(fdt, -1, "fsl,elbc");
+ if (off > 0) {
+ const u32 *reg = fdt_getprop(fdt, off, "reg", NULL);
+ if (reg) {
+ uint64_t uaddr = CCSR_VIRT_TO_PHYS(CONFIG_SYS_LBC_ADDR);
+
+ addr = fdt_translate_address(fdt, off, reg);
+ if (uaddr != addr) {
+ msg("the localbus", uaddr, addr);
+ return 0;
+ }
+ }
+ }
+#endif
+
return 1;
}
diff --git a/arch/powerpc/cpu/mpc85xx/release.S b/arch/powerpc/cpu/mpc85xx/release.S
index 6678ed4118..c81e19c0e9 100644
--- a/arch/powerpc/cpu/mpc85xx/release.S
+++ b/arch/powerpc/cpu/mpc85xx/release.S
@@ -68,6 +68,12 @@ __secondary_start_page:
mtspr SPRN_HID1,r3
#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_CPU_A003999
+ mfspr r3,977
+ oris r3,r3,0x0100
+ mtspr 977,r3
+#endif
+
/* Enable branch prediction */
lis r3,BUCSR_ENABLE@h
ori r3,r3,BUCSR_ENABLE@l
diff --git a/arch/powerpc/cpu/mpc85xx/start.S b/arch/powerpc/cpu/mpc85xx/start.S
index 7bd5cc0b0f..4d37d6e863 100644
--- a/arch/powerpc/cpu/mpc85xx/start.S
+++ b/arch/powerpc/cpu/mpc85xx/start.S
@@ -253,6 +253,12 @@ l2_disabled:
mtspr HID1,r0
#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_CPU_A003999
+ mfspr r3,977
+ oris r3,r3,0x0100
+ mtspr 977,r3
+#endif
+
/* Enable Branch Prediction */
#if defined(CONFIG_BTB)
lis r0,BUCSR_ENABLE@h