aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/netlogic/xlp
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/netlogic/xlp')
-rw-r--r--arch/mips/netlogic/xlp/Makefile2
-rw-r--r--arch/mips/netlogic/xlp/cop2-ex.c118
-rw-r--r--arch/mips/netlogic/xlp/dt.c99
-rw-r--r--arch/mips/netlogic/xlp/setup.c95
-rw-r--r--arch/mips/netlogic/xlp/wakeup.c26
5 files changed, 264 insertions, 76 deletions
diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile
index a84d6ed3746c..85ac4a892ced 100644
--- a/arch/mips/netlogic/xlp/Makefile
+++ b/arch/mips/netlogic/xlp/Makefile
@@ -1,3 +1,3 @@
1obj-y += setup.o nlm_hal.o 1obj-y += setup.o nlm_hal.o cop2-ex.o dt.o
2obj-$(CONFIG_SMP) += wakeup.o 2obj-$(CONFIG_SMP) += wakeup.o
3obj-$(CONFIG_USB) += usb-init.o 3obj-$(CONFIG_USB) += usb-init.o
diff --git a/arch/mips/netlogic/xlp/cop2-ex.c b/arch/mips/netlogic/xlp/cop2-ex.c
new file mode 100644
index 000000000000..52bc5de42005
--- /dev/null
+++ b/arch/mips/netlogic/xlp/cop2-ex.c
@@ -0,0 +1,118 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2013 Broadcom Corporation.
7 *
8 * based on arch/mips/cavium-octeon/cpu.c
9 * Copyright (C) 2009 Wind River Systems,
10 * written by Ralf Baechle <ralf@linux-mips.org>
11 */
12#include <linux/init.h>
13#include <linux/irqflags.h>
14#include <linux/notifier.h>
15#include <linux/prefetch.h>
16#include <linux/sched.h>
17
18#include <asm/cop2.h>
19#include <asm/current.h>
20#include <asm/mipsregs.h>
21#include <asm/page.h>
22
23#include <asm/netlogic/mips-extns.h>
24
25/*
26 * 64 bit ops are done in inline assembly to support 32 bit
27 * compilation
28 */
29void nlm_cop2_save(struct nlm_cop2_state *r)
30{
31 asm volatile(
32 ".set push\n"
33 ".set noat\n"
34 "dmfc2 $1, $0, 0\n"
35 "sd $1, 0(%1)\n"
36 "dmfc2 $1, $0, 1\n"
37 "sd $1, 8(%1)\n"
38 "dmfc2 $1, $0, 2\n"
39 "sd $1, 16(%1)\n"
40 "dmfc2 $1, $0, 3\n"
41 "sd $1, 24(%1)\n"
42 "dmfc2 $1, $1, 0\n"
43 "sd $1, 0(%2)\n"
44 "dmfc2 $1, $1, 1\n"
45 "sd $1, 8(%2)\n"
46 "dmfc2 $1, $1, 2\n"
47 "sd $1, 16(%2)\n"
48 "dmfc2 $1, $1, 3\n"
49 "sd $1, 24(%2)\n"
50 ".set pop\n"
51 : "=m"(*r)
52 : "r"(r->tx), "r"(r->rx));
53
54 r->tx_msg_status = __read_32bit_c2_register($2, 0);
55 r->rx_msg_status = __read_32bit_c2_register($3, 0) & 0x0fffffff;
56}
57
58void nlm_cop2_restore(struct nlm_cop2_state *r)
59{
60 u32 rstat;
61
62 asm volatile(
63 ".set push\n"
64 ".set noat\n"
65 "ld $1, 0(%1)\n"
66 "dmtc2 $1, $0, 0\n"
67 "ld $1, 8(%1)\n"
68 "dmtc2 $1, $0, 1\n"
69 "ld $1, 16(%1)\n"
70 "dmtc2 $1, $0, 2\n"
71 "ld $1, 24(%1)\n"
72 "dmtc2 $1, $0, 3\n"
73 "ld $1, 0(%2)\n"
74 "dmtc2 $1, $1, 0\n"
75 "ld $1, 8(%2)\n"
76 "dmtc2 $1, $1, 1\n"
77 "ld $1, 16(%2)\n"
78 "dmtc2 $1, $1, 2\n"
79 "ld $1, 24(%2)\n"
80 "dmtc2 $1, $1, 3\n"
81 ".set pop\n"
82 : : "m"(*r), "r"(r->tx), "r"(r->rx));
83
84 __write_32bit_c2_register($2, 0, r->tx_msg_status);
85 rstat = __read_32bit_c2_register($3, 0) & 0xf0000000u;
86 __write_32bit_c2_register($3, 0, r->rx_msg_status | rstat);
87}
88
89static int nlm_cu2_call(struct notifier_block *nfb, unsigned long action,
90 void *data)
91{
92 unsigned long flags;
93 unsigned int status;
94
95 switch (action) {
96 case CU2_EXCEPTION:
97 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
98 break;
99 local_irq_save(flags);
100 KSTK_STATUS(current) |= ST0_CU2;
101 status = read_c0_status();
102 write_c0_status(status | ST0_CU2);
103 nlm_cop2_restore(&(current->thread.cp2));
104 write_c0_status(status & ~ST0_CU2);
105 local_irq_restore(flags);
106 pr_info("COP2 access enabled for pid %d (%s)\n",
107 current->pid, current->comm);
108 return NOTIFY_BAD; /* Don't call default notifier */
109 }
110
111 return NOTIFY_OK; /* Let default notifier send signals */
112}
113
114static int __init nlm_cu2_setup(void)
115{
116 return cu2_notifier(nlm_cu2_call, 0);
117}
118early_initcall(nlm_cu2_setup);
diff --git a/arch/mips/netlogic/xlp/dt.c b/arch/mips/netlogic/xlp/dt.c
new file mode 100644
index 000000000000..a15cdbb8d0bd
--- /dev/null
+++ b/arch/mips/netlogic/xlp/dt.c
@@ -0,0 +1,99 @@
1/*
2 * Copyright 2003-2013 Broadcom Corporation.
3 * All Rights Reserved.
4 *
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the Broadcom
9 * license below:
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
20 * distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
32 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include <linux/kernel.h>
36#include <linux/bootmem.h>
37
38#include <linux/of_fdt.h>
39#include <linux/of_platform.h>
40#include <linux/of_device.h>
41
42extern u32 __dtb_xlp_evp_begin[], __dtb_xlp_svp_begin[], __dtb_start[];
43
44void __init *xlp_dt_init(void *fdtp)
45{
46 if (!fdtp) {
47 switch (current_cpu_data.processor_id & 0xff00) {
48#ifdef CONFIG_DT_XLP_SVP
49 case PRID_IMP_NETLOGIC_XLP3XX:
50 fdtp = __dtb_xlp_svp_begin;
51 break;
52#endif
53#ifdef CONFIG_DT_XLP_EVP
54 case PRID_IMP_NETLOGIC_XLP8XX:
55 fdtp = __dtb_xlp_evp_begin;
56 break;
57#endif
58 default:
59 /* Pick a built-in if any, and hope for the best */
60 fdtp = __dtb_start;
61 break;
62 }
63 }
64 initial_boot_params = fdtp;
65 return fdtp;
66}
67
68void __init device_tree_init(void)
69{
70 unsigned long base, size;
71
72 if (!initial_boot_params)
73 return;
74
75 base = virt_to_phys((void *)initial_boot_params);
76 size = be32_to_cpu(initial_boot_params->totalsize);
77
78 /* Before we do anything, lets reserve the dt blob */
79 reserve_bootmem(base, size, BOOTMEM_DEFAULT);
80
81 unflatten_device_tree();
82
83 /* free the space reserved for the dt blob */
84 free_bootmem(base, size);
85}
86
87static struct of_device_id __initdata xlp_ids[] = {
88 { .compatible = "simple-bus", },
89 {},
90};
91
92int __init xlp8xx_ds_publish_devices(void)
93{
94 if (!of_have_populated_dt())
95 return 0;
96 return of_platform_bus_probe(NULL, xlp_ids, NULL);
97}
98
99device_initcall(xlp8xx_ds_publish_devices);
diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c
index eaa99d28cb8e..7b638f7be491 100644
--- a/arch/mips/netlogic/xlp/setup.c
+++ b/arch/mips/netlogic/xlp/setup.c
@@ -33,19 +33,13 @@
33 */ 33 */
34 34
35#include <linux/kernel.h> 35#include <linux/kernel.h>
36#include <linux/serial_8250.h> 36#include <linux/of_fdt.h>
37#include <linux/pm.h>
38#include <linux/bootmem.h>
39 37
40#include <asm/idle.h> 38#include <asm/idle.h>
41#include <asm/reboot.h> 39#include <asm/reboot.h>
42#include <asm/time.h> 40#include <asm/time.h>
43#include <asm/bootinfo.h> 41#include <asm/bootinfo.h>
44 42
45#include <linux/of_fdt.h>
46#include <linux/of_platform.h>
47#include <linux/of_device.h>
48
49#include <asm/netlogic/haldefs.h> 43#include <asm/netlogic/haldefs.h>
50#include <asm/netlogic/common.h> 44#include <asm/netlogic/common.h>
51 45
@@ -57,7 +51,6 @@ uint64_t nlm_io_base;
57struct nlm_soc_info nlm_nodes[NLM_NR_NODES]; 51struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
58cpumask_t nlm_cpumask = CPU_MASK_CPU0; 52cpumask_t nlm_cpumask = CPU_MASK_CPU0;
59unsigned int nlm_threads_per_core; 53unsigned int nlm_threads_per_core;
60extern u32 __dtb_xlp_evp_begin[], __dtb_xlp_svp_begin[], __dtb_start[];
61 54
62static void nlm_linux_exit(void) 55static void nlm_linux_exit(void)
63{ 56{
@@ -68,41 +61,28 @@ static void nlm_linux_exit(void)
68 cpu_wait(); 61 cpu_wait();
69} 62}
70 63
71void __init plat_mem_setup(void) 64static void nlm_fixup_mem(void)
72{ 65{
73 void *fdtp; 66 const int pref_backup = 512;
67 int i;
68
69 for (i = 0; i < boot_mem_map.nr_map; i++) {
70 if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
71 continue;
72 boot_mem_map.map[i].size -= pref_backup;
73 }
74}
74 75
76void __init plat_mem_setup(void)
77{
75 panic_timeout = 5; 78 panic_timeout = 5;
76 _machine_restart = (void (*)(char *))nlm_linux_exit; 79 _machine_restart = (void (*)(char *))nlm_linux_exit;
77 _machine_halt = nlm_linux_exit; 80 _machine_halt = nlm_linux_exit;
78 pm_power_off = nlm_linux_exit; 81 pm_power_off = nlm_linux_exit;
79 82
80 /* 83 /* memory and bootargs from DT */
81 * If no FDT pointer is passed in, use the built-in FDT. 84 early_init_devtree(initial_boot_params);
82 * device_tree_init() does not handle CKSEG0 pointers in 85 nlm_fixup_mem();
83 * 64-bit, so convert pointer.
84 */
85 fdtp = (void *)(long)fw_arg0;
86 if (!fdtp) {
87 switch (current_cpu_data.processor_id & 0xff00) {
88#ifdef CONFIG_DT_XLP_SVP
89 case PRID_IMP_NETLOGIC_XLP3XX:
90 fdtp = __dtb_xlp_svp_begin;
91 break;
92#endif
93#ifdef CONFIG_DT_XLP_EVP
94 case PRID_IMP_NETLOGIC_XLP8XX:
95 fdtp = __dtb_xlp_evp_begin;
96 break;
97#endif
98 default:
99 /* Pick a built-in if any, and hope for the best */
100 fdtp = __dtb_start;
101 break;
102 }
103 }
104 fdtp = phys_to_virt(__pa(fdtp));
105 early_init_devtree(fdtp);
106} 86}
107 87
108const char *get_system_type(void) 88const char *get_system_type(void)
@@ -131,9 +111,19 @@ void nlm_percpu_init(int hwcpuid)
131 111
132void __init prom_init(void) 112void __init prom_init(void)
133{ 113{
114 void *reset_vec;
115
134 nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE); 116 nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE);
117 nlm_init_boot_cpu();
135 xlp_mmu_init(); 118 xlp_mmu_init();
136 nlm_node_init(0); 119 nlm_node_init(0);
120 xlp_dt_init((void *)(long)fw_arg0);
121
122 /* Update reset entry point with CPU init code */
123 reset_vec = (void *)CKSEG1ADDR(RESET_VEC_PHYS);
124 memset(reset_vec, 0, RESET_VEC_SIZE);
125 memcpy(reset_vec, (void *)nlm_reset_entry,
126 (nlm_reset_entry_end - nlm_reset_entry));
137 127
138#ifdef CONFIG_SMP 128#ifdef CONFIG_SMP
139 cpumask_setall(&nlm_cpumask); 129 cpumask_setall(&nlm_cpumask);
@@ -145,36 +135,3 @@ void __init prom_init(void)
145 register_smp_ops(&nlm_smp_ops); 135 register_smp_ops(&nlm_smp_ops);
146#endif 136#endif
147} 137}
148
149void __init device_tree_init(void)
150{
151 unsigned long base, size;
152
153 if (!initial_boot_params)
154 return;
155
156 base = virt_to_phys((void *)initial_boot_params);
157 size = be32_to_cpu(initial_boot_params->totalsize);
158
159 /* Before we do anything, lets reserve the dt blob */
160 reserve_bootmem(base, size, BOOTMEM_DEFAULT);
161
162 unflatten_device_tree();
163
164 /* free the space reserved for the dt blob */
165 free_bootmem(base, size);
166}
167
168static struct of_device_id __initdata xlp_ids[] = {
169 { .compatible = "simple-bus", },
170 {},
171};
172
173int __init xlp8xx_ds_publish_devices(void)
174{
175 if (!of_have_populated_dt())
176 return 0;
177 return of_platform_bus_probe(NULL, xlp_ids, NULL);
178}
179
180device_initcall(xlp8xx_ds_publish_devices);
diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c
index abb3e08cc052..0cce37cbffef 100644
--- a/arch/mips/netlogic/xlp/wakeup.c
+++ b/arch/mips/netlogic/xlp/wakeup.c
@@ -77,12 +77,28 @@ static int xlp_wakeup_core(uint64_t sysbase, int node, int core)
77 return count != 0; 77 return count != 0;
78} 78}
79 79
80static int wait_for_cpus(int cpu, int bootcpu)
81{
82 volatile uint32_t *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY);
83 int i, count, notready;
84
85 count = 0x20000000;
86 do {
87 notready = nlm_threads_per_core;
88 for (i = 0; i < nlm_threads_per_core; i++)
89 if (cpu_ready[cpu + i] || cpu == bootcpu)
90 --notready;
91 } while (notready != 0 && --count > 0);
92
93 return count != 0;
94}
95
80static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) 96static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
81{ 97{
82 struct nlm_soc_info *nodep; 98 struct nlm_soc_info *nodep;
83 uint64_t syspcibase; 99 uint64_t syspcibase;
84 uint32_t syscoremask; 100 uint32_t syscoremask;
85 int core, n, cpu, count, val; 101 int core, n, cpu;
86 102
87 for (n = 0; n < NLM_NR_NODES; n++) { 103 for (n = 0; n < NLM_NR_NODES; n++) {
88 syspcibase = nlm_get_sys_pcibase(n); 104 syspcibase = nlm_get_sys_pcibase(n);
@@ -122,11 +138,8 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
122 /* core is up */ 138 /* core is up */
123 nodep->coremask |= 1u << core; 139 nodep->coremask |= 1u << core;
124 140
125 /* spin until the first hw thread sets its ready */ 141 /* spin until the hw threads sets their ready */
126 count = 0x20000000; 142 wait_for_cpus(cpu, 0);
127 do {
128 val = *(volatile int *)&nlm_cpu_ready[cpu];
129 } while (val == 0 && --count > 0);
130 } 143 }
131 } 144 }
132} 145}
@@ -138,6 +151,7 @@ void xlp_wakeup_secondary_cpus()
138 * first wakeup core 0 threads 151 * first wakeup core 0 threads
139 */ 152 */
140 xlp_boot_core0_siblings(); 153 xlp_boot_core0_siblings();
154 wait_for_cpus(0, 0);
141 155
142 /* now get other cores out of reset */ 156 /* now get other cores out of reset */
143 xlp_enable_secondary_cores(&nlm_cpumask); 157 xlp_enable_secondary_cores(&nlm_cpumask);