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
This commit is contained in:
parent
95fd2c39d8
commit
0ecd3402cf
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
@ -730,6 +730,113 @@ ENTRY(icache_enable)
|
||||
isync
|
||||
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@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@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@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()
|
||||
*
|
||||
|
@ -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;
|
||||
uint32_t csr;
|
||||
|
||||
/* 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");
|
||||
}
|
||||
}
|
||||
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
|
||||
|
@ -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 *trgt_mem, int *trgt_io)
|
||||
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;
|
||||
}
|
||||
|
@ -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
|
||||
@ -83,6 +103,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
|
||||
*/
|
||||
@ -110,4 +144,8 @@ int law_pci_target(struct resource *, int *, int *);
|
||||
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_ */
|
||||
|
@ -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, struct cpuref *cpuref)
|
||||
* 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, struct pcpu *pc)
|
||||
{
|
||||
#ifdef SMP
|
||||
uint32_t *tlb1;
|
||||
uint32_t bptr, eebpcr;
|
||||
vm_paddr_t bptr;
|
||||
uint32_t reg;
|
||||
int i, timeout;
|
||||
uintptr_t brr;
|
||||
int cpuid;
|
||||
|
||||
eebpcr = ccsr_read4(OCP85XX_EEBPCR);
|
||||
if ((eebpcr & (1 << (pc->pc_cpuid + 24))) != 0) {
|
||||
#ifdef QORIQ_DPAA
|
||||
uint32_t tgt;
|
||||
|
||||
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, struct pcpu *pc)
|
||||
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, struct pcpu *pc)
|
||||
* 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)
|
||||
|
Loading…
Reference in New Issue
Block a user