diff options
author | 2025-03-08 22:04:20 +0800 | |
---|---|---|
committer | 2025-03-08 22:04:20 +0800 | |
commit | a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch) | |
tree | 84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /arch/mips/netlogic/xlr | |
download | ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip |
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'arch/mips/netlogic/xlr')
-rw-r--r-- | arch/mips/netlogic/xlr/Makefile | 3 | ||||
-rw-r--r-- | arch/mips/netlogic/xlr/fmn-config.c | 293 | ||||
-rw-r--r-- | arch/mips/netlogic/xlr/fmn.c | 199 | ||||
-rw-r--r-- | arch/mips/netlogic/xlr/platform-flash.c | 216 | ||||
-rw-r--r-- | arch/mips/netlogic/xlr/platform.c | 250 | ||||
-rw-r--r-- | arch/mips/netlogic/xlr/setup.c | 211 | ||||
-rw-r--r-- | arch/mips/netlogic/xlr/wakeup.c | 85 |
7 files changed, 1257 insertions, 0 deletions
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 | ||
2 | obj-y += fmn.o fmn-config.o setup.o platform.o platform-flash.o | ||
3 | obj-$(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 | |||
46 | struct xlr_board_fmn_config xlr_board_fmn_config; | ||
47 | |||
48 | static 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 | |||
81 | static 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 | */ | ||
119 | static 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 | */ | ||
163 | static 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 | */ | ||
180 | void 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) \ | ||
46 | do { \ | ||
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 | |||
57 | struct 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 | */ | ||
69 | static 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 | |||
113 | void 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 | */ | ||
172 | int 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 | |||
188 | void 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 | */ | ||
34 | static 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 | */ | ||
45 | static 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 */ | ||
59 | struct physmap_flash_data xlr_nor_data = { | ||
60 | .width = 2, | ||
61 | .parts = xlr_nor_parts, | ||
62 | .nr_parts = ARRAY_SIZE(xlr_nor_parts), | ||
63 | }; | ||
64 | |||
65 | static struct resource xlr_nor_res[] = { | ||
66 | { | ||
67 | .flags = IORESOURCE_MEM, | ||
68 | }, | ||
69 | }; | ||
70 | |||
71 | static 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 | */ | ||
87 | struct xlr_nand_flash_priv { | ||
88 | int cs; | ||
89 | uint64_t flash_mmio; | ||
90 | }; | ||
91 | |||
92 | static struct xlr_nand_flash_priv nand_priv; | ||
93 | |||
94 | static 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 | |||
105 | struct 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 | |||
117 | static struct resource xlr_nand_res[] = { | ||
118 | { | ||
119 | .flags = IORESOURCE_MEM, | ||
120 | }, | ||
121 | }; | ||
122 | |||
123 | static 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 | */ | ||
142 | static 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 | |||
154 | static 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 | |||
216 | arch_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 | |||
26 | static 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 | |||
44 | static 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 | |||
73 | static struct plat_serial8250_port xlr_uart_data[] = { | ||
74 | PORT(PIC_UART_0_IRQ), | ||
75 | PORT(PIC_UART_1_IRQ), | ||
76 | {}, | ||
77 | }; | ||
78 | |||
79 | static struct platform_device uart_device = { | ||
80 | .name = "serial8250", | ||
81 | .id = PLAT8250_DEV_PLATFORM, | ||
82 | .dev = { | ||
83 | .platform_data = xlr_uart_data, | ||
84 | }, | ||
85 | }; | ||
86 | |||
87 | static 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 | |||
102 | arch_initcall(nlm_uart_init); | ||
103 | |||
104 | #ifdef CONFIG_USB | ||
105 | /* Platform USB devices, only on XLS chips */ | ||
106 | static 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 | |||
128 | static struct usb_ehci_pdata xls_usb_ehci_pdata = { | ||
129 | .caps_offset = 0, | ||
130 | }; | ||
131 | |||
132 | static struct usb_ohci_pdata xls_usb_ohci_pdata; | ||
133 | |||
134 | static struct platform_device xls_usb_ehci_device = | ||
135 | USB_PLATFORM_DEV("ehci-platform", 0, PIC_USB_IRQ); | ||
136 | static struct platform_device xls_usb_ohci_device_0 = | ||
137 | USB_PLATFORM_DEV("ohci-platform", 1, PIC_USB_IRQ); | ||
138 | static struct platform_device xls_usb_ohci_device_1 = | ||
139 | USB_PLATFORM_DEV("ohci-platform", 2, PIC_USB_IRQ); | ||
140 | |||
141 | static 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 | |||
147 | int 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 | |||
199 | arch_initcall(xls_platform_usb_init); | ||
200 | #endif | ||
201 | |||
202 | #ifdef CONFIG_I2C | ||
203 | static 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 | |||
215 | static struct resource i2c_resources[] = { | ||
216 | [0] = { | ||
217 | .start = 0, /* filled at init */ | ||
218 | .end = 0, | ||
219 | .flags = IORESOURCE_MEM, | ||
220 | }, | ||
221 | }; | ||
222 | |||
223 | static struct platform_device nlm_xlr_i2c_1 = { | ||
224 | .name = "xlr-i2cbus", | ||
225 | .id = 1, | ||
226 | .num_resources = 1, | ||
227 | .resource = i2c_resources, | ||
228 | }; | ||
229 | |||
230 | static 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 | |||
249 | arch_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 | |||
56 | uint64_t nlm_io_base = DEFAULT_NETLOGIC_IO_BASE; | ||
57 | struct psb_info nlm_prom_info; | ||
58 | |||
59 | /* default to uniprocessor */ | ||
60 | unsigned int nlm_threads_per_core = 1; | ||
61 | struct nlm_soc_info nlm_nodes[NLM_NR_NODES]; | ||
62 | cpumask_t nlm_cpumask = CPU_MASK_CPU0; | ||
63 | |||
64 | static 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 | |||
75 | void __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 | |||
82 | const char *get_system_type(void) | ||
83 | { | ||
84 | return "Netlogic XLR/XLS Series"; | ||
85 | } | ||
86 | |||
87 | unsigned int nlm_get_cpu_frequency(void) | ||
88 | { | ||
89 | return (unsigned int)nlm_prom_info.cpu_frequency; | ||
90 | } | ||
91 | |||
92 | void __init prom_free_prom_memory(void) | ||
93 | { | ||
94 | /* Nothing yet */ | ||
95 | } | ||
96 | |||
97 | void nlm_percpu_init(int hwcpuid) | ||
98 | { | ||
99 | if (hwcpuid % 4 == 0) | ||
100 | xlr_percpu_fmn_init(); | ||
101 | } | ||
102 | |||
103 | static 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; | ||
140 | fail: | ||
141 | panic("Cannot add %s, command line too big!", arg); | ||
142 | } | ||
143 | |||
144 | static 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 | |||
166 | static 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 | |||
176 | void __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 | |||
51 | int 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 | } | ||