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