diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-30 17:20:32 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-30 17:20:32 -0800 |
commit | cdfc83075fb76369a31e6c187d0cebcab9f8b9c8 (patch) | |
tree | 33d1cdca3e2cb610451ed30943189f55652bac4c /arch/mips/netlogic/xlp/wakeup.c | |
parent | 04a24ae45d018e177db7e4ae2d03a70f79149782 (diff) | |
parent | b26a21c1eacdb7daf22a304fa857413df2650cfe (diff) |
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle:
"The most notable new addition inside this pull request is the support
for MIPS's latest and greatest core called "inter/proAptiv". The
patch series describes this core as follows.
"The interAptiv is a power-efficient multi-core microprocessor
for use in system-on-chip (SoC) applications. The interAptiv combines
a multi-threading pipeline with a coherence manager to deliver improved
computational throughput and power efficiency. The interAptiv can
contain one to four MIPS32R3 interAptiv cores, system level
coherence manager with L2 cache, optional coherent I/O port,
and optional floating point unit."
The platform specific patches touch all 3 Broadcom families. It adds
support for the new Broadcom/Netlogix XLP9xx Soc, building a common
BCM63XX SMP kernel for all BCM63XX SoCs regardless of core type/count
and full gpio button/led descriptions for BCM47xx.
The rest of the series are cleanups and bug fixes that are MIPS
generic and consist largely of changes that Imgtec/MIPS had published
in their linux-mti-3.10.git stable tree. Random other cleanups and
patches preparing code to be merged in 3.15"
* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (139 commits)
mips: select ARCH_MIGHT_HAVE_PC_SERIO
mips: delete non-required instances of include <linux/init.h>
MIPS: KVM: remove shadow_tlb code
MIPS: KVM: use common EHINV aware UNIQUE_ENTRYHI
mips/ide: flush dcache also if icache does not snoop dcache
MIPS: BCM47XX: fix position of cpu_wait disabling
MIPS: BCM63XX: select correct MIPS_L1_CACHE_SHIFT value
MIPS: update MIPS_L1_CACHE_SHIFT based on MIPS_L1_CACHE_SHIFT_<N>
MIPS: introduce MIPS_L1_CACHE_SHIFT_<N>
MIPS: ZBOOT: gather string functions into string.c
arch/mips/pci: don't check resource with devm_ioremap_resource
arch/mips/lantiq/xway: don't check resource with devm_ioremap_resource
bcma: gpio: don't cast u32 to unsigned long
ssb: gpio: add own IRQ domain
MIPS: BCM47XX: fix sparse warnings in board.c
MIPS: BCM47XX: add board detection for Linksys WRT54GS V1
MIPS: BCM47XX: fix detection for some boards
MIPS: BCM47XX: Enable buttons support on SSB
MIPS: BCM47XX: Convert WNDR4500 to new syntax
MIPS: BCM47XX: Use "timer" trigger for status LEDs
...
Diffstat (limited to 'arch/mips/netlogic/xlp/wakeup.c')
-rw-r--r-- | arch/mips/netlogic/xlp/wakeup.c | 92 |
1 files changed, 70 insertions, 22 deletions
diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c index 682d5638dc01..9a92617a2af5 100644 --- a/arch/mips/netlogic/xlp/wakeup.c +++ b/arch/mips/netlogic/xlp/wakeup.c @@ -32,7 +32,6 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <linux/init.h> #include <linux/kernel.h> #include <linux/threads.h> @@ -47,14 +46,14 @@ #include <asm/netlogic/mips-extns.h> #include <asm/netlogic/xlp-hal/iomap.h> -#include <asm/netlogic/xlp-hal/pic.h> #include <asm/netlogic/xlp-hal/xlp.h> +#include <asm/netlogic/xlp-hal/pic.h> #include <asm/netlogic/xlp-hal/sys.h> static int xlp_wakeup_core(uint64_t sysbase, int node, int core) { uint32_t coremask, value; - int count; + int count, resetreg; coremask = (1 << core); @@ -65,12 +64,24 @@ static int xlp_wakeup_core(uint64_t sysbase, int node, int core) nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, value); } + /* On 9XX, mark coherent first */ + if (cpu_is_xlp9xx()) { + value = nlm_read_sys_reg(sysbase, SYS_9XX_CPU_NONCOHERENT_MODE); + value &= ~coremask; + nlm_write_sys_reg(sysbase, SYS_9XX_CPU_NONCOHERENT_MODE, value); + } + /* Remove CPU Reset */ - value = nlm_read_sys_reg(sysbase, SYS_CPU_RESET); + resetreg = cpu_is_xlp9xx() ? SYS_9XX_CPU_RESET : SYS_CPU_RESET; + value = nlm_read_sys_reg(sysbase, resetreg); value &= ~coremask; - nlm_write_sys_reg(sysbase, SYS_CPU_RESET, value); + nlm_write_sys_reg(sysbase, resetreg, value); + + /* We are done on 9XX */ + if (cpu_is_xlp9xx()) + return 1; - /* Poll for CPU to mark itself coherent */ + /* Poll for CPU to mark itself coherent on other type of XLP */ count = 100000; do { value = nlm_read_sys_reg(sysbase, SYS_CPU_NONCOHERENT_MODE); @@ -84,7 +95,7 @@ static int wait_for_cpus(int cpu, int bootcpu) volatile uint32_t *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY); int i, count, notready; - count = 0x20000000; + count = 0x800000; do { notready = nlm_threads_per_core; for (i = 0; i < nlm_threads_per_core; i++) @@ -98,27 +109,62 @@ static int wait_for_cpus(int cpu, int bootcpu) static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) { struct nlm_soc_info *nodep; - uint64_t syspcibase; - uint32_t syscoremask; + uint64_t syspcibase, fusebase; + uint32_t syscoremask, mask, fusemask; int core, n, cpu; for (n = 0; n < NLM_NR_NODES; n++) { - syspcibase = nlm_get_sys_pcibase(n); - if (nlm_read_reg(syspcibase, 0) == 0xffffffff) - break; + if (n != 0) { + /* check if node exists and is online */ + if (cpu_is_xlp9xx()) { + int b = xlp9xx_get_socbus(n); + pr_info("Node %d SoC PCI bus %d.\n", n, b); + if (b == 0) + break; + } else { + syspcibase = nlm_get_sys_pcibase(n); + if (nlm_read_reg(syspcibase, 0) == 0xffffffff) + break; + } + nlm_node_init(n); + } /* read cores in reset from SYS */ - if (n != 0) - nlm_node_init(n); nodep = nlm_get_node(n); - syscoremask = nlm_read_sys_reg(nodep->sysbase, SYS_CPU_RESET); + + if (cpu_is_xlp9xx()) { + fusebase = nlm_get_fuse_regbase(n); + fusemask = nlm_read_reg(fusebase, FUSE_9XX_DEVCFG6); + mask = 0xfffff; + } else { + fusemask = nlm_read_sys_reg(nodep->sysbase, + SYS_EFUSE_DEVICE_CFG_STATUS0); + switch (read_c0_prid() & 0xff00) { + case PRID_IMP_NETLOGIC_XLP3XX: + mask = 0xf; + break; + case PRID_IMP_NETLOGIC_XLP2XX: + mask = 0x3; + break; + case PRID_IMP_NETLOGIC_XLP8XX: + default: + mask = 0xff; + break; + } + } + + /* + * Fused out cores are set in the fusemask, and the remaining + * cores are renumbered to range 0 .. nactive-1 + */ + syscoremask = (1 << hweight32(~fusemask & mask)) - 1; + /* The boot cpu */ - if (n == 0) { - syscoremask |= 1; + if (n == 0) nodep->coremask = 1; - } - for (core = 0; core < NLM_CORES_PER_NODE; core++) { + pr_info("Node %d - SYS/FUSE coremask %x\n", n, syscoremask); + for (core = 0; core < nlm_cores_per_node(); core++) { /* we will be on node 0 core 0 */ if (n == 0 && core == 0) continue; @@ -128,7 +174,7 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) continue; /* see if at least the first hw thread is enabled */ - cpu = (n * NLM_CORES_PER_NODE + core) + cpu = (n * nlm_cores_per_node() + core) * NLM_THREADS_PER_CORE; if (!cpumask_test_cpu(cpu, wakeup_mask)) continue; @@ -141,7 +187,8 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) nodep->coremask |= 1u << core; /* spin until the hw threads sets their ready */ - wait_for_cpus(cpu, 0); + if (!wait_for_cpus(cpu, 0)) + pr_err("Node %d : timeout core %d\n", n, core); } } } @@ -153,7 +200,8 @@ void xlp_wakeup_secondary_cpus() * first wakeup core 0 threads */ xlp_boot_core0_siblings(); - wait_for_cpus(0, 0); + if (!wait_for_cpus(0, 0)) + pr_err("Node 0 : timeout core 0\n"); /* now get other cores out of reset */ xlp_enable_secondary_cores(&nlm_cpumask); |