ts72xx.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /*
  2. * arch/arm/mach-ep93xx/ts72xx.c
  3. * Technologic Systems TS72xx SBC support.
  4. *
  5. * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or (at
  10. * your option) any later version.
  11. */
  12. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  13. #include <linux/kernel.h>
  14. #include <linux/init.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/io.h>
  17. #include <linux/m48t86.h>
  18. #include <linux/mtd/physmap.h>
  19. #include <linux/mtd/nand.h>
  20. #include <linux/mtd/partitions.h>
  21. #include <mach/hardware.h>
  22. #include <mach/ts72xx.h>
  23. #include <asm/mach-types.h>
  24. #include <asm/mach/map.h>
  25. #include <asm/mach/arch.h>
  26. static struct map_desc ts72xx_io_desc[] __initdata = {
  27. {
  28. .virtual = TS72XX_MODEL_VIRT_BASE,
  29. .pfn = __phys_to_pfn(TS72XX_MODEL_PHYS_BASE),
  30. .length = TS72XX_MODEL_SIZE,
  31. .type = MT_DEVICE,
  32. }, {
  33. .virtual = TS72XX_OPTIONS_VIRT_BASE,
  34. .pfn = __phys_to_pfn(TS72XX_OPTIONS_PHYS_BASE),
  35. .length = TS72XX_OPTIONS_SIZE,
  36. .type = MT_DEVICE,
  37. }, {
  38. .virtual = TS72XX_OPTIONS2_VIRT_BASE,
  39. .pfn = __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE),
  40. .length = TS72XX_OPTIONS2_SIZE,
  41. .type = MT_DEVICE,
  42. }, {
  43. .virtual = TS72XX_RTC_INDEX_VIRT_BASE,
  44. .pfn = __phys_to_pfn(TS72XX_RTC_INDEX_PHYS_BASE),
  45. .length = TS72XX_RTC_INDEX_SIZE,
  46. .type = MT_DEVICE,
  47. }, {
  48. .virtual = TS72XX_RTC_DATA_VIRT_BASE,
  49. .pfn = __phys_to_pfn(TS72XX_RTC_DATA_PHYS_BASE),
  50. .length = TS72XX_RTC_DATA_SIZE,
  51. .type = MT_DEVICE,
  52. }
  53. };
  54. static void __init ts72xx_map_io(void)
  55. {
  56. ep93xx_map_io();
  57. iotable_init(ts72xx_io_desc, ARRAY_SIZE(ts72xx_io_desc));
  58. }
  59. /*************************************************************************
  60. * NAND flash
  61. *************************************************************************/
  62. #define TS72XX_NAND_CONTROL_ADDR_LINE 22 /* 0xN0400000 */
  63. #define TS72XX_NAND_BUSY_ADDR_LINE 23 /* 0xN0800000 */
  64. static void ts72xx_nand_hwcontrol(struct mtd_info *mtd,
  65. int cmd, unsigned int ctrl)
  66. {
  67. struct nand_chip *chip = mtd->priv;
  68. if (ctrl & NAND_CTRL_CHANGE) {
  69. void __iomem *addr = chip->IO_ADDR_R;
  70. unsigned char bits;
  71. addr += (1 << TS72XX_NAND_CONTROL_ADDR_LINE);
  72. bits = __raw_readb(addr) & ~0x07;
  73. bits |= (ctrl & NAND_NCE) << 2; /* bit 0 -> bit 2 */
  74. bits |= (ctrl & NAND_CLE); /* bit 1 -> bit 1 */
  75. bits |= (ctrl & NAND_ALE) >> 2; /* bit 2 -> bit 0 */
  76. __raw_writeb(bits, addr);
  77. }
  78. if (cmd != NAND_CMD_NONE)
  79. __raw_writeb(cmd, chip->IO_ADDR_W);
  80. }
  81. static int ts72xx_nand_device_ready(struct mtd_info *mtd)
  82. {
  83. struct nand_chip *chip = mtd->priv;
  84. void __iomem *addr = chip->IO_ADDR_R;
  85. addr += (1 << TS72XX_NAND_BUSY_ADDR_LINE);
  86. return !!(__raw_readb(addr) & 0x20);
  87. }
  88. static const char *ts72xx_nand_part_probes[] = { "cmdlinepart", NULL };
  89. #define TS72XX_BOOTROM_PART_SIZE (SZ_16K)
  90. #define TS72XX_REDBOOT_PART_SIZE (SZ_2M + SZ_1M)
  91. static struct mtd_partition ts72xx_nand_parts[] = {
  92. {
  93. .name = "TS-BOOTROM",
  94. .offset = 0,
  95. .size = TS72XX_BOOTROM_PART_SIZE,
  96. .mask_flags = MTD_WRITEABLE, /* force read-only */
  97. }, {
  98. .name = "Linux",
  99. .offset = MTDPART_OFS_APPEND,
  100. .size = 0, /* filled in later */
  101. }, {
  102. .name = "RedBoot",
  103. .offset = MTDPART_OFS_APPEND,
  104. .size = MTDPART_SIZ_FULL,
  105. .mask_flags = MTD_WRITEABLE, /* force read-only */
  106. },
  107. };
  108. static void ts72xx_nand_set_parts(uint64_t size,
  109. struct platform_nand_chip *chip)
  110. {
  111. /* Factory TS-72xx boards only come with 32MiB or 128MiB NAND options */
  112. if (size == SZ_32M || size == SZ_128M) {
  113. /* Set the "Linux" partition size */
  114. ts72xx_nand_parts[1].size = size - TS72XX_REDBOOT_PART_SIZE;
  115. chip->partitions = ts72xx_nand_parts;
  116. chip->nr_partitions = ARRAY_SIZE(ts72xx_nand_parts);
  117. } else {
  118. pr_warning("Unknown nand disk size:%lluMiB\n", size >> 20);
  119. }
  120. }
  121. static struct platform_nand_data ts72xx_nand_data = {
  122. .chip = {
  123. .nr_chips = 1,
  124. .chip_offset = 0,
  125. .chip_delay = 15,
  126. .part_probe_types = ts72xx_nand_part_probes,
  127. .set_parts = ts72xx_nand_set_parts,
  128. },
  129. .ctrl = {
  130. .cmd_ctrl = ts72xx_nand_hwcontrol,
  131. .dev_ready = ts72xx_nand_device_ready,
  132. },
  133. };
  134. static struct resource ts72xx_nand_resource[] = {
  135. {
  136. .start = 0, /* filled in later */
  137. .end = 0, /* filled in later */
  138. .flags = IORESOURCE_MEM,
  139. },
  140. };
  141. static struct platform_device ts72xx_nand_flash = {
  142. .name = "gen_nand",
  143. .id = -1,
  144. .dev.platform_data = &ts72xx_nand_data,
  145. .resource = ts72xx_nand_resource,
  146. .num_resources = ARRAY_SIZE(ts72xx_nand_resource),
  147. };
  148. /*************************************************************************
  149. * NOR flash (TS-7200 only)
  150. *************************************************************************/
  151. static struct physmap_flash_data ts72xx_nor_data = {
  152. .width = 2,
  153. };
  154. static struct resource ts72xx_nor_resource = {
  155. .start = EP93XX_CS6_PHYS_BASE,
  156. .end = EP93XX_CS6_PHYS_BASE + SZ_16M - 1,
  157. .flags = IORESOURCE_MEM,
  158. };
  159. static struct platform_device ts72xx_nor_flash = {
  160. .name = "physmap-flash",
  161. .id = 0,
  162. .dev.platform_data = &ts72xx_nor_data,
  163. .resource = &ts72xx_nor_resource,
  164. .num_resources = 1,
  165. };
  166. static void __init ts72xx_register_flash(void)
  167. {
  168. if (board_is_ts7200()) {
  169. platform_device_register(&ts72xx_nor_flash);
  170. } else {
  171. resource_size_t start;
  172. if (is_ts9420_installed())
  173. start = EP93XX_CS7_PHYS_BASE;
  174. else
  175. start = EP93XX_CS6_PHYS_BASE;
  176. ts72xx_nand_resource[0].start = start;
  177. ts72xx_nand_resource[0].end = start + SZ_16M - 1;
  178. platform_device_register(&ts72xx_nand_flash);
  179. }
  180. }
  181. static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
  182. {
  183. __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
  184. return __raw_readb(TS72XX_RTC_DATA_VIRT_BASE);
  185. }
  186. static void ts72xx_rtc_writebyte(unsigned char value, unsigned long addr)
  187. {
  188. __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
  189. __raw_writeb(value, TS72XX_RTC_DATA_VIRT_BASE);
  190. }
  191. static struct m48t86_ops ts72xx_rtc_ops = {
  192. .readbyte = ts72xx_rtc_readbyte,
  193. .writebyte = ts72xx_rtc_writebyte,
  194. };
  195. static struct platform_device ts72xx_rtc_device = {
  196. .name = "rtc-m48t86",
  197. .id = -1,
  198. .dev = {
  199. .platform_data = &ts72xx_rtc_ops,
  200. },
  201. .num_resources = 0,
  202. };
  203. static struct resource ts72xx_wdt_resources[] = {
  204. {
  205. .start = TS72XX_WDT_CONTROL_PHYS_BASE,
  206. .end = TS72XX_WDT_CONTROL_PHYS_BASE + SZ_4K - 1,
  207. .flags = IORESOURCE_MEM,
  208. },
  209. {
  210. .start = TS72XX_WDT_FEED_PHYS_BASE,
  211. .end = TS72XX_WDT_FEED_PHYS_BASE + SZ_4K - 1,
  212. .flags = IORESOURCE_MEM,
  213. },
  214. };
  215. static struct platform_device ts72xx_wdt_device = {
  216. .name = "ts72xx-wdt",
  217. .id = -1,
  218. .num_resources = ARRAY_SIZE(ts72xx_wdt_resources),
  219. .resource = ts72xx_wdt_resources,
  220. };
  221. static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
  222. .phy_id = 1,
  223. };
  224. static void __init ts72xx_init_machine(void)
  225. {
  226. ep93xx_init_devices();
  227. ts72xx_register_flash();
  228. platform_device_register(&ts72xx_rtc_device);
  229. platform_device_register(&ts72xx_wdt_device);
  230. ep93xx_register_eth(&ts72xx_eth_data, 1);
  231. }
  232. MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
  233. /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
  234. .phys_io = EP93XX_APB_PHYS_BASE,
  235. .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
  236. .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100,
  237. .map_io = ts72xx_map_io,
  238. .init_irq = ep93xx_init_irq,
  239. .timer = &ep93xx_timer,
  240. .init_machine = ts72xx_init_machine,
  241. MACHINE_END