aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/netlogic
diff options
context:
space:
mode:
authorWe-unite <3205135446@qq.com>2025-03-08 22:04:20 +0800
committerWe-unite <3205135446@qq.com>2025-03-08 22:04:20 +0800
commita07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch)
tree84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /arch/mips/netlogic
downloadohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz
ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'arch/mips/netlogic')
-rw-r--r--arch/mips/netlogic/Kconfig86
-rw-r--r--arch/mips/netlogic/Makefile4
-rw-r--r--arch/mips/netlogic/Platform16
-rw-r--r--arch/mips/netlogic/common/Makefile5
-rw-r--r--arch/mips/netlogic/common/earlycons.c63
-rw-r--r--arch/mips/netlogic/common/irq.c354
-rw-r--r--arch/mips/netlogic/common/reset.S299
-rw-r--r--arch/mips/netlogic/common/smp.c285
-rw-r--r--arch/mips/netlogic/common/smpboot.S141
-rw-r--r--arch/mips/netlogic/common/time.c110
-rw-r--r--arch/mips/netlogic/xlp/Makefile11
-rw-r--r--arch/mips/netlogic/xlp/ahci-init-xlp2.c390
-rw-r--r--arch/mips/netlogic/xlp/ahci-init.c209
-rw-r--r--arch/mips/netlogic/xlp/cop2-ex.c121
-rw-r--r--arch/mips/netlogic/xlp/dt.c95
-rw-r--r--arch/mips/netlogic/xlp/nlm_hal.c508
-rw-r--r--arch/mips/netlogic/xlp/setup.c179
-rw-r--r--arch/mips/netlogic/xlp/usb-init-xlp2.c288
-rw-r--r--arch/mips/netlogic/xlp/usb-init.c149
-rw-r--r--arch/mips/netlogic/xlp/wakeup.c212
-rw-r--r--arch/mips/netlogic/xlr/Makefile3
-rw-r--r--arch/mips/netlogic/xlr/fmn-config.c293
-rw-r--r--arch/mips/netlogic/xlr/fmn.c199
-rw-r--r--arch/mips/netlogic/xlr/platform-flash.c216
-rw-r--r--arch/mips/netlogic/xlr/platform.c250
-rw-r--r--arch/mips/netlogic/xlr/setup.c211
-rw-r--r--arch/mips/netlogic/xlr/wakeup.c85
27 files changed, 4782 insertions, 0 deletions
diff --git a/arch/mips/netlogic/Kconfig b/arch/mips/netlogic/Kconfig
new file mode 100644
index 000000000..412351c5a
--- /dev/null
+++ b/arch/mips/netlogic/Kconfig
@@ -0,0 +1,86 @@
1# SPDX-License-Identifier: GPL-2.0
2if NLM_XLP_BOARD || NLM_XLR_BOARD
3
4if NLM_XLP_BOARD
5config DT_XLP_EVP
6 bool "Built-in device tree for XLP EVP boards"
7 default y
8 select BUILTIN_DTB
9 help
10 Add an FDT blob for XLP EVP boards into the kernel.
11 This DTB will be used if the firmware does not pass in a DTB
12 pointer to the kernel. The corresponding DTS file is at
13 arch/mips/netlogic/dts/xlp_evp.dts
14
15config DT_XLP_SVP
16 bool "Built-in device tree for XLP SVP boards"
17 default y
18 select BUILTIN_DTB
19 help
20 Add an FDT blob for XLP VP boards into the kernel.
21 This DTB will be used if the firmware does not pass in a DTB
22 pointer to the kernel. The corresponding DTS file is at
23 arch/mips/netlogic/dts/xlp_svp.dts
24
25config DT_XLP_FVP
26 bool "Built-in device tree for XLP FVP boards"
27 default y
28 select BUILTIN_DTB
29 help
30 Add an FDT blob for XLP FVP board into the kernel.
31 This DTB will be used if the firmware does not pass in a DTB
32 pointer to the kernel. The corresponding DTS file is at
33 arch/mips/netlogic/dts/xlp_fvp.dts
34
35config DT_XLP_GVP
36 bool "Built-in device tree for XLP GVP boards"
37 default y
38 select BUILTIN_DTB
39 help
40 Add an FDT blob for XLP GVP board into the kernel.
41 This DTB will be used if the firmware does not pass in a DTB
42 pointer to the kernel. The corresponding DTS file is at
43 arch/mips/netlogic/dts/xlp_gvp.dts
44
45config DT_XLP_RVP
46 bool "Built-in device tree for XLP RVP boards"
47 default y
48 help
49 Add an FDT blob for XLP RVP board into the kernel.
50 This DTB will be used if the firmware does not pass in a DTB
51 pointer to the kernel. The corresponding DTS file is at
52 arch/mips/netlogic/dts/xlp_rvp.dts
53
54config NLM_MULTINODE
55 bool "Support for multi-chip boards"
56 depends on NLM_XLP_BOARD
57 default n
58 help
59 Add support for boards with 2 or 4 XLPs connected over ICI.
60
61if NLM_MULTINODE
62choice
63 prompt "Number of XLPs on the board"
64 default NLM_MULTINODE_2
65 help
66 In the multi-node case, specify the number of SoCs on the board.
67
68config NLM_MULTINODE_2
69 bool "Dual-XLP board"
70 help
71 Support boards with upto two XLPs connected over ICI.
72
73config NLM_MULTINODE_4
74 bool "Quad-XLP board"
75 help
76 Support boards with upto four XLPs connected over ICI.
77
78endchoice
79
80endif
81endif
82
83config NLM_COMMON
84 bool
85
86endif
diff --git a/arch/mips/netlogic/Makefile b/arch/mips/netlogic/Makefile
new file mode 100644
index 000000000..c53561589
--- /dev/null
+++ b/arch/mips/netlogic/Makefile
@@ -0,0 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0-only
2obj-$(CONFIG_NLM_COMMON) += common/
3obj-$(CONFIG_CPU_XLR) += xlr/
4obj-$(CONFIG_CPU_XLP) += xlp/
diff --git a/arch/mips/netlogic/Platform b/arch/mips/netlogic/Platform
new file mode 100644
index 000000000..4195a097f
--- /dev/null
+++ b/arch/mips/netlogic/Platform
@@ -0,0 +1,16 @@
1#
2# NETLOGIC includes
3#
4cflags-$(CONFIG_NLM_COMMON) += -I$(srctree)/arch/mips/include/asm/mach-netlogic
5cflags-$(CONFIG_NLM_COMMON) += -I$(srctree)/arch/mips/include/asm/netlogic
6
7#
8# use mips64 if xlr is not available
9#
10cflags-$(CONFIG_CPU_XLR) += $(call cc-option,-march=xlr,-march=mips64)
11cflags-$(CONFIG_CPU_XLP) += $(call cc-option,-march=xlp,-march=mips64r2)
12
13#
14# NETLOGIC processor support
15#
16load-$(CONFIG_NLM_COMMON) += 0xffffffff80100000
diff --git a/arch/mips/netlogic/common/Makefile b/arch/mips/netlogic/common/Makefile
new file mode 100644
index 000000000..89f6e3f39
--- /dev/null
+++ b/arch/mips/netlogic/common/Makefile
@@ -0,0 +1,5 @@
1# SPDX-License-Identifier: GPL-2.0
2obj-y += irq.o time.o
3obj-y += reset.o
4obj-$(CONFIG_SMP) += smp.o smpboot.o
5obj-$(CONFIG_EARLY_PRINTK) += earlycons.o
diff --git a/arch/mips/netlogic/common/earlycons.c b/arch/mips/netlogic/common/earlycons.c
new file mode 100644
index 000000000..8f5bc1597
--- /dev/null
+++ b/arch/mips/netlogic/common/earlycons.c
@@ -0,0 +1,63 @@
1/*
2 * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
3 * 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 NetLogic
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 NETLOGIC ``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 NETLOGIC 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/types.h>
36#include <linux/serial_reg.h>
37
38#include <asm/mipsregs.h>
39#include <asm/setup.h>
40#include <asm/netlogic/haldefs.h>
41#include <asm/netlogic/common.h>
42
43#if defined(CONFIG_CPU_XLP)
44#include <asm/netlogic/xlp-hal/iomap.h>
45#include <asm/netlogic/xlp-hal/xlp.h>
46#include <asm/netlogic/xlp-hal/uart.h>
47#elif defined(CONFIG_CPU_XLR)
48#include <asm/netlogic/xlr/iomap.h>
49#endif
50
51void prom_putchar(char c)
52{
53 uint64_t uartbase;
54
55#if defined(CONFIG_CPU_XLP)
56 uartbase = nlm_get_uart_regbase(0, 0);
57#elif defined(CONFIG_CPU_XLR)
58 uartbase = nlm_mmio_base(NETLOGIC_IO_UART_0_OFFSET);
59#endif
60 while ((nlm_read_reg(uartbase, UART_LSR) & UART_LSR_THRE) == 0)
61 ;
62 nlm_write_reg(uartbase, UART_TX, c);
63}
diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c
new file mode 100644
index 000000000..cf33dd8a4
--- /dev/null
+++ b/arch/mips/netlogic/common/irq.c
@@ -0,0 +1,354 @@
1/*
2 * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
3 * 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 NetLogic
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 NETLOGIC ``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 NETLOGIC 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/init.h>
37#include <linux/linkage.h>
38#include <linux/interrupt.h>
39#include <linux/mm.h>
40#include <linux/slab.h>
41#include <linux/irq.h>
42
43#include <linux/irqdomain.h>
44#include <linux/of_address.h>
45#include <linux/of_irq.h>
46
47#include <asm/errno.h>
48#include <asm/signal.h>
49#include <asm/ptrace.h>
50#include <asm/mipsregs.h>
51#include <asm/thread_info.h>
52
53#include <asm/netlogic/mips-extns.h>
54#include <asm/netlogic/interrupt.h>
55#include <asm/netlogic/haldefs.h>
56#include <asm/netlogic/common.h>
57
58#if defined(CONFIG_CPU_XLP)
59#include <asm/netlogic/xlp-hal/iomap.h>
60#include <asm/netlogic/xlp-hal/xlp.h>
61#include <asm/netlogic/xlp-hal/pic.h>
62#elif defined(CONFIG_CPU_XLR)
63#include <asm/netlogic/xlr/iomap.h>
64#include <asm/netlogic/xlr/pic.h>
65#include <asm/netlogic/xlr/fmn.h>
66#else
67#error "Unknown CPU"
68#endif
69
70#ifdef CONFIG_SMP
71#define SMP_IRQ_MASK ((1ULL << IRQ_IPI_SMP_FUNCTION) | \
72 (1ULL << IRQ_IPI_SMP_RESCHEDULE))
73#else
74#define SMP_IRQ_MASK 0
75#endif
76#define PERCPU_IRQ_MASK (SMP_IRQ_MASK | (1ull << IRQ_TIMER) | \
77 (1ull << IRQ_FMN))
78
79struct nlm_pic_irq {
80 void (*extra_ack)(struct irq_data *);
81 struct nlm_soc_info *node;
82 int picirq;
83 int irt;
84 int flags;
85};
86
87static void xlp_pic_enable(struct irq_data *d)
88{
89 unsigned long flags;
90 struct nlm_pic_irq *pd = irq_data_get_irq_chip_data(d);
91
92 BUG_ON(!pd);
93 spin_lock_irqsave(&pd->node->piclock, flags);
94 nlm_pic_enable_irt(pd->node->picbase, pd->irt);
95 spin_unlock_irqrestore(&pd->node->piclock, flags);
96}
97
98static void xlp_pic_disable(struct irq_data *d)
99{
100 struct nlm_pic_irq *pd = irq_data_get_irq_chip_data(d);
101 unsigned long flags;
102
103 BUG_ON(!pd);
104 spin_lock_irqsave(&pd->node->piclock, flags);
105 nlm_pic_disable_irt(pd->node->picbase, pd->irt);
106 spin_unlock_irqrestore(&pd->node->piclock, flags);
107}
108
109static void xlp_pic_mask_ack(struct irq_data *d)
110{
111 struct nlm_pic_irq *pd = irq_data_get_irq_chip_data(d);
112
113 clear_c0_eimr(pd->picirq);
114 ack_c0_eirr(pd->picirq);
115}
116
117static void xlp_pic_unmask(struct irq_data *d)
118{
119 struct nlm_pic_irq *pd = irq_data_get_irq_chip_data(d);
120
121 BUG_ON(!pd);
122
123 if (pd->extra_ack)
124 pd->extra_ack(d);
125
126 /* re-enable the intr on this cpu */
127 set_c0_eimr(pd->picirq);
128
129 /* Ack is a single write, no need to lock */
130 nlm_pic_ack(pd->node->picbase, pd->irt);
131}
132
133static struct irq_chip xlp_pic = {
134 .name = "XLP-PIC",
135 .irq_enable = xlp_pic_enable,
136 .irq_disable = xlp_pic_disable,
137 .irq_mask_ack = xlp_pic_mask_ack,
138 .irq_unmask = xlp_pic_unmask,
139};
140
141static void cpuintr_disable(struct irq_data *d)
142{
143 clear_c0_eimr(d->irq);
144}
145
146static void cpuintr_enable(struct irq_data *d)
147{
148 set_c0_eimr(d->irq);
149}
150
151static void cpuintr_ack(struct irq_data *d)
152{
153 ack_c0_eirr(d->irq);
154}
155
156/*
157 * Chip definition for CPU originated interrupts(timer, msg) and
158 * IPIs
159 */
160struct irq_chip nlm_cpu_intr = {
161 .name = "XLP-CPU-INTR",
162 .irq_enable = cpuintr_enable,
163 .irq_disable = cpuintr_disable,
164 .irq_mask = cpuintr_disable,
165 .irq_ack = cpuintr_ack,
166 .irq_eoi = cpuintr_enable,
167};
168
169static void __init nlm_init_percpu_irqs(void)
170{
171 int i;
172
173 for (i = 0; i < PIC_IRT_FIRST_IRQ; i++)
174 irq_set_chip_and_handler(i, &nlm_cpu_intr, handle_percpu_irq);
175#ifdef CONFIG_SMP
176 irq_set_chip_and_handler(IRQ_IPI_SMP_FUNCTION, &nlm_cpu_intr,
177 nlm_smp_function_ipi_handler);
178 irq_set_chip_and_handler(IRQ_IPI_SMP_RESCHEDULE, &nlm_cpu_intr,
179 nlm_smp_resched_ipi_handler);
180#endif
181}
182
183
184void nlm_setup_pic_irq(int node, int picirq, int irq, int irt)
185{
186 struct nlm_pic_irq *pic_data;
187 int xirq;
188
189 xirq = nlm_irq_to_xirq(node, irq);
190 pic_data = kzalloc(sizeof(*pic_data), GFP_KERNEL);
191 BUG_ON(pic_data == NULL);
192 pic_data->irt = irt;
193 pic_data->picirq = picirq;
194 pic_data->node = nlm_get_node(node);
195 irq_set_chip_and_handler(xirq, &xlp_pic, handle_level_irq);
196 irq_set_chip_data(xirq, pic_data);
197}
198
199void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))
200{
201 struct nlm_pic_irq *pic_data;
202 int xirq;
203
204 xirq = nlm_irq_to_xirq(node, irq);
205 pic_data = irq_get_chip_data(xirq);
206 if (WARN_ON(!pic_data))
207 return;
208 pic_data->extra_ack = xack;
209}
210
211static void nlm_init_node_irqs(int node)
212{
213 struct nlm_soc_info *nodep;
214 int i, irt;
215
216 pr_info("Init IRQ for node %d\n", node);
217 nodep = nlm_get_node(node);
218 nodep->irqmask = PERCPU_IRQ_MASK;
219 for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++) {
220 irt = nlm_irq_to_irt(i);
221 if (irt == -1) /* unused irq */
222 continue;
223 nodep->irqmask |= 1ull << i;
224 if (irt == -2) /* not a direct PIC irq */
225 continue;
226
227 nlm_pic_init_irt(nodep->picbase, irt, i,
228 node * nlm_threads_per_node(), 0);
229 nlm_setup_pic_irq(node, i, i, irt);
230 }
231}
232
233void nlm_smp_irq_init(int hwtid)
234{
235 int cpu, node;
236
237 cpu = hwtid % nlm_threads_per_node();
238 node = hwtid / nlm_threads_per_node();
239
240 if (cpu == 0 && node != 0)
241 nlm_init_node_irqs(node);
242 write_c0_eimr(nlm_get_node(node)->irqmask);
243}
244
245asmlinkage void plat_irq_dispatch(void)
246{
247 uint64_t eirr;
248 int i, node;
249
250 node = nlm_nodeid();
251 eirr = read_c0_eirr_and_eimr();
252 if (eirr == 0)
253 return;
254
255 i = __ffs64(eirr);
256 /* per-CPU IRQs don't need translation */
257 if (i < PIC_IRQ_BASE) {
258 do_IRQ(i);
259 return;
260 }
261
262#if defined(CONFIG_PCI_MSI) && defined(CONFIG_CPU_XLP)
263 /* PCI interrupts need a second level dispatch for MSI bits */
264 if (i >= PIC_PCIE_LINK_MSI_IRQ(0) && i <= PIC_PCIE_LINK_MSI_IRQ(3)) {
265 nlm_dispatch_msi(node, i);
266 return;
267 }
268 if (i >= PIC_PCIE_MSIX_IRQ(0) && i <= PIC_PCIE_MSIX_IRQ(3)) {
269 nlm_dispatch_msix(node, i);
270 return;
271 }
272
273#endif
274 /* top level irq handling */
275 do_IRQ(nlm_irq_to_xirq(node, i));
276}
277
278#ifdef CONFIG_CPU_XLP
279static const struct irq_domain_ops xlp_pic_irq_domain_ops = {
280 .xlate = irq_domain_xlate_onetwocell,
281};
282
283static int __init xlp_of_pic_init(struct device_node *node,
284 struct device_node *parent)
285{
286 const int n_picirqs = PIC_IRT_LAST_IRQ - PIC_IRQ_BASE + 1;
287 struct irq_domain *xlp_pic_domain;
288 struct resource res;
289 int socid, ret, bus;
290
291 /* we need a hack to get the PIC's SoC chip id */
292 ret = of_address_to_resource(node, 0, &res);
293 if (ret < 0) {
294 pr_err("PIC %pOFn: reg property not found!\n", node);
295 return -EINVAL;
296 }
297
298 if (cpu_is_xlp9xx()) {
299 bus = (res.start >> 20) & 0xf;
300 for (socid = 0; socid < NLM_NR_NODES; socid++) {
301 if (!nlm_node_present(socid))
302 continue;
303 if (nlm_get_node(socid)->socbus == bus)
304 break;
305 }
306 if (socid == NLM_NR_NODES) {
307 pr_err("PIC %pOFn: Node mapping for bus %d not found!\n",
308 node, bus);
309 return -EINVAL;
310 }
311 } else {
312 socid = (res.start >> 18) & 0x3;
313 if (!nlm_node_present(socid)) {
314 pr_err("PIC %pOFn: node %d does not exist!\n",
315 node, socid);
316 return -EINVAL;
317 }
318 }
319
320 if (!nlm_node_present(socid)) {
321 pr_err("PIC %pOFn: node %d does not exist!\n", node, socid);
322 return -EINVAL;
323 }
324
325 xlp_pic_domain = irq_domain_add_legacy(node, n_picirqs,
326 nlm_irq_to_xirq(socid, PIC_IRQ_BASE), PIC_IRQ_BASE,
327 &xlp_pic_irq_domain_ops, NULL);
328 if (xlp_pic_domain == NULL) {
329 pr_err("PIC %pOFn: Creating legacy domain failed!\n", node);
330 return -EINVAL;
331 }
332 pr_info("Node %d: IRQ domain created for PIC@%pR\n", socid, &res);
333 return 0;
334}
335
336static struct of_device_id __initdata xlp_pic_irq_ids[] = {
337 { .compatible = "netlogic,xlp-pic", .data = xlp_of_pic_init },
338 {},
339};
340#endif
341
342void __init arch_init_irq(void)
343{
344 /* Initialize the irq descriptors */
345 nlm_init_percpu_irqs();
346 nlm_init_node_irqs(0);
347 write_c0_eimr(nlm_current_node()->irqmask);
348#if defined(CONFIG_CPU_XLR)
349 nlm_setup_fmn_irq();
350#endif
351#ifdef CONFIG_CPU_XLP
352 of_irq_init(xlp_pic_irq_ids);
353#endif
354}
diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S
new file mode 100644
index 000000000..c474981a6
--- /dev/null
+++ b/arch/mips/netlogic/common/reset.S
@@ -0,0 +1,299 @@
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
36#include <asm/asm.h>
37#include <asm/asm-offsets.h>
38#include <asm/cpu.h>
39#include <asm/cacheops.h>
40#include <asm/regdef.h>
41#include <asm/mipsregs.h>
42#include <asm/stackframe.h>
43#include <asm/asmmacro.h>
44#include <asm/addrspace.h>
45
46#include <asm/netlogic/common.h>
47
48#include <asm/netlogic/xlp-hal/iomap.h>
49#include <asm/netlogic/xlp-hal/xlp.h>
50#include <asm/netlogic/xlp-hal/sys.h>
51#include <asm/netlogic/xlp-hal/cpucontrol.h>
52
53#define SYS_CPU_COHERENT_BASE CKSEG1ADDR(XLP_DEFAULT_IO_BASE) + \
54 XLP_IO_SYS_OFFSET(0) + XLP_IO_PCI_HDRSZ + \
55 SYS_CPU_NONCOHERENT_MODE * 4
56
57/* Enable XLP features and workarounds in the LSU */
58.macro xlp_config_lsu
59 li t0, LSU_DEFEATURE
60 mfcr t1, t0
61
62 lui t2, 0x4080 /* Enable Unaligned Access, L2HPE */
63 or t1, t1, t2
64 mtcr t1, t0
65
66 li t0, ICU_DEFEATURE
67 mfcr t1, t0
68 ori t1, 0x1000 /* Enable Icache partitioning */
69 mtcr t1, t0
70
71 li t0, SCHED_DEFEATURE
72 lui t1, 0x0100 /* Disable BRU accepting ALU ops */
73 mtcr t1, t0
74.endm
75
76/*
77 * Allow access to physical mem >64G by enabling ELPA in PAGEGRAIN
78 * register. This is needed before going to C code since the SP can
79 * in this region. Called from all HW threads.
80 */
81.macro xlp_early_mmu_init
82 mfc0 t0, CP0_PAGEMASK, 1
83 li t1, (1 << 29) /* ELPA bit */
84 or t0, t1
85 mtc0 t0, CP0_PAGEMASK, 1
86.endm
87
88/*
89 * L1D cache has to be flushed before enabling threads in XLP.
90 * On XLP8xx/XLP3xx, we do a low level flush using processor control
91 * registers. On XLPII CPUs, usual cache instructions work.
92 */
93.macro xlp_flush_l1_dcache
94 mfc0 t0, CP0_PRID
95 andi t0, t0, PRID_IMP_MASK
96 slt t1, t0, 0x1200
97 beqz t1, 15f
98 nop
99
100 /* XLP8xx low level cache flush */
101 li t0, LSU_DEBUG_DATA0
102 li t1, LSU_DEBUG_ADDR
103 li t2, 0 /* index */
104 li t3, 0x1000 /* loop count */
10511:
106 sll v0, t2, 5
107 mtcr zero, t0
108 ori v1, v0, 0x3 /* way0 | write_enable | write_active */
109 mtcr v1, t1
11012:
111 mfcr v1, t1
112 andi v1, 0x1 /* wait for write_active == 0 */
113 bnez v1, 12b
114 nop
115 mtcr zero, t0
116 ori v1, v0, 0x7 /* way1 | write_enable | write_active */
117 mtcr v1, t1
11813:
119 mfcr v1, t1
120 andi v1, 0x1 /* wait for write_active == 0 */
121 bnez v1, 13b
122 nop
123 addi t2, 1
124 bne t3, t2, 11b
125 nop
126 b 17f
127 nop
128
129 /* XLPII CPUs, Invalidate all 64k of L1 D-cache */
13015:
131 li t0, 0x80000000
132 li t1, 0x80010000
13316: cache Index_Writeback_Inv_D, 0(t0)
134 addiu t0, t0, 32
135 bne t0, t1, 16b
136 nop
13717:
138.endm
139
140/*
141 * nlm_reset_entry will be copied to the reset entry point for
142 * XLR and XLP. The XLP cores start here when they are woken up. This
143 * is also the NMI entry point.
144 *
145 * We use scratch reg 6/7 to save k0/k1 and check for NMI first.
146 *
147 * The data corresponding to reset/NMI is stored at RESET_DATA_PHYS
148 * location, this will have the thread mask (used when core is woken up)
149 * and the current NMI handler in case we reached here for an NMI.
150 *
151 * When a core or thread is newly woken up, it marks itself ready and
152 * loops in a 'wait'. When the CPU really needs waking up, we send an NMI
153 * IPI to it, with the NMI handler set to prom_boot_secondary_cpus
154 */
155 .set noreorder
156 .set noat
157 .set arch=xlr /* for mfcr/mtcr, XLR is sufficient */
158
159FEXPORT(nlm_reset_entry)
160 dmtc0 k0, $22, 6
161 dmtc0 k1, $22, 7
162 mfc0 k0, CP0_STATUS
163 li k1, 0x80000
164 and k1, k0, k1
165 beqz k1, 1f /* go to real reset entry */
166 nop
167 li k1, CKSEG1ADDR(RESET_DATA_PHYS) /* NMI */
168 ld k0, BOOT_NMI_HANDLER(k1)
169 jr k0
170 nop
171
1721: /* Entry point on core wakeup */
173 mfc0 t0, CP0_PRID /* processor ID */
174 andi t0, PRID_IMP_MASK
175 li t1, 0x1500 /* XLP 9xx */
176 beq t0, t1, 2f /* does not need to set coherent */
177 nop
178
179 li t1, 0x1300 /* XLP 5xx */
180 beq t0, t1, 2f /* does not need to set coherent */
181 nop
182
183 /* set bit in SYS coherent register for the core */
184 mfc0 t0, CP0_EBASE
185 mfc0 t1, CP0_EBASE
186 srl t1, 5
187 andi t1, 0x3 /* t1 <- node */
188 li t2, 0x40000
189 mul t3, t2, t1 /* t3 = node * 0x40000 */
190 srl t0, t0, 2
191 and t0, t0, 0x7 /* t0 <- core */
192 li t1, 0x1
193 sll t0, t1, t0
194 nor t0, t0, zero /* t0 <- ~(1 << core) */
195 li t2, SYS_CPU_COHERENT_BASE
196 add t2, t2, t3 /* t2 <- SYS offset for node */
197 lw t1, 0(t2)
198 and t1, t1, t0
199 sw t1, 0(t2)
200
201 /* read back to ensure complete */
202 lw t1, 0(t2)
203 sync
204
2052:
206 /* Configure LSU on Non-0 Cores. */
207 xlp_config_lsu
208 /* FALL THROUGH */
209
210/*
211 * Wake up sibling threads from the initial thread in a core.
212 */
213EXPORT(nlm_boot_siblings)
214 /* core L1D flush before enable threads */
215 xlp_flush_l1_dcache
216 /* save ra and sp, will be used later (only for boot cpu) */
217 dmtc0 ra, $22, 6
218 dmtc0 sp, $22, 7
219 /* Enable hw threads by writing to MAP_THREADMODE of the core */
220 li t0, CKSEG1ADDR(RESET_DATA_PHYS)
221 lw t1, BOOT_THREAD_MODE(t0) /* t1 <- thread mode */
222 li t0, ((CPU_BLOCKID_MAP << 8) | MAP_THREADMODE)
223 mfcr t2, t0
224 or t2, t2, t1
225 mtcr t2, t0
226
227 /*
228 * The new hardware thread starts at the next instruction
229 * For all the cases other than core 0 thread 0, we will
230 * jump to the secondary wait function.
231
232 * NOTE: All GPR contents are lost after the mtcr above!
233 */
234 mfc0 v0, CP0_EBASE
235 andi v0, 0x3ff /* v0 <- node/core */
236
237 /*
238 * Errata: to avoid potential live lock, setup IFU_BRUB_RESERVE
239 * when running 4 threads per core
240 */
241 andi v1, v0, 0x3 /* v1 <- thread id */
242 bnez v1, 2f
243 nop
244
245 /* thread 0 of each core. */
246 li t0, CKSEG1ADDR(RESET_DATA_PHYS)
247 lw t1, BOOT_THREAD_MODE(t0) /* t1 <- thread mode */
248 subu t1, 0x3 /* 4-thread per core mode? */
249 bnez t1, 2f
250 nop
251
252 li t0, IFU_BRUB_RESERVE
253 li t1, 0x55
254 mtcr t1, t0
255 _ehb
2562:
257 beqz v0, 4f /* boot cpu (cpuid == 0)? */
258 nop
259
260 /* setup status reg */
261 move t1, zero
262#ifdef CONFIG_64BIT
263 ori t1, ST0_KX
264#endif
265 mtc0 t1, CP0_STATUS
266
267 xlp_early_mmu_init
268
269 /* mark CPU ready */
270 li t3, CKSEG1ADDR(RESET_DATA_PHYS)
271 ADDIU t1, t3, BOOT_CPU_READY
272 sll v1, v0, 2
273 PTR_ADDU t1, v1
274 li t2, 1
275 sw t2, 0(t1)
276 /* Wait until NMI hits */
2773: wait
278 b 3b
279 nop
280
281 /*
282 * For the boot CPU, we have to restore ra and sp and return, rest
283 * of the registers will be restored by the caller
284 */
2854:
286 dmfc0 ra, $22, 6
287 dmfc0 sp, $22, 7
288 jr ra
289 nop
290EXPORT(nlm_reset_entry_end)
291
292LEAF(nlm_init_boot_cpu)
293#ifdef CONFIG_CPU_XLP
294 xlp_config_lsu
295 xlp_early_mmu_init
296#endif
297 jr ra
298 nop
299END(nlm_init_boot_cpu)
diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
new file mode 100644
index 000000000..39a300bd6
--- /dev/null
+++ b/arch/mips/netlogic/common/smp.c
@@ -0,0 +1,285 @@
1/*
2 * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
3 * 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 NetLogic
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 NETLOGIC ``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 NETLOGIC 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/delay.h>
37#include <linux/init.h>
38#include <linux/sched/task_stack.h>
39#include <linux/smp.h>
40#include <linux/irq.h>
41
42#include <asm/mmu_context.h>
43
44#include <asm/netlogic/interrupt.h>
45#include <asm/netlogic/mips-extns.h>
46#include <asm/netlogic/haldefs.h>
47#include <asm/netlogic/common.h>
48
49#if defined(CONFIG_CPU_XLP)
50#include <asm/netlogic/xlp-hal/iomap.h>
51#include <asm/netlogic/xlp-hal/xlp.h>
52#include <asm/netlogic/xlp-hal/pic.h>
53#elif defined(CONFIG_CPU_XLR)
54#include <asm/netlogic/xlr/iomap.h>
55#include <asm/netlogic/xlr/pic.h>
56#include <asm/netlogic/xlr/xlr.h>
57#else
58#error "Unknown CPU"
59#endif
60
61void nlm_send_ipi_single(int logical_cpu, unsigned int action)
62{
63 unsigned int hwtid;
64 uint64_t picbase;
65
66 /* node id is part of hwtid, and needed for send_ipi */
67 hwtid = cpu_logical_map(logical_cpu);
68 picbase = nlm_get_node(nlm_hwtid_to_node(hwtid))->picbase;
69
70 if (action & SMP_CALL_FUNCTION)
71 nlm_pic_send_ipi(picbase, hwtid, IRQ_IPI_SMP_FUNCTION, 0);
72 if (action & SMP_RESCHEDULE_YOURSELF)
73 nlm_pic_send_ipi(picbase, hwtid, IRQ_IPI_SMP_RESCHEDULE, 0);
74}
75
76void nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action)
77{
78 int cpu;
79
80 for_each_cpu(cpu, mask) {
81 nlm_send_ipi_single(cpu, action);
82 }
83}
84
85/* IRQ_IPI_SMP_FUNCTION Handler */
86void nlm_smp_function_ipi_handler(struct irq_desc *desc)
87{
88 unsigned int irq = irq_desc_get_irq(desc);
89 clear_c0_eimr(irq);
90 ack_c0_eirr(irq);
91 generic_smp_call_function_interrupt();
92 set_c0_eimr(irq);
93}
94
95/* IRQ_IPI_SMP_RESCHEDULE handler */
96void nlm_smp_resched_ipi_handler(struct irq_desc *desc)
97{
98 unsigned int irq = irq_desc_get_irq(desc);
99 clear_c0_eimr(irq);
100 ack_c0_eirr(irq);
101 scheduler_ipi();
102 set_c0_eimr(irq);
103}
104
105/*
106 * Called before going into mips code, early cpu init
107 */
108void nlm_early_init_secondary(int cpu)
109{
110 change_c0_config(CONF_CM_CMASK, 0x3);
111#ifdef CONFIG_CPU_XLP
112 xlp_mmu_init();
113#endif
114 write_c0_ebase(nlm_current_node()->ebase);
115}
116
117/*
118 * Code to run on secondary just after probing the CPU
119 */
120static void nlm_init_secondary(void)
121{
122 int hwtid;
123
124 hwtid = hard_smp_processor_id();
125 cpu_set_core(&current_cpu_data, hwtid / NLM_THREADS_PER_CORE);
126 current_cpu_data.package = nlm_nodeid();
127 nlm_percpu_init(hwtid);
128 nlm_smp_irq_init(hwtid);
129}
130
131void nlm_prepare_cpus(unsigned int max_cpus)
132{
133 /* declare we are SMT capable */
134 smp_num_siblings = nlm_threads_per_core;
135}
136
137void nlm_smp_finish(void)
138{
139 local_irq_enable();
140}
141
142/*
143 * Boot all other cpus in the system, initialize them, and bring them into
144 * the boot function
145 */
146unsigned long nlm_next_gp;
147unsigned long nlm_next_sp;
148static cpumask_t phys_cpu_present_mask;
149
150int nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
151{
152 uint64_t picbase;
153 int hwtid;
154
155 hwtid = cpu_logical_map(logical_cpu);
156 picbase = nlm_get_node(nlm_hwtid_to_node(hwtid))->picbase;
157
158 nlm_next_sp = (unsigned long)__KSTK_TOS(idle);
159 nlm_next_gp = (unsigned long)task_thread_info(idle);
160
161 /* barrier for sp/gp store above */
162 __sync();
163 nlm_pic_send_ipi(picbase, hwtid, 1, 1); /* NMI */
164
165 return 0;
166}
167
168void __init nlm_smp_setup(void)
169{
170 unsigned int boot_cpu;
171 int num_cpus, i, ncore, node;
172 volatile u32 *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY);
173
174 boot_cpu = hard_smp_processor_id();
175 cpumask_clear(&phys_cpu_present_mask);
176
177 cpumask_set_cpu(boot_cpu, &phys_cpu_present_mask);
178 __cpu_number_map[boot_cpu] = 0;
179 __cpu_logical_map[0] = boot_cpu;
180 set_cpu_possible(0, true);
181
182 num_cpus = 1;
183 for (i = 0; i < NR_CPUS; i++) {
184 /*
185 * cpu_ready array is not set for the boot_cpu,
186 * it is only set for ASPs (see smpboot.S)
187 */
188 if (cpu_ready[i]) {
189 cpumask_set_cpu(i, &phys_cpu_present_mask);
190 __cpu_number_map[i] = num_cpus;
191 __cpu_logical_map[num_cpus] = i;
192 set_cpu_possible(num_cpus, true);
193 node = nlm_hwtid_to_node(i);
194 cpumask_set_cpu(num_cpus, &nlm_get_node(node)->cpumask);
195 ++num_cpus;
196 }
197 }
198
199 pr_info("Physical CPU mask: %*pb\n",
200 cpumask_pr_args(&phys_cpu_present_mask));
201 pr_info("Possible CPU mask: %*pb\n",
202 cpumask_pr_args(cpu_possible_mask));
203
204 /* check with the cores we have woken up */
205 for (ncore = 0, i = 0; i < NLM_NR_NODES; i++)
206 ncore += hweight32(nlm_get_node(i)->coremask);
207
208 pr_info("Detected (%dc%dt) %d Slave CPU(s)\n", ncore,
209 nlm_threads_per_core, num_cpus);
210
211 /* switch NMI handler to boot CPUs */
212 nlm_set_nmi_handler(nlm_boot_secondary_cpus);
213}
214
215static int nlm_parse_cpumask(cpumask_t *wakeup_mask)
216{
217 uint32_t core0_thr_mask, core_thr_mask;
218 int threadmode, i, j;
219
220 core0_thr_mask = 0;
221 for (i = 0; i < NLM_THREADS_PER_CORE; i++)
222 if (cpumask_test_cpu(i, wakeup_mask))
223 core0_thr_mask |= (1 << i);
224 switch (core0_thr_mask) {
225 case 1:
226 nlm_threads_per_core = 1;
227 threadmode = 0;
228 break;
229 case 3:
230 nlm_threads_per_core = 2;
231 threadmode = 2;
232 break;
233 case 0xf:
234 nlm_threads_per_core = 4;
235 threadmode = 3;
236 break;
237 default:
238 goto unsupp;
239 }
240
241 /* Verify other cores CPU masks */
242 for (i = 0; i < NR_CPUS; i += NLM_THREADS_PER_CORE) {
243 core_thr_mask = 0;
244 for (j = 0; j < NLM_THREADS_PER_CORE; j++)
245 if (cpumask_test_cpu(i + j, wakeup_mask))
246 core_thr_mask |= (1 << j);
247 if (core_thr_mask != 0 && core_thr_mask != core0_thr_mask)
248 goto unsupp;
249 }
250 return threadmode;
251
252unsupp:
253 panic("Unsupported CPU mask %*pb", cpumask_pr_args(wakeup_mask));
254 return 0;
255}
256
257int nlm_wakeup_secondary_cpus(void)
258{
259 u32 *reset_data;
260 int threadmode;
261
262 /* verify the mask and setup core config variables */
263 threadmode = nlm_parse_cpumask(&nlm_cpumask);
264
265 /* Setup CPU init parameters */
266 reset_data = nlm_get_boot_data(BOOT_THREAD_MODE);
267 *reset_data = threadmode;
268
269#ifdef CONFIG_CPU_XLP
270 xlp_wakeup_secondary_cpus();
271#else
272 xlr_wakeup_secondary_cpus();
273#endif
274 return 0;
275}
276
277const struct plat_smp_ops nlm_smp_ops = {
278 .send_ipi_single = nlm_send_ipi_single,
279 .send_ipi_mask = nlm_send_ipi_mask,
280 .init_secondary = nlm_init_secondary,
281 .smp_finish = nlm_smp_finish,
282 .boot_secondary = nlm_boot_secondary,
283 .smp_setup = nlm_smp_setup,
284 .prepare_cpus = nlm_prepare_cpus,
285};
diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S
new file mode 100644
index 000000000..509c1a7e7
--- /dev/null
+++ b/arch/mips/netlogic/common/smpboot.S
@@ -0,0 +1,141 @@
1/*
2 * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
3 * 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 NetLogic
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 NETLOGIC ``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 NETLOGIC 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
36#include <asm/asm.h>
37#include <asm/asm-offsets.h>
38#include <asm/regdef.h>
39#include <asm/mipsregs.h>
40#include <asm/stackframe.h>
41#include <asm/asmmacro.h>
42#include <asm/addrspace.h>
43
44#include <asm/netlogic/common.h>
45
46#include <asm/netlogic/xlp-hal/iomap.h>
47#include <asm/netlogic/xlp-hal/xlp.h>
48#include <asm/netlogic/xlp-hal/sys.h>
49#include <asm/netlogic/xlp-hal/cpucontrol.h>
50
51 .set noreorder
52 .set noat
53 .set arch=xlr /* for mfcr/mtcr, XLR is sufficient */
54
55/* Called by the boot cpu to wake up its sibling threads */
56NESTED(xlp_boot_core0_siblings, PT_SIZE, sp)
57 /* CPU register contents lost when enabling threads, save them first */
58 SAVE_ALL
59 sync
60 /* find the location to which nlm_boot_siblings was relocated */
61 li t0, CKSEG1ADDR(RESET_VEC_PHYS)
62 PTR_LA t1, nlm_reset_entry
63 PTR_LA t2, nlm_boot_siblings
64 dsubu t2, t1
65 daddu t2, t0
66 /* call it */
67 jalr t2
68 nop
69 RESTORE_ALL
70 jr ra
71 nop
72END(xlp_boot_core0_siblings)
73
74NESTED(nlm_boot_secondary_cpus, 16, sp)
75 /* Initialize CP0 Status */
76 move t1, zero
77#ifdef CONFIG_64BIT
78 ori t1, ST0_KX
79#endif
80 mtc0 t1, CP0_STATUS
81 PTR_LA t1, nlm_next_sp
82 PTR_L sp, 0(t1)
83 PTR_LA t1, nlm_next_gp
84 PTR_L gp, 0(t1)
85
86 /* a0 has the processor id */
87 mfc0 a0, CP0_EBASE
88 andi a0, 0x3ff /* a0 <- node/core */
89 PTR_LA t0, nlm_early_init_secondary
90 jalr t0
91 nop
92
93 PTR_LA t0, smp_bootstrap
94 jr t0
95 nop
96END(nlm_boot_secondary_cpus)
97
98/*
99 * In case of RMIboot bootloader which is used on XLR boards, the CPUs
100 * be already woken up and waiting in bootloader code.
101 * This will get them out of the bootloader code and into linux. Needed
102 * because the bootloader area will be taken and initialized by linux.
103 */
104NESTED(nlm_rmiboot_preboot, 16, sp)
105 mfc0 t0, $15, 1 /* read ebase */
106 andi t0, 0x1f /* t0 has the processor_id() */
107 andi t2, t0, 0x3 /* thread num */
108 sll t0, 2 /* offset in cpu array */
109
110 li t3, CKSEG1ADDR(RESET_DATA_PHYS)
111 ADDIU t1, t3, BOOT_CPU_READY
112 ADDU t1, t0
113 li t3, 1
114 sw t3, 0(t1)
115
116 bnez t2, 1f /* skip thread programming */
117 nop /* for thread id != 0 */
118
119 /*
120 * XLR MMU setup only for first thread in core
121 */
122 li t0, 0x400
123 mfcr t1, t0
124 li t2, 6 /* XLR thread mode mask */
125 nor t3, t2, zero
126 and t2, t1, t2 /* t2 - current thread mode */
127 li v0, CKSEG1ADDR(RESET_DATA_PHYS)
128 lw v1, BOOT_THREAD_MODE(v0) /* v1 - new thread mode */
129 sll v1, 1
130 beq v1, t2, 1f /* same as request value */
131 nop /* nothing to do */
132
133 and t2, t1, t3 /* mask out old thread mode */
134 or t1, t2, v1 /* put in new value */
135 mtcr t1, t0 /* update core control */
136
137 /* wait for NMI to hit */
1381: wait
139 b 1b
140 nop
141END(nlm_rmiboot_preboot)
diff --git a/arch/mips/netlogic/common/time.c b/arch/mips/netlogic/common/time.c
new file mode 100644
index 000000000..cbbf0d482
--- /dev/null
+++ b/arch/mips/netlogic/common/time.c
@@ -0,0 +1,110 @@
1/*
2 * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
3 * 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 NetLogic
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 NETLOGIC ``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 NETLOGIC 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/init.h>
36
37#include <asm/time.h>
38#include <asm/cpu-features.h>
39
40#include <asm/netlogic/interrupt.h>
41#include <asm/netlogic/common.h>
42#include <asm/netlogic/haldefs.h>
43
44#if defined(CONFIG_CPU_XLP)
45#include <asm/netlogic/xlp-hal/iomap.h>
46#include <asm/netlogic/xlp-hal/xlp.h>
47#include <asm/netlogic/xlp-hal/sys.h>
48#include <asm/netlogic/xlp-hal/pic.h>
49#elif defined(CONFIG_CPU_XLR)
50#include <asm/netlogic/xlr/iomap.h>
51#include <asm/netlogic/xlr/pic.h>
52#include <asm/netlogic/xlr/xlr.h>
53#else
54#error "Unknown CPU"
55#endif
56
57unsigned int get_c0_compare_int(void)
58{
59 return IRQ_TIMER;
60}
61
62static u64 nlm_get_pic_timer(struct clocksource *cs)
63{
64 uint64_t picbase = nlm_get_node(0)->picbase;
65
66 return ~nlm_pic_read_timer(picbase, PIC_CLOCK_TIMER);
67}
68
69static u64 nlm_get_pic_timer32(struct clocksource *cs)
70{
71 uint64_t picbase = nlm_get_node(0)->picbase;
72
73 return ~nlm_pic_read_timer32(picbase, PIC_CLOCK_TIMER);
74}
75
76static struct clocksource csrc_pic = {
77 .name = "PIC",
78 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
79};
80
81static void nlm_init_pic_timer(void)
82{
83 uint64_t picbase = nlm_get_node(0)->picbase;
84 u32 picfreq;
85
86 nlm_pic_set_timer(picbase, PIC_CLOCK_TIMER, ~0ULL, 0, 0);
87 if (current_cpu_data.cputype == CPU_XLR) {
88 csrc_pic.mask = CLOCKSOURCE_MASK(32);
89 csrc_pic.read = nlm_get_pic_timer32;
90 } else {
91 csrc_pic.mask = CLOCKSOURCE_MASK(64);
92 csrc_pic.read = nlm_get_pic_timer;
93 }
94 csrc_pic.rating = 1000;
95 picfreq = pic_timer_freq();
96 clocksource_register_hz(&csrc_pic, picfreq);
97 pr_info("PIC clock source added, frequency %d\n", picfreq);
98}
99
100void __init plat_time_init(void)
101{
102 nlm_init_pic_timer();
103 mips_hpt_frequency = nlm_get_cpu_frequency();
104 if (current_cpu_type() == CPU_XLR)
105 preset_lpj = mips_hpt_frequency / (3 * HZ);
106 else
107 preset_lpj = mips_hpt_frequency / (2 * HZ);
108 pr_info("MIPS counter frequency [%ld]\n",
109 (unsigned long)mips_hpt_frequency);
110}
diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile
new file mode 100644
index 000000000..d62465717
--- /dev/null
+++ b/arch/mips/netlogic/xlp/Makefile
@@ -0,0 +1,11 @@
1# SPDX-License-Identifier: GPL-2.0
2obj-y += setup.o nlm_hal.o cop2-ex.o dt.o
3obj-$(CONFIG_SMP) += wakeup.o
4ifdef CONFIG_USB
5obj-y += usb-init.o
6obj-y += usb-init-xlp2.o
7endif
8ifdef CONFIG_SATA_AHCI
9obj-y += ahci-init.o
10obj-y += ahci-init-xlp2.o
11endif
diff --git a/arch/mips/netlogic/xlp/ahci-init-xlp2.c b/arch/mips/netlogic/xlp/ahci-init-xlp2.c
new file mode 100644
index 000000000..c11b9c7dc
--- /dev/null
+++ b/arch/mips/netlogic/xlp/ahci-init-xlp2.c
@@ -0,0 +1,390 @@
1/*
2 * Copyright (c) 2003-2014 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/dma-mapping.h>
36#include <linux/kernel.h>
37#include <linux/delay.h>
38#include <linux/init.h>
39#include <linux/pci.h>
40#include <linux/irq.h>
41#include <linux/bitops.h>
42#include <linux/pci_ids.h>
43#include <linux/nodemask.h>
44
45#include <asm/cpu.h>
46#include <asm/mipsregs.h>
47
48#include <asm/netlogic/common.h>
49#include <asm/netlogic/haldefs.h>
50#include <asm/netlogic/mips-extns.h>
51#include <asm/netlogic/xlp-hal/xlp.h>
52#include <asm/netlogic/xlp-hal/iomap.h>
53
54#define SATA_CTL 0x0
55#define SATA_STATUS 0x1 /* Status Reg */
56#define SATA_INT 0x2 /* Interrupt Reg */
57#define SATA_INT_MASK 0x3 /* Interrupt Mask Reg */
58#define SATA_BIU_TIMEOUT 0x4
59#define AXIWRSPERRLOG 0x5
60#define AXIRDSPERRLOG 0x6
61#define BiuTimeoutLow 0x7
62#define BiuTimeoutHi 0x8
63#define BiuSlvErLow 0x9
64#define BiuSlvErHi 0xa
65#define IO_CONFIG_SWAP_DIS 0xb
66#define CR_REG_TIMER 0xc
67#define CORE_ID 0xd
68#define AXI_SLAVE_OPT1 0xe
69#define PHY_MEM_ACCESS 0xf
70#define PHY0_CNTRL 0x10
71#define PHY0_STAT 0x11
72#define PHY0_RX_ALIGN 0x12
73#define PHY0_RX_EQ_LO 0x13
74#define PHY0_RX_EQ_HI 0x14
75#define PHY0_BIST_LOOP 0x15
76#define PHY1_CNTRL 0x16
77#define PHY1_STAT 0x17
78#define PHY1_RX_ALIGN 0x18
79#define PHY1_RX_EQ_LO 0x19
80#define PHY1_RX_EQ_HI 0x1a
81#define PHY1_BIST_LOOP 0x1b
82#define RdExBase 0x1c
83#define RdExLimit 0x1d
84#define CacheAllocBase 0x1e
85#define CacheAllocLimit 0x1f
86#define BiuSlaveCmdGstNum 0x20
87
88/*SATA_CTL Bits */
89#define SATA_RST_N BIT(0) /* Active low reset sata_core phy */
90#define SataCtlReserve0 BIT(1)
91#define M_CSYSREQ BIT(2) /* AXI master low power, not used */
92#define S_CSYSREQ BIT(3) /* AXI slave low power, not used */
93#define P0_CP_DET BIT(8) /* Reserved, bring in from pad */
94#define P0_MP_SW BIT(9) /* Mech Switch */
95#define P0_DISABLE BIT(10) /* disable p0 */
96#define P0_ACT_LED_EN BIT(11) /* Active LED enable */
97#define P0_IRST_HARD_SYNTH BIT(12) /* PHY hard synth reset */
98#define P0_IRST_HARD_TXRX BIT(13) /* PHY lane hard reset */
99#define P0_IRST_POR BIT(14) /* PHY power on reset*/
100#define P0_IPDTXL BIT(15) /* PHY Tx lane dis/power down */
101#define P0_IPDRXL BIT(16) /* PHY Rx lane dis/power down */
102#define P0_IPDIPDMSYNTH BIT(17) /* PHY synthesizer dis/porwer down */
103#define P0_CP_POD_EN BIT(18) /* CP_POD enable */
104#define P0_AT_BYPASS BIT(19) /* P0 address translation by pass */
105#define P1_CP_DET BIT(20) /* Reserved,Cold Detect */
106#define P1_MP_SW BIT(21) /* Mech Switch */
107#define P1_DISABLE BIT(22) /* disable p1 */
108#define P1_ACT_LED_EN BIT(23) /* Active LED enable */
109#define P1_IRST_HARD_SYNTH BIT(24) /* PHY hard synth reset */
110#define P1_IRST_HARD_TXRX BIT(25) /* PHY lane hard reset */
111#define P1_IRST_POR BIT(26) /* PHY power on reset*/
112#define P1_IPDTXL BIT(27) /* PHY Tx lane dis/porwer down */
113#define P1_IPDRXL BIT(28) /* PHY Rx lane dis/porwer down */
114#define P1_IPDIPDMSYNTH BIT(29) /* PHY synthesizer dis/porwer down */
115#define P1_CP_POD_EN BIT(30)
116#define P1_AT_BYPASS BIT(31) /* P1 address translation by pass */
117
118/* Status register */
119#define M_CACTIVE BIT(0) /* m_cactive, not used */
120#define S_CACTIVE BIT(1) /* s_cactive, not used */
121#define P0_PHY_READY BIT(8) /* phy is ready */
122#define P0_CP_POD BIT(9) /* Cold PowerOn */
123#define P0_SLUMBER BIT(10) /* power mode slumber */
124#define P0_PATIAL BIT(11) /* power mode patial */
125#define P0_PHY_SIG_DET BIT(12) /* phy dignal detect */
126#define P0_PHY_CALI BIT(13) /* phy calibration done */
127#define P1_PHY_READY BIT(16) /* phy is ready */
128#define P1_CP_POD BIT(17) /* Cold PowerOn */
129#define P1_SLUMBER BIT(18) /* power mode slumber */
130#define P1_PATIAL BIT(19) /* power mode patial */
131#define P1_PHY_SIG_DET BIT(20) /* phy dignal detect */
132#define P1_PHY_CALI BIT(21) /* phy calibration done */
133
134/* SATA CR_REG_TIMER bits */
135#define CR_TIME_SCALE (0x1000 << 0)
136
137/* SATA PHY specific registers start and end address */
138#define RXCDRCALFOSC0 0x0065
139#define CALDUTY 0x006e
140#define RXDPIF 0x8065
141#define PPMDRIFTMAX_HI 0x80A4
142
143#define nlm_read_sata_reg(b, r) nlm_read_reg(b, r)
144#define nlm_write_sata_reg(b, r, v) nlm_write_reg(b, r, v)
145#define nlm_get_sata_pcibase(node) \
146 nlm_pcicfg_base(XLP9XX_IO_SATA_OFFSET(node))
147#define nlm_get_sata_regbase(node) \
148 (nlm_get_sata_pcibase(node) + 0x100)
149
150/* SATA PHY config for register block 1 0x0065 .. 0x006e */
151static const u8 sata_phy_config1[] = {
152 0xC9, 0xC9, 0x07, 0x07, 0x18, 0x18, 0x01, 0x01, 0x22, 0x00
153};
154
155/* SATA PHY config for register block 2 0x8065 .. 0x80A4 */
156static const u8 sata_phy_config2[] = {
157 0xAA, 0x00, 0x4C, 0xC9, 0xC9, 0x07, 0x07, 0x18,
158 0x18, 0x05, 0x0C, 0x10, 0x00, 0x10, 0x00, 0xFF,
159 0xCF, 0xF7, 0xE1, 0xF5, 0xFD, 0xFD, 0xFF, 0xFF,
160 0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5, 0xFD, 0xFD,
161 0xF5, 0xF5, 0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5,
162 0xFD, 0xFD, 0xF5, 0xF5, 0xFF, 0xFF, 0xFF, 0xF5,
163 0x3F, 0x00, 0x32, 0x00, 0x03, 0x01, 0x05, 0x05,
164 0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x04,
165};
166
167const int sata_phy_debug = 0; /* set to verify PHY writes */
168
169static void sata_clear_glue_reg(u64 regbase, u32 off, u32 bit)
170{
171 u32 reg_val;
172
173 reg_val = nlm_read_sata_reg(regbase, off);
174 nlm_write_sata_reg(regbase, off, (reg_val & ~bit));
175}
176
177static void sata_set_glue_reg(u64 regbase, u32 off, u32 bit)
178{
179 u32 reg_val;
180
181 reg_val = nlm_read_sata_reg(regbase, off);
182 nlm_write_sata_reg(regbase, off, (reg_val | bit));
183}
184
185static void write_phy_reg(u64 regbase, u32 addr, u32 physel, u8 data)
186{
187 nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
188 (1u << 31) | (physel << 24) | (data << 16) | addr);
189 udelay(850);
190}
191
192static u8 read_phy_reg(u64 regbase, u32 addr, u32 physel)
193{
194 u32 val;
195
196 nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
197 (0 << 31) | (physel << 24) | (0 << 16) | addr);
198 udelay(850);
199 val = nlm_read_sata_reg(regbase, PHY_MEM_ACCESS);
200 return (val >> 16) & 0xff;
201}
202
203static void config_sata_phy(u64 regbase)
204{
205 u32 port, i, reg;
206 u8 val;
207
208 for (port = 0; port < 2; port++) {
209 for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
210 write_phy_reg(regbase, reg, port, sata_phy_config1[i]);
211
212 for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
213 write_phy_reg(regbase, reg, port, sata_phy_config2[i]);
214
215 /* Fix for PHY link up failures at lower temperatures */
216 write_phy_reg(regbase, 0x800F, port, 0x1f);
217
218 val = read_phy_reg(regbase, 0x0029, port);
219 write_phy_reg(regbase, 0x0029, port, val | (0x7 << 1));
220
221 val = read_phy_reg(regbase, 0x0056, port);
222 write_phy_reg(regbase, 0x0056, port, val & ~(1 << 3));
223
224 val = read_phy_reg(regbase, 0x0018, port);
225 write_phy_reg(regbase, 0x0018, port, val & ~(0x7 << 0));
226 }
227}
228
229static void check_phy_register(u64 regbase, u32 addr, u32 physel, u8 xdata)
230{
231 u8 data;
232
233 data = read_phy_reg(regbase, addr, physel);
234 pr_info("PHY read addr = 0x%x physel = %d data = 0x%x %s\n",
235 addr, physel, data, data == xdata ? "TRUE" : "FALSE");
236}
237
238static void verify_sata_phy_config(u64 regbase)
239{
240 u32 port, i, reg;
241
242 for (port = 0; port < 2; port++) {
243 for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
244 check_phy_register(regbase, reg, port,
245 sata_phy_config1[i]);
246
247 for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
248 check_phy_register(regbase, reg, port,
249 sata_phy_config2[i]);
250 }
251}
252
253static void nlm_sata_firmware_init(int node)
254{
255 u32 reg_val;
256 u64 regbase;
257 int n;
258
259 pr_info("Initializing XLP9XX On-chip AHCI...\n");
260 regbase = nlm_get_sata_regbase(node);
261
262 /* Reset port0 */
263 sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
264 sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
265 sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
266 sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
267 sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
268 sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
269
270 /* port1 */
271 sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
272 sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
273 sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
274 sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
275 sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
276 sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
277 udelay(300);
278
279 /* Set PHY */
280 sata_set_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
281 sata_set_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
282 sata_set_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
283 sata_set_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
284 sata_set_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
285 sata_set_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
286
287 udelay(1000);
288 sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
289 udelay(1000);
290 sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
291 udelay(1000);
292
293 /* setup PHY */
294 config_sata_phy(regbase);
295 if (sata_phy_debug)
296 verify_sata_phy_config(regbase);
297
298 udelay(1000);
299 sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
300 sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
301 sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
302 sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
303 udelay(300);
304
305 /* Override reset in serial PHY mode */
306 sata_set_glue_reg(regbase, CR_REG_TIMER, CR_TIME_SCALE);
307 /* Set reset SATA */
308 sata_set_glue_reg(regbase, SATA_CTL, SATA_RST_N);
309 sata_set_glue_reg(regbase, SATA_CTL, M_CSYSREQ);
310 sata_set_glue_reg(regbase, SATA_CTL, S_CSYSREQ);
311
312 pr_debug("Waiting for PHYs to come up.\n");
313 n = 10000;
314 do {
315 reg_val = nlm_read_sata_reg(regbase, SATA_STATUS);
316 if ((reg_val & P1_PHY_READY) && (reg_val & P0_PHY_READY))
317 break;
318 udelay(10);
319 } while (--n > 0);
320
321 if (reg_val & P0_PHY_READY)
322 pr_info("PHY0 is up.\n");
323 else
324 pr_info("PHY0 is down.\n");
325 if (reg_val & P1_PHY_READY)
326 pr_info("PHY1 is up.\n");
327 else
328 pr_info("PHY1 is down.\n");
329
330 pr_info("XLP AHCI Init Done.\n");
331}
332
333static int __init nlm_ahci_init(void)
334{
335 int node;
336
337 if (!cpu_is_xlp9xx())
338 return 0;
339 for (node = 0; node < NLM_NR_NODES; node++)
340 if (nlm_node_present(node))
341 nlm_sata_firmware_init(node);
342 return 0;
343}
344
345static void nlm_sata_intr_ack(struct irq_data *data)
346{
347 u64 regbase;
348 u32 val;
349 int node;
350
351 node = data->irq / NLM_IRQS_PER_NODE;
352 regbase = nlm_get_sata_regbase(node);
353 val = nlm_read_sata_reg(regbase, SATA_INT);
354 sata_set_glue_reg(regbase, SATA_INT, val);
355}
356
357static void nlm_sata_fixup_bar(struct pci_dev *dev)
358{
359 dev->resource[5] = dev->resource[0];
360 memset(&dev->resource[0], 0, sizeof(dev->resource[0]));
361}
362
363static void nlm_sata_fixup_final(struct pci_dev *dev)
364{
365 u32 val;
366 u64 regbase;
367 int node;
368
369 /* Find end bridge function to find node */
370 node = xlp_socdev_to_node(dev);
371 regbase = nlm_get_sata_regbase(node);
372
373 /* clear pending interrupts and then enable them */
374 val = nlm_read_sata_reg(regbase, SATA_INT);
375 sata_set_glue_reg(regbase, SATA_INT, val);
376
377 /* Enable only the core interrupt */
378 sata_set_glue_reg(regbase, SATA_INT_MASK, 0x1);
379
380 dev->irq = nlm_irq_to_xirq(node, PIC_SATA_IRQ);
381 nlm_set_pic_extra_ack(node, PIC_SATA_IRQ, nlm_sata_intr_ack);
382}
383
384arch_initcall(nlm_ahci_init);
385
386DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
387 nlm_sata_fixup_bar);
388
389DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
390 nlm_sata_fixup_final);
diff --git a/arch/mips/netlogic/xlp/ahci-init.c b/arch/mips/netlogic/xlp/ahci-init.c
new file mode 100644
index 000000000..92be1a325
--- /dev/null
+++ b/arch/mips/netlogic/xlp/ahci-init.c
@@ -0,0 +1,209 @@
1/*
2 * Copyright (c) 2003-2014 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/dma-mapping.h>
36#include <linux/kernel.h>
37#include <linux/delay.h>
38#include <linux/init.h>
39#include <linux/pci.h>
40#include <linux/irq.h>
41#include <linux/bitops.h>
42
43#include <asm/cpu.h>
44#include <asm/mipsregs.h>
45
46#include <asm/netlogic/haldefs.h>
47#include <asm/netlogic/xlp-hal/xlp.h>
48#include <asm/netlogic/common.h>
49#include <asm/netlogic/xlp-hal/iomap.h>
50#include <asm/netlogic/mips-extns.h>
51
52#define SATA_CTL 0x0
53#define SATA_STATUS 0x1 /* Status Reg */
54#define SATA_INT 0x2 /* Interrupt Reg */
55#define SATA_INT_MASK 0x3 /* Interrupt Mask Reg */
56#define SATA_CR_REG_TIMER 0x4 /* PHY Conrol Timer Reg */
57#define SATA_CORE_ID 0x5 /* Core ID Reg */
58#define SATA_AXI_SLAVE_OPT1 0x6 /* AXI Slave Options Reg */
59#define SATA_PHY_LOS_LEV 0x7 /* PHY LOS Level Reg */
60#define SATA_PHY_MULTI 0x8 /* PHY Multiplier Reg */
61#define SATA_PHY_CLK_SEL 0x9 /* Clock Select Reg */
62#define SATA_PHY_AMP1_GEN1 0xa /* PHY Transmit Amplitude Reg 1 */
63#define SATA_PHY_AMP1_GEN2 0xb /* PHY Transmit Amplitude Reg 2 */
64#define SATA_PHY_AMP1_GEN3 0xc /* PHY Transmit Amplitude Reg 3 */
65#define SATA_PHY_PRE1 0xd /* PHY Transmit Preemphasis Reg 1 */
66#define SATA_PHY_PRE2 0xe /* PHY Transmit Preemphasis Reg 2 */
67#define SATA_PHY_PRE3 0xf /* PHY Transmit Preemphasis Reg 3 */
68#define SATA_SPDMODE 0x10 /* Speed Mode Reg */
69#define SATA_REFCLK 0x11 /* Reference Clock Control Reg */
70#define SATA_BYTE_SWAP_DIS 0x12 /* byte swap disable */
71
72/*SATA_CTL Bits */
73#define SATA_RST_N BIT(0)
74#define PHY0_RESET_N BIT(16)
75#define PHY1_RESET_N BIT(17)
76#define PHY2_RESET_N BIT(18)
77#define PHY3_RESET_N BIT(19)
78#define M_CSYSREQ BIT(2)
79#define S_CSYSREQ BIT(3)
80
81/*SATA_STATUS Bits */
82#define P0_PHY_READY BIT(4)
83#define P1_PHY_READY BIT(5)
84#define P2_PHY_READY BIT(6)
85#define P3_PHY_READY BIT(7)
86
87#define nlm_read_sata_reg(b, r) nlm_read_reg(b, r)
88#define nlm_write_sata_reg(b, r, v) nlm_write_reg(b, r, v)
89#define nlm_get_sata_pcibase(node) \
90 nlm_pcicfg_base(XLP_IO_SATA_OFFSET(node))
91/* SATA device specific configuration registers are starts at 0x900 offset */
92#define nlm_get_sata_regbase(node) \
93 (nlm_get_sata_pcibase(node) + 0x900)
94
95static void sata_clear_glue_reg(uint64_t regbase, uint32_t off, uint32_t bit)
96{
97 uint32_t reg_val;
98
99 reg_val = nlm_read_sata_reg(regbase, off);
100 nlm_write_sata_reg(regbase, off, (reg_val & ~bit));
101}
102
103static void sata_set_glue_reg(uint64_t regbase, uint32_t off, uint32_t bit)
104{
105 uint32_t reg_val;
106
107 reg_val = nlm_read_sata_reg(regbase, off);
108 nlm_write_sata_reg(regbase, off, (reg_val | bit));
109}
110
111static void nlm_sata_firmware_init(int node)
112{
113 uint32_t reg_val;
114 uint64_t regbase;
115 int i;
116
117 pr_info("XLP AHCI Initialization started.\n");
118 regbase = nlm_get_sata_regbase(node);
119
120 /* Reset SATA */
121 sata_clear_glue_reg(regbase, SATA_CTL, SATA_RST_N);
122 /* Reset PHY */
123 sata_clear_glue_reg(regbase, SATA_CTL,
124 (PHY3_RESET_N | PHY2_RESET_N
125 | PHY1_RESET_N | PHY0_RESET_N));
126
127 /* Set SATA */
128 sata_set_glue_reg(regbase, SATA_CTL, SATA_RST_N);
129 /* Set PHY */
130 sata_set_glue_reg(regbase, SATA_CTL,
131 (PHY3_RESET_N | PHY2_RESET_N
132 | PHY1_RESET_N | PHY0_RESET_N));
133
134 pr_debug("Waiting for PHYs to come up.\n");
135 i = 0;
136 do {
137 reg_val = nlm_read_sata_reg(regbase, SATA_STATUS);
138 i++;
139 } while (((reg_val & 0xF0) != 0xF0) && (i < 10000));
140
141 for (i = 0; i < 4; i++) {
142 if (reg_val & (P0_PHY_READY << i))
143 pr_info("PHY%d is up.\n", i);
144 else
145 pr_info("PHY%d is down.\n", i);
146 }
147
148 pr_info("XLP AHCI init done.\n");
149}
150
151static int __init nlm_ahci_init(void)
152{
153 int node = 0;
154 int chip = read_c0_prid() & PRID_IMP_MASK;
155
156 if (chip == PRID_IMP_NETLOGIC_XLP3XX)
157 nlm_sata_firmware_init(node);
158 return 0;
159}
160
161static void nlm_sata_intr_ack(struct irq_data *data)
162{
163 uint32_t val = 0;
164 uint64_t regbase;
165
166 regbase = nlm_get_sata_regbase(nlm_nodeid());
167 val = nlm_read_sata_reg(regbase, SATA_INT);
168 sata_set_glue_reg(regbase, SATA_INT, val);
169}
170
171static void nlm_sata_fixup_bar(struct pci_dev *dev)
172{
173 /*
174 * The AHCI resource is in BAR 0, move it to
175 * BAR 5, where it is expected
176 */
177 dev->resource[5] = dev->resource[0];
178 memset(&dev->resource[0], 0, sizeof(dev->resource[0]));
179}
180
181static void nlm_sata_fixup_final(struct pci_dev *dev)
182{
183 uint32_t val;
184 uint64_t regbase;
185 int node = 0; /* XLP3XX does not support multi-node */
186
187 regbase = nlm_get_sata_regbase(node);
188
189 /* clear pending interrupts and then enable them */
190 val = nlm_read_sata_reg(regbase, SATA_INT);
191 sata_set_glue_reg(regbase, SATA_INT, val);
192
193 /* Mask the core interrupt. If all the interrupts
194 * are enabled there are spurious interrupt flow
195 * happening, to avoid only enable core interrupt
196 * mask.
197 */
198 sata_set_glue_reg(regbase, SATA_INT_MASK, 0x1);
199
200 dev->irq = PIC_SATA_IRQ;
201 nlm_set_pic_extra_ack(node, PIC_SATA_IRQ, nlm_sata_intr_ack);
202}
203
204arch_initcall(nlm_ahci_init);
205
206DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_SATA,
207 nlm_sata_fixup_bar);
208DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_SATA,
209 nlm_sata_fixup_final);
diff --git a/arch/mips/netlogic/xlp/cop2-ex.c b/arch/mips/netlogic/xlp/cop2-ex.c
new file mode 100644
index 000000000..21e439b3d
--- /dev/null
+++ b/arch/mips/netlogic/xlp/cop2-ex.c
@@ -0,0 +1,121 @@
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/capability.h>
13#include <linux/init.h>
14#include <linux/irqflags.h>
15#include <linux/notifier.h>
16#include <linux/prefetch.h>
17#include <linux/ptrace.h>
18#include <linux/sched.h>
19#include <linux/sched/task_stack.h>
20
21#include <asm/cop2.h>
22#include <asm/current.h>
23#include <asm/mipsregs.h>
24#include <asm/page.h>
25
26#include <asm/netlogic/mips-extns.h>
27
28/*
29 * 64 bit ops are done in inline assembly to support 32 bit
30 * compilation
31 */
32void nlm_cop2_save(struct nlm_cop2_state *r)
33{
34 asm volatile(
35 ".set push\n"
36 ".set noat\n"
37 "dmfc2 $1, $0, 0\n"
38 "sd $1, 0(%1)\n"
39 "dmfc2 $1, $0, 1\n"
40 "sd $1, 8(%1)\n"
41 "dmfc2 $1, $0, 2\n"
42 "sd $1, 16(%1)\n"
43 "dmfc2 $1, $0, 3\n"
44 "sd $1, 24(%1)\n"
45 "dmfc2 $1, $1, 0\n"
46 "sd $1, 0(%2)\n"
47 "dmfc2 $1, $1, 1\n"
48 "sd $1, 8(%2)\n"
49 "dmfc2 $1, $1, 2\n"
50 "sd $1, 16(%2)\n"
51 "dmfc2 $1, $1, 3\n"
52 "sd $1, 24(%2)\n"
53 ".set pop\n"
54 : "=m"(*r)
55 : "r"(r->tx), "r"(r->rx));
56
57 r->tx_msg_status = __read_32bit_c2_register($2, 0);
58 r->rx_msg_status = __read_32bit_c2_register($3, 0) & 0x0fffffff;
59}
60
61void nlm_cop2_restore(struct nlm_cop2_state *r)
62{
63 u32 rstat;
64
65 asm volatile(
66 ".set push\n"
67 ".set noat\n"
68 "ld $1, 0(%1)\n"
69 "dmtc2 $1, $0, 0\n"
70 "ld $1, 8(%1)\n"
71 "dmtc2 $1, $0, 1\n"
72 "ld $1, 16(%1)\n"
73 "dmtc2 $1, $0, 2\n"
74 "ld $1, 24(%1)\n"
75 "dmtc2 $1, $0, 3\n"
76 "ld $1, 0(%2)\n"
77 "dmtc2 $1, $1, 0\n"
78 "ld $1, 8(%2)\n"
79 "dmtc2 $1, $1, 1\n"
80 "ld $1, 16(%2)\n"
81 "dmtc2 $1, $1, 2\n"
82 "ld $1, 24(%2)\n"
83 "dmtc2 $1, $1, 3\n"
84 ".set pop\n"
85 : : "m"(*r), "r"(r->tx), "r"(r->rx));
86
87 __write_32bit_c2_register($2, 0, r->tx_msg_status);
88 rstat = __read_32bit_c2_register($3, 0) & 0xf0000000u;
89 __write_32bit_c2_register($3, 0, r->rx_msg_status | rstat);
90}
91
92static int nlm_cu2_call(struct notifier_block *nfb, unsigned long action,
93 void *data)
94{
95 unsigned long flags;
96 unsigned int status;
97
98 switch (action) {
99 case CU2_EXCEPTION:
100 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
101 break;
102 local_irq_save(flags);
103 KSTK_STATUS(current) |= ST0_CU2;
104 status = read_c0_status();
105 write_c0_status(status | ST0_CU2);
106 nlm_cop2_restore(&(current->thread.cp2));
107 write_c0_status(status & ~ST0_CU2);
108 local_irq_restore(flags);
109 pr_info("COP2 access enabled for pid %d (%s)\n",
110 current->pid, current->comm);
111 return NOTIFY_BAD; /* Don't call default notifier */
112 }
113
114 return NOTIFY_OK; /* Let default notifier send signals */
115}
116
117static int __init nlm_cu2_setup(void)
118{
119 return cu2_notifier(nlm_cu2_call, 0);
120}
121early_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 000000000..c856f2a3e
--- /dev/null
+++ b/arch/mips/netlogic/xlp/dt.c
@@ -0,0 +1,95 @@
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/memblock.h>
37
38#include <linux/of_fdt.h>
39#include <linux/of_platform.h>
40#include <linux/of_device.h>
41
42#include <asm/prom.h>
43
44extern u32 __dtb_xlp_evp_begin[], __dtb_xlp_svp_begin[], __dtb_xlp_fvp_begin[],
45 __dtb_xlp_gvp_begin[], __dtb_xlp_rvp_begin[];
46static void *xlp_fdt_blob;
47
48void __init *xlp_dt_init(void *fdtp)
49{
50 if (!fdtp) {
51 switch (current_cpu_data.processor_id & PRID_IMP_MASK) {
52#ifdef CONFIG_DT_XLP_RVP
53 case PRID_IMP_NETLOGIC_XLP5XX:
54 fdtp = __dtb_xlp_rvp_begin;
55 break;
56#endif
57#ifdef CONFIG_DT_XLP_GVP
58 case PRID_IMP_NETLOGIC_XLP9XX:
59 fdtp = __dtb_xlp_gvp_begin;
60 break;
61#endif
62#ifdef CONFIG_DT_XLP_FVP
63 case PRID_IMP_NETLOGIC_XLP2XX:
64 fdtp = __dtb_xlp_fvp_begin;
65 break;
66#endif
67#ifdef CONFIG_DT_XLP_SVP
68 case PRID_IMP_NETLOGIC_XLP3XX:
69 fdtp = __dtb_xlp_svp_begin;
70 break;
71#endif
72#ifdef CONFIG_DT_XLP_EVP
73 case PRID_IMP_NETLOGIC_XLP8XX:
74 fdtp = __dtb_xlp_evp_begin;
75 break;
76#endif
77 default:
78 /* Pick a built-in if any, and hope for the best */
79 fdtp = __dtb_start;
80 break;
81 }
82 }
83 xlp_fdt_blob = fdtp;
84 return fdtp;
85}
86
87void __init xlp_early_init_devtree(void)
88{
89 __dt_setup_arch(xlp_fdt_blob);
90}
91
92void __init device_tree_init(void)
93{
94 unflatten_and_copy_device_tree();
95}
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
new file mode 100644
index 000000000..25ee69489
--- /dev/null
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -0,0 +1,508 @@
1/*
2 * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
3 * 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 NetLogic
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 NETLOGIC ``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 NETLOGIC 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/types.h>
36#include <linux/kernel.h>
37#include <linux/mm.h>
38#include <linux/delay.h>
39
40#include <asm/mipsregs.h>
41#include <asm/time.h>
42
43#include <asm/netlogic/common.h>
44#include <asm/netlogic/haldefs.h>
45#include <asm/netlogic/xlp-hal/iomap.h>
46#include <asm/netlogic/xlp-hal/xlp.h>
47#include <asm/netlogic/xlp-hal/bridge.h>
48#include <asm/netlogic/xlp-hal/pic.h>
49#include <asm/netlogic/xlp-hal/sys.h>
50
51/* Main initialization */
52void nlm_node_init(int node)
53{
54 struct nlm_soc_info *nodep;
55
56 nodep = nlm_get_node(node);
57 if (node == 0)
58 nodep->coremask = 1; /* node 0, boot cpu */
59 nodep->sysbase = nlm_get_sys_regbase(node);
60 nodep->picbase = nlm_get_pic_regbase(node);
61 nodep->ebase = read_c0_ebase() & MIPS_EBASE_BASE;
62 if (cpu_is_xlp9xx())
63 nodep->socbus = xlp9xx_get_socbus(node);
64 else
65 nodep->socbus = 0;
66 spin_lock_init(&nodep->piclock);
67}
68
69static int xlp9xx_irq_to_irt(int irq)
70{
71 switch (irq) {
72 case PIC_GPIO_IRQ:
73 return 12;
74 case PIC_I2C_0_IRQ:
75 return 125;
76 case PIC_I2C_1_IRQ:
77 return 126;
78 case PIC_I2C_2_IRQ:
79 return 127;
80 case PIC_I2C_3_IRQ:
81 return 128;
82 case PIC_9XX_XHCI_0_IRQ:
83 return 114;
84 case PIC_9XX_XHCI_1_IRQ:
85 return 115;
86 case PIC_9XX_XHCI_2_IRQ:
87 return 116;
88 case PIC_UART_0_IRQ:
89 return 133;
90 case PIC_UART_1_IRQ:
91 return 134;
92 case PIC_SATA_IRQ:
93 return 143;
94 case PIC_NAND_IRQ:
95 return 151;
96 case PIC_SPI_IRQ:
97 return 152;
98 case PIC_MMC_IRQ:
99 return 153;
100 case PIC_PCIE_LINK_LEGACY_IRQ(0):
101 case PIC_PCIE_LINK_LEGACY_IRQ(1):
102 case PIC_PCIE_LINK_LEGACY_IRQ(2):
103 case PIC_PCIE_LINK_LEGACY_IRQ(3):
104 return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE;
105 }
106 return -1;
107}
108
109static int xlp_irq_to_irt(int irq)
110{
111 uint64_t pcibase;
112 int devoff, irt;
113
114 devoff = 0;
115 switch (irq) {
116 case PIC_UART_0_IRQ:
117 devoff = XLP_IO_UART0_OFFSET(0);
118 break;
119 case PIC_UART_1_IRQ:
120 devoff = XLP_IO_UART1_OFFSET(0);
121 break;
122 case PIC_MMC_IRQ:
123 devoff = XLP_IO_MMC_OFFSET(0);
124 break;
125 case PIC_I2C_0_IRQ: /* I2C will be fixed up */
126 case PIC_I2C_1_IRQ:
127 case PIC_I2C_2_IRQ:
128 case PIC_I2C_3_IRQ:
129 if (cpu_is_xlpii())
130 devoff = XLP2XX_IO_I2C_OFFSET(0);
131 else
132 devoff = XLP_IO_I2C0_OFFSET(0);
133 break;
134 case PIC_SATA_IRQ:
135 devoff = XLP_IO_SATA_OFFSET(0);
136 break;
137 case PIC_GPIO_IRQ:
138 devoff = XLP_IO_GPIO_OFFSET(0);
139 break;
140 case PIC_NAND_IRQ:
141 devoff = XLP_IO_NAND_OFFSET(0);
142 break;
143 case PIC_SPI_IRQ:
144 devoff = XLP_IO_SPI_OFFSET(0);
145 break;
146 default:
147 if (cpu_is_xlpii()) {
148 switch (irq) {
149 /* XLP2XX has three XHCI USB controller */
150 case PIC_2XX_XHCI_0_IRQ:
151 devoff = XLP2XX_IO_USB_XHCI0_OFFSET(0);
152 break;
153 case PIC_2XX_XHCI_1_IRQ:
154 devoff = XLP2XX_IO_USB_XHCI1_OFFSET(0);
155 break;
156 case PIC_2XX_XHCI_2_IRQ:
157 devoff = XLP2XX_IO_USB_XHCI2_OFFSET(0);
158 break;
159 }
160 } else {
161 switch (irq) {
162 case PIC_EHCI_0_IRQ:
163 devoff = XLP_IO_USB_EHCI0_OFFSET(0);
164 break;
165 case PIC_EHCI_1_IRQ:
166 devoff = XLP_IO_USB_EHCI1_OFFSET(0);
167 break;
168 case PIC_OHCI_0_IRQ:
169 devoff = XLP_IO_USB_OHCI0_OFFSET(0);
170 break;
171 case PIC_OHCI_1_IRQ:
172 devoff = XLP_IO_USB_OHCI1_OFFSET(0);
173 break;
174 case PIC_OHCI_2_IRQ:
175 devoff = XLP_IO_USB_OHCI2_OFFSET(0);
176 break;
177 case PIC_OHCI_3_IRQ:
178 devoff = XLP_IO_USB_OHCI3_OFFSET(0);
179 break;
180 }
181 }
182 }
183
184 if (devoff != 0) {
185 uint32_t val;
186
187 pcibase = nlm_pcicfg_base(devoff);
188 val = nlm_read_reg(pcibase, XLP_PCI_IRTINFO_REG);
189 if (val == 0xffffffff) {
190 irt = -1;
191 } else {
192 irt = val & 0xffff;
193 /* HW weirdness, I2C IRT entry has to be fixed up */
194 switch (irq) {
195 case PIC_I2C_1_IRQ:
196 irt = irt + 1; break;
197 case PIC_I2C_2_IRQ:
198 irt = irt + 2; break;
199 case PIC_I2C_3_IRQ:
200 irt = irt + 3; break;
201 }
202 }
203 } else if (irq >= PIC_PCIE_LINK_LEGACY_IRQ(0) &&
204 irq <= PIC_PCIE_LINK_LEGACY_IRQ(3)) {
205 /* HW bug, PCI IRT entries are bad on early silicon, fix */
206 irt = PIC_IRT_PCIE_LINK_INDEX(irq -
207 PIC_PCIE_LINK_LEGACY_IRQ_BASE);
208 } else {
209 irt = -1;
210 }
211 return irt;
212}
213
214int nlm_irq_to_irt(int irq)
215{
216 /* return -2 for irqs without 1-1 mapping */
217 if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) && irq <= PIC_PCIE_LINK_MSI_IRQ(3))
218 return -2;
219 if (irq >= PIC_PCIE_MSIX_IRQ(0) && irq <= PIC_PCIE_MSIX_IRQ(3))
220 return -2;
221
222 if (cpu_is_xlp9xx())
223 return xlp9xx_irq_to_irt(irq);
224 else
225 return xlp_irq_to_irt(irq);
226}
227
228static unsigned int nlm_xlp2_get_core_frequency(int node, int core)
229{
230 unsigned int pll_post_div, ctrl_val0, ctrl_val1, denom;
231 uint64_t num, sysbase, clockbase;
232
233 if (cpu_is_xlp9xx()) {
234 clockbase = nlm_get_clock_regbase(node);
235 ctrl_val0 = nlm_read_sys_reg(clockbase,
236 SYS_9XX_CPU_PLL_CTRL0(core));
237 ctrl_val1 = nlm_read_sys_reg(clockbase,
238 SYS_9XX_CPU_PLL_CTRL1(core));
239 } else {
240 sysbase = nlm_get_node(node)->sysbase;
241 ctrl_val0 = nlm_read_sys_reg(sysbase,
242 SYS_CPU_PLL_CTRL0(core));
243 ctrl_val1 = nlm_read_sys_reg(sysbase,
244 SYS_CPU_PLL_CTRL1(core));
245 }
246
247 /* Find PLL post divider value */
248 switch ((ctrl_val0 >> 24) & 0x7) {
249 case 1:
250 pll_post_div = 2;
251 break;
252 case 3:
253 pll_post_div = 4;
254 break;
255 case 7:
256 pll_post_div = 8;
257 break;
258 case 6:
259 pll_post_div = 16;
260 break;
261 case 0:
262 default:
263 pll_post_div = 1;
264 break;
265 }
266
267 num = 1000000ULL * (400 * 3 + 100 * (ctrl_val1 & 0x3f));
268 denom = 3 * pll_post_div;
269 do_div(num, denom);
270
271 return (unsigned int)num;
272}
273
274static unsigned int nlm_xlp_get_core_frequency(int node, int core)
275{
276 unsigned int pll_divf, pll_divr, dfs_div, ext_div;
277 unsigned int rstval, dfsval, denom;
278 uint64_t num, sysbase;
279
280 sysbase = nlm_get_node(node)->sysbase;
281 rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG);
282 dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE);
283 pll_divf = ((rstval >> 10) & 0x7f) + 1;
284 pll_divr = ((rstval >> 8) & 0x3) + 1;
285 ext_div = ((rstval >> 30) & 0x3) + 1;
286 dfs_div = ((dfsval >> (core * 4)) & 0xf) + 1;
287
288 num = 800000000ULL * pll_divf;
289 denom = 3 * pll_divr * ext_div * dfs_div;
290 do_div(num, denom);
291
292 return (unsigned int)num;
293}
294
295unsigned int nlm_get_core_frequency(int node, int core)
296{
297 if (cpu_is_xlpii())
298 return nlm_xlp2_get_core_frequency(node, core);
299 else
300 return nlm_xlp_get_core_frequency(node, core);
301}
302
303/*
304 * Calculate PIC frequency from PLL registers.
305 * freq_out = (ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13) /
306 * ((2^ctrl0[7:5]) * Table(ctrl0[26:24]))
307 */
308static unsigned int nlm_xlp2_get_pic_frequency(int node)
309{
310 u32 ctrl_val0, ctrl_val2, vco_post_div, pll_post_div, cpu_xlp9xx;
311 u32 mdiv, fdiv, pll_out_freq_den, reg_select, ref_div, pic_div;
312 u64 sysbase, pll_out_freq_num, ref_clk_select, clockbase, ref_clk;
313
314 sysbase = nlm_get_node(node)->sysbase;
315 clockbase = nlm_get_clock_regbase(node);
316 cpu_xlp9xx = cpu_is_xlp9xx();
317
318 /* Find ref_clk_base */
319 if (cpu_xlp9xx)
320 ref_clk_select = (nlm_read_sys_reg(sysbase,
321 SYS_9XX_POWER_ON_RESET_CFG) >> 18) & 0x3;
322 else
323 ref_clk_select = (nlm_read_sys_reg(sysbase,
324 SYS_POWER_ON_RESET_CFG) >> 18) & 0x3;
325 switch (ref_clk_select) {
326 case 0:
327 ref_clk = 200000000ULL;
328 ref_div = 3;
329 break;
330 case 1:
331 ref_clk = 100000000ULL;
332 ref_div = 1;
333 break;
334 case 2:
335 ref_clk = 125000000ULL;
336 ref_div = 1;
337 break;
338 case 3:
339 ref_clk = 400000000ULL;
340 ref_div = 3;
341 break;
342 }
343
344 /* Find the clock source PLL device for PIC */
345 if (cpu_xlp9xx) {
346 reg_select = nlm_read_sys_reg(clockbase,
347 SYS_9XX_CLK_DEV_SEL_REG) & 0x3;
348 switch (reg_select) {
349 case 0:
350 ctrl_val0 = nlm_read_sys_reg(clockbase,
351 SYS_9XX_PLL_CTRL0);
352 ctrl_val2 = nlm_read_sys_reg(clockbase,
353 SYS_9XX_PLL_CTRL2);
354 break;
355 case 1:
356 ctrl_val0 = nlm_read_sys_reg(clockbase,
357 SYS_9XX_PLL_CTRL0_DEVX(0));
358 ctrl_val2 = nlm_read_sys_reg(clockbase,
359 SYS_9XX_PLL_CTRL2_DEVX(0));
360 break;
361 case 2:
362 ctrl_val0 = nlm_read_sys_reg(clockbase,
363 SYS_9XX_PLL_CTRL0_DEVX(1));
364 ctrl_val2 = nlm_read_sys_reg(clockbase,
365 SYS_9XX_PLL_CTRL2_DEVX(1));
366 break;
367 case 3:
368 ctrl_val0 = nlm_read_sys_reg(clockbase,
369 SYS_9XX_PLL_CTRL0_DEVX(2));
370 ctrl_val2 = nlm_read_sys_reg(clockbase,
371 SYS_9XX_PLL_CTRL2_DEVX(2));
372 break;
373 }
374 } else {
375 reg_select = (nlm_read_sys_reg(sysbase,
376 SYS_CLK_DEV_SEL_REG) >> 22) & 0x3;
377 switch (reg_select) {
378 case 0:
379 ctrl_val0 = nlm_read_sys_reg(sysbase,
380 SYS_PLL_CTRL0);
381 ctrl_val2 = nlm_read_sys_reg(sysbase,
382 SYS_PLL_CTRL2);
383 break;
384 case 1:
385 ctrl_val0 = nlm_read_sys_reg(sysbase,
386 SYS_PLL_CTRL0_DEVX(0));
387 ctrl_val2 = nlm_read_sys_reg(sysbase,
388 SYS_PLL_CTRL2_DEVX(0));
389 break;
390 case 2:
391 ctrl_val0 = nlm_read_sys_reg(sysbase,
392 SYS_PLL_CTRL0_DEVX(1));
393 ctrl_val2 = nlm_read_sys_reg(sysbase,
394 SYS_PLL_CTRL2_DEVX(1));
395 break;
396 case 3:
397 ctrl_val0 = nlm_read_sys_reg(sysbase,
398 SYS_PLL_CTRL0_DEVX(2));
399 ctrl_val2 = nlm_read_sys_reg(sysbase,
400 SYS_PLL_CTRL2_DEVX(2));
401 break;
402 }
403 }
404
405 vco_post_div = (ctrl_val0 >> 5) & 0x7;
406 pll_post_div = (ctrl_val0 >> 24) & 0x7;
407 mdiv = ctrl_val2 & 0xff;
408 fdiv = (ctrl_val2 >> 8) & 0x1fff;
409
410 /* Find PLL post divider value */
411 switch (pll_post_div) {
412 case 1:
413 pll_post_div = 2;
414 break;
415 case 3:
416 pll_post_div = 4;
417 break;
418 case 7:
419 pll_post_div = 8;
420 break;
421 case 6:
422 pll_post_div = 16;
423 break;
424 case 0:
425 default:
426 pll_post_div = 1;
427 break;
428 }
429
430 fdiv = fdiv/(1 << 13);
431 pll_out_freq_num = ((ref_clk >> 1) * (6 + mdiv)) + fdiv;
432 pll_out_freq_den = (1 << vco_post_div) * pll_post_div * ref_div;
433
434 if (pll_out_freq_den > 0)
435 do_div(pll_out_freq_num, pll_out_freq_den);
436
437 /* PIC post divider, which happens after PLL */
438 if (cpu_xlp9xx)
439 pic_div = nlm_read_sys_reg(clockbase,
440 SYS_9XX_CLK_DEV_DIV_REG) & 0x3;
441 else
442 pic_div = (nlm_read_sys_reg(sysbase,
443 SYS_CLK_DEV_DIV_REG) >> 22) & 0x3;
444 do_div(pll_out_freq_num, 1 << pic_div);
445
446 return pll_out_freq_num;
447}
448
449unsigned int nlm_get_pic_frequency(int node)
450{
451 if (cpu_is_xlpii())
452 return nlm_xlp2_get_pic_frequency(node);
453 else
454 return 133333333;
455}
456
457unsigned int nlm_get_cpu_frequency(void)
458{
459 return nlm_get_core_frequency(0, 0);
460}
461
462/*
463 * Fills upto 8 pairs of entries containing the DRAM map of a node
464 * if node < 0, get dram map for all nodes
465 */
466int nlm_get_dram_map(int node, uint64_t *dram_map, int nentries)
467{
468 uint64_t bridgebase, base, lim;
469 uint32_t val;
470 unsigned int barreg, limreg, xlatreg;
471 int i, n, rv;
472
473 /* Look only at mapping on Node 0, we don't handle crazy configs */
474 bridgebase = nlm_get_bridge_regbase(0);
475 rv = 0;
476 for (i = 0; i < 8; i++) {
477 if (rv + 1 >= nentries)
478 break;
479 if (cpu_is_xlp9xx()) {
480 barreg = BRIDGE_9XX_DRAM_BAR(i);
481 limreg = BRIDGE_9XX_DRAM_LIMIT(i);
482 xlatreg = BRIDGE_9XX_DRAM_NODE_TRANSLN(i);
483 } else {
484 barreg = BRIDGE_DRAM_BAR(i);
485 limreg = BRIDGE_DRAM_LIMIT(i);
486 xlatreg = BRIDGE_DRAM_NODE_TRANSLN(i);
487 }
488 if (node >= 0) {
489 /* node specified, get node mapping of BAR */
490 val = nlm_read_bridge_reg(bridgebase, xlatreg);
491 n = (val >> 1) & 0x3;
492 if (n != node)
493 continue;
494 }
495 val = nlm_read_bridge_reg(bridgebase, barreg);
496 val = (val >> 12) & 0xfffff;
497 base = (uint64_t) val << 20;
498 val = nlm_read_bridge_reg(bridgebase, limreg);
499 val = (val >> 12) & 0xfffff;
500 if (val == 0) /* BAR not used */
501 continue;
502 lim = ((uint64_t)val + 1) << 20;
503 dram_map[rv] = base;
504 dram_map[rv + 1] = lim;
505 rv += 2;
506 }
507 return rv;
508}
diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c
new file mode 100644
index 000000000..9adc0c1b4
--- /dev/null
+++ b/arch/mips/netlogic/xlp/setup.c
@@ -0,0 +1,179 @@
1/*
2 * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
3 * 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 NetLogic
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 NETLOGIC ``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 NETLOGIC 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/of_fdt.h>
37#include <linux/memblock.h>
38
39#include <asm/idle.h>
40#include <asm/reboot.h>
41#include <asm/time.h>
42#include <asm/bootinfo.h>
43
44#include <asm/netlogic/haldefs.h>
45#include <asm/netlogic/common.h>
46
47#include <asm/netlogic/xlp-hal/iomap.h>
48#include <asm/netlogic/xlp-hal/xlp.h>
49#include <asm/netlogic/xlp-hal/sys.h>
50
51uint64_t nlm_io_base;
52struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
53cpumask_t nlm_cpumask = CPU_MASK_CPU0;
54unsigned int nlm_threads_per_core;
55
56static void nlm_linux_exit(void)
57{
58 uint64_t sysbase = nlm_get_node(0)->sysbase;
59
60 if (cpu_is_xlp9xx())
61 nlm_write_sys_reg(sysbase, SYS_9XX_CHIP_RESET, 1);
62 else
63 nlm_write_sys_reg(sysbase, SYS_CHIP_RESET, 1);
64 for ( ; ; )
65 cpu_wait();
66}
67
68static void nlm_fixup_mem(void)
69{
70 const int pref_backup = 512;
71 struct memblock_region *mem;
72
73 for_each_mem_region(mem) {
74 memblock_remove(mem->base + mem->size - pref_backup,
75 pref_backup);
76 }
77}
78
79static void __init xlp_init_mem_from_bars(void)
80{
81 uint64_t map[16];
82 int i, n;
83
84 n = nlm_get_dram_map(-1, map, ARRAY_SIZE(map)); /* -1 : all nodes */
85 for (i = 0; i < n; i += 2) {
86 /* exclude 0x1000_0000-0x2000_0000, u-boot device */
87 if (map[i] <= 0x10000000 && map[i+1] > 0x10000000)
88 map[i+1] = 0x10000000;
89 if (map[i] > 0x10000000 && map[i] < 0x20000000)
90 map[i] = 0x20000000;
91
92 memblock_add(map[i], map[i+1] - map[i]);
93 }
94}
95
96void __init plat_mem_setup(void)
97{
98#ifdef CONFIG_SMP
99 nlm_wakeup_secondary_cpus();
100
101 /* update TLB size after waking up threads */
102 current_cpu_data.tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1;
103
104 register_smp_ops(&nlm_smp_ops);
105#endif
106 _machine_restart = (void (*)(char *))nlm_linux_exit;
107 _machine_halt = nlm_linux_exit;
108 pm_power_off = nlm_linux_exit;
109
110 /* memory and bootargs from DT */
111 xlp_early_init_devtree();
112
113 if (memblock_end_of_DRAM() == 0) {
114 pr_info("Using DRAM BARs for memory map.\n");
115 xlp_init_mem_from_bars();
116 }
117 /* Calculate and setup wired entries for mapped kernel */
118 nlm_fixup_mem();
119}
120
121const char *get_system_type(void)
122{
123 switch (read_c0_prid() & PRID_IMP_MASK) {
124 case PRID_IMP_NETLOGIC_XLP9XX:
125 case PRID_IMP_NETLOGIC_XLP5XX:
126 case PRID_IMP_NETLOGIC_XLP2XX:
127 return "Broadcom XLPII Series";
128 default:
129 return "Netlogic XLP Series";
130 }
131}
132
133void __init prom_free_prom_memory(void)
134{
135 /* Nothing yet */
136}
137
138void xlp_mmu_init(void)
139{
140 u32 conf4;
141
142 if (cpu_is_xlpii()) {
143 /* XLPII series has extended pagesize in config 4 */
144 conf4 = read_c0_config4() & ~0x1f00u;
145 write_c0_config4(conf4 | ((PAGE_SHIFT - 10) / 2 << 8));
146 } else {
147 /* enable extended TLB and Large Fixed TLB */
148 write_c0_config6(read_c0_config6() | 0x24);
149
150 /* set page mask of extended Fixed TLB in config7 */
151 write_c0_config7(PM_DEFAULT_MASK >>
152 (13 + (ffz(PM_DEFAULT_MASK >> 13) / 2)));
153 }
154}
155
156void nlm_percpu_init(int hwcpuid)
157{
158}
159
160void __init prom_init(void)
161{
162 void *reset_vec;
163
164 nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE);
165 nlm_init_boot_cpu();
166 xlp_mmu_init();
167 nlm_node_init(0);
168 xlp_dt_init((void *)(long)fw_arg0);
169
170 /* Update reset entry point with CPU init code */
171 reset_vec = (void *)CKSEG1ADDR(RESET_VEC_PHYS);
172 memset(reset_vec, 0, RESET_VEC_SIZE);
173 memcpy(reset_vec, (void *)nlm_reset_entry,
174 (nlm_reset_entry_end - nlm_reset_entry));
175
176#ifdef CONFIG_SMP
177 cpumask_setall(&nlm_cpumask);
178#endif
179}
diff --git a/arch/mips/netlogic/xlp/usb-init-xlp2.c b/arch/mips/netlogic/xlp/usb-init-xlp2.c
new file mode 100644
index 000000000..2524939a5
--- /dev/null
+++ b/arch/mips/netlogic/xlp/usb-init-xlp2.c
@@ -0,0 +1,288 @@
1/*
2 * Copyright (c) 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/dma-mapping.h>
36#include <linux/kernel.h>
37#include <linux/delay.h>
38#include <linux/init.h>
39#include <linux/pci.h>
40#include <linux/pci_ids.h>
41#include <linux/platform_device.h>
42#include <linux/irq.h>
43
44#include <asm/netlogic/common.h>
45#include <asm/netlogic/haldefs.h>
46#include <asm/netlogic/xlp-hal/iomap.h>
47#include <asm/netlogic/xlp-hal/xlp.h>
48
49#define XLPII_USB3_CTL_0 0xc0
50#define XLPII_VAUXRST BIT(0)
51#define XLPII_VCCRST BIT(1)
52#define XLPII_NUM2PORT 9
53#define XLPII_NUM3PORT 13
54#define XLPII_RTUNEREQ BIT(20)
55#define XLPII_MS_CSYSREQ BIT(21)
56#define XLPII_XS_CSYSREQ BIT(22)
57#define XLPII_RETENABLEN BIT(23)
58#define XLPII_TX2RX BIT(24)
59#define XLPII_XHCIREV BIT(25)
60#define XLPII_ECCDIS BIT(26)
61
62#define XLPII_USB3_INT_REG 0xc2
63#define XLPII_USB3_INT_MASK 0xc3
64
65#define XLPII_USB_PHY_TEST 0xc6
66#define XLPII_PRESET BIT(0)
67#define XLPII_ATERESET BIT(1)
68#define XLPII_LOOPEN BIT(2)
69#define XLPII_TESTPDHSP BIT(3)
70#define XLPII_TESTPDSSP BIT(4)
71#define XLPII_TESTBURNIN BIT(5)
72
73#define XLPII_USB_PHY_LOS_LV 0xc9
74#define XLPII_LOSLEV 0
75#define XLPII_LOSBIAS 5
76#define XLPII_SQRXTX 8
77#define XLPII_TXBOOST 11
78#define XLPII_RSLKSEL 16
79#define XLPII_FSEL 20
80
81#define XLPII_USB_RFCLK_REG 0xcc
82#define XLPII_VVLD 30
83
84#define nlm_read_usb_reg(b, r) nlm_read_reg(b, r)
85#define nlm_write_usb_reg(b, r, v) nlm_write_reg(b, r, v)
86
87#define nlm_xlpii_get_usb_pcibase(node, inst) \
88 nlm_pcicfg_base(cpu_is_xlp9xx() ? \
89 XLP9XX_IO_USB_OFFSET(node, inst) : \
90 XLP2XX_IO_USB_OFFSET(node, inst))
91#define nlm_xlpii_get_usb_regbase(node, inst) \
92 (nlm_xlpii_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ)
93
94static void xlp2xx_usb_ack(struct irq_data *data)
95{
96 u64 port_addr;
97
98 switch (data->irq) {
99 case PIC_2XX_XHCI_0_IRQ:
100 port_addr = nlm_xlpii_get_usb_regbase(0, 1);
101 break;
102 case PIC_2XX_XHCI_1_IRQ:
103 port_addr = nlm_xlpii_get_usb_regbase(0, 2);
104 break;
105 case PIC_2XX_XHCI_2_IRQ:
106 port_addr = nlm_xlpii_get_usb_regbase(0, 3);
107 break;
108 default:
109 pr_err("No matching USB irq!\n");
110 return;
111 }
112 nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff);
113}
114
115static void xlp9xx_usb_ack(struct irq_data *data)
116{
117 u64 port_addr;
118 int node, irq;
119
120 /* Find the node and irq on the node */
121 irq = data->irq % NLM_IRQS_PER_NODE;
122 node = data->irq / NLM_IRQS_PER_NODE;
123
124 switch (irq) {
125 case PIC_9XX_XHCI_0_IRQ:
126 port_addr = nlm_xlpii_get_usb_regbase(node, 1);
127 break;
128 case PIC_9XX_XHCI_1_IRQ:
129 port_addr = nlm_xlpii_get_usb_regbase(node, 2);
130 break;
131 case PIC_9XX_XHCI_2_IRQ:
132 port_addr = nlm_xlpii_get_usb_regbase(node, 3);
133 break;
134 default:
135 pr_err("No matching USB irq %d node %d!\n", irq, node);
136 return;
137 }
138 nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff);
139}
140
141static void nlm_xlpii_usb_hw_reset(int node, int port)
142{
143 u64 port_addr, xhci_base, pci_base;
144 void __iomem *corebase;
145 u32 val;
146
147 port_addr = nlm_xlpii_get_usb_regbase(node, port);
148
149 /* Set frequency */
150 val = nlm_read_usb_reg(port_addr, XLPII_USB_PHY_LOS_LV);
151 val &= ~(0x3f << XLPII_FSEL);
152 val |= (0x27 << XLPII_FSEL);
153 nlm_write_usb_reg(port_addr, XLPII_USB_PHY_LOS_LV, val);
154
155 val = nlm_read_usb_reg(port_addr, XLPII_USB_RFCLK_REG);
156 val |= (1 << XLPII_VVLD);
157 nlm_write_usb_reg(port_addr, XLPII_USB_RFCLK_REG, val);
158
159 /* PHY reset */
160 val = nlm_read_usb_reg(port_addr, XLPII_USB_PHY_TEST);
161 val &= (XLPII_ATERESET | XLPII_LOOPEN | XLPII_TESTPDHSP
162 | XLPII_TESTPDSSP | XLPII_TESTBURNIN);
163 nlm_write_usb_reg(port_addr, XLPII_USB_PHY_TEST, val);
164
165 /* Setup control register */
166 val = XLPII_VAUXRST | XLPII_VCCRST | (1 << XLPII_NUM2PORT)
167 | (1 << XLPII_NUM3PORT) | XLPII_MS_CSYSREQ | XLPII_XS_CSYSREQ
168 | XLPII_RETENABLEN | XLPII_XHCIREV;
169 nlm_write_usb_reg(port_addr, XLPII_USB3_CTL_0, val);
170
171 /* Enable interrupts */
172 nlm_write_usb_reg(port_addr, XLPII_USB3_INT_MASK, 0x00000001);
173
174 /* Clear all interrupts */
175 nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff);
176
177 udelay(2000);
178
179 /* XHCI configuration at PCI mem */
180 pci_base = nlm_xlpii_get_usb_pcibase(node, port);
181 xhci_base = nlm_read_usb_reg(pci_base, 0x4) & ~0xf;
182 corebase = ioremap(xhci_base, 0x10000);
183 if (!corebase)
184 return;
185
186 writel(0x240002, corebase + 0xc2c0);
187 /* GCTL 0xc110 */
188 val = readl(corebase + 0xc110);
189 val &= ~(0x3 << 12);
190 val |= (1 << 12);
191 writel(val, corebase + 0xc110);
192 udelay(100);
193
194 /* PHYCFG 0xc200 */
195 val = readl(corebase + 0xc200);
196 val &= ~(1 << 6);
197 writel(val, corebase + 0xc200);
198 udelay(100);
199
200 /* PIPECTL 0xc2c0 */
201 val = readl(corebase + 0xc2c0);
202 val &= ~(1 << 17);
203 writel(val, corebase + 0xc2c0);
204
205 iounmap(corebase);
206}
207
208static int __init nlm_platform_xlpii_usb_init(void)
209{
210 int node;
211
212 if (!cpu_is_xlpii())
213 return 0;
214
215 if (!cpu_is_xlp9xx()) {
216 /* XLP 2XX single node */
217 pr_info("Initializing 2XX USB Interface\n");
218 nlm_xlpii_usb_hw_reset(0, 1);
219 nlm_xlpii_usb_hw_reset(0, 2);
220 nlm_xlpii_usb_hw_reset(0, 3);
221 nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_0_IRQ, xlp2xx_usb_ack);
222 nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_1_IRQ, xlp2xx_usb_ack);
223 nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_2_IRQ, xlp2xx_usb_ack);
224 return 0;
225 }
226
227 /* XLP 9XX, multi-node */
228 pr_info("Initializing 9XX/5XX USB Interface\n");
229 for (node = 0; node < NLM_NR_NODES; node++) {
230 if (!nlm_node_present(node))
231 continue;
232 nlm_xlpii_usb_hw_reset(node, 1);
233 nlm_xlpii_usb_hw_reset(node, 2);
234 nlm_xlpii_usb_hw_reset(node, 3);
235 nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_0_IRQ, xlp9xx_usb_ack);
236 nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_1_IRQ, xlp9xx_usb_ack);
237 nlm_set_pic_extra_ack(node, PIC_9XX_XHCI_2_IRQ, xlp9xx_usb_ack);
238 }
239 return 0;
240}
241
242arch_initcall(nlm_platform_xlpii_usb_init);
243
244static u64 xlp_usb_dmamask = ~(u32)0;
245
246/* Fixup the IRQ for USB devices which is exist on XLP9XX SOC PCIE bus */
247static void nlm_xlp9xx_usb_fixup_final(struct pci_dev *dev)
248{
249 int node;
250
251 node = xlp_socdev_to_node(dev);
252 dev->dev.dma_mask = &xlp_usb_dmamask;
253 dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
254 switch (dev->devfn) {
255 case 0x21:
256 dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_0_IRQ);
257 break;
258 case 0x22:
259 dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_1_IRQ);
260 break;
261 case 0x23:
262 dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_2_IRQ);
263 break;
264 }
265}
266
267/* Fixup the IRQ for USB devices which is exist on XLP2XX SOC PCIE bus */
268static void nlm_xlp2xx_usb_fixup_final(struct pci_dev *dev)
269{
270 dev->dev.dma_mask = &xlp_usb_dmamask;
271 dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
272 switch (dev->devfn) {
273 case 0x21:
274 dev->irq = PIC_2XX_XHCI_0_IRQ;
275 break;
276 case 0x22:
277 dev->irq = PIC_2XX_XHCI_1_IRQ;
278 break;
279 case 0x23:
280 dev->irq = PIC_2XX_XHCI_2_IRQ;
281 break;
282 }
283}
284
285DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_XHCI,
286 nlm_xlp9xx_usb_fixup_final);
287DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_XHCI,
288 nlm_xlp2xx_usb_fixup_final);
diff --git a/arch/mips/netlogic/xlp/usb-init.c b/arch/mips/netlogic/xlp/usb-init.c
new file mode 100644
index 000000000..f8117985f
--- /dev/null
+++ b/arch/mips/netlogic/xlp/usb-init.c
@@ -0,0 +1,149 @@
1/*
2 * Copyright (c) 2003-2012 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/dma-mapping.h>
36#include <linux/kernel.h>
37#include <linux/delay.h>
38#include <linux/init.h>
39#include <linux/pci.h>
40#include <linux/platform_device.h>
41
42#include <asm/netlogic/haldefs.h>
43#include <asm/netlogic/xlp-hal/iomap.h>
44#include <asm/netlogic/xlp-hal/xlp.h>
45
46/*
47 * USB glue logic registers, used only during initialization
48 */
49#define USB_CTL_0 0x01
50#define USB_PHY_0 0x0A
51#define USB_PHY_RESET 0x01
52#define USB_PHY_PORT_RESET_0 0x10
53#define USB_PHY_PORT_RESET_1 0x20
54#define USB_CONTROLLER_RESET 0x01
55#define USB_INT_STATUS 0x0E
56#define USB_INT_EN 0x0F
57#define USB_PHY_INTERRUPT_EN 0x01
58#define USB_OHCI_INTERRUPT_EN 0x02
59#define USB_OHCI_INTERRUPT1_EN 0x04
60#define USB_OHCI_INTERRUPT2_EN 0x08
61#define USB_CTRL_INTERRUPT_EN 0x10
62
63#define nlm_read_usb_reg(b, r) nlm_read_reg(b, r)
64#define nlm_write_usb_reg(b, r, v) nlm_write_reg(b, r, v)
65#define nlm_get_usb_pcibase(node, inst) \
66 nlm_pcicfg_base(XLP_IO_USB_OFFSET(node, inst))
67#define nlm_get_usb_regbase(node, inst) \
68 (nlm_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ)
69
70static void nlm_usb_intr_en(int node, int port)
71{
72 uint32_t val;
73 uint64_t port_addr;
74
75 port_addr = nlm_get_usb_regbase(node, port);
76 val = nlm_read_usb_reg(port_addr, USB_INT_EN);
77 val = USB_CTRL_INTERRUPT_EN | USB_OHCI_INTERRUPT_EN |
78 USB_OHCI_INTERRUPT1_EN | USB_OHCI_INTERRUPT2_EN;
79 nlm_write_usb_reg(port_addr, USB_INT_EN, val);
80}
81
82static void nlm_usb_hw_reset(int node, int port)
83{
84 uint64_t port_addr;
85 uint32_t val;
86
87 /* reset USB phy */
88 port_addr = nlm_get_usb_regbase(node, port);
89 val = nlm_read_usb_reg(port_addr, USB_PHY_0);
90 val &= ~(USB_PHY_RESET | USB_PHY_PORT_RESET_0 | USB_PHY_PORT_RESET_1);
91 nlm_write_usb_reg(port_addr, USB_PHY_0, val);
92
93 mdelay(100);
94 val = nlm_read_usb_reg(port_addr, USB_CTL_0);
95 val &= ~(USB_CONTROLLER_RESET);
96 val |= 0x4;
97 nlm_write_usb_reg(port_addr, USB_CTL_0, val);
98}
99
100static int __init nlm_platform_usb_init(void)
101{
102 if (cpu_is_xlpii())
103 return 0;
104
105 pr_info("Initializing USB Interface\n");
106 nlm_usb_hw_reset(0, 0);
107 nlm_usb_hw_reset(0, 3);
108
109 /* Enable PHY interrupts */
110 nlm_usb_intr_en(0, 0);
111 nlm_usb_intr_en(0, 3);
112
113 return 0;
114}
115
116arch_initcall(nlm_platform_usb_init);
117
118static u64 xlp_usb_dmamask = ~(u32)0;
119
120/* Fixup the IRQ for USB devices which is exist on XLP SOC PCIE bus */
121static void nlm_usb_fixup_final(struct pci_dev *dev)
122{
123 dev->dev.dma_mask = &xlp_usb_dmamask;
124 dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
125 switch (dev->devfn) {
126 case 0x10:
127 dev->irq = PIC_EHCI_0_IRQ;
128 break;
129 case 0x11:
130 dev->irq = PIC_OHCI_0_IRQ;
131 break;
132 case 0x12:
133 dev->irq = PIC_OHCI_1_IRQ;
134 break;
135 case 0x13:
136 dev->irq = PIC_EHCI_1_IRQ;
137 break;
138 case 0x14:
139 dev->irq = PIC_OHCI_2_IRQ;
140 break;
141 case 0x15:
142 dev->irq = PIC_OHCI_3_IRQ;
143 break;
144 }
145}
146DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_EHCI,
147 nlm_usb_fixup_final);
148DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_OHCI,
149 nlm_usb_fixup_final);
diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c
new file mode 100644
index 000000000..d61004dd7
--- /dev/null
+++ b/arch/mips/netlogic/xlp/wakeup.c
@@ -0,0 +1,212 @@
1/*
2 * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
3 * 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 NetLogic
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 NETLOGIC ``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 NETLOGIC 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/threads.h>
37
38#include <asm/asm.h>
39#include <asm/asm-offsets.h>
40#include <asm/mipsregs.h>
41#include <asm/addrspace.h>
42#include <asm/string.h>
43
44#include <asm/netlogic/haldefs.h>
45#include <asm/netlogic/common.h>
46#include <asm/netlogic/mips-extns.h>
47
48#include <asm/netlogic/xlp-hal/iomap.h>
49#include <asm/netlogic/xlp-hal/xlp.h>
50#include <asm/netlogic/xlp-hal/pic.h>
51#include <asm/netlogic/xlp-hal/sys.h>
52
53static int xlp_wakeup_core(uint64_t sysbase, int node, int core)
54{
55 uint32_t coremask, value;
56 int count, resetreg;
57
58 coremask = (1 << core);
59
60 /* Enable CPU clock in case of 8xx/3xx */
61 if (!cpu_is_xlpii()) {
62 value = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL);
63 value &= ~coremask;
64 nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, value);
65 }
66
67 /* On 9XX, mark coherent first */
68 if (cpu_is_xlp9xx()) {
69 value = nlm_read_sys_reg(sysbase, SYS_9XX_CPU_NONCOHERENT_MODE);
70 value &= ~coremask;
71 nlm_write_sys_reg(sysbase, SYS_9XX_CPU_NONCOHERENT_MODE, value);
72 }
73
74 /* Remove CPU Reset */
75 resetreg = cpu_is_xlp9xx() ? SYS_9XX_CPU_RESET : SYS_CPU_RESET;
76 value = nlm_read_sys_reg(sysbase, resetreg);
77 value &= ~coremask;
78 nlm_write_sys_reg(sysbase, resetreg, value);
79
80 /* We are done on 9XX */
81 if (cpu_is_xlp9xx())
82 return 1;
83
84 /* Poll for CPU to mark itself coherent on other type of XLP */
85 count = 100000;
86 do {
87 value = nlm_read_sys_reg(sysbase, SYS_CPU_NONCOHERENT_MODE);
88 } while ((value & coremask) != 0 && --count > 0);
89
90 return count != 0;
91}
92
93static int wait_for_cpus(int cpu, int bootcpu)
94{
95 volatile uint32_t *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY);
96 int i, count, notready;
97
98 count = 0x800000;
99 do {
100 notready = nlm_threads_per_core;
101 for (i = 0; i < nlm_threads_per_core; i++)
102 if (cpu_ready[cpu + i] || (cpu + i) == bootcpu)
103 --notready;
104 } while (notready != 0 && --count > 0);
105
106 return count != 0;
107}
108
109static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
110{
111 struct nlm_soc_info *nodep;
112 uint64_t syspcibase, fusebase;
113 uint32_t syscoremask, mask, fusemask;
114 int core, n, cpu, ncores;
115
116 for (n = 0; n < NLM_NR_NODES; n++) {
117 if (n != 0) {
118 /* check if node exists and is online */
119 if (cpu_is_xlp9xx()) {
120 int b = xlp9xx_get_socbus(n);
121 pr_info("Node %d SoC PCI bus %d.\n", n, b);
122 if (b == 0)
123 break;
124 } else {
125 syspcibase = nlm_get_sys_pcibase(n);
126 if (nlm_read_reg(syspcibase, 0) == 0xffffffff)
127 break;
128 }
129 nlm_node_init(n);
130 }
131
132 /* read cores in reset from SYS */
133 nodep = nlm_get_node(n);
134
135 if (cpu_is_xlp9xx()) {
136 fusebase = nlm_get_fuse_regbase(n);
137 fusemask = nlm_read_reg(fusebase, FUSE_9XX_DEVCFG6);
138 switch (read_c0_prid() & PRID_IMP_MASK) {
139 case PRID_IMP_NETLOGIC_XLP5XX:
140 mask = 0xff;
141 break;
142 case PRID_IMP_NETLOGIC_XLP9XX:
143 default:
144 mask = 0xfffff;
145 break;
146 }
147 } else {
148 fusemask = nlm_read_sys_reg(nodep->sysbase,
149 SYS_EFUSE_DEVICE_CFG_STATUS0);
150 switch (read_c0_prid() & PRID_IMP_MASK) {
151 case PRID_IMP_NETLOGIC_XLP3XX:
152 mask = 0xf;
153 break;
154 case PRID_IMP_NETLOGIC_XLP2XX:
155 mask = 0x3;
156 break;
157 case PRID_IMP_NETLOGIC_XLP8XX:
158 default:
159 mask = 0xff;
160 break;
161 }
162 }
163
164 /*
165 * Fused out cores are set in the fusemask, and the remaining
166 * cores are renumbered to range 0 .. nactive-1
167 */
168 syscoremask = (1 << hweight32(~fusemask & mask)) - 1;
169
170 pr_info("Node %d - SYS/FUSE coremask %x\n", n, syscoremask);
171 ncores = nlm_cores_per_node();
172 for (core = 0; core < ncores; core++) {
173 /* we will be on node 0 core 0 */
174 if (n == 0 && core == 0)
175 continue;
176
177 /* see if the core exists */
178 if ((syscoremask & (1 << core)) == 0)
179 continue;
180
181 /* see if at least the first hw thread is enabled */
182 cpu = (n * ncores + core) * NLM_THREADS_PER_CORE;
183 if (!cpumask_test_cpu(cpu, wakeup_mask))
184 continue;
185
186 /* wake up the core */
187 if (!xlp_wakeup_core(nodep->sysbase, n, core))
188 continue;
189
190 /* core is up */
191 nodep->coremask |= 1u << core;
192
193 /* spin until the hw threads sets their ready */
194 if (!wait_for_cpus(cpu, 0))
195 pr_err("Node %d : timeout core %d\n", n, core);
196 }
197 }
198}
199
200void xlp_wakeup_secondary_cpus(void)
201{
202 /*
203 * In case of u-boot, the secondaries are in reset
204 * first wakeup core 0 threads
205 */
206 xlp_boot_core0_siblings();
207 if (!wait_for_cpus(0, 0))
208 pr_err("Node 0 : timeout core 0\n");
209
210 /* now get other cores out of reset */
211 xlp_enable_secondary_cores(&nlm_cpumask);
212}
diff --git a/arch/mips/netlogic/xlr/Makefile b/arch/mips/netlogic/xlr/Makefile
new file mode 100644
index 000000000..7c83100e5
--- /dev/null
+++ b/arch/mips/netlogic/xlr/Makefile
@@ -0,0 +1,3 @@
1# SPDX-License-Identifier: GPL-2.0-only
2obj-y += fmn.o fmn-config.o setup.o platform.o platform-flash.o
3obj-$(CONFIG_SMP) += wakeup.o
diff --git a/arch/mips/netlogic/xlr/fmn-config.c b/arch/mips/netlogic/xlr/fmn-config.c
new file mode 100644
index 000000000..c7622c6e5
--- /dev/null
+++ b/arch/mips/netlogic/xlr/fmn-config.c
@@ -0,0 +1,293 @@
1/*
2 * Copyright (c) 2003-2012 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 <asm/cpu-info.h>
36#include <linux/irq.h>
37#include <linux/interrupt.h>
38
39#include <asm/cpu.h>
40#include <asm/mipsregs.h>
41#include <asm/netlogic/xlr/fmn.h>
42#include <asm/netlogic/xlr/xlr.h>
43#include <asm/netlogic/common.h>
44#include <asm/netlogic/haldefs.h>
45
46struct xlr_board_fmn_config xlr_board_fmn_config;
47
48static void __maybe_unused print_credit_config(struct xlr_fmn_info *fmn_info)
49{
50 int bkt;
51
52 pr_info("Bucket size :\n");
53 pr_info("Station\t: Size\n");
54 for (bkt = 0; bkt < 16; bkt++)
55 pr_info(" %d %d %d %d %d %d %d %d\n",
56 xlr_board_fmn_config.bucket_size[(bkt * 8) + 0],
57 xlr_board_fmn_config.bucket_size[(bkt * 8) + 1],
58 xlr_board_fmn_config.bucket_size[(bkt * 8) + 2],
59 xlr_board_fmn_config.bucket_size[(bkt * 8) + 3],
60 xlr_board_fmn_config.bucket_size[(bkt * 8) + 4],
61 xlr_board_fmn_config.bucket_size[(bkt * 8) + 5],
62 xlr_board_fmn_config.bucket_size[(bkt * 8) + 6],
63 xlr_board_fmn_config.bucket_size[(bkt * 8) + 7]);
64 pr_info("\n");
65
66 pr_info("Credits distribution :\n");
67 pr_info("Station\t: Size\n");
68 for (bkt = 0; bkt < 16; bkt++)
69 pr_info(" %d %d %d %d %d %d %d %d\n",
70 fmn_info->credit_config[(bkt * 8) + 0],
71 fmn_info->credit_config[(bkt * 8) + 1],
72 fmn_info->credit_config[(bkt * 8) + 2],
73 fmn_info->credit_config[(bkt * 8) + 3],
74 fmn_info->credit_config[(bkt * 8) + 4],
75 fmn_info->credit_config[(bkt * 8) + 5],
76 fmn_info->credit_config[(bkt * 8) + 6],
77 fmn_info->credit_config[(bkt * 8) + 7]);
78 pr_info("\n");
79}
80
81static void check_credit_distribution(void)
82{
83 struct xlr_board_fmn_config *cfg = &xlr_board_fmn_config;
84 int bkt, n, total_credits, ncores;
85
86 ncores = hweight32(nlm_current_node()->coremask);
87 for (bkt = 0; bkt < 128; bkt++) {
88 total_credits = 0;
89 for (n = 0; n < ncores; n++)
90 total_credits += cfg->cpu[n].credit_config[bkt];
91 total_credits += cfg->gmac[0].credit_config[bkt];
92 total_credits += cfg->gmac[1].credit_config[bkt];
93 total_credits += cfg->dma.credit_config[bkt];
94 total_credits += cfg->cmp.credit_config[bkt];
95 total_credits += cfg->sae.credit_config[bkt];
96 total_credits += cfg->xgmac[0].credit_config[bkt];
97 total_credits += cfg->xgmac[1].credit_config[bkt];
98 if (total_credits > cfg->bucket_size[bkt])
99 pr_err("ERROR: Bucket %d: credits (%d) > size (%d)\n",
100 bkt, total_credits, cfg->bucket_size[bkt]);
101 }
102 pr_info("Credit distribution complete.\n");
103}
104
105/**
106 * Configure bucket size and credits for a device. 'size' is the size of
107 * the buckets for the device. This size is distributed among all the CPUs
108 * so that all of them can send messages to the device.
109 *
110 * The device is also given 'cpu_credits' to send messages to the CPUs
111 *
112 * @dev_info: FMN information structure for each devices
113 * @start_stn_id: Starting station id of dev_info
114 * @end_stn_id: End station id of dev_info
115 * @num_buckets: Total number of buckets for den_info
116 * @cpu_credits: Allowed credits to cpu for each devices pointing by dev_info
117 * @size: Size of the each buckets in the device station
118 */
119static void setup_fmn_cc(struct xlr_fmn_info *dev_info, int start_stn_id,
120 int end_stn_id, int num_buckets, int cpu_credits, int size)
121{
122 int i, j, num_core, n, credits_per_cpu;
123 struct xlr_fmn_info *cpu = xlr_board_fmn_config.cpu;
124
125 num_core = hweight32(nlm_current_node()->coremask);
126 dev_info->num_buckets = num_buckets;
127 dev_info->start_stn_id = start_stn_id;
128 dev_info->end_stn_id = end_stn_id;
129
130 n = num_core;
131 if (num_core == 3)
132 n = 4;
133
134 for (i = start_stn_id; i <= end_stn_id; i++) {
135 xlr_board_fmn_config.bucket_size[i] = size;
136
137 /* Dividing device credits equally to cpus */
138 credits_per_cpu = size / n;
139 for (j = 0; j < num_core; j++)
140 cpu[j].credit_config[i] = credits_per_cpu;
141
142 /* credits left to distribute */
143 credits_per_cpu = size - (credits_per_cpu * num_core);
144
145 /* distribute the remaining credits (if any), among cores */
146 for (j = 0; (j < num_core) && (credits_per_cpu >= 4); j++) {
147 cpu[j].credit_config[i] += 4;
148 credits_per_cpu -= 4;
149 }
150 }
151
152 /* Distributing cpu per bucket credits to devices */
153 for (i = 0; i < num_core; i++) {
154 for (j = 0; j < FMN_CORE_NBUCKETS; j++)
155 dev_info->credit_config[(i * 8) + j] = cpu_credits;
156 }
157}
158
159/*
160 * Each core has 256 slots and 8 buckets,
161 * Configure the 8 buckets each with 32 slots
162 */
163static void setup_cpu_fmninfo(struct xlr_fmn_info *cpu, int num_core)
164{
165 int i, j;
166
167 for (i = 0; i < num_core; i++) {
168 cpu[i].start_stn_id = (8 * i);
169 cpu[i].end_stn_id = (8 * i + 8);
170
171 for (j = cpu[i].start_stn_id; j < cpu[i].end_stn_id; j++)
172 xlr_board_fmn_config.bucket_size[j] = 32;
173 }
174}
175
176/**
177 * Setup the FMN details for each devices according to the device available
178 * in each variant of XLR/XLS processor
179 */
180void xlr_board_info_setup(void)
181{
182 struct xlr_fmn_info *cpu = xlr_board_fmn_config.cpu;
183 struct xlr_fmn_info *gmac = xlr_board_fmn_config.gmac;
184 struct xlr_fmn_info *xgmac = xlr_board_fmn_config.xgmac;
185 struct xlr_fmn_info *dma = &xlr_board_fmn_config.dma;
186 struct xlr_fmn_info *cmp = &xlr_board_fmn_config.cmp;
187 struct xlr_fmn_info *sae = &xlr_board_fmn_config.sae;
188 int processor_id, num_core;
189
190 num_core = hweight32(nlm_current_node()->coremask);
191 processor_id = read_c0_prid() & PRID_IMP_MASK;
192
193 setup_cpu_fmninfo(cpu, num_core);
194 switch (processor_id) {
195 case PRID_IMP_NETLOGIC_XLS104:
196 case PRID_IMP_NETLOGIC_XLS108:
197 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
198 FMN_STNID_GMAC0_TX3, 8, 16, 32);
199 setup_fmn_cc(dma, FMN_STNID_DMA_0,
200 FMN_STNID_DMA_3, 4, 8, 64);
201 setup_fmn_cc(sae, FMN_STNID_SEC0,
202 FMN_STNID_SEC1, 2, 8, 128);
203 break;
204
205 case PRID_IMP_NETLOGIC_XLS204:
206 case PRID_IMP_NETLOGIC_XLS208:
207 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
208 FMN_STNID_GMAC0_TX3, 8, 16, 32);
209 setup_fmn_cc(dma, FMN_STNID_DMA_0,
210 FMN_STNID_DMA_3, 4, 8, 64);
211 setup_fmn_cc(sae, FMN_STNID_SEC0,
212 FMN_STNID_SEC1, 2, 8, 128);
213 break;
214
215 case PRID_IMP_NETLOGIC_XLS404:
216 case PRID_IMP_NETLOGIC_XLS408:
217 case PRID_IMP_NETLOGIC_XLS404B:
218 case PRID_IMP_NETLOGIC_XLS408B:
219 case PRID_IMP_NETLOGIC_XLS416B:
220 case PRID_IMP_NETLOGIC_XLS608B:
221 case PRID_IMP_NETLOGIC_XLS616B:
222 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
223 FMN_STNID_GMAC0_TX3, 8, 8, 32);
224 setup_fmn_cc(&gmac[1], FMN_STNID_GMAC1_FR_0,
225 FMN_STNID_GMAC1_TX3, 8, 8, 32);
226 setup_fmn_cc(dma, FMN_STNID_DMA_0,
227 FMN_STNID_DMA_3, 4, 4, 64);
228 setup_fmn_cc(cmp, FMN_STNID_CMP_0,
229 FMN_STNID_CMP_3, 4, 4, 64);
230 setup_fmn_cc(sae, FMN_STNID_SEC0,
231 FMN_STNID_SEC1, 2, 8, 128);
232 break;
233
234 case PRID_IMP_NETLOGIC_XLS412B:
235 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
236 FMN_STNID_GMAC0_TX3, 8, 8, 32);
237 setup_fmn_cc(&gmac[1], FMN_STNID_GMAC1_FR_0,
238 FMN_STNID_GMAC1_TX3, 8, 8, 32);
239 setup_fmn_cc(dma, FMN_STNID_DMA_0,
240 FMN_STNID_DMA_3, 4, 4, 64);
241 setup_fmn_cc(cmp, FMN_STNID_CMP_0,
242 FMN_STNID_CMP_3, 4, 4, 64);
243 setup_fmn_cc(sae, FMN_STNID_SEC0,
244 FMN_STNID_SEC1, 2, 8, 128);
245 break;
246
247 case PRID_IMP_NETLOGIC_XLR308:
248 case PRID_IMP_NETLOGIC_XLR308C:
249 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
250 FMN_STNID_GMAC0_TX3, 8, 16, 32);
251 setup_fmn_cc(dma, FMN_STNID_DMA_0,
252 FMN_STNID_DMA_3, 4, 8, 64);
253 setup_fmn_cc(sae, FMN_STNID_SEC0,
254 FMN_STNID_SEC1, 2, 4, 128);
255 break;
256
257 case PRID_IMP_NETLOGIC_XLR532:
258 case PRID_IMP_NETLOGIC_XLR532C:
259 case PRID_IMP_NETLOGIC_XLR516C:
260 case PRID_IMP_NETLOGIC_XLR508C:
261 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
262 FMN_STNID_GMAC0_TX3, 8, 16, 32);
263 setup_fmn_cc(dma, FMN_STNID_DMA_0,
264 FMN_STNID_DMA_3, 4, 8, 64);
265 setup_fmn_cc(sae, FMN_STNID_SEC0,
266 FMN_STNID_SEC1, 2, 4, 128);
267 break;
268
269 case PRID_IMP_NETLOGIC_XLR732:
270 case PRID_IMP_NETLOGIC_XLR716:
271 setup_fmn_cc(&xgmac[0], FMN_STNID_XMAC0_00_TX,
272 FMN_STNID_XMAC0_15_TX, 8, 0, 32);
273 setup_fmn_cc(&xgmac[1], FMN_STNID_XMAC1_00_TX,
274 FMN_STNID_XMAC1_15_TX, 8, 0, 32);
275 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
276 FMN_STNID_GMAC0_TX3, 8, 24, 32);
277 setup_fmn_cc(dma, FMN_STNID_DMA_0,
278 FMN_STNID_DMA_3, 4, 4, 64);
279 setup_fmn_cc(sae, FMN_STNID_SEC0,
280 FMN_STNID_SEC1, 2, 4, 128);
281 break;
282 default:
283 pr_err("Unknown CPU with processor ID [%d]\n", processor_id);
284 pr_err("Error: Cannot initialize FMN credits.\n");
285 }
286
287 check_credit_distribution();
288
289#if 0 /* debug */
290 print_credit_config(&cpu[0]);
291 print_credit_config(&gmac[0]);
292#endif
293}
diff --git a/arch/mips/netlogic/xlr/fmn.c b/arch/mips/netlogic/xlr/fmn.c
new file mode 100644
index 000000000..f90303f31
--- /dev/null
+++ b/arch/mips/netlogic/xlr/fmn.c
@@ -0,0 +1,199 @@
1/*
2 * Copyright (c) 2003-2012 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/irqreturn.h>
37#include <linux/irq.h>
38#include <linux/interrupt.h>
39
40#include <asm/mipsregs.h>
41#include <asm/netlogic/interrupt.h>
42#include <asm/netlogic/xlr/fmn.h>
43#include <asm/netlogic/common.h>
44
45#define COP2_CC_INIT_CPU_DEST(dest, conf) \
46do { \
47 nlm_write_c2_cc##dest(0, conf[(dest * 8) + 0]); \
48 nlm_write_c2_cc##dest(1, conf[(dest * 8) + 1]); \
49 nlm_write_c2_cc##dest(2, conf[(dest * 8) + 2]); \
50 nlm_write_c2_cc##dest(3, conf[(dest * 8) + 3]); \
51 nlm_write_c2_cc##dest(4, conf[(dest * 8) + 4]); \
52 nlm_write_c2_cc##dest(5, conf[(dest * 8) + 5]); \
53 nlm_write_c2_cc##dest(6, conf[(dest * 8) + 6]); \
54 nlm_write_c2_cc##dest(7, conf[(dest * 8) + 7]); \
55} while (0)
56
57struct fmn_message_handler {
58 void (*action)(int, int, int, int, struct nlm_fmn_msg *, void *);
59 void *arg;
60} msg_handlers[128];
61
62/*
63 * FMN interrupt handler. We configure the FMN so that any messages in
64 * any of the CPU buckets will trigger an interrupt on the CPU.
65 * The message can be from any device on the FMN (like NAE/SAE/DMA).
66 * The source station id is used to figure out which of the registered
67 * handlers have to be called.
68 */
69static irqreturn_t fmn_message_handler(int irq, void *data)
70{
71 struct fmn_message_handler *hndlr;
72 int bucket, rv;
73 int size = 0, code = 0, src_stnid = 0;
74 struct nlm_fmn_msg msg;
75 uint32_t mflags, bkt_status;
76
77 mflags = nlm_cop2_enable_irqsave();
78 /* Disable message ring interrupt */
79 nlm_fmn_setup_intr(irq, 0);
80 while (1) {
81 /* 8 bkts per core, [24:31] each bit represents one bucket
82 * Bit is Zero if bucket is not empty */
83 bkt_status = (nlm_read_c2_status0() >> 24) & 0xff;
84 if (bkt_status == 0xff)
85 break;
86 for (bucket = 0; bucket < 8; bucket++) {
87 /* Continue on empty bucket */
88 if (bkt_status & (1 << bucket))
89 continue;
90 rv = nlm_fmn_receive(bucket, &size, &code, &src_stnid,
91 &msg);
92 if (rv != 0)
93 continue;
94
95 hndlr = &msg_handlers[src_stnid];
96 if (hndlr->action == NULL)
97 pr_warn("No msgring handler for stnid %d\n",
98 src_stnid);
99 else {
100 nlm_cop2_disable_irqrestore(mflags);
101 hndlr->action(bucket, src_stnid, size, code,
102 &msg, hndlr->arg);
103 mflags = nlm_cop2_enable_irqsave();
104 }
105 }
106 }
107 /* Enable message ring intr, to any thread in core */
108 nlm_fmn_setup_intr(irq, (1 << nlm_threads_per_core) - 1);
109 nlm_cop2_disable_irqrestore(mflags);
110 return IRQ_HANDLED;
111}
112
113void xlr_percpu_fmn_init(void)
114{
115 struct xlr_fmn_info *cpu_fmn_info;
116 int *bucket_sizes;
117 uint32_t flags;
118 int id;
119
120 BUG_ON(nlm_thread_id() != 0);
121 id = nlm_core_id();
122
123 bucket_sizes = xlr_board_fmn_config.bucket_size;
124 cpu_fmn_info = &xlr_board_fmn_config.cpu[id];
125 flags = nlm_cop2_enable_irqsave();
126
127 /* Setup bucket sizes for the core. */
128 nlm_write_c2_bucksize(0, bucket_sizes[id * 8 + 0]);
129 nlm_write_c2_bucksize(1, bucket_sizes[id * 8 + 1]);
130 nlm_write_c2_bucksize(2, bucket_sizes[id * 8 + 2]);
131 nlm_write_c2_bucksize(3, bucket_sizes[id * 8 + 3]);
132 nlm_write_c2_bucksize(4, bucket_sizes[id * 8 + 4]);
133 nlm_write_c2_bucksize(5, bucket_sizes[id * 8 + 5]);
134 nlm_write_c2_bucksize(6, bucket_sizes[id * 8 + 6]);
135 nlm_write_c2_bucksize(7, bucket_sizes[id * 8 + 7]);
136
137 /*
138 * For sending FMN messages, we need credits on the destination
139 * bucket. Program the credits this core has on the 128 possible
140 * destination buckets.
141 * We cannot use a loop here, because the the first argument has
142 * to be a constant integer value.
143 */
144 COP2_CC_INIT_CPU_DEST(0, cpu_fmn_info->credit_config);
145 COP2_CC_INIT_CPU_DEST(1, cpu_fmn_info->credit_config);
146 COP2_CC_INIT_CPU_DEST(2, cpu_fmn_info->credit_config);
147 COP2_CC_INIT_CPU_DEST(3, cpu_fmn_info->credit_config);
148 COP2_CC_INIT_CPU_DEST(4, cpu_fmn_info->credit_config);
149 COP2_CC_INIT_CPU_DEST(5, cpu_fmn_info->credit_config);
150 COP2_CC_INIT_CPU_DEST(6, cpu_fmn_info->credit_config);
151 COP2_CC_INIT_CPU_DEST(7, cpu_fmn_info->credit_config);
152 COP2_CC_INIT_CPU_DEST(8, cpu_fmn_info->credit_config);
153 COP2_CC_INIT_CPU_DEST(9, cpu_fmn_info->credit_config);
154 COP2_CC_INIT_CPU_DEST(10, cpu_fmn_info->credit_config);
155 COP2_CC_INIT_CPU_DEST(11, cpu_fmn_info->credit_config);
156 COP2_CC_INIT_CPU_DEST(12, cpu_fmn_info->credit_config);
157 COP2_CC_INIT_CPU_DEST(13, cpu_fmn_info->credit_config);
158 COP2_CC_INIT_CPU_DEST(14, cpu_fmn_info->credit_config);
159 COP2_CC_INIT_CPU_DEST(15, cpu_fmn_info->credit_config);
160
161 /* enable FMN interrupts on this CPU */
162 nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1);
163 nlm_cop2_disable_irqrestore(flags);
164}
165
166
167/*
168 * Register a FMN message handler with respect to the source station id
169 * @stnid: source station id
170 * @action: Handler function pointer
171 */
172int nlm_register_fmn_handler(int start_stnid, int end_stnid,
173 void (*action)(int, int, int, int, struct nlm_fmn_msg *, void *),
174 void *arg)
175{
176 int sstnid;
177
178 for (sstnid = start_stnid; sstnid <= end_stnid; sstnid++) {
179 msg_handlers[sstnid].arg = arg;
180 smp_wmb();
181 msg_handlers[sstnid].action = action;
182 }
183 pr_debug("Registered FMN msg handler for stnid %d-%d\n",
184 start_stnid, end_stnid);
185 return 0;
186}
187
188void nlm_setup_fmn_irq(void)
189{
190 uint32_t flags;
191
192 /* request irq only once */
193 if (request_irq(IRQ_FMN, fmn_message_handler, IRQF_PERCPU, "fmn", NULL))
194 pr_err("Failed to request irq %d (fmn)\n", IRQ_FMN);
195
196 flags = nlm_cop2_enable_irqsave();
197 nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1);
198 nlm_cop2_disable_irqrestore(flags);
199}
diff --git a/arch/mips/netlogic/xlr/platform-flash.c b/arch/mips/netlogic/xlr/platform-flash.c
new file mode 100644
index 000000000..cf9162284
--- /dev/null
+++ b/arch/mips/netlogic/xlr/platform-flash.c
@@ -0,0 +1,216 @@
1/*
2 * Copyright 2011, Netlogic Microsystems.
3 * Copyright 2004, Matt Porter <mporter@kernel.crashing.org>
4 *
5 * This file is licensed under the terms of the GNU General Public
6 * License version 2. This program is licensed "as is" without any
7 * warranty of any kind, whether express or implied.
8 */
9
10#include <linux/device.h>
11#include <linux/platform_device.h>
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/io.h>
15#include <linux/delay.h>
16#include <linux/ioport.h>
17#include <linux/resource.h>
18#include <linux/spi/flash.h>
19
20#include <linux/mtd/mtd.h>
21#include <linux/mtd/physmap.h>
22#include <linux/mtd/platnand.h>
23
24#include <asm/netlogic/haldefs.h>
25#include <asm/netlogic/xlr/iomap.h>
26#include <asm/netlogic/xlr/flash.h>
27#include <asm/netlogic/xlr/bridge.h>
28#include <asm/netlogic/xlr/gpio.h>
29#include <asm/netlogic/xlr/xlr.h>
30
31/*
32 * Default NOR partition layout
33 */
34static struct mtd_partition xlr_nor_parts[] = {
35 {
36 .name = "User FS",
37 .offset = 0x800000,
38 .size = MTDPART_SIZ_FULL,
39 }
40};
41
42/*
43 * Default NAND partition layout
44 */
45static struct mtd_partition xlr_nand_parts[] = {
46 {
47 .name = "Root Filesystem",
48 .offset = 64 * 64 * 2048,
49 .size = 432 * 64 * 2048,
50 },
51 {
52 .name = "Home Filesystem",
53 .offset = MTDPART_OFS_APPEND,
54 .size = MTDPART_SIZ_FULL,
55 },
56};
57
58/* Use PHYSMAP flash for NOR */
59struct physmap_flash_data xlr_nor_data = {
60 .width = 2,
61 .parts = xlr_nor_parts,
62 .nr_parts = ARRAY_SIZE(xlr_nor_parts),
63};
64
65static struct resource xlr_nor_res[] = {
66 {
67 .flags = IORESOURCE_MEM,
68 },
69};
70
71static struct platform_device xlr_nor_dev = {
72 .name = "physmap-flash",
73 .dev = {
74 .platform_data = &xlr_nor_data,
75 },
76 .num_resources = ARRAY_SIZE(xlr_nor_res),
77 .resource = xlr_nor_res,
78};
79
80/*
81 * Use "gen_nand" driver for NAND flash
82 *
83 * There seems to be no way to store a private pointer containing
84 * platform specific info in gen_nand drivier. We will use a global
85 * struct for now, since we currently have only one NAND chip per board.
86 */
87struct xlr_nand_flash_priv {
88 int cs;
89 uint64_t flash_mmio;
90};
91
92static struct xlr_nand_flash_priv nand_priv;
93
94static void xlr_nand_ctrl(struct nand_chip *chip, int cmd,
95 unsigned int ctrl)
96{
97 if (ctrl & NAND_CLE)
98 nlm_write_reg(nand_priv.flash_mmio,
99 FLASH_NAND_CLE(nand_priv.cs), cmd);
100 else if (ctrl & NAND_ALE)
101 nlm_write_reg(nand_priv.flash_mmio,
102 FLASH_NAND_ALE(nand_priv.cs), cmd);
103}
104
105struct platform_nand_data xlr_nand_data = {
106 .chip = {
107 .nr_chips = 1,
108 .nr_partitions = ARRAY_SIZE(xlr_nand_parts),
109 .chip_delay = 50,
110 .partitions = xlr_nand_parts,
111 },
112 .ctrl = {
113 .cmd_ctrl = xlr_nand_ctrl,
114 },
115};
116
117static struct resource xlr_nand_res[] = {
118 {
119 .flags = IORESOURCE_MEM,
120 },
121};
122
123static struct platform_device xlr_nand_dev = {
124 .name = "gen_nand",
125 .id = -1,
126 .num_resources = ARRAY_SIZE(xlr_nand_res),
127 .resource = xlr_nand_res,
128 .dev = {
129 .platform_data = &xlr_nand_data,
130 }
131};
132
133/*
134 * XLR/XLS supports upto 8 devices on its FLASH interface. The value in
135 * FLASH_BAR (on the MEM/IO bridge) gives the base for mapping all the
136 * flash devices.
137 * Under this, each flash device has an offset and size given by the
138 * CSBASE_ADDR and CSBASE_MASK registers for the device.
139 *
140 * The CSBASE_ registers are expected to be setup by the bootloader.
141 */
142static void setup_flash_resource(uint64_t flash_mmio,
143 uint64_t flash_map_base, int cs, struct resource *res)
144{
145 u32 base, mask;
146
147 base = nlm_read_reg(flash_mmio, FLASH_CSBASE_ADDR(cs));
148 mask = nlm_read_reg(flash_mmio, FLASH_CSADDR_MASK(cs));
149
150 res->start = flash_map_base + ((unsigned long)base << 16);
151 res->end = res->start + (mask + 1) * 64 * 1024;
152}
153
154static int __init xlr_flash_init(void)
155{
156 uint64_t gpio_mmio, flash_mmio, flash_map_base;
157 u32 gpio_resetcfg, flash_bar;
158 int cs, boot_nand, boot_nor;
159
160 /* Flash address bits 39:24 is in bridge flash BAR */
161 flash_bar = nlm_read_reg(nlm_io_base, BRIDGE_FLASH_BAR);
162 flash_map_base = (flash_bar & 0xffff0000) << 8;
163
164 gpio_mmio = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET);
165 flash_mmio = nlm_mmio_base(NETLOGIC_IO_FLASH_OFFSET);
166
167 /* Get the chip reset config */
168 gpio_resetcfg = nlm_read_reg(gpio_mmio, GPIO_PWRON_RESET_CFG_REG);
169
170 /* Check for boot flash type */
171 boot_nor = boot_nand = 0;
172 if (nlm_chip_is_xls()) {
173 /* On XLS, check boot from NAND bit (GPIO reset reg bit 16) */
174 if (gpio_resetcfg & (1 << 16))
175 boot_nand = 1;
176
177 /* check boot from PCMCIA, (GPIO reset reg bit 15 */
178 if ((gpio_resetcfg & (1 << 15)) == 0)
179 boot_nor = 1; /* not set, booted from NOR */
180 } else { /* XLR */
181 /* check boot from PCMCIA (bit 16 in GPIO reset on XLR) */
182 if ((gpio_resetcfg & (1 << 16)) == 0)
183 boot_nor = 1; /* not set, booted from NOR */
184 }
185
186 /* boot flash at chip select 0 */
187 cs = 0;
188
189 if (boot_nand) {
190 nand_priv.cs = cs;
191 nand_priv.flash_mmio = flash_mmio;
192 setup_flash_resource(flash_mmio, flash_map_base, cs,
193 xlr_nand_res);
194
195 /* Initialize NAND flash at CS 0 */
196 nlm_write_reg(flash_mmio, FLASH_CSDEV_PARM(cs),
197 FLASH_NAND_CSDEV_PARAM);
198 nlm_write_reg(flash_mmio, FLASH_CSTIME_PARMA(cs),
199 FLASH_NAND_CSTIME_PARAMA);
200 nlm_write_reg(flash_mmio, FLASH_CSTIME_PARMB(cs),
201 FLASH_NAND_CSTIME_PARAMB);
202
203 pr_info("ChipSelect %d: NAND Flash %pR\n", cs, xlr_nand_res);
204 return platform_device_register(&xlr_nand_dev);
205 }
206
207 if (boot_nor) {
208 setup_flash_resource(flash_mmio, flash_map_base, cs,
209 xlr_nor_res);
210 pr_info("ChipSelect %d: NOR Flash %pR\n", cs, xlr_nor_res);
211 return platform_device_register(&xlr_nor_dev);
212 }
213 return 0;
214}
215
216arch_initcall(xlr_flash_init);
diff --git a/arch/mips/netlogic/xlr/platform.c b/arch/mips/netlogic/xlr/platform.c
new file mode 100644
index 000000000..4785932af
--- /dev/null
+++ b/arch/mips/netlogic/xlr/platform.c
@@ -0,0 +1,250 @@
1/*
2 * Copyright 2011, Netlogic Microsystems.
3 * Copyright 2004, Matt Porter <mporter@kernel.crashing.org>
4 *
5 * This file is licensed under the terms of the GNU General Public
6 * License version 2. This program is licensed "as is" without any
7 * warranty of any kind, whether express or implied.
8 */
9
10#include <linux/device.h>
11#include <linux/platform_device.h>
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/resource.h>
15#include <linux/serial_8250.h>
16#include <linux/serial_reg.h>
17#include <linux/i2c.h>
18#include <linux/usb/ehci_pdriver.h>
19#include <linux/usb/ohci_pdriver.h>
20
21#include <asm/netlogic/haldefs.h>
22#include <asm/netlogic/xlr/iomap.h>
23#include <asm/netlogic/xlr/pic.h>
24#include <asm/netlogic/xlr/xlr.h>
25
26static unsigned int nlm_xlr_uart_in(struct uart_port *p, int offset)
27{
28 uint64_t uartbase;
29 unsigned int value;
30
31 /* sign extend to 64 bits, if needed */
32 uartbase = (uint64_t)(long)p->membase;
33 value = nlm_read_reg(uartbase, offset);
34
35 /* See XLR/XLS errata */
36 if (offset == UART_MSR)
37 value ^= 0xF0;
38 else if (offset == UART_MCR)
39 value ^= 0x3;
40
41 return value;
42}
43
44static void nlm_xlr_uart_out(struct uart_port *p, int offset, int value)
45{
46 uint64_t uartbase;
47
48 /* sign extend to 64 bits, if needed */
49 uartbase = (uint64_t)(long)p->membase;
50
51 /* See XLR/XLS errata */
52 if (offset == UART_MSR)
53 value ^= 0xF0;
54 else if (offset == UART_MCR)
55 value ^= 0x3;
56
57 nlm_write_reg(uartbase, offset, value);
58}
59
60#define PORT(_irq) \
61 { \
62 .irq = _irq, \
63 .regshift = 2, \
64 .iotype = UPIO_MEM32, \
65 .flags = (UPF_SKIP_TEST | \
66 UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF),\
67 .uartclk = PIC_CLK_HZ, \
68 .type = PORT_16550A, \
69 .serial_in = nlm_xlr_uart_in, \
70 .serial_out = nlm_xlr_uart_out, \
71 }
72
73static struct plat_serial8250_port xlr_uart_data[] = {
74 PORT(PIC_UART_0_IRQ),
75 PORT(PIC_UART_1_IRQ),
76 {},
77};
78
79static struct platform_device uart_device = {
80 .name = "serial8250",
81 .id = PLAT8250_DEV_PLATFORM,
82 .dev = {
83 .platform_data = xlr_uart_data,
84 },
85};
86
87static int __init nlm_uart_init(void)
88{
89 unsigned long uartbase;
90
91 uartbase = (unsigned long)nlm_mmio_base(NETLOGIC_IO_UART_0_OFFSET);
92 xlr_uart_data[0].membase = (void __iomem *)uartbase;
93 xlr_uart_data[0].mapbase = CPHYSADDR(uartbase);
94
95 uartbase = (unsigned long)nlm_mmio_base(NETLOGIC_IO_UART_1_OFFSET);
96 xlr_uart_data[1].membase = (void __iomem *)uartbase;
97 xlr_uart_data[1].mapbase = CPHYSADDR(uartbase);
98
99 return platform_device_register(&uart_device);
100}
101
102arch_initcall(nlm_uart_init);
103
104#ifdef CONFIG_USB
105/* Platform USB devices, only on XLS chips */
106static u64 xls_usb_dmamask = ~(u32)0;
107#define USB_PLATFORM_DEV(n, i, irq) \
108 { \
109 .name = n, \
110 .id = i, \
111 .num_resources = 2, \
112 .dev = { \
113 .dma_mask = &xls_usb_dmamask, \
114 .coherent_dma_mask = 0xffffffff, \
115 }, \
116 .resource = (struct resource[]) { \
117 { \
118 .flags = IORESOURCE_MEM, \
119 }, \
120 { \
121 .start = irq, \
122 .end = irq, \
123 .flags = IORESOURCE_IRQ, \
124 }, \
125 }, \
126 }
127
128static struct usb_ehci_pdata xls_usb_ehci_pdata = {
129 .caps_offset = 0,
130};
131
132static struct usb_ohci_pdata xls_usb_ohci_pdata;
133
134static struct platform_device xls_usb_ehci_device =
135 USB_PLATFORM_DEV("ehci-platform", 0, PIC_USB_IRQ);
136static struct platform_device xls_usb_ohci_device_0 =
137 USB_PLATFORM_DEV("ohci-platform", 1, PIC_USB_IRQ);
138static struct platform_device xls_usb_ohci_device_1 =
139 USB_PLATFORM_DEV("ohci-platform", 2, PIC_USB_IRQ);
140
141static struct platform_device *xls_platform_devices[] = {
142 &xls_usb_ehci_device,
143 &xls_usb_ohci_device_0,
144 &xls_usb_ohci_device_1,
145};
146
147int xls_platform_usb_init(void)
148{
149 uint64_t usb_mmio, gpio_mmio;
150 unsigned long memres;
151 uint32_t val;
152
153 if (!nlm_chip_is_xls())
154 return 0;
155
156 gpio_mmio = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET);
157 usb_mmio = nlm_mmio_base(NETLOGIC_IO_USB_1_OFFSET);
158
159 /* Clear Rogue Phy INTs */
160 nlm_write_reg(usb_mmio, 49, 0x10000000);
161 /* Enable all interrupts */
162 nlm_write_reg(usb_mmio, 50, 0x1f000000);
163
164 /* Enable ports */
165 nlm_write_reg(usb_mmio, 1, 0x07000500);
166
167 val = nlm_read_reg(gpio_mmio, 21);
168 if (((val >> 22) & 0x01) == 0) {
169 pr_info("Detected USB Device mode - Not supported!\n");
170 nlm_write_reg(usb_mmio, 0, 0x01000000);
171 return 0;
172 }
173
174 pr_info("Detected USB Host mode - Adding XLS USB devices.\n");
175 /* Clear reset, host mode */
176 nlm_write_reg(usb_mmio, 0, 0x02000000);
177
178 /* Memory resource for various XLS usb ports */
179 usb_mmio = nlm_mmio_base(NETLOGIC_IO_USB_0_OFFSET);
180 memres = CPHYSADDR((unsigned long)usb_mmio);
181 xls_usb_ehci_device.resource[0].start = memres;
182 xls_usb_ehci_device.resource[0].end = memres + 0x400 - 1;
183 xls_usb_ehci_device.dev.platform_data = &xls_usb_ehci_pdata;
184
185 memres += 0x400;
186 xls_usb_ohci_device_0.resource[0].start = memres;
187 xls_usb_ohci_device_0.resource[0].end = memres + 0x400 - 1;
188 xls_usb_ohci_device_0.dev.platform_data = &xls_usb_ohci_pdata;
189
190 memres += 0x400;
191 xls_usb_ohci_device_1.resource[0].start = memres;
192 xls_usb_ohci_device_1.resource[0].end = memres + 0x400 - 1;
193 xls_usb_ohci_device_1.dev.platform_data = &xls_usb_ohci_pdata;
194
195 return platform_add_devices(xls_platform_devices,
196 ARRAY_SIZE(xls_platform_devices));
197}
198
199arch_initcall(xls_platform_usb_init);
200#endif
201
202#ifdef CONFIG_I2C
203static struct i2c_board_info nlm_i2c_board_info1[] __initdata = {
204 /* All XLR boards have this RTC and Max6657 Temp Chip */
205 [0] = {
206 .type = "ds1374",
207 .addr = 0x68
208 },
209 [1] = {
210 .type = "lm90",
211 .addr = 0x4c
212 },
213};
214
215static struct resource i2c_resources[] = {
216 [0] = {
217 .start = 0, /* filled at init */
218 .end = 0,
219 .flags = IORESOURCE_MEM,
220 },
221};
222
223static struct platform_device nlm_xlr_i2c_1 = {
224 .name = "xlr-i2cbus",
225 .id = 1,
226 .num_resources = 1,
227 .resource = i2c_resources,
228};
229
230static int __init nlm_i2c_init(void)
231{
232 int err = 0;
233 unsigned int offset;
234
235 /* I2C bus 0 does not have any useful devices, configure only bus 1 */
236 offset = NETLOGIC_IO_I2C_1_OFFSET;
237 nlm_xlr_i2c_1.resource[0].start = CPHYSADDR(nlm_mmio_base(offset));
238 nlm_xlr_i2c_1.resource[0].end = nlm_xlr_i2c_1.resource[0].start + 0xfff;
239
240 platform_device_register(&nlm_xlr_i2c_1);
241
242 err = i2c_register_board_info(1, nlm_i2c_board_info1,
243 ARRAY_SIZE(nlm_i2c_board_info1));
244 if (err < 0)
245 pr_err("nlm-i2c: cannot register board I2C devices\n");
246 return err;
247}
248
249arch_initcall(nlm_i2c_init);
250#endif
diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c
new file mode 100644
index 000000000..627e88101
--- /dev/null
+++ b/arch/mips/netlogic/xlr/setup.c
@@ -0,0 +1,211 @@
1/*
2 * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
3 * 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 NetLogic
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 NETLOGIC ``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 NETLOGIC 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/serial_8250.h>
37#include <linux/memblock.h>
38#include <linux/pm.h>
39
40#include <asm/idle.h>
41#include <asm/reboot.h>
42#include <asm/time.h>
43#include <asm/bootinfo.h>
44
45#include <asm/netlogic/interrupt.h>
46#include <asm/netlogic/psb-bootinfo.h>
47#include <asm/netlogic/haldefs.h>
48#include <asm/netlogic/common.h>
49
50#include <asm/netlogic/xlr/xlr.h>
51#include <asm/netlogic/xlr/iomap.h>
52#include <asm/netlogic/xlr/pic.h>
53#include <asm/netlogic/xlr/gpio.h>
54#include <asm/netlogic/xlr/fmn.h>
55
56uint64_t nlm_io_base = DEFAULT_NETLOGIC_IO_BASE;
57struct psb_info nlm_prom_info;
58
59/* default to uniprocessor */
60unsigned int nlm_threads_per_core = 1;
61struct nlm_soc_info nlm_nodes[NLM_NR_NODES];
62cpumask_t nlm_cpumask = CPU_MASK_CPU0;
63
64static void nlm_linux_exit(void)
65{
66 uint64_t gpiobase;
67
68 gpiobase = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET);
69 /* trigger a chip reset by writing 1 to GPIO_SWRESET_REG */
70 nlm_write_reg(gpiobase, GPIO_SWRESET_REG, 1);
71 for ( ; ; )
72 cpu_wait();
73}
74
75void __init plat_mem_setup(void)
76{
77 _machine_restart = (void (*)(char *))nlm_linux_exit;
78 _machine_halt = nlm_linux_exit;
79 pm_power_off = nlm_linux_exit;
80}
81
82const char *get_system_type(void)
83{
84 return "Netlogic XLR/XLS Series";
85}
86
87unsigned int nlm_get_cpu_frequency(void)
88{
89 return (unsigned int)nlm_prom_info.cpu_frequency;
90}
91
92void __init prom_free_prom_memory(void)
93{
94 /* Nothing yet */
95}
96
97void nlm_percpu_init(int hwcpuid)
98{
99 if (hwcpuid % 4 == 0)
100 xlr_percpu_fmn_init();
101}
102
103static void __init build_arcs_cmdline(int *argv)
104{
105 int i, remain, len;
106 char *arg;
107
108 remain = sizeof(arcs_cmdline) - 1;
109 arcs_cmdline[0] = '\0';
110 for (i = 0; argv[i] != 0; i++) {
111 arg = (char *)(long)argv[i];
112 len = strlen(arg);
113 if (len + 1 > remain)
114 break;
115 strcat(arcs_cmdline, arg);
116 strcat(arcs_cmdline, " ");
117 remain -= len + 1;
118 }
119
120 /* Add the default options here */
121 if ((strstr(arcs_cmdline, "console=")) == NULL) {
122 arg = "console=ttyS0,38400 ";
123 len = strlen(arg);
124 if (len > remain)
125 goto fail;
126 strcat(arcs_cmdline, arg);
127 remain -= len;
128 }
129#ifdef CONFIG_BLK_DEV_INITRD
130 if ((strstr(arcs_cmdline, "rdinit=")) == NULL) {
131 arg = "rdinit=/sbin/init ";
132 len = strlen(arg);
133 if (len > remain)
134 goto fail;
135 strcat(arcs_cmdline, arg);
136 remain -= len;
137 }
138#endif
139 return;
140fail:
141 panic("Cannot add %s, command line too big!", arg);
142}
143
144static void prom_add_memory(void)
145{
146 struct nlm_boot_mem_map *bootm;
147 u64 start, size;
148 u64 pref_backup = 512; /* avoid pref walking beyond end */
149 int i;
150
151 bootm = (void *)(long)nlm_prom_info.psb_mem_map;
152 for (i = 0; i < bootm->nr_map; i++) {
153 if (bootm->map[i].type != NLM_BOOT_MEM_RAM)
154 continue;
155 start = bootm->map[i].addr;
156 size = bootm->map[i].size;
157
158 /* Work around for using bootloader mem */
159 if (i == 0 && start == 0 && size == 0x0c000000)
160 size = 0x0ff00000;
161
162 memblock_add(start, size - pref_backup);
163 }
164}
165
166static void nlm_init_node(void)
167{
168 struct nlm_soc_info *nodep;
169
170 nodep = nlm_current_node();
171 nodep->picbase = nlm_mmio_base(NETLOGIC_IO_PIC_OFFSET);
172 nodep->ebase = read_c0_ebase() & MIPS_EBASE_BASE;
173 spin_lock_init(&nodep->piclock);
174}
175
176void __init prom_init(void)
177{
178 int *argv, *envp; /* passed as 32 bit ptrs */
179 struct psb_info *prom_infop;
180 void *reset_vec;
181#ifdef CONFIG_SMP
182 int i;
183#endif
184
185 /* truncate to 32 bit and sign extend all args */
186 argv = (int *)(long)(int)fw_arg1;
187 envp = (int *)(long)(int)fw_arg2;
188 prom_infop = (struct psb_info *)(long)(int)fw_arg3;
189
190 nlm_prom_info = *prom_infop;
191 nlm_init_node();
192
193 /* Update reset entry point with CPU init code */
194 reset_vec = (void *)CKSEG1ADDR(RESET_VEC_PHYS);
195 memset(reset_vec, 0, RESET_VEC_SIZE);
196 memcpy(reset_vec, (void *)nlm_reset_entry,
197 (nlm_reset_entry_end - nlm_reset_entry));
198
199 build_arcs_cmdline(argv);
200 prom_add_memory();
201
202#ifdef CONFIG_SMP
203 for (i = 0; i < 32; i++)
204 if (nlm_prom_info.online_cpu_map & (1 << i))
205 cpumask_set_cpu(i, &nlm_cpumask);
206 nlm_wakeup_secondary_cpus();
207 register_smp_ops(&nlm_smp_ops);
208#endif
209 xlr_board_info_setup();
210 xlr_percpu_fmn_init();
211}
diff --git a/arch/mips/netlogic/xlr/wakeup.c b/arch/mips/netlogic/xlr/wakeup.c
new file mode 100644
index 000000000..d61cba1e9
--- /dev/null
+++ b/arch/mips/netlogic/xlr/wakeup.c
@@ -0,0 +1,85 @@
1/*
2 * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
3 * 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 NetLogic
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 NETLOGIC ``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 NETLOGIC 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/delay.h>
36#include <linux/threads.h>
37
38#include <asm/asm.h>
39#include <asm/asm-offsets.h>
40#include <asm/mipsregs.h>
41#include <asm/addrspace.h>
42#include <asm/string.h>
43
44#include <asm/netlogic/haldefs.h>
45#include <asm/netlogic/common.h>
46#include <asm/netlogic/mips-extns.h>
47
48#include <asm/netlogic/xlr/iomap.h>
49#include <asm/netlogic/xlr/pic.h>
50
51int xlr_wakeup_secondary_cpus(void)
52{
53 struct nlm_soc_info *nodep;
54 unsigned int i, j, boot_cpu;
55 volatile u32 *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY);
56
57 /*
58 * In case of RMI boot, hit with NMI to get the cores
59 * from bootloader to linux code.
60 */
61 nodep = nlm_get_node(0);
62 boot_cpu = hard_smp_processor_id();
63 nlm_set_nmi_handler(nlm_rmiboot_preboot);
64 for (i = 0; i < NR_CPUS; i++) {
65 if (i == boot_cpu || !cpumask_test_cpu(i, &nlm_cpumask))
66 continue;
67 nlm_pic_send_ipi(nodep->picbase, i, 1, 1); /* send NMI */
68 }
69
70 /* Fill up the coremask early */
71 nodep->coremask = 1;
72 for (i = 1; i < nlm_cores_per_node(); i++) {
73 for (j = 1000000; j > 0; j--) {
74 if (cpu_ready[i * NLM_THREADS_PER_CORE])
75 break;
76 udelay(10);
77 }
78 if (j != 0)
79 nodep->coremask |= (1u << i);
80 else
81 pr_err("Failed to wakeup core %d\n", i);
82 }
83
84 return 0;
85}