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