Advertisement
Guest User

Untitled

a guest
Sep 7th, 2010
283
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.18 KB | None | 0 0
  1. Index: linux-2.6.21/drivers/mtd/maps/ralink-flash.c
  2. ===================================================================
  3. --- /dev/null 1970-01-01 00:00:00.000000000 +0000
  4. +++ linux-2.6.21/drivers/mtd/maps/ralink-flash.c 2009-06-08 15:45:07.000000000 +0200
  5. @@ -0,0 +1,307 @@
  6. +/* ralink-flash.c
  7. + *
  8. + * Steven Liu <steven_liu@ralinktech.com.tw>:
  9. + * - initial approach
  10. + *
  11. + * Winfred Lu <winfred_lu@ralinktech.com.tw>:
  12. + * - 32MB flash support for RT3052
  13. + */
  14. +
  15. +#include <linux/module.h>
  16. +#include <linux/types.h>
  17. +#include <linux/init.h>
  18. +#include <linux/kernel.h>
  19. +
  20. +#include <asm/io.h>
  21. +#include <linux/mtd/mtd.h>
  22. +#include <linux/mtd/map.h>
  23. +#include <linux/mtd/concat.h>
  24. +#include <linux/mtd/partitions.h>
  25. +#include <linux/vmalloc.h>
  26. +#include <linux/squashfs_fs.h>
  27. +#include <linux/err.h>
  28. +
  29. +
  30. +#define WINDOW_ADDR CONFIG_MTD_PHYSMAP_START
  31. +#define WINDOW_SIZE CONFIG_MTD_PHYSMAP_LEN
  32. +#define NUM_FLASH_BANKS 1
  33. +
  34. +#define BUSWIDTH CONFIG_MTD_PHYSMAP_BUSWIDTH
  35. +
  36. +static struct mtd_info *ramips_mtd;
  37. +static struct map_info ramips_map = {
  38. + .name = "Ralink SoC physically mapped flash",
  39. + .bankwidth = BUSWIDTH,
  40. + .size = WINDOW_SIZE,
  41. + .phys = WINDOW_ADDR
  42. +};
  43. +
  44. +static struct mtd_partition ramips_partitions[] = {
  45. + {
  46. + name: "Bootloader",
  47. + size: 0x30000,
  48. + offset: 0,
  49. + }, {
  50. + name: "Config",
  51. + size: 0x10000,
  52. + offset: MTDPART_OFS_APPEND,
  53. + mask_flags: 0
  54. + }, {
  55. + name: "Factory",
  56. + size: 0x10000,
  57. + offset: MTDPART_OFS_APPEND,
  58. + // mask_flags: 0
  59. + }, {
  60. + name: "rootfs",
  61. + // size: CONFIG_MTD_KERNEL_PART_SIZ,
  62. + size: 0x400000 - 0x50000,
  63. + offset: 0x50000,
  64. + }
  65. +};
  66. +
  67. +static int ramips_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
  68. +{
  69. + return 0;
  70. +}
  71. +
  72. +static int ramips_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
  73. +{
  74. + return 0;
  75. +}
  76. +
  77. +int
  78. +find_uImage_size(unsigned long start_offset){
  79. + unsigned long temp, temp2;
  80. + memcpy_fromio(&temp, ramips_map.virt + start_offset + 12, 4);
  81. + temp2 = temp >> 24;
  82. + temp2 += (temp >> 8) & 0xff00;
  83. + temp2 += (temp << 8) & 0xff0000;
  84. + printk(KERN_INFO "ramips_mtd: kernel size is %ld \n", temp2 + 0x40);
  85. + return temp2 + 0x40;
  86. +}
  87. +
  88. +int
  89. +detect_squashfs_partition(unsigned long start_offset){
  90. + unsigned long temp;
  91. + memcpy_fromio(&temp, ramips_map.virt + start_offset, 4);
  92. + return (temp == 0x71736873 /*SQUASHFS_MAGIC*/);
  93. +}
  94. +
  95. +int __init ramips_mtd_init(void)
  96. +{
  97. + int ret = -ENXIO;
  98. + int k_size = 0;
  99. +
  100. + ramips_map.virt = ioremap(ramips_map.phys, ramips_map.size);
  101. + if(!ramips_map.virt)
  102. + {
  103. + printk(KERN_ERR "ramips_mtd: failed to ioremap\n");
  104. + return -EIO;
  105. + }
  106. +
  107. + simple_map_init(&ramips_map);
  108. + ramips_mtd = do_map_probe("cfi_probe", &ramips_map);
  109. + if(!ramips_mtd)
  110. + {
  111. + iounmap(ramips_map.virt);
  112. + printk("ramips_mtd: now flash found\n");
  113. + return -ENXIO;
  114. + }
  115. +
  116. + ramips_mtd->owner = THIS_MODULE;
  117. + ramips_mtd->lock = ramips_lock;
  118. + ramips_mtd->unlock = ramips_unlock;
  119. +
  120. + k_size = find_uImage_size(ramips_partitions[3].offset);
  121. + if(detect_squashfs_partition(ramips_partitions[3].offset + k_size))
  122. + {
  123. + printk(KERN_INFO "found a squashfs directly behind uImage\n");
  124. + ramips_partitions[4].offset = ramips_partitions[3].offset + k_size;
  125. + ramips_partitions[4].size = 0x800000 - (ramips_partitions[3].offset + k_size);
  126. + }
  127. + ret = add_mtd_partitions(ramips_mtd, ramips_partitions,ARRAY_SIZE(ramips_partitions));
  128. +
  129. + printk(KERN_NOTICE "ramips_mtd: 0x%lx at 0x%x\n", ramips_map.size, ramips_map.phys);
  130. +
  131. + return ret;
  132. +}
  133. +
  134. +static void __exit ramips_mtd_cleanup(void)
  135. +{
  136. + if(ramips_mtd)
  137. + map_destroy(ramips_mtd);
  138. +
  139. + if(ramips_map.virt)
  140. + iounmap(ramips_map.virt);
  141. +}
  142. +
  143. +module_init(ramips_mtd_init);
  144. +module_exit(ramips_mtd_cleanup);
  145. +
  146. +MODULE_AUTHOR("Steven Liu <steven_liu@ralinktech.com.tw>");
  147. +MODULE_DESCRIPTION("Ralink APSoC Flash Map");
  148. +MODULE_LICENSE("GPL");
  149. +
  150. +
  151. +/*
  152. + * Flash API: ra_mtd_read, ra_mtd_write
  153. + * Arguments:
  154. + * - num: specific the mtd number
  155. + * - to/from: the offset to read from or written to
  156. + * - len: length
  157. + * - buf: data to be read/written
  158. + * Returns:
  159. + * - return -errno if failed
  160. + * - return the number of bytes read/written if successed
  161. + */
  162. +int ra_mtd_write(int num, loff_t to, size_t len, const u_char *buf)
  163. +{
  164. + int ret = -1;
  165. + size_t rdlen, wrlen;
  166. + struct mtd_info *mtd;
  167. + struct erase_info ei;
  168. + u_char *bak = NULL;
  169. +
  170. + mtd = get_mtd_device(NULL, num);
  171. + if (IS_ERR(mtd))
  172. + return (int)mtd;
  173. + if (len > mtd->erasesize) {
  174. + put_mtd_device(mtd);
  175. + return -E2BIG;
  176. + }
  177. +
  178. + bak = kmalloc(mtd->erasesize, GFP_KERNEL);
  179. + if (bak == NULL) {
  180. + put_mtd_device(mtd);
  181. + return -ENOMEM;
  182. + }
  183. +
  184. + ret = mtd->read(mtd, 0, mtd->erasesize, &rdlen, bak);
  185. + if (ret != 0) {
  186. + put_mtd_device(mtd);
  187. + kfree(bak);
  188. + return ret;
  189. + }
  190. + if (rdlen != mtd->erasesize)
  191. + printk("warning: ra_mtd_write: rdlen is not equal to erasesize\n");
  192. +
  193. + memcpy(bak + to, buf, len);
  194. +
  195. + ei.mtd = mtd;
  196. + ei.callback = NULL;
  197. + ei.addr = 0;
  198. + ei.len = mtd->erasesize;
  199. + ei.priv = 0;
  200. + ret = mtd->erase(mtd, &ei);
  201. + if (ret != 0) {
  202. + put_mtd_device(mtd);
  203. + kfree(bak);
  204. + return ret;
  205. + }
  206. +
  207. + ret = mtd->write(mtd, 0, mtd->erasesize, &wrlen, bak);
  208. +
  209. + put_mtd_device(mtd);
  210. + kfree(bak);
  211. + return ret;
  212. +}
  213. +
  214. +int ra_mtd_write_nm(char *name, loff_t to, size_t len, const u_char *buf)
  215. +{
  216. + int ret = -1;
  217. + size_t rdlen, wrlen;
  218. + struct mtd_info *mtd;
  219. + struct erase_info ei;
  220. + u_char *bak = NULL;
  221. +
  222. + mtd = get_mtd_device_nm(name);
  223. + if (IS_ERR(mtd))
  224. + return (int)mtd;
  225. + if (len > mtd->erasesize) {
  226. + put_mtd_device(mtd);
  227. + return -E2BIG;
  228. + }
  229. +
  230. + bak = kmalloc(mtd->erasesize, GFP_KERNEL);
  231. + if (bak == NULL) {
  232. + put_mtd_device(mtd);
  233. + return -ENOMEM;
  234. + }
  235. +
  236. + ret = mtd->read(mtd, 0, mtd->erasesize, &rdlen, bak);
  237. + if (ret != 0) {
  238. + put_mtd_device(mtd);
  239. + kfree(bak);
  240. + return ret;
  241. + }
  242. + if (rdlen != mtd->erasesize)
  243. + printk("warning: ra_mtd_write: rdlen is not equal to erasesize\n");
  244. +
  245. + memcpy(bak + to, buf, len);
  246. +
  247. + ei.mtd = mtd;
  248. + ei.callback = NULL;
  249. + ei.addr = 0;
  250. + ei.len = mtd->erasesize;
  251. + ei.priv = 0;
  252. + ret = mtd->erase(mtd, &ei);
  253. + if (ret != 0) {
  254. + put_mtd_device(mtd);
  255. + kfree(bak);
  256. + return ret;
  257. + }
  258. +
  259. + ret = mtd->write(mtd, 0, mtd->erasesize, &wrlen, bak);
  260. +
  261. + put_mtd_device(mtd);
  262. + kfree(bak);
  263. + return ret;
  264. +}
  265. +
  266. +int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf)
  267. +{
  268. + int ret;
  269. + size_t rdlen;
  270. + struct mtd_info *mtd;
  271. +
  272. + mtd = get_mtd_device(NULL, num);
  273. + if (IS_ERR(mtd))
  274. + return (int)mtd;
  275. +
  276. + ret = mtd->read(mtd, from, len, &rdlen, buf);
  277. + if (rdlen != len)
  278. + printk("warning: ra_mtd_read: rdlen is not equal to len\n");
  279. +
  280. + put_mtd_device(mtd);
  281. + return ret;
  282. +}
  283. +
  284. +int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf)
  285. +{
  286. + int ret;
  287. + size_t rdlen;
  288. + struct mtd_info *mtd;
  289. +
  290. + mtd = get_mtd_device_nm(name);
  291. + if (IS_ERR(mtd))
  292. + return (int)mtd;
  293. +
  294. + ret = mtd->read(mtd, from, len, &rdlen, buf);
  295. + if (rdlen != len)
  296. + printk("warning: ra_mtd_read_nm: rdlen is not equal to len\n");
  297. +
  298. + put_mtd_device(mtd);
  299. + return ret;
  300. +}
  301. +
  302. +EXPORT_SYMBOL(ra_mtd_write);
  303. +EXPORT_SYMBOL(ra_mtd_read);
  304. +EXPORT_SYMBOL(ra_mtd_write_nm);
  305. +EXPORT_SYMBOL(ra_mtd_read_nm);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement