aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/include/asm/netlogic/common.h1
-rw-r--r--arch/mips/include/asm/netlogic/interrupt.h2
-rw-r--r--arch/mips/include/asm/netlogic/mips-extns.h137
-rw-r--r--arch/mips/include/asm/netlogic/xlr/fmn.h363
-rw-r--r--arch/mips/include/asm/netlogic/xlr/xlr.h6
-rw-r--r--arch/mips/netlogic/common/irq.c8
-rw-r--r--arch/mips/netlogic/common/smp.c4
-rw-r--r--arch/mips/netlogic/xlp/setup.c4
-rw-r--r--arch/mips/netlogic/xlr/Makefile4
-rw-r--r--arch/mips/netlogic/xlr/fmn-config.c290
-rw-r--r--arch/mips/netlogic/xlr/fmn.c204
-rw-r--r--arch/mips/netlogic/xlr/setup.c9
12 files changed, 1020 insertions, 12 deletions
diff --git a/arch/mips/include/asm/netlogic/common.h b/arch/mips/include/asm/netlogic/common.h
index 1fee7eff64a..42bfd5f1eee 100644
--- a/arch/mips/include/asm/netlogic/common.h
+++ b/arch/mips/include/asm/netlogic/common.h
@@ -57,6 +57,7 @@ void nlm_smp_irq_init(int hwcpuid);
57void nlm_boot_secondary_cpus(void); 57void nlm_boot_secondary_cpus(void);
58int nlm_wakeup_secondary_cpus(void); 58int nlm_wakeup_secondary_cpus(void);
59void nlm_rmiboot_preboot(void); 59void nlm_rmiboot_preboot(void);
60void nlm_percpu_init(int hwcpuid);
60 61
61static inline void 62static inline void
62nlm_set_nmi_handler(void *handler) 63nlm_set_nmi_handler(void *handler)
diff --git a/arch/mips/include/asm/netlogic/interrupt.h b/arch/mips/include/asm/netlogic/interrupt.h
index a85aadb6cfd..ed5993d9b7b 100644
--- a/arch/mips/include/asm/netlogic/interrupt.h
+++ b/arch/mips/include/asm/netlogic/interrupt.h
@@ -39,7 +39,7 @@
39 39
40#define IRQ_IPI_SMP_FUNCTION 3 40#define IRQ_IPI_SMP_FUNCTION 3
41#define IRQ_IPI_SMP_RESCHEDULE 4 41#define IRQ_IPI_SMP_RESCHEDULE 4
42#define IRQ_MSGRING 6 42#define IRQ_FMN 5
43#define IRQ_TIMER 7 43#define IRQ_TIMER 7
44 44
45#endif 45#endif
diff --git a/arch/mips/include/asm/netlogic/mips-extns.h b/arch/mips/include/asm/netlogic/mips-extns.h
index c9f6de53d41..32ba6d95d47 100644
--- a/arch/mips/include/asm/netlogic/mips-extns.h
+++ b/arch/mips/include/asm/netlogic/mips-extns.h
@@ -78,4 +78,141 @@ static inline int nlm_nodeid(void)
78 return (__read_32bit_c0_register($15, 1) >> 5) & 0x3; 78 return (__read_32bit_c0_register($15, 1) >> 5) & 0x3;
79} 79}
80 80
81static inline unsigned int nlm_core_id(void)
82{
83 return (read_c0_ebase() & 0x1c) >> 2;
84}
85
86static inline unsigned int nlm_thread_id(void)
87{
88 return read_c0_ebase() & 0x3;
89}
90
91#define __read_64bit_c2_split(source, sel) \
92({ \
93 unsigned long long __val; \
94 unsigned long __flags; \
95 \
96 local_irq_save(__flags); \
97 if (sel == 0) \
98 __asm__ __volatile__( \
99 ".set\tmips64\n\t" \
100 "dmfc2\t%M0, " #source "\n\t" \
101 "dsll\t%L0, %M0, 32\n\t" \
102 "dsra\t%M0, %M0, 32\n\t" \
103 "dsra\t%L0, %L0, 32\n\t" \
104 ".set\tmips0\n\t" \
105 : "=r" (__val)); \
106 else \
107 __asm__ __volatile__( \
108 ".set\tmips64\n\t" \
109 "dmfc2\t%M0, " #source ", " #sel "\n\t" \
110 "dsll\t%L0, %M0, 32\n\t" \
111 "dsra\t%M0, %M0, 32\n\t" \
112 "dsra\t%L0, %L0, 32\n\t" \
113 ".set\tmips0\n\t" \
114 : "=r" (__val)); \
115 local_irq_restore(__flags); \
116 \
117 __val; \
118})
119
120#define __write_64bit_c2_split(source, sel, val) \
121do { \
122 unsigned long __flags; \
123 \
124 local_irq_save(__flags); \
125 if (sel == 0) \
126 __asm__ __volatile__( \
127 ".set\tmips64\n\t" \
128 "dsll\t%L0, %L0, 32\n\t" \
129 "dsrl\t%L0, %L0, 32\n\t" \
130 "dsll\t%M0, %M0, 32\n\t" \
131 "or\t%L0, %L0, %M0\n\t" \
132 "dmtc2\t%L0, " #source "\n\t" \
133 ".set\tmips0\n\t" \
134 : : "r" (val)); \
135 else \
136 __asm__ __volatile__( \
137 ".set\tmips64\n\t" \
138 "dsll\t%L0, %L0, 32\n\t" \
139 "dsrl\t%L0, %L0, 32\n\t" \
140 "dsll\t%M0, %M0, 32\n\t" \
141 "or\t%L0, %L0, %M0\n\t" \
142 "dmtc2\t%L0, " #source ", " #sel "\n\t" \
143 ".set\tmips0\n\t" \
144 : : "r" (val)); \
145 local_irq_restore(__flags); \
146} while (0)
147
148#define __read_32bit_c2_register(source, sel) \
149({ uint32_t __res; \
150 if (sel == 0) \
151 __asm__ __volatile__( \
152 ".set\tmips32\n\t" \
153 "mfc2\t%0, " #source "\n\t" \
154 ".set\tmips0\n\t" \
155 : "=r" (__res)); \
156 else \
157 __asm__ __volatile__( \
158 ".set\tmips32\n\t" \
159 "mfc2\t%0, " #source ", " #sel "\n\t" \
160 ".set\tmips0\n\t" \
161 : "=r" (__res)); \
162 __res; \
163})
164
165#define __read_64bit_c2_register(source, sel) \
166({ unsigned long long __res; \
167 if (sizeof(unsigned long) == 4) \
168 __res = __read_64bit_c2_split(source, sel); \
169 else if (sel == 0) \
170 __asm__ __volatile__( \
171 ".set\tmips64\n\t" \
172 "dmfc2\t%0, " #source "\n\t" \
173 ".set\tmips0\n\t" \
174 : "=r" (__res)); \
175 else \
176 __asm__ __volatile__( \
177 ".set\tmips64\n\t" \
178 "dmfc2\t%0, " #source ", " #sel "\n\t" \
179 ".set\tmips0\n\t" \
180 : "=r" (__res)); \
181 __res; \
182})
183
184#define __write_64bit_c2_register(register, sel, value) \
185do { \
186 if (sizeof(unsigned long) == 4) \
187 __write_64bit_c2_split(register, sel, value); \
188 else if (sel == 0) \
189 __asm__ __volatile__( \
190 ".set\tmips64\n\t" \
191 "dmtc2\t%z0, " #register "\n\t" \
192 ".set\tmips0\n\t" \
193 : : "Jr" (value)); \
194 else \
195 __asm__ __volatile__( \
196 ".set\tmips64\n\t" \
197 "dmtc2\t%z0, " #register ", " #sel "\n\t" \
198 ".set\tmips0\n\t" \
199 : : "Jr" (value)); \
200} while (0)
201
202#define __write_32bit_c2_register(reg, sel, value) \
203({ \
204 if (sel == 0) \
205 __asm__ __volatile__( \
206 ".set\tmips32\n\t" \
207 "mtc2\t%z0, " #reg "\n\t" \
208 ".set\tmips0\n\t" \
209 : : "Jr" (value)); \
210 else \
211 __asm__ __volatile__( \
212 ".set\tmips32\n\t" \
213 "mtc2\t%z0, " #reg ", " #sel "\n\t" \
214 ".set\tmips0\n\t" \
215 : : "Jr" (value)); \
216})
217
81#endif /*_ASM_NLM_MIPS_EXTS_H */ 218#endif /*_ASM_NLM_MIPS_EXTS_H */
diff --git a/arch/mips/include/asm/netlogic/xlr/fmn.h b/arch/mips/include/asm/netlogic/xlr/fmn.h
new file mode 100644
index 00000000000..68d5167c86b
--- /dev/null
+++ b/arch/mips/include/asm/netlogic/xlr/fmn.h
@@ -0,0 +1,363 @@
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#ifndef _NLM_FMN_H_
36#define _NLM_FMN_H_
37
38#include <asm/netlogic/mips-extns.h> /* for COP2 access */
39
40/* Station IDs */
41#define FMN_STNID_CPU0 0x00
42#define FMN_STNID_CPU1 0x08
43#define FMN_STNID_CPU2 0x10
44#define FMN_STNID_CPU3 0x18
45#define FMN_STNID_CPU4 0x20
46#define FMN_STNID_CPU5 0x28
47#define FMN_STNID_CPU6 0x30
48#define FMN_STNID_CPU7 0x38
49
50#define FMN_STNID_XGS0_TX 64
51#define FMN_STNID_XMAC0_00_TX 64
52#define FMN_STNID_XMAC0_01_TX 65
53#define FMN_STNID_XMAC0_02_TX 66
54#define FMN_STNID_XMAC0_03_TX 67
55#define FMN_STNID_XMAC0_04_TX 68
56#define FMN_STNID_XMAC0_05_TX 69
57#define FMN_STNID_XMAC0_06_TX 70
58#define FMN_STNID_XMAC0_07_TX 71
59#define FMN_STNID_XMAC0_08_TX 72
60#define FMN_STNID_XMAC0_09_TX 73
61#define FMN_STNID_XMAC0_10_TX 74
62#define FMN_STNID_XMAC0_11_TX 75
63#define FMN_STNID_XMAC0_12_TX 76
64#define FMN_STNID_XMAC0_13_TX 77
65#define FMN_STNID_XMAC0_14_TX 78
66#define FMN_STNID_XMAC0_15_TX 79
67
68#define FMN_STNID_XGS1_TX 80
69#define FMN_STNID_XMAC1_00_TX 80
70#define FMN_STNID_XMAC1_01_TX 81
71#define FMN_STNID_XMAC1_02_TX 82
72#define FMN_STNID_XMAC1_03_TX 83
73#define FMN_STNID_XMAC1_04_TX 84
74#define FMN_STNID_XMAC1_05_TX 85
75#define FMN_STNID_XMAC1_06_TX 86
76#define FMN_STNID_XMAC1_07_TX 87
77#define FMN_STNID_XMAC1_08_TX 88
78#define FMN_STNID_XMAC1_09_TX 89
79#define FMN_STNID_XMAC1_10_TX 90
80#define FMN_STNID_XMAC1_11_TX 91
81#define FMN_STNID_XMAC1_12_TX 92
82#define FMN_STNID_XMAC1_13_TX 93
83#define FMN_STNID_XMAC1_14_TX 94
84#define FMN_STNID_XMAC1_15_TX 95
85
86#define FMN_STNID_GMAC 96
87#define FMN_STNID_GMACJFR_0 96
88#define FMN_STNID_GMACRFR_0 97
89#define FMN_STNID_GMACTX0 98
90#define FMN_STNID_GMACTX1 99
91#define FMN_STNID_GMACTX2 100
92#define FMN_STNID_GMACTX3 101
93#define FMN_STNID_GMACJFR_1 102
94#define FMN_STNID_GMACRFR_1 103
95
96#define FMN_STNID_DMA 104
97#define FMN_STNID_DMA_0 104
98#define FMN_STNID_DMA_1 105
99#define FMN_STNID_DMA_2 106
100#define FMN_STNID_DMA_3 107
101
102#define FMN_STNID_XGS0FR 112
103#define FMN_STNID_XMAC0JFR 112
104#define FMN_STNID_XMAC0RFR 113
105
106#define FMN_STNID_XGS1FR 114
107#define FMN_STNID_XMAC1JFR 114
108#define FMN_STNID_XMAC1RFR 115
109#define FMN_STNID_SEC 120
110#define FMN_STNID_SEC0 120
111#define FMN_STNID_SEC1 121
112#define FMN_STNID_SEC2 122
113#define FMN_STNID_SEC3 123
114#define FMN_STNID_PK0 124
115#define FMN_STNID_SEC_RSA 124
116#define FMN_STNID_SEC_RSVD0 125
117#define FMN_STNID_SEC_RSVD1 126
118#define FMN_STNID_SEC_RSVD2 127
119
120#define FMN_STNID_GMAC1 80
121#define FMN_STNID_GMAC1_FR_0 81
122#define FMN_STNID_GMAC1_TX0 82
123#define FMN_STNID_GMAC1_TX1 83
124#define FMN_STNID_GMAC1_TX2 84
125#define FMN_STNID_GMAC1_TX3 85
126#define FMN_STNID_GMAC1_FR_1 87
127#define FMN_STNID_GMAC0 96
128#define FMN_STNID_GMAC0_FR_0 97
129#define FMN_STNID_GMAC0_TX0 98
130#define FMN_STNID_GMAC0_TX1 99
131#define FMN_STNID_GMAC0_TX2 100
132#define FMN_STNID_GMAC0_TX3 101
133#define FMN_STNID_GMAC0_FR_1 103
134#define FMN_STNID_CMP_0 108
135#define FMN_STNID_CMP_1 109
136#define FMN_STNID_CMP_2 110
137#define FMN_STNID_CMP_3 111
138#define FMN_STNID_PCIE_0 116
139#define FMN_STNID_PCIE_1 117
140#define FMN_STNID_PCIE_2 118
141#define FMN_STNID_PCIE_3 119
142#define FMN_STNID_XLS_PK0 121
143
144#define nlm_read_c2_cc0(s) __read_32bit_c2_register($16, s)
145#define nlm_read_c2_cc1(s) __read_32bit_c2_register($17, s)
146#define nlm_read_c2_cc2(s) __read_32bit_c2_register($18, s)
147#define nlm_read_c2_cc3(s) __read_32bit_c2_register($19, s)
148#define nlm_read_c2_cc4(s) __read_32bit_c2_register($20, s)
149#define nlm_read_c2_cc5(s) __read_32bit_c2_register($21, s)
150#define nlm_read_c2_cc6(s) __read_32bit_c2_register($22, s)
151#define nlm_read_c2_cc7(s) __read_32bit_c2_register($23, s)
152#define nlm_read_c2_cc8(s) __read_32bit_c2_register($24, s)
153#define nlm_read_c2_cc9(s) __read_32bit_c2_register($25, s)
154#define nlm_read_c2_cc10(s) __read_32bit_c2_register($26, s)
155#define nlm_read_c2_cc11(s) __read_32bit_c2_register($27, s)
156#define nlm_read_c2_cc12(s) __read_32bit_c2_register($28, s)
157#define nlm_read_c2_cc13(s) __read_32bit_c2_register($29, s)
158#define nlm_read_c2_cc14(s) __read_32bit_c2_register($30, s)
159#define nlm_read_c2_cc15(s) __read_32bit_c2_register($31, s)
160
161#define nlm_write_c2_cc0(s, v) __write_32bit_c2_register($16, s, v)
162#define nlm_write_c2_cc1(s, v) __write_32bit_c2_register($17, s, v)
163#define nlm_write_c2_cc2(s, v) __write_32bit_c2_register($18, s, v)
164#define nlm_write_c2_cc3(s, v) __write_32bit_c2_register($19, s, v)
165#define nlm_write_c2_cc4(s, v) __write_32bit_c2_register($20, s, v)
166#define nlm_write_c2_cc5(s, v) __write_32bit_c2_register($21, s, v)
167#define nlm_write_c2_cc6(s, v) __write_32bit_c2_register($22, s, v)
168#define nlm_write_c2_cc7(s, v) __write_32bit_c2_register($23, s, v)
169#define nlm_write_c2_cc8(s, v) __write_32bit_c2_register($24, s, v)
170#define nlm_write_c2_cc9(s, v) __write_32bit_c2_register($25, s, v)
171#define nlm_write_c2_cc10(s, v) __write_32bit_c2_register($26, s, v)
172#define nlm_write_c2_cc11(s, v) __write_32bit_c2_register($27, s, v)
173#define nlm_write_c2_cc12(s, v) __write_32bit_c2_register($28, s, v)
174#define nlm_write_c2_cc13(s, v) __write_32bit_c2_register($29, s, v)
175#define nlm_write_c2_cc14(s, v) __write_32bit_c2_register($30, s, v)
176#define nlm_write_c2_cc15(s, v) __write_32bit_c2_register($31, s, v)
177
178#define nlm_read_c2_status(sel) __read_32bit_c2_register($2, 0)
179#define nlm_read_c2_config() __read_32bit_c2_register($3, 0)
180#define nlm_write_c2_config(v) __write_32bit_c2_register($3, 0, v)
181#define nlm_read_c2_bucksize(b) __read_32bit_c2_register($4, b)
182#define nlm_write_c2_bucksize(b, v) __write_32bit_c2_register($4, b, v)
183
184#define nlm_read_c2_rx_msg0() __read_64bit_c2_register($1, 0)
185#define nlm_read_c2_rx_msg1() __read_64bit_c2_register($1, 1)
186#define nlm_read_c2_rx_msg2() __read_64bit_c2_register($1, 2)
187#define nlm_read_c2_rx_msg3() __read_64bit_c2_register($1, 3)
188
189#define nlm_write_c2_tx_msg0(v) __write_64bit_c2_register($0, 0, v)
190#define nlm_write_c2_tx_msg1(v) __write_64bit_c2_register($0, 1, v)
191#define nlm_write_c2_tx_msg2(v) __write_64bit_c2_register($0, 2, v)
192#define nlm_write_c2_tx_msg3(v) __write_64bit_c2_register($0, 3, v)
193
194#define FMN_STN_RX_QSIZE 256
195#define FMN_NSTATIONS 128
196#define FMN_CORE_NBUCKETS 8
197
198static inline void nlm_msgsnd(unsigned int stid)
199{
200 __asm__ volatile (
201 ".set push\n"
202 ".set noreorder\n"
203 ".set noat\n"
204 "move $1, %0\n"
205 "c2 0x10001\n" /* msgsnd $1 */
206 ".set pop\n"
207 : : "r" (stid) : "$1"
208 );
209}
210
211static inline void nlm_msgld(unsigned int pri)
212{
213 __asm__ volatile (
214 ".set push\n"
215 ".set noreorder\n"
216 ".set noat\n"
217 "move $1, %0\n"
218 "c2 0x10002\n" /* msgld $1 */
219 ".set pop\n"
220 : : "r" (pri) : "$1"
221 );
222}
223
224static inline void nlm_msgwait(unsigned int mask)
225{
226 __asm__ volatile (
227 ".set push\n"
228 ".set noreorder\n"
229 ".set noat\n"
230 "move $8, %0\n"
231 "c2 0x10003\n" /* msgwait $1 */
232 ".set pop\n"
233 : : "r" (mask) : "$1"
234 );
235}
236
237/*
238 * Disable interrupts and enable COP2 access
239 */
240static inline uint32_t nlm_cop2_enable(void)
241{
242 uint32_t sr = read_c0_status();
243
244 write_c0_status((sr & ~ST0_IE) | ST0_CU2);
245 return sr;
246}
247
248static inline void nlm_cop2_restore(uint32_t sr)
249{
250 write_c0_status(sr);
251}
252
253static inline void nlm_fmn_setup_intr(int irq, unsigned int tmask)
254{
255 uint32_t config;
256
257 config = (1 << 24) /* interrupt water mark - 1 msg */
258 | (irq << 16) /* irq */
259 | (tmask << 8) /* thread mask */
260 | 0x2; /* enable watermark intr, disable empty intr */
261 nlm_write_c2_config(config);
262}
263
264struct nlm_fmn_msg {
265 uint64_t msg0;
266 uint64_t msg1;
267 uint64_t msg2;
268 uint64_t msg3;
269};
270
271static inline int nlm_fmn_send(unsigned int size, unsigned int code,
272 unsigned int stid, struct nlm_fmn_msg *msg)
273{
274 unsigned int dest;
275 uint32_t status;
276 int i;
277
278 /*
279 * Make sure that all the writes pending at the cpu are flushed.
280 * Any writes pending on CPU will not be see by devices. L1/L2
281 * caches are coherent with IO, so no cache flush needed.
282 */
283 __asm __volatile("sync");
284
285 /* Load TX message buffers */
286 nlm_write_c2_tx_msg0(msg->msg0);
287 nlm_write_c2_tx_msg1(msg->msg1);
288 nlm_write_c2_tx_msg2(msg->msg2);
289 nlm_write_c2_tx_msg3(msg->msg3);
290 dest = ((size - 1) << 16) | (code << 8) | stid;
291
292 /*
293 * Retry a few times on credit fail, this should be a
294 * transient condition, unless there is a configuration
295 * failure, or the receiver is stuck.
296 */
297 for (i = 0; i < 8; i++) {
298 nlm_msgsnd(dest);
299 status = nlm_read_c2_status(0);
300 if ((status & 0x2) == 1)
301 pr_info("Send pending fail!\n");
302 if ((status & 0x4) == 0)
303 return 0;
304 }
305
306 /* If there is a credit failure, return error */
307 return status & 0x06;
308}
309
310static inline int nlm_fmn_receive(int bucket, int *size, int *code, int *stid,
311 struct nlm_fmn_msg *msg)
312{
313 uint32_t status, tmp;
314
315 nlm_msgld(bucket);
316
317 /* wait for load pending to clear */
318 do {
319 status = nlm_read_c2_status(1);
320 } while ((status & 0x08) != 0);
321
322 /* receive error bits */
323 tmp = status & 0x30;
324 if (tmp != 0)
325 return tmp;
326
327 *size = ((status & 0xc0) >> 6) + 1;
328 *code = (status & 0xff00) >> 8;
329 *stid = (status & 0x7f0000) >> 16;
330 msg->msg0 = nlm_read_c2_rx_msg0();
331 msg->msg1 = nlm_read_c2_rx_msg1();
332 msg->msg2 = nlm_read_c2_rx_msg2();
333 msg->msg3 = nlm_read_c2_rx_msg3();
334
335 return 0;
336}
337
338struct xlr_fmn_info {
339 int num_buckets;
340 int start_stn_id;
341 int end_stn_id;
342 int credit_config[128];
343};
344
345struct xlr_board_fmn_config {
346 int bucket_size[128]; /* size of buckets for all stations */
347 struct xlr_fmn_info cpu[8];
348 struct xlr_fmn_info gmac[2];
349 struct xlr_fmn_info dma;
350 struct xlr_fmn_info cmp;
351 struct xlr_fmn_info sae;
352 struct xlr_fmn_info xgmac[2];
353};
354
355extern int nlm_register_fmn_handler(int start, int end,
356 void (*fn)(int, int, int, int, struct nlm_fmn_msg *, void *),
357 void *arg);
358extern void xlr_percpu_fmn_init(void);
359extern void nlm_setup_fmn_irq(void);
360extern void xlr_board_info_setup(void);
361
362extern struct xlr_board_fmn_config xlr_board_fmn_config;
363#endif
diff --git a/arch/mips/include/asm/netlogic/xlr/xlr.h b/arch/mips/include/asm/netlogic/xlr/xlr.h
index ff4a17b0bf7..c1667e0c272 100644
--- a/arch/mips/include/asm/netlogic/xlr/xlr.h
+++ b/arch/mips/include/asm/netlogic/xlr/xlr.h
@@ -51,10 +51,8 @@ static inline unsigned int nlm_chip_is_xls_b(void)
51 return ((prid & 0xf000) == 0x4000); 51 return ((prid & 0xf000) == 0x4000);
52} 52}
53 53
54/* 54/* XLR chip types */
55 * XLR chip types 55/* The XLS product line has chip versions 0x[48c]? */
56 */
57 /* The XLS product line has chip versions 0x[48c]? */
58static inline unsigned int nlm_chip_is_xls(void) 56static inline unsigned int nlm_chip_is_xls(void)
59{ 57{
60 uint32_t prid = read_c0_prid(); 58 uint32_t prid = read_c0_prid();
diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c
index b89d5a6b62c..00dcc7a2bc5 100644
--- a/arch/mips/netlogic/common/irq.c
+++ b/arch/mips/netlogic/common/irq.c
@@ -58,6 +58,7 @@
58#elif defined(CONFIG_CPU_XLR) 58#elif defined(CONFIG_CPU_XLR)
59#include <asm/netlogic/xlr/iomap.h> 59#include <asm/netlogic/xlr/iomap.h>
60#include <asm/netlogic/xlr/pic.h> 60#include <asm/netlogic/xlr/pic.h>
61#include <asm/netlogic/xlr/fmn.h>
61#else 62#else
62#error "Unknown CPU" 63#error "Unknown CPU"
63#endif 64#endif
@@ -68,8 +69,8 @@
68#else 69#else
69#define SMP_IRQ_MASK 0 70#define SMP_IRQ_MASK 0
70#endif 71#endif
71#define PERCPU_IRQ_MASK (SMP_IRQ_MASK | (1ull << IRQ_TIMER)) 72#define PERCPU_IRQ_MASK (SMP_IRQ_MASK | (1ull << IRQ_TIMER) | \
72 73 (1ull << IRQ_FMN))
73 74
74struct nlm_pic_irq { 75struct nlm_pic_irq {
75 void (*extra_ack)(struct irq_data *); 76 void (*extra_ack)(struct irq_data *);
@@ -241,6 +242,9 @@ void __init arch_init_irq(void)
241 nlm_init_percpu_irqs(); 242 nlm_init_percpu_irqs();
242 nlm_init_node_irqs(0); 243 nlm_init_node_irqs(0);
243 write_c0_eimr(nlm_current_node()->irqmask); 244 write_c0_eimr(nlm_current_node()->irqmask);
245#if defined(CONFIG_CPU_XLR)
246 nlm_setup_fmn_irq();
247#endif
244} 248}
245 249
246void nlm_smp_irq_init(int hwcpuid) 250void nlm_smp_irq_init(int hwcpuid)
diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index 0315b298a64..a080d9ee3cd 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -118,6 +118,7 @@ static void __cpuinit nlm_init_secondary(void)
118 118
119 hwtid = hard_smp_processor_id(); 119 hwtid = hard_smp_processor_id();
120 current_cpu_data.core = hwtid / NLM_THREADS_PER_CORE; 120 current_cpu_data.core = hwtid / NLM_THREADS_PER_CORE;
121 nlm_percpu_init(hwtid);
121 nlm_smp_irq_init(hwtid); 122 nlm_smp_irq_init(hwtid);
122} 123}
123 124
@@ -129,9 +130,6 @@ void nlm_prepare_cpus(unsigned int max_cpus)
129 130
130void nlm_smp_finish(void) 131void nlm_smp_finish(void)
131{ 132{
132#ifdef notyet
133 nlm_common_msgring_cpu_init();
134#endif
135 local_irq_enable(); 133 local_irq_enable();
136} 134}
137 135
diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c
index 465b8d60463..4894d62043a 100644
--- a/arch/mips/netlogic/xlp/setup.c
+++ b/arch/mips/netlogic/xlp/setup.c
@@ -108,6 +108,10 @@ void xlp_mmu_init(void)
108 (13 + (ffz(PM_DEFAULT_MASK >> 13) / 2))); 108 (13 + (ffz(PM_DEFAULT_MASK >> 13) / 2)));
109} 109}
110 110
111void nlm_percpu_init(int hwcpuid)
112{
113}
114
111void __init prom_init(void) 115void __init prom_init(void)
112{ 116{
113 nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE); 117 nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE);
diff --git a/arch/mips/netlogic/xlr/Makefile b/arch/mips/netlogic/xlr/Makefile
index c287dea8757..05902bc6f08 100644
--- a/arch/mips/netlogic/xlr/Makefile
+++ b/arch/mips/netlogic/xlr/Makefile
@@ -1,2 +1,2 @@
1obj-y += setup.o platform.o platform-flash.o 1obj-y += fmn.o fmn-config.o setup.o platform.o platform-flash.o
2obj-$(CONFIG_SMP) += wakeup.o 2obj-$(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 00000000000..bed2cffa100
--- /dev/null
+++ b/arch/mips/netlogic/xlr/fmn-config.c
@@ -0,0 +1,290 @@
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/mipsregs.h>
40#include <asm/netlogic/xlr/fmn.h>
41#include <asm/netlogic/xlr/xlr.h>
42#include <asm/netlogic/common.h>
43#include <asm/netlogic/haldefs.h>
44
45struct xlr_board_fmn_config xlr_board_fmn_config;
46
47static void __maybe_unused print_credit_config(struct xlr_fmn_info *fmn_info)
48{
49 int bkt;
50
51 pr_info("Bucket size :\n");
52 pr_info("Station\t: Size\n");
53 for (bkt = 0; bkt < 16; bkt++)
54 pr_info(" %d %d %d %d %d %d %d %d\n",
55 xlr_board_fmn_config.bucket_size[(bkt * 8) + 0],
56 xlr_board_fmn_config.bucket_size[(bkt * 8) + 1],
57 xlr_board_fmn_config.bucket_size[(bkt * 8) + 2],
58 xlr_board_fmn_config.bucket_size[(bkt * 8) + 3],
59 xlr_board_fmn_config.bucket_size[(bkt * 8) + 4],
60 xlr_board_fmn_config.bucket_size[(bkt * 8) + 5],
61 xlr_board_fmn_config.bucket_size[(bkt * 8) + 6],
62 xlr_board_fmn_config.bucket_size[(bkt * 8) + 7]);
63 pr_info("\n");
64
65 pr_info("Credits distribution :\n");
66 pr_info("Station\t: Size\n");
67 for (bkt = 0; bkt < 16; bkt++)
68 pr_info(" %d %d %d %d %d %d %d %d\n",
69 fmn_info->credit_config[(bkt * 8) + 0],
70 fmn_info->credit_config[(bkt * 8) + 1],
71 fmn_info->credit_config[(bkt * 8) + 2],
72 fmn_info->credit_config[(bkt * 8) + 3],
73 fmn_info->credit_config[(bkt * 8) + 4],
74 fmn_info->credit_config[(bkt * 8) + 5],
75 fmn_info->credit_config[(bkt * 8) + 6],
76 fmn_info->credit_config[(bkt * 8) + 7]);
77 pr_info("\n");
78}
79
80static void check_credit_distribution(void)
81{
82 struct xlr_board_fmn_config *cfg = &xlr_board_fmn_config;
83 int bkt, n, total_credits, ncores;
84
85 ncores = hweight32(nlm_current_node()->coremask);
86 for (bkt = 0; bkt < 128; bkt++) {
87 total_credits = 0;
88 for (n = 0; n < ncores; n++)
89 total_credits += cfg->cpu[n].credit_config[bkt];
90 total_credits += cfg->gmac[0].credit_config[bkt];
91 total_credits += cfg->gmac[1].credit_config[bkt];
92 total_credits += cfg->dma.credit_config[bkt];
93 total_credits += cfg->cmp.credit_config[bkt];
94 total_credits += cfg->sae.credit_config[bkt];
95 total_credits += cfg->xgmac[0].credit_config[bkt];
96 total_credits += cfg->xgmac[1].credit_config[bkt];
97 if (total_credits > cfg->bucket_size[bkt])
98 pr_err("ERROR: Bucket %d: credits (%d) > size (%d)\n",
99 bkt, total_credits, cfg->bucket_size[bkt]);
100 }
101 pr_info("Credit distribution complete.\n");
102}
103
104/**
105 * Configure bucket size and credits for a device. 'size' is the size of
106 * the buckets for the device. This size is distributed among all the CPUs
107 * so that all of them can send messages to the device.
108 *
109 * The device is also given 'cpu_credits' to send messages to the CPUs
110 *
111 * @dev_info: FMN information structure for each devices
112 * @start_stn_id: Starting station id of dev_info
113 * @end_stn_id: End station id of dev_info
114 * @num_buckets: Total number of buckets for den_info
115 * @cpu_credits: Allowed credits to cpu for each devices pointing by dev_info
116 * @size: Size of the each buckets in the device station
117 */
118static void setup_fmn_cc(struct xlr_fmn_info *dev_info, int start_stn_id,
119 int end_stn_id, int num_buckets, int cpu_credits, int size)
120{
121 int i, j, num_core, n, credits_per_cpu;
122 struct xlr_fmn_info *cpu = xlr_board_fmn_config.cpu;
123
124 num_core = hweight32(nlm_current_node()->coremask);
125 dev_info->num_buckets = num_buckets;
126 dev_info->start_stn_id = start_stn_id;
127 dev_info->end_stn_id = end_stn_id;
128
129 n = num_core;
130 if (num_core == 3)
131 n = 4;
132
133 for (i = start_stn_id; i <= end_stn_id; i++) {
134 xlr_board_fmn_config.bucket_size[i] = size;
135
136 /* Dividing device credits equally to cpus */
137 credits_per_cpu = size / n;
138 for (j = 0; j < num_core; j++)
139 cpu[j].credit_config[i] = credits_per_cpu;
140
141 /* credits left to distribute */
142 credits_per_cpu = size - (credits_per_cpu * num_core);
143
144 /* distribute the remaining credits (if any), among cores */
145 for (j = 0; (j < num_core) && (credits_per_cpu >= 4); j++) {
146 cpu[j].credit_config[i] += 4;
147 credits_per_cpu -= 4;
148 }
149 }
150
151 /* Distributing cpu per bucket credits to devices */
152 for (i = 0; i < num_core; i++) {
153 for (j = 0; j < FMN_CORE_NBUCKETS; j++)
154 dev_info->credit_config[(i * 8) + j] = cpu_credits;
155 }
156}
157
158/*
159 * Each core has 256 slots and 8 buckets,
160 * Configure the 8 buckets each with 32 slots
161 */
162static void setup_cpu_fmninfo(struct xlr_fmn_info *cpu, int num_core)
163{
164 int i, j;
165
166 for (i = 0; i < num_core; i++) {
167 cpu[i].start_stn_id = (8 * i);
168 cpu[i].end_stn_id = (8 * i + 8);
169
170 for (j = cpu[i].start_stn_id; j < cpu[i].end_stn_id; j++)
171 xlr_board_fmn_config.bucket_size[j] = 32;
172 }
173}
174
175/**
176 * Setup the FMN details for each devices according to the device available
177 * in each variant of XLR/XLS processor
178 */
179void xlr_board_info_setup(void)
180{
181 struct xlr_fmn_info *cpu = xlr_board_fmn_config.cpu;
182 struct xlr_fmn_info *gmac = xlr_board_fmn_config.gmac;
183 struct xlr_fmn_info *xgmac = xlr_board_fmn_config.xgmac;
184 struct xlr_fmn_info *dma = &xlr_board_fmn_config.dma;
185 struct xlr_fmn_info *cmp = &xlr_board_fmn_config.cmp;
186 struct xlr_fmn_info *sae = &xlr_board_fmn_config.sae;
187 int processor_id, num_core;
188
189 num_core = hweight32(nlm_current_node()->coremask);
190 processor_id = read_c0_prid() & 0xff00;
191
192 setup_cpu_fmninfo(cpu, num_core);
193 switch (processor_id) {
194 case PRID_IMP_NETLOGIC_XLS104:
195 case PRID_IMP_NETLOGIC_XLS108:
196 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
197 FMN_STNID_GMAC0_TX3, 8, 16, 32);
198 setup_fmn_cc(dma, FMN_STNID_DMA_0,
199 FMN_STNID_DMA_3, 4, 8, 64);
200 setup_fmn_cc(sae, FMN_STNID_SEC0,
201 FMN_STNID_SEC1, 2, 8, 128);
202 break;
203
204 case PRID_IMP_NETLOGIC_XLS204:
205 case PRID_IMP_NETLOGIC_XLS208:
206 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
207 FMN_STNID_GMAC0_TX3, 8, 16, 32);
208 setup_fmn_cc(dma, FMN_STNID_DMA_0,
209 FMN_STNID_DMA_3, 4, 8, 64);
210 setup_fmn_cc(sae, FMN_STNID_SEC0,
211 FMN_STNID_SEC1, 2, 8, 128);
212 break;
213
214 case PRID_IMP_NETLOGIC_XLS404:
215 case PRID_IMP_NETLOGIC_XLS408:
216 case PRID_IMP_NETLOGIC_XLS404B:
217 case PRID_IMP_NETLOGIC_XLS408B:
218 case PRID_IMP_NETLOGIC_XLS416B:
219 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
220 FMN_STNID_GMAC0_TX3, 8, 8, 32);
221 setup_fmn_cc(&gmac[1], FMN_STNID_GMAC1_FR_0,
222 FMN_STNID_GMAC1_TX3, 8, 8, 32);
223 setup_fmn_cc(dma, FMN_STNID_DMA_0,
224 FMN_STNID_DMA_3, 4, 4, 64);
225 setup_fmn_cc(cmp, FMN_STNID_CMP_0,
226 FMN_STNID_CMP_3, 4, 4, 64);
227 setup_fmn_cc(sae, FMN_STNID_SEC0,
228 FMN_STNID_SEC1, 2, 8, 128);
229 break;
230
231 case PRID_IMP_NETLOGIC_XLS412B:
232 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
233 FMN_STNID_GMAC0_TX3, 8, 8, 32);
234 setup_fmn_cc(&gmac[1], FMN_STNID_GMAC1_FR_0,
235 FMN_STNID_GMAC1_TX3, 8, 8, 32);
236 setup_fmn_cc(dma, FMN_STNID_DMA_0,
237 FMN_STNID_DMA_3, 4, 4, 64);
238 setup_fmn_cc(cmp, FMN_STNID_CMP_0,
239 FMN_STNID_CMP_3, 4, 4, 64);
240 setup_fmn_cc(sae, FMN_STNID_SEC0,
241 FMN_STNID_SEC1, 2, 8, 128);
242 break;
243
244 case PRID_IMP_NETLOGIC_XLR308:
245 case PRID_IMP_NETLOGIC_XLR308C:
246 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
247 FMN_STNID_GMAC0_TX3, 8, 16, 32);
248 setup_fmn_cc(dma, FMN_STNID_DMA_0,
249 FMN_STNID_DMA_3, 4, 8, 64);
250 setup_fmn_cc(sae, FMN_STNID_SEC0,
251 FMN_STNID_SEC1, 2, 4, 128);
252 break;
253
254 case PRID_IMP_NETLOGIC_XLR532:
255 case PRID_IMP_NETLOGIC_XLR532C:
256 case PRID_IMP_NETLOGIC_XLR516C:
257 case PRID_IMP_NETLOGIC_XLR508C:
258 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
259 FMN_STNID_GMAC0_TX3, 8, 16, 32);
260 setup_fmn_cc(dma, FMN_STNID_DMA_0,
261 FMN_STNID_DMA_3, 4, 8, 64);
262 setup_fmn_cc(sae, FMN_STNID_SEC0,
263 FMN_STNID_SEC1, 2, 4, 128);
264 break;
265
266 case PRID_IMP_NETLOGIC_XLR732:
267 case PRID_IMP_NETLOGIC_XLR716:
268 setup_fmn_cc(&xgmac[0], FMN_STNID_XMAC0_00_TX,
269 FMN_STNID_XMAC0_15_TX, 8, 0, 32);
270 setup_fmn_cc(&xgmac[1], FMN_STNID_XMAC1_00_TX,
271 FMN_STNID_XMAC1_15_TX, 8, 0, 32);
272 setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
273 FMN_STNID_GMAC0_TX3, 8, 24, 32);
274 setup_fmn_cc(dma, FMN_STNID_DMA_0,
275 FMN_STNID_DMA_3, 4, 4, 64);
276 setup_fmn_cc(sae, FMN_STNID_SEC0,
277 FMN_STNID_SEC1, 2, 4, 128);
278 break;
279 default:
280 pr_err("Unknown CPU with processor ID [%d]\n", processor_id);
281 pr_err("Error: Cannot initialize FMN credits.\n");
282 }
283
284 check_credit_distribution();
285
286#if 0 /* debug */
287 print_credit_config(&cpu[0]);
288 print_credit_config(&gmac[0]);
289#endif
290}
diff --git a/arch/mips/netlogic/xlr/fmn.c b/arch/mips/netlogic/xlr/fmn.c
new file mode 100644
index 00000000000..4d74f03de50
--- /dev/null
+++ b/arch/mips/netlogic/xlr/fmn.c
@@ -0,0 +1,204 @@
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();
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_status() >> 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_restore(mflags);
101 hndlr->action(bucket, src_stnid, size, code,
102 &msg, hndlr->arg);
103 mflags = nlm_cop2_enable();
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_restore(mflags);
110 return IRQ_HANDLED;
111}
112
113struct irqaction fmn_irqaction = {
114 .handler = fmn_message_handler,
115 .flags = IRQF_PERCPU,
116 .name = "fmn",
117};
118
119void xlr_percpu_fmn_init(void)
120{
121 struct xlr_fmn_info *cpu_fmn_info;
122 int *bucket_sizes;
123 uint32_t flags;
124 int id;
125
126 BUG_ON(nlm_thread_id() != 0);
127 id = nlm_core_id();
128
129 bucket_sizes = xlr_board_fmn_config.bucket_size;
130 cpu_fmn_info = &xlr_board_fmn_config.cpu[id];
131 flags = nlm_cop2_enable();
132
133 /* Setup bucket sizes for the core. */
134 nlm_write_c2_bucksize(0, bucket_sizes[id * 8 + 0]);
135 nlm_write_c2_bucksize(1, bucket_sizes[id * 8 + 1]);
136 nlm_write_c2_bucksize(2, bucket_sizes[id * 8 + 2]);
137 nlm_write_c2_bucksize(3, bucket_sizes[id * 8 + 3]);
138 nlm_write_c2_bucksize(4, bucket_sizes[id * 8 + 4]);
139 nlm_write_c2_bucksize(5, bucket_sizes[id * 8 + 5]);
140 nlm_write_c2_bucksize(6, bucket_sizes[id * 8 + 6]);
141 nlm_write_c2_bucksize(7, bucket_sizes[id * 8 + 7]);
142
143 /*
144 * For sending FMN messages, we need credits on the destination
145 * bucket. Program the credits this core has on the 128 possible
146 * destination buckets.
147 * We cannot use a loop here, because the the first argument has
148 * to be a constant integer value.
149 */
150 COP2_CC_INIT_CPU_DEST(0, cpu_fmn_info->credit_config);
151 COP2_CC_INIT_CPU_DEST(1, cpu_fmn_info->credit_config);
152 COP2_CC_INIT_CPU_DEST(2, cpu_fmn_info->credit_config);
153 COP2_CC_INIT_CPU_DEST(3, cpu_fmn_info->credit_config);
154 COP2_CC_INIT_CPU_DEST(4, cpu_fmn_info->credit_config);
155 COP2_CC_INIT_CPU_DEST(5, cpu_fmn_info->credit_config);
156 COP2_CC_INIT_CPU_DEST(6, cpu_fmn_info->credit_config);
157 COP2_CC_INIT_CPU_DEST(7, cpu_fmn_info->credit_config);
158 COP2_CC_INIT_CPU_DEST(8, cpu_fmn_info->credit_config);
159 COP2_CC_INIT_CPU_DEST(9, cpu_fmn_info->credit_config);
160 COP2_CC_INIT_CPU_DEST(10, cpu_fmn_info->credit_config);
161 COP2_CC_INIT_CPU_DEST(11, cpu_fmn_info->credit_config);
162 COP2_CC_INIT_CPU_DEST(12, cpu_fmn_info->credit_config);
163 COP2_CC_INIT_CPU_DEST(13, cpu_fmn_info->credit_config);
164 COP2_CC_INIT_CPU_DEST(14, cpu_fmn_info->credit_config);
165 COP2_CC_INIT_CPU_DEST(15, cpu_fmn_info->credit_config);
166
167 /* enable FMN interrupts on this CPU */
168 nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1);
169 nlm_cop2_restore(flags);
170}
171
172
173/*
174 * Register a FMN message handler with respect to the source station id
175 * @stnid: source station id
176 * @action: Handler function pointer
177 */
178int nlm_register_fmn_handler(int start_stnid, int end_stnid,
179 void (*action)(int, int, int, int, struct nlm_fmn_msg *, void *),
180 void *arg)
181{
182 int sstnid;
183
184 for (sstnid = start_stnid; sstnid <= end_stnid; sstnid++) {
185 msg_handlers[sstnid].arg = arg;
186 smp_wmb();
187 msg_handlers[sstnid].action = action;
188 }
189 pr_debug("Registered FMN msg handler for stnid %d-%d\n",
190 start_stnid, end_stnid);
191 return 0;
192}
193
194void nlm_setup_fmn_irq(void)
195{
196 uint32_t flags;
197
198 /* setup irq only once */
199 setup_irq(IRQ_FMN, &fmn_irqaction);
200
201 flags = nlm_cop2_enable();
202 nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1);
203 nlm_cop2_restore(flags);
204}
diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c
index 696d4248b92..4e7f49d3d5a 100644
--- a/arch/mips/netlogic/xlr/setup.c
+++ b/arch/mips/netlogic/xlr/setup.c
@@ -49,6 +49,7 @@
49#include <asm/netlogic/xlr/iomap.h> 49#include <asm/netlogic/xlr/iomap.h>
50#include <asm/netlogic/xlr/pic.h> 50#include <asm/netlogic/xlr/pic.h>
51#include <asm/netlogic/xlr/gpio.h> 51#include <asm/netlogic/xlr/gpio.h>
52#include <asm/netlogic/xlr/fmn.h>
52 53
53uint64_t nlm_io_base = DEFAULT_NETLOGIC_IO_BASE; 54uint64_t nlm_io_base = DEFAULT_NETLOGIC_IO_BASE;
54struct psb_info nlm_prom_info; 55struct psb_info nlm_prom_info;
@@ -111,6 +112,12 @@ void __init prom_free_prom_memory(void)
111 /* Nothing yet */ 112 /* Nothing yet */
112} 113}
113 114
115void nlm_percpu_init(int hwcpuid)
116{
117 if (hwcpuid % 4 == 0)
118 xlr_percpu_fmn_init();
119}
120
114static void __init build_arcs_cmdline(int *argv) 121static void __init build_arcs_cmdline(int *argv)
115{ 122{
116 int i, remain, len; 123 int i, remain, len;
@@ -208,4 +215,6 @@ void __init prom_init(void)
208 nlm_wakeup_secondary_cpus(); 215 nlm_wakeup_secondary_cpus();
209 register_smp_ops(&nlm_smp_ops); 216 register_smp_ops(&nlm_smp_ops);
210#endif 217#endif
218 xlr_board_info_setup();
219 xlr_percpu_fmn_init();
211} 220}