svn commit: r292903 - in head/sys/powerpc: booke mpc85xx

Justin Hibbits jhibbits at FreeBSD.org
Wed Dec 30 03:43:27 UTC 2015


Author: jhibbits
Date: Wed Dec 30 03:43:25 2015
New Revision: 292903
URL: https://svnweb.freebsd.org/changeset/base/292903

Log:
  Add platform support for QorIQ SoCs.
  
  This includes the following changes:
  * SMP kickoff for QorIQ (tested on P5020)
  * Errata fixes for some silicon revisions
  * Enables L2 (and L3 if available) caches
  Obtained from:	Semihalf
  Sponsored by:	Alex Perez/Inertial Computing

Modified:
  head/sys/powerpc/booke/booke_machdep.c
  head/sys/powerpc/booke/locore.S
  head/sys/powerpc/booke/machdep_e500.c
  head/sys/powerpc/mpc85xx/mpc85xx.c
  head/sys/powerpc/mpc85xx/mpc85xx.h
  head/sys/powerpc/mpc85xx/platform_mpc85xx.c

Modified: head/sys/powerpc/booke/booke_machdep.c
==============================================================================
--- head/sys/powerpc/booke/booke_machdep.c	Wed Dec 30 03:36:22 2015	(r292902)
+++ head/sys/powerpc/booke/booke_machdep.c	Wed Dec 30 03:43:25 2015	(r292903)
@@ -316,8 +316,20 @@ booke_init(uint32_t arg1, uint32_t arg2)
 
 	ret = powerpc_init(dtbp, 0, 0, mdp);
 
-	/* Enable L1 caches */
+	/* Default to 32 byte cache line size. */
+	switch ((mfpvr()) >> 16) {
+	case FSL_E500mc:
+	case FSL_E5500:
+	case FSL_E6500:
+		cacheline_size = 64;
+		break;
+	}
+
+	/* Enable caches */
 	booke_enable_l1_cache();
+	booke_enable_l2_cache();
+
+	booke_enable_bpred();
 
 	return (ret);
 }

Modified: head/sys/powerpc/booke/locore.S
==============================================================================
--- head/sys/powerpc/booke/locore.S	Wed Dec 30 03:36:22 2015	(r292902)
+++ head/sys/powerpc/booke/locore.S	Wed Dec 30 03:43:25 2015	(r292903)
@@ -301,7 +301,7 @@ bp_ntlb1s:
 
 	.globl	bp_tlb1
 bp_tlb1:
-	.space	4 * 3 * 16
+	.space	4 * 3 * 64
 
 	.globl	bp_tlb1_end
 bp_tlb1_end:
@@ -731,6 +731,113 @@ ENTRY(icache_enable)
 	blr
 
 /*
+ * L2 cache disable/enable/inval sequences for E500mc.
+ */
+
+ENTRY(l2cache_inval)
+	mfspr	%r3, SPR_L2CSR0
+	oris	%r3, %r3, (L2CSR0_L2FI | L2CSR0_L2LFC)@h
+	ori	%r3, %r3, (L2CSR0_L2FI | L2CSR0_L2LFC)@l
+	isync
+	mtspr	SPR_L2CSR0, %r3
+	isync
+1:	mfspr   %r3, SPR_L2CSR0
+	andis.	%r3, %r3, L2CSR0_L2FI at h
+	bne	1b
+	blr
+
+ENTRY(l2cache_enable)
+	mfspr	%r3, SPR_L2CSR0
+	oris	%r3, %r3, (L2CSR0_L2E | L2CSR0_L2PE)@h
+	isync
+	mtspr	SPR_L2CSR0, %r3
+	isync
+	blr
+
+/*
+ * Branch predictor setup.
+ */
+ENTRY(bpred_enable)
+	mfspr	%r3, SPR_BUCSR
+	ori	%r3, %r3, BUCSR_BBFI
+	isync
+	mtspr	SPR_BUCSR, %r3
+	isync
+	ori	%r3, %r3, BUCSR_BPEN
+	isync
+	mtspr	SPR_BUCSR, %r3
+	isync
+	blr
+
+ENTRY(dataloss_erratum_access)
+	/* Lock two cache lines into I-Cache */
+	sync
+	mfspr	%r11, SPR_L1CSR1
+	rlwinm	%r11, %r11, 0, ~L1CSR1_ICUL
+	sync
+	isync
+	mtspr	SPR_L1CSR1, %r11
+	isync
+
+	mflr	%r9
+	bl	1f
+	.long 2f-.
+1:
+	mflr	%r5
+	lwz	%r8, 0(%r5)
+	mtlr	%r9
+	add	%r8, %r8, %r5
+	icbtls	0, 0, %r8
+	addi	%r9, %r8, 64
+
+	sync
+	mfspr	%r11, SPR_L1CSR1
+3:	andi.	%r11, %r11, L1CSR1_ICUL
+	bne	3b
+
+	icbtls	0, 0, %r9
+
+	sync
+	mfspr	%r11, SPR_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, TBR_TBL
+4:	addis	%r11, %r5, 0x100000 at h	/* wait around one million timebase ticks */
+	mfspr	%r5, TBR_TBL
+	subf.	%r5, %r5, %r11
+	bgt	4b
+
+	stw	%r4, 0(%r3)
+
+	mfspr	%r5, TBR_TBL
+4:	addis	%r11, %r5, 0x100000 at h	/* wait around one million timebase ticks */
+	mfspr	%r5, TBR_TBL
+	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
+
+	icblc	0, 0, %r8
+	icblc	0, 0, %r9
+
+	blr
+
+/*
  * int setfault()
  *
  * Similar to setjmp to setup for handling faults on accesses to user memory.

Modified: head/sys/powerpc/booke/machdep_e500.c
==============================================================================
--- head/sys/powerpc/booke/machdep_e500.c	Wed Dec 30 03:36:22 2015	(r292902)
+++ head/sys/powerpc/booke/machdep_e500.c	Wed Dec 30 03:43:25 2015	(r292903)
@@ -27,9 +27,15 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/cdefs.h>
 #include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
 #include <sys/reboot.h>
 
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
 #include <machine/machdep.h>
 
 #include <dev/fdt/fdt_common.h>
@@ -42,6 +48,7 @@ extern void icache_enable(void);
 extern void icache_inval(void);
 extern void l2cache_enable(void);
 extern void l2cache_inval(void);
+extern void bpred_enable(void);
 
 void
 booke_init_tlb(vm_paddr_t fdt_immr_pa)
@@ -79,7 +86,6 @@ booke_enable_l1_cache(void)
 		    (csr & L1CSR1_ICE) ? "en" : "dis");
 }
 
-#if 0
 void
 booke_enable_l2_cache(void)
 {
@@ -102,55 +108,18 @@ booke_enable_l2_cache(void)
 }
 
 void
-booke_enable_l3_cache(void)
+booke_enable_bpred(void)
 {
-	uint32_t csr, size, ver;
-
-	/* Enable L3 CoreNet Platform Cache (CPC) */
-	ver = SVR_VER(mfspr(SPR_SVR));
-	if (ver == SVR_P2041 || ver == SVR_P2041E || ver == SVR_P3041 ||
-	    ver == SVR_P3041E || ver == SVR_P5020 || ver == SVR_P5020E) {
-		csr = ccsr_read4(OCP85XX_CPC_CSR0);
-		if ((csr & OCP85XX_CPC_CSR0_CE) == 0) {
-			l3cache_inval();
-			l3cache_enable();
-		}
+	uint32_t csr;
 
-		csr = ccsr_read4(OCP85XX_CPC_CSR0);
-		if ((boothowto & RB_VERBOSE) != 0 ||
-		    (csr & OCP85XX_CPC_CSR0_CE) == 0) {
-			size = OCP85XX_CPC_CFG0_SZ_K(ccsr_read4(OCP85XX_CPC_CFG0));
-			printf("L3 Corenet Platform Cache: %d KB %sabled\n",
-			    size, (csr & OCP85XX_CPC_CSR0_CE) == 0 ?
-			    "dis" : "en");
-		}
-	}
+	bpred_enable();
+	csr = mfspr(SPR_BUCSR);
+	if ((boothowto & RB_VERBOSE) != 0 || (csr & BUCSR_BPEN) == 0)
+		printf("Branch Predictor %sabled\n",
+		    (csr & BUCSR_BPEN) ? "en" : "dis");
 }
 
 void
 booke_disable_l2_cache(void)
 {
 }
-
-static void
-l3cache_inval(void)
-{
-
-	/* Flash invalidate the CPC and clear all the locks */
-	ccsr_write4(OCP85XX_CPC_CSR0, OCP85XX_CPC_CSR0_FI |
-	    OCP85XX_CPC_CSR0_LFC);
-	while (ccsr_read4(OCP85XX_CPC_CSR0) & (OCP85XX_CPC_CSR0_FI |
-	    OCP85XX_CPC_CSR0_LFC))
-		;
-}
-
-static void
-l3cache_enable(void)
-{
-
-	ccsr_write4(OCP85XX_CPC_CSR0, OCP85XX_CPC_CSR0_CE |
-	    OCP85XX_CPC_CSR0_PE);
-	/* Read back to sync write */
-	ccsr_read4(OCP85XX_CPC_CSR0);
-}
-#endif

Modified: head/sys/powerpc/mpc85xx/mpc85xx.c
==============================================================================
--- head/sys/powerpc/mpc85xx/mpc85xx.c	Wed Dec 30 03:36:22 2015	(r292902)
+++ head/sys/powerpc/mpc85xx/mpc85xx.c	Wed Dec 30 03:43:25 2015	(r292903)
@@ -32,18 +32,26 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
+#include <sys/reboot.h>
 #include <sys/rman.h>
 
 #include <vm/vm.h>
 #include <vm/vm_param.h>
+#include <vm/pmap.h>
 
 #include <machine/cpu.h>
 #include <machine/cpufunc.h>
+#include <machine/machdep.h>
 #include <machine/pio.h>
 #include <machine/spr.h>
 
 #include <dev/fdt/fdt_common.h>
 
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+
 #include <powerpc/mpc85xx/mpc85xx.h>
 
 
@@ -249,3 +257,166 @@ law_pci_target(struct resource *res, int
 	return (rv);
 }
 
+static void
+l3cache_inval(void)
+{
+
+	/* Flash invalidate the CPC and clear all the locks */
+	ccsr_write4(OCP85XX_CPC_CSR0, OCP85XX_CPC_CSR0_FI |
+	    OCP85XX_CPC_CSR0_LFC);
+	while (ccsr_read4(OCP85XX_CPC_CSR0) & (OCP85XX_CPC_CSR0_FI |
+	    OCP85XX_CPC_CSR0_LFC))
+		;
+}
+
+static void
+l3cache_enable(void)
+{
+
+	ccsr_write4(OCP85XX_CPC_CSR0, OCP85XX_CPC_CSR0_CE |
+	    OCP85XX_CPC_CSR0_PE);
+	/* Read back to sync write */
+	ccsr_read4(OCP85XX_CPC_CSR0);
+}
+
+void
+mpc85xx_enable_l3_cache(void)
+{
+	uint32_t csr, size, ver;
+
+	/* Enable L3 CoreNet Platform Cache (CPC) */
+	ver = SVR_VER(mfspr(SPR_SVR));
+	if (ver == SVR_P2041 || ver == SVR_P2041E || ver == SVR_P3041 ||
+	    ver == SVR_P3041E || ver == SVR_P5020 || ver == SVR_P5020E) {
+		csr = ccsr_read4(OCP85XX_CPC_CSR0);
+		if ((csr & OCP85XX_CPC_CSR0_CE) == 0) {
+			l3cache_inval();
+			l3cache_enable();
+		}
+
+		csr = ccsr_read4(OCP85XX_CPC_CSR0);
+		if ((boothowto & RB_VERBOSE) != 0 ||
+		    (csr & OCP85XX_CPC_CSR0_CE) == 0) {
+			size = OCP85XX_CPC_CFG0_SZ_K(ccsr_read4(OCP85XX_CPC_CFG0));
+			printf("L3 Corenet Platform Cache: %d KB %sabled\n",
+			    size, (csr & OCP85XX_CPC_CSR0_CE) == 0 ?
+			    "dis" : "en");
+		}
+	}
+}
+
+static void
+mpc85xx_dataloss_erratum_spr976(void)
+{
+	uint32_t svr = SVR_VER(mfspr(SPR_SVR));
+
+	/* Ignore whether it's the E variant */
+	svr &= ~0x8;
+
+	if (svr != SVR_P3041 && svr != SVR_P4040 &&
+	    svr != SVR_P4080 && svr != SVR_P5020)
+		return;
+
+	mb();
+	isync();
+	mtspr(976, (mfspr(976) & ~0x1f8) | 0x48);
+	isync();
+}
+
+static vm_offset_t
+mpc85xx_map_dcsr(void)
+{
+	phandle_t node;
+	u_long b, s;
+	int err;
+
+	/*
+	 * Try to access the dcsr node directly i.e. through /aliases/.
+	 */
+	if ((node = OF_finddevice("dcsr")) != -1)
+		if (fdt_is_compatible_strict(node, "fsl,dcsr"))
+			goto moveon;
+	/*
+	 * Find the node the long way.
+	 */
+	if ((node = OF_finddevice("/")) == -1)
+		return (ENXIO);
+
+	if ((node = ofw_bus_find_compatible(node, "fsl,dcsr")) == 0)
+		return (ENXIO);
+
+moveon:
+	err = fdt_get_range(node, 0, &b, &s);
+
+	if (err != 0)
+		return (err);
+
+#ifdef QORIQ_DPAA
+	law_enable(OCP85XX_TGTIF_DCSR, b, 0x400000);
+#endif
+	return pmap_early_io_map(b, 0x400000);
+}
+
+
+
+void
+mpc85xx_fix_errata(vm_offset_t va_ccsr)
+{
+	uint32_t svr = SVR_VER(mfspr(SPR_SVR));
+	vm_offset_t va_dcsr;
+
+	/* Ignore whether it's the E variant */
+	svr &= ~0x8;
+
+	if (svr != SVR_P3041 && svr != SVR_P4040 &&
+	    svr != SVR_P4080 && svr != SVR_P5020)
+		return;
+
+	if (mfmsr() & PSL_EE)
+		return;
+
+	/*
+	 * dcsr region need to be mapped thus patch can refer to.
+	 * Align dcsr right after ccsbar.
+	 */
+	va_dcsr = mpc85xx_map_dcsr();
+	if (va_dcsr == 0)
+		goto err;
+
+	/*
+	 * As A004510 errata specify, special purpose register 976
+	 * SPR976[56:60] = 6'b001001 must be set. e500mc core reference manual
+	 * does not document SPR976 register.
+	 */
+	mpc85xx_dataloss_erratum_spr976();
+
+	/*
+	 * Specific settings in the CCF and core platform cache (CPC)
+	 * are required to reconfigure the CoreNet coherency fabric.
+	 * The register settings that should be updated are described
+	 * in errata and relay on base address, offset and updated value.
+	 * Special conditions must be used to update these registers correctly.
+	 */
+	dataloss_erratum_access(va_dcsr + 0xb0e08, 0xe0201800);
+	dataloss_erratum_access(va_dcsr + 0xb0e18, 0xe0201800);
+	dataloss_erratum_access(va_dcsr + 0xb0e38, 0xe0400000);
+	dataloss_erratum_access(va_dcsr + 0xb0008, 0x00900000);
+	dataloss_erratum_access(va_dcsr + 0xb0e40, 0xe00a0000);
+
+	switch (svr) {
+	case SVR_P5020:
+		dataloss_erratum_access(va_ccsr + 0x18600, 0xc0000000);
+		break;
+	case SVR_P4040:
+	case SVR_P4080:
+		dataloss_erratum_access(va_ccsr + 0x18600, 0xff000000);
+		break;
+	case SVR_P3041:
+		dataloss_erratum_access(va_ccsr + 0x18600, 0xf0000000);
+	}
+	dataloss_erratum_access(va_ccsr + 0x10f00, 0x415e5000);
+	dataloss_erratum_access(va_ccsr + 0x11f00, 0x415e5000);
+
+err:
+	return;
+}

Modified: head/sys/powerpc/mpc85xx/mpc85xx.h
==============================================================================
--- head/sys/powerpc/mpc85xx/mpc85xx.h	Wed Dec 30 03:36:22 2015	(r292902)
+++ head/sys/powerpc/mpc85xx/mpc85xx.h	Wed Dec 30 03:43:25 2015	(r292903)
@@ -40,6 +40,25 @@ extern vm_offset_t		ccsrbar_va;
 #define	OCP85XX_CCSRBAR		(CCSRBAR_VA + 0x0)
 #define	OCP85XX_BPTR		(CCSRBAR_VA + 0x20)
 
+#define	OCP85XX_BSTRH		(CCSRBAR_VA + 0x20)
+#define	OCP85XX_BSTRL		(CCSRBAR_VA + 0x24)
+#define	OCP85XX_BSTAR		(CCSRBAR_VA + 0x28)
+
+#define	OCP85XX_COREDISR	(CCSRBAR_VA + 0xE0094)
+#define	OCP85XX_BRR		(CCSRBAR_VA + 0xE00E4)
+
+/*
+ * Run Control and Power Management registers
+ */
+#define CCSR_CTBENR		(CCSRBAR_VA + 0xE2084)
+#define CCSR_CTBCKSELR		(CCSRBAR_VA + 0xE208C)
+#define CCSR_CTBCHLTCR		(CCSRBAR_VA + 0xE2094)
+
+/*
+ * DDR Memory controller.
+ */
+#define	OCP85XX_DDR1_CS0_CONFIG		(CCSRBAR_VA + 0x8080)
+
 /*
  * E500 Coherency Module registers
  */
@@ -68,6 +87,7 @@ extern vm_offset_t		ccsrbar_va;
 #define	OCP85XX_TGTIF_RAM1	0x10
 #define	OCP85XX_TGTIF_RAM2	0x11
 #define	OCP85XX_TGTIF_BMAN	0x18
+#define	OCP85XX_TGTIF_DCSR	0x1D
 #define	OCP85XX_TGTIF_QMAN	0x3C
 #define	OCP85XX_TRGT_SHIFT	20
 #else
@@ -84,6 +104,20 @@ extern vm_offset_t		ccsrbar_va;
 #define OCP85XX_L2CTL		(CCSRBAR_VA + 0x20000)
 
 /*
+ * L3 CoreNet platform cache (CPC) registers
+ */
+#define	OCP85XX_CPC_CSR0		(CCSRBAR_VA + 0x10000)
+#define	  OCP85XX_CPC_CSR0_CE		  0x80000000
+#define	  OCP85XX_CPC_CSR0_PE		  0x40000000
+#define	  OCP85XX_CPC_CSR0_FI		  0x00200000
+#define	  OCP85XX_CPC_CSR0_WT		  0x00080000
+#define	  OCP85XX_CPC_CSR0_FL		  0x00000800
+#define	  OCP85XX_CPC_CSR0_LFC		  0x00000400
+#define	OCP85XX_CPC_CFG0		(CCSRBAR_VA + 0x10008)
+#define	  OCP85XX_CPC_CFG_SZ_MASK	  0x00003fff
+#define	  OCP85XX_CPC_CFG0_SZ_K(x)	  (((x) & OCP85XX_CPC_CFG_SZ_MASK) << 6)
+
+/*
  * Power-On Reset configuration
  */
 #define	OCP85XX_PORDEVSR	(CCSRBAR_VA + 0xe000c)
@@ -110,4 +144,8 @@ int law_pci_target(struct resource *, in
 DECLARE_CLASS(mpc85xx_platform);
 int mpc85xx_attach(platform_t);
 
+void mpc85xx_enable_l3_cache(void);
+void mpc85xx_fix_errata(vm_offset_t);
+void dataloss_erratum_access(vm_offset_t, uint32_t);
+
 #endif /* _MPC85XX_H_ */

Modified: head/sys/powerpc/mpc85xx/platform_mpc85xx.c
==============================================================================
--- head/sys/powerpc/mpc85xx/platform_mpc85xx.c	Wed Dec 30 03:36:22 2015	(r292902)
+++ head/sys/powerpc/mpc85xx/platform_mpc85xx.c	Wed Dec 30 03:43:25 2015	(r292903)
@@ -24,6 +24,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "opt_platform.h"
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
@@ -38,6 +39,7 @@ __FBSDID("$FreeBSD$");
 #include <machine/bus.h>
 #include <machine/cpu.h>
 #include <machine/hid.h>
+#include <machine/machdep.h>
 #include <machine/platform.h>
 #include <machine/platformvar.h>
 #include <machine/smp.h>
@@ -175,6 +177,9 @@ mpc85xx_attach(platform_t plat)
 	}
 	ccsrbar_va = pmap_early_io_map(ccsrbar, ccsrsize);
 
+	mpc85xx_fix_errata(ccsrbar_va);
+	mpc85xx_enable_l3_cache();
+
 	/*
 	 * Clear local access windows. Skip DRAM entries, so we don't shoot
 	 * ourselves in the foot.
@@ -182,14 +187,14 @@ mpc85xx_attach(platform_t plat)
 	law_max = law_getmax();
 	for (i = 0; i < law_max; i++) {
 		sr = ccsr_read4(OCP85XX_LAWSR(i));
-		if ((sr & 0x80000000) == 0)
+		if ((sr & OCP85XX_ENA_MASK) == 0)
 			continue;
 		tgt = (sr & 0x01f00000) >> 20;
 		if (tgt == OCP85XX_TGTIF_RAM1 || tgt == OCP85XX_TGTIF_RAM2 ||
 		    tgt == OCP85XX_TGTIF_RAM_INTL)
 			continue;
 
-		ccsr_write4(OCP85XX_LAWSR(i), sr & 0x7fffffff);
+		ccsr_write4(OCP85XX_LAWSR(i), sr & OCP85XX_DIS_MASK);
 	}
 
 	return (0);
@@ -256,7 +261,11 @@ mpc85xx_timebase_freq(platform_t plat, s
 	 * HID0[SEL_TBCLK] = 0
 	 */
 	if (freq != 0)
+#ifdef QORIQ_DPAA
+		ticks = freq / 32;
+#else
 		ticks = freq / 8;
+#endif
 
 out:
 	if (ticks <= 0)
@@ -309,17 +318,37 @@ mpc85xx_smp_start_cpu(platform_t plat, s
 {
 #ifdef SMP
 	uint32_t *tlb1;
-	uint32_t bptr, eebpcr;
+	vm_paddr_t bptr;
+	uint32_t reg;
 	int i, timeout;
+	uintptr_t brr;
+	int cpuid;
+
+#ifdef QORIQ_DPAA
+	uint32_t tgt;
 
-	eebpcr = ccsr_read4(OCP85XX_EEBPCR);
-	if ((eebpcr & (1 << (pc->pc_cpuid + 24))) != 0) {
+	reg = ccsr_read4(OCP85XX_COREDISR);
+	cpuid = pc->pc_cpuid;
+
+	if ((reg & cpuid) != 0) {
+		printf("%s: CPU %d is disabled!\n", __func__, pc->pc_cpuid);
+		return (-1);
+	}
+
+	brr = OCP85XX_BRR;
+#else /* QORIQ_DPAA */
+	brr = OCP85XX_EEBPCR;
+	cpuid = pc->pc_cpuid + 24;
+#endif
+	reg = ccsr_read4(brr);
+	if ((reg & (1 << cpuid)) != 0) {
 		printf("SMP: CPU %d already out of hold-off state!\n",
 		    pc->pc_cpuid);
 		return (ENXIO);
 	}
 
 	ap_pcpu = pc;
+	__asm __volatile("msync; isync");
 
 	i = 0;
 	tlb1 = bp_tlb1;
@@ -335,24 +364,67 @@ mpc85xx_smp_start_cpu(platform_t plat, s
 	if (i < bp_ntlb1s)
 		bp_ntlb1s = i;
 
+	/* Flush caches to have our changes hit DRAM. */
+	cpu_flush_dcache(__boot_page, 4096);
+
+	bptr = ((vm_paddr_t)(uintptr_t)__boot_page - KERNBASE) + kernload;
+	KASSERT((bptr & 0xfff) == 0,
+	    ("%s: boot page is not aligned (%#jx)", __func__, (uintmax_t)bptr));
+#ifdef QORIQ_DPAA
+
+	/*
+	 * Read DDR controller configuration to select proper BPTR target ID.
+	 *
+	 * On P5020 bit 29 of DDR1_CS0_CONFIG enables DDR controllers
+	 * interleaving. If this bit is set, we have to use
+	 * OCP85XX_TGTIF_RAM_INTL as BPTR target ID. On other QorIQ DPAA SoCs,
+	 * this bit is reserved and always 0.
+	 */
+
+	reg = ccsr_read4(OCP85XX_DDR1_CS0_CONFIG);
+	if (reg & (1 << 29))
+		tgt = OCP85XX_TGTIF_RAM_INTL;
+	else
+		tgt = OCP85XX_TGTIF_RAM1;
+
+	/*
+	 * Set BSTR to the physical address of the boot page
+	 */
+	ccsr_write4(OCP85XX_BSTRH, bptr >> 32);
+	ccsr_write4(OCP85XX_BSTRL, bptr);
+	ccsr_write4(OCP85XX_BSTAR, OCP85XX_ENA_MASK |
+	    (tgt << OCP85XX_TRGT_SHIFT) | (ffsl(PAGE_SIZE) - 2));
+
+	/* Read back OCP85XX_BSTAR to synchronize write */
+	ccsr_read4(OCP85XX_BSTAR);
+
+	/*
+	 * Enable and configure time base on new CPU.
+	 */
+
+	/* Set TB clock source to platform clock / 32 */
+	reg = ccsr_read4(CCSR_CTBCKSELR);
+	ccsr_write4(CCSR_CTBCKSELR, reg & ~(1 << pc->pc_cpuid));
+
+	/* Enable TB */
+	reg = ccsr_read4(CCSR_CTBENR);
+	ccsr_write4(CCSR_CTBENR, reg | (1 << pc->pc_cpuid));
+#else
+
 	/*
 	 * Set BPTR to the physical address of the boot page
 	 */
-	bptr = ((uint32_t)__boot_page - KERNBASE) + kernload;
-	KASSERT((bptr & 0xfff) == 0,
-	    ("%s: boot page is not aligned (%#x)", __func__, bptr));
 	bptr = (bptr >> 12) | 0x80000000u;
 	ccsr_write4(OCP85XX_BPTR, bptr);
 	__asm __volatile("isync; msync");
 
-	/* Flush caches to have our changes hit DRAM. */
-	cpu_flush_dcache(__boot_page, 4096);
+#endif /* QORIQ_DPAA */
 
 	/*
 	 * Release AP from hold-off state
 	 */
-	eebpcr |= (1 << (pc->pc_cpuid + 24));
-	ccsr_write4(OCP85XX_EEBPCR, eebpcr);
+	reg = ccsr_read4(brr);
+	ccsr_write4(brr, reg | (1 << cpuid));
 	__asm __volatile("isync; msync");
 
 	timeout = 500;
@@ -364,7 +436,11 @@ mpc85xx_smp_start_cpu(platform_t plat, s
 	 * address (= 0xfffff000) isn't permanently remapped and thus not
 	 * usable otherwise.
 	 */
+#ifdef QORIQ_DPAA
+	ccsr_write4(OCP85XX_BSTAR, 0);
+#else
 	ccsr_write4(OCP85XX_BPTR, 0);
+#endif
 	__asm __volatile("isync; msync");
 
 	if (!pc->pc_awake)


More information about the svn-src-all mailing list