Commit 9287b95e authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt

Merge remote-tracking branch 'scott/next' into next

Scott writes:

Highlights include e6500 hardware threading support, an e6500 TLB erratum
workaround, corenet error reporting, support for a new board, and some
minor fixes.
parents ea668936 78eb9094
......@@ -84,3 +84,19 @@ Example:
compatible = "fsl,bsc9132qds-fpga", "fsl,fpga-qixis-i2c";
reg = <0x66>;
};
* Freescale on-board CPLD
Some Freescale boards like T1040RDB have an on board CPLD connected.
Required properties:
- compatible: Should be a board-specific string like "fsl,<board>-cpld"
Example:
"fsl,t1040rdb-cpld", "fsl,t1042rdb-cpld", "fsl,t1042rdb_pi-cpld"
- reg: should describe CPLD registers
Example:
cpld@3,0 {
compatible = "fsl,t1040rdb-cpld";
reg = <3 0 0x300>;
};
/*
* T2080PCIe-RDB Board Device Tree Source
*
* Copyright 2014 Freescale Semiconductor Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Freescale Semiconductor nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") as published by the Free Software
* Foundation, either version 2 of that License or (at your option) any
* later version.
*
* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/include/ "fsl/t208xsi-pre.dtsi"
/include/ "t208xrdb.dtsi"
/ {
model = "fsl,T2080RDB";
compatible = "fsl,T2080RDB";
#address-cells = <2>;
#size-cells = <2>;
interrupt-parent = <&mpic>;
rio: rapidio@ffe0c0000 {
reg = <0xf 0xfe0c0000 0 0x11000>;
port1 {
ranges = <0 0 0xc 0x20000000 0 0x10000000>;
};
port2 {
ranges = <0 0 0xc 0x30000000 0 0x10000000>;
};
};
};
/include/ "fsl/t2080si-post.dtsi"
/*
* T2080PCIe-RDB Board Device Tree Source
*
* Copyright 2014 Freescale Semiconductor Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Freescale Semiconductor nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") as published by the Free Software
* Foundation, either version 2 of that License or (at your option) any
* later version.
*
* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/ {
model = "fsl,T2080RDB";
compatible = "fsl,T2080RDB";
#address-cells = <2>;
#size-cells = <2>;
interrupt-parent = <&mpic>;
ifc: localbus@ffe124000 {
reg = <0xf 0xfe124000 0 0x2000>;
ranges = <0 0 0xf 0xe8000000 0x08000000
2 0 0xf 0xff800000 0x00010000
3 0 0xf 0xffdf0000 0x00008000>;
nor@0,0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cfi-flash";
reg = <0x0 0x0 0x8000000>;
bank-width = <2>;
device-width = <1>;
};
nand@1,0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "fsl,ifc-nand";
reg = <0x2 0x0 0x10000>;
};
boardctrl: board-control@2,0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "fsl,t2080-cpld";
reg = <3 0 0x300>;
ranges = <0 3 0 0x300>;
};
};
memory {
device_type = "memory";
};
dcsr: dcsr@f00000000 {
ranges = <0x00000000 0xf 0x00000000 0x01072000>;
};
soc: soc@ffe000000 {
ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
reg = <0xf 0xfe000000 0 0x00001000>;
spi@110000 {
flash@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "micron,n25q512a";
reg = <0>;
spi-max-frequency = <10000000>; /* input clock */
};
};
i2c@118000 {
adt7481@4c {
compatible = "adi,adt7481";
reg = <0x4c>;
};
rtc@68 {
compatible = "dallas,ds1339";
reg = <0x68>;
interrupts = <0x1 0x1 0 0>;
};
eeprom@50 {
compatible = "atmel,24c256";
reg = <0x50>;
};
};
i2c@118100 {
pca9546@77 {
compatible = "nxp,pca9546";
reg = <0x77>;
};
};
sdhc@114000 {
voltage-ranges = <1800 1800 3300 3300>;
};
};
pci0: pcie@ffe240000 {
reg = <0xf 0xfe240000 0 0x10000>;
ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
0 0x20000000
0x01000000 0 0x00000000
0x01000000 0 0x00000000
0 0x00010000>;
};
};
pci1: pcie@ffe250000 {
reg = <0xf 0xfe250000 0 0x10000>;
ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x10000000
0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
0 0x20000000
0x01000000 0 0x00000000
0x01000000 0 0x00000000
0 0x00010000>;
};
};
pci2: pcie@ffe260000 {
reg = <0xf 0xfe260000 0 0x1000>;
ranges = <0x02000000 0 0xe0000000 0xc 0x30000000 0 0x10000000
0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
0 0x20000000
0x01000000 0 0x00000000
0x01000000 0 0x00000000
0 0x00010000>;
};
};
pci3: pcie@ffe270000 {
reg = <0xf 0xfe270000 0 0x10000>;
ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x10000000
0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
0 0x20000000
0x01000000 0 0x00000000
0x01000000 0 0x00000000
0 0x00010000>;
};
};
};
......@@ -180,3 +180,4 @@ CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_AES=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_DEV_FSL_CAAM=y
CONFIG_FSL_CORENET_CF=y
......@@ -179,3 +179,4 @@ CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_DEV_FSL_CAAM=y
CONFIG_FSL_CORENET_CF=y
......@@ -391,7 +391,7 @@ extern const char *powerpc_base_platform;
CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_CELL_TB_BUG)
CPU_FTR_CELL_TB_BUG | CPU_FTR_SMT)
#define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
/* 64-bit CPUs */
......
......@@ -150,8 +150,10 @@
#define PPC_INST_MCRXR_MASK 0xfc0007fe
#define PPC_INST_MFSPR_PVR 0x7c1f42a6
#define PPC_INST_MFSPR_PVR_MASK 0xfc1fffff
#define PPC_INST_MFTMR 0x7c0002dc
#define PPC_INST_MSGSND 0x7c00019c
#define PPC_INST_MSGSNDP 0x7c00011c
#define PPC_INST_MTTMR 0x7c0003dc
#define PPC_INST_NOP 0x60000000
#define PPC_INST_POPCNTB 0x7c0000f4
#define PPC_INST_POPCNTB_MASK 0xfc0007fe
......@@ -369,4 +371,11 @@
#define TABORT(r) stringify_in_c(.long PPC_INST_TABORT \
| __PPC_RA(r))
/* book3e thread control instructions */
#define TMRN(x) ((((x) & 0x1f) << 16) | (((x) & 0x3e0) << 6))
#define MTTMR(tmr, r) stringify_in_c(.long PPC_INST_MTTMR | \
TMRN(tmr) | ___PPC_RS(r))
#define MFTMR(tmr, r) stringify_in_c(.long PPC_INST_MFTMR | \
TMRN(tmr) | ___PPC_RT(r))
#endif /* _ASM_POWERPC_PPC_OPCODE_H */
......@@ -15,16 +15,28 @@
#ifndef __ASM_POWERPC_REG_BOOKE_H__
#define __ASM_POWERPC_REG_BOOKE_H__
#include <asm/ppc-opcode.h>
/* Machine State Register (MSR) Fields */
#define MSR_GS (1<<28) /* Guest state */
#define MSR_UCLE (1<<26) /* User-mode cache lock enable */
#define MSR_SPE (1<<25) /* Enable SPE */
#define MSR_DWE (1<<10) /* Debug Wait Enable */
#define MSR_UBLE (1<<10) /* BTB lock enable (e500) */
#define MSR_IS MSR_IR /* Instruction Space */
#define MSR_DS MSR_DR /* Data Space */
#define MSR_PMM (1<<2) /* Performance monitor mark bit */
#define MSR_CM (1<<31) /* Computation Mode (0=32-bit, 1=64-bit) */
#define MSR_GS_LG 28 /* Guest state */
#define MSR_UCLE_LG 26 /* User-mode cache lock enable */
#define MSR_SPE_LG 25 /* Enable SPE */
#define MSR_DWE_LG 10 /* Debug Wait Enable */
#define MSR_UBLE_LG 10 /* BTB lock enable (e500) */
#define MSR_IS_LG MSR_IR_LG /* Instruction Space */
#define MSR_DS_LG MSR_DR_LG /* Data Space */
#define MSR_PMM_LG 2 /* Performance monitor mark bit */
#define MSR_CM_LG 31 /* Computation Mode (0=32-bit, 1=64-bit) */
#define MSR_GS __MASK(MSR_GS_LG)
#define MSR_UCLE __MASK(MSR_UCLE_LG)
#define MSR_SPE __MASK(MSR_SPE_LG)
#define MSR_DWE __MASK(MSR_DWE_LG)
#define MSR_UBLE __MASK(MSR_UBLE_LG)
#define MSR_IS __MASK(MSR_IS_LG)
#define MSR_DS __MASK(MSR_DS_LG)
#define MSR_PMM __MASK(MSR_PMM_LG)
#define MSR_CM __MASK(MSR_CM_LG)
#if defined(CONFIG_PPC_BOOK3E_64)
#define MSR_64BIT MSR_CM
......@@ -598,6 +610,13 @@
/* Bit definitions for L1CSR2. */
#define L1CSR2_DCWS 0x40000000 /* Data Cache write shadow */
/* Bit definitions for BUCSR. */
#define BUCSR_STAC_EN 0x01000000 /* Segment Target Address Cache */
#define BUCSR_LS_EN 0x00400000 /* Link Stack */
#define BUCSR_BBFI 0x00000200 /* Branch Buffer flash invalidate */
#define BUCSR_BPEN 0x00000001 /* Branch prediction enable */
#define BUCSR_INIT (BUCSR_STAC_EN | BUCSR_LS_EN | BUCSR_BBFI | BUCSR_BPEN)
/* Bit definitions for L2CSR0. */
#define L2CSR0_L2E 0x80000000 /* L2 Cache Enable */
#define L2CSR0_L2PE 0x40000000 /* L2 Cache Parity/ECC Enable */
......@@ -721,5 +740,23 @@
#define MMUBE1_VBE4 0x00000002
#define MMUBE1_VBE5 0x00000001
#define TMRN_IMSR0 0x120 /* Initial MSR Register 0 (e6500) */
#define TMRN_IMSR1 0x121 /* Initial MSR Register 1 (e6500) */
#define TMRN_INIA0 0x140 /* Next Instruction Address Register 0 */
#define TMRN_INIA1 0x141 /* Next Instruction Address Register 1 */
#define SPRN_TENSR 0x1b5 /* Thread Enable Status Register */
#define SPRN_TENS 0x1b6 /* Thread Enable Set Register */
#define SPRN_TENC 0x1b7 /* Thread Enable Clear Register */
#define TEN_THREAD(x) (1 << (x))
#ifndef __ASSEMBLY__
#define mftmr(rn) ({unsigned long rval; \
asm volatile(MFTMR(rn, %0) : "=r" (rval)); rval;})
#define mttmr(rn, v) asm volatile(MTTMR(rn, %0) : \
: "r" ((unsigned long)(v)) \
: "memory")
#endif /* !__ASSEMBLY__ */
#endif /* __ASM_POWERPC_REG_BOOKE_H__ */
#endif /* __KERNEL__ */
......@@ -180,6 +180,28 @@ exception_marker:
#include "exceptions-64s.S"
#endif
#ifdef CONFIG_PPC_BOOK3E
_GLOBAL(fsl_secondary_thread_init)
/* Enable branch prediction */
lis r3,BUCSR_INIT@h
ori r3,r3,BUCSR_INIT@l
mtspr SPRN_BUCSR,r3
isync
/*
* Fix PIR to match the linear numbering in the device tree.
*
* On e6500, the reset value of PIR uses the low three bits for
* the thread within a core, and the upper bits for the core
* number. There are two threads per core, so shift everything
* but the low bit right by two bits so that the cpu numbering is
* continuous.
*/
mfspr r3, SPRN_PIR
rlwimi r3, r3, 30, 2, 30
mtspr SPRN_PIR, r3
#endif
_GLOBAL(generic_secondary_thread_init)
mr r24,r3
......
......@@ -308,12 +308,10 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
/* Get physical cpuid */
intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len);
if (intserv) {
nthreads = len / sizeof(int);
} else {
intserv = of_get_flat_dt_prop(node, "reg", NULL);
nthreads = 1;
}
if (!intserv)
intserv = of_get_flat_dt_prop(node, "reg", &len);
nthreads = len / sizeof(int);
/*
* Now see if any of these threads match our boot cpu.
......
......@@ -456,18 +456,20 @@ void __init smp_setup_cpu_maps(void)
intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s",
&len);
if (intserv) {
nthreads = len / sizeof(int);
DBG(" ibm,ppc-interrupt-server#s -> %d threads\n",
nthreads);
} else {
DBG(" no ibm,ppc-interrupt-server#s -> 1 thread\n");
intserv = of_get_property(dn, "reg", NULL);
intserv = of_get_property(dn, "reg", &len);
if (!intserv) {
cpu_be = cpu_to_be32(cpu);
intserv = &cpu_be; /* assume logical == phys */
len = 4;
}
}
nthreads = len / sizeof(int);
for (j = 0; j < nthreads && cpu < nr_cpu_ids; j++) {
bool avail;
......
......@@ -511,7 +511,11 @@ void __init setup_system(void)
check_smt_enabled();
setup_tlb_core_data();
#ifdef CONFIG_SMP
/*
* Freescale Book3e parts spin in a loop provided by firmware,
* so smp_release_cpus() does nothing for them
*/
#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_FSL_BOOK3E)
/* Release secondary cpus out of their spinloops at 0x60 now that
* we can map physical -> logical CPU ids
*/
......
......@@ -299,7 +299,9 @@ itlb_miss_fault_bolted:
* r10 = crap (free to use)
*/
tlb_miss_common_e6500:
BEGIN_FTR_SECTION
crmove cr2*4+2,cr0*4+2 /* cr2.eq != 0 if kernel address */
BEGIN_FTR_SECTION /* CPU_FTR_SMT */
/*
* Search if we already have an indirect entry for that virtual
* address, and if we do, bail out.
......@@ -324,17 +326,62 @@ BEGIN_FTR_SECTION
b 1b
.previous
/*
* Erratum A-008139 says that we can't use tlbwe to change
* an indirect entry in any way (including replacing or
* invalidating) if the other thread could be in the process
* of a lookup. The workaround is to invalidate the entry
* with tlbilx before overwriting.
*/
lbz r15,TCD_ESEL_NEXT(r11)
rlwinm r10,r15,16,0xff0000
oris r10,r10,MAS0_TLBSEL(1)@h
mtspr SPRN_MAS0,r10
isync
tlbre
mfspr r15,SPRN_MAS1
mfspr r10,SPRN_MAS2
andis. r15,r15,MAS1_VALID@h
beq 5f
BEGIN_FTR_SECTION_NESTED(532)
mfspr r10,SPRN_MAS8
rlwinm r10,r10,0,0x80000fff /* tgs,tlpid -> sgs,slpid */
mtspr SPRN_MAS5,r10
END_FTR_SECTION_NESTED(CPU_FTR_EMB_HV,CPU_FTR_EMB_HV,532)
tlbsx 0,r16
mtspr SPRN_MAS2,r10
mfspr r10,SPRN_MAS1
mtspr SPRN_MAS1,r15
rlwinm r15,r10,0,0x3fff0000 /* tid -> spid */
rlwimi r15,r10,20,0x00000003 /* ind,ts -> sind,sas */
mfspr r10,SPRN_MAS6
mtspr SPRN_MAS6,r15
mfspr r15,SPRN_MAS2
isync
tlbilxva 0,r15
isync
mtspr SPRN_MAS6,r10
andis. r10,r10,MAS1_VALID@h
5:
BEGIN_FTR_SECTION_NESTED(532)
li r10,0
mtspr SPRN_MAS8,r10
mtspr SPRN_MAS5,r10
END_FTR_SECTION_NESTED(CPU_FTR_EMB_HV,CPU_FTR_EMB_HV,532)
tlbsx 0,r16
mfspr r10,SPRN_MAS1
andis. r15,r10,MAS1_VALID@h
bne tlb_miss_done_e6500
END_FTR_SECTION_IFSET(CPU_FTR_SMT)
FTR_SECTION_ELSE
mfspr r10,SPRN_MAS1
ALT_FTR_SECTION_END_IFSET(CPU_FTR_SMT)
oris r10,r10,MAS1_VALID@h
beq cr2,4f
rlwinm r10,r10,0,16,1 /* Clear TID */
4: mtspr SPRN_MAS1,r10
/* Now, we need to walk the page tables. First check if we are in
* range.
......@@ -410,12 +457,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_SMT)
rfi
tlb_miss_kernel_e6500:
mfspr r10,SPRN_MAS1
ld r14,PACA_KERNELPGD(r13)
cmpldi cr0,r15,8 /* Check for vmalloc region */
rlwinm r10,r10,0,16,1 /* Clear TID */
mtspr SPRN_MAS1,r10
beq+ tlb_miss_common_e6500
cmpldi cr1,r15,8 /* Check for vmalloc region */
beq+ cr1,tlb_miss_common_e6500
tlb_miss_fault_e6500:
tlb_unlock_e6500
......
......@@ -274,7 +274,7 @@ config CORENET_GENERIC
For 32bit kernel, the following boards are supported:
P2041 RDB, P3041 DS, P4080 DS, kmcoge4, and OCA4080
For 64bit kernel, the following boards are supported:
T208x QDS, T4240 QDS/RDB and B4 QDS
T208x QDS/RDB, T4240 QDS/RDB and B4 QDS
The following boards are supported for both 32bit and 64bit kernel:
P5020 DS, P5040 DS and T104xQDS
......
......@@ -120,6 +120,7 @@ static const char * const boards[] __initconst = {
"fsl,P5020DS",
"fsl,P5040DS",
"fsl,T2080QDS",
"fsl,T2080RDB",
"fsl,T2081QDS",
"fsl,T4240QDS",
"fsl,T4240RDB",
......
......@@ -28,6 +28,7 @@
#include <asm/dbell.h>
#include <asm/fsl_guts.h>
#include <asm/code-patching.h>
#include <asm/cputhreads.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/mpic.h>
......@@ -168,6 +169,24 @@ static inline u32 read_spin_table_addr_l(void *spin_table)
return in_be32(&((struct epapr_spin_table *)spin_table)->addr_l);
}
#ifdef CONFIG_PPC64
static void wake_hw_thread(void *info)
{
void fsl_secondary_thread_init(void);
unsigned long imsr1, inia1;
int nr = *(const int *)info;
imsr1 = MSR_KERNEL;
inia1 = *(unsigned long *)fsl_secondary_thread_init;
mttmr(TMRN_IMSR1, imsr1);
mttmr(TMRN_INIA1, inia1);
mtspr(SPRN_TENS, TEN_THREAD(1));
smp_generic_kick_cpu(nr);
}
#endif
static int smp_85xx_kick_cpu(int nr)
{
unsigned long flags;
......@@ -183,6 +202,31 @@ static int smp_85xx_kick_cpu(int nr)
pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr);
#ifdef CONFIG_PPC64
/* Threads don't use the spin table */
if (cpu_thread_in_core(nr) != 0) {
int primary = cpu_first_thread_sibling(nr);
if (WARN_ON_ONCE(!cpu_has_feature(CPU_FTR_SMT)))
return -ENOENT;
if (cpu_thread_in_core(nr) != 1) {
pr_err("%s: cpu %d: invalid hw thread %d\n",
__func__, nr, cpu_thread_in_core(nr));
return -ENOENT;
}
if (!cpu_online(primary)) {
pr_err("%s: cpu %d: primary %d not online\n",
__func__, nr, primary);
return -ENOENT;
}
smp_call_function_single(primary, wake_hw_thread, &nr, 0);
return 0;
}
#endif
np = of_get_cpu_node(nr, NULL);
cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL);
......
......@@ -853,8 +853,8 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose)
in = pcie->cfg_type0 + PEX_RC_INWIN_BASE;
for (i = 0; i < 4; i++) {
/* not enabled, skip */
if (!in_le32(&in[i].ar) & PEX_RCIWARn_EN)
continue;
if (!(in_le32(&in[i].ar) & PEX_RCIWARn_EN))
continue;
if (get_immrbase() == in_le32(&in[i].tar))
return (u64)in_le32(&in[i].barh) << 32 |
......
......@@ -184,7 +184,7 @@ static int mpic_msgr_probe(struct platform_device *dev)
dev_info(&dev->dev, "Found %d message registers\n",
mpic_msgr_count);
mpic_msgrs = kzalloc(sizeof(struct mpic_msgr) * mpic_msgr_count,
mpic_msgrs = kcalloc(mpic_msgr_count, sizeof(*mpic_msgrs),
GFP_KERNEL);
if (!mpic_msgrs) {
dev_err(&dev->dev,
......
......@@ -61,6 +61,16 @@ config TEGRA30_MC
analysis, especially for IOMMU/SMMU(System Memory Management
Unit) module.
config FSL_CORENET_CF
tristate "Freescale CoreNet Error Reporting"
depends on FSL_SOC_BOOKE
help
Say Y for reporting of errors from the Freescale CoreNet
Coherency Fabric. Errors reported include accesses to
physical addresses that mapped by no local access window
(LAW) or an invalid LAW, as well as bad cache state that
represents a coherency violation.
config FSL_IFC
bool
depends on FSL_SOC
......
......@@ -7,6 +7,7 @@ obj-$(CONFIG_OF) += of_memory.o
endif
obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
obj-$(CONFIG_TI_EMIF) += emif.o
obj-$(CONFIG_FSL_CORENET_CF) += fsl-corenet-cf.o
obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o
obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o
......
/*
* CoreNet Coherency Fabric error reporting
*
* Copyright 2014 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 Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
enum ccf_version {
CCF1,
CCF2,
};
struct ccf_info {
enum ccf_version version;
int err_reg_offs;
};
static const struct ccf_info ccf1_info = {
.version = CCF1,
.err_reg_offs = 0xa00,
};
static const struct ccf_info ccf2_info = {
.version = CCF2,
.err_reg_offs = 0xe40,
};
static const struct of_device_id ccf_matches[] = {
{
.compatible = "fsl,corenet1-cf",
.data = &ccf1_info,
},
{
.compatible = "fsl,corenet2-cf",
.data = &ccf2_info,
},
{}
};
struct ccf_err_regs {
u32 errdet; /* 0x00 Error Detect Register */
/* 0x04 Error Enable (ccf1)/Disable (ccf2) Register */
u32 errdis;
/* 0x08 Error Interrupt Enable Register (ccf2 only) */
u32 errinten;
u32 cecar; /* 0x0c Error Capture Attribute Register */
u32 cecaddrh; /* 0x10 Error Capture Address High */
u32 cecaddrl; /* 0x14 Error Capture Address Low */
u32 cecar2; /* 0x18 Error Capture Attribute Register 2 */
};
/* LAE/CV also valid for errdis and errinten */
#define ERRDET_LAE (1 << 0) /* Local Access Error */
#define ERRDET_CV (1 << 1) /* Coherency Violation */
#define ERRDET_CTYPE_SHIFT 26 /* Capture Type (ccf2 only) */
#define ERRDET_CTYPE_MASK (0x1f << ERRDET_CTYPE_SHIFT)
#define ERRDET_CAP (1 << 31) /* Capture Valid (ccf2 only) */
#define CECAR_VAL (1 << 0) /* Valid (ccf1 only) */
#define CECAR_UVT (1 << 15) /* Unavailable target ID (ccf1) */
#define CECAR_SRCID_SHIFT_CCF1 24
#define CECAR_SRCID_MASK_CCF1 (0xff << CECAR_SRCID_SHIFT_CCF1)
#define CECAR_SRCID_SHIFT_CCF2 18
#define CECAR_SRCID_MASK_CCF2 (0xff << CECAR_SRCID_SHIFT_CCF2)
#define CECADDRH_ADDRH 0xff
struct ccf_private {
const struct ccf_info *info;
struct device *dev;
void __iomem *regs;
struct ccf_err_regs __iomem *err_regs;
};
static irqreturn_t ccf_irq(int irq, void *dev_id)
{
struct ccf_private *ccf = dev_id;
static DEFINE_RATELIMIT_STATE(ratelimit, DEFAULT_RATELIMIT_INTERVAL,
DEFAULT_RATELIMIT_BURST);
u32 errdet, cecar, cecar2;
u64 addr;
u32 src_id;
bool uvt = false;
bool cap_valid = false;
errdet = ioread32be(&ccf->err_regs->errdet);
cecar = ioread32be(&ccf->err_regs->cecar);
cecar2 = ioread32be(&ccf->err_regs->cecar2);
addr = ioread32be(&ccf->err_regs->cecaddrl);
addr |= ((u64)(ioread32be(&ccf->err_regs->cecaddrh) &
CECADDRH_ADDRH)) << 32;
if (!__ratelimit(&ratelimit))
goto out;
switch (ccf->info->version) {
case CCF1:
if (cecar & CECAR_VAL) {
if (cecar & CECAR_UVT)
uvt = true;
src_id = (cecar & CECAR_SRCID_MASK_CCF1) >>
CECAR_SRCID_SHIFT_CCF1;
cap_valid = true;
}
break;
case CCF2:
if (errdet & ERRDET_CAP) {
src_id = (cecar & CECAR_SRCID_MASK_CCF2) >>
CECAR_SRCID_SHIFT_CCF2;
cap_valid = true;
}
break;
}
dev_crit(ccf->dev, "errdet 0x%08x cecar 0x%08x cecar2 0x%08x\n",
errdet, cecar, cecar2);
if (errdet & ERRDET_LAE) {
if (uvt)
dev_crit(ccf->dev, "LAW Unavailable Target ID\n");
else
dev_crit(ccf->dev, "Local Access Window Error\n");
}
if (errdet & ERRDET_CV)
dev_crit(ccf->dev, "Coherency Violation\n");
if (cap_valid) {
dev_crit(ccf->dev, "address 0x%09llx, src id 0x%x\n",
addr, src_id);
}
out:
iowrite32be(errdet, &ccf->err_regs->errdet);
return errdet ? IRQ_HANDLED : IRQ_NONE;
}
static int ccf_probe(struct platform_device *pdev)
{
struct ccf_private *ccf;
struct resource *r;
const struct of_device_id *match;
int ret, irq;
match = of_match_device(ccf_matches, &pdev->dev);
if (WARN_ON(!match))
return -ENODEV;
ccf = devm_kzalloc(&pdev->dev, sizeof(*ccf), GFP_KERNEL);
if (!ccf)
return -ENOMEM;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) {
dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
return -ENXIO;
}
ccf->regs = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(ccf->regs)) {
dev_err(&pdev->dev, "%s: can't map mem resource\n", __func__);
return PTR_ERR(ccf->regs);
}
ccf->dev = &pdev->dev;
ccf->info = match->data;
ccf->err_regs = ccf->regs + ccf->info->err_reg_offs;
dev_set_drvdata(&pdev->dev, ccf);
irq = platform_get_irq(pdev, 0);
if (!irq) {
dev_err(&pdev->dev, "%s: no irq\n", __func__);
return -ENXIO;
}
ret = devm_request_irq(&pdev->dev, irq, ccf_irq, 0, pdev->name, ccf);
if (ret) {
dev_err(&pdev->dev, "%s: can't request irq\n", __func__);
return ret;
}
switch (ccf->info->version) {
case CCF1:
/* On CCF1 this register enables rather than disables. */
iowrite32be(ERRDET_LAE | ERRDET_CV, &ccf->err_regs->errdis);
break;
case CCF2:
iowrite32be(0, &ccf->err_regs->errdis);
iowrite32be(ERRDET_LAE | ERRDET_CV, &ccf->err_regs->errinten);
break;
}
return 0;
}
static int ccf_remove(struct platform_device *pdev)
{
struct ccf_private *ccf = dev_get_drvdata(&pdev->dev);
switch (ccf->info->version) {
case CCF1:
iowrite32be(0, &ccf->err_regs->errdis);
break;
case CCF2:
/*
* We clear errdis on ccf1 because that's the only way to
* disable interrupts, but on ccf2 there's no need to disable
* detection.
*/
iowrite32be(0, &ccf->err_regs->errinten);
break;
}
return 0;
}
static struct platform_driver ccf_driver = {
.driver = {
.name = KBUILD_MODNAME,
.owner = THIS_MODULE,
.of_match_table = ccf_matches,
},
.probe = ccf_probe,
.remove = ccf_remove,
};
module_platform_driver(ccf_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Freescale Semiconductor");
MODULE_DESCRIPTION("Freescale CoreNet Coherency Fabric error reporting");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment