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