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 32 static struct bcm963xx_nvram nvram; 33 static unsigned int mac_addr_used; 34 static struct board_info board; 35 36 /* 37 * known 6338 boards 38 */ 39 #ifdef CONFIG_BCM63XX_CPU_6338 40 static 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 83 static 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 129 static 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 141 static 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 185 static 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 245 static 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 299 static 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 357 static 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 381 static 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 400 static 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 420 static 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 446 static 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 498 static 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 546 static 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 569 static 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 */ 594 static 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 626 static 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 647 int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out) 648 { 649 if (bus->bustype == SSB_BUSTYPE_PCI) { 650 memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom)); 651 return 0; 652 } else { 653 printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n"); 654 return -EINVAL; 655 } 656 } 657 #endif 658 659 /* 660 * return board name for /proc/cpuinfo 661 */ 662 const char *board_get_name(void) 663 { 664 return board.name; 665 } 666 667 /* 668 * register & return a new board mac address 669 */ 670 static int board_get_mac_address(u8 *mac) 671 { 672 u8 *p; 673 int count; 674 675 if (mac_addr_used >= nvram.mac_addr_count) { 676 printk(KERN_ERR PFX "not enough mac address\n"); 677 return -ENODEV; 678 } 679 680 memcpy(mac, nvram.mac_addr_base, ETH_ALEN); 681 p = mac + ETH_ALEN - 1; 682 count = mac_addr_used; 683 684 while (count--) { 685 do { 686 (*p)++; 687 if (*p != 0) 688 break; 689 p--; 690 } while (p != mac); 691 } 692 693 if (p == mac) { 694 printk(KERN_ERR PFX "unable to fetch mac address\n"); 695 return -ENODEV; 696 } 697 698 mac_addr_used++; 699 return 0; 700 } 701 702 /* 703 * early init callback, read nvram data from flash and checksum it 704 */ 705 void __init board_prom_init(void) 706 { 707 unsigned int check_len, i; 708 u8 *boot_addr, *cfe, *p; 709 char cfe_version[32]; 710 u32 val; 711 712 /* read base address of boot chip select (0) 713 * 6345 does not have MPI but boots from standard 714 * MIPS Flash address */ 715 if (BCMCPU_IS_6345()) 716 val = 0x1fc00000; 717 else { 718 val = bcm_mpi_readl(MPI_CSBASE_REG(0)); 719 val &= MPI_CSBASE_BASE_MASK; 720 } 721 boot_addr = (u8 *)KSEG1ADDR(val); 722 723 /* dump cfe version */ 724 cfe = boot_addr + BCM963XX_CFE_VERSION_OFFSET; 725 if (!memcmp(cfe, "cfe-v", 5)) 726 snprintf(cfe_version, sizeof(cfe_version), "%u.%u.%u-%u.%u", 727 cfe[5], cfe[6], cfe[7], cfe[8], cfe[9]); 728 else 729 strcpy(cfe_version, "unknown"); 730 printk(KERN_INFO PFX "CFE version: %s\n", cfe_version); 731 732 /* extract nvram data */ 733 memcpy(&nvram, boot_addr + BCM963XX_NVRAM_OFFSET, sizeof(nvram)); 734 735 /* check checksum before using data */ 736 if (nvram.version <= 4) 737 check_len = offsetof(struct bcm963xx_nvram, checksum_old); 738 else 739 check_len = sizeof(nvram); 740 val = 0; 741 p = (u8 *)&nvram; 742 while (check_len--) 743 val += *p; 744 if (val) { 745 printk(KERN_ERR PFX "invalid nvram checksum\n"); 746 return; 747 } 748 749 /* find board by name */ 750 for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) { 751 if (strncmp(nvram.name, bcm963xx_boards[i]->name, 752 sizeof(nvram.name))) 753 continue; 754 /* copy, board desc array is marked initdata */ 755 memcpy(&board, bcm963xx_boards[i], sizeof(board)); 756 break; 757 } 758 759 /* bail out if board is not found, will complain later */ 760 if (!board.name[0]) { 761 char name[17]; 762 memcpy(name, nvram.name, 16); 763 name[16] = 0; 764 printk(KERN_ERR PFX "unknown bcm963xx board: %s\n", 765 name); 766 return; 767 } 768 769 /* setup pin multiplexing depending on board enabled device, 770 * this has to be done this early since PCI init is done 771 * inside arch_initcall */ 772 val = 0; 773 774 #ifdef CONFIG_PCI 775 if (board.has_pci) { 776 bcm63xx_pci_enabled = 1; 777 if (BCMCPU_IS_6348()) 778 val |= GPIO_MODE_6348_G2_PCI; 779 } 780 #endif 781 782 if (board.has_pccard) { 783 if (BCMCPU_IS_6348()) 784 val |= GPIO_MODE_6348_G1_MII_PCCARD; 785 } 786 787 if (board.has_enet0 && !board.enet0.use_internal_phy) { 788 if (BCMCPU_IS_6348()) 789 val |= GPIO_MODE_6348_G3_EXT_MII | 790 GPIO_MODE_6348_G0_EXT_MII; 791 } 792 793 if (board.has_enet1 && !board.enet1.use_internal_phy) { 794 if (BCMCPU_IS_6348()) 795 val |= GPIO_MODE_6348_G3_EXT_MII | 796 GPIO_MODE_6348_G0_EXT_MII; 797 } 798 799 bcm_gpio_writel(val, GPIO_MODE_REG); 800 801 /* Generate MAC address for WLAN and 802 * register our SPROM */ 803 #ifdef CONFIG_SSB_PCIHOST 804 if (!board_get_mac_address(bcm63xx_sprom.il0mac)) { 805 memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN); 806 memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN); 807 if (ssb_arch_register_fallback_sprom( 808 &bcm63xx_get_fallback_sprom) < 0) 809 printk(KERN_ERR PFX "failed to register fallback SPROM\n"); 810 } 811 #endif 812 } 813 814 /* 815 * second stage init callback, good time to panic if we couldn't 816 * identify on which board we're running since early printk is working 817 */ 818 void __init board_setup(void) 819 { 820 if (!board.name[0]) 821 panic("unable to detect bcm963xx board"); 822 printk(KERN_INFO PFX "board name: %s\n", board.name); 823 824 /* make sure we're running on expected cpu */ 825 if (bcm63xx_get_cpu_id() != board.expected_cpu_id) 826 panic("unexpected CPU for bcm963xx board"); 827 } 828 829 static struct mtd_partition mtd_partitions[] = { 830 { 831 .name = "cfe", 832 .offset = 0x0, 833 .size = 0x40000, 834 } 835 }; 836 837 static struct physmap_flash_data flash_data = { 838 .width = 2, 839 .nr_parts = ARRAY_SIZE(mtd_partitions), 840 .parts = mtd_partitions, 841 }; 842 843 static struct resource mtd_resources[] = { 844 { 845 .start = 0, /* filled at runtime */ 846 .end = 0, /* filled at runtime */ 847 .flags = IORESOURCE_MEM, 848 } 849 }; 850 851 static struct platform_device mtd_dev = { 852 .name = "physmap-flash", 853 .resource = mtd_resources, 854 .num_resources = ARRAY_SIZE(mtd_resources), 855 .dev = { 856 .platform_data = &flash_data, 857 }, 858 }; 859 860 static struct gpio_led_platform_data bcm63xx_led_data; 861 862 static struct platform_device bcm63xx_gpio_leds = { 863 .name = "leds-gpio", 864 .id = 0, 865 .dev.platform_data = &bcm63xx_led_data, 866 }; 867 868 /* 869 * third stage init callback, register all board devices. 870 */ 871 int __init board_register_devices(void) 872 { 873 u32 val; 874 875 if (board.has_uart0) 876 bcm63xx_uart_register(0); 877 878 if (board.has_uart1) 879 bcm63xx_uart_register(1); 880 881 if (board.has_pccard) 882 bcm63xx_pcmcia_register(); 883 884 if (board.has_enet0 && 885 !board_get_mac_address(board.enet0.mac_addr)) 886 bcm63xx_enet_register(0, &board.enet0); 887 888 if (board.has_enet1 && 889 !board_get_mac_address(board.enet1.mac_addr)) 890 bcm63xx_enet_register(1, &board.enet1); 891 892 if (board.has_dsp) 893 bcm63xx_dsp_register(&board.dsp); 894 895 /* read base address of boot chip select (0) */ 896 if (BCMCPU_IS_6345()) 897 val = 0x1fc00000; 898 else { 899 val = bcm_mpi_readl(MPI_CSBASE_REG(0)); 900 val &= MPI_CSBASE_BASE_MASK; 901 } 902 mtd_resources[0].start = val; 903 mtd_resources[0].end = 0x1FFFFFFF; 904 905 platform_device_register(&mtd_dev); 906 907 bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds); 908 bcm63xx_led_data.leds = board.leds; 909 910 platform_device_register(&bcm63xx_gpio_leds); 911 912 return 0; 913 } 914