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
39static struct board_info board;
40
41/*
42 * known 3368 boards
43 */
44#ifdef CONFIG_BCM63XX_CPU_3368
45static 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
77static 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
125static 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
168static 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
214static 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
226static 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
270static 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
330static 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
384static 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
442static 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
466static 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
485static 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
505static 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
531static 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
583static 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
631static 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
654static 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 */
679static 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
717static 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
738int 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 */
753const 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 */
761void __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 */
853void __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
864static struct gpio_led_platform_data bcm63xx_led_data;
865
866static 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 */
875int __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