ipaq-flash.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /*
  2. * Flash memory access on iPAQ Handhelds (either SA1100 or PXA250 based)
  3. *
  4. * (C) 2000 Nicolas Pitre <nico@cam.org>
  5. * (C) 2002 Hewlett-Packard Company <jamey.hicks@hp.com>
  6. * (C) 2003 Christian Pellegrin <chri@ascensit.com>, <chri@infis.univ.ts.it>: concatenation of multiple flashes
  7. */
  8. #include <linux/module.h>
  9. #include <linux/types.h>
  10. #include <linux/kernel.h>
  11. #include <linux/spinlock.h>
  12. #include <linux/init.h>
  13. #include <linux/slab.h>
  14. #include <asm/page.h>
  15. #include <asm/mach-types.h>
  16. #include <asm/system.h>
  17. #include <asm/errno.h>
  18. #include <linux/mtd/mtd.h>
  19. #include <linux/mtd/map.h>
  20. #include <linux/mtd/partitions.h>
  21. #ifdef CONFIG_MTD_CONCAT
  22. #include <linux/mtd/concat.h>
  23. #endif
  24. #include <mach/hardware.h>
  25. #include <mach/h3600.h>
  26. #include <asm/io.h>
  27. #ifndef CONFIG_IPAQ_HANDHELD
  28. #error This is for iPAQ Handhelds only
  29. #endif
  30. #ifdef CONFIG_SA1100_JORNADA56X
  31. static void jornada56x_set_vpp(struct map_info *map, int vpp)
  32. {
  33. if (vpp)
  34. GPSR = GPIO_GPIO26;
  35. else
  36. GPCR = GPIO_GPIO26;
  37. GPDR |= GPIO_GPIO26;
  38. }
  39. #endif
  40. #ifdef CONFIG_SA1100_JORNADA720
  41. static void jornada720_set_vpp(struct map_info *map, int vpp)
  42. {
  43. if (vpp)
  44. PPSR |= 0x80;
  45. else
  46. PPSR &= ~0x80;
  47. PPDR |= 0x80;
  48. }
  49. #endif
  50. #define MAX_IPAQ_CS 2 /* Number of CS we are going to test */
  51. #define IPAQ_MAP_INIT(X) \
  52. { \
  53. name: "IPAQ flash " X, \
  54. }
  55. static struct map_info ipaq_map[MAX_IPAQ_CS] = {
  56. IPAQ_MAP_INIT("bank 1"),
  57. IPAQ_MAP_INIT("bank 2")
  58. };
  59. static struct mtd_info *my_sub_mtd[MAX_IPAQ_CS] = {
  60. NULL,
  61. NULL
  62. };
  63. /*
  64. * Here are partition information for all known IPAQ-based devices.
  65. * See include/linux/mtd/partitions.h for definition of the mtd_partition
  66. * structure.
  67. *
  68. * The *_max_flash_size is the maximum possible mapped flash size which
  69. * is not necessarily the actual flash size. It must be no more than
  70. * the value specified in the "struct map_desc *_io_desc" mapping
  71. * definition for the corresponding machine.
  72. *
  73. * Please keep these in alphabetical order, and formatted as per existing
  74. * entries. Thanks.
  75. */
  76. #ifdef CONFIG_IPAQ_HANDHELD
  77. static unsigned long h3xxx_max_flash_size = 0x04000000;
  78. static struct mtd_partition h3xxx_partitions[] = {
  79. {
  80. name: "H3XXX boot firmware",
  81. #ifndef CONFIG_LAB
  82. size: 0x00040000,
  83. #else
  84. size: 0x00080000,
  85. #endif
  86. offset: 0,
  87. #ifndef CONFIG_LAB
  88. mask_flags: MTD_WRITEABLE, /* force read-only */
  89. #endif
  90. },
  91. {
  92. name: "H3XXX root jffs2",
  93. #ifndef CONFIG_LAB
  94. size: 0x2000000 - 2*0x40000, /* Warning, this is fixed later */
  95. offset: 0x00040000,
  96. #else
  97. size: 0x2000000 - 0x40000 - 0x80000, /* Warning, this is fixed later */
  98. offset: 0x00080000,
  99. #endif
  100. },
  101. {
  102. name: "asset",
  103. size: 0x40000,
  104. offset: 0x2000000 - 0x40000, /* Warning, this is fixed later */
  105. mask_flags: MTD_WRITEABLE, /* force read-only */
  106. }
  107. };
  108. #ifndef CONFIG_MTD_CONCAT
  109. static struct mtd_partition h3xxx_partitions_bank2[] = {
  110. /* this is used only on 2 CS machines when concat is not present */
  111. {
  112. name: "second H3XXX root jffs2",
  113. size: 0x1000000 - 0x40000, /* Warning, this is fixed later */
  114. offset: 0x00000000,
  115. },
  116. {
  117. name: "second asset",
  118. size: 0x40000,
  119. offset: 0x1000000 - 0x40000, /* Warning, this is fixed later */
  120. mask_flags: MTD_WRITEABLE, /* force read-only */
  121. }
  122. };
  123. #endif
  124. static DEFINE_SPINLOCK(ipaq_vpp_lock);
  125. static void h3xxx_set_vpp(struct map_info *map, int vpp)
  126. {
  127. static int nest = 0;
  128. spin_lock(&ipaq_vpp_lock);
  129. if (vpp)
  130. nest++;
  131. else
  132. nest--;
  133. if (nest)
  134. assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, 1);
  135. else
  136. assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, 0);
  137. spin_unlock(&ipaq_vpp_lock);
  138. }
  139. #endif
  140. #if defined(CONFIG_SA1100_JORNADA56X) || defined(CONFIG_SA1100_JORNADA720)
  141. static unsigned long jornada_max_flash_size = 0x02000000;
  142. static struct mtd_partition jornada_partitions[] = {
  143. {
  144. name: "Jornada boot firmware",
  145. size: 0x00040000,
  146. offset: 0,
  147. mask_flags: MTD_WRITEABLE, /* force read-only */
  148. }, {
  149. name: "Jornada root jffs2",
  150. size: MTDPART_SIZ_FULL,
  151. offset: 0x00040000,
  152. }
  153. };
  154. #endif
  155. static struct mtd_partition *parsed_parts;
  156. static struct mtd_info *mymtd;
  157. static unsigned long cs_phys[] = {
  158. #ifdef CONFIG_ARCH_SA1100
  159. SA1100_CS0_PHYS,
  160. SA1100_CS1_PHYS,
  161. SA1100_CS2_PHYS,
  162. SA1100_CS3_PHYS,
  163. SA1100_CS4_PHYS,
  164. SA1100_CS5_PHYS,
  165. #else
  166. PXA_CS0_PHYS,
  167. PXA_CS1_PHYS,
  168. PXA_CS2_PHYS,
  169. PXA_CS3_PHYS,
  170. PXA_CS4_PHYS,
  171. PXA_CS5_PHYS,
  172. #endif
  173. };
  174. static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
  175. static int __init h1900_special_case(void);
  176. int __init ipaq_mtd_init(void)
  177. {
  178. struct mtd_partition *parts = NULL;
  179. int nb_parts = 0;
  180. int parsed_nr_parts = 0;
  181. const char *part_type;
  182. int i; /* used when we have >1 flash chips */
  183. unsigned long tot_flashsize = 0; /* used when we have >1 flash chips */
  184. /* Default flash bankwidth */
  185. // ipaq_map.bankwidth = (MSC0 & MSC_RBW) ? 2 : 4;
  186. if (machine_is_h1900())
  187. {
  188. /* For our intents, the h1900 is not a real iPAQ, so we special-case it. */
  189. return h1900_special_case();
  190. }
  191. if (machine_is_h3100() || machine_is_h1900())
  192. for(i=0; i<MAX_IPAQ_CS; i++)
  193. ipaq_map[i].bankwidth = 2;
  194. else
  195. for(i=0; i<MAX_IPAQ_CS; i++)
  196. ipaq_map[i].bankwidth = 4;
  197. /*
  198. * Static partition definition selection
  199. */
  200. part_type = "static";
  201. simple_map_init(&ipaq_map[0]);
  202. simple_map_init(&ipaq_map[1]);
  203. #ifdef CONFIG_IPAQ_HANDHELD
  204. if (machine_is_ipaq()) {
  205. parts = h3xxx_partitions;
  206. nb_parts = ARRAY_SIZE(h3xxx_partitions);
  207. for(i=0; i<MAX_IPAQ_CS; i++) {
  208. ipaq_map[i].size = h3xxx_max_flash_size;
  209. ipaq_map[i].set_vpp = h3xxx_set_vpp;
  210. ipaq_map[i].phys = cs_phys[i];
  211. ipaq_map[i].virt = ioremap(cs_phys[i], 0x04000000);
  212. if (machine_is_h3100 () || machine_is_h1900())
  213. ipaq_map[i].bankwidth = 2;
  214. }
  215. if (machine_is_h3600()) {
  216. /* No asset partition here */
  217. h3xxx_partitions[1].size += 0x40000;
  218. nb_parts--;
  219. }
  220. }
  221. #endif
  222. #ifdef CONFIG_ARCH_H5400
  223. if (machine_is_h5400()) {
  224. ipaq_map[0].size = 0x02000000;
  225. ipaq_map[1].size = 0x02000000;
  226. ipaq_map[1].phys = 0x02000000;
  227. ipaq_map[1].virt = ipaq_map[0].virt + 0x02000000;
  228. }
  229. #endif
  230. #ifdef CONFIG_ARCH_H1900
  231. if (machine_is_h1900()) {
  232. ipaq_map[0].size = 0x00400000;
  233. ipaq_map[1].size = 0x02000000;
  234. ipaq_map[1].phys = 0x00080000;
  235. ipaq_map[1].virt = ipaq_map[0].virt + 0x00080000;
  236. }
  237. #endif
  238. #ifdef CONFIG_SA1100_JORNADA56X
  239. if (machine_is_jornada56x()) {
  240. parts = jornada_partitions;
  241. nb_parts = ARRAY_SIZE(jornada_partitions);
  242. ipaq_map[0].size = jornada_max_flash_size;
  243. ipaq_map[0].set_vpp = jornada56x_set_vpp;
  244. ipaq_map[0].virt = (__u32)ioremap(0x0, 0x04000000);
  245. }
  246. #endif
  247. #ifdef CONFIG_SA1100_JORNADA720
  248. if (machine_is_jornada720()) {
  249. parts = jornada_partitions;
  250. nb_parts = ARRAY_SIZE(jornada_partitions);
  251. ipaq_map[0].size = jornada_max_flash_size;
  252. ipaq_map[0].set_vpp = jornada720_set_vpp;
  253. }
  254. #endif
  255. if (machine_is_ipaq()) { /* for iPAQs only */
  256. for(i=0; i<MAX_IPAQ_CS; i++) {
  257. printk(KERN_NOTICE "iPAQ flash: probing %d-bit flash bus, window=%lx with CFI.\n", ipaq_map[i].bankwidth*8, ipaq_map[i].virt);
  258. my_sub_mtd[i] = do_map_probe("cfi_probe", &ipaq_map[i]);
  259. if (!my_sub_mtd[i]) {
  260. printk(KERN_NOTICE "iPAQ flash: probing %d-bit flash bus, window=%lx with JEDEC.\n", ipaq_map[i].bankwidth*8, ipaq_map[i].virt);
  261. my_sub_mtd[i] = do_map_probe("jedec_probe", &ipaq_map[i]);
  262. }
  263. if (!my_sub_mtd[i]) {
  264. printk(KERN_NOTICE "iPAQ flash: failed to find flash.\n");
  265. if (i)
  266. break;
  267. else
  268. return -ENXIO;
  269. } else
  270. printk(KERN_NOTICE "iPAQ flash: found %d bytes\n", my_sub_mtd[i]->size);
  271. /* do we really need this debugging? --joshua 20030703 */
  272. // printk("my_sub_mtd[%d]=%p\n", i, my_sub_mtd[i]);
  273. my_sub_mtd[i]->owner = THIS_MODULE;
  274. tot_flashsize += my_sub_mtd[i]->size;
  275. }
  276. #ifdef CONFIG_MTD_CONCAT
  277. /* fix the asset location */
  278. # ifdef CONFIG_LAB
  279. h3xxx_partitions[1].size = tot_flashsize - 0x40000 - 0x80000 /* extra big boot block */;
  280. # else
  281. h3xxx_partitions[1].size = tot_flashsize - 2 * 0x40000;
  282. # endif
  283. h3xxx_partitions[2].offset = tot_flashsize - 0x40000;
  284. /* and concat the devices */
  285. mymtd = mtd_concat_create(&my_sub_mtd[0], i,
  286. "ipaq");
  287. if (!mymtd) {
  288. printk("Cannot create iPAQ concat device\n");
  289. return -ENXIO;
  290. }
  291. #else
  292. mymtd = my_sub_mtd[0];
  293. /*
  294. *In the very near future, command line partition parsing
  295. * will use the device name as 'mtd-id' instead of a value
  296. * passed to the parse_cmdline_partitions() routine. Since
  297. * the bootldr says 'ipaq', make sure it continues to work.
  298. */
  299. mymtd->name = "ipaq";
  300. if ((machine_is_h3600())) {
  301. # ifdef CONFIG_LAB
  302. h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x80000;
  303. # else
  304. h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x40000;
  305. # endif
  306. nb_parts = 2;
  307. } else {
  308. # ifdef CONFIG_LAB
  309. h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x40000 - 0x80000; /* extra big boot block */
  310. # else
  311. h3xxx_partitions[1].size = my_sub_mtd[0]->size - 2*0x40000;
  312. # endif
  313. h3xxx_partitions[2].offset = my_sub_mtd[0]->size - 0x40000;
  314. }
  315. if (my_sub_mtd[1]) {
  316. # ifdef CONFIG_LAB
  317. h3xxx_partitions_bank2[0].size = my_sub_mtd[1]->size - 0x80000;
  318. # else
  319. h3xxx_partitions_bank2[0].size = my_sub_mtd[1]->size - 0x40000;
  320. # endif
  321. h3xxx_partitions_bank2[1].offset = my_sub_mtd[1]->size - 0x40000;
  322. }
  323. #endif
  324. }
  325. else {
  326. /*
  327. * Now let's probe for the actual flash. Do it here since
  328. * specific machine settings might have been set above.
  329. */
  330. printk(KERN_NOTICE "IPAQ flash: probing %d-bit flash bus, window=%lx\n", ipaq_map[0].bankwidth*8, ipaq_map[0].virt);
  331. mymtd = do_map_probe("cfi_probe", &ipaq_map[0]);
  332. if (!mymtd)
  333. return -ENXIO;
  334. mymtd->owner = THIS_MODULE;
  335. }
  336. /*
  337. * Dynamic partition selection stuff (might override the static ones)
  338. */
  339. i = parse_mtd_partitions(mymtd, part_probes, &parsed_parts, 0);
  340. if (i > 0) {
  341. nb_parts = parsed_nr_parts = i;
  342. parts = parsed_parts;
  343. part_type = "dynamic";
  344. }
  345. if (!parts) {
  346. printk(KERN_NOTICE "IPAQ flash: no partition info available, registering whole flash at once\n");
  347. add_mtd_device(mymtd);
  348. #ifndef CONFIG_MTD_CONCAT
  349. if (my_sub_mtd[1])
  350. add_mtd_device(my_sub_mtd[1]);
  351. #endif
  352. } else {
  353. printk(KERN_NOTICE "Using %s partition definition\n", part_type);
  354. add_mtd_partitions(mymtd, parts, nb_parts);
  355. #ifndef CONFIG_MTD_CONCAT
  356. if (my_sub_mtd[1])
  357. add_mtd_partitions(my_sub_mtd[1], h3xxx_partitions_bank2, ARRAY_SIZE(h3xxx_partitions_bank2));
  358. #endif
  359. }
  360. return 0;
  361. }
  362. static void __exit ipaq_mtd_cleanup(void)
  363. {
  364. int i;
  365. if (mymtd) {
  366. del_mtd_partitions(mymtd);
  367. #ifndef CONFIG_MTD_CONCAT
  368. if (my_sub_mtd[1])
  369. del_mtd_partitions(my_sub_mtd[1]);
  370. #endif
  371. map_destroy(mymtd);
  372. #ifdef CONFIG_MTD_CONCAT
  373. for(i=0; i<MAX_IPAQ_CS; i++)
  374. #else
  375. for(i=1; i<MAX_IPAQ_CS; i++)
  376. #endif
  377. {
  378. if (my_sub_mtd[i])
  379. map_destroy(my_sub_mtd[i]);
  380. }
  381. kfree(parsed_parts);
  382. }
  383. }
  384. static int __init h1900_special_case(void)
  385. {
  386. /* The iPAQ h1900 is a special case - it has weird ROM. */
  387. simple_map_init(&ipaq_map[0]);
  388. ipaq_map[0].size = 0x80000;
  389. ipaq_map[0].set_vpp = h3xxx_set_vpp;
  390. ipaq_map[0].phys = 0x0;
  391. ipaq_map[0].virt = ioremap(0x0, 0x04000000);
  392. ipaq_map[0].bankwidth = 2;
  393. printk(KERN_NOTICE "iPAQ flash: probing %d-bit flash bus, window=%lx with JEDEC.\n", ipaq_map[0].bankwidth*8, ipaq_map[0].virt);
  394. mymtd = do_map_probe("jedec_probe", &ipaq_map[0]);
  395. if (!mymtd)
  396. return -ENODEV;
  397. add_mtd_device(mymtd);
  398. printk(KERN_NOTICE "iPAQ flash: registered h1910 flash\n");
  399. return 0;
  400. }
  401. module_init(ipaq_mtd_init);
  402. module_exit(ipaq_mtd_cleanup);
  403. MODULE_AUTHOR("Jamey Hicks");
  404. MODULE_DESCRIPTION("IPAQ CFI map driver");
  405. MODULE_LICENSE("MIT");