[brcm63xx] fix the flash address comment and register the flash device again with...
[openwrt.git] / target / linux / brcm63xx / files / 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  */
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/mtd/mtd.h>
14 #include <linux/mtd/partitions.h>
15 #include <linux/mtd/physmap.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_regs.h>
21 #include <bcm63xx_io.h>
22 #include <bcm63xx_board.h>
23 #include <bcm63xx_dev_pci.h>
24 #include <bcm63xx_dev_uart.h>
25 #include <bcm63xx_dev_wdt.h>
26 #include <bcm63xx_dev_enet.h>
27 #include <bcm63xx_dev_pcmcia.h>
28 #include <bcm63xx_dev_usb_ohci.h>
29 #include <bcm63xx_dev_usb_ehci.h>
30 #include <bcm63xx_dev_usb_udc.h>
31 #include <bcm63xx_dev_spi.h>
32 #include <board_bcm963xx.h>
33
34 #define PFX     "board_bcm963xx: "
35
36 static struct bcm963xx_nvram nvram;
37 static unsigned int mac_addr_used = 0;
38 static struct board_info board;
39
40 /*
41  * known 6338 boards
42  */
43
44 #ifdef CONFIG_BCM63XX_CPU_6338
45 static struct board_info __initdata board_96338gw = {
46         .name                           = "96338GW",
47         .expected_cpu_id                = 0x6338,
48
49         .has_enet0                      = 1,
50         .enet0 = {
51                 .has_phy                = 1,
52                 .use_internal_phy       = 1,
53         },
54
55         .has_ohci0                      = 1,
56 };
57
58 static struct board_info __initdata board_96338w = {
59         .name                           = "96338W",
60         .expected_cpu_id                = 0x6338,
61
62         .has_enet0                      = 1,
63 };
64 #endif
65
66 /*
67  * known 6348 boards
68  */
69 #ifdef CONFIG_BCM63XX_CPU_6348
70 static struct board_info __initdata board_96348r = {
71         .name                           = "96348R",
72         .expected_cpu_id                = 0x6348,
73
74         .has_enet0                      = 1,
75         .has_pci                        = 1,
76
77         .enet0 = {
78                 .has_phy                = 1,
79                 .use_internal_phy       = 1,
80         },
81 };
82
83 static struct board_info __initdata board_96348gw_10 = { 
84         .name                           = "96348GW-10",
85         .expected_cpu_id                = 0x6348,
86         
87         .has_enet0                      = 1,
88         .has_enet1                      = 1,
89         .has_pci                        = 1, 
90         
91         .enet0 = {
92                 .has_phy                = 1,
93                 .use_internal_phy       = 1,
94         },
95         .enet1 = {
96                 .force_speed_100        = 1,
97                 .force_duplex_full      = 1,
98         },
99         
100         .has_ohci0                      = 1,
101         .has_pccard                     = 1,
102         .has_ehci0                      = 1,
103 }; 
104
105 static struct board_info __initdata board_96348gw_11 = {
106         .name                           = "96348GW-11",
107         .expected_cpu_id                = 0x6348,
108
109         .has_enet0                      = 1,
110         .has_enet1                      = 1,
111         .has_pci                        = 1,
112
113         .enet0 = {
114                 .has_phy                = 1,
115                 .use_internal_phy       = 1,
116         },
117
118         .enet1 = {
119                 .force_speed_100        = 1,
120                 .force_duplex_full      = 1,
121         },
122
123
124         .has_ohci0 = 1,
125         .has_pccard = 1,
126         .has_ehci0 = 1,
127 };
128
129 static struct board_info __initdata board_96348gw = {
130         .name                           = "96348GW",
131         .expected_cpu_id                = 0x6348,
132
133         .has_enet0                      = 1,
134         .has_enet1                      = 1,
135         .has_pci                        = 1,
136
137         .enet0 = {
138                 .has_phy                = 1,
139                 .use_internal_phy       = 1,
140         },
141         .enet1 = {
142                 .force_speed_100        = 1,
143                 .force_duplex_full      = 1,
144         },
145
146         .has_ohci0 = 1,
147 };
148
149 static struct board_info __initdata board_FAST2404 = {
150         .name                           = "F@ST2404",
151         .expected_cpu_id                = 0x6348,
152
153         .has_enet0                      = 1,
154         .has_enet1                      = 1,
155         .has_pci                        = 1,
156
157         .enet0 = {
158                 .has_phy                = 1,
159                 .use_internal_phy       = 1,
160         },
161
162         .enet1 = {
163                 .force_speed_100        = 1,
164                 .force_duplex_full      = 1,
165         },
166
167
168         .has_ohci0 = 1,
169         .has_pccard = 1,
170         .has_ehci0 = 1,
171 };
172
173 static struct board_info __initdata board_DV201AMR = {
174         .name                           = "DV201AMR",
175         .expected_cpu_id                = 0x6348,
176
177         .has_pci                        = 1,
178         .has_ohci0                      = 1,
179         .has_udc0                       = 1,
180
181         .has_enet0                      = 1,
182         .has_enet1                      = 1,
183         .enet0 = {
184                 .has_phy                = 1,
185                 .use_internal_phy       = 1,
186         },
187         .enet1 = {
188                 .force_speed_100        = 1,
189                 .force_duplex_full      = 1,
190         },
191 };
192
193 static struct board_info __initdata board_96348gw_a = {
194         .name                           = "96348GW-A",
195         .expected_cpu_id                = 0x6348,
196
197         .has_enet0                      = 1,
198         .has_enet1                      = 1,
199         .has_pci                        = 1,
200
201         .enet0 = {
202                 .has_phy                = 1,
203                 .use_internal_phy       = 1,
204         },
205         .enet1 = {
206                 .force_speed_100        = 1,
207                 .force_duplex_full      = 1,
208         },
209
210         .has_ohci0 = 1,
211 };
212
213
214 #endif
215
216 /*
217  * known 6358 boards
218  */
219 #ifdef CONFIG_BCM63XX_CPU_6358
220 static struct board_info __initdata board_96358vw = {
221         .name                           = "96358VW",
222         .expected_cpu_id                = 0x6358,
223
224         .has_enet0                      = 1,
225         .has_enet1                      = 1,
226         .has_pci                        = 1,
227
228         .enet0 = {
229                 .has_phy                = 1,
230                 .use_internal_phy       = 1,
231         },
232
233         .enet1 = {
234                 .force_speed_100        = 1,
235                 .force_duplex_full      = 1,
236         },
237
238
239         .has_ohci0 = 1,
240         .has_pccard = 1,
241         .has_ehci0 = 1,
242 };
243
244 static struct board_info __initdata board_96358vw2 = {
245         .name                           = "96358VW2",
246         .expected_cpu_id                = 0x6358,
247
248         .has_enet0                      = 1,
249         .has_enet1                      = 1,
250         .has_pci                        = 1,
251
252         .enet0 = {
253                 .has_phy                = 1,
254                 .use_internal_phy       = 1,
255         },
256
257         .enet1 = {
258                 .force_speed_100        = 1,
259                 .force_duplex_full      = 1,
260         },
261
262
263         .has_ohci0 = 1,
264         .has_pccard = 1,
265         .has_ehci0 = 1,
266 };
267
268 static struct board_info __initdata board_AGPFS0 = {
269         .name                           = "AGPF-S0",
270         .expected_cpu_id                = 0x6358,
271
272         .has_enet0                      = 1,
273         .has_enet1                      = 1,
274         .has_pci                        = 1,
275
276         .enet0 = {
277                 .has_phy                = 1,
278                 .use_internal_phy       = 1,
279         },
280
281         .enet1 = {
282                 .force_speed_100        = 1,
283                 .force_duplex_full      = 1,
284         },
285
286         .has_ohci0 = 1,
287         .has_ehci0 = 1,
288 };
289 #endif
290
291 /*
292  * all boards
293  */
294 static const struct board_info __initdata *bcm963xx_boards[] = {
295 #ifdef CONFIG_BCM63XX_CPU_6338
296         &board_96338gw,
297         &board_96338w,
298 #endif
299 #ifdef CONFIG_BCM63XX_CPU_6348
300         &board_96348r,
301         &board_96348gw,
302         &board_96348gw_10,
303         &board_96348gw_11,
304         &board_FAST2404,
305         &board_DV201AMR,
306         &board_96348gw_a,
307 #endif
308
309 #ifdef CONFIG_BCM63XX_CPU_6358
310         &board_96358vw,
311         &board_96358vw2,
312         &board_AGPFS0,
313 #endif
314 };
315
316 /*
317  * early init callback, read nvram data from flash and checksum it
318  */
319 void __init board_prom_init(void)
320 {
321         unsigned int check_len, i;
322         u8 *boot_addr, *cfe, *p;
323         char cfe_version[32];
324         u32 val;
325
326         /* read base address of boot chip select (0) 
327          * 6338/6345 does not have MPI but boots from standard
328          * MIPS Flash address */
329         if (BCMCPU_IS_6338() || BCMCPU_IS_6345())
330                 val = 0x1fc00000;
331         else {
332                 val = bcm_mpi_readl(MPI_CSBASE_REG(0));
333                 val &= MPI_CSBASE_BASE_MASK;
334         }
335         boot_addr = (u8 *)KSEG1ADDR(val);
336
337         /* dump cfe version */
338         cfe = boot_addr + BCM963XX_CFE_VERSION_OFFSET;
339         if (!memcmp(cfe, "cfe-v", 5))
340                 snprintf(cfe_version, sizeof(cfe_version), "%u.%u.%u-%u.%u",
341                          cfe[5], cfe[6], cfe[7], cfe[8], cfe[9]);
342         else
343                 strcpy(cfe_version, "unknown");
344         printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);
345
346         /* extract nvram data */
347         memcpy(&nvram, boot_addr + BCM963XX_NVRAM_OFFSET, sizeof(nvram));
348
349         /* check checksum before using data */
350         if (nvram.version <= 4)
351                 check_len = offsetof(struct bcm963xx_nvram, checksum_old);
352         else
353                 check_len = sizeof(nvram);
354         val = 0;
355         p = (u8 *)&nvram;
356         while (check_len--)
357                 val += *p;
358         if (val) {
359                 printk(KERN_ERR PFX "invalid nvram checksum\n");
360                 return;
361         }
362
363         /* find board by name */
364         for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) {
365                 if (strncmp(nvram.name, bcm963xx_boards[i]->name,
366                             sizeof(nvram.name)))
367                         continue;
368                 /* copy, board desc array is marked initdata */
369                 memcpy(&board, bcm963xx_boards[i], sizeof(board));
370                 break;
371         }
372
373         /* bail out if board is not found, will complain later */
374         if (!board.name[0]) {
375                 char name[17];
376                 memcpy(name, nvram.name, 16);
377                 name[16] = 0;
378                 printk(KERN_ERR PFX "unknown bcm963xx board: %s\n",
379                        name);
380                 return;
381         }
382
383         /* setup pin multiplexing depending on board enabled device,
384          * this has to be done this early since PCI init is done
385          * inside arch_initcall */
386         val = 0;
387 #ifdef CONFIG_PCI
388         if (board.has_pci) {
389                 bcm63xx_pci_enabled = 1;
390                 if (BCMCPU_IS_6348())
391                         val |= GPIO_MODE_6348_G2_PCI;
392         }
393 #endif
394         if (board.has_pccard) {
395                 if (BCMCPU_IS_6348())
396                         val |= GPIO_MODE_6348_G1_MII_PCCARD;
397         }
398
399         if (board.has_enet0 && !board.enet0.use_internal_phy) {
400                 if (BCMCPU_IS_6348())
401                         val |= GPIO_MODE_6348_G3_EXT_MII |
402                                 GPIO_MODE_6348_G0_EXT_MII;
403         }
404
405         if (board.has_enet1 && !board.enet1.use_internal_phy) {
406                 if (BCMCPU_IS_6348())
407                         val |= GPIO_MODE_6348_G3_EXT_MII |
408                                 GPIO_MODE_6348_G0_EXT_MII;
409         }
410
411         bcm_gpio_writel(val, GPIO_MODE_REG);
412 }
413
414 /*
415  * second stage init callback, good time to panic if we couldn't
416  * identify on which board we're running since early printk is working
417  */
418 void __init board_setup(void)
419 {
420         if (!board.name[0])
421                 panic("unable to detect bcm963xx board");
422         printk(KERN_INFO PFX "board name: %s\n", board.name);
423
424         /* make sure we're running on expected cpu */
425         if (bcm63xx_get_cpu_id() != board.expected_cpu_id)
426                 panic("unexpected CPU for bcm963xx board");
427 }
428
429 /*
430  * return board name for /proc/cpuinfo
431  */
432 const char *board_get_name(void)
433 {
434         return board.name;
435 }
436
437 /*
438  * register & return a new board mac address
439  */
440 static int board_get_mac_address(u8 *mac)
441 {
442         u8 *p;
443         int count;
444
445         if (mac_addr_used >= nvram.mac_addr_count) {
446                 printk(KERN_ERR PFX "not enough mac address\n");
447                 return -ENODEV;
448         }
449
450         memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
451         p = mac + ETH_ALEN - 1;
452         count = mac_addr_used;
453
454         while (count--) {
455                 do {
456                         (*p)++;
457                         if (*p != 0)
458                                 break;
459                         p--;
460                 } while (p != mac);
461         }
462
463         if (p == mac) {
464                 printk(KERN_ERR PFX "unable to fetch mac address\n");
465                 return -ENODEV;
466         }
467
468         mac_addr_used++;
469         return 0;
470 }
471
472 static struct resource mtd_resources[] = {
473         {
474                 .start          = 0,    /* filled at runtime */
475                 .end            = 0,    /* filled at runtime */
476                 .flags          = IORESOURCE_MEM,
477         }
478 };
479
480 static struct platform_device mtd_dev = {
481         .name                   = "bcm963xx-flash",
482         .resource               = mtd_resources,
483         .num_resources          = ARRAY_SIZE(mtd_resources),
484 };
485
486 /*
487  * Register a sane SPROMv2 to make the on-board
488  * bcm4318 WLAN work
489  */
490 static struct ssb_sprom bcm63xx_sprom = {
491         .revision               = 0x02,
492         .board_rev              = 0x17,
493         .country_code           = 0x0,
494         .ant_available_bg       = 0x3,
495         .pa0b0                  = 0x15ae,
496         .pa0b1                  = 0xfa85,
497         .pa0b2                  = 0xfe8d,
498         .pa1b0                  = 0xffff,
499         .pa1b1                  = 0xffff,
500         .pa1b2                  = 0xffff,
501         .gpio0                  = 0xff,
502         .gpio1                  = 0xff,
503         .gpio2                  = 0xff,
504         .gpio3                  = 0xff,
505         .maxpwr_bg              = 0x004c,
506         .itssi_bg               = 0x00,
507         .boardflags_lo          = 0x2848,
508         .boardflags_hi          = 0x0000,
509 };
510
511 static struct resource gpiodev_resource = {
512         .start                  = 0xFFFFFFFF,
513 };
514
515 /*
516  * third stage init callback, register all board devices.
517  */
518 int __init board_register_devices(void)
519 {
520         u32 val;
521
522         bcm63xx_uart_register();
523         bcm63xx_wdt_register();
524         bcm63xx_spi_register();
525
526         if (board.has_pccard)
527                 bcm63xx_pcmcia_register();
528
529         if (board.has_enet0 &&
530             !board_get_mac_address(board.enet0.mac_addr))
531                 bcm63xx_enet_register(0, &board.enet0);
532
533         if (board.has_enet1 &&
534             !board_get_mac_address(board.enet1.mac_addr))
535                 bcm63xx_enet_register(1, &board.enet1);
536
537         if (board.has_ohci0)
538                 bcm63xx_ohci_register();
539
540         if (board.has_ehci0)
541                 bcm63xx_ehci_register();
542
543         if (board.has_udc0)
544                 bcm63xx_udc_register();
545         /* Generate MAC address for WLAN and
546          * register our SPROM */
547 #ifdef CONFIG_PCI
548         if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {
549                 memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
550                 memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
551                 if (ssb_arch_set_fallback_sprom(&bcm63xx_sprom) < 0)
552                         printk(KERN_ERR "failed to register fallback SPROM\n");
553         }
554 #endif
555
556         /* read base address of boot chip select (0) */
557         if (BCMCPU_IS_6338() || BCMCPU_IS_6345())
558                 val = 0x1fc0000;
559         else {
560                 val = bcm_mpi_readl(MPI_CSBASE_REG(0));
561                 val &= MPI_CSBASE_BASE_MASK;
562         }
563         mtd_resources[0].start = val;
564         mtd_resources[0].end = 0x1FFFFFFF;
565
566         platform_device_register(&mtd_dev);
567
568         /* Register GPIODEV */
569         platform_device_register_simple("GPIODEV", 0, &gpiodev_resource, 1);
570
571         return 0;
572 }
573