From 65040e224e5b214a93fa0c790add5d69b054ecae Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Wed, 16 Nov 2011 00:21:28 +0000 Subject: MIPS: Netlogic: Add XLP platform files for XLP SoC - Update common files to support XLP. - Add arch/mips/include/asm/netlogic/xlp-hal for register definitions and access macros - Add arch/mips/netlogic/xlp/ for XLP specific files. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2967/ Signed-off-by: Ralf Baechle --- arch/mips/netlogic/xlp/nlm_hal.c | 105 ++++++++++++++++++ arch/mips/netlogic/xlp/platform.c | 108 +++++++++++++++++++ arch/mips/netlogic/xlp/setup.c | 101 ++++++++++++++++++ arch/mips/netlogic/xlp/smpboot.S | 217 ++++++++++++++++++++++++++++++++++++++ arch/mips/netlogic/xlp/wakeup.c | 149 ++++++++++++++++++++++++++ 5 files changed, 680 insertions(+) create mode 100644 arch/mips/netlogic/xlp/nlm_hal.c create mode 100644 arch/mips/netlogic/xlp/platform.c create mode 100644 arch/mips/netlogic/xlp/setup.c create mode 100644 arch/mips/netlogic/xlp/smpboot.S create mode 100644 arch/mips/netlogic/xlp/wakeup.c (limited to 'arch/mips/netlogic/xlp') diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c new file mode 100644 index 000000000000..885f6878594a --- /dev/null +++ b/arch/mips/netlogic/xlp/nlm_hal.c @@ -0,0 +1,105 @@ +/* + * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights + * reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the NetLogic + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``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 NETLOGIC OR CONTRIBUTORS 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 +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +/* These addresses are computed by the nlm_hal_init() */ +uint64_t nlm_io_base; +uint64_t nlm_sys_base; +uint64_t nlm_pic_base; + +/* Main initialization */ +void nlm_hal_init(void) +{ + nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE); + nlm_sys_base = nlm_get_sys_regbase(0); /* node 0 */ + nlm_pic_base = nlm_get_pic_regbase(0); /* node 0 */ +} + +int nlm_irq_to_irt(int irq) +{ + if (!PIC_IRQ_IS_IRT(irq)) + return -1; + + switch (irq) { + case PIC_UART_0_IRQ: + return PIC_IRT_UART_0_INDEX; + case PIC_UART_1_IRQ: + return PIC_IRT_UART_1_INDEX; + default: + return -1; + } +} + +int nlm_irt_to_irq(int irt) +{ + switch (irt) { + case PIC_IRT_UART_0_INDEX: + return PIC_UART_0_IRQ; + case PIC_IRT_UART_1_INDEX: + return PIC_UART_1_IRQ; + default: + return -1; + } +} + +unsigned int nlm_get_cpu_frequency(void) +{ + unsigned int pll_divf, pll_divr, dfs_div, denom; + unsigned int val; + uint64_t num; + + val = nlm_read_sys_reg(nlm_sys_base, SYS_POWER_ON_RESET_CFG); + pll_divf = (val >> 10) & 0x7f; + pll_divr = (val >> 8) & 0x3; + dfs_div = (val >> 17) & 0x3; + + num = pll_divf + 1; + denom = 3 * (pll_divr + 1) * (1 << (dfs_div + 1)); + num = num * 800000000ULL; + do_div(num, denom); + return (unsigned int)num; +} diff --git a/arch/mips/netlogic/xlp/platform.c b/arch/mips/netlogic/xlp/platform.c new file mode 100644 index 000000000000..1f5e4cba891d --- /dev/null +++ b/arch/mips/netlogic/xlp/platform.c @@ -0,0 +1,108 @@ +/* + * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights + * reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the NetLogic + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``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 NETLOGIC OR CONTRIBUTORS 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static unsigned int nlm_xlp_uart_in(struct uart_port *p, int offset) +{ + return nlm_read_reg(p->iobase, offset); +} + +static void nlm_xlp_uart_out(struct uart_port *p, int offset, int value) +{ + nlm_write_reg(p->iobase, offset, value); +} + +#define PORT(_irq) \ + { \ + .irq = _irq, \ + .regshift = 2, \ + .iotype = UPIO_MEM32, \ + .flags = (UPF_SKIP_TEST|UPF_FIXED_TYPE|\ + UPF_BOOT_AUTOCONF), \ + .uartclk = XLP_IO_CLK, \ + .type = PORT_16550A, \ + .serial_in = nlm_xlp_uart_in, \ + .serial_out = nlm_xlp_uart_out, \ + } + +static struct plat_serial8250_port xlp_uart_data[] = { + PORT(PIC_UART_0_IRQ), + PORT(PIC_UART_1_IRQ), + {}, +}; + +static struct platform_device uart_device = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = xlp_uart_data, + }, +}; + +static int __init nlm_platform_uart_init(void) +{ + unsigned long mmio; + + mmio = (unsigned long)nlm_get_uart_regbase(0, 0); + xlp_uart_data[0].iobase = mmio; + xlp_uart_data[0].membase = (void __iomem *)mmio; + xlp_uart_data[0].mapbase = mmio; + + mmio = (unsigned long)nlm_get_uart_regbase(0, 1); + xlp_uart_data[1].iobase = mmio; + xlp_uart_data[1].membase = (void __iomem *)mmio; + xlp_uart_data[1].mapbase = mmio; + + return platform_device_register(&uart_device); +} + +arch_initcall(nlm_platform_uart_init); diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c new file mode 100644 index 000000000000..f40a0e73580f --- /dev/null +++ b/arch/mips/netlogic/xlp/setup.c @@ -0,0 +1,101 @@ +/* + * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights + * reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the NetLogic + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``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 NETLOGIC OR CONTRIBUTORS 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 +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +unsigned long nlm_common_ebase = 0x0; + +static void nlm_linux_exit(void) +{ + nlm_write_sys_reg(nlm_sys_base, SYS_CHIP_RESET, 1); + for ( ; ; ) + cpu_wait(); +} + +void __init plat_mem_setup(void) +{ + panic_timeout = 5; + _machine_restart = (void (*)(char *))nlm_linux_exit; + _machine_halt = nlm_linux_exit; + pm_power_off = nlm_linux_exit; +} + +const char *get_system_type(void) +{ + return "Netlogic XLP Series"; +} + +void __init prom_free_prom_memory(void) +{ + /* Nothing yet */ +} + +void xlp_mmu_init(void) +{ + write_c0_config6(read_c0_config6() | 0x24); + current_cpu_data.tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1; + write_c0_config7(PM_DEFAULT_MASK >> + (13 + (ffz(PM_DEFAULT_MASK >> 13) / 2))); +} + +void __init prom_init(void) +{ + void *fdtp; + + fdtp = (void *)(long)fw_arg0; + xlp_mmu_init(); + nlm_hal_init(); + early_init_devtree(fdtp); + + nlm_common_ebase = read_c0_ebase() & (~((1 << 12) - 1)); +#ifdef CONFIG_SMP + nlm_wakeup_secondary_cpus(0xffffffff); + register_smp_ops(&nlm_smp_ops); +#endif +} diff --git a/arch/mips/netlogic/xlp/smpboot.S b/arch/mips/netlogic/xlp/smpboot.S new file mode 100644 index 000000000000..7dd323234d70 --- /dev/null +++ b/arch/mips/netlogic/xlp/smpboot.S @@ -0,0 +1,217 @@ +/* + * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights + * reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the NetLogic + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``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 NETLOGIC OR CONTRIBUTORS 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define CP0_EBASE $15 +#define SYS_CPU_COHERENT_BASE(node) CKSEG1ADDR(XLP_DEFAULT_IO_BASE) + \ + XLP_IO_SYS_OFFSET(node) + XLP_IO_PCI_HDRSZ + \ + SYS_CPU_NONCOHERENT_MODE * 4 + +.macro __config_lsu + li t0, LSU_DEFEATURE + mfcr t1, t0 + + lui t2, 0x4080 /* Enable Unaligned Access, L2HPE */ + or t1, t1, t2 + li t2, ~0xe /* S1RCM */ + and t1, t1, t2 + mtcr t1, t0 + + li t0, SCHED_DEFEATURE + lui t1, 0x0100 /* Experimental: Disable BRU accepting ALU ops */ + mtcr t1, t0 +.endm + + .set noreorder + .set arch=xlr /* for mfcr/mtcr, XLR is sufficient */ + + __CPUINIT +EXPORT(nlm_reset_entry) + mfc0 t0, CP0_EBASE, 1 + mfc0 t1, CP0_EBASE, 1 + srl t1, 5 + andi t1, 0x3 /* t1 <- node */ + li t2, 0x40000 + mul t3, t2, t1 /* t3 = node * 0x40000 */ + srl t0, t0, 2 + and t0, t0, 0x7 /* t0 <- core */ + li t1, 0x1 + sll t0, t1, t0 + nor t0, t0, zero /* t0 <- ~(1 << core) */ + li t2, SYS_CPU_COHERENT_BASE(0) + add t2, t2, t3 /* t2 <- SYS offset for node */ + lw t1, 0(t2) + and t1, t1, t0 + sw t1, 0(t2) + + /* read back to ensure complete */ + lw t1, 0(t2) + sync + + /* Configure LSU on Non-0 Cores. */ + __config_lsu + +/* + * Wake up sibling threads from the initial thread in + * a core. + */ +EXPORT(nlm_boot_siblings) + li t0, CKSEG1ADDR(RESET_DATA_PHYS) + lw t1, BOOT_THREAD_MODE(t0) /* t1 <- thread mode */ + li t0, ((CPU_BLOCKID_MAP << 8) | MAP_THREADMODE) + mfcr t2, t0 + or t2, t2, t1 + mtcr t2, t0 + + /* + * The new hardware thread starts at the next instruction + * For all the cases other than core 0 thread 0, we will + * jump to the secondary wait function. + */ + mfc0 v0, CP0_EBASE, 1 + andi v0, 0x7f /* v0 <- node/core */ + +#if 1 + /* A0 errata - Write MMU_SETUP after changing thread mode register. */ + andi v1, v0, 0x3 /* v1 <- thread id */ + bnez v1, 2f + nop + + li t0, MMU_SETUP + li t1, 0 + mtcr t1, t0 + ehb +#endif + +2: beqz v0, 3f + nop + + /* setup status reg */ + mfc0 t1, CP0_STATUS + li t0, ST0_BEV + or t1, t0 + xor t1, t0 +#ifdef CONFIG_64BIT + ori t1, ST0_KX +#endif + mtc0 t1, CP0_STATUS + + /* SETUP TLBs for a mapped kernel here */ + PTR_LA t0, prom_pre_boot_secondary_cpus + jalr t0 + nop + + /* + * For the boot CPU, we have to restore registers and + * return + */ +3: dmfc0 t0, $4, 2 /* restore SP from UserLocal */ + li t1, 0xfadebeef + dmtc0 t1, $4, 2 /* restore SP from UserLocal */ + PTR_SUBU sp, t0, PT_SIZE + RESTORE_ALL + jr ra + nop +EXPORT(nlm_reset_entry_end) + +EXPORT(nlm_boot_core0_siblings) /* "Master" (n0c0t0) cpu starts from here */ + __config_lsu + dmtc0 sp, $4, 2 /* SP saved in UserLocal */ + SAVE_ALL + sync + /* find the location to which nlm_boot_siblings was relocated */ + li t0, CKSEG1ADDR(RESET_VEC_PHYS) + dla t1, nlm_reset_entry + dla t2, nlm_boot_siblings + dsubu t2, t1 + daddu t2, t0 + /* call it */ + jr t2 + nop + __FINIT + + __CPUINIT +NESTED(prom_pre_boot_secondary_cpus, 16, sp) + .set mips64 + mfc0 a0, CP0_EBASE, 1 /* read ebase */ + andi a0, 0x3ff /* a0 has the processor_id() */ + sll t0, a0, 2 /* offset in cpu array */ + + PTR_LA t1, nlm_cpu_ready /* mark CPU ready */ + PTR_ADDU t1, t0 + li t2, 1 + sw t2, 0(t1) + + PTR_LA t1, nlm_cpu_unblock + PTR_ADDU t1, t0 +1: lw t2, 0(t1) /* wait till unblocked */ + bnez t2, 2f + nop + nop + nop + nop + nop + nop + j 1b + nop + +2: PTR_LA t1, nlm_next_sp + PTR_L sp, 0(t1) + PTR_LA t1, nlm_next_gp + PTR_L gp, 0(t1) + + /* a0 has the processor id */ + PTR_LA t0, nlm_early_init_secondary + jalr t0 + nop + + PTR_LA t0, smp_bootstrap + jr t0 + nop +END(prom_pre_boot_secondary_cpus) + __FINIT diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c new file mode 100644 index 000000000000..e081a778678e --- /dev/null +++ b/arch/mips/netlogic/xlp/wakeup.c @@ -0,0 +1,149 @@ +/* + * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights + * reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the NetLogic + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``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 NETLOGIC OR CONTRIBUTORS 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 +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +unsigned long secondary_entry; +uint32_t nlm_coremask; +unsigned int nlm_threads_per_core; +unsigned int nlm_threadmode; + +static void nlm_enable_secondary_cores(unsigned int cores_bitmap) +{ + uint32_t core, value, coremask; + + for (core = 1; core < 8; core++) { + coremask = 1 << core; + if ((cores_bitmap & coremask) == 0) + continue; + + /* Enable CPU clock */ + value = nlm_read_sys_reg(nlm_sys_base, SYS_CORE_DFS_DIS_CTRL); + value &= ~coremask; + nlm_write_sys_reg(nlm_sys_base, SYS_CORE_DFS_DIS_CTRL, value); + + /* Remove CPU Reset */ + value = nlm_read_sys_reg(nlm_sys_base, SYS_CPU_RESET); + value &= ~coremask; + nlm_write_sys_reg(nlm_sys_base, SYS_CPU_RESET, value); + + /* Poll for CPU to mark itself coherent */ + do { + value = nlm_read_sys_reg(nlm_sys_base, + SYS_CPU_NONCOHERENT_MODE); + } while ((value & coremask) != 0); + } +} + + +static void nlm_parse_cpumask(u32 cpu_mask) +{ + uint32_t core0_thr_mask, core_thr_mask; + int i; + + core0_thr_mask = cpu_mask & 0xf; + switch (core0_thr_mask) { + case 1: + nlm_threads_per_core = 1; + nlm_threadmode = 0; + break; + case 3: + nlm_threads_per_core = 2; + nlm_threadmode = 2; + break; + case 0xf: + nlm_threads_per_core = 4; + nlm_threadmode = 3; + break; + default: + goto unsupp; + } + + /* Verify other cores CPU masks */ + nlm_coremask = 1; + for (i = 1; i < 8; i++) { + core_thr_mask = (cpu_mask >> (i * 4)) & 0xf; + if (core_thr_mask) { + if (core_thr_mask != core0_thr_mask) + goto unsupp; + nlm_coremask |= 1 << i; + } + } + return; + +unsupp: + panic("Unsupported CPU mask %x\n", cpu_mask); +} + +int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask) +{ + unsigned long reset_vec; + unsigned int *reset_data; + + /* Update reset entry point with CPU init code */ + reset_vec = CKSEG1ADDR(RESET_VEC_PHYS); + memcpy((void *)reset_vec, (void *)nlm_reset_entry, + (nlm_reset_entry_end - nlm_reset_entry)); + + /* verify the mask and setup core config variables */ + nlm_parse_cpumask(wakeup_mask); + + /* Setup CPU init parameters */ + reset_data = (unsigned int *)CKSEG1ADDR(RESET_DATA_PHYS); + reset_data[BOOT_THREAD_MODE] = nlm_threadmode; + + /* first wakeup core 0 siblings */ + nlm_boot_core0_siblings(); + + /* enable the reset of the cores */ + nlm_enable_secondary_cores(nlm_coremask); + return 0; +} -- cgit v1.2.1 From 1c773ea4dceff889c2f872343609a87ae0cfbf56 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Wed, 16 Nov 2011 00:21:28 +0000 Subject: MIPS: Netlogic: Add XLP makefiles and config - Add CPU_XLP and NLM_XLR_BOARD to arch/mips/Kconfig for Netlogic XLP boards - Update mips Makefiles to add XLP Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2968/ Signed-off-by: Ralf Baechle --- arch/mips/netlogic/xlp/Makefile | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 arch/mips/netlogic/xlp/Makefile (limited to 'arch/mips/netlogic/xlp') diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile new file mode 100644 index 000000000000..1940d1c946d0 --- /dev/null +++ b/arch/mips/netlogic/xlp/Makefile @@ -0,0 +1,2 @@ +obj-y += setup.o platform.o nlm_hal.o +obj-$(CONFIG_SMP) += smpboot.o wakeup.o -- cgit v1.2.1 From 66d29985fab8207b1b2c03ac34a2c294c5b47a30 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Wed, 16 Nov 2011 00:21:29 +0000 Subject: MIPS: Netlogic: Merge some of XLR/XLP wakup code Create a common NMI and reset handler in smpboot.S and use this for both XLR and XLP. In the earlier code, the woken up CPUs would busy wait until released, switch this to wakeup by NMI. The initial wakeup code or XLR and XLP are differ since they are started from different bootloaders (XLP from u-boot and XLR from netlogic bootloader). But in both platforms the woken up CPUs wait and are released by sending an NMI. Add support for starting XLR and XLP in 1/2/4 threads per core. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2970/ Signed-off-by: Ralf Baechle --- arch/mips/netlogic/xlp/Makefile | 2 +- arch/mips/netlogic/xlp/setup.c | 4 + arch/mips/netlogic/xlp/smpboot.S | 217 --------------------------------------- arch/mips/netlogic/xlp/wakeup.c | 93 +++++------------ 4 files changed, 28 insertions(+), 288 deletions(-) delete mode 100644 arch/mips/netlogic/xlp/smpboot.S (limited to 'arch/mips/netlogic/xlp') diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile index 1940d1c946d0..b93ed83474ec 100644 --- a/arch/mips/netlogic/xlp/Makefile +++ b/arch/mips/netlogic/xlp/Makefile @@ -1,2 +1,2 @@ obj-y += setup.o platform.o nlm_hal.o -obj-$(CONFIG_SMP) += smpboot.o wakeup.o +obj-$(CONFIG_SMP) += wakeup.o diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c index f40a0e73580f..acb677a1227c 100644 --- a/arch/mips/netlogic/xlp/setup.c +++ b/arch/mips/netlogic/xlp/setup.c @@ -51,6 +51,10 @@ unsigned long nlm_common_ebase = 0x0; +/* default to uniprocessor */ +uint32_t nlm_coremask = 1, nlm_cpumask = 1; +int nlm_threads_per_core = 1; + static void nlm_linux_exit(void) { nlm_write_sys_reg(nlm_sys_base, SYS_CHIP_RESET, 1); diff --git a/arch/mips/netlogic/xlp/smpboot.S b/arch/mips/netlogic/xlp/smpboot.S deleted file mode 100644 index 7dd323234d70..000000000000 --- a/arch/mips/netlogic/xlp/smpboot.S +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights - * reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the NetLogic - * license below: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * - * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``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 NETLOGIC OR CONTRIBUTORS 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 - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define CP0_EBASE $15 -#define SYS_CPU_COHERENT_BASE(node) CKSEG1ADDR(XLP_DEFAULT_IO_BASE) + \ - XLP_IO_SYS_OFFSET(node) + XLP_IO_PCI_HDRSZ + \ - SYS_CPU_NONCOHERENT_MODE * 4 - -.macro __config_lsu - li t0, LSU_DEFEATURE - mfcr t1, t0 - - lui t2, 0x4080 /* Enable Unaligned Access, L2HPE */ - or t1, t1, t2 - li t2, ~0xe /* S1RCM */ - and t1, t1, t2 - mtcr t1, t0 - - li t0, SCHED_DEFEATURE - lui t1, 0x0100 /* Experimental: Disable BRU accepting ALU ops */ - mtcr t1, t0 -.endm - - .set noreorder - .set arch=xlr /* for mfcr/mtcr, XLR is sufficient */ - - __CPUINIT -EXPORT(nlm_reset_entry) - mfc0 t0, CP0_EBASE, 1 - mfc0 t1, CP0_EBASE, 1 - srl t1, 5 - andi t1, 0x3 /* t1 <- node */ - li t2, 0x40000 - mul t3, t2, t1 /* t3 = node * 0x40000 */ - srl t0, t0, 2 - and t0, t0, 0x7 /* t0 <- core */ - li t1, 0x1 - sll t0, t1, t0 - nor t0, t0, zero /* t0 <- ~(1 << core) */ - li t2, SYS_CPU_COHERENT_BASE(0) - add t2, t2, t3 /* t2 <- SYS offset for node */ - lw t1, 0(t2) - and t1, t1, t0 - sw t1, 0(t2) - - /* read back to ensure complete */ - lw t1, 0(t2) - sync - - /* Configure LSU on Non-0 Cores. */ - __config_lsu - -/* - * Wake up sibling threads from the initial thread in - * a core. - */ -EXPORT(nlm_boot_siblings) - li t0, CKSEG1ADDR(RESET_DATA_PHYS) - lw t1, BOOT_THREAD_MODE(t0) /* t1 <- thread mode */ - li t0, ((CPU_BLOCKID_MAP << 8) | MAP_THREADMODE) - mfcr t2, t0 - or t2, t2, t1 - mtcr t2, t0 - - /* - * The new hardware thread starts at the next instruction - * For all the cases other than core 0 thread 0, we will - * jump to the secondary wait function. - */ - mfc0 v0, CP0_EBASE, 1 - andi v0, 0x7f /* v0 <- node/core */ - -#if 1 - /* A0 errata - Write MMU_SETUP after changing thread mode register. */ - andi v1, v0, 0x3 /* v1 <- thread id */ - bnez v1, 2f - nop - - li t0, MMU_SETUP - li t1, 0 - mtcr t1, t0 - ehb -#endif - -2: beqz v0, 3f - nop - - /* setup status reg */ - mfc0 t1, CP0_STATUS - li t0, ST0_BEV - or t1, t0 - xor t1, t0 -#ifdef CONFIG_64BIT - ori t1, ST0_KX -#endif - mtc0 t1, CP0_STATUS - - /* SETUP TLBs for a mapped kernel here */ - PTR_LA t0, prom_pre_boot_secondary_cpus - jalr t0 - nop - - /* - * For the boot CPU, we have to restore registers and - * return - */ -3: dmfc0 t0, $4, 2 /* restore SP from UserLocal */ - li t1, 0xfadebeef - dmtc0 t1, $4, 2 /* restore SP from UserLocal */ - PTR_SUBU sp, t0, PT_SIZE - RESTORE_ALL - jr ra - nop -EXPORT(nlm_reset_entry_end) - -EXPORT(nlm_boot_core0_siblings) /* "Master" (n0c0t0) cpu starts from here */ - __config_lsu - dmtc0 sp, $4, 2 /* SP saved in UserLocal */ - SAVE_ALL - sync - /* find the location to which nlm_boot_siblings was relocated */ - li t0, CKSEG1ADDR(RESET_VEC_PHYS) - dla t1, nlm_reset_entry - dla t2, nlm_boot_siblings - dsubu t2, t1 - daddu t2, t0 - /* call it */ - jr t2 - nop - __FINIT - - __CPUINIT -NESTED(prom_pre_boot_secondary_cpus, 16, sp) - .set mips64 - mfc0 a0, CP0_EBASE, 1 /* read ebase */ - andi a0, 0x3ff /* a0 has the processor_id() */ - sll t0, a0, 2 /* offset in cpu array */ - - PTR_LA t1, nlm_cpu_ready /* mark CPU ready */ - PTR_ADDU t1, t0 - li t2, 1 - sw t2, 0(t1) - - PTR_LA t1, nlm_cpu_unblock - PTR_ADDU t1, t0 -1: lw t2, 0(t1) /* wait till unblocked */ - bnez t2, 2f - nop - nop - nop - nop - nop - nop - j 1b - nop - -2: PTR_LA t1, nlm_next_sp - PTR_L sp, 0(t1) - PTR_LA t1, nlm_next_gp - PTR_L gp, 0(t1) - - /* a0 has the processor id */ - PTR_LA t0, nlm_early_init_secondary - jalr t0 - nop - - PTR_LA t0, smp_bootstrap - jr t0 - nop -END(prom_pre_boot_secondary_cpus) - __FINIT diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c index e081a778678e..44d923ff3846 100644 --- a/arch/mips/netlogic/xlp/wakeup.c +++ b/arch/mips/netlogic/xlp/wakeup.c @@ -51,18 +51,20 @@ #include #include -unsigned long secondary_entry; -uint32_t nlm_coremask; -unsigned int nlm_threads_per_core; -unsigned int nlm_threadmode; - -static void nlm_enable_secondary_cores(unsigned int cores_bitmap) +static void xlp_enable_secondary_cores(void) { - uint32_t core, value, coremask; + uint32_t core, value, coremask, syscoremask; + int count; + + /* read cores in reset from SYS block */ + syscoremask = nlm_read_sys_reg(nlm_sys_base, SYS_CPU_RESET); + + /* update user specified */ + nlm_coremask = nlm_coremask & (syscoremask | 1); for (core = 1; core < 8; core++) { coremask = 1 << core; - if ((cores_bitmap & coremask) == 0) + if ((nlm_coremask & coremask) == 0) continue; /* Enable CPU clock */ @@ -76,74 +78,25 @@ static void nlm_enable_secondary_cores(unsigned int cores_bitmap) nlm_write_sys_reg(nlm_sys_base, SYS_CPU_RESET, value); /* Poll for CPU to mark itself coherent */ + count = 100000; do { value = nlm_read_sys_reg(nlm_sys_base, SYS_CPU_NONCOHERENT_MODE); - } while ((value & coremask) != 0); - } -} - - -static void nlm_parse_cpumask(u32 cpu_mask) -{ - uint32_t core0_thr_mask, core_thr_mask; - int i; + } while ((value & coremask) != 0 && count-- > 0); - core0_thr_mask = cpu_mask & 0xf; - switch (core0_thr_mask) { - case 1: - nlm_threads_per_core = 1; - nlm_threadmode = 0; - break; - case 3: - nlm_threads_per_core = 2; - nlm_threadmode = 2; - break; - case 0xf: - nlm_threads_per_core = 4; - nlm_threadmode = 3; - break; - default: - goto unsupp; + if (count == 0) + pr_err("Failed to enable core %d\n", core); } - - /* Verify other cores CPU masks */ - nlm_coremask = 1; - for (i = 1; i < 8; i++) { - core_thr_mask = (cpu_mask >> (i * 4)) & 0xf; - if (core_thr_mask) { - if (core_thr_mask != core0_thr_mask) - goto unsupp; - nlm_coremask |= 1 << i; - } - } - return; - -unsupp: - panic("Unsupported CPU mask %x\n", cpu_mask); } -int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask) +void xlp_wakeup_secondary_cpus(void) { - unsigned long reset_vec; - unsigned int *reset_data; - - /* Update reset entry point with CPU init code */ - reset_vec = CKSEG1ADDR(RESET_VEC_PHYS); - memcpy((void *)reset_vec, (void *)nlm_reset_entry, - (nlm_reset_entry_end - nlm_reset_entry)); - - /* verify the mask and setup core config variables */ - nlm_parse_cpumask(wakeup_mask); - - /* Setup CPU init parameters */ - reset_data = (unsigned int *)CKSEG1ADDR(RESET_DATA_PHYS); - reset_data[BOOT_THREAD_MODE] = nlm_threadmode; - - /* first wakeup core 0 siblings */ - nlm_boot_core0_siblings(); - - /* enable the reset of the cores */ - nlm_enable_secondary_cores(nlm_coremask); - return 0; + /* + * In case of u-boot, the secondaries are in reset + * first wakeup core 0 threads + */ + xlp_boot_core0_siblings(); + + /* now get other cores out of reset */ + xlp_enable_secondary_cores(); } -- cgit v1.2.1 From 2aa54b2009bb4f85cdc42d16dde18093dd832a31 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Wed, 16 Nov 2011 00:21:29 +0000 Subject: MIPS: Netlogic: Add support for XLP 3XX cores Add new processor ID to asm/cpu.h and kernel/cpu-probe.c. Update to new CPU frequency detection code which works on XLP 3XX and 8XX. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2971/ Signed-off-by: Ralf Baechle --- arch/mips/netlogic/xlp/nlm_hal.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'arch/mips/netlogic/xlp') diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c index 885f6878594a..9428e7125fed 100644 --- a/arch/mips/netlogic/xlp/nlm_hal.c +++ b/arch/mips/netlogic/xlp/nlm_hal.c @@ -86,20 +86,26 @@ int nlm_irt_to_irq(int irt) } } -unsigned int nlm_get_cpu_frequency(void) +unsigned int nlm_get_core_frequency(int core) { - unsigned int pll_divf, pll_divr, dfs_div, denom; - unsigned int val; + unsigned int pll_divf, pll_divr, dfs_div, ext_div; + unsigned int rstval, dfsval, denom; uint64_t num; - val = nlm_read_sys_reg(nlm_sys_base, SYS_POWER_ON_RESET_CFG); - pll_divf = (val >> 10) & 0x7f; - pll_divr = (val >> 8) & 0x3; - dfs_div = (val >> 17) & 0x3; + rstval = nlm_read_sys_reg(nlm_sys_base, SYS_POWER_ON_RESET_CFG); + dfsval = nlm_read_sys_reg(nlm_sys_base, SYS_CORE_DFS_DIV_VALUE); + pll_divf = ((rstval >> 10) & 0x7f) + 1; + pll_divr = ((rstval >> 8) & 0x3) + 1; + ext_div = ((rstval >> 30) & 0x3) + 1; + dfs_div = ((dfsval >> (core * 4)) & 0xf) + 1; - num = pll_divf + 1; - denom = 3 * (pll_divr + 1) * (1 << (dfs_div + 1)); - num = num * 800000000ULL; + num = 800000000ULL * pll_divf; + denom = 3 * pll_divr * ext_div * dfs_div; do_div(num, denom); return (unsigned int)num; } + +unsigned int nlm_get_cpu_frequency(void) +{ + return nlm_get_core_frequency(0); +} -- cgit v1.2.1