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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12 13 #include <linux/kernel.h> 14 #include <linux/init.h> 15 #include <linux/sysfs.h> 16 #include <linux/platform_device.h> 17 #include <linux/mv643xx_eth.h> 18 #include <linux/ata_platform.h> 19 #include <linux/mtd/platnand.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 "common.h" 25 #include "mpp.h" 26 #include "orion5x.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 IOMEM(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 = (unsigned long)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 static 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_PHYS_BASE + 0x808) 82 #define TS_RTC_DATA (TS78XX_FPGA_REGS_PHYS_BASE + 0x80c) 83 84 static struct resource ts78xx_ts_rtc_resources[] = { 85 DEFINE_RES_MEM(TS_RTC_CTRL, 0x01), 86 DEFINE_RES_MEM(TS_RTC_DATA, 0x01), 87 }; 88 89 static struct platform_device ts78xx_ts_rtc_device = { 90 .name = "rtc-m48t86", 91 .id = -1, 92 .resource = ts78xx_ts_rtc_resources, 93 .num_resources = ARRAY_SIZE(ts78xx_ts_rtc_resources), 94 }; 95 96 static int ts78xx_ts_rtc_load(void) 97 { 98 int rc; 99 100 if (ts78xx_fpga.supports.ts_rtc.init == 0) { 101 rc = platform_device_register(&ts78xx_ts_rtc_device); 102 if (!rc) 103 ts78xx_fpga.supports.ts_rtc.init = 1; 104 } else { 105 rc = platform_device_add(&ts78xx_ts_rtc_device); 106 } 107 108 if (rc) 109 pr_info("RTC could not be registered: %d\n", rc); 110 111 return rc; 112 } 113 114 static void ts78xx_ts_rtc_unload(void) 115 { 116 platform_device_del(&ts78xx_ts_rtc_device); 117 } 118 119 /***************************************************************************** 120 * NAND Flash 121 ****************************************************************************/ 122 #define TS_NAND_CTRL (TS78XX_FPGA_REGS_VIRT_BASE + 0x800) /* VIRT */ 123 #define TS_NAND_DATA (TS78XX_FPGA_REGS_PHYS_BASE + 0x804) /* PHYS */ 124 125 /* 126 * hardware specific access to control-lines 127 * 128 * ctrl: 129 * NAND_NCE: bit 0 -> bit 2 130 * NAND_CLE: bit 1 -> bit 1 131 * NAND_ALE: bit 2 -> bit 0 132 */ 133 static void ts78xx_ts_nand_cmd_ctrl(struct nand_chip *this, int cmd, 134 unsigned int ctrl) 135 { 136 if (ctrl & NAND_CTRL_CHANGE) { 137 unsigned char bits; 138 139 bits = (ctrl & NAND_NCE) << 2; 140 bits |= ctrl & NAND_CLE; 141 bits |= (ctrl & NAND_ALE) >> 2; 142 143 writeb((readb(TS_NAND_CTRL) & ~0x7) | bits, TS_NAND_CTRL); 144 } 145 146 if (cmd != NAND_CMD_NONE) 147 writeb(cmd, this->legacy.IO_ADDR_W); 148 } 149 150 static int ts78xx_ts_nand_dev_ready(struct nand_chip *chip) 151 { 152 return readb(TS_NAND_CTRL) & 0x20; 153 } 154 155 static void ts78xx_ts_nand_write_buf(struct nand_chip *chip, 156 const uint8_t *buf, int len) 157 { 158 void __iomem *io_base = chip->legacy.IO_ADDR_W; 159 unsigned long off = ((unsigned long)buf & 3); 160 int sz; 161 162 if (off) { 163 sz = min_t(int, 4 - off, len); 164 writesb(io_base, buf, sz); 165 buf += sz; 166 len -= sz; 167 } 168 169 sz = len >> 2; 170 if (sz) { 171 u32 *buf32 = (u32 *)buf; 172 writesl(io_base, buf32, sz); 173 buf += sz << 2; 174 len -= sz << 2; 175 } 176 177 if (len) 178 writesb(io_base, buf, len); 179 } 180 181 static void ts78xx_ts_nand_read_buf(struct nand_chip *chip, 182 uint8_t *buf, int len) 183 { 184 void __iomem *io_base = chip->legacy.IO_ADDR_R; 185 unsigned long off = ((unsigned long)buf & 3); 186 int sz; 187 188 if (off) { 189 sz = min_t(int, 4 - off, len); 190 readsb(io_base, buf, sz); 191 buf += sz; 192 len -= sz; 193 } 194 195 sz = len >> 2; 196 if (sz) { 197 u32 *buf32 = (u32 *)buf; 198 readsl(io_base, buf32, sz); 199 buf += sz << 2; 200 len -= sz << 2; 201 } 202 203 if (len) 204 readsb(io_base, buf, len); 205 } 206 207 static struct mtd_partition ts78xx_ts_nand_parts[] = { 208 { 209 .name = "mbr", 210 .offset = 0, 211 .size = SZ_128K, 212 .mask_flags = MTD_WRITEABLE, 213 }, { 214 .name = "kernel", 215 .offset = MTDPART_OFS_APPEND, 216 .size = SZ_4M, 217 }, { 218 .name = "initrd", 219 .offset = MTDPART_OFS_APPEND, 220 .size = SZ_4M, 221 }, { 222 .name = "rootfs", 223 .offset = MTDPART_OFS_APPEND, 224 .size = MTDPART_SIZ_FULL, 225 } 226 }; 227 228 static struct platform_nand_data ts78xx_ts_nand_data = { 229 .chip = { 230 .nr_chips = 1, 231 .partitions = ts78xx_ts_nand_parts, 232 .nr_partitions = ARRAY_SIZE(ts78xx_ts_nand_parts), 233 .chip_delay = 15, 234 .bbt_options = NAND_BBT_USE_FLASH, 235 }, 236 .ctrl = { 237 /* 238 * The HW ECC offloading functions, used to give about a 9% 239 * performance increase for 'dd if=/dev/mtdblockX' and 5% for 240 * nanddump. This all however was changed by git commit 241 * e6cf5df1838c28bb060ac45b5585e48e71bbc740 so now there is 242 * no performance advantage to be had so we no longer bother 243 */ 244 .cmd_ctrl = ts78xx_ts_nand_cmd_ctrl, 245 .dev_ready = ts78xx_ts_nand_dev_ready, 246 .write_buf = ts78xx_ts_nand_write_buf, 247 .read_buf = ts78xx_ts_nand_read_buf, 248 }, 249 }; 250 251 static struct resource ts78xx_ts_nand_resources 252 = DEFINE_RES_MEM(TS_NAND_DATA, 4); 253 254 static struct platform_device ts78xx_ts_nand_device = { 255 .name = "gen_nand", 256 .id = -1, 257 .dev = { 258 .platform_data = &ts78xx_ts_nand_data, 259 }, 260 .resource = &ts78xx_ts_nand_resources, 261 .num_resources = 1, 262 }; 263 264 static int ts78xx_ts_nand_load(void) 265 { 266 int rc; 267 268 if (ts78xx_fpga.supports.ts_nand.init == 0) { 269 rc = platform_device_register(&ts78xx_ts_nand_device); 270 if (!rc) 271 ts78xx_fpga.supports.ts_nand.init = 1; 272 } else 273 rc = platform_device_add(&ts78xx_ts_nand_device); 274 275 if (rc) 276 pr_info("NAND could not be registered: %d\n", rc); 277 return rc; 278 }; 279 280 static void ts78xx_ts_nand_unload(void) 281 { 282 platform_device_del(&ts78xx_ts_nand_device); 283 } 284 285 /***************************************************************************** 286 * HW RNG 287 ****************************************************************************/ 288 #define TS_RNG_DATA (TS78XX_FPGA_REGS_PHYS_BASE | 0x044) 289 290 static struct resource ts78xx_ts_rng_resource 291 = DEFINE_RES_MEM(TS_RNG_DATA, 4); 292 293 static struct timeriomem_rng_data ts78xx_ts_rng_data = { 294 .period = 1000000, /* one second */ 295 }; 296 297 static struct platform_device ts78xx_ts_rng_device = { 298 .name = "timeriomem_rng", 299 .id = -1, 300 .dev = { 301 .platform_data = &ts78xx_ts_rng_data, 302 }, 303 .resource = &ts78xx_ts_rng_resource, 304 .num_resources = 1, 305 }; 306 307 static int ts78xx_ts_rng_load(void) 308 { 309 int rc; 310 311 if (ts78xx_fpga.supports.ts_rng.init == 0) { 312 rc = platform_device_register(&ts78xx_ts_rng_device); 313 if (!rc) 314 ts78xx_fpga.supports.ts_rng.init = 1; 315 } else 316 rc = platform_device_add(&ts78xx_ts_rng_device); 317 318 if (rc) 319 pr_info("RNG could not be registered: %d\n", rc); 320 return rc; 321 }; 322 323 static void ts78xx_ts_rng_unload(void) 324 { 325 platform_device_del(&ts78xx_ts_rng_device); 326 } 327 328 /***************************************************************************** 329 * FPGA 'hotplug' support code 330 ****************************************************************************/ 331 static void ts78xx_fpga_devices_zero_init(void) 332 { 333 ts78xx_fpga.supports.ts_rtc.init = 0; 334 ts78xx_fpga.supports.ts_nand.init = 0; 335 ts78xx_fpga.supports.ts_rng.init = 0; 336 } 337 338 static void ts78xx_fpga_supports(void) 339 { 340 /* TODO: put this 'table' into ts78xx-fpga.h */ 341 switch (ts78xx_fpga.id) { 342 case TS7800_REV_1: 343 case TS7800_REV_2: 344 case TS7800_REV_3: 345 case TS7800_REV_4: 346 case TS7800_REV_5: 347 case TS7800_REV_6: 348 case TS7800_REV_7: 349 case TS7800_REV_8: 350 case TS7800_REV_9: 351 ts78xx_fpga.supports.ts_rtc.present = 1; 352 ts78xx_fpga.supports.ts_nand.present = 1; 353 ts78xx_fpga.supports.ts_rng.present = 1; 354 break; 355 default: 356 /* enable devices if magic matches */ 357 switch ((ts78xx_fpga.id >> 8) & 0xffffff) { 358 case TS7800_FPGA_MAGIC: 359 pr_warn("unrecognised FPGA revision 0x%.2x\n", 360 ts78xx_fpga.id & 0xff); 361 ts78xx_fpga.supports.ts_rtc.present = 1; 362 ts78xx_fpga.supports.ts_nand.present = 1; 363 ts78xx_fpga.supports.ts_rng.present = 1; 364 break; 365 default: 366 ts78xx_fpga.supports.ts_rtc.present = 0; 367 ts78xx_fpga.supports.ts_nand.present = 0; 368 ts78xx_fpga.supports.ts_rng.present = 0; 369 } 370 } 371 } 372 373 static int ts78xx_fpga_load_devices(void) 374 { 375 int tmp, ret = 0; 376 377 if (ts78xx_fpga.supports.ts_rtc.present == 1) { 378 tmp = ts78xx_ts_rtc_load(); 379 if (tmp) 380 ts78xx_fpga.supports.ts_rtc.present = 0; 381 ret |= tmp; 382 } 383 if (ts78xx_fpga.supports.ts_nand.present == 1) { 384 tmp = ts78xx_ts_nand_load(); 385 if (tmp) 386 ts78xx_fpga.supports.ts_nand.present = 0; 387 ret |= tmp; 388 } 389 if (ts78xx_fpga.supports.ts_rng.present == 1) { 390 tmp = ts78xx_ts_rng_load(); 391 if (tmp) 392 ts78xx_fpga.supports.ts_rng.present = 0; 393 ret |= tmp; 394 } 395 396 return ret; 397 } 398 399 static int ts78xx_fpga_unload_devices(void) 400 { 401 int ret = 0; 402 403 if (ts78xx_fpga.supports.ts_rtc.present == 1) 404 ts78xx_ts_rtc_unload(); 405 if (ts78xx_fpga.supports.ts_nand.present == 1) 406 ts78xx_ts_nand_unload(); 407 if (ts78xx_fpga.supports.ts_rng.present == 1) 408 ts78xx_ts_rng_unload(); 409 410 return ret; 411 } 412 413 static int ts78xx_fpga_load(void) 414 { 415 ts78xx_fpga.id = readl(TS78XX_FPGA_REGS_VIRT_BASE); 416 417 pr_info("FPGA magic=0x%.6x, rev=0x%.2x\n", 418 (ts78xx_fpga.id >> 8) & 0xffffff, 419 ts78xx_fpga.id & 0xff); 420 421 ts78xx_fpga_supports(); 422 423 if (ts78xx_fpga_load_devices()) { 424 ts78xx_fpga.state = -1; 425 return -EBUSY; 426 } 427 428 return 0; 429 }; 430 431 static int ts78xx_fpga_unload(void) 432 { 433 unsigned int fpga_id; 434 435 fpga_id = readl(TS78XX_FPGA_REGS_VIRT_BASE); 436 437 /* 438 * There does not seem to be a feasible way to block access to the GPIO 439 * pins from userspace (/dev/mem). This if clause should hopefully warn 440 * those foolish enough not to follow 'policy' :) 441 * 442 * UrJTAG SVN since r1381 can be used to reprogram the FPGA 443 */ 444 if (ts78xx_fpga.id != fpga_id) { 445 pr_err("FPGA magic/rev mismatch\n" 446 "TS-78xx FPGA: was 0x%.6x/%.2x but now 0x%.6x/%.2x\n", 447 (ts78xx_fpga.id >> 8) & 0xffffff, ts78xx_fpga.id & 0xff, 448 (fpga_id >> 8) & 0xffffff, fpga_id & 0xff); 449 ts78xx_fpga.state = -1; 450 return -EBUSY; 451 } 452 453 if (ts78xx_fpga_unload_devices()) { 454 ts78xx_fpga.state = -1; 455 return -EBUSY; 456 } 457 458 return 0; 459 }; 460 461 static ssize_t ts78xx_fpga_show(struct kobject *kobj, 462 struct kobj_attribute *attr, char *buf) 463 { 464 if (ts78xx_fpga.state < 0) 465 return sprintf(buf, "borked\n"); 466 467 return sprintf(buf, "%s\n", (ts78xx_fpga.state) ? "online" : "offline"); 468 } 469 470 static ssize_t ts78xx_fpga_store(struct kobject *kobj, 471 struct kobj_attribute *attr, const char *buf, size_t n) 472 { 473 int value, ret; 474 475 if (ts78xx_fpga.state < 0) { 476 pr_err("FPGA borked, you must powercycle ASAP\n"); 477 return -EBUSY; 478 } 479 480 if (strncmp(buf, "online", sizeof("online") - 1) == 0) 481 value = 1; 482 else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) 483 value = 0; 484 else 485 return -EINVAL; 486 487 if (ts78xx_fpga.state == value) 488 return n; 489 490 ret = (ts78xx_fpga.state == 0) 491 ? ts78xx_fpga_load() 492 : ts78xx_fpga_unload(); 493 494 if (!(ret < 0)) 495 ts78xx_fpga.state = value; 496 497 return n; 498 } 499 500 static struct kobj_attribute ts78xx_fpga_attr = 501 __ATTR(ts78xx_fpga, 0644, ts78xx_fpga_show, ts78xx_fpga_store); 502 503 /***************************************************************************** 504 * General Setup 505 ****************************************************************************/ 506 static unsigned int ts78xx_mpp_modes[] __initdata = { 507 MPP0_UNUSED, 508 MPP1_GPIO, /* JTAG Clock */ 509 MPP2_GPIO, /* JTAG Data In */ 510 MPP3_GPIO, /* Lat ECP2 256 FPGA - PB2B */ 511 MPP4_GPIO, /* JTAG Data Out */ 512 MPP5_GPIO, /* JTAG TMS */ 513 MPP6_GPIO, /* Lat ECP2 256 FPGA - PB31A_CLK4+ */ 514 MPP7_GPIO, /* Lat ECP2 256 FPGA - PB22B */ 515 MPP8_UNUSED, 516 MPP9_UNUSED, 517 MPP10_UNUSED, 518 MPP11_UNUSED, 519 MPP12_UNUSED, 520 MPP13_UNUSED, 521 MPP14_UNUSED, 522 MPP15_UNUSED, 523 MPP16_UART, 524 MPP17_UART, 525 MPP18_UART, 526 MPP19_UART, 527 /* 528 * MPP[20] PCI Clock Out 1 529 * MPP[21] PCI Clock Out 0 530 * MPP[22] Unused 531 * MPP[23] Unused 532 * MPP[24] Unused 533 * MPP[25] Unused 534 */ 535 0, 536 }; 537 538 static void __init ts78xx_init(void) 539 { 540 int ret; 541 542 /* 543 * Setup basic Orion functions. Need to be called early. 544 */ 545 orion5x_init(); 546 547 orion5x_mpp_conf(ts78xx_mpp_modes); 548 549 /* 550 * Configure peripherals. 551 */ 552 orion5x_ehci0_init(); 553 orion5x_ehci1_init(); 554 orion5x_eth_init(&ts78xx_eth_data); 555 orion5x_sata_init(&ts78xx_sata_data); 556 orion5x_uart0_init(); 557 orion5x_uart1_init(); 558 orion5x_xor_init(); 559 560 /* FPGA init */ 561 ts78xx_fpga_devices_zero_init(); 562 ret = ts78xx_fpga_load(); 563 ret = sysfs_create_file(firmware_kobj, &ts78xx_fpga_attr.attr); 564 if (ret) 565 pr_err("sysfs_create_file failed: %d\n", ret); 566 } 567 568 MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC") 569 /* Maintainer: Alexander Clouter <alex@digriz.org.uk> */ 570 .atag_offset = 0x100, 571 .nr_irqs = ORION5X_NR_IRQS, 572 .init_machine = ts78xx_init, 573 .map_io = ts78xx_map_io, 574 .init_early = orion5x_init_early, 575 .init_irq = orion5x_init_irq, 576 .init_time = orion5x_timer_init, 577 .restart = orion5x_restart, 578 MACHINE_END 579