sbc8240.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. * Handle mapping of the flash memory access routines on the SBC8240 board.
  3. *
  4. * Carolyn Smith, Tektronix, Inc.
  5. *
  6. * This code is GPLed
  7. *
  8. * $Id: sbc8240.c,v 1.5 2005/11/07 11:14:28 gleixner Exp $
  9. *
  10. */
  11. /*
  12. * The SBC8240 has 2 flash banks.
  13. * Bank 0 is a 512 KiB AMD AM29F040B; 8 x 64 KiB sectors.
  14. * It contains the U-Boot code (7 sectors) and the environment (1 sector).
  15. * Bank 1 is 4 x 1 MiB AMD AM29LV800BT; 15 x 64 KiB sectors, 1 x 32 KiB sector,
  16. * 2 x 8 KiB sectors, 1 x 16 KiB sectors.
  17. * Both parts are JEDEC compatible.
  18. */
  19. #include <linux/module.h>
  20. #include <linux/types.h>
  21. #include <linux/kernel.h>
  22. #include <asm/io.h>
  23. #include <linux/mtd/mtd.h>
  24. #include <linux/mtd/map.h>
  25. #include <linux/mtd/cfi.h>
  26. #ifdef CONFIG_MTD_PARTITIONS
  27. #include <linux/mtd/partitions.h>
  28. #endif
  29. #define DEBUG
  30. #ifdef DEBUG
  31. # define debugk(fmt,args...) printk(fmt ,##args)
  32. #else
  33. # define debugk(fmt,args...)
  34. #endif
  35. #define WINDOW_ADDR0 0xFFF00000 /* 512 KiB */
  36. #define WINDOW_SIZE0 0x00080000
  37. #define BUSWIDTH0 1
  38. #define WINDOW_ADDR1 0xFF000000 /* 4 MiB */
  39. #define WINDOW_SIZE1 0x00400000
  40. #define BUSWIDTH1 8
  41. #define MSG_PREFIX "sbc8240:" /* prefix for our printk()'s */
  42. #define MTDID "sbc8240-%d" /* for mtdparts= partitioning */
  43. static struct map_info sbc8240_map[2] = {
  44. {
  45. .name = "sbc8240 Flash Bank #0",
  46. .size = WINDOW_SIZE0,
  47. .bankwidth = BUSWIDTH0,
  48. },
  49. {
  50. .name = "sbc8240 Flash Bank #1",
  51. .size = WINDOW_SIZE1,
  52. .bankwidth = BUSWIDTH1,
  53. }
  54. };
  55. #define NUM_FLASH_BANKS ARRAY_SIZE(sbc8240_map)
  56. /*
  57. * The following defines the partition layout of SBC8240 boards.
  58. *
  59. * See include/linux/mtd/partitions.h for definition of the
  60. * mtd_partition structure.
  61. *
  62. * The *_max_flash_size is the maximum possible mapped flash size
  63. * which is not necessarily the actual flash size. It must correspond
  64. * to the value specified in the mapping definition defined by the
  65. * "struct map_desc *_io_desc" for the corresponding machine.
  66. */
  67. #ifdef CONFIG_MTD_PARTITIONS
  68. static struct mtd_partition sbc8240_uboot_partitions [] = {
  69. /* Bank 0 */
  70. {
  71. .name = "U-boot", /* U-Boot Firmware */
  72. .offset = 0,
  73. .size = 0x00070000, /* 7 x 64 KiB sectors */
  74. .mask_flags = MTD_WRITEABLE, /* force read-only */
  75. },
  76. {
  77. .name = "environment", /* U-Boot environment */
  78. .offset = 0x00070000,
  79. .size = 0x00010000, /* 1 x 64 KiB sector */
  80. },
  81. };
  82. static struct mtd_partition sbc8240_fs_partitions [] = {
  83. {
  84. .name = "jffs", /* JFFS filesystem */
  85. .offset = 0,
  86. .size = 0x003C0000, /* 4 * 15 * 64KiB */
  87. },
  88. {
  89. .name = "tmp32",
  90. .offset = 0x003C0000,
  91. .size = 0x00020000, /* 4 * 32KiB */
  92. },
  93. {
  94. .name = "tmp8a",
  95. .offset = 0x003E0000,
  96. .size = 0x00008000, /* 4 * 8KiB */
  97. },
  98. {
  99. .name = "tmp8b",
  100. .offset = 0x003E8000,
  101. .size = 0x00008000, /* 4 * 8KiB */
  102. },
  103. {
  104. .name = "tmp16",
  105. .offset = 0x003F0000,
  106. .size = 0x00010000, /* 4 * 16KiB */
  107. }
  108. };
  109. /* trivial struct to describe partition information */
  110. struct mtd_part_def
  111. {
  112. int nums;
  113. unsigned char *type;
  114. struct mtd_partition* mtd_part;
  115. };
  116. static struct mtd_info *sbc8240_mtd[NUM_FLASH_BANKS];
  117. static struct mtd_part_def sbc8240_part_banks[NUM_FLASH_BANKS];
  118. #endif /* CONFIG_MTD_PARTITIONS */
  119. int __init init_sbc8240_mtd (void)
  120. {
  121. static struct _cjs {
  122. u_long addr;
  123. u_long size;
  124. } pt[NUM_FLASH_BANKS] = {
  125. {
  126. .addr = WINDOW_ADDR0,
  127. .size = WINDOW_SIZE0
  128. },
  129. {
  130. .addr = WINDOW_ADDR1,
  131. .size = WINDOW_SIZE1
  132. },
  133. };
  134. int devicesfound = 0;
  135. int i,j;
  136. for (i = 0; i < NUM_FLASH_BANKS; i++) {
  137. printk (KERN_NOTICE MSG_PREFIX
  138. "Probing 0x%08lx at 0x%08lx\n", pt[i].size, pt[i].addr);
  139. sbc8240_map[i].map_priv_1 =
  140. (unsigned long) ioremap (pt[i].addr, pt[i].size);
  141. if (!sbc8240_map[i].map_priv_1) {
  142. printk (MSG_PREFIX "failed to ioremap\n");
  143. for (j = 0; j < i; j++) {
  144. iounmap((void *) sbc8240_map[j].map_priv_1);
  145. sbc8240_map[j].map_priv_1 = 0;
  146. }
  147. return -EIO;
  148. }
  149. simple_map_init(&sbc8240_mtd[i]);
  150. sbc8240_mtd[i] = do_map_probe("jedec_probe", &sbc8240_map[i]);
  151. if (sbc8240_mtd[i]) {
  152. sbc8240_mtd[i]->module = THIS_MODULE;
  153. devicesfound++;
  154. } else {
  155. if (sbc8240_map[i].map_priv_1) {
  156. iounmap((void *) sbc8240_map[i].map_priv_1);
  157. sbc8240_map[i].map_priv_1 = 0;
  158. }
  159. }
  160. }
  161. if (!devicesfound) {
  162. printk(KERN_NOTICE MSG_PREFIX
  163. "No suppported flash chips found!\n");
  164. return -ENXIO;
  165. }
  166. #ifdef CONFIG_MTD_PARTITIONS
  167. sbc8240_part_banks[0].mtd_part = sbc8240_uboot_partitions;
  168. sbc8240_part_banks[0].type = "static image";
  169. sbc8240_part_banks[0].nums = ARRAY_SIZE(sbc8240_uboot_partitions);
  170. sbc8240_part_banks[1].mtd_part = sbc8240_fs_partitions;
  171. sbc8240_part_banks[1].type = "static file system";
  172. sbc8240_part_banks[1].nums = ARRAY_SIZE(sbc8240_fs_partitions);
  173. for (i = 0; i < NUM_FLASH_BANKS; i++) {
  174. if (!sbc8240_mtd[i]) continue;
  175. if (sbc8240_part_banks[i].nums == 0) {
  176. printk (KERN_NOTICE MSG_PREFIX
  177. "No partition info available, registering whole device\n");
  178. add_mtd_device(sbc8240_mtd[i]);
  179. } else {
  180. printk (KERN_NOTICE MSG_PREFIX
  181. "Using %s partition definition\n", sbc8240_part_banks[i].mtd_part->name);
  182. add_mtd_partitions (sbc8240_mtd[i],
  183. sbc8240_part_banks[i].mtd_part,
  184. sbc8240_part_banks[i].nums);
  185. }
  186. }
  187. #else
  188. printk(KERN_NOTICE MSG_PREFIX
  189. "Registering %d flash banks at once\n", devicesfound);
  190. for (i = 0; i < devicesfound; i++) {
  191. add_mtd_device(sbc8240_mtd[i]);
  192. }
  193. #endif /* CONFIG_MTD_PARTITIONS */
  194. return devicesfound == 0 ? -ENXIO : 0;
  195. }
  196. static void __exit cleanup_sbc8240_mtd (void)
  197. {
  198. int i;
  199. for (i = 0; i < NUM_FLASH_BANKS; i++) {
  200. if (sbc8240_mtd[i]) {
  201. del_mtd_device (sbc8240_mtd[i]);
  202. map_destroy (sbc8240_mtd[i]);
  203. }
  204. if (sbc8240_map[i].map_priv_1) {
  205. iounmap ((void *) sbc8240_map[i].map_priv_1);
  206. sbc8240_map[i].map_priv_1 = 0;
  207. }
  208. }
  209. }
  210. module_init (init_sbc8240_mtd);
  211. module_exit (cleanup_sbc8240_mtd);
  212. MODULE_LICENSE ("GPL");
  213. MODULE_AUTHOR ("Carolyn Smith <carolyn.smith@tektronix.com>");
  214. MODULE_DESCRIPTION ("MTD map driver for SBC8240 boards");