platform.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. * Generic RDC321x platform devices
  3. *
  4. * Copyright (C) 2007-2009 OpenWrt.org
  5. * Copyright (C) 2007 Florian Fainelli <[email protected]>
  6. * Copyright (C) 2008-2009 Daniel Gimpelevich <[email protected]>
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the
  20. * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  21. * Boston, MA 02110-1301, USA.
  22. *
  23. */
  24. #include <linux/init.h>
  25. #include <linux/kernel.h>
  26. #include <linux/list.h>
  27. #include <linux/device.h>
  28. #include <linux/platform_device.h>
  29. #include <linux/version.h>
  30. #include <linux/leds.h>
  31. #include <linux/gpio_keys.h>
  32. #include <linux/input.h>
  33. #include <linux/mtd/map.h>
  34. #include <linux/mtd/mtd.h>
  35. #include <linux/mtd/physmap.h>
  36. #include <linux/root_dev.h>
  37. #include <asm/rdc321x_gpio.h>
  38. /* Flash */
  39. #ifdef CONFIG_MTD_R8610
  40. #define CONFIG_MTD_RDC3210 1
  41. #elif defined CONFIG_MTD_RDC3210
  42. static struct resource rdc_flash_resource[] = {
  43. [0] = {
  44. .start = (u32)-CONFIG_MTD_RDC3210_SIZE,
  45. .end = (u32)-1,
  46. .flags = IORESOURCE_MEM,
  47. },
  48. };
  49. static struct platform_device rdc_flash_device = {
  50. .name = "rdc321x-flash",
  51. .id = -1,
  52. .num_resources = ARRAY_SIZE(rdc_flash_resource),
  53. .resource = rdc_flash_resource,
  54. };
  55. #else
  56. static struct mtd_partition rdc_flash_parts[15];
  57. static struct resource rdc_flash_resource = {
  58. .end = (u32)-1,
  59. .flags = IORESOURCE_MEM,
  60. };
  61. static struct physmap_flash_data rdc_flash_data = {
  62. .parts = rdc_flash_parts,
  63. };
  64. static struct platform_device rdc_flash_device = {
  65. .name = "physmap-flash",
  66. .id = -1,
  67. .resource = &rdc_flash_resource,
  68. .num_resources = 1,
  69. .dev.platform_data = &rdc_flash_data,
  70. };
  71. #endif
  72. /* LEDS */
  73. static struct gpio_led default_leds[] = {
  74. { .name = "rdc321x:dmz", .gpio = 1, .active_low = 1},
  75. };
  76. static struct gpio_led_platform_data rdc321x_led_data = {
  77. .num_leds = ARRAY_SIZE(default_leds),
  78. .leds = default_leds,
  79. };
  80. static struct platform_device rdc321x_leds = {
  81. .name = "leds-gpio",
  82. .id = -1,
  83. .dev = {
  84. .platform_data = &rdc321x_led_data,
  85. }
  86. };
  87. /* Watchdog */
  88. static struct platform_device rdc321x_wdt = {
  89. .name = "rdc321x-wdt",
  90. .id = -1,
  91. .num_resources = 0,
  92. };
  93. /* Button */
  94. static struct gpio_keys_button rdc321x_gpio_btn[] = {
  95. {
  96. .gpio = 0,
  97. .code = BTN_0,
  98. .desc = "Reset",
  99. .active_low = 1,
  100. }
  101. };
  102. static struct gpio_keys_platform_data rdc321x_gpio_btn_data = {
  103. .buttons = rdc321x_gpio_btn,
  104. .nbuttons = ARRAY_SIZE(rdc321x_gpio_btn),
  105. };
  106. static struct platform_device rdc321x_button = {
  107. .name = "gpio-keys",
  108. .id = -1,
  109. .dev = {
  110. .platform_data = &rdc321x_gpio_btn_data,
  111. }
  112. };
  113. static struct platform_device *rdc321x_devs[] = {
  114. &rdc_flash_device,
  115. &rdc321x_leds,
  116. &rdc321x_wdt,
  117. &rdc321x_button,
  118. };
  119. static int probe_flash_start(struct map_info *the_map)
  120. {
  121. struct mtd_info *res;
  122. the_map->virt = ioremap(the_map->phys, the_map->size);
  123. if (the_map->virt == NULL)
  124. return 1;
  125. for (the_map->bankwidth = 32; the_map->bankwidth; the_map->bankwidth
  126. >>= 1) {
  127. res = do_map_probe("cfi_probe", the_map);
  128. if (res == NULL)
  129. res = do_map_probe("jedec_probe", the_map);
  130. if (res != NULL)
  131. break;
  132. }
  133. iounmap(the_map->virt);
  134. if (res != NULL)
  135. the_map->phys = (u32)-(s32)(the_map->size = res->size);
  136. return res == NULL;
  137. }
  138. static int __init rdc_board_setup(void)
  139. {
  140. #ifndef CONFIG_MTD_RDC3210
  141. struct map_info rdc_map_info;
  142. u32 the_header[8];
  143. ROOT_DEV = 0;
  144. rdc_map_info.name = rdc_flash_device.name;
  145. rdc_map_info.size = 0x800000; //8MB
  146. rdc_map_info.phys = (u32) -rdc_map_info.size;
  147. rdc_map_info.bankwidth = 2;
  148. rdc_map_info.set_vpp = NULL;
  149. simple_map_init(&rdc_map_info);
  150. while (probe_flash_start(&rdc_map_info)) {
  151. if (rdc_map_info.size /= 2 < 0x100000) //1MB
  152. panic("Could not find start of flash!");
  153. rdc_map_info.phys = (u32) -rdc_map_info.size;
  154. }
  155. rdc_flash_resource.start = rdc_map_info.phys;
  156. rdc_flash_data.width = rdc_map_info.bankwidth;
  157. rdc_map_info.virt = ioremap_nocache(rdc_map_info.phys, 0x10);
  158. if (rdc_map_info.virt == NULL)
  159. panic("Could not ioremap to read device magic!");
  160. the_header[0] = ((u32 *)rdc_map_info.virt)[0];
  161. the_header[1] = ((u32 *)rdc_map_info.virt)[1];
  162. the_header[2] = ((u32 *)rdc_map_info.virt)[2];
  163. the_header[3] = ((u32 *)rdc_map_info.virt)[3];
  164. iounmap(rdc_map_info.virt);
  165. rdc_map_info.virt = ioremap_nocache(rdc_map_info.phys + 0x8000, 0x10);
  166. if (rdc_map_info.virt == NULL)
  167. panic("Could not ioremap to read device magic!");
  168. the_header[4] = ((u32 *)rdc_map_info.virt)[0];
  169. the_header[5] = ((u32 *)rdc_map_info.virt)[1];
  170. the_header[6] = ((u32 *)rdc_map_info.virt)[2];
  171. the_header[7] = ((u32 *)rdc_map_info.virt)[3];
  172. iounmap(rdc_map_info.virt);
  173. if (!memcmp(the_header, "GMTK", 4)) { /* Gemtek */
  174. /* TODO */
  175. } else if (!memcmp(the_header + 4, "CSYS", 4)) { /* Sitecom */
  176. rdc_flash_parts[0].name = "system";
  177. rdc_flash_parts[0].offset = 0;
  178. rdc_flash_parts[0].size = rdc_map_info.size - 0x10000;
  179. rdc_flash_parts[1].name = "config";
  180. rdc_flash_parts[1].offset = 0;
  181. rdc_flash_parts[1].size = 0x8000;
  182. rdc_flash_parts[2].name = "magic";
  183. rdc_flash_parts[2].offset = 0x8000;
  184. rdc_flash_parts[2].size = 0x14;
  185. rdc_flash_parts[3].name = "kernel";
  186. rdc_flash_parts[3].offset = 0x8014;
  187. rdc_flash_parts[3].size = the_header[5];
  188. rdc_flash_parts[4].name = "rootfs";
  189. rdc_flash_parts[4].offset = 0x8014 + the_header[5];
  190. rdc_flash_parts[4].size = rdc_flash_parts[0].size - rdc_flash_parts[4].offset;
  191. rdc_flash_parts[5].name = "bootloader";
  192. rdc_flash_parts[5].offset = rdc_flash_parts[0].size;
  193. rdc_flash_parts[5].size = 0x10000;
  194. rdc_flash_data.nr_parts = 6;
  195. } else if (!memcmp(((u8 *)the_header) + 14, "Li", 2)) { /* AMIT */
  196. rdc_flash_parts[0].name = "kernel_parthdr";
  197. rdc_flash_parts[0].offset = 0;
  198. rdc_flash_parts[0].size = 0x10;
  199. rdc_flash_parts[1].name = "kernel";
  200. rdc_flash_parts[1].offset = 0x10;
  201. rdc_flash_parts[1].size = 0xffff0;
  202. rdc_flash_parts[2].name = "rootfs_parthdr";
  203. rdc_flash_parts[2].offset = 0x100000;
  204. rdc_flash_parts[2].size = 0x10;
  205. rdc_flash_parts[3].name = "rootfs";
  206. rdc_flash_parts[3].offset = 0x100010;
  207. rdc_flash_parts[3].size = rdc_map_info.size - 0x160010;
  208. rdc_flash_parts[4].name = "config_parthdr";
  209. rdc_flash_parts[4].offset = rdc_map_info.size - 0x60000;
  210. rdc_flash_parts[4].size = 0x10;
  211. rdc_flash_parts[5].name = "config";
  212. rdc_flash_parts[5].offset = rdc_map_info.size - 0x5fff0;
  213. rdc_flash_parts[5].size = 0xfff0;
  214. rdc_flash_parts[6].name = "recoveryfs_parthdr";
  215. rdc_flash_parts[6].offset = rdc_map_info.size - 0x50000;
  216. rdc_flash_parts[6].size = 0x10;
  217. rdc_flash_parts[7].name = "recoveryfs";
  218. rdc_flash_parts[7].offset = rdc_map_info.size - 0x4fff0;
  219. rdc_flash_parts[7].size = 0x3fff0;
  220. rdc_flash_parts[8].name = "recovery_parthdr";
  221. rdc_flash_parts[8].offset = rdc_map_info.size - 0x10000;
  222. rdc_flash_parts[8].size = 0x10;
  223. rdc_flash_parts[9].name = "recovery";
  224. rdc_flash_parts[9].offset = rdc_map_info.size - 0xfff0;
  225. rdc_flash_parts[9].size = 0x7ff0;
  226. rdc_flash_parts[10].name = "productinfo_parthdr";
  227. rdc_flash_parts[10].offset = rdc_map_info.size - 0x8000;
  228. rdc_flash_parts[10].size = 0x10;
  229. rdc_flash_parts[11].name = "productinfo";
  230. rdc_flash_parts[11].offset = rdc_map_info.size - 0x7ff0;
  231. rdc_flash_parts[11].size = 0x1ff0;
  232. rdc_flash_parts[12].name = "bootloader_parthdr";
  233. rdc_flash_parts[12].offset = rdc_map_info.size - 0x6000;
  234. rdc_flash_parts[12].size = 0x10;
  235. rdc_flash_parts[13].name = "bootloader";
  236. rdc_flash_parts[13].offset = rdc_map_info.size - 0x5ff0;
  237. rdc_flash_parts[13].size = 0x5ff0;
  238. rdc_flash_parts[14].name = "everything";
  239. rdc_flash_parts[14].offset = 0;
  240. rdc_flash_parts[14].size = rdc_map_info.size;
  241. rdc_flash_data.nr_parts = 15;
  242. } else { /* ZyXEL */
  243. rdc_flash_parts[0].name = "kernel";
  244. rdc_flash_parts[0].offset = 0;
  245. rdc_flash_parts[0].size = 0x100000;
  246. rdc_flash_parts[1].name = "rootfs";
  247. rdc_flash_parts[1].offset = 0x100000;
  248. rdc_flash_parts[1].size = rdc_map_info.size - 0x140000;
  249. rdc_flash_parts[2].name = "linux";
  250. rdc_flash_parts[2].offset = 0;
  251. rdc_flash_parts[2].size = rdc_map_info.size - 0x40000;
  252. rdc_flash_parts[3].name = "config";
  253. rdc_flash_parts[3].offset = rdc_map_info.size - 0x40000;
  254. rdc_flash_parts[3].size = 0x10000;
  255. rdc_flash_parts[4].name = "productinfo";
  256. rdc_flash_parts[4].offset = rdc_map_info.size - 0x30000;
  257. rdc_flash_parts[4].size = 0x10000;
  258. rdc_flash_parts[5].name = "bootloader";
  259. rdc_flash_parts[5].offset = rdc_map_info.size - 0x20000;
  260. rdc_flash_parts[5].size = 0x20000;
  261. rdc_flash_data.nr_parts = 6;
  262. }
  263. #endif
  264. return platform_add_devices(rdc321x_devs, ARRAY_SIZE(rdc321x_devs));
  265. }
  266. #ifdef CONFIG_MTD_RDC3210
  267. arch_initcall(rdc_board_setup);
  268. #else
  269. late_initcall(rdc_board_setup);
  270. #endif