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