• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/mips/bcm63xx/boards/
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>
21#include <bcm63xx_dev_uart.h>
22#include <bcm63xx_regs.h>
23#include <bcm63xx_io.h>
24#include <bcm63xx_dev_pci.h>
25#include <bcm63xx_dev_enet.h>
26#include <bcm63xx_dev_dsp.h>
27#include <bcm63xx_dev_pcmcia.h>
28#include <board_bcm963xx.h>
29
30#define PFX	"board_bcm963xx: "
31
32static struct bcm963xx_nvram nvram;
33static unsigned int mac_addr_used;
34static struct board_info board;
35
36/*
37 * known 6338 boards
38 */
39#ifdef CONFIG_BCM63XX_CPU_6338
40static struct board_info __initdata board_96338gw = {
41	.name				= "96338GW",
42	.expected_cpu_id		= 0x6338,
43
44	.has_uart0			= 1,
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
83static struct board_info __initdata board_96338w = {
84	.name				= "96338W",
85	.expected_cpu_id		= 0x6338,
86
87	.has_uart0			= 1,
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
129static struct board_info __initdata board_96345gw2 = {
130	.name				= "96345GW2",
131	.expected_cpu_id		= 0x6345,
132
133	.has_uart0			= 1,
134};
135#endif
136
137/*
138 * known 6348 boards
139 */
140#ifdef CONFIG_BCM63XX_CPU_6348
141static struct board_info __initdata board_96348r = {
142	.name				= "96348R",
143	.expected_cpu_id		= 0x6348,
144
145	.has_uart0			= 1,
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
185static struct board_info __initdata board_96348gw_10 = {
186	.name				= "96348GW-10",
187	.expected_cpu_id		= 0x6348,
188
189	.has_uart0			= 1,
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
245static struct board_info __initdata board_96348gw_11 = {
246	.name				= "96348GW-11",
247	.expected_cpu_id		= 0x6348,
248
249	.has_uart0			= 1,
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
299static struct board_info __initdata board_96348gw = {
300	.name				= "96348GW",
301	.expected_cpu_id		= 0x6348,
302
303	.has_uart0			= 1,
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
357static struct board_info __initdata board_FAST2404 = {
358	.name				= "F@ST2404",
359	.expected_cpu_id		= 0x6348,
360
361	.has_uart0			= 1,
362        .has_enet0			= 1,
363        .has_enet1			= 1,
364        .has_pci			= 1,
365
366	.enet0 = {
367		.has_phy		= 1,
368		.use_internal_phy	= 1,
369	},
370
371	.enet1 = {
372		.force_speed_100	= 1,
373		.force_duplex_full	= 1,
374	},
375
376	.has_ohci0			= 1,
377	.has_pccard			= 1,
378	.has_ehci0			= 1,
379};
380
381static 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
400static struct board_info __initdata board_DV201AMR = {
401	.name				= "DV201AMR",
402	.expected_cpu_id		= 0x6348,
403
404	.has_uart0			= 1,
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
420static struct board_info __initdata board_96348gw_a = {
421	.name				= "96348GW-A",
422	.expected_cpu_id		= 0x6348,
423
424	.has_uart0			= 1,
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
446static struct board_info __initdata board_96358vw = {
447	.name				= "96358VW",
448	.expected_cpu_id		= 0x6358,
449
450	.has_uart0			= 1,
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
498static struct board_info __initdata board_96358vw2 = {
499	.name				= "96358VW2",
500	.expected_cpu_id		= 0x6358,
501
502	.has_uart0			= 1,
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
546static struct board_info __initdata board_AGPFS0 = {
547	.name                           = "AGPF-S0",
548	.expected_cpu_id                = 0x6358,
549
550	.has_uart0			= 1,
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};
568
569static 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};
589#endif
590
591/*
592 * all boards
593 */
594static 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,
610	&board_rta1025w_16,
611#endif
612
613#ifdef CONFIG_BCM63XX_CPU_6358
614	&board_96358vw,
615	&board_96358vw2,
616	&board_AGPFS0,
617	&board_DWVS0,
618#endif
619};
620
621/*
622 * Register a sane SPROMv2 to make the on-board
623 * bcm4318 WLAN work
624 */
625#ifdef CONFIG_SSB_PCIHOST
626static 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 */
651const char *board_get_name(void)
652{
653	return board.name;
654}
655
656/*
657 * register & return a new board mac address
658 */
659static 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
691/*
692 * early init callback, read nvram data from flash and checksum it
693 */
694void __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);
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
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 */
806void __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
817static struct mtd_partition mtd_partitions[] = {
818	{
819		.name		= "cfe",
820		.offset		= 0x0,
821		.size		= 0x40000,
822	}
823};
824
825static struct physmap_flash_data flash_data = {
826	.width			= 2,
827	.nr_parts		= ARRAY_SIZE(mtd_partitions),
828	.parts			= mtd_partitions,
829};
830
831static struct resource mtd_resources[] = {
832	{
833		.start		= 0,	/* filled at runtime */
834		.end		= 0,	/* filled at runtime */
835		.flags		= IORESOURCE_MEM,
836	}
837};
838
839static 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
848static struct gpio_led_platform_data bcm63xx_led_data;
849
850static 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 */
859int __init board_register_devices(void)
860{
861	u32 val;
862
863	if (board.has_uart0)
864		bcm63xx_uart_register(0);
865
866	if (board.has_uart1)
867		bcm63xx_uart_register(1);
868
869	if (board.has_pccard)
870		bcm63xx_pcmcia_register();
871
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
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}
902