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