Commit | Line | Data |
---|---|---|
e7300d04 MB |
1 | /* |
2 | * This file is subject to the terms and conditions of the GNU General Public | |
3 | * License. See the file "COPYING" in the main directory of this archive | |
4 | * for more details. | |
5 | * | |
6 | * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> | |
7 | * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org> | |
8 | */ | |
9 | ||
10 | #include <linux/init.h> | |
11 | #include <linux/kernel.h> | |
12 | #include <linux/string.h> | |
13 | #include <linux/platform_device.h> | |
14 | #include <linux/mtd/mtd.h> | |
15 | #include <linux/mtd/partitions.h> | |
16 | #include <linux/mtd/physmap.h> | |
17 | #include <linux/ssb/ssb.h> | |
18 | #include <asm/addrspace.h> | |
19 | #include <bcm63xx_board.h> | |
20 | #include <bcm63xx_cpu.h> | |
524ef29c | 21 | #include <bcm63xx_dev_uart.h> |
e7300d04 MB |
22 | #include <bcm63xx_regs.h> |
23 | #include <bcm63xx_io.h> | |
e7300d04 MB |
24 | #include <bcm63xx_dev_pci.h> |
25 | #include <bcm63xx_dev_enet.h> | |
26 | #include <bcm63xx_dev_dsp.h> | |
553d6d5f | 27 | #include <bcm63xx_dev_pcmcia.h> |
e7300d04 MB |
28 | #include <board_bcm963xx.h> |
29 | ||
30 | #define PFX "board_bcm963xx: " | |
31 | ||
32 | static struct bcm963xx_nvram nvram; | |
33 | static unsigned int mac_addr_used; | |
34 | static struct board_info board; | |
35 | ||
36 | /* | |
37 | * known 6338 boards | |
38 | */ | |
39 | #ifdef CONFIG_BCM63XX_CPU_6338 | |
40 | static struct board_info __initdata board_96338gw = { | |
41 | .name = "96338GW", | |
42 | .expected_cpu_id = 0x6338, | |
43 | ||
524ef29c | 44 | .has_uart0 = 1, |
e7300d04 MB |
45 | .has_enet0 = 1, |
46 | .enet0 = { | |
47 | .force_speed_100 = 1, | |
48 | .force_duplex_full = 1, | |
49 | }, | |
50 | ||
51 | .has_ohci0 = 1, | |
52 | ||
53 | .leds = { | |
54 | { | |
55 | .name = "adsl", | |
56 | .gpio = 3, | |
57 | .active_low = 1, | |
58 | }, | |
59 | { | |
60 | .name = "ses", | |
61 | .gpio = 5, | |
62 | .active_low = 1, | |
63 | }, | |
64 | { | |
65 | .name = "ppp-fail", | |
66 | .gpio = 4, | |
67 | .active_low = 1, | |
68 | }, | |
69 | { | |
70 | .name = "power", | |
71 | .gpio = 0, | |
72 | .active_low = 1, | |
73 | .default_trigger = "default-on", | |
74 | }, | |
75 | { | |
76 | .name = "stop", | |
77 | .gpio = 1, | |
78 | .active_low = 1, | |
79 | } | |
80 | }, | |
81 | }; | |
82 | ||
83 | static struct board_info __initdata board_96338w = { | |
84 | .name = "96338W", | |
85 | .expected_cpu_id = 0x6338, | |
86 | ||
524ef29c | 87 | .has_uart0 = 1, |
e7300d04 MB |
88 | .has_enet0 = 1, |
89 | .enet0 = { | |
90 | .force_speed_100 = 1, | |
91 | .force_duplex_full = 1, | |
92 | }, | |
93 | ||
94 | .leds = { | |
95 | { | |
96 | .name = "adsl", | |
97 | .gpio = 3, | |
98 | .active_low = 1, | |
99 | }, | |
100 | { | |
101 | .name = "ses", | |
102 | .gpio = 5, | |
103 | .active_low = 1, | |
104 | }, | |
105 | { | |
106 | .name = "ppp-fail", | |
107 | .gpio = 4, | |
108 | .active_low = 1, | |
109 | }, | |
110 | { | |
111 | .name = "power", | |
112 | .gpio = 0, | |
113 | .active_low = 1, | |
114 | .default_trigger = "default-on", | |
115 | }, | |
116 | { | |
117 | .name = "stop", | |
118 | .gpio = 1, | |
119 | .active_low = 1, | |
120 | }, | |
121 | }, | |
122 | }; | |
123 | #endif | |
124 | ||
125 | /* | |
126 | * known 6345 boards | |
127 | */ | |
128 | #ifdef CONFIG_BCM63XX_CPU_6345 | |
129 | static struct board_info __initdata board_96345gw2 = { | |
130 | .name = "96345GW2", | |
131 | .expected_cpu_id = 0x6345, | |
524ef29c MB |
132 | |
133 | .has_uart0 = 1, | |
e7300d04 MB |
134 | }; |
135 | #endif | |
136 | ||
137 | /* | |
138 | * known 6348 boards | |
139 | */ | |
140 | #ifdef CONFIG_BCM63XX_CPU_6348 | |
141 | static struct board_info __initdata board_96348r = { | |
142 | .name = "96348R", | |
143 | .expected_cpu_id = 0x6348, | |
144 | ||
524ef29c | 145 | .has_uart0 = 1, |
e7300d04 MB |
146 | .has_enet0 = 1, |
147 | .has_pci = 1, | |
148 | ||
149 | .enet0 = { | |
150 | .has_phy = 1, | |
151 | .use_internal_phy = 1, | |
152 | }, | |
153 | ||
154 | .leds = { | |
155 | { | |
156 | .name = "adsl-fail", | |
157 | .gpio = 2, | |
158 | .active_low = 1, | |
159 | }, | |
160 | { | |
161 | .name = "ppp", | |
162 | .gpio = 3, | |
163 | .active_low = 1, | |
164 | }, | |
165 | { | |
166 | .name = "ppp-fail", | |
167 | .gpio = 4, | |
168 | .active_low = 1, | |
169 | }, | |
170 | { | |
171 | .name = "power", | |
172 | .gpio = 0, | |
173 | .active_low = 1, | |
174 | .default_trigger = "default-on", | |
175 | ||
176 | }, | |
177 | { | |
178 | .name = "stop", | |
179 | .gpio = 1, | |
180 | .active_low = 1, | |
181 | }, | |
182 | }, | |
183 | }; | |
184 | ||
185 | static struct board_info __initdata board_96348gw_10 = { | |
186 | .name = "96348GW-10", | |
187 | .expected_cpu_id = 0x6348, | |
188 | ||
524ef29c | 189 | .has_uart0 = 1, |
e7300d04 MB |
190 | .has_enet0 = 1, |
191 | .has_enet1 = 1, | |
192 | .has_pci = 1, | |
193 | ||
194 | .enet0 = { | |
195 | .has_phy = 1, | |
196 | .use_internal_phy = 1, | |
197 | }, | |
198 | .enet1 = { | |
199 | .force_speed_100 = 1, | |
200 | .force_duplex_full = 1, | |
201 | }, | |
202 | ||
203 | .has_ohci0 = 1, | |
204 | .has_pccard = 1, | |
205 | .has_ehci0 = 1, | |
206 | ||
207 | .has_dsp = 1, | |
208 | .dsp = { | |
209 | .gpio_rst = 6, | |
210 | .gpio_int = 34, | |
211 | .cs = 2, | |
212 | .ext_irq = 2, | |
213 | }, | |
214 | ||
215 | .leds = { | |
216 | { | |
217 | .name = "adsl-fail", | |
218 | .gpio = 2, | |
219 | .active_low = 1, | |
220 | }, | |
221 | { | |
222 | .name = "ppp", | |
223 | .gpio = 3, | |
224 | .active_low = 1, | |
225 | }, | |
226 | { | |
227 | .name = "ppp-fail", | |
228 | .gpio = 4, | |
229 | .active_low = 1, | |
230 | }, | |
231 | { | |
232 | .name = "power", | |
233 | .gpio = 0, | |
234 | .active_low = 1, | |
235 | .default_trigger = "default-on", | |
236 | }, | |
237 | { | |
238 | .name = "stop", | |
239 | .gpio = 1, | |
240 | .active_low = 1, | |
241 | }, | |
242 | }, | |
243 | }; | |
244 | ||
245 | static struct board_info __initdata board_96348gw_11 = { | |
246 | .name = "96348GW-11", | |
247 | .expected_cpu_id = 0x6348, | |
248 | ||
524ef29c | 249 | .has_uart0 = 1, |
e7300d04 MB |
250 | .has_enet0 = 1, |
251 | .has_enet1 = 1, | |
252 | .has_pci = 1, | |
253 | ||
254 | .enet0 = { | |
255 | .has_phy = 1, | |
256 | .use_internal_phy = 1, | |
257 | }, | |
258 | ||
259 | .enet1 = { | |
260 | .force_speed_100 = 1, | |
261 | .force_duplex_full = 1, | |
262 | }, | |
263 | ||
264 | ||
265 | .has_ohci0 = 1, | |
266 | .has_pccard = 1, | |
267 | .has_ehci0 = 1, | |
268 | ||
269 | .leds = { | |
270 | { | |
271 | .name = "adsl-fail", | |
272 | .gpio = 2, | |
273 | .active_low = 1, | |
274 | }, | |
275 | { | |
276 | .name = "ppp", | |
277 | .gpio = 3, | |
278 | .active_low = 1, | |
279 | }, | |
280 | { | |
281 | .name = "ppp-fail", | |
282 | .gpio = 4, | |
283 | .active_low = 1, | |
284 | }, | |
285 | { | |
286 | .name = "power", | |
287 | .gpio = 0, | |
288 | .active_low = 1, | |
289 | .default_trigger = "default-on", | |
290 | }, | |
291 | { | |
292 | .name = "stop", | |
293 | .gpio = 1, | |
294 | .active_low = 1, | |
295 | }, | |
296 | }, | |
297 | }; | |
298 | ||
299 | static struct board_info __initdata board_96348gw = { | |
300 | .name = "96348GW", | |
301 | .expected_cpu_id = 0x6348, | |
302 | ||
524ef29c | 303 | .has_uart0 = 1, |
e7300d04 MB |
304 | .has_enet0 = 1, |
305 | .has_enet1 = 1, | |
306 | .has_pci = 1, | |
307 | ||
308 | .enet0 = { | |
309 | .has_phy = 1, | |
310 | .use_internal_phy = 1, | |
311 | }, | |
312 | .enet1 = { | |
313 | .force_speed_100 = 1, | |
314 | .force_duplex_full = 1, | |
315 | }, | |
316 | ||
317 | .has_ohci0 = 1, | |
318 | ||
319 | .has_dsp = 1, | |
320 | .dsp = { | |
321 | .gpio_rst = 6, | |
322 | .gpio_int = 34, | |
323 | .ext_irq = 2, | |
324 | .cs = 2, | |
325 | }, | |
326 | ||
327 | .leds = { | |
328 | { | |
329 | .name = "adsl-fail", | |
330 | .gpio = 2, | |
331 | .active_low = 1, | |
332 | }, | |
333 | { | |
334 | .name = "ppp", | |
335 | .gpio = 3, | |
336 | .active_low = 1, | |
337 | }, | |
338 | { | |
339 | .name = "ppp-fail", | |
340 | .gpio = 4, | |
341 | .active_low = 1, | |
342 | }, | |
343 | { | |
344 | .name = "power", | |
345 | .gpio = 0, | |
346 | .active_low = 1, | |
347 | .default_trigger = "default-on", | |
348 | }, | |
349 | { | |
350 | .name = "stop", | |
351 | .gpio = 1, | |
352 | .active_low = 1, | |
353 | }, | |
354 | }, | |
355 | }; | |
356 | ||
357 | static struct board_info __initdata board_FAST2404 = { | |
05c69468 FF |
358 | .name = "F@ST2404", |
359 | .expected_cpu_id = 0x6348, | |
e7300d04 | 360 | |
524ef29c MB |
361 | .has_uart0 = 1, |
362 | .has_enet0 = 1, | |
363 | .has_enet1 = 1, | |
364 | .has_pci = 1, | |
e7300d04 | 365 | |
05c69468 FF |
366 | .enet0 = { |
367 | .has_phy = 1, | |
368 | .use_internal_phy = 1, | |
369 | }, | |
e7300d04 | 370 | |
05c69468 FF |
371 | .enet1 = { |
372 | .force_speed_100 = 1, | |
373 | .force_duplex_full = 1, | |
374 | }, | |
e7300d04 | 375 | |
05c69468 FF |
376 | .has_ohci0 = 1, |
377 | .has_pccard = 1, | |
378 | .has_ehci0 = 1, | |
e7300d04 MB |
379 | }; |
380 | ||
2e6ad9a9 FF |
381 | static struct board_info __initdata board_rta1025w_16 = { |
382 | .name = "RTA1025W_16", | |
383 | .expected_cpu_id = 0x6348, | |
384 | ||
385 | .has_enet0 = 1, | |
386 | .has_enet1 = 1, | |
387 | .has_pci = 1, | |
388 | ||
389 | .enet0 = { | |
390 | .has_phy = 1, | |
391 | .use_internal_phy = 1, | |
392 | }, | |
393 | .enet1 = { | |
394 | .force_speed_100 = 1, | |
395 | .force_duplex_full = 1, | |
396 | }, | |
397 | }; | |
398 | ||
399 | ||
e7300d04 MB |
400 | static struct board_info __initdata board_DV201AMR = { |
401 | .name = "DV201AMR", | |
402 | .expected_cpu_id = 0x6348, | |
403 | ||
524ef29c | 404 | .has_uart0 = 1, |
e7300d04 MB |
405 | .has_pci = 1, |
406 | .has_ohci0 = 1, | |
407 | ||
408 | .has_enet0 = 1, | |
409 | .has_enet1 = 1, | |
410 | .enet0 = { | |
411 | .has_phy = 1, | |
412 | .use_internal_phy = 1, | |
413 | }, | |
414 | .enet1 = { | |
415 | .force_speed_100 = 1, | |
416 | .force_duplex_full = 1, | |
417 | }, | |
418 | }; | |
419 | ||
420 | static struct board_info __initdata board_96348gw_a = { | |
421 | .name = "96348GW-A", | |
422 | .expected_cpu_id = 0x6348, | |
423 | ||
524ef29c | 424 | .has_uart0 = 1, |
e7300d04 MB |
425 | .has_enet0 = 1, |
426 | .has_enet1 = 1, | |
427 | .has_pci = 1, | |
428 | ||
429 | .enet0 = { | |
430 | .has_phy = 1, | |
431 | .use_internal_phy = 1, | |
432 | }, | |
433 | .enet1 = { | |
434 | .force_speed_100 = 1, | |
435 | .force_duplex_full = 1, | |
436 | }, | |
437 | ||
438 | .has_ohci0 = 1, | |
439 | }; | |
440 | #endif | |
441 | ||
442 | /* | |
443 | * known 6358 boards | |
444 | */ | |
445 | #ifdef CONFIG_BCM63XX_CPU_6358 | |
446 | static struct board_info __initdata board_96358vw = { | |
447 | .name = "96358VW", | |
448 | .expected_cpu_id = 0x6358, | |
449 | ||
524ef29c | 450 | .has_uart0 = 1, |
e7300d04 MB |
451 | .has_enet0 = 1, |
452 | .has_enet1 = 1, | |
453 | .has_pci = 1, | |
454 | ||
455 | .enet0 = { | |
456 | .has_phy = 1, | |
457 | .use_internal_phy = 1, | |
458 | }, | |
459 | ||
460 | .enet1 = { | |
461 | .force_speed_100 = 1, | |
462 | .force_duplex_full = 1, | |
463 | }, | |
464 | ||
465 | ||
466 | .has_ohci0 = 1, | |
467 | .has_pccard = 1, | |
468 | .has_ehci0 = 1, | |
469 | ||
470 | .leds = { | |
471 | { | |
472 | .name = "adsl-fail", | |
473 | .gpio = 15, | |
474 | .active_low = 1, | |
475 | }, | |
476 | { | |
477 | .name = "ppp", | |
478 | .gpio = 22, | |
479 | .active_low = 1, | |
480 | }, | |
481 | { | |
482 | .name = "ppp-fail", | |
483 | .gpio = 23, | |
484 | .active_low = 1, | |
485 | }, | |
486 | { | |
487 | .name = "power", | |
488 | .gpio = 4, | |
489 | .default_trigger = "default-on", | |
490 | }, | |
491 | { | |
492 | .name = "stop", | |
493 | .gpio = 5, | |
494 | }, | |
495 | }, | |
496 | }; | |
497 | ||
498 | static struct board_info __initdata board_96358vw2 = { | |
499 | .name = "96358VW2", | |
500 | .expected_cpu_id = 0x6358, | |
501 | ||
524ef29c | 502 | .has_uart0 = 1, |
e7300d04 MB |
503 | .has_enet0 = 1, |
504 | .has_enet1 = 1, | |
505 | .has_pci = 1, | |
506 | ||
507 | .enet0 = { | |
508 | .has_phy = 1, | |
509 | .use_internal_phy = 1, | |
510 | }, | |
511 | ||
512 | .enet1 = { | |
513 | .force_speed_100 = 1, | |
514 | .force_duplex_full = 1, | |
515 | }, | |
516 | ||
517 | ||
518 | .has_ohci0 = 1, | |
519 | .has_pccard = 1, | |
520 | .has_ehci0 = 1, | |
521 | ||
522 | .leds = { | |
523 | { | |
524 | .name = "adsl", | |
525 | .gpio = 22, | |
526 | .active_low = 1, | |
527 | }, | |
528 | { | |
529 | .name = "ppp-fail", | |
530 | .gpio = 23, | |
531 | }, | |
532 | { | |
533 | .name = "power", | |
534 | .gpio = 5, | |
535 | .active_low = 1, | |
536 | .default_trigger = "default-on", | |
537 | }, | |
538 | { | |
539 | .name = "stop", | |
540 | .gpio = 4, | |
541 | .active_low = 1, | |
542 | }, | |
543 | }, | |
544 | }; | |
545 | ||
546 | static struct board_info __initdata board_AGPFS0 = { | |
547 | .name = "AGPF-S0", | |
548 | .expected_cpu_id = 0x6358, | |
549 | ||
524ef29c | 550 | .has_uart0 = 1, |
e7300d04 MB |
551 | .has_enet0 = 1, |
552 | .has_enet1 = 1, | |
553 | .has_pci = 1, | |
554 | ||
555 | .enet0 = { | |
556 | .has_phy = 1, | |
557 | .use_internal_phy = 1, | |
558 | }, | |
559 | ||
560 | .enet1 = { | |
561 | .force_speed_100 = 1, | |
562 | .force_duplex_full = 1, | |
563 | }, | |
564 | ||
565 | .has_ohci0 = 1, | |
566 | .has_ehci0 = 1, | |
567 | }; | |
f29b7cac FF |
568 | |
569 | static struct board_info __initdata board_DWVS0 = { | |
570 | .name = "DWV-S0", | |
571 | .expected_cpu_id = 0x6358, | |
572 | ||
573 | .has_enet0 = 1, | |
574 | .has_enet1 = 1, | |
575 | .has_pci = 1, | |
576 | ||
577 | .enet0 = { | |
578 | .has_phy = 1, | |
579 | .use_internal_phy = 1, | |
580 | }, | |
581 | ||
582 | .enet1 = { | |
583 | .force_speed_100 = 1, | |
584 | .force_duplex_full = 1, | |
585 | }, | |
586 | ||
587 | .has_ohci0 = 1, | |
588 | }; | |
e7300d04 MB |
589 | #endif |
590 | ||
591 | /* | |
592 | * all boards | |
593 | */ | |
594 | static const struct board_info __initdata *bcm963xx_boards[] = { | |
595 | #ifdef CONFIG_BCM63XX_CPU_6338 | |
596 | &board_96338gw, | |
597 | &board_96338w, | |
598 | #endif | |
599 | #ifdef CONFIG_BCM63XX_CPU_6345 | |
600 | &board_96345gw2, | |
601 | #endif | |
602 | #ifdef CONFIG_BCM63XX_CPU_6348 | |
603 | &board_96348r, | |
604 | &board_96348gw, | |
605 | &board_96348gw_10, | |
606 | &board_96348gw_11, | |
607 | &board_FAST2404, | |
608 | &board_DV201AMR, | |
609 | &board_96348gw_a, | |
2e6ad9a9 | 610 | &board_rta1025w_16, |
e7300d04 MB |
611 | #endif |
612 | ||
613 | #ifdef CONFIG_BCM63XX_CPU_6358 | |
614 | &board_96358vw, | |
615 | &board_96358vw2, | |
616 | &board_AGPFS0, | |
f29b7cac | 617 | &board_DWVS0, |
e7300d04 MB |
618 | #endif |
619 | }; | |
620 | ||
5e3644a9 FF |
621 | /* |
622 | * Register a sane SPROMv2 to make the on-board | |
623 | * bcm4318 WLAN work | |
624 | */ | |
625 | #ifdef CONFIG_SSB_PCIHOST | |
626 | static struct ssb_sprom bcm63xx_sprom = { | |
627 | .revision = 0x02, | |
628 | .board_rev = 0x17, | |
629 | .country_code = 0x0, | |
630 | .ant_available_bg = 0x3, | |
631 | .pa0b0 = 0x15ae, | |
632 | .pa0b1 = 0xfa85, | |
633 | .pa0b2 = 0xfe8d, | |
634 | .pa1b0 = 0xffff, | |
635 | .pa1b1 = 0xffff, | |
636 | .pa1b2 = 0xffff, | |
637 | .gpio0 = 0xff, | |
638 | .gpio1 = 0xff, | |
639 | .gpio2 = 0xff, | |
640 | .gpio3 = 0xff, | |
641 | .maxpwr_bg = 0x004c, | |
642 | .itssi_bg = 0x00, | |
643 | .boardflags_lo = 0x2848, | |
644 | .boardflags_hi = 0x0000, | |
645 | }; | |
646 | #endif | |
647 | ||
648 | /* | |
649 | * return board name for /proc/cpuinfo | |
650 | */ | |
651 | const char *board_get_name(void) | |
652 | { | |
653 | return board.name; | |
654 | } | |
655 | ||
656 | /* | |
657 | * register & return a new board mac address | |
658 | */ | |
659 | static int board_get_mac_address(u8 *mac) | |
660 | { | |
661 | u8 *p; | |
662 | int count; | |
663 | ||
664 | if (mac_addr_used >= nvram.mac_addr_count) { | |
665 | printk(KERN_ERR PFX "not enough mac address\n"); | |
666 | return -ENODEV; | |
667 | } | |
668 | ||
669 | memcpy(mac, nvram.mac_addr_base, ETH_ALEN); | |
670 | p = mac + ETH_ALEN - 1; | |
671 | count = mac_addr_used; | |
672 | ||
673 | while (count--) { | |
674 | do { | |
675 | (*p)++; | |
676 | if (*p != 0) | |
677 | break; | |
678 | p--; | |
679 | } while (p != mac); | |
680 | } | |
681 | ||
682 | if (p == mac) { | |
683 | printk(KERN_ERR PFX "unable to fetch mac address\n"); | |
684 | return -ENODEV; | |
685 | } | |
686 | ||
687 | mac_addr_used++; | |
688 | return 0; | |
689 | } | |
690 | ||
e7300d04 MB |
691 | /* |
692 | * early init callback, read nvram data from flash and checksum it | |
693 | */ | |
694 | void __init board_prom_init(void) | |
695 | { | |
696 | unsigned int check_len, i; | |
697 | u8 *boot_addr, *cfe, *p; | |
698 | char cfe_version[32]; | |
699 | u32 val; | |
700 | ||
701 | /* read base address of boot chip select (0) | |
702 | * 6345 does not have MPI but boots from standard | |
703 | * MIPS Flash address */ | |
704 | if (BCMCPU_IS_6345()) | |
705 | val = 0x1fc00000; | |
706 | else { | |
707 | val = bcm_mpi_readl(MPI_CSBASE_REG(0)); | |
708 | val &= MPI_CSBASE_BASE_MASK; | |
709 | } | |
710 | boot_addr = (u8 *)KSEG1ADDR(val); | |
711 | ||
712 | /* dump cfe version */ | |
713 | cfe = boot_addr + BCM963XX_CFE_VERSION_OFFSET; | |
714 | if (!memcmp(cfe, "cfe-v", 5)) | |
715 | snprintf(cfe_version, sizeof(cfe_version), "%u.%u.%u-%u.%u", | |
716 | cfe[5], cfe[6], cfe[7], cfe[8], cfe[9]); | |
717 | else | |
718 | strcpy(cfe_version, "unknown"); | |
719 | printk(KERN_INFO PFX "CFE version: %s\n", cfe_version); | |
720 | ||
721 | /* extract nvram data */ | |
722 | memcpy(&nvram, boot_addr + BCM963XX_NVRAM_OFFSET, sizeof(nvram)); | |
723 | ||
724 | /* check checksum before using data */ | |
725 | if (nvram.version <= 4) | |
726 | check_len = offsetof(struct bcm963xx_nvram, checksum_old); | |
727 | else | |
728 | check_len = sizeof(nvram); | |
729 | val = 0; | |
730 | p = (u8 *)&nvram; | |
731 | while (check_len--) | |
732 | val += *p; | |
733 | if (val) { | |
734 | printk(KERN_ERR PFX "invalid nvram checksum\n"); | |
735 | return; | |
736 | } | |
737 | ||
738 | /* find board by name */ | |
739 | for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) { | |
740 | if (strncmp(nvram.name, bcm963xx_boards[i]->name, | |
741 | sizeof(nvram.name))) | |
742 | continue; | |
743 | /* copy, board desc array is marked initdata */ | |
744 | memcpy(&board, bcm963xx_boards[i], sizeof(board)); | |
745 | break; | |
746 | } | |
747 | ||
748 | /* bail out if board is not found, will complain later */ | |
749 | if (!board.name[0]) { | |
750 | char name[17]; | |
751 | memcpy(name, nvram.name, 16); | |
752 | name[16] = 0; | |
753 | printk(KERN_ERR PFX "unknown bcm963xx board: %s\n", | |
754 | name); | |
755 | return; | |
756 | } | |
757 | ||
758 | /* setup pin multiplexing depending on board enabled device, | |
759 | * this has to be done this early since PCI init is done | |
760 | * inside arch_initcall */ | |
761 | val = 0; | |
762 | ||
763 | #ifdef CONFIG_PCI | |
764 | if (board.has_pci) { | |
765 | bcm63xx_pci_enabled = 1; | |
766 | if (BCMCPU_IS_6348()) | |
767 | val |= GPIO_MODE_6348_G2_PCI; | |
768 | } | |
769 | #endif | |
770 | ||
771 | if (board.has_pccard) { | |
772 | if (BCMCPU_IS_6348()) | |
773 | val |= GPIO_MODE_6348_G1_MII_PCCARD; | |
774 | } | |
775 | ||
776 | if (board.has_enet0 && !board.enet0.use_internal_phy) { | |
777 | if (BCMCPU_IS_6348()) | |
778 | val |= GPIO_MODE_6348_G3_EXT_MII | | |
779 | GPIO_MODE_6348_G0_EXT_MII; | |
780 | } | |
781 | ||
782 | if (board.has_enet1 && !board.enet1.use_internal_phy) { | |
783 | if (BCMCPU_IS_6348()) | |
784 | val |= GPIO_MODE_6348_G3_EXT_MII | | |
785 | GPIO_MODE_6348_G0_EXT_MII; | |
786 | } | |
787 | ||
788 | bcm_gpio_writel(val, GPIO_MODE_REG); | |
e23a90eb FF |
789 | |
790 | /* Generate MAC address for WLAN and | |
791 | * register our SPROM */ | |
792 | #ifdef CONFIG_SSB_PCIHOST | |
793 | if (!board_get_mac_address(bcm63xx_sprom.il0mac)) { | |
794 | memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN); | |
795 | memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN); | |
796 | if (ssb_arch_set_fallback_sprom(&bcm63xx_sprom) < 0) | |
797 | printk(KERN_ERR "failed to register fallback SPROM\n"); | |
798 | } | |
799 | #endif | |
e7300d04 MB |
800 | } |
801 | ||
802 | /* | |
803 | * second stage init callback, good time to panic if we couldn't | |
804 | * identify on which board we're running since early printk is working | |
805 | */ | |
806 | void __init board_setup(void) | |
807 | { | |
808 | if (!board.name[0]) | |
809 | panic("unable to detect bcm963xx board"); | |
810 | printk(KERN_INFO PFX "board name: %s\n", board.name); | |
811 | ||
812 | /* make sure we're running on expected cpu */ | |
813 | if (bcm63xx_get_cpu_id() != board.expected_cpu_id) | |
814 | panic("unexpected CPU for bcm963xx board"); | |
815 | } | |
816 | ||
e7300d04 MB |
817 | static struct mtd_partition mtd_partitions[] = { |
818 | { | |
819 | .name = "cfe", | |
820 | .offset = 0x0, | |
821 | .size = 0x40000, | |
822 | } | |
823 | }; | |
824 | ||
825 | static struct physmap_flash_data flash_data = { | |
826 | .width = 2, | |
827 | .nr_parts = ARRAY_SIZE(mtd_partitions), | |
828 | .parts = mtd_partitions, | |
829 | }; | |
830 | ||
831 | static struct resource mtd_resources[] = { | |
832 | { | |
833 | .start = 0, /* filled at runtime */ | |
834 | .end = 0, /* filled at runtime */ | |
835 | .flags = IORESOURCE_MEM, | |
836 | } | |
837 | }; | |
838 | ||
839 | static struct platform_device mtd_dev = { | |
840 | .name = "physmap-flash", | |
841 | .resource = mtd_resources, | |
842 | .num_resources = ARRAY_SIZE(mtd_resources), | |
843 | .dev = { | |
844 | .platform_data = &flash_data, | |
845 | }, | |
846 | }; | |
847 | ||
e7300d04 MB |
848 | static struct gpio_led_platform_data bcm63xx_led_data; |
849 | ||
850 | static struct platform_device bcm63xx_gpio_leds = { | |
851 | .name = "leds-gpio", | |
852 | .id = 0, | |
853 | .dev.platform_data = &bcm63xx_led_data, | |
854 | }; | |
855 | ||
856 | /* | |
857 | * third stage init callback, register all board devices. | |
858 | */ | |
859 | int __init board_register_devices(void) | |
860 | { | |
861 | u32 val; | |
862 | ||
524ef29c MB |
863 | if (board.has_uart0) |
864 | bcm63xx_uart_register(0); | |
865 | ||
866 | if (board.has_uart1) | |
867 | bcm63xx_uart_register(1); | |
868 | ||
553d6d5f MB |
869 | if (board.has_pccard) |
870 | bcm63xx_pcmcia_register(); | |
871 | ||
e7300d04 MB |
872 | if (board.has_enet0 && |
873 | !board_get_mac_address(board.enet0.mac_addr)) | |
874 | bcm63xx_enet_register(0, &board.enet0); | |
875 | ||
876 | if (board.has_enet1 && | |
877 | !board_get_mac_address(board.enet1.mac_addr)) | |
878 | bcm63xx_enet_register(1, &board.enet1); | |
879 | ||
880 | if (board.has_dsp) | |
881 | bcm63xx_dsp_register(&board.dsp); | |
882 | ||
e7300d04 MB |
883 | /* read base address of boot chip select (0) */ |
884 | if (BCMCPU_IS_6345()) | |
885 | val = 0x1fc00000; | |
886 | else { | |
887 | val = bcm_mpi_readl(MPI_CSBASE_REG(0)); | |
888 | val &= MPI_CSBASE_BASE_MASK; | |
889 | } | |
890 | mtd_resources[0].start = val; | |
891 | mtd_resources[0].end = 0x1FFFFFFF; | |
892 | ||
893 | platform_device_register(&mtd_dev); | |
894 | ||
895 | bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds); | |
896 | bcm63xx_led_data.leds = board.leds; | |
897 | ||
898 | platform_device_register(&bcm63xx_gpio_leds); | |
899 | ||
900 | return 0; | |
901 | } |