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