1 /* 2 * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org> 3 * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 #include <linux/init.h> 21 #include <linux/types.h> 22 #include <linux/delay.h> 23 #include <linux/dma-mapping.h> 24 #include <linux/platform_device.h> 25 #include <linux/mtd/physmap.h> 26 #include <linux/serial.h> 27 #include <linux/serial_8250.h> 28 #include <linux/ioport.h> 29 #include <linux/io.h> 30 #include <linux/vlynq.h> 31 #include <linux/leds.h> 32 #include <linux/string.h> 33 #include <linux/etherdevice.h> 34 #include <linux/phy.h> 35 #include <linux/phy_fixed.h> 36 #include <linux/gpio.h> 37 #include <linux/clk.h> 38 39 #include <asm/addrspace.h> 40 #include <asm/mach-ar7/ar7.h> 41 #include <asm/mach-ar7/prom.h> 42 43 /***************************************************************************** 44 * VLYNQ Bus 45 ****************************************************************************/ 46 struct plat_vlynq_data { 47 struct plat_vlynq_ops ops; 48 int gpio_bit; 49 int reset_bit; 50 }; 51 52 static int vlynq_on(struct vlynq_device *dev) 53 { 54 int ret; 55 struct plat_vlynq_data *pdata = dev->dev.platform_data; 56 57 ret = gpio_request(pdata->gpio_bit, "vlynq"); 58 if (ret) 59 goto out; 60 61 ar7_device_reset(pdata->reset_bit); 62 63 ret = ar7_gpio_disable(pdata->gpio_bit); 64 if (ret) 65 goto out_enabled; 66 67 ret = ar7_gpio_enable(pdata->gpio_bit); 68 if (ret) 69 goto out_enabled; 70 71 ret = gpio_direction_output(pdata->gpio_bit, 0); 72 if (ret) 73 goto out_gpio_enabled; 74 75 msleep(50); 76 77 gpio_set_value(pdata->gpio_bit, 1); 78 79 msleep(50); 80 81 return 0; 82 83 out_gpio_enabled: 84 ar7_gpio_disable(pdata->gpio_bit); 85 out_enabled: 86 ar7_device_disable(pdata->reset_bit); 87 gpio_free(pdata->gpio_bit); 88 out: 89 return ret; 90 } 91 92 static void vlynq_off(struct vlynq_device *dev) 93 { 94 struct plat_vlynq_data *pdata = dev->dev.platform_data; 95 96 ar7_gpio_disable(pdata->gpio_bit); 97 gpio_free(pdata->gpio_bit); 98 ar7_device_disable(pdata->reset_bit); 99 } 100 101 static struct resource vlynq_low_res[] = { 102 { 103 .name = "regs", 104 .flags = IORESOURCE_MEM, 105 .start = AR7_REGS_VLYNQ0, 106 .end = AR7_REGS_VLYNQ0 + 0xff, 107 }, 108 { 109 .name = "irq", 110 .flags = IORESOURCE_IRQ, 111 .start = 29, 112 .end = 29, 113 }, 114 { 115 .name = "mem", 116 .flags = IORESOURCE_MEM, 117 .start = 0x04000000, 118 .end = 0x04ffffff, 119 }, 120 { 121 .name = "devirq", 122 .flags = IORESOURCE_IRQ, 123 .start = 80, 124 .end = 111, 125 }, 126 }; 127 128 static struct resource vlynq_high_res[] = { 129 { 130 .name = "regs", 131 .flags = IORESOURCE_MEM, 132 .start = AR7_REGS_VLYNQ1, 133 .end = AR7_REGS_VLYNQ1 + 0xff, 134 }, 135 { 136 .name = "irq", 137 .flags = IORESOURCE_IRQ, 138 .start = 33, 139 .end = 33, 140 }, 141 { 142 .name = "mem", 143 .flags = IORESOURCE_MEM, 144 .start = 0x0c000000, 145 .end = 0x0cffffff, 146 }, 147 { 148 .name = "devirq", 149 .flags = IORESOURCE_IRQ, 150 .start = 112, 151 .end = 143, 152 }, 153 }; 154 155 static struct plat_vlynq_data vlynq_low_data = { 156 .ops = { 157 .on = vlynq_on, 158 .off = vlynq_off, 159 }, 160 .reset_bit = 20, 161 .gpio_bit = 18, 162 }; 163 164 static struct plat_vlynq_data vlynq_high_data = { 165 .ops = { 166 .on = vlynq_on, 167 .off = vlynq_off, 168 }, 169 .reset_bit = 16, 170 .gpio_bit = 19, 171 }; 172 173 static struct platform_device vlynq_low = { 174 .id = 0, 175 .name = "vlynq", 176 .dev = { 177 .platform_data = &vlynq_low_data, 178 }, 179 .resource = vlynq_low_res, 180 .num_resources = ARRAY_SIZE(vlynq_low_res), 181 }; 182 183 static struct platform_device vlynq_high = { 184 .id = 1, 185 .name = "vlynq", 186 .dev = { 187 .platform_data = &vlynq_high_data, 188 }, 189 .resource = vlynq_high_res, 190 .num_resources = ARRAY_SIZE(vlynq_high_res), 191 }; 192 193 /***************************************************************************** 194 * Flash 195 ****************************************************************************/ 196 static struct resource physmap_flash_resource = { 197 .name = "mem", 198 .flags = IORESOURCE_MEM, 199 .start = 0x10000000, 200 .end = 0x107fffff, 201 }; 202 203 static const char *ar7_probe_types[] = { "ar7part", NULL }; 204 205 static struct physmap_flash_data physmap_flash_data = { 206 .width = 2, 207 .part_probe_types = ar7_probe_types, 208 }; 209 210 static struct platform_device physmap_flash = { 211 .name = "physmap-flash", 212 .dev = { 213 .platform_data = &physmap_flash_data, 214 }, 215 .resource = &physmap_flash_resource, 216 .num_resources = 1, 217 }; 218 219 /***************************************************************************** 220 * Ethernet 221 ****************************************************************************/ 222 static struct resource cpmac_low_res[] = { 223 { 224 .name = "regs", 225 .flags = IORESOURCE_MEM, 226 .start = AR7_REGS_MAC0, 227 .end = AR7_REGS_MAC0 + 0x7ff, 228 }, 229 { 230 .name = "irq", 231 .flags = IORESOURCE_IRQ, 232 .start = 27, 233 .end = 27, 234 }, 235 }; 236 237 static struct resource cpmac_high_res[] = { 238 { 239 .name = "regs", 240 .flags = IORESOURCE_MEM, 241 .start = AR7_REGS_MAC1, 242 .end = AR7_REGS_MAC1 + 0x7ff, 243 }, 244 { 245 .name = "irq", 246 .flags = IORESOURCE_IRQ, 247 .start = 41, 248 .end = 41, 249 }, 250 }; 251 252 static struct fixed_phy_status fixed_phy_status __initdata = { 253 .link = 1, 254 .speed = 100, 255 .duplex = 1, 256 }; 257 258 static struct plat_cpmac_data cpmac_low_data = { 259 .reset_bit = 17, 260 .power_bit = 20, 261 .phy_mask = 0x80000000, 262 }; 263 264 static struct plat_cpmac_data cpmac_high_data = { 265 .reset_bit = 21, 266 .power_bit = 22, 267 .phy_mask = 0x7fffffff, 268 }; 269 270 static u64 cpmac_dma_mask = DMA_BIT_MASK(32); 271 272 static struct platform_device cpmac_low = { 273 .id = 0, 274 .name = "cpmac", 275 .dev = { 276 .dma_mask = &cpmac_dma_mask, 277 .coherent_dma_mask = DMA_BIT_MASK(32), 278 .platform_data = &cpmac_low_data, 279 }, 280 .resource = cpmac_low_res, 281 .num_resources = ARRAY_SIZE(cpmac_low_res), 282 }; 283 284 static struct platform_device cpmac_high = { 285 .id = 1, 286 .name = "cpmac", 287 .dev = { 288 .dma_mask = &cpmac_dma_mask, 289 .coherent_dma_mask = DMA_BIT_MASK(32), 290 .platform_data = &cpmac_high_data, 291 }, 292 .resource = cpmac_high_res, 293 .num_resources = ARRAY_SIZE(cpmac_high_res), 294 }; 295 296 static void __init cpmac_get_mac(int instance, unsigned char *dev_addr) 297 { 298 char name[5], *mac; 299 300 sprintf(name, "mac%c", 'a' + instance); 301 mac = prom_getenv(name); 302 if (!mac && instance) { 303 sprintf(name, "mac%c", 'a'); 304 mac = prom_getenv(name); 305 } 306 307 if (mac) { 308 if (!mac_pton(mac, dev_addr)) { 309 pr_warn("cannot parse mac address, using random address\n"); 310 eth_random_addr(dev_addr); 311 } 312 } else 313 eth_random_addr(dev_addr); 314 } 315 316 /***************************************************************************** 317 * USB 318 ****************************************************************************/ 319 static struct resource usb_res[] = { 320 { 321 .name = "regs", 322 .flags = IORESOURCE_MEM, 323 .start = AR7_REGS_USB, 324 .end = AR7_REGS_USB + 0xff, 325 }, 326 { 327 .name = "irq", 328 .flags = IORESOURCE_IRQ, 329 .start = 32, 330 .end = 32, 331 }, 332 { 333 .name = "mem", 334 .flags = IORESOURCE_MEM, 335 .start = 0x03400000, 336 .end = 0x03401fff, 337 }, 338 }; 339 340 static struct platform_device ar7_udc = { 341 .name = "ar7_udc", 342 .resource = usb_res, 343 .num_resources = ARRAY_SIZE(usb_res), 344 }; 345 346 /***************************************************************************** 347 * LEDs 348 ****************************************************************************/ 349 static const struct gpio_led default_leds[] = { 350 { 351 .name = "status", 352 .gpio = 8, 353 .active_low = 1, 354 }, 355 }; 356 357 static const struct gpio_led titan_leds[] = { 358 { .name = "status", .gpio = 8, .active_low = 1, }, 359 { .name = "wifi", .gpio = 13, .active_low = 1, }, 360 }; 361 362 static const struct gpio_led dsl502t_leds[] = { 363 { 364 .name = "status", 365 .gpio = 9, 366 .active_low = 1, 367 }, 368 { 369 .name = "ethernet", 370 .gpio = 7, 371 .active_low = 1, 372 }, 373 { 374 .name = "usb", 375 .gpio = 12, 376 .active_low = 1, 377 }, 378 }; 379 380 static const struct gpio_led dg834g_leds[] = { 381 { 382 .name = "ppp", 383 .gpio = 6, 384 .active_low = 1, 385 }, 386 { 387 .name = "status", 388 .gpio = 7, 389 .active_low = 1, 390 }, 391 { 392 .name = "adsl", 393 .gpio = 8, 394 .active_low = 1, 395 }, 396 { 397 .name = "wifi", 398 .gpio = 12, 399 .active_low = 1, 400 }, 401 { 402 .name = "power", 403 .gpio = 14, 404 .active_low = 1, 405 .default_trigger = "default-on", 406 }, 407 }; 408 409 static const struct gpio_led fb_sl_leds[] = { 410 { 411 .name = "1", 412 .gpio = 7, 413 }, 414 { 415 .name = "2", 416 .gpio = 13, 417 .active_low = 1, 418 }, 419 { 420 .name = "3", 421 .gpio = 10, 422 .active_low = 1, 423 }, 424 { 425 .name = "4", 426 .gpio = 12, 427 .active_low = 1, 428 }, 429 { 430 .name = "5", 431 .gpio = 9, 432 .active_low = 1, 433 }, 434 }; 435 436 static const struct gpio_led fb_fon_leds[] = { 437 { 438 .name = "1", 439 .gpio = 8, 440 }, 441 { 442 .name = "2", 443 .gpio = 3, 444 .active_low = 1, 445 }, 446 { 447 .name = "3", 448 .gpio = 5, 449 }, 450 { 451 .name = "4", 452 .gpio = 4, 453 .active_low = 1, 454 }, 455 { 456 .name = "5", 457 .gpio = 11, 458 .active_low = 1, 459 }, 460 }; 461 462 static const struct gpio_led gt701_leds[] = { 463 { 464 .name = "inet:green", 465 .gpio = 13, 466 .active_low = 1, 467 }, 468 { 469 .name = "usb", 470 .gpio = 12, 471 .active_low = 1, 472 }, 473 { 474 .name = "inet:red", 475 .gpio = 9, 476 .active_low = 1, 477 }, 478 { 479 .name = "power:red", 480 .gpio = 7, 481 .active_low = 1, 482 }, 483 { 484 .name = "power:green", 485 .gpio = 8, 486 .active_low = 1, 487 .default_trigger = "default-on", 488 }, 489 { 490 .name = "ethernet", 491 .gpio = 10, 492 .active_low = 1, 493 }, 494 }; 495 496 static struct gpio_led_platform_data ar7_led_data; 497 498 static struct platform_device ar7_gpio_leds = { 499 .name = "leds-gpio", 500 .dev = { 501 .platform_data = &ar7_led_data, 502 } 503 }; 504 505 static void __init detect_leds(void) 506 { 507 char *prid, *usb_prod; 508 509 /* Default LEDs */ 510 ar7_led_data.num_leds = ARRAY_SIZE(default_leds); 511 ar7_led_data.leds = default_leds; 512 513 /* FIXME: the whole thing is unreliable */ 514 prid = prom_getenv("ProductID"); 515 usb_prod = prom_getenv("usb_prod"); 516 517 /* If we can't get the product id from PROM, use the default LEDs */ 518 if (!prid) 519 return; 520 521 if (strstr(prid, "Fritz_Box_FON")) { 522 ar7_led_data.num_leds = ARRAY_SIZE(fb_fon_leds); 523 ar7_led_data.leds = fb_fon_leds; 524 } else if (strstr(prid, "Fritz_Box_")) { 525 ar7_led_data.num_leds = ARRAY_SIZE(fb_sl_leds); 526 ar7_led_data.leds = fb_sl_leds; 527 } else if ((!strcmp(prid, "AR7RD") || !strcmp(prid, "AR7DB")) 528 && usb_prod != NULL && strstr(usb_prod, "DSL-502T")) { 529 ar7_led_data.num_leds = ARRAY_SIZE(dsl502t_leds); 530 ar7_led_data.leds = dsl502t_leds; 531 } else if (strstr(prid, "DG834")) { 532 ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds); 533 ar7_led_data.leds = dg834g_leds; 534 } else if (strstr(prid, "CYWM") || strstr(prid, "CYWL")) { 535 ar7_led_data.num_leds = ARRAY_SIZE(titan_leds); 536 ar7_led_data.leds = titan_leds; 537 } else if (strstr(prid, "GT701")) { 538 ar7_led_data.num_leds = ARRAY_SIZE(gt701_leds); 539 ar7_led_data.leds = gt701_leds; 540 } 541 } 542 543 /***************************************************************************** 544 * Watchdog 545 ****************************************************************************/ 546 static struct resource ar7_wdt_res = { 547 .name = "regs", 548 .flags = IORESOURCE_MEM, 549 .start = -1, /* Filled at runtime */ 550 .end = -1, /* Filled at runtime */ 551 }; 552 553 static struct platform_device ar7_wdt = { 554 .name = "ar7_wdt", 555 .resource = &ar7_wdt_res, 556 .num_resources = 1, 557 }; 558 559 /***************************************************************************** 560 * Init 561 ****************************************************************************/ 562 static int __init ar7_register_uarts(void) 563 { 564 #ifdef CONFIG_SERIAL_8250 565 static struct uart_port uart_port __initdata; 566 struct clk *bus_clk; 567 int res; 568 569 memset(&uart_port, 0, sizeof(struct uart_port)); 570 571 bus_clk = clk_get(NULL, "bus"); 572 if (IS_ERR(bus_clk)) 573 panic("unable to get bus clk"); 574 575 uart_port.type = PORT_AR7; 576 uart_port.uartclk = clk_get_rate(bus_clk) / 2; 577 uart_port.iotype = UPIO_MEM32; 578 uart_port.flags = UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF; 579 uart_port.regshift = 2; 580 581 uart_port.line = 0; 582 uart_port.irq = AR7_IRQ_UART0; 583 uart_port.mapbase = AR7_REGS_UART0; 584 uart_port.membase = ioremap(uart_port.mapbase, 256); 585 586 res = early_serial_setup(&uart_port); 587 if (res) 588 return res; 589 590 /* Only TNETD73xx have a second serial port */ 591 if (ar7_has_second_uart()) { 592 uart_port.line = 1; 593 uart_port.irq = AR7_IRQ_UART1; 594 uart_port.mapbase = UR8_REGS_UART1; 595 uart_port.membase = ioremap(uart_port.mapbase, 256); 596 597 res = early_serial_setup(&uart_port); 598 if (res) 599 return res; 600 } 601 #endif 602 603 return 0; 604 } 605 606 static void __init titan_fixup_devices(void) 607 { 608 /* Set vlynq0 data */ 609 vlynq_low_data.reset_bit = 15; 610 vlynq_low_data.gpio_bit = 14; 611 612 /* Set vlynq1 data */ 613 vlynq_high_data.reset_bit = 16; 614 vlynq_high_data.gpio_bit = 7; 615 616 /* Set vlynq0 resources */ 617 vlynq_low_res[0].start = TITAN_REGS_VLYNQ0; 618 vlynq_low_res[0].end = TITAN_REGS_VLYNQ0 + 0xff; 619 vlynq_low_res[1].start = 33; 620 vlynq_low_res[1].end = 33; 621 vlynq_low_res[2].start = 0x0c000000; 622 vlynq_low_res[2].end = 0x0fffffff; 623 vlynq_low_res[3].start = 80; 624 vlynq_low_res[3].end = 111; 625 626 /* Set vlynq1 resources */ 627 vlynq_high_res[0].start = TITAN_REGS_VLYNQ1; 628 vlynq_high_res[0].end = TITAN_REGS_VLYNQ1 + 0xff; 629 vlynq_high_res[1].start = 34; 630 vlynq_high_res[1].end = 34; 631 vlynq_high_res[2].start = 0x40000000; 632 vlynq_high_res[2].end = 0x43ffffff; 633 vlynq_high_res[3].start = 112; 634 vlynq_high_res[3].end = 143; 635 636 /* Set cpmac0 data */ 637 cpmac_low_data.phy_mask = 0x40000000; 638 639 /* Set cpmac1 data */ 640 cpmac_high_data.phy_mask = 0x80000000; 641 642 /* Set cpmac0 resources */ 643 cpmac_low_res[0].start = TITAN_REGS_MAC0; 644 cpmac_low_res[0].end = TITAN_REGS_MAC0 + 0x7ff; 645 646 /* Set cpmac1 resources */ 647 cpmac_high_res[0].start = TITAN_REGS_MAC1; 648 cpmac_high_res[0].end = TITAN_REGS_MAC1 + 0x7ff; 649 } 650 651 static int __init ar7_register_devices(void) 652 { 653 void __iomem *bootcr; 654 u32 val; 655 int res; 656 657 res = ar7_gpio_init(); 658 if (res) 659 pr_warn("unable to register gpios: %d\n", res); 660 661 res = ar7_register_uarts(); 662 if (res) 663 pr_err("unable to setup uart(s): %d\n", res); 664 665 res = platform_device_register(&physmap_flash); 666 if (res) 667 pr_warn("unable to register physmap-flash: %d\n", res); 668 669 if (ar7_is_titan()) 670 titan_fixup_devices(); 671 672 ar7_device_disable(vlynq_low_data.reset_bit); 673 res = platform_device_register(&vlynq_low); 674 if (res) 675 pr_warn("unable to register vlynq-low: %d\n", res); 676 677 if (ar7_has_high_vlynq()) { 678 ar7_device_disable(vlynq_high_data.reset_bit); 679 res = platform_device_register(&vlynq_high); 680 if (res) 681 pr_warn("unable to register vlynq-high: %d\n", res); 682 } 683 684 if (ar7_has_high_cpmac()) { 685 res = fixed_phy_add(PHY_POLL, cpmac_high.id, 686 &fixed_phy_status); 687 if (!res) { 688 cpmac_get_mac(1, cpmac_high_data.dev_addr); 689 690 res = platform_device_register(&cpmac_high); 691 if (res) 692 pr_warn("unable to register cpmac-high: %d\n", 693 res); 694 } else 695 pr_warn("unable to add cpmac-high phy: %d\n", res); 696 } else 697 cpmac_low_data.phy_mask = 0xffffffff; 698 699 res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status); 700 if (!res) { 701 cpmac_get_mac(0, cpmac_low_data.dev_addr); 702 res = platform_device_register(&cpmac_low); 703 if (res) 704 pr_warn("unable to register cpmac-low: %d\n", res); 705 } else 706 pr_warn("unable to add cpmac-low phy: %d\n", res); 707 708 detect_leds(); 709 res = platform_device_register(&ar7_gpio_leds); 710 if (res) 711 pr_warn("unable to register leds: %d\n", res); 712 713 res = platform_device_register(&ar7_udc); 714 if (res) 715 pr_warn("unable to register usb slave: %d\n", res); 716 717 /* Register watchdog only if enabled in hardware */ 718 bootcr = ioremap_nocache(AR7_REGS_DCL, 4); 719 val = readl(bootcr); 720 iounmap(bootcr); 721 if (val & AR7_WDT_HW_ENA) { 722 if (ar7_has_high_vlynq()) 723 ar7_wdt_res.start = UR8_REGS_WDT; 724 else 725 ar7_wdt_res.start = AR7_REGS_WDT; 726 727 ar7_wdt_res.end = ar7_wdt_res.start + 0x20; 728 res = platform_device_register(&ar7_wdt); 729 if (res) 730 pr_warn("unable to register watchdog: %d\n", res); 731 } 732 733 return 0; 734 } 735 device_initcall(ar7_register_devices); 736