1 /* 2 * arch/arm/mach-orion5x/common.c 3 * 4 * Core functions for Marvell Orion 5x SoCs 5 * 6 * Maintainer: Tzachi Perelstein <tzachi@marvell.com> 7 * 8 * This file is licensed under the terms of the GNU General Public 9 * License version 2. This program is licensed "as is" without any 10 * warranty of any kind, whether express or implied. 11 */ 12 13 #include <linux/kernel.h> 14 #include <linux/init.h> 15 #include <linux/platform_device.h> 16 #include <linux/serial_8250.h> 17 #include <linux/mbus.h> 18 #include <linux/mv643xx_eth.h> 19 #include <linux/mv643xx_i2c.h> 20 #include <linux/ata_platform.h> 21 #include <linux/spi/orion_spi.h> 22 #include <net/dsa.h> 23 #include <asm/page.h> 24 #include <asm/setup.h> 25 #include <asm/timex.h> 26 #include <asm/mach/arch.h> 27 #include <asm/mach/map.h> 28 #include <asm/mach/time.h> 29 #include <mach/hardware.h> 30 #include <mach/orion5x.h> 31 #include <plat/ehci-orion.h> 32 #include <plat/mv_xor.h> 33 #include <plat/orion_nand.h> 34 #include <plat/orion5x_wdt.h> 35 #include <plat/time.h> 36 #include "common.h" 37 38 /***************************************************************************** 39 * I/O Address Mapping 40 ****************************************************************************/ 41 static struct map_desc orion5x_io_desc[] __initdata = { 42 { 43 .virtual = ORION5X_REGS_VIRT_BASE, 44 .pfn = __phys_to_pfn(ORION5X_REGS_PHYS_BASE), 45 .length = ORION5X_REGS_SIZE, 46 .type = MT_DEVICE, 47 }, { 48 .virtual = ORION5X_PCIE_IO_VIRT_BASE, 49 .pfn = __phys_to_pfn(ORION5X_PCIE_IO_PHYS_BASE), 50 .length = ORION5X_PCIE_IO_SIZE, 51 .type = MT_DEVICE, 52 }, { 53 .virtual = ORION5X_PCI_IO_VIRT_BASE, 54 .pfn = __phys_to_pfn(ORION5X_PCI_IO_PHYS_BASE), 55 .length = ORION5X_PCI_IO_SIZE, 56 .type = MT_DEVICE, 57 }, { 58 .virtual = ORION5X_PCIE_WA_VIRT_BASE, 59 .pfn = __phys_to_pfn(ORION5X_PCIE_WA_PHYS_BASE), 60 .length = ORION5X_PCIE_WA_SIZE, 61 .type = MT_DEVICE, 62 }, 63 }; 64 65 void __init orion5x_map_io(void) 66 { 67 iotable_init(orion5x_io_desc, ARRAY_SIZE(orion5x_io_desc)); 68 } 69 70 71 /***************************************************************************** 72 * EHCI 73 ****************************************************************************/ 74 static struct orion_ehci_data orion5x_ehci_data = { 75 .dram = &orion5x_mbus_dram_info, 76 .phy_version = EHCI_PHY_ORION, 77 }; 78 79 static u64 ehci_dmamask = 0xffffffffUL; 80 81 82 /***************************************************************************** 83 * EHCI0 84 ****************************************************************************/ 85 static struct resource orion5x_ehci0_resources[] = { 86 { 87 .start = ORION5X_USB0_PHYS_BASE, 88 .end = ORION5X_USB0_PHYS_BASE + SZ_4K - 1, 89 .flags = IORESOURCE_MEM, 90 }, { 91 .start = IRQ_ORION5X_USB0_CTRL, 92 .end = IRQ_ORION5X_USB0_CTRL, 93 .flags = IORESOURCE_IRQ, 94 }, 95 }; 96 97 static struct platform_device orion5x_ehci0 = { 98 .name = "orion-ehci", 99 .id = 0, 100 .dev = { 101 .dma_mask = &ehci_dmamask, 102 .coherent_dma_mask = 0xffffffff, 103 .platform_data = &orion5x_ehci_data, 104 }, 105 .resource = orion5x_ehci0_resources, 106 .num_resources = ARRAY_SIZE(orion5x_ehci0_resources), 107 }; 108 109 void __init orion5x_ehci0_init(void) 110 { 111 platform_device_register(&orion5x_ehci0); 112 } 113 114 115 /***************************************************************************** 116 * EHCI1 117 ****************************************************************************/ 118 static struct resource orion5x_ehci1_resources[] = { 119 { 120 .start = ORION5X_USB1_PHYS_BASE, 121 .end = ORION5X_USB1_PHYS_BASE + SZ_4K - 1, 122 .flags = IORESOURCE_MEM, 123 }, { 124 .start = IRQ_ORION5X_USB1_CTRL, 125 .end = IRQ_ORION5X_USB1_CTRL, 126 .flags = IORESOURCE_IRQ, 127 }, 128 }; 129 130 static struct platform_device orion5x_ehci1 = { 131 .name = "orion-ehci", 132 .id = 1, 133 .dev = { 134 .dma_mask = &ehci_dmamask, 135 .coherent_dma_mask = 0xffffffff, 136 .platform_data = &orion5x_ehci_data, 137 }, 138 .resource = orion5x_ehci1_resources, 139 .num_resources = ARRAY_SIZE(orion5x_ehci1_resources), 140 }; 141 142 void __init orion5x_ehci1_init(void) 143 { 144 platform_device_register(&orion5x_ehci1); 145 } 146 147 148 /***************************************************************************** 149 * GigE 150 ****************************************************************************/ 151 struct mv643xx_eth_shared_platform_data orion5x_eth_shared_data = { 152 .dram = &orion5x_mbus_dram_info, 153 }; 154 155 static struct resource orion5x_eth_shared_resources[] = { 156 { 157 .start = ORION5X_ETH_PHYS_BASE + 0x2000, 158 .end = ORION5X_ETH_PHYS_BASE + 0x3fff, 159 .flags = IORESOURCE_MEM, 160 }, { 161 .start = IRQ_ORION5X_ETH_ERR, 162 .end = IRQ_ORION5X_ETH_ERR, 163 .flags = IORESOURCE_IRQ, 164 }, 165 }; 166 167 static struct platform_device orion5x_eth_shared = { 168 .name = MV643XX_ETH_SHARED_NAME, 169 .id = 0, 170 .dev = { 171 .platform_data = &orion5x_eth_shared_data, 172 }, 173 .num_resources = ARRAY_SIZE(orion5x_eth_shared_resources), 174 .resource = orion5x_eth_shared_resources, 175 }; 176 177 static struct resource orion5x_eth_resources[] = { 178 { 179 .name = "eth irq", 180 .start = IRQ_ORION5X_ETH_SUM, 181 .end = IRQ_ORION5X_ETH_SUM, 182 .flags = IORESOURCE_IRQ, 183 }, 184 }; 185 186 static struct platform_device orion5x_eth = { 187 .name = MV643XX_ETH_NAME, 188 .id = 0, 189 .num_resources = 1, 190 .resource = orion5x_eth_resources, 191 }; 192 193 void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data) 194 { 195 eth_data->shared = &orion5x_eth_shared; 196 orion5x_eth.dev.platform_data = eth_data; 197 198 platform_device_register(&orion5x_eth_shared); 199 platform_device_register(&orion5x_eth); 200 } 201 202 203 /***************************************************************************** 204 * Ethernet switch 205 ****************************************************************************/ 206 static struct resource orion5x_switch_resources[] = { 207 { 208 .start = 0, 209 .end = 0, 210 .flags = IORESOURCE_IRQ, 211 }, 212 }; 213 214 static struct platform_device orion5x_switch_device = { 215 .name = "dsa", 216 .id = 0, 217 .num_resources = 0, 218 .resource = orion5x_switch_resources, 219 }; 220 221 void __init orion5x_eth_switch_init(struct dsa_platform_data *d, int irq) 222 { 223 int i; 224 225 if (irq != NO_IRQ) { 226 orion5x_switch_resources[0].start = irq; 227 orion5x_switch_resources[0].end = irq; 228 orion5x_switch_device.num_resources = 1; 229 } 230 231 d->netdev = &orion5x_eth.dev; 232 for (i = 0; i < d->nr_chips; i++) 233 d->chip[i].mii_bus = &orion5x_eth_shared.dev; 234 orion5x_switch_device.dev.platform_data = d; 235 236 platform_device_register(&orion5x_switch_device); 237 } 238 239 240 /***************************************************************************** 241 * I2C 242 ****************************************************************************/ 243 static struct mv64xxx_i2c_pdata orion5x_i2c_pdata = { 244 .freq_m = 8, /* assumes 166 MHz TCLK */ 245 .freq_n = 3, 246 .timeout = 1000, /* Default timeout of 1 second */ 247 }; 248 249 static struct resource orion5x_i2c_resources[] = { 250 { 251 .name = "i2c base", 252 .start = I2C_PHYS_BASE, 253 .end = I2C_PHYS_BASE + 0x1f, 254 .flags = IORESOURCE_MEM, 255 }, { 256 .name = "i2c irq", 257 .start = IRQ_ORION5X_I2C, 258 .end = IRQ_ORION5X_I2C, 259 .flags = IORESOURCE_IRQ, 260 }, 261 }; 262 263 static struct platform_device orion5x_i2c = { 264 .name = MV64XXX_I2C_CTLR_NAME, 265 .id = 0, 266 .num_resources = ARRAY_SIZE(orion5x_i2c_resources), 267 .resource = orion5x_i2c_resources, 268 .dev = { 269 .platform_data = &orion5x_i2c_pdata, 270 }, 271 }; 272 273 void __init orion5x_i2c_init(void) 274 { 275 platform_device_register(&orion5x_i2c); 276 } 277 278 279 /***************************************************************************** 280 * SATA 281 ****************************************************************************/ 282 static struct resource orion5x_sata_resources[] = { 283 { 284 .name = "sata base", 285 .start = ORION5X_SATA_PHYS_BASE, 286 .end = ORION5X_SATA_PHYS_BASE + 0x5000 - 1, 287 .flags = IORESOURCE_MEM, 288 }, { 289 .name = "sata irq", 290 .start = IRQ_ORION5X_SATA, 291 .end = IRQ_ORION5X_SATA, 292 .flags = IORESOURCE_IRQ, 293 }, 294 }; 295 296 static struct platform_device orion5x_sata = { 297 .name = "sata_mv", 298 .id = 0, 299 .dev = { 300 .coherent_dma_mask = 0xffffffff, 301 }, 302 .num_resources = ARRAY_SIZE(orion5x_sata_resources), 303 .resource = orion5x_sata_resources, 304 }; 305 306 void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data) 307 { 308 sata_data->dram = &orion5x_mbus_dram_info; 309 orion5x_sata.dev.platform_data = sata_data; 310 platform_device_register(&orion5x_sata); 311 } 312 313 314 /***************************************************************************** 315 * SPI 316 ****************************************************************************/ 317 static struct orion_spi_info orion5x_spi_plat_data = { 318 .tclk = 0, 319 .enable_clock_fix = 1, 320 }; 321 322 static struct resource orion5x_spi_resources[] = { 323 { 324 .name = "spi base", 325 .start = SPI_PHYS_BASE, 326 .end = SPI_PHYS_BASE + 0x1f, 327 .flags = IORESOURCE_MEM, 328 }, 329 }; 330 331 static struct platform_device orion5x_spi = { 332 .name = "orion_spi", 333 .id = 0, 334 .dev = { 335 .platform_data = &orion5x_spi_plat_data, 336 }, 337 .num_resources = ARRAY_SIZE(orion5x_spi_resources), 338 .resource = orion5x_spi_resources, 339 }; 340 341 void __init orion5x_spi_init() 342 { 343 platform_device_register(&orion5x_spi); 344 } 345 346 347 /***************************************************************************** 348 * UART0 349 ****************************************************************************/ 350 static struct plat_serial8250_port orion5x_uart0_data[] = { 351 { 352 .mapbase = UART0_PHYS_BASE, 353 .membase = (char *)UART0_VIRT_BASE, 354 .irq = IRQ_ORION5X_UART0, 355 .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, 356 .iotype = UPIO_MEM, 357 .regshift = 2, 358 .uartclk = 0, 359 }, { 360 }, 361 }; 362 363 static struct resource orion5x_uart0_resources[] = { 364 { 365 .start = UART0_PHYS_BASE, 366 .end = UART0_PHYS_BASE + 0xff, 367 .flags = IORESOURCE_MEM, 368 }, { 369 .start = IRQ_ORION5X_UART0, 370 .end = IRQ_ORION5X_UART0, 371 .flags = IORESOURCE_IRQ, 372 }, 373 }; 374 375 static struct platform_device orion5x_uart0 = { 376 .name = "serial8250", 377 .id = PLAT8250_DEV_PLATFORM, 378 .dev = { 379 .platform_data = orion5x_uart0_data, 380 }, 381 .resource = orion5x_uart0_resources, 382 .num_resources = ARRAY_SIZE(orion5x_uart0_resources), 383 }; 384 385 void __init orion5x_uart0_init(void) 386 { 387 platform_device_register(&orion5x_uart0); 388 } 389 390 391 /***************************************************************************** 392 * UART1 393 ****************************************************************************/ 394 static struct plat_serial8250_port orion5x_uart1_data[] = { 395 { 396 .mapbase = UART1_PHYS_BASE, 397 .membase = (char *)UART1_VIRT_BASE, 398 .irq = IRQ_ORION5X_UART1, 399 .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, 400 .iotype = UPIO_MEM, 401 .regshift = 2, 402 .uartclk = 0, 403 }, { 404 }, 405 }; 406 407 static struct resource orion5x_uart1_resources[] = { 408 { 409 .start = UART1_PHYS_BASE, 410 .end = UART1_PHYS_BASE + 0xff, 411 .flags = IORESOURCE_MEM, 412 }, { 413 .start = IRQ_ORION5X_UART1, 414 .end = IRQ_ORION5X_UART1, 415 .flags = IORESOURCE_IRQ, 416 }, 417 }; 418 419 static struct platform_device orion5x_uart1 = { 420 .name = "serial8250", 421 .id = PLAT8250_DEV_PLATFORM1, 422 .dev = { 423 .platform_data = orion5x_uart1_data, 424 }, 425 .resource = orion5x_uart1_resources, 426 .num_resources = ARRAY_SIZE(orion5x_uart1_resources), 427 }; 428 429 void __init orion5x_uart1_init(void) 430 { 431 platform_device_register(&orion5x_uart1); 432 } 433 434 435 /***************************************************************************** 436 * XOR engine 437 ****************************************************************************/ 438 struct mv_xor_platform_shared_data orion5x_xor_shared_data = { 439 .dram = &orion5x_mbus_dram_info, 440 }; 441 442 static struct resource orion5x_xor_shared_resources[] = { 443 { 444 .name = "xor low", 445 .start = ORION5X_XOR_PHYS_BASE, 446 .end = ORION5X_XOR_PHYS_BASE + 0xff, 447 .flags = IORESOURCE_MEM, 448 }, { 449 .name = "xor high", 450 .start = ORION5X_XOR_PHYS_BASE + 0x200, 451 .end = ORION5X_XOR_PHYS_BASE + 0x2ff, 452 .flags = IORESOURCE_MEM, 453 }, 454 }; 455 456 static struct platform_device orion5x_xor_shared = { 457 .name = MV_XOR_SHARED_NAME, 458 .id = 0, 459 .dev = { 460 .platform_data = &orion5x_xor_shared_data, 461 }, 462 .num_resources = ARRAY_SIZE(orion5x_xor_shared_resources), 463 .resource = orion5x_xor_shared_resources, 464 }; 465 466 static u64 orion5x_xor_dmamask = DMA_BIT_MASK(32); 467 468 static struct resource orion5x_xor0_resources[] = { 469 [0] = { 470 .start = IRQ_ORION5X_XOR0, 471 .end = IRQ_ORION5X_XOR0, 472 .flags = IORESOURCE_IRQ, 473 }, 474 }; 475 476 static struct mv_xor_platform_data orion5x_xor0_data = { 477 .shared = &orion5x_xor_shared, 478 .hw_id = 0, 479 .pool_size = PAGE_SIZE, 480 }; 481 482 static struct platform_device orion5x_xor0_channel = { 483 .name = MV_XOR_NAME, 484 .id = 0, 485 .num_resources = ARRAY_SIZE(orion5x_xor0_resources), 486 .resource = orion5x_xor0_resources, 487 .dev = { 488 .dma_mask = &orion5x_xor_dmamask, 489 .coherent_dma_mask = DMA_BIT_MASK(64), 490 .platform_data = (void *)&orion5x_xor0_data, 491 }, 492 }; 493 494 static struct resource orion5x_xor1_resources[] = { 495 [0] = { 496 .start = IRQ_ORION5X_XOR1, 497 .end = IRQ_ORION5X_XOR1, 498 .flags = IORESOURCE_IRQ, 499 }, 500 }; 501 502 static struct mv_xor_platform_data orion5x_xor1_data = { 503 .shared = &orion5x_xor_shared, 504 .hw_id = 1, 505 .pool_size = PAGE_SIZE, 506 }; 507 508 static struct platform_device orion5x_xor1_channel = { 509 .name = MV_XOR_NAME, 510 .id = 1, 511 .num_resources = ARRAY_SIZE(orion5x_xor1_resources), 512 .resource = orion5x_xor1_resources, 513 .dev = { 514 .dma_mask = &orion5x_xor_dmamask, 515 .coherent_dma_mask = DMA_BIT_MASK(64), 516 .platform_data = (void *)&orion5x_xor1_data, 517 }, 518 }; 519 520 void __init orion5x_xor_init(void) 521 { 522 platform_device_register(&orion5x_xor_shared); 523 524 /* 525 * two engines can't do memset simultaneously, this limitation 526 * satisfied by removing memset support from one of the engines. 527 */ 528 dma_cap_set(DMA_MEMCPY, orion5x_xor0_data.cap_mask); 529 dma_cap_set(DMA_XOR, orion5x_xor0_data.cap_mask); 530 platform_device_register(&orion5x_xor0_channel); 531 532 dma_cap_set(DMA_MEMCPY, orion5x_xor1_data.cap_mask); 533 dma_cap_set(DMA_MEMSET, orion5x_xor1_data.cap_mask); 534 dma_cap_set(DMA_XOR, orion5x_xor1_data.cap_mask); 535 platform_device_register(&orion5x_xor1_channel); 536 } 537 538 539 /***************************************************************************** 540 * Watchdog 541 ****************************************************************************/ 542 static struct orion5x_wdt_platform_data orion5x_wdt_data = { 543 .tclk = 0, 544 }; 545 546 static struct platform_device orion5x_wdt_device = { 547 .name = "orion5x_wdt", 548 .id = -1, 549 .dev = { 550 .platform_data = &orion5x_wdt_data, 551 }, 552 .num_resources = 0, 553 }; 554 555 void __init orion5x_wdt_init(void) 556 { 557 orion5x_wdt_data.tclk = orion5x_tclk; 558 platform_device_register(&orion5x_wdt_device); 559 } 560 561 562 /***************************************************************************** 563 * Time handling 564 ****************************************************************************/ 565 int orion5x_tclk; 566 567 int __init orion5x_find_tclk(void) 568 { 569 u32 dev, rev; 570 571 orion5x_pcie_id(&dev, &rev); 572 if (dev == MV88F6183_DEV_ID && 573 (readl(MPP_RESET_SAMPLE) & 0x00000200) == 0) 574 return 133333333; 575 576 return 166666667; 577 } 578 579 static void orion5x_timer_init(void) 580 { 581 orion5x_tclk = orion5x_find_tclk(); 582 orion_time_init(IRQ_ORION5X_BRIDGE, orion5x_tclk); 583 } 584 585 struct sys_timer orion5x_timer = { 586 .init = orion5x_timer_init, 587 }; 588 589 590 /***************************************************************************** 591 * General 592 ****************************************************************************/ 593 /* 594 * Identify device ID and rev from PCIe configuration header space '0'. 595 */ 596 static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name) 597 { 598 orion5x_pcie_id(dev, rev); 599 600 if (*dev == MV88F5281_DEV_ID) { 601 if (*rev == MV88F5281_REV_D2) { 602 *dev_name = "MV88F5281-D2"; 603 } else if (*rev == MV88F5281_REV_D1) { 604 *dev_name = "MV88F5281-D1"; 605 } else if (*rev == MV88F5281_REV_D0) { 606 *dev_name = "MV88F5281-D0"; 607 } else { 608 *dev_name = "MV88F5281-Rev-Unsupported"; 609 } 610 } else if (*dev == MV88F5182_DEV_ID) { 611 if (*rev == MV88F5182_REV_A2) { 612 *dev_name = "MV88F5182-A2"; 613 } else { 614 *dev_name = "MV88F5182-Rev-Unsupported"; 615 } 616 } else if (*dev == MV88F5181_DEV_ID) { 617 if (*rev == MV88F5181_REV_B1) { 618 *dev_name = "MV88F5181-Rev-B1"; 619 } else if (*rev == MV88F5181L_REV_A1) { 620 *dev_name = "MV88F5181L-Rev-A1"; 621 } else { 622 *dev_name = "MV88F5181(L)-Rev-Unsupported"; 623 } 624 } else if (*dev == MV88F6183_DEV_ID) { 625 if (*rev == MV88F6183_REV_B0) { 626 *dev_name = "MV88F6183-Rev-B0"; 627 } else { 628 *dev_name = "MV88F6183-Rev-Unsupported"; 629 } 630 } else { 631 *dev_name = "Device-Unknown"; 632 } 633 } 634 635 void __init orion5x_init(void) 636 { 637 char *dev_name; 638 u32 dev, rev; 639 640 orion5x_id(&dev, &rev, &dev_name); 641 printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, orion5x_tclk); 642 643 orion5x_eth_shared_data.t_clk = orion5x_tclk; 644 orion5x_spi_plat_data.tclk = orion5x_tclk; 645 orion5x_uart0_data[0].uartclk = orion5x_tclk; 646 orion5x_uart1_data[0].uartclk = orion5x_tclk; 647 648 /* 649 * Setup Orion address map 650 */ 651 orion5x_setup_cpu_mbus_bridge(); 652 653 /* 654 * Don't issue "Wait for Interrupt" instruction if we are 655 * running on D0 5281 silicon. 656 */ 657 if (dev == MV88F5281_DEV_ID && rev == MV88F5281_REV_D0) { 658 printk(KERN_INFO "Orion: Applying 5281 D0 WFI workaround.\n"); 659 disable_hlt(); 660 } 661 662 /* 663 * Register watchdog driver 664 */ 665 orion5x_wdt_init(); 666 } 667 668 /* 669 * Many orion-based systems have buggy bootloader implementations. 670 * This is a common fixup for bogus memory tags. 671 */ 672 void __init tag_fixup_mem32(struct machine_desc *mdesc, struct tag *t, 673 char **from, struct meminfo *meminfo) 674 { 675 for (; t->hdr.size; t = tag_next(t)) 676 if (t->hdr.tag == ATAG_MEM && 677 (!t->u.mem.size || t->u.mem.size & ~PAGE_MASK || 678 t->u.mem.start & ~PAGE_MASK)) { 679 printk(KERN_WARNING 680 "Clearing invalid memory bank %dKB@0x%08x\n", 681 t->u.mem.size / 1024, t->u.mem.start); 682 t->hdr.tag = 0; 683 } 684 } 685