diff options
Diffstat (limited to 'arch/mips/netlogic/xlp')
-rw-r--r-- | arch/mips/netlogic/xlp/nlm_hal.c | 67 | ||||
-rw-r--r-- | arch/mips/netlogic/xlp/setup.c | 50 | ||||
-rw-r--r-- | arch/mips/netlogic/xlp/wakeup.c | 83 |
3 files changed, 98 insertions, 102 deletions
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c index 6c65ac701912..529e74742d9f 100644 --- a/arch/mips/netlogic/xlp/nlm_hal.c +++ b/arch/mips/netlogic/xlp/nlm_hal.c @@ -40,23 +40,23 @@ #include <asm/mipsregs.h> #include <asm/time.h> +#include <asm/netlogic/common.h> #include <asm/netlogic/haldefs.h> #include <asm/netlogic/xlp-hal/iomap.h> #include <asm/netlogic/xlp-hal/xlp.h> #include <asm/netlogic/xlp-hal/pic.h> #include <asm/netlogic/xlp-hal/sys.h> -/* 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) +void nlm_node_init(int node) { - 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 */ + struct nlm_soc_info *nodep; + + nodep = nlm_get_node(node); + nodep->sysbase = nlm_get_sys_regbase(node); + nodep->picbase = nlm_get_pic_regbase(node); + nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1)); + spin_lock_init(&nodep->piclock); } int nlm_irq_to_irt(int irq) @@ -100,52 +100,15 @@ int nlm_irq_to_irt(int irq) } } -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; - case PIC_IRT_PCIE_LINK_0_INDEX: - return PIC_PCIE_LINK_0_IRQ; - case PIC_IRT_PCIE_LINK_1_INDEX: - return PIC_PCIE_LINK_1_IRQ; - case PIC_IRT_PCIE_LINK_2_INDEX: - return PIC_PCIE_LINK_2_IRQ; - case PIC_IRT_PCIE_LINK_3_INDEX: - return PIC_PCIE_LINK_3_IRQ; - case PIC_IRT_EHCI_0_INDEX: - return PIC_EHCI_0_IRQ; - case PIC_IRT_EHCI_1_INDEX: - return PIC_EHCI_1_IRQ; - case PIC_IRT_OHCI_0_INDEX: - return PIC_OHCI_0_IRQ; - case PIC_IRT_OHCI_1_INDEX: - return PIC_OHCI_1_IRQ; - case PIC_IRT_OHCI_2_INDEX: - return PIC_OHCI_2_IRQ; - case PIC_IRT_OHCI_3_INDEX: - return PIC_OHCI_3_IRQ; - case PIC_IRT_MMC_INDEX: - return PIC_MMC_IRQ; - case PIC_IRT_I2C_0_INDEX: - return PIC_I2C_0_IRQ; - case PIC_IRT_I2C_1_INDEX: - return PIC_I2C_1_IRQ; - default: - return -1; - } -} - -unsigned int nlm_get_core_frequency(int core) +unsigned int nlm_get_core_frequency(int node, int core) { unsigned int pll_divf, pll_divr, dfs_div, ext_div; unsigned int rstval, dfsval, denom; - uint64_t num; + uint64_t num, sysbase; - 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); + sysbase = nlm_get_node(node)->sysbase; + rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG); + dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE); pll_divf = ((rstval >> 10) & 0x7f) + 1; pll_divr = ((rstval >> 8) & 0x3) + 1; ext_div = ((rstval >> 30) & 0x3) + 1; @@ -159,5 +122,5 @@ unsigned int nlm_get_core_frequency(int core) unsigned int nlm_get_cpu_frequency(void) { - return nlm_get_core_frequency(0); + return nlm_get_core_frequency(0, 0); } diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c index d8997098defd..4894d62043ac 100644 --- a/arch/mips/netlogic/xlp/setup.c +++ b/arch/mips/netlogic/xlp/setup.c @@ -52,26 +52,40 @@ #include <asm/netlogic/xlp-hal/xlp.h> #include <asm/netlogic/xlp-hal/sys.h> -unsigned long nlm_common_ebase = 0x0; - -/* default to uniprocessor */ -uint32_t nlm_coremask = 1, nlm_cpumask = 1; -int nlm_threads_per_core = 1; +uint64_t nlm_io_base; +struct nlm_soc_info nlm_nodes[NLM_NR_NODES]; +cpumask_t nlm_cpumask = CPU_MASK_CPU0; +unsigned int nlm_threads_per_core; extern u32 __dtb_start[]; static void nlm_linux_exit(void) { - nlm_write_sys_reg(nlm_sys_base, SYS_CHIP_RESET, 1); + uint64_t sysbase = nlm_get_node(0)->sysbase; + + nlm_write_sys_reg(sysbase, SYS_CHIP_RESET, 1); for ( ; ; ) cpu_wait(); } void __init plat_mem_setup(void) { + void *fdtp; + panic_timeout = 5; _machine_restart = (void (*)(char *))nlm_linux_exit; _machine_halt = nlm_linux_exit; pm_power_off = nlm_linux_exit; + + /* + * If no FDT pointer is passed in, use the built-in FDT. + * device_tree_init() does not handle CKSEG0 pointers in + * 64-bit, so convert pointer. + */ + fdtp = (void *)(long)fw_arg0; + if (!fdtp) + fdtp = __dtb_start; + fdtp = phys_to_virt(__pa(fdtp)); + early_init_devtree(fdtp); } const char *get_system_type(void) @@ -94,27 +108,19 @@ void xlp_mmu_init(void) (13 + (ffz(PM_DEFAULT_MASK >> 13) / 2))); } -void __init prom_init(void) +void nlm_percpu_init(int hwcpuid) { - void *fdtp; +} +void __init prom_init(void) +{ + nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE); xlp_mmu_init(); - nlm_hal_init(); - - /* - * If no FDT pointer is passed in, use the built-in FDT. - * device_tree_init() does not handle CKSEG0 pointers in - * 64-bit, so convert pointer. - */ - fdtp = (void *)(long)fw_arg0; - if (!fdtp) - fdtp = __dtb_start; - fdtp = phys_to_virt(__pa(fdtp)); - early_init_devtree(fdtp); + nlm_node_init(0); - nlm_common_ebase = read_c0_ebase() & (~((1 << 12) - 1)); #ifdef CONFIG_SMP - nlm_wakeup_secondary_cpus(0xffffffff); + cpumask_setall(&nlm_cpumask); + nlm_wakeup_secondary_cpus(); /* update TLB size after waking up threads */ current_cpu_data.tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1; diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c index 44d923ff3846..cb9010642ac3 100644 --- a/arch/mips/netlogic/xlp/wakeup.c +++ b/arch/mips/netlogic/xlp/wakeup.c @@ -51,45 +51,72 @@ #include <asm/netlogic/xlp-hal/xlp.h> #include <asm/netlogic/xlp-hal/sys.h> -static void xlp_enable_secondary_cores(void) +static int xlp_wakeup_core(uint64_t sysbase, int core) { - uint32_t core, value, coremask, syscoremask; + uint32_t coremask, value; int count; - /* read cores in reset from SYS block */ - syscoremask = nlm_read_sys_reg(nlm_sys_base, SYS_CPU_RESET); + coremask = (1 << core); - /* update user specified */ - nlm_coremask = nlm_coremask & (syscoremask | 1); + /* Enable CPU clock */ + value = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL); + value &= ~coremask; + nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, value); - for (core = 1; core < 8; core++) { - coremask = 1 << core; - if ((nlm_coremask & coremask) == 0) - continue; + /* Remove CPU Reset */ + value = nlm_read_sys_reg(sysbase, SYS_CPU_RESET); + value &= ~coremask; + nlm_write_sys_reg(sysbase, SYS_CPU_RESET, value); - /* 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); + /* Poll for CPU to mark itself coherent */ + count = 100000; + do { + value = nlm_read_sys_reg(sysbase, SYS_CPU_NONCOHERENT_MODE); + } while ((value & coremask) != 0 && --count > 0); - /* 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); + return count != 0; +} + +static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) +{ + struct nlm_soc_info *nodep; + uint64_t syspcibase; + uint32_t syscoremask; + 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; + + /* read cores in reset from SYS and account for boot cpu */ + nlm_node_init(n); + nodep = nlm_get_node(n); + syscoremask = nlm_read_sys_reg(nodep->sysbase, SYS_CPU_RESET); + if (n == 0) + syscoremask |= 1; + + for (core = 0; core < NLM_CORES_PER_NODE; core++) { + /* see if the core exists */ + if ((syscoremask & (1 << core)) == 0) + continue; - /* 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 && count-- > 0); + /* see if at least the first thread is enabled */ + cpu = (n * NLM_CORES_PER_NODE + core) + * NLM_THREADS_PER_CORE; + if (!cpumask_test_cpu(cpu, wakeup_mask)) + continue; - if (count == 0) - pr_err("Failed to enable core %d\n", core); + /* wake up the core */ + if (xlp_wakeup_core(nodep->sysbase, core)) + nodep->coremask |= 1u << core; + else + pr_err("Failed to enable core %d\n", core); + } } } -void xlp_wakeup_secondary_cpus(void) +void xlp_wakeup_secondary_cpus() { /* * In case of u-boot, the secondaries are in reset @@ -98,5 +125,5 @@ void xlp_wakeup_secondary_cpus(void) xlp_boot_core0_siblings(); /* now get other cores out of reset */ - xlp_enable_secondary_cores(); + xlp_enable_secondary_cores(&nlm_cpumask); } |