1 /* 2 * arch/arm/mach-orion5x/ts78xx-setup.c 3 * 4 * Maintainer: Alexander Clouter <alex@digriz.org.uk> 5 * 6 * This file is licensed under the terms of the GNU General Public 7 * License version 2. This program is licensed "as is" without any 8 * warranty of any kind, whether express or implied. 9 */ 10 11 #include <linux/kernel.h> 12 #include <linux/init.h> 13 #include <linux/sysfs.h> 14 #include <linux/platform_device.h> 15 #include <linux/mv643xx_eth.h> 16 #include <linux/ata_platform.h> 17 #include <linux/m48t86.h> 18 #include <linux/mtd/nand.h> 19 #include <linux/mtd/partitions.h> 20 #include <linux/timeriomem-rng.h> 21 #include <asm/mach-types.h> 22 #include <asm/mach/arch.h> 23 #include <asm/mach/map.h> 24 #include <mach/orion5x.h> 25 #include "common.h" 26 #include "mpp.h" 27 #include "ts78xx-fpga.h" 28 29 /***************************************************************************** 30 * TS-78xx Info 31 ****************************************************************************/ 32 33 /* 34 * FPGA - lives where the PCI bus would be at ORION5X_PCI_MEM_PHYS_BASE 35 */ 36 #define TS78XX_FPGA_REGS_PHYS_BASE 0xe8000000 37 #define TS78XX_FPGA_REGS_VIRT_BASE 0xff900000 38 #define TS78XX_FPGA_REGS_SIZE SZ_1M 39 40 static struct ts78xx_fpga_data ts78xx_fpga = { 41 .id = 0, 42 .state = 1, 43 /* .supports = ... - populated by ts78xx_fpga_supports() */ 44 }; 45 46 /***************************************************************************** 47 * I/O Address Mapping 48 ****************************************************************************/ 49 static struct map_desc ts78xx_io_desc[] __initdata = { 50 { 51 .virtual = TS78XX_FPGA_REGS_VIRT_BASE, 52 .pfn = __phys_to_pfn(TS78XX_FPGA_REGS_PHYS_BASE), 53 .length = TS78XX_FPGA_REGS_SIZE, 54 .type = MT_DEVICE, 55 }, 56 }; 57 58 void __init ts78xx_map_io(void) 59 { 60 orion5x_map_io(); 61 iotable_init(ts78xx_io_desc, ARRAY_SIZE(ts78xx_io_desc)); 62 } 63 64 /***************************************************************************** 65 * Ethernet 66 ****************************************************************************/ 67 static struct mv643xx_eth_platform_data ts78xx_eth_data = { 68 .phy_addr = MV643XX_ETH_PHY_ADDR(0), 69 }; 70 71 /***************************************************************************** 72 * SATA 73 ****************************************************************************/ 74 static struct mv_sata_platform_data ts78xx_sata_data = { 75 .n_ports = 2, 76 }; 77 78 /***************************************************************************** 79 * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c 80 ****************************************************************************/ 81 #define TS_RTC_CTRL (TS78XX_FPGA_REGS_VIRT_BASE | 0x808) 82 #define TS_RTC_DATA (TS78XX_FPGA_REGS_VIRT_BASE | 0x80c) 83 84 static unsigned char ts78xx_ts_rtc_readbyte(unsigned long addr) 85 { 86 writeb(addr, TS_RTC_CTRL); 87 return readb(TS_RTC_DATA); 88 } 89 90 static void ts78xx_ts_rtc_writebyte(unsigned char value, unsigned long addr) 91 { 92 writeb(addr, TS_RTC_CTRL); 93 writeb(value, TS_RTC_DATA); 94 } 95 96 static struct m48t86_ops ts78xx_ts_rtc_ops = { 97 .readbyte = ts78xx_ts_rtc_readbyte, 98 .writebyte = ts78xx_ts_rtc_writebyte, 99 }; 100 101 static struct platform_device ts78xx_ts_rtc_device = { 102 .name = "rtc-m48t86", 103 .id = -1, 104 .dev = { 105 .platform_data = &ts78xx_ts_rtc_ops, 106 }, 107 .num_resources = 0, 108 }; 109 110 /* 111 * TS uses some of the user storage space on the RTC chip so see if it is 112 * present; as it's an optional feature at purchase time and not all boards 113 * will have it present 114 * 115 * I've used the method TS use in their rtc7800.c example for the detection 116 * 117 * TODO: track down a guinea pig without an RTC to see if we can work out a 118 * better RTC detection routine 119 */ 120 static int ts78xx_ts_rtc_load(void) 121 { 122 int rc; 123 unsigned char tmp_rtc0, tmp_rtc1; 124 125 tmp_rtc0 = ts78xx_ts_rtc_readbyte(126); 126 tmp_rtc1 = ts78xx_ts_rtc_readbyte(127); 127 128 ts78xx_ts_rtc_writebyte(0x00, 126); 129 ts78xx_ts_rtc_writebyte(0x55, 127); 130 if (ts78xx_ts_rtc_readbyte(127) == 0x55) { 131 ts78xx_ts_rtc_writebyte(0xaa, 127); 132 if (ts78xx_ts_rtc_readbyte(127) == 0xaa 133 && ts78xx_ts_rtc_readbyte(126) == 0x00) { 134 ts78xx_ts_rtc_writebyte(tmp_rtc0, 126); 135 ts78xx_ts_rtc_writebyte(tmp_rtc1, 127); 136 137 if (ts78xx_fpga.supports.ts_rtc.init == 0) { 138 rc = platform_device_register(&ts78xx_ts_rtc_device); 139 if (!rc) 140 ts78xx_fpga.supports.ts_rtc.init = 1; 141 } else 142 rc = platform_device_add(&ts78xx_ts_rtc_device); 143 144 return rc; 145 } 146 } 147 148 return -ENODEV; 149 }; 150 151 static void ts78xx_ts_rtc_unload(void) 152 { 153 platform_device_del(&ts78xx_ts_rtc_device); 154 } 155 156 /***************************************************************************** 157 * NAND Flash 158 ****************************************************************************/ 159 #define TS_NAND_CTRL (TS78XX_FPGA_REGS_VIRT_BASE | 0x800) /* VIRT */ 160 #define TS_NAND_DATA (TS78XX_FPGA_REGS_PHYS_BASE | 0x804) /* PHYS */ 161 162 /* 163 * hardware specific access to control-lines 164 * 165 * ctrl: 166 * NAND_NCE: bit 0 -> bit 2 167 * NAND_CLE: bit 1 -> bit 1 168 * NAND_ALE: bit 2 -> bit 0 169 */ 170 static void ts78xx_ts_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, 171 unsigned int ctrl) 172 { 173 struct nand_chip *this = mtd->priv; 174 175 if (ctrl & NAND_CTRL_CHANGE) { 176 unsigned char bits; 177 178 bits = (ctrl & NAND_NCE) << 2; 179 bits |= ctrl & NAND_CLE; 180 bits |= (ctrl & NAND_ALE) >> 2; 181 182 writeb((readb(TS_NAND_CTRL) & ~0x7) | bits, TS_NAND_CTRL); 183 } 184 185 if (cmd != NAND_CMD_NONE) 186 writeb(cmd, this->IO_ADDR_W); 187 } 188 189 static int ts78xx_ts_nand_dev_ready(struct mtd_info *mtd) 190 { 191 return readb(TS_NAND_CTRL) & 0x20; 192 } 193 194 static void ts78xx_ts_nand_write_buf(struct mtd_info *mtd, 195 const uint8_t *buf, int len) 196 { 197 struct nand_chip *chip = mtd->priv; 198 void __iomem *io_base = chip->IO_ADDR_W; 199 unsigned long off = ((unsigned long)buf & 3); 200 int sz; 201 202 if (off) { 203 sz = min_t(int, 4 - off, len); 204 writesb(io_base, buf, sz); 205 buf += sz; 206 len -= sz; 207 } 208 209 sz = len >> 2; 210 if (sz) { 211 u32 *buf32 = (u32 *)buf; 212 writesl(io_base, buf32, sz); 213 buf += sz << 2; 214 len -= sz << 2; 215 } 216 217 if (len) 218 writesb(io_base, buf, len); 219 } 220 221 static void ts78xx_ts_nand_read_buf(struct mtd_info *mtd, 222 uint8_t *buf, int len) 223 { 224 struct nand_chip *chip = mtd->priv; 225 void __iomem *io_base = chip->IO_ADDR_R; 226 unsigned long off = ((unsigned long)buf & 3); 227 int sz; 228 229 if (off) { 230 sz = min_t(int, 4 - off, len); 231 readsb(io_base, buf, sz); 232 buf += sz; 233 len -= sz; 234 } 235 236 sz = len >> 2; 237 if (sz) { 238 u32 *buf32 = (u32 *)buf; 239 readsl(io_base, buf32, sz); 240 buf += sz << 2; 241 len -= sz << 2; 242 } 243 244 if (len) 245 readsb(io_base, buf, len); 246 } 247 248 const char *ts_nand_part_probes[] = { "cmdlinepart", NULL }; 249 250 static struct mtd_partition ts78xx_ts_nand_parts[] = { 251 { 252 .name = "mbr", 253 .offset = 0, 254 .size = SZ_128K, 255 .mask_flags = MTD_WRITEABLE, 256 }, { 257 .name = "kernel", 258 .offset = MTDPART_OFS_APPEND, 259 .size = SZ_4M, 260 }, { 261 .name = "initrd", 262 .offset = MTDPART_OFS_APPEND, 263 .size = SZ_4M, 264 }, { 265 .name = "rootfs", 266 .offset = MTDPART_OFS_APPEND, 267 .size = MTDPART_SIZ_FULL, 268 } 269 }; 270 271 static struct platform_nand_data ts78xx_ts_nand_data = { 272 .chip = { 273 .nr_chips = 1, 274 .part_probe_types = ts_nand_part_probes, 275 .partitions = ts78xx_ts_nand_parts, 276 .nr_partitions = ARRAY_SIZE(ts78xx_ts_nand_parts), 277 .chip_delay = 15, 278 .bbt_options = NAND_BBT_USE_FLASH, 279 }, 280 .ctrl = { 281 /* 282 * The HW ECC offloading functions, used to give about a 9% 283 * performance increase for 'dd if=/dev/mtdblockX' and 5% for 284 * nanddump. This all however was changed by git commit 285 * e6cf5df1838c28bb060ac45b5585e48e71bbc740 so now there is 286 * no performance advantage to be had so we no longer bother 287 */ 288 .cmd_ctrl = ts78xx_ts_nand_cmd_ctrl, 289 .dev_ready = ts78xx_ts_nand_dev_ready, 290 .write_buf = ts78xx_ts_nand_write_buf, 291 .read_buf = ts78xx_ts_nand_read_buf, 292 }, 293 }; 294 295 static struct resource ts78xx_ts_nand_resources = { 296 .start = TS_NAND_DATA, 297 .end = TS_NAND_DATA + 4, 298 .flags = IORESOURCE_MEM, 299 }; 300 301 static struct platform_device ts78xx_ts_nand_device = { 302 .name = "gen_nand", 303 .id = -1, 304 .dev = { 305 .platform_data = &ts78xx_ts_nand_data, 306 }, 307 .resource = &ts78xx_ts_nand_resources, 308 .num_resources = 1, 309 }; 310 311 static int ts78xx_ts_nand_load(void) 312 { 313 int rc; 314 315 if (ts78xx_fpga.supports.ts_nand.init == 0) { 316 rc = platform_device_register(&ts78xx_ts_nand_device); 317 if (!rc) 318 ts78xx_fpga.supports.ts_nand.init = 1; 319 } else 320 rc = platform_device_add(&ts78xx_ts_nand_device); 321 322 return rc; 323 }; 324 325 static void ts78xx_ts_nand_unload(void) 326 { 327 platform_device_del(&ts78xx_ts_nand_device); 328 } 329 330 /***************************************************************************** 331 * HW RNG 332 ****************************************************************************/ 333 #define TS_RNG_DATA (TS78XX_FPGA_REGS_PHYS_BASE | 0x044) 334 335 static struct resource ts78xx_ts_rng_resource = { 336 .flags = IORESOURCE_MEM, 337 .start = TS_RNG_DATA, 338 .end = TS_RNG_DATA + 4 - 1, 339 }; 340 341 static struct timeriomem_rng_data ts78xx_ts_rng_data = { 342 .period = 1000000, /* one second */ 343 }; 344 345 static struct platform_device ts78xx_ts_rng_device = { 346 .name = "timeriomem_rng", 347 .id = -1, 348 .dev = { 349 .platform_data = &ts78xx_ts_rng_data, 350 }, 351 .resource = &ts78xx_ts_rng_resource, 352 .num_resources = 1, 353 }; 354 355 static int ts78xx_ts_rng_load(void) 356 { 357 int rc; 358 359 if (ts78xx_fpga.supports.ts_rng.init == 0) { 360 rc = platform_device_register(&ts78xx_ts_rng_device); 361 if (!rc) 362 ts78xx_fpga.supports.ts_rng.init = 1; 363 } else 364 rc = platform_device_add(&ts78xx_ts_rng_device); 365 366 return rc; 367 }; 368 369 static void ts78xx_ts_rng_unload(void) 370 { 371 platform_device_del(&ts78xx_ts_rng_device); 372 } 373 374 /***************************************************************************** 375 * FPGA 'hotplug' support code 376 ****************************************************************************/ 377 static void ts78xx_fpga_devices_zero_init(void) 378 { 379 ts78xx_fpga.supports.ts_rtc.init = 0; 380 ts78xx_fpga.supports.ts_nand.init = 0; 381 ts78xx_fpga.supports.ts_rng.init = 0; 382 } 383 384 static void ts78xx_fpga_supports(void) 385 { 386 /* TODO: put this 'table' into ts78xx-fpga.h */ 387 switch (ts78xx_fpga.id) { 388 case TS7800_REV_1: 389 case TS7800_REV_2: 390 case TS7800_REV_3: 391 case TS7800_REV_4: 392 case TS7800_REV_5: 393 case TS7800_REV_6: 394 case TS7800_REV_7: 395 case TS7800_REV_8: 396 case TS7800_REV_9: 397 ts78xx_fpga.supports.ts_rtc.present = 1; 398 ts78xx_fpga.supports.ts_nand.present = 1; 399 ts78xx_fpga.supports.ts_rng.present = 1; 400 break; 401 default: 402 /* enable devices if magic matches */ 403 switch ((ts78xx_fpga.id >> 8) & 0xffffff) { 404 case TS7800_FPGA_MAGIC: 405 pr_warning("TS-7800 FPGA: unrecognized revision 0x%.2x\n", 406 ts78xx_fpga.id & 0xff); 407 ts78xx_fpga.supports.ts_rtc.present = 1; 408 ts78xx_fpga.supports.ts_nand.present = 1; 409 ts78xx_fpga.supports.ts_rng.present = 1; 410 break; 411 default: 412 ts78xx_fpga.supports.ts_rtc.present = 0; 413 ts78xx_fpga.supports.ts_nand.present = 0; 414 ts78xx_fpga.supports.ts_rng.present = 0; 415 } 416 } 417 } 418 419 static int ts78xx_fpga_load_devices(void) 420 { 421 int tmp, ret = 0; 422 423 if (ts78xx_fpga.supports.ts_rtc.present == 1) { 424 tmp = ts78xx_ts_rtc_load(); 425 if (tmp) { 426 pr_info("TS-78xx: RTC not registered\n"); 427 ts78xx_fpga.supports.ts_rtc.present = 0; 428 } 429 ret |= tmp; 430 } 431 if (ts78xx_fpga.supports.ts_nand.present == 1) { 432 tmp = ts78xx_ts_nand_load(); 433 if (tmp) { 434 pr_info("TS-78xx: NAND not registered\n"); 435 ts78xx_fpga.supports.ts_nand.present = 0; 436 } 437 ret |= tmp; 438 } 439 if (ts78xx_fpga.supports.ts_rng.present == 1) { 440 tmp = ts78xx_ts_rng_load(); 441 if (tmp) { 442 pr_info("TS-78xx: RNG not registered\n"); 443 ts78xx_fpga.supports.ts_rng.present = 0; 444 } 445 ret |= tmp; 446 } 447 448 return ret; 449 } 450 451 static int ts78xx_fpga_unload_devices(void) 452 { 453 int ret = 0; 454 455 if (ts78xx_fpga.supports.ts_rtc.present == 1) 456 ts78xx_ts_rtc_unload(); 457 if (ts78xx_fpga.supports.ts_nand.present == 1) 458 ts78xx_ts_nand_unload(); 459 if (ts78xx_fpga.supports.ts_rng.present == 1) 460 ts78xx_ts_rng_unload(); 461 462 return ret; 463 } 464 465 static int ts78xx_fpga_load(void) 466 { 467 ts78xx_fpga.id = readl(TS78XX_FPGA_REGS_VIRT_BASE); 468 469 pr_info("TS-78xx FPGA: magic=0x%.6x, rev=0x%.2x\n", 470 (ts78xx_fpga.id >> 8) & 0xffffff, 471 ts78xx_fpga.id & 0xff); 472 473 ts78xx_fpga_supports(); 474 475 if (ts78xx_fpga_load_devices()) { 476 ts78xx_fpga.state = -1; 477 return -EBUSY; 478 } 479 480 return 0; 481 }; 482 483 static int ts78xx_fpga_unload(void) 484 { 485 unsigned int fpga_id; 486 487 fpga_id = readl(TS78XX_FPGA_REGS_VIRT_BASE); 488 489 /* 490 * There does not seem to be a feasible way to block access to the GPIO 491 * pins from userspace (/dev/mem). This if clause should hopefully warn 492 * those foolish enough not to follow 'policy' :) 493 * 494 * UrJTAG SVN since r1381 can be used to reprogram the FPGA 495 */ 496 if (ts78xx_fpga.id != fpga_id) { 497 pr_err("TS-78xx FPGA: magic/rev mismatch\n" 498 "TS-78xx FPGA: was 0x%.6x/%.2x but now 0x%.6x/%.2x\n", 499 (ts78xx_fpga.id >> 8) & 0xffffff, ts78xx_fpga.id & 0xff, 500 (fpga_id >> 8) & 0xffffff, fpga_id & 0xff); 501 ts78xx_fpga.state = -1; 502 return -EBUSY; 503 } 504 505 if (ts78xx_fpga_unload_devices()) { 506 ts78xx_fpga.state = -1; 507 return -EBUSY; 508 } 509 510 return 0; 511 }; 512 513 static ssize_t ts78xx_fpga_show(struct kobject *kobj, 514 struct kobj_attribute *attr, char *buf) 515 { 516 if (ts78xx_fpga.state < 0) 517 return sprintf(buf, "borked\n"); 518 519 return sprintf(buf, "%s\n", (ts78xx_fpga.state) ? "online" : "offline"); 520 } 521 522 static ssize_t ts78xx_fpga_store(struct kobject *kobj, 523 struct kobj_attribute *attr, const char *buf, size_t n) 524 { 525 int value, ret; 526 527 if (ts78xx_fpga.state < 0) { 528 pr_err("TS-78xx FPGA: borked, you must powercycle asap\n"); 529 return -EBUSY; 530 } 531 532 if (strncmp(buf, "online", sizeof("online") - 1) == 0) 533 value = 1; 534 else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) 535 value = 0; 536 else { 537 pr_err("ts78xx_fpga_store: Invalid value\n"); 538 return -EINVAL; 539 } 540 541 if (ts78xx_fpga.state == value) 542 return n; 543 544 ret = (ts78xx_fpga.state == 0) 545 ? ts78xx_fpga_load() 546 : ts78xx_fpga_unload(); 547 548 if (!(ret < 0)) 549 ts78xx_fpga.state = value; 550 551 return n; 552 } 553 554 static struct kobj_attribute ts78xx_fpga_attr = 555 __ATTR(ts78xx_fpga, 0644, ts78xx_fpga_show, ts78xx_fpga_store); 556 557 /***************************************************************************** 558 * General Setup 559 ****************************************************************************/ 560 static unsigned int ts78xx_mpp_modes[] __initdata = { 561 MPP0_UNUSED, 562 MPP1_GPIO, /* JTAG Clock */ 563 MPP2_GPIO, /* JTAG Data In */ 564 MPP3_GPIO, /* Lat ECP2 256 FPGA - PB2B */ 565 MPP4_GPIO, /* JTAG Data Out */ 566 MPP5_GPIO, /* JTAG TMS */ 567 MPP6_GPIO, /* Lat ECP2 256 FPGA - PB31A_CLK4+ */ 568 MPP7_GPIO, /* Lat ECP2 256 FPGA - PB22B */ 569 MPP8_UNUSED, 570 MPP9_UNUSED, 571 MPP10_UNUSED, 572 MPP11_UNUSED, 573 MPP12_UNUSED, 574 MPP13_UNUSED, 575 MPP14_UNUSED, 576 MPP15_UNUSED, 577 MPP16_UART, 578 MPP17_UART, 579 MPP18_UART, 580 MPP19_UART, 581 /* 582 * MPP[20] PCI Clock Out 1 583 * MPP[21] PCI Clock Out 0 584 * MPP[22] Unused 585 * MPP[23] Unused 586 * MPP[24] Unused 587 * MPP[25] Unused 588 */ 589 0, 590 }; 591 592 static void __init ts78xx_init(void) 593 { 594 int ret; 595 596 /* 597 * Setup basic Orion functions. Need to be called early. 598 */ 599 orion5x_init(); 600 601 orion5x_mpp_conf(ts78xx_mpp_modes); 602 603 /* 604 * Configure peripherals. 605 */ 606 orion5x_ehci0_init(); 607 orion5x_ehci1_init(); 608 orion5x_eth_init(&ts78xx_eth_data); 609 orion5x_sata_init(&ts78xx_sata_data); 610 orion5x_uart0_init(); 611 orion5x_uart1_init(); 612 orion5x_xor_init(); 613 614 /* FPGA init */ 615 ts78xx_fpga_devices_zero_init(); 616 ret = ts78xx_fpga_load(); 617 ret = sysfs_create_file(power_kobj, &ts78xx_fpga_attr.attr); 618 if (ret) 619 pr_err("sysfs_create_file failed: %d\n", ret); 620 } 621 622 MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC") 623 /* Maintainer: Alexander Clouter <alex@digriz.org.uk> */ 624 .atag_offset = 0x100, 625 .init_machine = ts78xx_init, 626 .map_io = ts78xx_map_io, 627 .init_early = orion5x_init_early, 628 .init_irq = orion5x_init_irq, 629 .timer = &orion5x_timer, 630 .restart = orion5x_restart, 631 MACHINE_END 632