ts78xx-setup.c 14 KB

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