fortunet.c 6.7 KB

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