From 89f4289958c12e6b64a6073f820255c1f719c5cc Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Mon, 23 Jul 2012 10:58:02 +0000 Subject: mpc85xx: Initial SP alignment is wrong. PowerPC mandates SP to be 16 bytes aligned. Furthermore, a stack frame is added, pointing to the reset vector which may in the way when gdb is walking the stack because the reset vector may not accessible depending on emulator settings. Also use a temp register so gdb doesn't pick up intermediate values. Signed-off-by: Joakim Tjernlund Acked-by: Kumar Gala Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc85xx/start.S | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc85xx/start.S b/arch/powerpc/cpu/mpc85xx/start.S index 6aabc30c28..b1998b2152 100644 --- a/arch/powerpc/cpu/mpc85xx/start.S +++ b/arch/powerpc/cpu/mpc85xx/start.S @@ -855,18 +855,12 @@ version_string: .globl _start_cont _start_cont: /* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache*/ - lis r1,CONFIG_SYS_INIT_RAM_ADDR@h - ori r1,r1,CONFIG_SYS_INIT_SP_OFFSET@l - + lis r3,(CONFIG_SYS_INIT_RAM_ADDR)@h + ori r3,r3,((CONFIG_SYS_INIT_SP_OFFSET-16)&~0xf)@l /* Align to 16 */ li r0,0 - stwu r0,-4(r1) - stwu r0,-4(r1) /* Terminate call chain */ - - stwu r1,-8(r1) /* Save back chain and move SP */ - lis r0,RESET_VECTOR@h /* Address of reset vector */ - ori r0,r0,RESET_VECTOR@l - stwu r1,-8(r1) /* Save back chain and move SP */ - stw r0,+12(r1) /* Save return addr (underflow vect) */ + stw r0,0(r3) /* Terminate Back Chain */ + stw r0,+4(r3) /* NULL return address. */ + mr r1,r3 /* Transfer to SP(r1) */ GET_GOT bl cpu_init_early_f -- cgit v1.2.1 From 57125f222e410c35ac745a912d5f4b52b654932a Mon Sep 17 00:00:00 2001 From: York Sun Date: Wed, 8 Aug 2012 18:04:53 +0000 Subject: powerpc/mpc85xx: Make NMG_CPU_A011 workaround conditional This erratum applies to the following SoCs: P4080 rev 1.0, 2.0, fixed in rev 3.0 P2041 rev 1.0, 1.1, fixed in rev 2.0 P3041 rev 1.0, 1.1, fixed in rev 2.0. Workaround for erratum NMG_CPU_A011 is enabled by default. This workaround may degrade performance. P4080 erratum CPU22 shares the same workaround. So it is always enabled for P4080. For other SoCs, it can be disabled by hwconfig with syntax: fsl_cpu_a011:disable Signed-off-by: York Sun Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc85xx/cmd_errata.c | 6 +++++- arch/powerpc/cpu/mpc85xx/cpu_init.c | 37 +++++++++++++++++++++++++++++++++-- arch/powerpc/cpu/mpc85xx/release.S | 15 ++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c b/arch/powerpc/cpu/mpc85xx/cmd_errata.c index 4e1a54ad0c..858b3f8260 100644 --- a/arch/powerpc/cpu/mpc85xx/cmd_errata.c +++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c @@ -27,6 +27,9 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { +#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011 + extern int enable_cpu_a011_workaround; +#endif __maybe_unused u32 svr = get_svr(); #if defined(CONFIG_FSL_SATA_V2) && defined(CONFIG_FSL_SATA_ERRATUM_A001) @@ -56,8 +59,9 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* * NMG_CPU_A011 applies to P4080 rev 1.0, 2.0, fixed in 3.0 * also applies to P3041 rev 1.0, 1.1, P2041 rev 1.0, 1.1 + * The SVR has been checked by cpu_init_r(). */ - if (SVR_SOC_VER(svr) != SVR_P4080 || SVR_MAJ(svr) < 3) + if (enable_cpu_a011_workaround) puts("Work-around for Erratum CPU-A011 enabled\n"); #endif #if defined(CONFIG_SYS_FSL_ERRATUM_CPU_A003999) diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c b/arch/powerpc/cpu/mpc85xx/cpu_init.c index fc6c2877d2..74863b4a1a 100644 --- a/arch/powerpc/cpu/mpc85xx/cpu_init.c +++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include "mp.h" #ifdef CONFIG_SYS_QE_FMAN_FW_IN_NAND @@ -47,6 +48,8 @@ #include "../../../../drivers/block/fsl_sata.h" +#define HWCONFIG_BUFFER_SIZE 128 + DECLARE_GLOBAL_DATA_PTR; #ifdef CONFIG_QE @@ -311,11 +314,41 @@ int cpu_init_r(void) #if defined(CONFIG_SYS_P4080_ERRATUM_CPU22) || \ defined(CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011) /* + * CPU22 and NMG_CPU_A011 share the same workaround. * CPU22 applies to P4080 rev 1.0, 2.0, fixed in 3.0 * NMG_CPU_A011 applies to P4080 rev 1.0, 2.0, fixed in 3.0 - * also applies to P3041 rev 1.0, 1.1, P2041 rev 1.0, 1.1 + * also applies to P3041 rev 1.0, 1.1, P2041 rev 1.0, 1.1, both + * fixed in 2.0. NMG_CPU_A011 is activated by default and can + * be disabled by hwconfig with syntax: + * + * fsl_cpu_a011:disable */ - if (SVR_SOC_VER(svr) != SVR_P4080 || SVR_MAJ(svr) < 3) { + extern int enable_cpu_a011_workaround; +#ifdef CONFIG_SYS_P4080_ERRATUM_CPU22 + enable_cpu_a011_workaround = (SVR_MAJ(svr) < 3); +#else + char buffer[HWCONFIG_BUFFER_SIZE]; + char *buf = NULL; + int n, res; + + n = getenv_f("hwconfig", buffer, sizeof(buffer)); + if (n > 0) + buf = buffer; + + res = hwconfig_arg_cmp_f("fsl_cpu_a011", "disable", buf); + if (res > 0) + enable_cpu_a011_workaround = 0; + else { + if (n >= HWCONFIG_BUFFER_SIZE) { + printf("fsl_cpu_a011 was not found. hwconfig variable " + "may be too long\n"); + } + enable_cpu_a011_workaround = + (SVR_SOC_VER(svr) == SVR_P4080 && SVR_MAJ(svr) < 3) || + (SVR_SOC_VER(svr) != SVR_P4080 && SVR_MAJ(svr) < 2); + } +#endif + if (enable_cpu_a011_workaround) { flush_dcache(); mtspr(L1CSR2, (mfspr(L1CSR2) | L1CSR2_DCWS)); sync(); diff --git a/arch/powerpc/cpu/mpc85xx/release.S b/arch/powerpc/cpu/mpc85xx/release.S index 1860684c11..1555a9ba67 100644 --- a/arch/powerpc/cpu/mpc85xx/release.S +++ b/arch/powerpc/cpu/mpc85xx/release.S @@ -163,6 +163,12 @@ __secondary_start_page: cmpw r3,r5 bge 2f 1: +#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011 + lis r3,toreset(enable_cpu_a011_workaround)@ha + lwz r3,toreset(enable_cpu_a011_workaround)@l(r3) + cmpwi r3,0 + beq 2f +#endif mfspr r3,L1CSR2 oris r3,r3,(L1CSR2_DCWS)@h mtspr L1CSR2,r3 @@ -346,6 +352,15 @@ __bootpg_addr: __spin_table: .space CONFIG_MAX_CPUS*ENTRY_SIZE + /* + * This variable is set by cpu_init_r() after parsing hwconfig + * to enable workaround for erratum NMG_CPU_A011. + */ + .align L1_CACHE_SHIFT + .global enable_cpu_a011_workaround +enable_cpu_a011_workaround: + .long 1 + /* Fill in the empty space. The actual reset vector is * the last word of the page */ __secondary_start_code_end: -- cgit v1.2.1 From ff65f12699b4181b777cbc03b057510bc4605f5e Mon Sep 17 00:00:00 2001 From: Liu Gang Date: Thu, 9 Aug 2012 05:09:59 +0000 Subject: powerpc/corenet_ds: Get rid of the SRIOBOOT_MASTER build target Get rid of the SRIOBOOT_MASTER build target, and to support for serving as a SRIO boot master via environment variable. Set the environment variable "bootmaster" to "SRIO1" or "SRIO2" using the following command: setenv bootmaster SRIO1 saveenv The "bootmaster" will enable the function of the SRIO boot master, and this has the following advantages compared with SRIOBOOT_MASTER build configuration: 1. Reduce a build configuration item in boards.cfg file. No longer need to build a special image for master, just use a normal target image and set the "bootmaster" variable. 2. No longer need to rebuild an image when change the SRIO port for boot from SRIO, just set the corresponding value to "bootmaster" based on the using SRIO port. Signed-off-by: Liu Gang Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc85xx/cpu_init.c | 17 +++-- arch/powerpc/cpu/mpc8xxx/srio.c | 137 +++++++++++++----------------------- 2 files changed, 60 insertions(+), 94 deletions(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c b/arch/powerpc/cpu/mpc85xx/cpu_init.c index 74863b4a1a..f293265c86 100644 --- a/arch/powerpc/cpu/mpc85xx/cpu_init.c +++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c @@ -480,11 +480,18 @@ skip_l2: #ifdef CONFIG_SYS_SRIO srio_init(); -#ifdef CONFIG_SRIOBOOT_MASTER - srio_boot_master(); -#ifdef CONFIG_SRIOBOOT_SLAVE_HOLDOFF - srio_boot_master_release_slave(); -#endif +#ifdef CONFIG_FSL_CORENET + char *s = getenv("bootmaster"); + if (s) { + if (!strcmp(s, "SRIO1")) { + srio_boot_master(1); + srio_boot_master_release_slave(1); + } + if (!strcmp(s, "SRIO2")) { + srio_boot_master(2); + srio_boot_master_release_slave(2); + } + } #endif #endif diff --git a/arch/powerpc/cpu/mpc8xxx/srio.c b/arch/powerpc/cpu/mpc8xxx/srio.c index c7f394972b..ae83d6e172 100644 --- a/arch/powerpc/cpu/mpc8xxx/srio.c +++ b/arch/powerpc/cpu/mpc8xxx/srio.c @@ -95,126 +95,92 @@ void srio_init(void) } } -#ifdef CONFIG_SRIOBOOT_MASTER -void srio_boot_master(void) +#ifdef CONFIG_FSL_CORENET +void srio_boot_master(int port) { struct ccsr_rio *srio = (void *)CONFIG_SYS_FSL_SRIO_ADDR; /* set port accept-all */ - out_be32((void *)&srio->impl.port[CONFIG_SRIOBOOT_MASTER_PORT].ptaacr, + out_be32((void *)&srio->impl.port[port - 1].ptaacr, SRIO_PORT_ACCEPT_ALL); - debug("SRIOBOOT - MASTER: Master port [ %d ] for srio boot.\n", - CONFIG_SRIOBOOT_MASTER_PORT); + debug("SRIOBOOT - MASTER: Master port [ %d ] for srio boot.\n", port); /* configure inbound window for slave's u-boot image */ debug("SRIOBOOT - MASTER: Inbound window for slave's image; " "Local = 0x%llx, Srio = 0x%llx, Size = 0x%x\n", - (u64)CONFIG_SRIOBOOT_SLAVE_IMAGE_LAW_PHYS1, - (u64)CONFIG_SRIOBOOT_SLAVE_IMAGE_SRIO_PHYS1, + (u64)CONFIG_SRIOBOOT_SLAVE_IMAGE_MEM_PHYS, + (u64)CONFIG_SRIOBOOT_SLAVE_IMAGE_MEM_BUS1, CONFIG_SRIOBOOT_SLAVE_IMAGE_SIZE); - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT].inbw[0].riwtar, - CONFIG_SRIOBOOT_SLAVE_IMAGE_LAW_PHYS1 >> 12); - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT].inbw[0].riwbar, - CONFIG_SRIOBOOT_SLAVE_IMAGE_SRIO_PHYS1 >> 12); - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT].inbw[0].riwar, + out_be32((void *)&srio->atmu.port[port - 1].inbw[0].riwtar, + CONFIG_SRIOBOOT_SLAVE_IMAGE_MEM_PHYS >> 12); + out_be32((void *)&srio->atmu.port[port - 1].inbw[0].riwbar, + CONFIG_SRIOBOOT_SLAVE_IMAGE_MEM_BUS1 >> 12); + out_be32((void *)&srio->atmu.port[port - 1].inbw[0].riwar, SRIO_IB_ATMU_AR | atmu_size_mask(CONFIG_SRIOBOOT_SLAVE_IMAGE_SIZE)); /* configure inbound window for slave's u-boot image */ debug("SRIOBOOT - MASTER: Inbound window for slave's image; " "Local = 0x%llx, Srio = 0x%llx, Size = 0x%x\n", - (u64)CONFIG_SRIOBOOT_SLAVE_IMAGE_LAW_PHYS2, - (u64)CONFIG_SRIOBOOT_SLAVE_IMAGE_SRIO_PHYS2, + (u64)CONFIG_SRIOBOOT_SLAVE_IMAGE_MEM_PHYS, + (u64)CONFIG_SRIOBOOT_SLAVE_IMAGE_MEM_BUS2, CONFIG_SRIOBOOT_SLAVE_IMAGE_SIZE); - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT].inbw[1].riwtar, - CONFIG_SRIOBOOT_SLAVE_IMAGE_LAW_PHYS2 >> 12); - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT].inbw[1].riwbar, - CONFIG_SRIOBOOT_SLAVE_IMAGE_SRIO_PHYS2 >> 12); - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT].inbw[1].riwar, + out_be32((void *)&srio->atmu.port[port - 1].inbw[1].riwtar, + CONFIG_SRIOBOOT_SLAVE_IMAGE_MEM_PHYS >> 12); + out_be32((void *)&srio->atmu.port[port - 1].inbw[1].riwbar, + CONFIG_SRIOBOOT_SLAVE_IMAGE_MEM_BUS2 >> 12); + out_be32((void *)&srio->atmu.port[port - 1].inbw[1].riwar, SRIO_IB_ATMU_AR | atmu_size_mask(CONFIG_SRIOBOOT_SLAVE_IMAGE_SIZE)); - /* configure inbound window for slave's ucode */ - debug("SRIOBOOT - MASTER: Inbound window for slave's ucode; " + /* configure inbound window for slave's ucode and ENV */ + debug("SRIOBOOT - MASTER: Inbound window for slave's ucode and ENV; " "Local = 0x%llx, Srio = 0x%llx, Size = 0x%x\n", - (u64)CONFIG_SRIOBOOT_SLAVE_UCODE_LAW_PHYS, - (u64)CONFIG_SRIOBOOT_SLAVE_UCODE_SRIO_PHYS, - CONFIG_SRIOBOOT_SLAVE_UCODE_SIZE); - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT].inbw[2].riwtar, - CONFIG_SRIOBOOT_SLAVE_UCODE_LAW_PHYS >> 12); - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT].inbw[2].riwbar, - CONFIG_SRIOBOOT_SLAVE_UCODE_SRIO_PHYS >> 12); - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT].inbw[2].riwar, - SRIO_IB_ATMU_AR - | atmu_size_mask(CONFIG_SRIOBOOT_SLAVE_UCODE_SIZE)); - - /* configure inbound window for slave's ENV */ - debug("SRIOBOOT - MASTER: Inbound window for slave's ENV; " - "Local = 0x%llx, Siro = 0x%llx, Size = 0x%x\n", - CONFIG_SRIOBOOT_SLAVE_ENV_LAW_PHYS, - CONFIG_SRIOBOOT_SLAVE_ENV_SRIO_PHYS, - CONFIG_SRIOBOOT_SLAVE_ENV_SIZE); - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT].inbw[3].riwtar, - CONFIG_SRIOBOOT_SLAVE_ENV_LAW_PHYS >> 12); - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT].inbw[3].riwbar, - CONFIG_SRIOBOOT_SLAVE_ENV_SRIO_PHYS >> 12); - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT].inbw[3].riwar, + (u64)CONFIG_SRIOBOOT_SLAVE_UCODE_ENV_MEM_PHYS, + (u64)CONFIG_SRIOBOOT_SLAVE_UCODE_ENV_MEM_BUS, + CONFIG_SRIOBOOT_SLAVE_UCODE_ENV_SIZE); + out_be32((void *)&srio->atmu.port[port - 1].inbw[2].riwtar, + CONFIG_SRIOBOOT_SLAVE_UCODE_ENV_MEM_PHYS >> 12); + out_be32((void *)&srio->atmu.port[port - 1].inbw[2].riwbar, + CONFIG_SRIOBOOT_SLAVE_UCODE_ENV_MEM_BUS >> 12); + out_be32((void *)&srio->atmu.port[port - 1].inbw[2].riwar, SRIO_IB_ATMU_AR - | atmu_size_mask(CONFIG_SRIOBOOT_SLAVE_ENV_SIZE)); + | atmu_size_mask(CONFIG_SRIOBOOT_SLAVE_UCODE_ENV_SIZE)); } -#ifdef CONFIG_SRIOBOOT_SLAVE_HOLDOFF -void srio_boot_master_release_slave(void) +void srio_boot_master_release_slave(int port) { struct ccsr_rio *srio = (void *)CONFIG_SYS_FSL_SRIO_ADDR; u32 escsr; debug("SRIOBOOT - MASTER: " "Check the port status and release slave core ...\n"); - escsr = in_be32((void *)&srio->lp_serial - .port[CONFIG_SRIOBOOT_MASTER_PORT].pescsr); + escsr = in_be32((void *)&srio->lp_serial.port[port - 1].pescsr); if (escsr & 0x2) { if (escsr & 0x10100) { debug("SRIOBOOT - MASTER: Port [ %d ] is error.\n", - CONFIG_SRIOBOOT_MASTER_PORT); + port); } else { debug("SRIOBOOT - MASTER: " - "Port [ %d ] is ready, now release slave's core ...\n", - CONFIG_SRIOBOOT_MASTER_PORT); + "Port [ %d ] is ready, now release slave's core ...\n", + port); /* * configure outbound window * with maintenance attribute to set slave's LCSBA1CSR */ - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT] + out_be32((void *)&srio->atmu.port[port - 1] .outbw[1].rowtar, 0); - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT] + out_be32((void *)&srio->atmu.port[port - 1] .outbw[1].rowtear, 0); - if (CONFIG_SRIOBOOT_MASTER_PORT) - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT] + if (port - 1) + out_be32((void *)&srio->atmu.port[port - 1] .outbw[1].rowbar, CONFIG_SYS_SRIO2_MEM_PHYS >> 12); else - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT] + out_be32((void *)&srio->atmu.port[port - 1] .outbw[1].rowbar, CONFIG_SYS_SRIO1_MEM_PHYS >> 12); - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT] + out_be32((void *)&srio->atmu.port[port - 1] .outbw[1].rowar, SRIO_OB_ATMU_AR_MAINT | atmu_size_mask(SRIO_MAINT_WIN_SIZE)); @@ -223,27 +189,22 @@ void srio_boot_master_release_slave(void) * configure outbound window * with R/W attribute to set slave's BRR */ - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT] + out_be32((void *)&srio->atmu.port[port - 1] .outbw[2].rowtar, SRIO_LCSBA1CSR >> 9); - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT] + out_be32((void *)&srio->atmu.port[port - 1] .outbw[2].rowtear, 0); - if (CONFIG_SRIOBOOT_MASTER_PORT) - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT] + if (port - 1) + out_be32((void *)&srio->atmu.port[port - 1] .outbw[2].rowbar, (CONFIG_SYS_SRIO2_MEM_PHYS + SRIO_MAINT_WIN_SIZE) >> 12); else - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT] + out_be32((void *)&srio->atmu.port[port - 1] .outbw[2].rowbar, (CONFIG_SYS_SRIO1_MEM_PHYS + SRIO_MAINT_WIN_SIZE) >> 12); - out_be32((void *)&srio->atmu - .port[CONFIG_SRIOBOOT_MASTER_PORT] + out_be32((void *)&srio->atmu.port[port - 1] .outbw[2].rowar, SRIO_OB_ATMU_AR_RW | atmu_size_mask(SRIO_RW_WIN_SIZE)); @@ -252,7 +213,7 @@ void srio_boot_master_release_slave(void) * Set the LCSBA1CSR register in slave * by the maint-outbound window */ - if (CONFIG_SRIOBOOT_MASTER_PORT) { + if (port - 1) { out_be32((void *)CONFIG_SYS_SRIO2_MEM_VIRT + SRIO_LCSBA1CSR_OFFSET, SRIO_LCSBA1CSR); @@ -289,8 +250,6 @@ void srio_boot_master_release_slave(void) "Release slave successfully! Now the slave should start up!\n"); } } else - debug("SRIOBOOT - MASTER: Port [ %d ] is not ready.\n", - CONFIG_SRIOBOOT_MASTER_PORT); + debug("SRIOBOOT - MASTER: Port [ %d ] is not ready.\n", port); } #endif -#endif -- cgit v1.2.1 From b5f7c8732ad99b0c1a7fa456f706de1ab7d74eef Mon Sep 17 00:00:00 2001 From: Liu Gang Date: Thu, 9 Aug 2012 05:10:02 +0000 Subject: powerpc/corenet_ds: Master module for boot from PCIE For the powerpc processors with PCIE interface, boot location can be configured from one PCIE interface by RCW. The processor booting from PCIE can do without flash for u-boot image. The image can be fetched from another processor's memory space by PCIE link connected between them. The processor booting from PCIE is slave, the processor booting from normal flash memory space is master, and it can help slave to boot from master's memory space. When boot from PCIE, slave's core should be in holdoff after powered on for some specific requirements. Master will release the slave's core at the right time by PCIE interface. Environment and requirement: master: 1. NOR flash for its own u-boot image, ucode and ENV space. 2. Slave's u-boot image is in master NOR flash. 3. Normally boot from local NOR flash. 4. Configure PCIE system if needed. slave: 1. Just has EEPROM for RCW. No flash for u-boot image, ucode and ENV. 2. Boot location should be set to one PCIE interface by RCW. 3. RCW should configure the SerDes, PCIE interfaces correctly. 4. Must set all the cores in holdoff by RCW. 5. Must be powered on before master's boot. For the master module, need to finish these processes: 1. Initialize the PCIE port and address space. 2. Set inbound PCIE windows covered slave's u-boot image stored in master's NOR flash. 3. Set outbound windows in order to configure slave's registers for the core's releasing. 4. Should set the environment variable "bootmaster" to "PCIE1", "PCIE2" or "PCIE3" using the following command: setenv bootmaster PCIE1 saveenv Signed-off-by: Liu Gang Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc8xxx/srio.c | 44 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc8xxx/srio.c b/arch/powerpc/cpu/mpc8xxx/srio.c index ae83d6e172..0cb65b32e4 100644 --- a/arch/powerpc/cpu/mpc8xxx/srio.c +++ b/arch/powerpc/cpu/mpc8xxx/srio.c @@ -108,44 +108,44 @@ void srio_boot_master(int port) /* configure inbound window for slave's u-boot image */ debug("SRIOBOOT - MASTER: Inbound window for slave's image; " "Local = 0x%llx, Srio = 0x%llx, Size = 0x%x\n", - (u64)CONFIG_SRIOBOOT_SLAVE_IMAGE_MEM_PHYS, - (u64)CONFIG_SRIOBOOT_SLAVE_IMAGE_MEM_BUS1, - CONFIG_SRIOBOOT_SLAVE_IMAGE_SIZE); + (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS, + (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS1, + CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE); out_be32((void *)&srio->atmu.port[port - 1].inbw[0].riwtar, - CONFIG_SRIOBOOT_SLAVE_IMAGE_MEM_PHYS >> 12); + CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS >> 12); out_be32((void *)&srio->atmu.port[port - 1].inbw[0].riwbar, - CONFIG_SRIOBOOT_SLAVE_IMAGE_MEM_BUS1 >> 12); + CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS1 >> 12); out_be32((void *)&srio->atmu.port[port - 1].inbw[0].riwar, SRIO_IB_ATMU_AR - | atmu_size_mask(CONFIG_SRIOBOOT_SLAVE_IMAGE_SIZE)); + | atmu_size_mask(CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE)); /* configure inbound window for slave's u-boot image */ debug("SRIOBOOT - MASTER: Inbound window for slave's image; " "Local = 0x%llx, Srio = 0x%llx, Size = 0x%x\n", - (u64)CONFIG_SRIOBOOT_SLAVE_IMAGE_MEM_PHYS, - (u64)CONFIG_SRIOBOOT_SLAVE_IMAGE_MEM_BUS2, - CONFIG_SRIOBOOT_SLAVE_IMAGE_SIZE); + (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS, + (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS2, + CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE); out_be32((void *)&srio->atmu.port[port - 1].inbw[1].riwtar, - CONFIG_SRIOBOOT_SLAVE_IMAGE_MEM_PHYS >> 12); + CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS >> 12); out_be32((void *)&srio->atmu.port[port - 1].inbw[1].riwbar, - CONFIG_SRIOBOOT_SLAVE_IMAGE_MEM_BUS2 >> 12); + CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS2 >> 12); out_be32((void *)&srio->atmu.port[port - 1].inbw[1].riwar, SRIO_IB_ATMU_AR - | atmu_size_mask(CONFIG_SRIOBOOT_SLAVE_IMAGE_SIZE)); + | atmu_size_mask(CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE)); /* configure inbound window for slave's ucode and ENV */ debug("SRIOBOOT - MASTER: Inbound window for slave's ucode and ENV; " "Local = 0x%llx, Srio = 0x%llx, Size = 0x%x\n", - (u64)CONFIG_SRIOBOOT_SLAVE_UCODE_ENV_MEM_PHYS, - (u64)CONFIG_SRIOBOOT_SLAVE_UCODE_ENV_MEM_BUS, - CONFIG_SRIOBOOT_SLAVE_UCODE_ENV_SIZE); + (u64)CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_PHYS, + (u64)CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_BUS, + CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_SIZE); out_be32((void *)&srio->atmu.port[port - 1].inbw[2].riwtar, - CONFIG_SRIOBOOT_SLAVE_UCODE_ENV_MEM_PHYS >> 12); + CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_PHYS >> 12); out_be32((void *)&srio->atmu.port[port - 1].inbw[2].riwbar, - CONFIG_SRIOBOOT_SLAVE_UCODE_ENV_MEM_BUS >> 12); + CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_BUS >> 12); out_be32((void *)&srio->atmu.port[port - 1].inbw[2].riwar, SRIO_IB_ATMU_AR - | atmu_size_mask(CONFIG_SRIOBOOT_SLAVE_UCODE_ENV_SIZE)); + | atmu_size_mask(CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_SIZE)); } void srio_boot_master_release_slave(int port) @@ -227,8 +227,8 @@ void srio_boot_master_release_slave(int port) */ out_be32((void *)CONFIG_SYS_SRIO2_MEM_VIRT + SRIO_MAINT_WIN_SIZE - + CONFIG_SRIOBOOT_SLAVE_BRR_OFFSET, - CONFIG_SRIOBOOT_SLAVE_RELEASE_MASK); + + CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET, + CONFIG_SRIO_PCIE_BOOT_RELEASE_MASK); } else { out_be32((void *)CONFIG_SYS_SRIO1_MEM_VIRT + SRIO_LCSBA1CSR_OFFSET, @@ -243,8 +243,8 @@ void srio_boot_master_release_slave(int port) */ out_be32((void *)CONFIG_SYS_SRIO1_MEM_VIRT + SRIO_MAINT_WIN_SIZE - + CONFIG_SRIOBOOT_SLAVE_BRR_OFFSET, - CONFIG_SRIOBOOT_SLAVE_RELEASE_MASK); + + CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET, + CONFIG_SRIO_PCIE_BOOT_RELEASE_MASK); } debug("SRIOBOOT - MASTER: " "Release slave successfully! Now the slave should start up!\n"); -- cgit v1.2.1 From be7bebeac24f33bd7eef2f5047579c1a680d8df1 Mon Sep 17 00:00:00 2001 From: York Sun Date: Fri, 10 Aug 2012 11:07:26 +0000 Subject: powerpc/mpc8xxx: Remove P1015 and P1016 from CPU list P1015 is the same as P1011 and P1016 is the same as P1012 from software point of view. They have different packages but share SVRs. Signed-off-by: York Sun Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc85xx/Makefile | 4 ---- arch/powerpc/cpu/mpc85xx/speed.c | 3 +-- arch/powerpc/cpu/mpc8xxx/cpu.c | 2 -- 3 files changed, 1 insertion(+), 8 deletions(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc85xx/Makefile b/arch/powerpc/cpu/mpc85xx/Makefile index 34f6c54698..2f79a03119 100644 --- a/arch/powerpc/cpu/mpc85xx/Makefile +++ b/arch/powerpc/cpu/mpc85xx/Makefile @@ -55,8 +55,6 @@ COBJS-$(CONFIG_P1011) += ddr-gen3.o COBJS-$(CONFIG_P1012) += ddr-gen3.o COBJS-$(CONFIG_P1013) += ddr-gen3.o COBJS-$(CONFIG_P1014) += ddr-gen3.o -COBJS-$(CONFIG_P1015) += ddr-gen3.o -COBJS-$(CONFIG_P1016) += ddr-gen3.o COBJS-$(CONFIG_P1020) += ddr-gen3.o COBJS-$(CONFIG_P1021) += ddr-gen3.o COBJS-$(CONFIG_P1022) += ddr-gen3.o @@ -103,8 +101,6 @@ COBJS-$(CONFIG_P1011) += p1021_serdes.o COBJS-$(CONFIG_P1012) += p1021_serdes.o COBJS-$(CONFIG_P1013) += p1022_serdes.o COBJS-$(CONFIG_P1014) += p1010_serdes.o -COBJS-$(CONFIG_P1015) += p1021_serdes.o -COBJS-$(CONFIG_P1016) += p1021_serdes.o COBJS-$(CONFIG_P1017) += p1023_serdes.o COBJS-$(CONFIG_P1020) += p1021_serdes.o COBJS-$(CONFIG_P1021) += p1021_serdes.o diff --git a/arch/powerpc/cpu/mpc85xx/speed.c b/arch/powerpc/cpu/mpc85xx/speed.c index ce47532455..abfeb268d4 100644 --- a/arch/powerpc/cpu/mpc85xx/speed.c +++ b/arch/powerpc/cpu/mpc85xx/speed.c @@ -186,8 +186,7 @@ void get_sys_info (sys_info_t * sysInfo) #endif #ifdef CONFIG_QE -#if defined(CONFIG_P1012) || defined(CONFIG_P1016) || \ - defined(CONFIG_P1021) || defined(CONFIG_P1025) +#if defined(CONFIG_P1012) || defined(CONFIG_P1021) || defined(CONFIG_P1025) sysInfo->freqQE = sysInfo->freqSystemBus; #else qe_ratio = ((gur->porpllsr) & MPC85xx_PORPLLSR_QE_RATIO) diff --git a/arch/powerpc/cpu/mpc8xxx/cpu.c b/arch/powerpc/cpu/mpc8xxx/cpu.c index cbc674211a..1c615d0b55 100644 --- a/arch/powerpc/cpu/mpc8xxx/cpu.c +++ b/arch/powerpc/cpu/mpc8xxx/cpu.c @@ -57,8 +57,6 @@ struct cpu_type cpu_type_list [] = { CPU_TYPE_ENTRY(P1012, P1012, 1), CPU_TYPE_ENTRY(P1013, P1013, 1), CPU_TYPE_ENTRY(P1014, P1014, 1), - CPU_TYPE_ENTRY(P1015, P1015, 1), - CPU_TYPE_ENTRY(P1016, P1016, 1), CPU_TYPE_ENTRY(P1017, P1017, 1), CPU_TYPE_ENTRY(P1020, P1020, 2), CPU_TYPE_ENTRY(P1021, P1021, 2), -- cgit v1.2.1 From 99abf7ded3b8daf82bdf1a60d1a92cb76c482c9a Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Tue, 14 Aug 2012 06:47:21 +0000 Subject: powerpc/85xx: add support for FM2 DTSEC5 Unlike previous SOCs, the Freescale P5040 has a fifth DTSEC on the second Fman, so add the Fman and SerDes macros for that DTSEC. Signed-off-by: Timur Tabi Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c index 4b52dad56c..8aac1dec0f 100644 --- a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c +++ b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c @@ -68,6 +68,7 @@ static const char *serdes_prtcl_str[] = { [SGMII_FM2_DTSEC2] = "SGMII_FM2_DTSEC2", [SGMII_FM2_DTSEC3] = "SGMII_FM2_DTSEC3", [SGMII_FM2_DTSEC4] = "SGMII_FM2_DTSEC4", + [SGMII_FM2_DTSEC5] = "SGMII_FM2_DTSEC5", [XAUI_FM1] = "XAUI_FM1", [XAUI_FM2] = "XAUI_FM2", [AURORA] = "DEBUG", @@ -658,6 +659,7 @@ void fsl_serdes_init(void) case SGMII_FM2_DTSEC2: case SGMII_FM2_DTSEC3: case SGMII_FM2_DTSEC4: + case SGMII_FM2_DTSEC5: case XAUI_FM1: case XAUI_FM2: case SRIO1: @@ -717,6 +719,10 @@ void fsl_serdes_init(void) serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 | FSL_CORENET_DEVDISR2_DTSEC2_4; break; + case SGMII_FM2_DTSEC5: + serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 | + FSL_CORENET_DEVDISR2_DTSEC2_5; + break; case XAUI_FM1: serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM1 | FSL_CORENET_DEVDISR2_10GEC1; -- cgit v1.2.1 From 055ce08004136333fd237fa8f0a5ab3dd82c7a49 Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Tue, 14 Aug 2012 06:47:27 +0000 Subject: powerpc/85xx: remove support for the Freescale P3060 The P3060 was cancelled before it went into production, so there's no point in supporting it. Signed-off-by: Timur Tabi Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc85xx/Makefile | 3 - arch/powerpc/cpu/mpc85xx/fdt.c | 2 +- arch/powerpc/cpu/mpc85xx/p3060_ids.c | 117 ------------------------------- arch/powerpc/cpu/mpc85xx/p3060_serdes.c | 118 -------------------------------- arch/powerpc/cpu/mpc8xxx/cpu.c | 1 - 5 files changed, 1 insertion(+), 240 deletions(-) delete mode 100644 arch/powerpc/cpu/mpc85xx/p3060_ids.c delete mode 100644 arch/powerpc/cpu/mpc85xx/p3060_serdes.c (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc85xx/Makefile b/arch/powerpc/cpu/mpc85xx/Makefile index 2f79a03119..71b8bb7207 100644 --- a/arch/powerpc/cpu/mpc85xx/Makefile +++ b/arch/powerpc/cpu/mpc85xx/Makefile @@ -65,7 +65,6 @@ COBJS-$(CONFIG_P2020) += ddr-gen3.o COBJS-$(CONFIG_PPC_P2040) += ddr-gen3.o COBJS-$(CONFIG_PPC_P2041) += ddr-gen3.o COBJS-$(CONFIG_PPC_P3041) += ddr-gen3.o -COBJS-$(CONFIG_PPC_P3060) += ddr-gen3.o COBJS-$(CONFIG_PPC_P4080) += ddr-gen3.o COBJS-$(CONFIG_PPC_P5020) += ddr-gen3.o COBJS-$(CONFIG_BSC9131) += ddr-gen3.o @@ -81,7 +80,6 @@ COBJS-$(CONFIG_SYS_DPAA_QBMAN) += portals.o COBJS-$(CONFIG_PPC_P2040) += p2041_ids.o COBJS-$(CONFIG_PPC_P2041) += p2041_ids.o COBJS-$(CONFIG_PPC_P3041) += p3041_ids.o -COBJS-$(CONFIG_PPC_P3060) += p3060_ids.o COBJS-$(CONFIG_PPC_P4080) += p4080_ids.o COBJS-$(CONFIG_PPC_P5020) += p5020_ids.o @@ -113,7 +111,6 @@ COBJS-$(CONFIG_P2020) += p2020_serdes.o COBJS-$(CONFIG_PPC_P2040) += p2041_serdes.o COBJS-$(CONFIG_PPC_P2041) += p2041_serdes.o COBJS-$(CONFIG_PPC_P3041) += p3041_serdes.o -COBJS-$(CONFIG_PPC_P3060) += p3060_serdes.o COBJS-$(CONFIG_PPC_P4080) += p4080_serdes.o COBJS-$(CONFIG_PPC_P5020) += p5020_serdes.o diff --git a/arch/powerpc/cpu/mpc85xx/fdt.c b/arch/powerpc/cpu/mpc85xx/fdt.c index 21c3ad49bf..2ef2078461 100644 --- a/arch/powerpc/cpu/mpc85xx/fdt.c +++ b/arch/powerpc/cpu/mpc85xx/fdt.c @@ -534,7 +534,7 @@ void fdt_fixup_fman_firmware(void *blob) #define fdt_fixup_fman_firmware(x) #endif -#if defined(CONFIG_PPC_P4080) || defined(CONFIG_PPC_P3060) +#if defined(CONFIG_PPC_P4080) static void fdt_fixup_usb(void *fdt) { ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); diff --git a/arch/powerpc/cpu/mpc85xx/p3060_ids.c b/arch/powerpc/cpu/mpc85xx/p3060_ids.c deleted file mode 100644 index d32142f636..0000000000 --- a/arch/powerpc/cpu/mpc85xx/p3060_ids.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2011 Freescale Semiconductor, Inc. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include - -#ifdef CONFIG_SYS_DPAA_QBMAN -struct qportal_info qp_info[CONFIG_SYS_QMAN_NUM_PORTALS] = { - /* dqrr liodn, frame data liodn, liodn off, sdest */ - SET_QP_INFO( 1, 2, 1, 0), - SET_QP_INFO( 3, 4, 2, 1), - SET_QP_INFO( 5, 6, 3, 2), - SET_QP_INFO( 7, 8, 4, 3), - SET_QP_INFO( 9, 10, 5, 4), - SET_QP_INFO(11, 12, 6, 5), - SET_QP_INFO(13, 14, 7, 6), - SET_QP_INFO(15, 16, 8, 7), - SET_QP_INFO(17, 18, 9, 0), /* for now sdest to 0 */ - SET_QP_INFO(19, 20, 10, 0), /* for now sdest to 0 */ -}; -#endif - -struct srio_liodn_id_table srio_liodn_tbl[] = { - SET_SRIO_LIODN_1(1, 198), - SET_SRIO_LIODN_1(2, 199), -}; -int srio_liodn_tbl_sz = ARRAY_SIZE(srio_liodn_tbl); - -struct liodn_id_table liodn_tbl[] = { - SET_USB_LIODN(1, "fsl-usb2-mph", 127), - SET_USB_LIODN(2, "fsl-usb2-dr", 157), - - SET_PCI_LIODN("fsl,qoriq-pcie-v2.2", 1, 193), - SET_PCI_LIODN("fsl,qoriq-pcie-v2.2", 2, 194), - - SET_DMA_LIODN(1, 196), - SET_DMA_LIODN(2, 197), - - SET_GUTS_LIODN("fsl,srio-rmu", 200, rmuliodnr, 0xd3000), - -#ifdef CONFIG_SYS_DPAA_QBMAN - SET_QMAN_LIODN(31), - SET_BMAN_LIODN(32), -#endif - SET_PME_LIODN(128), -}; -int liodn_tbl_sz = ARRAY_SIZE(liodn_tbl); - -#ifdef CONFIG_SYS_DPAA_FMAN -struct liodn_id_table fman1_liodn_tbl[] = { - SET_FMAN_RX_1G_LIODN(1, 0, 11), - SET_FMAN_RX_1G_LIODN(1, 1, 12), - SET_FMAN_RX_1G_LIODN(1, 2, 13), - SET_FMAN_RX_1G_LIODN(1, 3, 14), -}; -int fman1_liodn_tbl_sz = ARRAY_SIZE(fman1_liodn_tbl); - -#if (CONFIG_SYS_NUM_FMAN == 2) -struct liodn_id_table fman2_liodn_tbl[] = { - SET_FMAN_RX_1G_LIODN(2, 0, 16), - SET_FMAN_RX_1G_LIODN(2, 1, 17), - SET_FMAN_RX_1G_LIODN(2, 2, 18), - SET_FMAN_RX_1G_LIODN(2, 3, 19), -}; -int fman2_liodn_tbl_sz = ARRAY_SIZE(fman2_liodn_tbl); -#endif -#endif - -struct liodn_id_table sec_liodn_tbl[] = { - SET_SEC_JR_LIODN_ENTRY(0, 146, 154), - SET_SEC_JR_LIODN_ENTRY(1, 147, 155), - SET_SEC_JR_LIODN_ENTRY(2, 178, 186), - SET_SEC_JR_LIODN_ENTRY(3, 179, 187), - SET_SEC_RTIC_LIODN_ENTRY(a, 144), - SET_SEC_RTIC_LIODN_ENTRY(b, 145), - SET_SEC_RTIC_LIODN_ENTRY(c, 176), - SET_SEC_RTIC_LIODN_ENTRY(d, 177), - SET_SEC_DECO_LIODN_ENTRY(0, 129, 161), - SET_SEC_DECO_LIODN_ENTRY(1, 130, 162), - SET_SEC_DECO_LIODN_ENTRY(2, 131, 163), - SET_SEC_DECO_LIODN_ENTRY(3, 132, 164), - SET_SEC_DECO_LIODN_ENTRY(4, 133, 165), -}; -int sec_liodn_tbl_sz = ARRAY_SIZE(sec_liodn_tbl); - -struct liodn_id_table liodn_bases[] = { - [FSL_HW_PORTAL_SEC] = SET_LIODN_BASE_2(96, 106), -#ifdef CONFIG_SYS_DPAA_FMAN - [FSL_HW_PORTAL_FMAN1] = SET_LIODN_BASE_1(32), -#if (CONFIG_SYS_NUM_FMAN == 2) - [FSL_HW_PORTAL_FMAN2] = SET_LIODN_BASE_1(64), -#endif -#endif -#ifdef CONFIG_SYS_DPAA_PME - [FSL_HW_PORTAL_PME] = SET_LIODN_BASE_2(116, 133), -#endif -}; diff --git a/arch/powerpc/cpu/mpc85xx/p3060_serdes.c b/arch/powerpc/cpu/mpc85xx/p3060_serdes.c deleted file mode 100644 index e720dcf6bd..0000000000 --- a/arch/powerpc/cpu/mpc85xx/p3060_serdes.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2011 Freescale Semiconductor, Inc. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include "fsl_corenet_serdes.h" - -static u8 serdes_cfg_tbl[][SRDS_MAX_LANES] = { - [0x03] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2, - SGMII_FM2_DTSEC4, SGMII_FM1_DTSEC4, SGMII_FM2_DTSEC1, - SGMII_FM1_DTSEC1, SGMII_FM2_DTSEC2, SGMII_FM1_DTSEC2, - NONE, NONE, AURORA, AURORA}, - [0x06] = {PCIE1, PCIE1, PCIE1, PCIE1, NONE, NONE, SGMII_FM2_DTSEC3, - SGMII_FM1_DTSEC3, SGMII_FM2_DTSEC4, SGMII_FM1_DTSEC4, - SGMII_FM2_DTSEC1, SGMII_FM1_DTSEC1, SGMII_FM2_DTSEC2, - SGMII_FM1_DTSEC2, NONE, NONE, AURORA, AURORA}, - [0x16] = {SRIO2, SRIO2, SRIO2, SRIO2, SRIO1, SRIO1, SRIO1, SRIO1, - AURORA, AURORA, SGMII_FM2_DTSEC1, SGMII_FM1_DTSEC1, - SGMII_FM2_DTSEC2, SGMII_FM1_DTSEC2, SGMII_FM2_DTSEC3, - SGMII_FM1_DTSEC3, SGMII_FM2_DTSEC4, SGMII_FM1_DTSEC4}, - [0x19] = {SRIO2, SRIO2, SRIO2, SRIO2, SRIO1, SRIO1, SRIO1, SRIO1, - AURORA, AURORA, PCIE2, PCIE2, PCIE2, PCIE2, SGMII_FM2_DTSEC3, - SGMII_FM1_DTSEC3, SGMII_FM2_DTSEC4, SGMII_FM1_DTSEC4}, - [0x1c] = {NONE, NONE, SRIO1, SRIO2, NONE, NONE, NONE, NONE, - AURORA, AURORA, SGMII_FM2_DTSEC1, SGMII_FM1_DTSEC1, - SGMII_FM2_DTSEC2, SGMII_FM1_DTSEC2, SGMII_FM2_DTSEC3, - SGMII_FM1_DTSEC3, SGMII_FM2_DTSEC4, SGMII_FM1_DTSEC4}, -}; - -enum srds_prtcl serdes_get_prtcl(int cfg, int lane) -{ - if (!serdes_lane_enabled(lane)) - return NONE; - - return serdes_cfg_tbl[cfg][lane]; -} - -int is_serdes_prtcl_valid(u32 prtcl) -{ - int i; - - if (prtcl > ARRAY_SIZE(serdes_cfg_tbl)) - return 0; - - for (i = 0; i < SRDS_MAX_LANES; i++) { - if (serdes_cfg_tbl[prtcl][i] != NONE) - return 1; - } - - return 0; -} - -void soc_serdes_init(void) -{ - /* - * On the P3060 the devdisr2 register does not correctly reflect - * the state of the MACs based on the RCW fields. So disable the MACs - * based on the srds_prtcl and ec1, ec2, ec3 fields - */ - - ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); - u32 devdisr2 = in_be32(&gur->devdisr2); - u32 rcwsr11 = in_be32(&gur->rcwsr[11]); - - /* NOTE: Leave FM1-1,FM1-2 alone for MDIO access */ - - if (!is_serdes_configured(SGMII_FM1_DTSEC3)) - devdisr2 |= FSL_CORENET_DEVDISR2_DTSEC1_3; - - if (!is_serdes_configured(SGMII_FM1_DTSEC4)) - devdisr2 |= FSL_CORENET_DEVDISR2_DTSEC1_4; - - if (!is_serdes_configured(SGMII_FM2_DTSEC1)) - devdisr2 |= FSL_CORENET_DEVDISR2_DTSEC2_1; - - if (!is_serdes_configured(SGMII_FM2_DTSEC2)) - devdisr2 |= FSL_CORENET_DEVDISR2_DTSEC2_2; - - if (!is_serdes_configured(SGMII_FM2_DTSEC3)) - devdisr2 |= FSL_CORENET_DEVDISR2_DTSEC2_3; - - if (!is_serdes_configured(SGMII_FM2_DTSEC4)) - devdisr2 |= FSL_CORENET_DEVDISR2_DTSEC2_4; - - if ((rcwsr11 & FSL_CORENET_RCWSR11_EC2) == - FSL_CORENET_RCWSR11_EC2_FM1_DTSEC2) { - devdisr2 &= ~FSL_CORENET_DEVDISR2_DTSEC1_2; - } - - if ((rcwsr11 & FSL_CORENET_RCWSR11_EC2) == - FSL_CORENET_RCWSR11_EC2_FM2_DTSEC1) { - devdisr2 &= ~FSL_CORENET_DEVDISR2_DTSEC2_1; - } - - out_be32(&gur->devdisr2, devdisr2); -} diff --git a/arch/powerpc/cpu/mpc8xxx/cpu.c b/arch/powerpc/cpu/mpc8xxx/cpu.c index 1c615d0b55..6cc5c4bcbb 100644 --- a/arch/powerpc/cpu/mpc8xxx/cpu.c +++ b/arch/powerpc/cpu/mpc8xxx/cpu.c @@ -69,7 +69,6 @@ struct cpu_type cpu_type_list [] = { CPU_TYPE_ENTRY(P2040, P2040, 4), CPU_TYPE_ENTRY(P2041, P2041, 4), CPU_TYPE_ENTRY(P3041, P3041, 4), - CPU_TYPE_ENTRY_MASK(P3060, P3060, 6, 0xf3), CPU_TYPE_ENTRY(P4040, P4040, 4), CPU_TYPE_ENTRY(P4080, P4080, 8), CPU_TYPE_ENTRY(P5010, P5010, 1), -- cgit v1.2.1 From 3e978f5dc85db40432f73380aa5be53096205f18 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Tue, 14 Aug 2012 10:14:51 +0000 Subject: powerpc/fsl-corenet: remove dead variant symbols These are not supported as individual build targets, but instead are supported by another target. The dead p4040 defines in particular had bitrotted significantly. Signed-off-by: Scott Wood Acked-by: Kumar Gala Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc85xx/Makefile | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc85xx/Makefile b/arch/powerpc/cpu/mpc85xx/Makefile index 71b8bb7207..33e93c88d7 100644 --- a/arch/powerpc/cpu/mpc85xx/Makefile +++ b/arch/powerpc/cpu/mpc85xx/Makefile @@ -62,7 +62,6 @@ COBJS-$(CONFIG_P1024) += ddr-gen3.o COBJS-$(CONFIG_P1025) += ddr-gen3.o COBJS-$(CONFIG_P2010) += ddr-gen3.o COBJS-$(CONFIG_P2020) += ddr-gen3.o -COBJS-$(CONFIG_PPC_P2040) += ddr-gen3.o COBJS-$(CONFIG_PPC_P2041) += ddr-gen3.o COBJS-$(CONFIG_PPC_P3041) += ddr-gen3.o COBJS-$(CONFIG_PPC_P4080) += ddr-gen3.o @@ -77,7 +76,6 @@ COBJS-$(CONFIG_PCI) += pci.o COBJS-$(CONFIG_SYS_DPAA_QBMAN) += portals.o # various SoC specific assignments -COBJS-$(CONFIG_PPC_P2040) += p2041_ids.o COBJS-$(CONFIG_PPC_P2041) += p2041_ids.o COBJS-$(CONFIG_PPC_P3041) += p3041_ids.o COBJS-$(CONFIG_PPC_P4080) += p4080_ids.o @@ -108,7 +106,6 @@ COBJS-$(CONFIG_P1024) += p1021_serdes.o COBJS-$(CONFIG_P1025) += p1021_serdes.o COBJS-$(CONFIG_P2010) += p2020_serdes.o COBJS-$(CONFIG_P2020) += p2020_serdes.o -COBJS-$(CONFIG_PPC_P2040) += p2041_serdes.o COBJS-$(CONFIG_PPC_P2041) += p2041_serdes.o COBJS-$(CONFIG_PPC_P3041) += p3041_serdes.o COBJS-$(CONFIG_PPC_P4080) += p4080_serdes.o -- cgit v1.2.1 From 33eee330cc8a445ff05f39a58af3c87324798230 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Tue, 14 Aug 2012 10:14:53 +0000 Subject: powerpc/fsl-corenet: work around erratum A004510 Erratum A004510 says that under certain load conditions, modified cache lines can be discarded, causing data corruption. To work around this, several CCSR and DCSR register updates need to be made in a careful manner, so that there is no other transaction in corenet when the update is made. The update is made from a locked cacheline, with a delay before to flush any previous activity, and a delay after to flush the CCSR/DCSR update. We can't use a readback because that would be another corenet transaction, which is not allowed. We lock the subsequent cacheline to prevent it from being fetched while we're executing the previous cacheline. It is filled with nops so that a branch doesn't cause us to fetch another cacheline. Ordinarily we are running in a cache-inhibited mapping at this point, so we temporarily change that. We make it guarded so that we should never see a speculative load, and we never do an explicit load. Thus, only the I-cache should ever fill from this mapping, and we flush/unlock it afterward. Thus we should avoid problems from any potential cache aliasing between inhibited and non-inhibited mappings. NOTE that if PAMU is used with this patch, it will need to use a dedicated LAW as described in the erratum. This is the responsibility of the OS that sets up PAMU. Signed-off-by: Scott Wood Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc85xx/cmd_errata.c | 3 + arch/powerpc/cpu/mpc85xx/release.S | 27 ++++ arch/powerpc/cpu/mpc85xx/start.S | 284 ++++++++++++++++++++++++++++++++++ 3 files changed, 314 insertions(+) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c b/arch/powerpc/cpu/mpc85xx/cmd_errata.c index 858b3f8260..e8989bdf45 100644 --- a/arch/powerpc/cpu/mpc85xx/cmd_errata.c +++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c @@ -123,6 +123,9 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129 if ((SVR_MAJ(svr) == 1) || IS_SVR_REV(svr, 2, 0)) puts("Work-around for Erratum NMG ETSEC129 enabled\n"); +#endif +#ifdef CONFIG_SYS_FSL_ERRATUM_A004510 + puts("Work-around for Erratum A004510 enabled\n"); #endif return 0; } diff --git a/arch/powerpc/cpu/mpc85xx/release.S b/arch/powerpc/cpu/mpc85xx/release.S index 1555a9ba67..043d0ff773 100644 --- a/arch/powerpc/cpu/mpc85xx/release.S +++ b/arch/powerpc/cpu/mpc85xx/release.S @@ -74,6 +74,33 @@ __secondary_start_page: mtspr 977,r3 #endif +#ifdef CONFIG_SYS_FSL_ERRATUM_A004510 + mfspr r3,SPRN_SVR + rlwinm r3,r3,0,0xff + li r4,CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV + cmpw r3,r4 + beq 1f + +#ifdef CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2 + li r4,CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2 + cmpw r3,r4 + beq 1f +#endif + + /* Not a supported revision affected by erratum */ + b 2f + +1: /* Erratum says set bits 55:60 to 001001 */ + msync + isync + mfspr r3,976 + li r4,0x48 + rlwimi r3,r4,0,0x1f8 + mtspr 976,r3 + isync +2: +#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 b1998b2152..66e8eb8f93 100644 --- a/arch/powerpc/cpu/mpc85xx/start.S +++ b/arch/powerpc/cpu/mpc85xx/start.S @@ -86,6 +86,35 @@ _start_e500: li r1,MSR_DE mtmsr r1 +#ifdef CONFIG_SYS_FSL_ERRATUM_A004510 + mfspr r3,SPRN_SVR + rlwinm r3,r3,0,0xff + li r4,CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV + cmpw r3,r4 + beq 1f + +#ifdef CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2 + li r4,CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2 + cmpw r3,r4 + beq 1f +#endif + + /* Not a supported revision affected by erratum */ + li r27,0 + b 2f + +1: li r27,1 /* Remember for later that we have the erratum */ + /* Erratum says set bits 55:60 to 001001 */ + msync + isync + mfspr r3,976 + li r4,0x48 + rlwimi r3,r4,0,0x1f8 + mtspr 976,r3 + isync +2: +#endif + #if defined(CONFIG_SECURE_BOOT) && defined(CONFIG_E500MC) /* ISBC uses L2 as stack. * Disable L2 cache here so that u-boot can enable it later @@ -440,6 +469,14 @@ nexti: mflr r1 /* R1 = our PC */ mfspr r2, MAS2 andc r2, r2, r3 or r2, r2, r1 +#ifdef CONFIG_SYS_FSL_ERRATUM_A004510 + cmpwi r27,0 + beq 1f + andi. r15, r2, MAS2_I|MAS2_G /* save the old I/G for later */ + rlwinm r2, r2, 0, ~MAS2_I + ori r2, r2, MAS2_G +1: +#endif mtspr MAS2, r2 /* Set the EPN to our PC base address */ mfspr r2, MAS3 @@ -719,6 +756,253 @@ delete_temp_tlbs: tlbwe #endif /* #if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR_PHYS) */ +#ifdef CONFIG_SYS_FSL_ERRATUM_A004510 +#define DCSR_LAWBARH0 (CONFIG_SYS_CCSRBAR + 0x1000) +#define LAW_SIZE_1M 0x13 +#define DCSRBAR_LAWAR (LAW_EN | (0x1d << 20) | LAW_SIZE_1M) + + cmpwi r27,0 + beq 9f + + /* + * Create a TLB entry for CCSR + * + * We're executing out of TLB1 entry in r14, and that's the only + * TLB entry that exists. To allocate some TLB entries for our + * own use, flip a bit high enough that we won't flip it again + * via incrementing. + */ + + xori r8, r14, 32 + lis r0, MAS0_TLBSEL(1)@h + rlwimi r0, r8, 16, MAS0_ESEL_MSK + lis r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_16M)@h + ori r1, r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_16M)@l + lis r7, CONFIG_SYS_CCSRBAR@h + ori r7, r7, CONFIG_SYS_CCSRBAR@l + ori r2, r7, MAS2_I|MAS2_G + lis r3, FSL_BOOKE_MAS3(CONFIG_SYS_CCSRBAR_PHYS_LOW, 0, (MAS3_SW|MAS3_SR))@h + ori r3, r3, FSL_BOOKE_MAS3(CONFIG_SYS_CCSRBAR_PHYS_LOW, 0, (MAS3_SW|MAS3_SR))@l + lis r4, CONFIG_SYS_CCSRBAR_PHYS_HIGH@h + ori r4, r4, CONFIG_SYS_CCSRBAR_PHYS_HIGH@l + mtspr MAS0, r0 + mtspr MAS1, r1 + mtspr MAS2, r2 + mtspr MAS3, r3 + mtspr MAS7, r4 + isync + tlbwe + isync + msync + + /* Map DCSR temporarily to physical address zero */ + li r0, 0 + lis r3, DCSRBAR_LAWAR@h + ori r3, r3, DCSRBAR_LAWAR@l + + stw r0, 0xc00(r7) /* LAWBARH0 */ + stw r0, 0xc04(r7) /* LAWBARL0 */ + sync + stw r3, 0xc08(r7) /* LAWAR0 */ + + /* Read back from LAWAR to ensure the update is complete. */ + lwz r3, 0xc08(r7) /* LAWAR0 */ + isync + + /* Create a TLB entry for DCSR at zero */ + + addi r9, r8, 1 + lis r0, MAS0_TLBSEL(1)@h + rlwimi r0, r9, 16, MAS0_ESEL_MSK + lis r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_1M)@h + ori r1, r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_1M)@l + li r6, 0 /* DCSR effective address */ + ori r2, r6, MAS2_I|MAS2_G + li r3, MAS3_SW|MAS3_SR + li r4, 0 + mtspr MAS0, r0 + mtspr MAS1, r1 + mtspr MAS2, r2 + mtspr MAS3, r3 + mtspr MAS7, r4 + isync + tlbwe + isync + msync + + /* enable the timebase */ +#define CTBENR 0xe2084 + li r3, 1 + addis r4, r7, CTBENR@ha + stw r3, CTBENR@l(r4) + lwz r3, CTBENR@l(r4) + twi 0,r3,0 + isync + + .macro erratum_set_ccsr offset value + addis r3, r7, \offset@ha + lis r4, \value@h + addi r3, r3, \offset@l + ori r4, r4, \value@l + bl erratum_set_value + .endm + + .macro erratum_set_dcsr offset value + addis r3, r6, \offset@ha + lis r4, \value@h + addi r3, r3, \offset@l + ori r4, r4, \value@l + bl erratum_set_value + .endm + + erratum_set_dcsr 0xb0e08 0xe0201800 + erratum_set_dcsr 0xb0e18 0xe0201800 + erratum_set_dcsr 0xb0e38 0xe0400000 + erratum_set_dcsr 0xb0008 0x00900000 + erratum_set_dcsr 0xb0e40 0xe00a0000 + erratum_set_ccsr 0x18600 CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY + erratum_set_ccsr 0x10f00 0x415e5000 + erratum_set_ccsr 0x11f00 0x415e5000 + + /* Make temp mapping uncacheable again, if it was initially */ + bl 2f +2: mflr r3 + tlbsx 0, r3 + mfspr r4, MAS2 + rlwimi r4, r15, 0, MAS2_I + rlwimi r4, r15, 0, MAS2_G + mtspr MAS2, r4 + isync + tlbwe + isync + msync + + /* Clear the cache */ + lis r3,(L1CSR1_ICFI|L1CSR1_ICLFR)@h + ori r3,r3,(L1CSR1_ICFI|L1CSR1_ICLFR)@l + sync + isync + mtspr SPRN_L1CSR1,r3 + isync +2: sync + mfspr r4,SPRN_L1CSR1 + and. r4,r4,r3 + bne 2b + + lis r3,(L1CSR1_CPE|L1CSR1_ICE)@h + ori r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l + sync + isync + mtspr SPRN_L1CSR1,r3 + isync +2: sync + mfspr r4,SPRN_L1CSR1 + and. r4,r4,r3 + beq 2b + + /* Remove temporary mappings */ + lis r0, MAS0_TLBSEL(1)@h + rlwimi r0, r9, 16, MAS0_ESEL_MSK + li r3, 0 + mtspr MAS0, r0 + mtspr MAS1, r3 + isync + tlbwe + isync + msync + + li r3, 0 + stw r3, 0xc08(r7) /* LAWAR0 */ + lwz r3, 0xc08(r7) + isync + + lis r0, MAS0_TLBSEL(1)@h + rlwimi r0, r8, 16, MAS0_ESEL_MSK + li r3, 0 + mtspr MAS0, r0 + mtspr MAS1, r3 + isync + tlbwe + isync + msync + + b 9f + + /* r3 = addr, r4 = value, clobbers r5, r11, r12 */ +erratum_set_value: + /* Lock two cache lines into I-Cache */ + sync + mfspr r11, SPRN_L1CSR1 + rlwinm r11, r11, 0, ~L1CSR1_ICUL + sync + isync + mtspr SPRN_L1CSR1, r11 + isync + + mflr r12 + bl 5f +5: mflr r5 + addi r5, r5, 2f - 5b + icbtls 0, 0, r5 + addi r5, r5, 64 + + sync + mfspr r11, SPRN_L1CSR1 +3: andi. r11, r11, L1CSR1_ICUL + bne 3b + + icbtls 0, 0, r5 + addi r5, r5, 64 + + sync + mfspr r11, SPRN_L1CSR1 +3: andi. r11, r11, L1CSR1_ICUL + bne 3b + + b 2f + .align 6 + /* Inside a locked cacheline, wait a while, write, then wait a while */ +2: sync + + mfspr r5, SPRN_TBRL + addis r11, r5, 0x10000@h /* wait 65536 timebase ticks */ +4: mfspr r5, SPRN_TBRL + subf. r5, r5, r11 + bgt 4b + + stw r4, 0(r3) + + mfspr r5, SPRN_TBRL + addis r11, r5, 0x10000@h /* wait 65536 timebase ticks */ +4: mfspr r5, SPRN_TBRL + subf. r5, r5, r11 + bgt 4b + + sync + + /* + * Fill out the rest of this cache line and the next with nops, + * to ensure that nothing outside the locked area will be + * fetched due to a branch. + */ + .rept 19 + nop + .endr + + sync + mfspr r11, SPRN_L1CSR1 + rlwinm r11, r11, 0, ~L1CSR1_ICUL + sync + isync + mtspr SPRN_L1CSR1, r11 + isync + + mtlr r12 + blr + +9: +#endif + create_init_ram_area: lis r6,FSL_BOOKE_MAS0(1, 15, 0)@h ori r6,r6,FSL_BOOKE_MAS0(1, 15, 0)@l -- cgit v1.2.1 From 123bd96d533190a207c9fcea84ae6328732a16cc Mon Sep 17 00:00:00 2001 From: York Sun Date: Fri, 17 Aug 2012 08:20:22 +0000 Subject: powerpc/mpc8xxx: use topology registers to calculate number of cores We have actual topology infomation to find out exactly which core is present. Calculate the number of cores if not specified. Signed-off-by: Kumar Gala Signed-off-by: York Sun Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc8xxx/cpu.c | 65 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 9 deletions(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc8xxx/cpu.c b/arch/powerpc/cpu/mpc8xxx/cpu.c index 6cc5c4bcbb..78a8f926b3 100644 --- a/arch/powerpc/cpu/mpc8xxx/cpu.c +++ b/arch/powerpc/cpu/mpc8xxx/cpu.c @@ -82,7 +82,39 @@ struct cpu_type cpu_type_list [] = { #endif }; -struct cpu_type cpu_type_unknown = CPU_TYPE_ENTRY(Unknown, Unknown, 1); +#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2 +u32 compute_ppc_cpumask(void) +{ + ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + int i = 0, count = 0; + u32 cluster, mask = 0; + + do { + int j; + cluster = in_be32(&gur->tp_cluster[i++].lower); + for (j = 0; j < 4; j++) { + u32 idx = (cluster >> (j*8)) & TP_CLUSTER_INIT_MASK; + u32 type = in_be32(&gur->tp_ityp[idx]); + + if (type & TP_ITYP_AV) { + if (TP_ITYP_TYPE(type) == TP_ITYP_TYPE_PPC) + mask |= 1 << count; + } + count++; + } + } while ((cluster & TP_CLUSTER_EOC) != TP_CLUSTER_EOC); + + return mask; +} +#else /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */ +/* + * Before chassis genenration 2, the cpumask should be hard-coded. + * In case of cpu type unknown or cpumask unset, use 1 as fail save. + */ +#define compute_ppc_cpumask() 1 +#endif /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */ + +struct cpu_type cpu_type_unknown = CPU_TYPE_ENTRY(Unknown, Unknown, 0); struct cpu_type *identify_cpu(u32 ver) { @@ -110,6 +142,9 @@ u32 cpu_mask() return ((in_be32(&pic->frr) & MPC8xxx_PICFRR_NCPU_MASK) >> MPC8xxx_PICFRR_NCPU_SHIFT) + 1; + if (cpu->num_cores == 0) + return compute_ppc_cpumask(); + return cpu->mask; } @@ -117,13 +152,14 @@ u32 cpu_mask() * Return the number of cores on this SOC. */ int cpu_numcores() { - ccsr_pic_t __iomem *pic = (void *)CONFIG_SYS_MPC8xxx_PIC_ADDR; struct cpu_type *cpu = gd->cpu; - /* better to query feature reporting register than just assume 1 */ - if (cpu == &cpu_type_unknown) - return ((in_be32(&pic->frr) & MPC8xxx_PICFRR_NCPU_MASK) >> - MPC8xxx_PICFRR_NCPU_SHIFT) + 1; + /* + * Report # of cores in terms of the cpu_mask if we haven't + * figured out how many there are yet + */ + if (cpu->num_cores == 0) + return hweight32(cpu_mask()); return cpu->num_cores; } @@ -135,9 +171,7 @@ int cpu_numcores() { */ int is_core_valid(unsigned int core) { - struct cpu_type *cpu = gd->cpu; - - return !!((1 << core) & cpu->mask); + return !!((1 << core) & cpu_mask()); } int probecpu (void) @@ -153,6 +187,19 @@ int probecpu (void) return 0; } +/* Once in memory, compute mask & # cores once and save them off */ +int fixup_cpu(void) +{ + struct cpu_type *cpu = gd->cpu; + + if (cpu->num_cores == 0) { + cpu->mask = cpu_mask(); + cpu->num_cores = cpu_numcores(); + } + + return 0; +} + /* * Initializes on-chip ethernet controllers. * to override, implement board_eth_init() -- cgit v1.2.1 From 5b6b85ae639e5c7e822970bdb29337d9e4b16e28 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 17 Aug 2012 08:20:23 +0000 Subject: Add e6500 processor detection Signed-off-by: York Sun Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc85xx/cpu.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc85xx/cpu.c b/arch/powerpc/cpu/mpc85xx/cpu.c index c1815e8860..8d2ef9ffc7 100644 --- a/arch/powerpc/cpu/mpc85xx/cpu.c +++ b/arch/powerpc/cpu/mpc85xx/cpu.c @@ -117,6 +117,9 @@ int checkcpu (void) case PVR_VER_E5500: puts("E5500"); break; + case PVR_VER_E6500: + puts("E6500"); + break; default: puts("Unknown"); break; -- cgit v1.2.1 From ffdf8890ae2564e8b5af36b1b384ca7e9bcdd7c2 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 17 Aug 2012 08:20:25 +0000 Subject: Added new ext fields to IFC In case more than 32 bit address is used, the EXT bit should be set. Need to fix up address map for IFC #CS for 4, also need to move # of IFC banks into config_mpc85xx.h Signed-off-by: Kumar Gala Signed-off-by: York Sun Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc8xxx/fsl_ifc.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc8xxx/fsl_ifc.c b/arch/powerpc/cpu/mpc8xxx/fsl_ifc.c index 66824960d3..56b319f5d4 100644 --- a/arch/powerpc/cpu/mpc8xxx/fsl_ifc.c +++ b/arch/powerpc/cpu/mpc8xxx/fsl_ifc.c @@ -44,12 +44,18 @@ void init_early_memctl_regs(void) set_ifc_ftim(IFC_CS0, IFC_FTIM3, CONFIG_SYS_CS0_FTIM3); #if !defined(CONFIG_SYS_FSL_ERRATUM_IFC_A003399) || defined(CONFIG_SYS_RAMBOOT) +#ifdef CONFIG_SYS_CSPR0_EXT + set_ifc_cspr_ext(IFC_CS0, CONFIG_SYS_CSPR0_EXT); +#endif set_ifc_cspr(IFC_CS0, CONFIG_SYS_CSPR0); set_ifc_amask(IFC_CS0, CONFIG_SYS_AMASK0); set_ifc_csor(IFC_CS0, CONFIG_SYS_CSOR0); #endif #endif +#ifdef CONFIG_SYS_CSPR1_EXT + set_ifc_cspr_ext(IFC_CS1, CONFIG_SYS_CSPR1_EXT); +#endif #if defined(CONFIG_SYS_CSPR1) && defined(CONFIG_SYS_CSOR1) set_ifc_ftim(IFC_CS1, IFC_FTIM0, CONFIG_SYS_CS1_FTIM0); set_ifc_ftim(IFC_CS1, IFC_FTIM1, CONFIG_SYS_CS1_FTIM1); @@ -61,6 +67,9 @@ void init_early_memctl_regs(void) set_ifc_cspr(IFC_CS1, CONFIG_SYS_CSPR1); #endif +#ifdef CONFIG_SYS_CSPR2_EXT + set_ifc_cspr_ext(IFC_CS2, CONFIG_SYS_CSPR2_EXT); +#endif #if defined(CONFIG_SYS_CSPR2) && defined(CONFIG_SYS_CSOR2) set_ifc_ftim(IFC_CS2, IFC_FTIM0, CONFIG_SYS_CS2_FTIM0); set_ifc_ftim(IFC_CS2, IFC_FTIM1, CONFIG_SYS_CS2_FTIM1); @@ -72,6 +81,9 @@ void init_early_memctl_regs(void) set_ifc_cspr(IFC_CS2, CONFIG_SYS_CSPR2); #endif +#ifdef CONFIG_SYS_CSPR3_EXT + set_ifc_cspr_ext(IFC_CS3, CONFIG_SYS_CSPR3_EXT); +#endif #if defined(CONFIG_SYS_CSPR3) && defined(CONFIG_SYS_CSOR3) set_ifc_ftim(IFC_CS3, IFC_FTIM0, CONFIG_SYS_CS3_FTIM0); set_ifc_ftim(IFC_CS3, IFC_FTIM1, CONFIG_SYS_CS3_FTIM1); -- cgit v1.2.1 From 709389b654de05fd6035656f5e082ba1757807b3 Mon Sep 17 00:00:00 2001 From: York Sun Date: Fri, 17 Aug 2012 08:20:26 +0000 Subject: powerpc/mpc8xxx: fix core id for multicore booting For the cores with multiple threads, we need to figure out which physical core a thread belongs. To match the core ids, update PIR registers and spin tables. Signed-off-by: York Sun Signed-off-by: Kumar Gala Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc85xx/fdt.c | 5 +++-- arch/powerpc/cpu/mpc85xx/release.S | 45 +++++++++++++++++++++++++++++++++++--- arch/powerpc/cpu/mpc8xxx/fdt.c | 3 ++- 3 files changed, 47 insertions(+), 6 deletions(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc85xx/fdt.c b/arch/powerpc/cpu/mpc85xx/fdt.c index 2ef2078461..a0a9b4c5ae 100644 --- a/arch/powerpc/cpu/mpc85xx/fdt.c +++ b/arch/powerpc/cpu/mpc85xx/fdt.c @@ -57,8 +57,9 @@ void ft_fixup_cpu(void *blob, u64 memory_limit) u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0); if (reg) { - u64 val = *reg * SIZE_BOOT_ENTRY + spin_tbl_addr; - val = cpu_to_fdt32(val); + u32 phys_cpu_id = thread_to_core(*reg); + u64 val = phys_cpu_id * SIZE_BOOT_ENTRY + spin_tbl_addr; + val = cpu_to_fdt64(val); if (*reg == id) { fdt_setprop_string(blob, off, "status", "okay"); diff --git a/arch/powerpc/cpu/mpc85xx/release.S b/arch/powerpc/cpu/mpc85xx/release.S index 043d0ff773..22e73e0661 100644 --- a/arch/powerpc/cpu/mpc85xx/release.S +++ b/arch/powerpc/cpu/mpc85xx/release.S @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 Freescale Semiconductor, Inc. + * Copyright 2008-2012 Freescale Semiconductor, Inc. * Kumar Gala * * See file CREDITS for list of people who contributed to this @@ -155,7 +155,27 @@ __secondary_start_page: /* r10 has the base address for the entry */ mfspr r0,SPRN_PIR -#ifdef CONFIG_E500MC +#if defined(CONFIG_E6500) +/* + * PIR definition for E6500 + * 0-17 Reserved (logic 0s) + * 8-19 CHIP_ID, 2’b00 - SoC 1 + * all others - reserved + * 20-24 CLUSTER_ID 5’b00000 - CCM 1 + * all others - reserved + * 25-26 CORE_CLUSTER_ID 2’b00 - cluster 1 + * 2’b01 - cluster 2 + * 2’b10 - cluster 3 + * 2’b11 - cluster 4 + * 27-28 CORE_ID 2’b00 - core 0 + * 2’b01 - core 1 + * 2’b10 - core 2 + * 2’b11 - core 3 + * 29-31 THREAD_ID 3’b000 - thread 0 + * 3’b001 - thread 1 + */ + rlwinm r4,r0,29,25,31 +#elif defined(CONFIG_E500MC) rlwinm r4,r0,27,27,31 #else mr r4,r0 @@ -170,6 +190,25 @@ __secondary_start_page: mtspr L1CSR2,r8 #endif +#ifdef CONFIG_E6500 + mfspr r0,SPRN_PIR + /* + * core 0 thread 0: pir reset value 0x00, new pir 0 + * core 0 thread 1: pir reset value 0x01, new pir 1 + * core 1 thread 0: pir reset value 0x08, new pir 2 + * core 1 thread 1: pir reset value 0x09, new pir 3 + * core 2 thread 0: pir reset value 0x10, new pir 4 + * core 2 thread 1: pir reset value 0x11, new pir 5 + * etc. + * + * Only thread 0 of each core will be running, updating PIR doesn't + * need to deal with the thread bits. + */ + rlwinm r4,r0,30,24,30 +#endif + + mtspr SPRN_PIR,r4 /* write to PIR register */ + #if defined(CONFIG_SYS_P4080_ERRATUM_CPU22) || \ defined(CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011) /* @@ -253,7 +292,7 @@ __secondary_start_page: /* setup the entry */ li r3,0 li r8,1 - stw r0,ENTRY_PIR(r10) + stw r4,ENTRY_PIR(r10) stw r3,ENTRY_ADDR_UPPER(r10) stw r8,ENTRY_ADDR_LOWER(r10) stw r3,ENTRY_R3_UPPER(r10) diff --git a/arch/powerpc/cpu/mpc8xxx/fdt.c b/arch/powerpc/cpu/mpc8xxx/fdt.c index 09810be7d3..32ab050962 100644 --- a/arch/powerpc/cpu/mpc8xxx/fdt.c +++ b/arch/powerpc/cpu/mpc8xxx/fdt.c @@ -62,8 +62,9 @@ void ft_fixup_num_cores(void *blob) { off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); while (off != -FDT_ERR_NOTFOUND) { u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0); + u32 phys_cpu_id = thread_to_core(*reg); - if (!is_core_valid(*reg) || is_core_disabled(*reg)) { + if (!is_core_valid(phys_cpu_id) || is_core_disabled(phys_cpu_id)) { int ph = fdt_get_phandle(blob, off); /* Delete the cpu node once there are no cpu handles */ -- cgit v1.2.1 From 744713a6a3ca19c77585a9452829a2e2a55693ad Mon Sep 17 00:00:00 2001 From: York Sun Date: Fri, 17 Aug 2012 08:22:36 +0000 Subject: powerpc/mpc85xx: Skip zero values for DDR debug registers Some debug registers have non-zero default out of reset. If software is not setting debug registers, skip writing to them to avoid unnecessary overriding. Also add debug messages for workarounds and debug registers. Signed-off-by: York Sun Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc85xx/ddr-gen3.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c index 81961def1b..0761d70080 100644 --- a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c +++ b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 Freescale Semiconductor, Inc. + * Copyright 2008-2012 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -43,6 +43,7 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, out_be32(&ddr->eor, regs->ddr_eor); #ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 + debug("Workaround for ERRATUM_DDR111_DDR134\n"); for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { cs_sa = (regs->cs[i].bnds >> 16) & 0xfff; cs_ea = regs->cs[i].bnds & 0xfff; @@ -115,8 +116,12 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, out_be32(&ddr->ddr_cdr2, regs->ddr_cdr2); out_be32(&ddr->err_disable, regs->err_disable); out_be32(&ddr->err_int_en, regs->err_int_en); - for (i = 0; i < 32; i++) - out_be32(&ddr->debug[i], regs->debug[i]); + for (i = 0; i < 32; i++) { + if (regs->debug[i]) { + debug("Write to debug_%d as %08x\n", i+1, regs->debug[i]); + out_be32(&ddr->debug[i], regs->debug[i]); + } + } #ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003474 out_be32(&ddr->debug[12], 0x00000015); @@ -128,6 +133,7 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN); out_be32(&ddr->sdram_cfg, temp_sdram_cfg); #ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003 + debug("Workaround for ERRATUM_DDR_A003\n"); if (regs->ddr_sdram_rcw_2 & 0x00f00000) { out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2 & 0xf07fffff); out_be32(&ddr->debug[2], 0x00000400); @@ -209,6 +215,7 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, * This erratum does not affect DDR3 mode, only for DDR2 mode. */ #ifdef CONFIG_SYS_FSL_ERRATUM_DDR_115 + debug("Workaround for ERRATUM_DDR_115\n"); if ((((in_be32(&ddr->sdram_cfg) >> 24) & 0x7) == SDRAM_TYPE_DDR2) && in_be32(&ddr->sdram_cfg) & 0x80000) { /* set DEBUG_1[31] */ @@ -216,6 +223,7 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, } #endif #ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 + debug("Workaround for ERRATUM_DDR111_DDR134\n"); /* * This is the combined workaround for DDR111 and DDR134 * following the published errata for MPC8572 -- cgit v1.2.1 From 73b5396b25c52463aa71c782316e2d77a4b8d5ed Mon Sep 17 00:00:00 2001 From: York Sun Date: Fri, 17 Aug 2012 08:22:37 +0000 Subject: powerpc/mpc8xxx: Add fine timing support for DDR3 When the DDR3 speed goes higher, we need to utilize fine offset from SPD. Signed-off-by: York Sun Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c | 25 +++++++++++++++++++------ arch/powerpc/cpu/mpc8xxx/ddr/interactive.c | 22 ++++++++++++++++------ 2 files changed, 35 insertions(+), 12 deletions(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c index d0a546610e..3e7c269e40 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2009 Freescale Semiconductor, Inc. + * Copyright 2008-2012 Freescale Semiconductor, Inc. * Dave Liu * * calculate the organization and timing parameter @@ -90,6 +90,7 @@ ddr_compute_dimm_parameters(const ddr3_spd_eeprom_t *spd, { unsigned int retval; unsigned int mtb_ps; + int ftb_10th_ps; int i; if (spd->mem_type) { @@ -196,6 +197,14 @@ ddr_compute_dimm_parameters(const ddr3_spd_eeprom_t *spd, mtb_ps = (spd->mtb_dividend * 1000) /spd->mtb_divisor; pdimm->mtb_ps = mtb_ps; + /* + * FTB - fine timebase + * use 1/10th of ps as our unit to avoid floating point + * eg, 10 for 1ps, 25 for 2.5ps, 50 for 5ps + */ + ftb_10th_ps = + ((spd->ftb_div & 0xf0) >> 4) * 10 / (spd->ftb_div & 0x0f); + pdimm->ftb_10th_ps = ftb_10th_ps; /* * sdram minimum cycle time * we assume the MTB is 0.125ns @@ -204,7 +213,8 @@ ddr_compute_dimm_parameters(const ddr3_spd_eeprom_t *spd, * =12 MTB (1.5ns) ->DDR3-1333 * =10 MTB (1.25ns) ->DDR3-1600 */ - pdimm->tCKmin_X_ps = spd->tCK_min * mtb_ps; + pdimm->tCKmin_X_ps = spd->tCK_min * mtb_ps + + (spd->fine_tCK_min * ftb_10th_ps) / 10; /* * CAS latency supported @@ -222,7 +232,8 @@ ddr_compute_dimm_parameters(const ddr3_spd_eeprom_t *spd, * DDR3-1333H 108 MTB (13.5ns) * DDR3-1600H 90 MTB (11.25ns) */ - pdimm->tAA_ps = spd->tAA_min * mtb_ps; + pdimm->tAA_ps = spd->tAA_min * mtb_ps + + (spd->fine_tAA_min * ftb_10th_ps) / 10; /* * min write recovery time @@ -239,7 +250,8 @@ ddr_compute_dimm_parameters(const ddr3_spd_eeprom_t *spd, * DDR3-1333H 108 MTB (13.5ns) * DDR3-1600H 90 MTB (11.25) */ - pdimm->tRCD_ps = spd->tRCD_min * mtb_ps; + pdimm->tRCD_ps = spd->tRCD_min * mtb_ps + + (spd->fine_tRCD_min * ftb_10th_ps) / 10; /* * min row active to row active delay time @@ -257,7 +269,8 @@ ddr_compute_dimm_parameters(const ddr3_spd_eeprom_t *spd, * DDR3-1333H 108 MTB (13.5ns) * DDR3-1600H 90 MTB (11.25ns) */ - pdimm->tRP_ps = spd->tRP_min * mtb_ps; + pdimm->tRP_ps = spd->tRP_min * mtb_ps + + (spd->fine_tRP_min * ftb_10th_ps) / 10; /* min active to precharge delay time * eg: tRAS_min = @@ -277,7 +290,7 @@ ddr_compute_dimm_parameters(const ddr3_spd_eeprom_t *spd, * DDR3-1600H 370 MTB (46.25ns) */ pdimm->tRC_ps = (((spd->tRAS_tRC_ext & 0xf0) << 4) | spd->tRC_min_lsb) - * mtb_ps; + * mtb_ps + (spd->fine_tRC_min * ftb_10th_ps) / 10; /* * min refresh recovery delay time * eg: tRFC_min = diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c b/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c index 5b724371f6..738c8089f5 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 Freescale Semiconductor, Inc. + * Copyright 2010-2012 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -1121,11 +1121,21 @@ void ddr3_spd_dump(const ddr3_spd_eeprom_t *spd) "therm_sensor SDRAM Thermal Sensor"); PRINT_NXS(33, spd->device_type, "device_type SDRAM Device Type"); - - printf("%-3d-%3d: ", 34, 59); /* Reserved, General Section */ - - for (i = 34; i <= 59; i++) - printf("%02x ", spd->res_34_59[i - 34]); + PRINT_NXS(34, spd->fine_tCK_min, + "fine_tCK_min Fine offset for tCKmin"); + PRINT_NXS(35, spd->fine_tAA_min, + "fine_tAA_min Fine offset for tAAmin"); + PRINT_NXS(36, spd->fine_tRCD_min, + "fine_tRCD_min Fine offset for tRCDmin"); + PRINT_NXS(37, spd->fine_tRP_min, + "fine_tRP_min Fine offset for tRPmin"); + PRINT_NXS(38, spd->fine_tRC_min, + "fine_tRC_min Fine offset for tRCmin"); + + printf("%-3d-%3d: ", 39, 59); /* Reserved, General Section */ + + for (i = 39; i <= 59; i++) + printf("%02x ", spd->res_39_59[i - 39]); puts("\n"); -- cgit v1.2.1 From fcea30688fd8c47d54473ffd0f551a5e6efc74a0 Mon Sep 17 00:00:00 2001 From: York Sun Date: Fri, 17 Aug 2012 08:22:38 +0000 Subject: powerpc/mpc8xxx: Add support for cas latency 12 and above Required by JEDEC 79-3E for high speed DDR3. Also change "CSn disabled" message to debug. Signed-off-by: York Sun Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c index 2067d53ad2..a8b2132f90 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 Freescale Semiconductor, Inc. + * Copyright 2008-2012 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -825,7 +825,7 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, /* Mode Register - MR0 */ unsigned int dll_on; /* DLL control for precharge PD, 0=off, 1=on */ - unsigned int wr; /* Write Recovery */ + unsigned int wr = 0; /* Write Recovery */ unsigned int dll_rst; /* DLL Reset */ unsigned int mode; /* Normal=0 or Test=1 */ unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */ @@ -885,24 +885,37 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, dll_on = 1; wr_mclk = (common_dimm->tWR_ps + mclk_ps - 1) / mclk_ps; - wr = wr_table[wr_mclk - 5]; + if (wr_mclk <= 16) { + wr = wr_table[wr_mclk - 5]; + } else { + printf("Error: unsupported write recovery for mode register " + "wr_mclk = %d\n", wr_mclk); + } dll_rst = 0; /* dll no reset */ mode = 0; /* normal mode */ /* look up table to get the cas latency bits */ - if (cas_latency >= 5 && cas_latency <= 11) { - unsigned char cas_latency_table[7] = { + if (cas_latency >= 5 && cas_latency <= 16) { + unsigned char cas_latency_table[] = { 0x2, /* 5 clocks */ 0x4, /* 6 clocks */ 0x6, /* 7 clocks */ 0x8, /* 8 clocks */ 0xa, /* 9 clocks */ 0xc, /* 10 clocks */ - 0xe /* 11 clocks */ + 0xe, /* 11 clocks */ + 0x1, /* 12 clocks */ + 0x3, /* 13 clocks */ + 0x5, /* 14 clocks */ + 0x7, /* 15 clocks */ + 0x9, /* 16 clocks */ }; caslat = cas_latency_table[cas_latency - 5]; + } else { + printf("Error: unsupported cas latency for mode register\n"); } + bt = 0; /* Nibble sequential */ switch (popts->burst_length) { @@ -930,6 +943,7 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, | ((mode & 0x1) << 7) | (((caslat >> 1) & 0x7) << 4) | ((bt & 0x1) << 3) + | ((caslat & 1) << 2) | ((bl & 0x3) << 0) ); @@ -1574,7 +1588,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, set_csn_config(dimm_number, i, ddr, popts, dimm_params); set_csn_config_2(i, ddr); } else - printf("CS%d is disabled.\n", i); + debug("CS%d is disabled.\n", i); } /* -- cgit v1.2.1 From a4c66509f1b95884e5753d5a30cf2cf884adb821 Mon Sep 17 00:00:00 2001 From: York Sun Date: Fri, 17 Aug 2012 08:22:39 +0000 Subject: powerpc/mpc8xxx: Enable 3-way and 4-way DDR interleaving Restructure DDR interleaving option to support 3 and 4 DDR controllers for 2-, 3- and 4-way interleaving. Signed-off-by: York Sun Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc85xx/cpu.c | 12 +- arch/powerpc/cpu/mpc85xx/ddr-gen3.c | 12 ++ arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c | 144 +++++---------- arch/powerpc/cpu/mpc8xxx/ddr/main.c | 305 +++++++++++++++++-------------- arch/powerpc/cpu/mpc8xxx/ddr/options.c | 211 +++++++++++++++------ arch/powerpc/cpu/mpc8xxx/ddr/util.c | 67 ++++--- 6 files changed, 434 insertions(+), 317 deletions(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc85xx/cpu.c b/arch/powerpc/cpu/mpc85xx/cpu.c index 8d2ef9ffc7..5ddb29435c 100644 --- a/arch/powerpc/cpu/mpc85xx/cpu.c +++ b/arch/powerpc/cpu/mpc85xx/cpu.c @@ -430,10 +430,20 @@ static void dump_spd_ddr_reg(void) case 0: ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR; break; -#ifdef CONFIG_SYS_MPC85xx_DDR2_ADDR +#if defined(CONFIG_SYS_MPC85xx_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1) case 1: ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR; break; +#endif +#if defined(CONFIG_SYS_MPC85xx_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2) + case 2: + ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR3_ADDR; + break; +#endif +#if defined(CONFIG_SYS_MPC85xx_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3) + case 3: + ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR4_ADDR; + break; #endif default: printf("%s unexpected controller number = %u\n", diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c index 0761d70080..ca4ed62645 100644 --- a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c +++ b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c @@ -32,9 +32,21 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, case 0: ddr = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR; break; +#if defined(CONFIG_SYS_MPC85xx_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1) case 1: ddr = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR; break; +#endif +#if defined(CONFIG_SYS_MPC85xx_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2) + case 2: + ddr = (void *)CONFIG_SYS_MPC85xx_DDR3_ADDR; + break; +#endif +#if defined(CONFIG_SYS_MPC85xx_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3) + case 3: + ddr = (void *)CONFIG_SYS_MPC85xx_DDR4_ADDR; + break; +#endif default: printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num); return; diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c index a8b2132f90..5938c44cec 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c @@ -151,8 +151,19 @@ static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr, if (dimm_params[dimm_number].n_ranks > 0) { go_config = 1; /* These fields only available in CS0_CONFIG */ - intlv_en = popts->memctl_interleaving; - intlv_ctl = popts->memctl_interleaving_mode; + if (!popts->memctl_interleaving) + break; + switch (popts->memctl_interleaving_mode) { + case FSL_DDR_CACHE_LINE_INTERLEAVING: + case FSL_DDR_PAGE_INTERLEAVING: + case FSL_DDR_BANK_INTERLEAVING: + case FSL_DDR_SUPERBANK_INTERLEAVING: + intlv_en = popts->memctl_interleaving; + intlv_ctl = popts->memctl_interleaving_mode; + break; + default: + break; + } } break; case 1: @@ -1413,73 +1424,37 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, /* Chip Select Memory Bounds (CSn_BNDS) */ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { - unsigned long long ea = 0, sa = 0; + unsigned long long ea, sa; unsigned int cs_per_dimm = CONFIG_CHIP_SELECTS_PER_CTRL / CONFIG_DIMM_SLOTS_PER_CTLR; unsigned int dimm_number = i / cs_per_dimm; unsigned long long rank_density - = dimm_params[dimm_number].rank_density; + = dimm_params[dimm_number].rank_density >> dbw_cap_adj; - if (((i == 1) && (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1)) || - ((i == 2) && (popts->ba_intlv_ctl & 0x04)) || - ((i == 3) && (popts->ba_intlv_ctl & FSL_DDR_CS2_CS3))) { - /* - * Don't set up boundaries for unused CS - * cs1 for cs0_cs1, cs0_cs1_and_cs2_cs3, cs0_cs1_cs2_cs3 - * cs2 for cs0_cs1_cs2_cs3 - * cs3 for cs2_cs3, cs0_cs1_and_cs2_cs3, cs0_cs1_cs2_cs3 - * But we need to set the ODT_RD_CFG and - * ODT_WR_CFG for CS1_CONFIG here. - */ - set_csn_config(dimm_number, i, ddr, popts, dimm_params); - continue; - } if (dimm_params[dimm_number].n_ranks == 0) { debug("Skipping setup of CS%u " "because n_ranks on DIMM %u is 0\n", i, dimm_number); continue; } - if (popts->memctl_interleaving && popts->ba_intlv_ctl) { - /* - * This works superbank 2CS - * There are 2 or more memory controllers configured - * identically, memory is interleaved between them, - * and each controller uses rank interleaving within - * itself. Therefore the starting and ending address - * on each controller is twice the amount present on - * each controller. If any CS is not included in the - * interleaving, the memory on that CS is not accssible - * and the total memory size is reduced. The CS is also - * disabled. - */ - unsigned long long ctlr_density = 0; + if (popts->memctl_interleaving) { switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) { + case FSL_DDR_CS0_CS1_CS2_CS3: + break; case FSL_DDR_CS0_CS1: case FSL_DDR_CS0_CS1_AND_CS2_CS3: - ctlr_density = dimm_params[0].rank_density * 2; if (i > 1) cs_en = 0; break; case FSL_DDR_CS2_CS3: - ctlr_density = dimm_params[0].rank_density; + default: if (i > 0) cs_en = 0; break; - case FSL_DDR_CS0_CS1_CS2_CS3: - /* - * The four CS interleaving should have been verified by - * populate_memctl_options() - */ - ctlr_density = dimm_params[0].rank_density * 4; - break; - default: - break; } - ea = (CONFIG_NUM_DDR_CONTROLLERS * - (ctlr_density >> dbw_cap_adj)) - 1; - } - else if (!popts->memctl_interleaving && popts->ba_intlv_ctl) { + sa = common_dimm->base_address; + ea = common_dimm->total_mem - 1; + } else if (!popts->memctl_interleaving) { /* * If memory interleaving between controllers is NOT * enabled, the starting address for each memory @@ -1491,49 +1466,40 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, */ switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) { case FSL_DDR_CS0_CS1_CS2_CS3: - /* CS0+CS1+CS2+CS3 interleaving, only CS0_CNDS - * needs to be set. - */ sa = common_dimm->base_address; - ea = sa + (4 * (rank_density >> dbw_cap_adj))-1; + ea = common_dimm->total_mem - 1; break; case FSL_DDR_CS0_CS1_AND_CS2_CS3: - /* CS0+CS1 and CS2+CS3 interleaving, CS0_CNDS - * and CS2_CNDS need to be set. - */ - if ((i == 2) && (dimm_number == 0)) { + if ((i >= 2) && (dimm_number == 0)) { sa = dimm_params[dimm_number].base_address + - 2 * (rank_density >> dbw_cap_adj); - ea = sa + 2 * (rank_density >> dbw_cap_adj) - 1; + 2 * rank_density; + ea = sa + 2 * rank_density - 1; } else { sa = dimm_params[dimm_number].base_address; - ea = sa + (2 * (rank_density >> - dbw_cap_adj)) - 1; + ea = sa + 2 * rank_density - 1; } break; case FSL_DDR_CS0_CS1: - /* CS0+CS1 interleaving, CS0_CNDS needs - * to be set - */ if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) { sa = dimm_params[dimm_number].base_address; - ea = sa + (rank_density >> dbw_cap_adj) - 1; - sa += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj); - ea += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj); + ea = sa + rank_density - 1; + if (i != 1) + sa += (i % cs_per_dimm) * rank_density; + ea += (i % cs_per_dimm) * rank_density; } else { sa = 0; ea = 0; } if (i == 0) - ea += (rank_density >> dbw_cap_adj); + ea += rank_density; break; case FSL_DDR_CS2_CS3: - /* CS2+CS3 interleaving*/ if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) { sa = dimm_params[dimm_number].base_address; - ea = sa + (rank_density >> dbw_cap_adj) - 1; - sa += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj); - ea += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj); + ea = sa + rank_density - 1; + if (i != 3) + sa += (i % cs_per_dimm) * rank_density; + ea += (i % cs_per_dimm) * rank_density; } else { sa = 0; ea = 0; @@ -1542,38 +1508,18 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, ea += (rank_density >> dbw_cap_adj); break; default: /* No bank(chip-select) interleaving */ + sa = dimm_params[dimm_number].base_address; + ea = sa + rank_density - 1; + if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) { + sa += (i % cs_per_dimm) * rank_density; + ea += (i % cs_per_dimm) * rank_density; + } else { + sa = 0; + ea = 0; + } break; } } - else if (popts->memctl_interleaving && !popts->ba_intlv_ctl) { - /* - * Only the rank on CS0 of each memory controller may - * be used if memory controller interleaving is used - * without rank interleaving within each memory - * controller. However, the ending address programmed - * into each CS0 must be the sum of the amount of - * memory in the two CS0 ranks. - */ - if (i == 0) { - ea = (2 * (rank_density >> dbw_cap_adj)) - 1; - } - - } - else if (!popts->memctl_interleaving && !popts->ba_intlv_ctl) { - /* - * No rank interleaving and no memory controller - * interleaving. - */ - sa = dimm_params[dimm_number].base_address; - ea = sa + (rank_density >> dbw_cap_adj) - 1; - if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) { - sa += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj); - ea += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj); - } else { - sa = 0; - ea = 0; - } - } sa >>= 24; ea >>= 24; diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/main.c b/arch/powerpc/cpu/mpc8xxx/ddr/main.c index c2a03e334c..4fd4f8fc33 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/main.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/main.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 Freescale Semiconductor, Inc. + * Copyright 2008-2012 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -15,13 +15,15 @@ #include #include #include +#include #include "ddr.h" -extern void fsl_ddr_set_lawbar( +void fsl_ddr_set_lawbar( const common_timing_params_t *memctl_common_params, unsigned int memctl_interleaved, unsigned int ctrl_num); +void fsl_ddr_set_intl3r(const unsigned int granule_size); /* processor specific function */ extern void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, @@ -51,6 +53,22 @@ u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { [1][0] = SPD_EEPROM_ADDRESS3, /* controller 2 */ [1][1] = SPD_EEPROM_ADDRESS4, /* controller 2 */ }; +#elif (CONFIG_NUM_DDR_CONTROLLERS == 3) && (CONFIG_DIMM_SLOTS_PER_CTLR == 1) +u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { + [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ + [1][0] = SPD_EEPROM_ADDRESS2, /* controller 2 */ + [2][0] = SPD_EEPROM_ADDRESS3, /* controller 3 */ +}; +#elif (CONFIG_NUM_DDR_CONTROLLERS == 3) && (CONFIG_DIMM_SLOTS_PER_CTLR == 2) +u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { + [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ + [0][1] = SPD_EEPROM_ADDRESS2, /* controller 1 */ + [1][0] = SPD_EEPROM_ADDRESS3, /* controller 2 */ + [1][1] = SPD_EEPROM_ADDRESS4, /* controller 2 */ + [2][0] = SPD_EEPROM_ADDRESS5, /* controller 3 */ + [2][1] = SPD_EEPROM_ADDRESS6, /* controller 3 */ +}; + #endif static void __get_spd(generic_spd_eeprom_t *spd, u8 i2c_address) @@ -156,12 +174,12 @@ const char * step_to_string(unsigned int step) { return step_string_tbl[s]; } -int step_assign_addresses(fsl_ddr_info_t *pinfo, - unsigned int dbw_cap_adj[], - unsigned int *all_memctl_interleaving, - unsigned int *all_ctlr_rank_interleaving) +unsigned long long step_assign_addresses(fsl_ddr_info_t *pinfo, + unsigned int dbw_cap_adj[]) { int i, j; + unsigned long long total_mem, current_mem_base, total_ctlr_mem; + unsigned long long rank_density, ctlr_density = 0; /* * If a reduced data width is requested, but the SPD @@ -220,86 +238,108 @@ int step_assign_addresses(fsl_ddr_info_t *pinfo, "specified controller %u\n", i); return 1; } + debug("dbw_cap_adj[%d]=%d\n", i, dbw_cap_adj[i]); } - j = 0; - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) - if (pinfo->memctl_opts[i].memctl_interleaving) - j++; - /* - * Not support less than all memory controllers interleaving - * if more than two controllers - */ - if (j == CONFIG_NUM_DDR_CONTROLLERS) - *all_memctl_interleaving = 1; - - /* Check that all controllers are rank interleaving. */ - j = 0; - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) - if (pinfo->memctl_opts[i].ba_intlv_ctl) - j++; - /* - * All memory controllers must be populated to qualify for - * all controller rank interleaving - */ - if (j == CONFIG_NUM_DDR_CONTROLLERS) - *all_ctlr_rank_interleaving = 1; - - if (*all_memctl_interleaving) { - unsigned long long addr, total_mem_per_ctlr = 0; - /* - * If interleaving between memory controllers, - * make each controller start at a base address - * of 0. - * - * Also, if bank interleaving (chip select - * interleaving) is enabled on each memory - * controller, CS0 needs to be programmed to - * cover the entire memory range on that memory - * controller - * - * Bank interleaving also implies that each - * addressed chip select is identical in size. - */ - + current_mem_base = 0ull; + total_mem = 0; + if (pinfo->memctl_opts[0].memctl_interleaving) { + rank_density = pinfo->dimm_params[0][0].rank_density >> + dbw_cap_adj[0]; + switch (pinfo->memctl_opts[0].ba_intlv_ctl & + FSL_DDR_CS0_CS1_CS2_CS3) { + case FSL_DDR_CS0_CS1_CS2_CS3: + ctlr_density = 4 * rank_density; + break; + case FSL_DDR_CS0_CS1: + case FSL_DDR_CS0_CS1_AND_CS2_CS3: + ctlr_density = 2 * rank_density; + break; + case FSL_DDR_CS2_CS3: + default: + ctlr_density = rank_density; + break; + } + debug("rank density is 0x%llx, ctlr density is 0x%llx\n", + rank_density, ctlr_density); for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - addr = 0; - pinfo->common_timing_params[i].base_address = 0ull; - for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { - unsigned long long cap - = pinfo->dimm_params[i][j].capacity; - - pinfo->dimm_params[i][j].base_address = addr; - addr += cap >> dbw_cap_adj[i]; - total_mem_per_ctlr += cap >> dbw_cap_adj[i]; + if (pinfo->memctl_opts[i].memctl_interleaving) { + switch (pinfo->memctl_opts[i].memctl_interleaving_mode) { + case FSL_DDR_CACHE_LINE_INTERLEAVING: + case FSL_DDR_PAGE_INTERLEAVING: + case FSL_DDR_BANK_INTERLEAVING: + case FSL_DDR_SUPERBANK_INTERLEAVING: + total_ctlr_mem = 2 * ctlr_density; + break; + case FSL_DDR_3WAY_1KB_INTERLEAVING: + case FSL_DDR_3WAY_4KB_INTERLEAVING: + case FSL_DDR_3WAY_8KB_INTERLEAVING: + total_ctlr_mem = 3 * ctlr_density; + break; + case FSL_DDR_4WAY_1KB_INTERLEAVING: + case FSL_DDR_4WAY_4KB_INTERLEAVING: + case FSL_DDR_4WAY_8KB_INTERLEAVING: + total_ctlr_mem = 4 * ctlr_density; + break; + default: + panic("Unknown interleaving mode"); + } + pinfo->common_timing_params[i].base_address = + current_mem_base; + pinfo->common_timing_params[i].total_mem = + total_ctlr_mem; + total_mem = current_mem_base + total_ctlr_mem; + debug("ctrl %d base 0x%llx\n", i, current_mem_base); + debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem); + } else { + /* when 3rd controller not interleaved */ + current_mem_base = total_mem; + total_ctlr_mem = 0; + pinfo->common_timing_params[i].base_address = + current_mem_base; + for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { + unsigned long long cap = + pinfo->dimm_params[i][j].capacity >> dbw_cap_adj[i]; + pinfo->dimm_params[i][j].base_address = + current_mem_base; + debug("ctrl %d dimm %d base 0x%llx\n", i, j, current_mem_base); + current_mem_base += cap; + total_ctlr_mem += cap; + } + debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem); + pinfo->common_timing_params[i].total_mem = + total_ctlr_mem; + total_mem += total_ctlr_mem; } } - pinfo->common_timing_params[0].total_mem = total_mem_per_ctlr; } else { /* * Simple linear assignment if memory * controllers are not interleaved. */ - unsigned long long cur_memsize = 0; for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - u64 total_mem_per_ctlr = 0; + total_ctlr_mem = 0; pinfo->common_timing_params[i].base_address = - cur_memsize; + current_mem_base; for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { /* Compute DIMM base addresses. */ unsigned long long cap = - pinfo->dimm_params[i][j].capacity; + pinfo->dimm_params[i][j].capacity >> dbw_cap_adj[i]; pinfo->dimm_params[i][j].base_address = - cur_memsize; - cur_memsize += cap >> dbw_cap_adj[i]; - total_mem_per_ctlr += cap >> dbw_cap_adj[i]; + current_mem_base; + debug("ctrl %d dimm %d base 0x%llx\n", i, j, current_mem_base); + current_mem_base += cap; + total_ctlr_mem += cap; } + debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem); pinfo->common_timing_params[i].total_mem = - total_mem_per_ctlr; + total_ctlr_mem; + total_mem += total_ctlr_mem; } } + debug("Total mem by %s is 0x%llx\n", __func__, total_mem); - return 0; + return total_mem; } unsigned long long @@ -307,8 +347,6 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, unsigned int size_only) { unsigned int i, j; - unsigned int all_controllers_memctl_interleaving = 0; - unsigned int all_controllers_rank_interleaving = 0; unsigned long long total_mem = 0; fsl_ddr_cfg_regs_t *ddr_reg = pinfo->fsl_ddr_config_reg; @@ -346,8 +384,9 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, retval = compute_dimm_parameters(spd, pdimm, i); #ifdef CONFIG_SYS_DDR_RAW_TIMING if (retval != 0) { - printf("SPD error! Trying fallback to " - "raw timing calculation\n"); + printf("SPD error on controller %d! " + "Trying fallback to raw timing " + "calculation\n", i); fsl_ddr_get_dimm_params(pdimm, i, j); } #else @@ -407,17 +446,14 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, &pinfo->memctl_opts[i], pinfo->dimm_params[i], i); } - check_interleaving_options(pinfo); case STEP_ASSIGN_ADDRESSES: /* STEP 5: Assign addresses to chip selects */ - step_assign_addresses(pinfo, - dbw_capacity_adjust, - &all_controllers_memctl_interleaving, - &all_controllers_rank_interleaving); + check_interleaving_options(pinfo); + total_mem = step_assign_addresses(pinfo, dbw_capacity_adjust); case STEP_COMPUTE_REGS: /* STEP 6: compute controller register values */ - debug("FSL Memory ctrl cg register computation\n"); + debug("FSL Memory ctrl register computation\n"); for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { if (timing_params[i].ndimms_present == 0) { memset(&ddr_reg[i], 0, @@ -437,21 +473,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, break; } - /* Compute the total amount of memory. */ - - /* - * If bank interleaving but NOT memory controller interleaving - * CS_BNDS describe the quantity of memory on each memory - * controller, so the total is the sum across. - */ - if (!all_controllers_memctl_interleaving - && all_controllers_rank_interleaving) { - total_mem = 0; - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - total_mem += timing_params[i].total_mem; - } - - } else { + { /* * Compute the amount of memory available just by * looking for the highest valid CSn_BNDS value. @@ -489,7 +511,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, phys_size_t fsl_ddr_sdram(void) { unsigned int i; - unsigned int memctl_interleaved; + unsigned int law_memctl = LAW_TRGT_IF_DDR_1; unsigned long long total_memory; fsl_ddr_info_t info; @@ -504,34 +526,6 @@ phys_size_t fsl_ddr_sdram(void) #endif total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 0); - /* Check for memory controller interleaving. */ - memctl_interleaved = 0; - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - memctl_interleaved += - info.memctl_opts[i].memctl_interleaving; - } - - if (memctl_interleaved) { - if (memctl_interleaved == CONFIG_NUM_DDR_CONTROLLERS) { - debug("memctl interleaving\n"); - /* - * Change the meaning of memctl_interleaved - * to be "boolean". - */ - memctl_interleaved = 1; - } else { - printf("Warning: memctl interleaving not " - "properly configured on all controllers\n"); - memctl_interleaved = 0; - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) - info.memctl_opts[i].memctl_interleaving = 0; - debug("Recomputing with memctl_interleaving off.\n"); - total_memory = fsl_ddr_compute(&info, - STEP_ASSIGN_ADDRESSES, - 0); - } - } - /* Program configuration registers. */ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { debug("Programming controller %u\n", i); @@ -544,24 +538,69 @@ phys_size_t fsl_ddr_sdram(void) fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]), i); } - if (memctl_interleaved) { - const unsigned int ctrl_num = 0; - - /* Only set LAWBAR1 if memory controller interleaving is on. */ - fsl_ddr_set_lawbar(&info.common_timing_params[0], - memctl_interleaved, ctrl_num); - } else { - /* - * Memory controller interleaving is NOT on; - * set each lawbar individually. - */ - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + /* program LAWs */ + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + if (info.memctl_opts[i].memctl_interleaving) { + switch (info.memctl_opts[i].memctl_interleaving_mode) { + case FSL_DDR_CACHE_LINE_INTERLEAVING: + case FSL_DDR_PAGE_INTERLEAVING: + case FSL_DDR_BANK_INTERLEAVING: + case FSL_DDR_SUPERBANK_INTERLEAVING: + if (i == 0) { + law_memctl = LAW_TRGT_IF_DDR_INTRLV; + fsl_ddr_set_lawbar(&info.common_timing_params[i], + law_memctl, i); + } else if (i == 2) { + law_memctl = LAW_TRGT_IF_DDR_INTLV_34; + fsl_ddr_set_lawbar(&info.common_timing_params[i], + law_memctl, i); + } + break; + case FSL_DDR_3WAY_1KB_INTERLEAVING: + case FSL_DDR_3WAY_4KB_INTERLEAVING: + case FSL_DDR_3WAY_8KB_INTERLEAVING: + law_memctl = LAW_TRGT_IF_DDR_INTLV_123; + if (i == 0) { + fsl_ddr_set_intl3r(info.memctl_opts[i].memctl_interleaving_mode); + fsl_ddr_set_lawbar(&info.common_timing_params[i], + law_memctl, i); + } + break; + case FSL_DDR_4WAY_1KB_INTERLEAVING: + case FSL_DDR_4WAY_4KB_INTERLEAVING: + case FSL_DDR_4WAY_8KB_INTERLEAVING: + law_memctl = LAW_TRGT_IF_DDR_INTLV_1234; + if (i == 0) + fsl_ddr_set_lawbar(&info.common_timing_params[i], + law_memctl, i); + /* place holder for future 4-way interleaving */ + break; + default: + break; + } + } else { + switch (i) { + case 0: + law_memctl = LAW_TRGT_IF_DDR_1; + break; + case 1: + law_memctl = LAW_TRGT_IF_DDR_2; + break; + case 2: + law_memctl = LAW_TRGT_IF_DDR_3; + break; + case 3: + law_memctl = LAW_TRGT_IF_DDR_4; + break; + default: + break; + } fsl_ddr_set_lawbar(&info.common_timing_params[i], - 0, i); + law_memctl, i); } } - debug("total_memory = %llu\n", total_memory); + debug("total_memory by %s = %llu\n", __func__, total_memory); #if !defined(CONFIG_PHYS_64BIT) /* Check for 4G or more. Bad. */ diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/options.c b/arch/powerpc/cpu/mpc8xxx/ddr/options.c index 00ec57be1f..2923456ebe 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/options.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/options.c @@ -1,5 +1,5 @@ /* - * Copyright 2008, 2010-2011 Freescale Semiconductor, Inc. + * Copyright 2008, 2010-2012 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -790,46 +790,97 @@ unsigned int populate_memctl_options(int all_DIMMs_registered, * should be a subset of the requested configuration. */ #if (CONFIG_NUM_DDR_CONTROLLERS > 1) - if (hwconfig_sub_f("fsl_ddr", "ctlr_intlv", buf)) { - if (pdimm[0].n_ranks == 0) { - printf("There is no rank on CS0 for controller %d. Because only" - " rank on CS0 and ranks chip-select interleaved with CS0" - " are controller interleaved, force non memory " - "controller interleaving\n", ctrl_num); - popts->memctl_interleaving = 0; - } else { - popts->memctl_interleaving = 1; - /* - * test null first. if CONFIG_HWCONFIG is not defined - * hwconfig_arg_cmp returns non-zero - */ - if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv", - "null", buf)) { - popts->memctl_interleaving = 0; - debug("memory controller interleaving disabled.\n"); - } else if (hwconfig_subarg_cmp_f("fsl_ddr", - "ctlr_intlv", - "cacheline", buf)) - popts->memctl_interleaving_mode = - FSL_DDR_CACHE_LINE_INTERLEAVING; - else if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv", - "page", buf)) - popts->memctl_interleaving_mode = - FSL_DDR_PAGE_INTERLEAVING; - else if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv", - "bank", buf)) - popts->memctl_interleaving_mode = - FSL_DDR_BANK_INTERLEAVING; - else if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv", - "superbank", buf)) - popts->memctl_interleaving_mode = - FSL_DDR_SUPERBANK_INTERLEAVING; - else { - popts->memctl_interleaving = 0; - printf("hwconfig has unrecognized parameter for ctlr_intlv.\n"); - } - } + if (!hwconfig_sub_f("fsl_ddr", "ctlr_intlv", buf)) + goto done; + + if (pdimm[0].n_ranks == 0) { + printf("There is no rank on CS0 for controller %d.\n", ctrl_num); + popts->memctl_interleaving = 0; + goto done; + } + popts->memctl_interleaving = 1; + /* + * test null first. if CONFIG_HWCONFIG is not defined + * hwconfig_arg_cmp returns non-zero + */ + if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv", + "null", buf)) { + popts->memctl_interleaving = 0; + debug("memory controller interleaving disabled.\n"); + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "cacheline", buf)) { + popts->memctl_interleaving_mode = + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? + 0 : FSL_DDR_CACHE_LINE_INTERLEAVING; + popts->memctl_interleaving = + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? + 0 : 1; + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "page", buf)) { + popts->memctl_interleaving_mode = + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? + 0 : FSL_DDR_PAGE_INTERLEAVING; + popts->memctl_interleaving = + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? + 0 : 1; + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "bank", buf)) { + popts->memctl_interleaving_mode = + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? + 0 : FSL_DDR_BANK_INTERLEAVING; + popts->memctl_interleaving = + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? + 0 : 1; + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "superbank", buf)) { + popts->memctl_interleaving_mode = + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? + 0 : FSL_DDR_SUPERBANK_INTERLEAVING; + popts->memctl_interleaving = + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? + 0 : 1; +#if (CONFIG_NUM_DDR_CONTROLLERS == 3) + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "3way_1KB", buf)) { + popts->memctl_interleaving_mode = + FSL_DDR_3WAY_1KB_INTERLEAVING; + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "3way_4KB", buf)) { + popts->memctl_interleaving_mode = + FSL_DDR_3WAY_4KB_INTERLEAVING; + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "3way_8KB", buf)) { + popts->memctl_interleaving_mode = + FSL_DDR_3WAY_8KB_INTERLEAVING; +#elif (CONFIG_NUM_DDR_CONTROLLERS == 4) + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "4way_1KB", buf)) { + popts->memctl_interleaving_mode = + FSL_DDR_4WAY_1KB_INTERLEAVING; + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "4way_4KB", buf)) { + popts->memctl_interleaving_mode = + FSL_DDR_4WAY_4KB_INTERLEAVING; + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "4way_8KB", buf)) { + popts->memctl_interleaving_mode = + FSL_DDR_4WAY_8KB_INTERLEAVING; +#endif + } else { + popts->memctl_interleaving = 0; + printf("hwconfig has unrecognized parameter for ctlr_intlv.\n"); } +done: #endif if ((hwconfig_sub_f("fsl_ddr", "bank_intlv", buf)) && (CONFIG_CHIP_SELECTS_PER_CTRL > 1)) { @@ -859,20 +910,20 @@ unsigned int populate_memctl_options(int all_DIMMs_registered, popts->ba_intlv_ctl = 0; printf("Not enough bank(chip-select) for " "CS0+CS1+CS2+CS3 on controller %d, " - "force non-interleaving!\n", ctrl_num); + "interleaving disabled!\n", ctrl_num); } #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) if ((pdimm[0].n_ranks < 2) && (pdimm[1].n_ranks < 2)) { popts->ba_intlv_ctl = 0; printf("Not enough bank(chip-select) for " "CS0+CS1+CS2+CS3 on controller %d, " - "force non-interleaving!\n", ctrl_num); + "interleaving disabled!\n", ctrl_num); } if (pdimm[0].capacity != pdimm[1].capacity) { popts->ba_intlv_ctl = 0; printf("Not identical DIMM size for " "CS0+CS1+CS2+CS3 on controller %d, " - "force non-interleaving!\n", ctrl_num); + "interleaving disabled!\n", ctrl_num); } #endif break; @@ -881,7 +932,7 @@ unsigned int populate_memctl_options(int all_DIMMs_registered, popts->ba_intlv_ctl = 0; printf("Not enough bank(chip-select) for " "CS0+CS1 on controller %d, " - "force non-interleaving!\n", ctrl_num); + "interleaving disabled!\n", ctrl_num); } break; case FSL_DDR_CS2_CS3: @@ -889,13 +940,13 @@ unsigned int populate_memctl_options(int all_DIMMs_registered, if (pdimm[0].n_ranks < 4) { popts->ba_intlv_ctl = 0; printf("Not enough bank(chip-select) for CS2+CS3 " - "on controller %d, force non-interleaving!\n", ctrl_num); + "on controller %d, interleaving disabled!\n", ctrl_num); } #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) if (pdimm[1].n_ranks < 2) { popts->ba_intlv_ctl = 0; printf("Not enough bank(chip-select) for CS2+CS3 " - "on controller %d, force non-interleaving!\n", ctrl_num); + "on controller %d, interleaving disabled!\n", ctrl_num); } #endif break; @@ -905,14 +956,14 @@ unsigned int populate_memctl_options(int all_DIMMs_registered, popts->ba_intlv_ctl = 0; printf("Not enough bank(CS) for CS0+CS1 and " "CS2+CS3 on controller %d, " - "force non-interleaving!\n", ctrl_num); + "interleaving disabled!\n", ctrl_num); } #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) if ((pdimm[0].n_ranks < 2) || (pdimm[1].n_ranks < 2)) { popts->ba_intlv_ctl = 0; printf("Not enough bank(CS) for CS0+CS1 and " "CS2+CS3 on controller %d, " - "force non-interleaving!\n", ctrl_num); + "interleaving disabled!\n", ctrl_num); } #endif break; @@ -954,33 +1005,73 @@ unsigned int populate_memctl_options(int all_DIMMs_registered, void check_interleaving_options(fsl_ddr_info_t *pinfo) { - int i, j, check_n_ranks, intlv_fixed = 0; + int i, j, k, check_n_ranks, intlv_invalid = 0; + unsigned int check_intlv, check_n_row_addr, check_n_col_addr; unsigned long long check_rank_density; + struct dimm_params_s *dimm; /* * Check if all controllers are configured for memory * controller interleaving. Identical dimms are recommended. At least - * the size should be checked. + * the size, row and col address should be checked. */ j = 0; check_n_ranks = pinfo->dimm_params[0][0].n_ranks; check_rank_density = pinfo->dimm_params[0][0].rank_density; + check_n_row_addr = pinfo->dimm_params[0][0].n_row_addr; + check_n_col_addr = pinfo->dimm_params[0][0].n_col_addr; + check_intlv = pinfo->memctl_opts[0].memctl_interleaving_mode; for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - if ((pinfo->memctl_opts[i].memctl_interleaving) && \ - (check_rank_density == pinfo->dimm_params[i][0].rank_density) && \ - (check_n_ranks == pinfo->dimm_params[i][0].n_ranks)) { + dimm = &pinfo->dimm_params[i][0]; + if (!pinfo->memctl_opts[i].memctl_interleaving) { + continue; + } else if (((check_rank_density != dimm->rank_density) || + (check_n_ranks != dimm->n_ranks) || + (check_n_row_addr != dimm->n_row_addr) || + (check_n_col_addr != dimm->n_col_addr) || + (check_intlv != + pinfo->memctl_opts[i].memctl_interleaving_mode))){ + intlv_invalid = 1; + break; + } else { j++; } + } - if (j != CONFIG_NUM_DDR_CONTROLLERS) { + if (intlv_invalid) { for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) - if (pinfo->memctl_opts[i].memctl_interleaving) { + pinfo->memctl_opts[i].memctl_interleaving = 0; + printf("Not all DIMMs are identical. " + "Memory controller interleaving disabled.\n"); + } else { + switch (check_intlv) { + case FSL_DDR_CACHE_LINE_INTERLEAVING: + case FSL_DDR_PAGE_INTERLEAVING: + case FSL_DDR_BANK_INTERLEAVING: + case FSL_DDR_SUPERBANK_INTERLEAVING: + if (3 == CONFIG_NUM_DDR_CONTROLLERS) + k = 2; + else + k = CONFIG_NUM_DDR_CONTROLLERS; + break; + case FSL_DDR_3WAY_1KB_INTERLEAVING: + case FSL_DDR_3WAY_4KB_INTERLEAVING: + case FSL_DDR_3WAY_8KB_INTERLEAVING: + case FSL_DDR_4WAY_1KB_INTERLEAVING: + case FSL_DDR_4WAY_4KB_INTERLEAVING: + case FSL_DDR_4WAY_8KB_INTERLEAVING: + default: + k = CONFIG_NUM_DDR_CONTROLLERS; + break; + } + debug("%d of %d controllers are interleaving.\n", j, k); + if (j != k) { + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) pinfo->memctl_opts[i].memctl_interleaving = 0; - intlv_fixed = 1; - } - if (intlv_fixed) - printf("Not all DIMMs are identical in size. " - "Memory controller interleaving disabled.\n"); + printf("Not all controllers have compatible " + "interleaving mode. All disabled.\n"); + } } + debug("Checking interleaving options completed\n"); } int fsl_use_spd(void) diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/util.c b/arch/powerpc/cpu/mpc8xxx/ddr/util.c index eb6a17a850..664ad09298 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/util.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/util.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 Freescale Semiconductor, Inc. + * Copyright 2008-2012 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -79,7 +79,7 @@ unsigned int mclk_to_picos(unsigned int mclk) void __fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params, - unsigned int memctl_interleaved, + unsigned int law_memctl, unsigned int ctrl_num) { unsigned long long base = memctl_common_params->base_address; @@ -98,28 +98,13 @@ __fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params, if ((base + size) >= CONFIG_MAX_MEM_MAPPED) size = CONFIG_MAX_MEM_MAPPED - base; #endif - - if (ctrl_num == 0) { - /* - * Set up LAW for DDR controller 1 space. - */ - unsigned int lawbar1_target_id = memctl_interleaved - ? LAW_TRGT_IF_DDR_INTRLV : LAW_TRGT_IF_DDR_1; - - if (set_ddr_laws(base, size, lawbar1_target_id) < 0) { - printf("%s: ERROR (ctrl #0, intrlv=%d)\n", __func__, - memctl_interleaved); - return ; - } - } else if (ctrl_num == 1) { - if (set_ddr_laws(base, size, LAW_TRGT_IF_DDR_2) < 0) { - printf("%s: ERROR (ctrl #1)\n", __func__); - return ; - } - } else { - printf("%s: unexpected DDR controller number (%u)\n", __func__, - ctrl_num); + if (set_ddr_laws(base, size, law_memctl) < 0) { + printf("%s: ERROR (ctrl #%d, TRGT ID=%x)\n", __func__, ctrl_num, + law_memctl); + return ; } + debug("setup ddr law base = 0x%llx, size 0x%llx, TRGT_ID 0x%x\n", + base, size, law_memctl); } __attribute__((weak, alias("__fsl_ddr_set_lawbar"))) void @@ -127,6 +112,15 @@ fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params, unsigned int memctl_interleaved, unsigned int ctrl_num); +void fsl_ddr_set_intl3r(const unsigned int granule_size) +{ +#ifdef CONFIG_E6500 + u32 *mcintl3r = (void *) (CONFIG_SYS_IMMR + 0x18004); + *mcintl3r = 0x80000000 | (granule_size & 0x1f); + debug("Enable MCINTL3R with granule size 0x%x\n", granule_size); +#endif +} + void board_add_ram_info(int use_default) { #if defined(CONFIG_MPC83xx) @@ -137,6 +131,9 @@ void board_add_ram_info(int use_default) #elif defined(CONFIG_MPC86xx) ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC86xx_DDR_ADDR); #endif +#if defined(CONFIG_E6500) && (CONFIG_NUM_DDR_CONTROLLERS == 3) + u32 *mcintl3r = (void *) (CONFIG_SYS_IMMR + 0x18004); +#endif #if (CONFIG_NUM_DDR_CONTROLLERS > 1) uint32_t cs0_config = in_be32(&ddr->cs0_config); #endif @@ -180,7 +177,29 @@ void board_add_ram_info(int use_default) else puts(", ECC off)"); -#if (CONFIG_NUM_DDR_CONTROLLERS > 1) +#if (CONFIG_NUM_DDR_CONTROLLERS == 3) +#ifdef CONFIG_E6500 + if (*mcintl3r & 0x80000000) { + puts("\n"); + puts(" DDR Controller Interleaving Mode: "); + switch (*mcintl3r & 0x1f) { + case FSL_DDR_3WAY_1KB_INTERLEAVING: + puts("3-way 1KB"); + break; + case FSL_DDR_3WAY_4KB_INTERLEAVING: + puts("3-way 4KB"); + break; + case FSL_DDR_3WAY_8KB_INTERLEAVING: + puts("3-way 8KB"); + break; + default: + puts("3-way UNKNOWN"); + break; + } + } +#endif +#endif +#if (CONFIG_NUM_DDR_CONTROLLERS >= 2) if (cs0_config & 0x20000000) { puts("\n"); puts(" DDR Controller Interleaving Mode: "); -- cgit v1.2.1 From 45064adcae724bd5162f64f186fdb17bfef8ab42 Mon Sep 17 00:00:00 2001 From: York Sun Date: Fri, 17 Aug 2012 08:22:40 +0000 Subject: powerpc/mpc8xxx: Fix bug for extended DDR timing Faster DDR3 timing requires parameters exceeding previously defined range. Extended parameters are fixed. Added some debug messages. Signed-off-by: York Sun Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c | 51 ++++++++++++++-------- .../cpu/mpc8xxx/ddr/lc_common_dimm_params.c | 12 ++++- 2 files changed, 43 insertions(+), 20 deletions(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c index 5938c44cec..2592873c9f 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c @@ -313,29 +313,41 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr, /* DDR SDRAM Timing Configuration 3 (TIMING_CFG_3) */ static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, const common_timing_params_t *common_dimm, unsigned int cas_latency) { + /* Extended precharge to activate interval (tRP) */ + unsigned int ext_pretoact = 0; /* Extended Activate to precharge interval (tRAS) */ unsigned int ext_acttopre = 0; - unsigned int ext_refrec; /* Extended refresh recovery time (tRFC) */ - unsigned int ext_caslat = 0; /* Extended MCAS latency from READ cmd */ - unsigned int cntl_adj = 0; /* Control Adjust */ - - /* If the tRAS > 19 MCLK, we use the ext mode */ - if (picos_to_mclk(common_dimm->tRAS_ps) > 0x13) - ext_acttopre = 1; - + /* Extended activate to read/write interval (tRCD) */ + unsigned int ext_acttorw = 0; + /* Extended refresh recovery time (tRFC) */ + unsigned int ext_refrec; + /* Extended MCAS latency from READ cmd */ + unsigned int ext_caslat = 0; + /* Extended last data to precharge interval (tWR) */ + unsigned int ext_wrrec = 0; + /* Control Adjust */ + unsigned int cntl_adj = 0; + + ext_pretoact = picos_to_mclk(common_dimm->tRP_ps) >> 4; + ext_acttopre = picos_to_mclk(common_dimm->tRAS_ps) >> 4; + ext_acttorw = picos_to_mclk(common_dimm->tRCD_ps) >> 4; + ext_caslat = (2 * cas_latency - 1) >> 4; ext_refrec = (picos_to_mclk(common_dimm->tRFC_ps) - 8) >> 4; - - /* If the CAS latency more than 8, use the ext mode */ - if (cas_latency > 8) - ext_caslat = 1; + /* ext_wrrec only deals with 16 clock and above, or 14 with OTF */ + ext_wrrec = (picos_to_mclk(common_dimm->tWR_ps) + + (popts->OTF_burst_chop_en ? 2 : 0)) >> 4; ddr->timing_cfg_3 = (0 - | ((ext_acttopre & 0x1) << 24) - | ((ext_refrec & 0xF) << 16) - | ((ext_caslat & 0x1) << 12) + | ((ext_pretoact & 0x1) << 28) + | ((ext_acttopre & 0x2) << 24) + | ((ext_acttorw & 0x1) << 22) + | ((ext_refrec & 0x1F) << 16) + | ((ext_caslat & 0x3) << 12) + | ((ext_wrrec & 0x1) << 8) | ((cntl_adj & 0x7) << 0) ); debug("FSLDDR: timing_cfg_3 = 0x%08x\n", ddr->timing_cfg_3); @@ -397,15 +409,16 @@ static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr, * we need set extend bit for it at * TIMING_CFG_3[EXT_CASLAT] */ - if (cas_latency > 8) - cas_latency -= 8; caslat_ctrl = 2 * cas_latency - 1; #endif refrec_ctrl = picos_to_mclk(common_dimm->tRFC_ps) - 8; wrrec_mclk = picos_to_mclk(common_dimm->tWR_ps); - wrrec_mclk = wrrec_table[wrrec_mclk - 1]; + if (wrrec_mclk > 16) + printf("Error: WRREC doesn't support more than 16 clocks\n"); + else + wrrec_mclk = wrrec_table[wrrec_mclk - 1]; if (popts->OTF_burst_chop_en) wrrec_mclk += 2; @@ -1550,7 +1563,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, set_timing_cfg_0(ddr, popts); #endif - set_timing_cfg_3(ddr, common_dimm, cas_latency); + set_timing_cfg_3(ddr, popts, common_dimm, cas_latency); set_timing_cfg_1(ddr, popts, common_dimm, cas_latency); set_timing_cfg_2(ddr, popts, common_dimm, cas_latency, additive_latency); diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c index 20c7db03ed..a474a654c2 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 Freescale Semiconductor, Inc. + * Copyright 2008-2012 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -491,5 +491,15 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params, */ outpdimm->additive_latency = additive_latency; + debug("tCKmin_ps = %u\n", outpdimm->tCKmin_X_ps); + debug("tRCD_ps = %u\n", outpdimm->tRCD_ps); + debug("tRP_ps = %u\n", outpdimm->tRP_ps); + debug("tRAS_ps = %u\n", outpdimm->tRAS_ps); + debug("tWR_ps = %u\n", outpdimm->tWR_ps); + debug("tWTR_ps = %u\n", outpdimm->tWTR_ps); + debug("tRFC_ps = %u\n", outpdimm->tRFC_ps); + debug("tRRD_ps = %u\n", outpdimm->tRRD_ps); + debug("tRC_ps = %u\n", outpdimm->tRC_ps); + return 0; } -- cgit v1.2.1 From 7e4db27ffd11f3eea7e4dfc33354fd087f9257d8 Mon Sep 17 00:00:00 2001 From: York Sun Date: Fri, 17 Aug 2012 08:22:41 +0000 Subject: powerpc/mpc8xxx DDR: Fix CAS latency calculation Empty slot should be skipped when calculating CAS latency. Signed-off-by: York Sun Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c index a474a654c2..03a784cd47 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c @@ -27,8 +27,10 @@ compute_cas_latency_ddr3(const dimm_params_t *dimm_params, /* compute the common CAS latency supported between slots */ tmp = dimm_params[0].caslat_X; - for (i = 1; i < number_of_dimms; i++) - tmp &= dimm_params[i].caslat_X; + for (i = 1; i < number_of_dimms; i++) { + if (dimm_params[i].n_ranks) + tmp &= dimm_params[i].caslat_X; + } common_caslat = tmp; /* compute the max tAAmin tCKmin between slots */ -- cgit v1.2.1 From 62f739fe465c41a2c5be0a46b3330c12b213dc07 Mon Sep 17 00:00:00 2001 From: York Sun Date: Fri, 17 Aug 2012 08:22:42 +0000 Subject: powerpc/mpc8xxx DDR: Fall back to raw timing for first controller only Only the first DIMM of first controller should fall back to raw timing parameters if SPD is missing or corrupted. Signed-off-by: York Sun Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc8xxx/ddr/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/main.c b/arch/powerpc/cpu/mpc8xxx/ddr/main.c index 4fd4f8fc33..b47268c20e 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/main.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/main.c @@ -383,7 +383,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, retval = compute_dimm_parameters(spd, pdimm, i); #ifdef CONFIG_SYS_DDR_RAW_TIMING - if (retval != 0) { + if (!i && !j && retval) { printf("SPD error on controller %d! " "Trying fallback to raw timing " "calculation\n", i); -- cgit v1.2.1 From 1d083ff2c4be7864aacec30a82d01e90b78e680a Mon Sep 17 00:00:00 2001 From: York Sun Date: Fri, 17 Aug 2012 08:22:43 +0000 Subject: powerpc/mpc8xxx DDR: Fix interactive DDR debugging Add one more argument to call function readline_into_buffer(). Fix print SPD format for negative values. Signed-off-by: York Sun Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc8xxx/ddr/interactive.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c b/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c index 738c8089f5..f59d1051bf 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c @@ -1047,7 +1047,7 @@ void ddr3_spd_dump(const ddr3_spd_eeprom_t *spd) /* General Section: Bytes 0-59 */ -#define PRINT_NXS(x, y, z...) printf("%-3d : %02x " z "\n", x, y); +#define PRINT_NXS(x, y, z...) printf("%-3d : %02x " z "\n", x, (u8)y); #define PRINT_NNXXS(n0, n1, x0, x1, s) \ printf("%-3d-%3d: %02x %02x " s "\n", n0, n1, x0, x1); @@ -1398,7 +1398,7 @@ unsigned long long fsl_ddr_interactive(fsl_ddr_info_t *pinfo) * No need to worry for buffer overflow here in * this function; readline() maxes out at CFG_CBSIZE */ - readline_into_buffer(prompt, buffer); + readline_into_buffer(prompt, buffer, 0); argc = parse_line(buffer, argv); if (argc == 0) continue; -- cgit v1.2.1 From 7ac3cc20e09e10051fb42e4bb2325177c8b32e86 Mon Sep 17 00:00:00 2001 From: York Sun Date: Fri, 17 Aug 2012 09:00:54 +0000 Subject: powerpc/mpc8xxx: Move HWCONFIG_BUFFER_SIZE into config.h Before proper environment is setup, we extract hwconfig and put it into a buffer with size HWCONFIG_BUFFER_SIZE. We need to enlarge the buffer to accommodate longer string. Since this macro is used in multiple files, we move it into arch/powerpc/include/asm/config.h. Signed-off-by: York Sun Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc85xx/cpu_init.c | 2 -- arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c | 2 -- arch/powerpc/cpu/mpc8xxx/ddr/options.c | 1 - 3 files changed, 5 deletions(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c b/arch/powerpc/cpu/mpc85xx/cpu_init.c index f293265c86..afb56719da 100644 --- a/arch/powerpc/cpu/mpc85xx/cpu_init.c +++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c @@ -48,8 +48,6 @@ #include "../../../../drivers/block/fsl_sata.h" -#define HWCONFIG_BUFFER_SIZE 128 - DECLARE_GLOBAL_DATA_PTR; #ifdef CONFIG_QE diff --git a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c index 8aac1dec0f..2a68060369 100644 --- a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c +++ b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c @@ -46,8 +46,6 @@ static u32 serdes_prtcl_map; -#define HWCONFIG_BUFFER_SIZE 128 - #ifdef DEBUG static const char *serdes_prtcl_str[] = { [NONE] = "NA", diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/options.c b/arch/powerpc/cpu/mpc8xxx/ddr/options.c index 2923456ebe..13e4825274 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/options.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/options.c @@ -19,7 +19,6 @@ * This is pretty fragile on both the use of stack and if the buffer is big * enough. However we will get a warning from getenv_f for the later. */ -#define HWCONFIG_BUFFER_SIZE 128 /* Board-specific functions defined in each board's ddr.c */ extern void fsl_ddr_board_options(memctl_options_t *popts, -- cgit v1.2.1 From 3ea21536d773b3b03ffd4005c7e7c3281a542bea Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 20 Aug 2012 13:10:08 +0000 Subject: powerpc/85xx: clear out TLB on boot Instead of just shooting down the entry that covers CCSR, clear out every TLB entry that isn't the one that we're executing out of. Signed-off-by: Scott Wood Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc85xx/start.S | 76 +++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 33 deletions(-) (limited to 'arch/powerpc/cpu') diff --git a/arch/powerpc/cpu/mpc85xx/start.S b/arch/powerpc/cpu/mpc85xx/start.S index 66e8eb8f93..9e04257d2c 100644 --- a/arch/powerpc/cpu/mpc85xx/start.S +++ b/arch/powerpc/cpu/mpc85xx/start.S @@ -435,12 +435,11 @@ l2_disabled: * Search for the TLB that covers the code we're executing, and shrink it * so that it covers only this 4K page. That will ensure that any other * TLB we create won't interfere with it. We assume that the TLB exists, - * which is why we don't check the Valid bit of MAS1. + * which is why we don't check the Valid bit of MAS1. We also assume + * it is in TLB1. * * This is necessary, for example, when booting from the on-chip ROM, * which (oddly) creates a single 4GB TLB that covers CCSR and DDR. - * If we don't shrink this TLB now, then we'll accidentally delete it - * in "purge_old_ccsr_tlb" below. */ bl nexti /* Find our address */ nexti: mflr r1 /* R1 = our PC */ @@ -450,11 +449,15 @@ nexti: mflr r1 /* R1 = our PC */ msync tlbsx 0, r1 /* This must succeed */ + mfspr r14, MAS0 /* Save ESEL for later */ + rlwinm r14, r14, 16, 0xfff + /* Set the size of the TLB to 4KB */ mfspr r3, MAS1 li r2, 0xF00 andc r3, r3, r2 /* Clear the TSIZE bits */ ori r3, r3, MAS1_TSIZE(BOOKE_PAGESZ_4K)@l + oris r3, r3, MAS1_IPROT@h mtspr MAS1, r3 /* @@ -488,6 +491,39 @@ nexti: mflr r1 /* R1 = our PC */ msync tlbwe +/* + * Clear out any other TLB entries that may exist, to avoid conflicts. + * Our TLB entry is in r14. + */ + li r0, TLBIVAX_ALL | TLBIVAX_TLB0 + tlbivax 0, r0 + tlbsync + + mfspr r4, SPRN_TLB1CFG + rlwinm r4, r4, 0, TLBnCFG_NENTRY_MASK + + li r3, 0 + mtspr MAS1, r3 +1: cmpw r3, r14 +#if defined(CONFIG_SYS_PPC_E500_DEBUG_TLB) && !defined(CONFIG_NAND_SPL) + cmpwi cr1, r3, CONFIG_SYS_PPC_E500_DEBUG_TLB + cror cr0*4+eq, cr0*4+eq, cr1*4+eq +#endif + rlwinm r5, r3, 16, MAS0_ESEL_MSK + addi r3, r3, 1 + beq 2f /* skip the entry we're executing from */ + + oris r5, r5, MAS0_TLBSEL(1)@h + mtspr MAS0, r5 + + isync + tlbwe + isync + msync + +2: cmpw r3, r4 + blt 1b + /* * Relocate CCSR, if necessary. We relocate CCSR if (obviously) the default * location is not where we want it. This typically happens on a 36-bit @@ -506,41 +542,15 @@ nexti: mflr r1 /* R1 = our PC */ #error "CONFIG_SYS_CCSRBAR_PHYS_HIGH and CONFIG_SYS_CCSRBAR_PHYS_LOW) must be defined." #endif -purge_old_ccsr_tlb: - lis r8, CONFIG_SYS_CCSRBAR@h - ori r8, r8, CONFIG_SYS_CCSRBAR@l - lis r9, (CONFIG_SYS_CCSRBAR + 0x1000)@h - ori r9, r9, (CONFIG_SYS_CCSRBAR + 0x1000)@l - - /* - * In a multi-stage boot (e.g. NAND boot), a previous stage may have - * created a TLB for CCSR, which will interfere with our relocation - * code. Since we're going to create a new TLB for CCSR anyway, - * it should be safe to delete this old TLB here. We have to search - * for it, though. - */ - - li r1, 0 - mtspr MAS6, r1 /* Search the current address space and PID */ - isync - msync - tlbsx 0, r8 - mfspr r1, MAS1 - andis. r2, r1, MAS1_VALID@h /* Check for the Valid bit */ - beq 1f /* Skip if no TLB found */ - - rlwinm r1, r1, 0, 1, 31 /* Clear Valid bit */ - mtspr MAS1, r1 - isync - msync - tlbwe -1: - create_ccsr_new_tlb: /* * Create a TLB for the new location of CCSR. Register R8 is reserved * for the virtual address of this TLB (CONFIG_SYS_CCSRBAR). */ + lis r8, CONFIG_SYS_CCSRBAR@h + ori r8, r8, CONFIG_SYS_CCSRBAR@l + lis r9, (CONFIG_SYS_CCSRBAR + 0x1000)@h + ori r9, r9, (CONFIG_SYS_CCSRBAR + 0x1000)@l lis r0, FSL_BOOKE_MAS0(0, 0, 0)@h ori r0, r0, FSL_BOOKE_MAS0(0, 0, 0)@l lis r1, FSL_BOOKE_MAS1(1, 0, 0, 0, BOOKE_PAGESZ_4K)@h -- cgit v1.2.1