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