fortunet.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /* fortunet.c memory map
  2. *
  3. */
  4. #include <linux/module.h>
  5. #include <linux/types.h>
  6. #include <linux/kernel.h>
  7. #include <linux/init.h>
  8. #include <linux/string.h>
  9. #include <linux/mtd/mtd.h>
  10. #include <linux/mtd/map.h>
  11. #include <linux/mtd/partitions.h>
  12. #include <asm/io.h>
  13. #define MAX_NUM_REGIONS 4
  14. #define MAX_NUM_PARTITIONS 8
  15. #define DEF_WINDOW_ADDR_PHY 0x00000000
  16. #define DEF_WINDOW_SIZE 0x00800000 // 8 Mega Bytes
  17. #define MTD_FORTUNET_PK "MTD FortuNet: "
  18. #define MAX_NAME_SIZE 128
  19. struct map_region
  20. {
  21. int window_addr_physical;
  22. int altbankwidth;
  23. struct map_info map_info;
  24. struct mtd_info *mymtd;
  25. struct mtd_partition parts[MAX_NUM_PARTITIONS];
  26. char map_name[MAX_NAME_SIZE];
  27. char parts_name[MAX_NUM_PARTITIONS][MAX_NAME_SIZE];
  28. };
  29. static struct map_region map_regions[MAX_NUM_REGIONS];
  30. static int map_regions_set[MAX_NUM_REGIONS] = {0,0,0,0};
  31. static int map_regions_parts[MAX_NUM_REGIONS] = {0,0,0,0};
  32. struct map_info default_map = {
  33. .size = DEF_WINDOW_SIZE,
  34. .bankwidth = 4,
  35. };
  36. static char * __init get_string_option(char *dest,int dest_size,char *sor)
  37. {
  38. if(!dest_size)
  39. return sor;
  40. dest_size--;
  41. while(*sor)
  42. {
  43. if(*sor==',')
  44. {
  45. sor++;
  46. break;
  47. }
  48. else if(*sor=='\"')
  49. {
  50. sor++;
  51. while(*sor)
  52. {
  53. if(*sor=='\"')
  54. {
  55. sor++;
  56. break;
  57. }
  58. *dest = *sor;
  59. dest++;
  60. sor++;
  61. dest_size--;
  62. if(!dest_size)
  63. {
  64. *dest = 0;
  65. return sor;
  66. }
  67. }
  68. }
  69. else
  70. {
  71. *dest = *sor;
  72. dest++;
  73. sor++;
  74. dest_size--;
  75. if(!dest_size)
  76. {
  77. *dest = 0;
  78. return sor;
  79. }
  80. }
  81. }
  82. *dest = 0;
  83. return sor;
  84. }
  85. static int __init MTD_New_Region(char *line)
  86. {
  87. char string[MAX_NAME_SIZE];
  88. int params[6];
  89. get_options (get_string_option(string,sizeof(string),line),6,params);
  90. if(params[0]<1)
  91. {
  92. printk(MTD_FORTUNET_PK "Bad parameters for MTD Region "
  93. " name,region-number[,base,size,bankwidth,altbankwidth]\n");
  94. return 1;
  95. }
  96. if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS))
  97. {
  98. printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n",
  99. params[1],MAX_NUM_REGIONS-1);
  100. return 1;
  101. }
  102. memset(&map_regions[params[1]],0,sizeof(map_regions[params[1]]));
  103. memcpy(&map_regions[params[1]].map_info,
  104. &default_map,sizeof(map_regions[params[1]].map_info));
  105. map_regions_set[params[1]] = 1;
  106. map_regions[params[1]].window_addr_physical = DEF_WINDOW_ADDR_PHY;
  107. map_regions[params[1]].altbankwidth = 2;
  108. map_regions[params[1]].mymtd = NULL;
  109. map_regions[params[1]].map_info.name = map_regions[params[1]].map_name;
  110. strcpy(map_regions[params[1]].map_info.name,string);
  111. if(params[0]>1)
  112. {
  113. map_regions[params[1]].window_addr_physical = params[2];
  114. }
  115. if(params[0]>2)
  116. {
  117. map_regions[params[1]].map_info.size = params[3];
  118. }
  119. if(params[0]>3)
  120. {
  121. map_regions[params[1]].map_info.bankwidth = params[4];
  122. }
  123. if(params[0]>4)
  124. {
  125. map_regions[params[1]].altbankwidth = params[5];
  126. }
  127. return 1;
  128. }
  129. static int __init MTD_New_Partition(char *line)
  130. {
  131. char string[MAX_NAME_SIZE];
  132. int params[4];
  133. get_options (get_string_option(string,sizeof(string),line),4,params);
  134. if(params[0]<3)
  135. {
  136. printk(MTD_FORTUNET_PK "Bad parameters for MTD Partition "
  137. " name,region-number,size,offset\n");
  138. return 1;
  139. }
  140. if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS))
  141. {
  142. printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n",
  143. params[1],MAX_NUM_REGIONS-1);
  144. return 1;
  145. }
  146. if(map_regions_parts[params[1]]>=MAX_NUM_PARTITIONS)
  147. {
  148. printk(MTD_FORTUNET_PK "Out of space for partition in this region\n");
  149. return 1;
  150. }
  151. map_regions[params[1]].parts[map_regions_parts[params[1]]].name =
  152. map_regions[params[1]]. parts_name[map_regions_parts[params[1]]];
  153. strcpy(map_regions[params[1]].parts[map_regions_parts[params[1]]].name,string);
  154. map_regions[params[1]].parts[map_regions_parts[params[1]]].size =
  155. params[2];
  156. map_regions[params[1]].parts[map_regions_parts[params[1]]].offset =
  157. params[3];
  158. map_regions[params[1]].parts[map_regions_parts[params[1]]].mask_flags = 0;
  159. map_regions_parts[params[1]]++;
  160. return 1;
  161. }
  162. __setup("MTD_Region=", MTD_New_Region);
  163. __setup("MTD_Partition=", MTD_New_Partition);
  164. /* Backwards-spelling-compatibility */
  165. __setup("MTD_Partion=", MTD_New_Partition);
  166. static int __init init_fortunet(void)
  167. {
  168. int ix,iy;
  169. for(iy=ix=0;ix<MAX_NUM_REGIONS;ix++)
  170. {
  171. if(map_regions_parts[ix]&&(!map_regions_set[ix]))
  172. {
  173. printk(MTD_FORTUNET_PK "Region %d is not setup (Setting to default)\n",
  174. ix);
  175. memset(&map_regions[ix],0,sizeof(map_regions[ix]));
  176. memcpy(&map_regions[ix].map_info,&default_map,
  177. sizeof(map_regions[ix].map_info));
  178. map_regions_set[ix] = 1;
  179. map_regions[ix].window_addr_physical = DEF_WINDOW_ADDR_PHY;
  180. map_regions[ix].altbankwidth = 2;
  181. map_regions[ix].mymtd = NULL;
  182. map_regions[ix].map_info.name = map_regions[ix].map_name;
  183. strcpy(map_regions[ix].map_info.name,"FORTUNET");
  184. }
  185. if(map_regions_set[ix])
  186. {
  187. iy++;
  188. printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash device at physically "
  189. " address %x size %x\n",
  190. map_regions[ix].map_info.name,
  191. map_regions[ix].window_addr_physical,
  192. map_regions[ix].map_info.size);
  193. map_regions[ix].map_info.phys = map_regions[ix].window_addr_physical,
  194. map_regions[ix].map_info.virt =
  195. ioremap_nocache(
  196. map_regions[ix].window_addr_physical,
  197. map_regions[ix].map_info.size);
  198. if(!map_regions[ix].map_info.virt)
  199. {
  200. int j = 0;
  201. printk(MTD_FORTUNET_PK "%s flash failed to ioremap!\n",
  202. map_regions[ix].map_info.name);
  203. for (j = 0 ; j < ix; j++)
  204. iounmap(map_regions[j].map_info.virt);
  205. return -ENXIO;
  206. }
  207. simple_map_init(&map_regions[ix].map_info);
  208. printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash is virtually at: %x\n",
  209. map_regions[ix].map_info.name,
  210. map_regions[ix].map_info.virt);
  211. map_regions[ix].mymtd = do_map_probe("cfi_probe",
  212. &map_regions[ix].map_info);
  213. if((!map_regions[ix].mymtd)&&(
  214. map_regions[ix].altbankwidth!=map_regions[ix].map_info.bankwidth))
  215. {
  216. printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternate bankwidth "
  217. "for %s flash.\n",
  218. map_regions[ix].map_info.name);
  219. map_regions[ix].map_info.bankwidth =
  220. map_regions[ix].altbankwidth;
  221. map_regions[ix].mymtd = do_map_probe("cfi_probe",
  222. &map_regions[ix].map_info);
  223. }
  224. map_regions[ix].mymtd->owner = THIS_MODULE;
  225. mtd_device_register(map_regions[ix].mymtd,
  226. map_regions[ix].parts,
  227. map_regions_parts[ix]);
  228. }
  229. }
  230. if(iy)
  231. return 0;
  232. return -ENXIO;
  233. }
  234. static void __exit cleanup_fortunet(void)
  235. {
  236. int ix;
  237. for(ix=0;ix<MAX_NUM_REGIONS;ix++)
  238. {
  239. if(map_regions_set[ix])
  240. {
  241. if( map_regions[ix].mymtd )
  242. {
  243. mtd_device_unregister(map_regions[ix].mymtd);
  244. map_destroy( map_regions[ix].mymtd );
  245. }
  246. iounmap((void *)map_regions[ix].map_info.virt);
  247. }
  248. }
  249. }
  250. module_init(init_fortunet);
  251. module_exit(cleanup_fortunet);
  252. MODULE_AUTHOR("FortuNet, Inc.");
  253. MODULE_DESCRIPTION("MTD map driver for FortuNet boards");