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