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