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