cfi_mtd.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /*
  2. * (C) Copyright 2008 Semihalf
  3. *
  4. * Written by: Piotr Ziecik <kosmo@semihalf.com>
  5. *
  6. * See file CREDITS for list of people who contributed to this
  7. * project.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation; either version 2 of
  12. * the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22. * MA 02111-1307 USA
  23. *
  24. */
  25. #include <common.h>
  26. #include <flash.h>
  27. #include <malloc.h>
  28. #include <asm/errno.h>
  29. #include <linux/mtd/mtd.h>
  30. #include <linux/mtd/concat.h>
  31. extern flash_info_t flash_info[];
  32. static struct mtd_info cfi_mtd_info[CONFIG_SYS_MAX_FLASH_BANKS];
  33. static char cfi_mtd_names[CONFIG_SYS_MAX_FLASH_BANKS][16];
  34. #ifdef CONFIG_MTD_CONCAT
  35. static char c_mtd_name[16];
  36. #endif
  37. static int cfi_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
  38. {
  39. flash_info_t *fi = mtd->priv;
  40. size_t a_start = fi->start[0] + instr->addr;
  41. size_t a_end = a_start + instr->len;
  42. int s_first = -1;
  43. int s_last = -1;
  44. int error, sect;
  45. for (sect = 0; sect < fi->sector_count; sect++) {
  46. if (a_start == fi->start[sect])
  47. s_first = sect;
  48. if (sect < fi->sector_count - 1) {
  49. if (a_end == fi->start[sect + 1]) {
  50. s_last = sect;
  51. break;
  52. }
  53. } else {
  54. s_last = sect;
  55. break;
  56. }
  57. }
  58. if (s_first >= 0 && s_first <= s_last) {
  59. instr->state = MTD_ERASING;
  60. flash_set_verbose(0);
  61. error = flash_erase(fi, s_first, s_last);
  62. flash_set_verbose(1);
  63. if (error) {
  64. instr->state = MTD_ERASE_FAILED;
  65. return -EIO;
  66. }
  67. instr->state = MTD_ERASE_DONE;
  68. mtd_erase_callback(instr);
  69. return 0;
  70. }
  71. return -EINVAL;
  72. }
  73. static int cfi_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
  74. size_t *retlen, u_char *buf)
  75. {
  76. flash_info_t *fi = mtd->priv;
  77. u_char *f = (u_char*)(fi->start[0]) + from;
  78. memcpy(buf, f, len);
  79. *retlen = len;
  80. return 0;
  81. }
  82. static int cfi_mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
  83. size_t *retlen, const u_char *buf)
  84. {
  85. flash_info_t *fi = mtd->priv;
  86. u_long t = fi->start[0] + to;
  87. int error;
  88. flash_set_verbose(0);
  89. error = write_buff(fi, (u_char*)buf, t, len);
  90. flash_set_verbose(1);
  91. if (!error) {
  92. *retlen = len;
  93. return 0;
  94. }
  95. return -EIO;
  96. }
  97. static void cfi_mtd_sync(struct mtd_info *mtd)
  98. {
  99. /*
  100. * This function should wait until all pending operations
  101. * finish. However this driver is fully synchronous, so
  102. * this function returns immediately
  103. */
  104. }
  105. static int cfi_mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
  106. {
  107. flash_info_t *fi = mtd->priv;
  108. flash_set_verbose(0);
  109. flash_protect(FLAG_PROTECT_SET, fi->start[0] + ofs,
  110. fi->start[0] + ofs + len - 1, fi);
  111. flash_set_verbose(1);
  112. return 0;
  113. }
  114. static int cfi_mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
  115. {
  116. flash_info_t *fi = mtd->priv;
  117. flash_set_verbose(0);
  118. flash_protect(FLAG_PROTECT_CLEAR, fi->start[0] + ofs,
  119. fi->start[0] + ofs + len - 1, fi);
  120. flash_set_verbose(1);
  121. return 0;
  122. }
  123. static int cfi_mtd_set_erasesize(struct mtd_info *mtd, flash_info_t *fi)
  124. {
  125. int sect_size = 0;
  126. int sect_size_old = 0;
  127. int sect;
  128. int regions = 0;
  129. int numblocks = 0;
  130. ulong offset = 0;
  131. ulong base_addr = fi->start[0];
  132. /*
  133. * First detect the number of eraseregions so that we can allocate
  134. * the array of eraseregions correctly
  135. */
  136. for (sect = 0; sect < fi->sector_count; sect++) {
  137. if (sect_size_old != flash_sector_size(fi, sect))
  138. regions++;
  139. sect_size_old = flash_sector_size(fi, sect);
  140. }
  141. mtd->eraseregions = malloc(sizeof(struct mtd_erase_region_info) * regions);
  142. /*
  143. * Now detect the largest sector and fill the eraseregions
  144. */
  145. sect_size_old = 0;
  146. regions = 0;
  147. for (sect = 0; sect < fi->sector_count; sect++) {
  148. if ((sect_size_old != flash_sector_size(fi, sect)) &&
  149. (sect_size_old != 0)) {
  150. mtd->eraseregions[regions].offset = offset - base_addr;
  151. mtd->eraseregions[regions].erasesize = sect_size_old;
  152. mtd->eraseregions[regions].numblocks = numblocks;
  153. /* Now start counting the next eraseregions */
  154. numblocks = 0;
  155. regions++;
  156. } else {
  157. numblocks++;
  158. }
  159. if (sect_size_old != flash_sector_size(fi, sect))
  160. offset = fi->start[sect];
  161. /*
  162. * Select the largest sector size as erasesize (e.g. for UBI)
  163. */
  164. if (flash_sector_size(fi, sect) > sect_size)
  165. sect_size = flash_sector_size(fi, sect);
  166. sect_size_old = flash_sector_size(fi, sect);
  167. }
  168. /*
  169. * Set the last region
  170. */
  171. mtd->eraseregions[regions].offset = offset - base_addr;
  172. mtd->eraseregions[regions].erasesize = sect_size_old;
  173. mtd->eraseregions[regions].numblocks = numblocks + 1;
  174. if (regions)
  175. mtd->numeraseregions = regions + 1;
  176. else
  177. mtd->numeraseregions = 0;
  178. mtd->erasesize = sect_size;
  179. return 0;
  180. }
  181. int cfi_mtd_init(void)
  182. {
  183. struct mtd_info *mtd;
  184. flash_info_t *fi;
  185. int error, i;
  186. int devices_found = 0;
  187. struct mtd_info *mtd_list[CONFIG_SYS_MAX_FLASH_BANKS];
  188. for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
  189. fi = &flash_info[i];
  190. mtd = &cfi_mtd_info[i];
  191. memset(mtd, 0, sizeof(struct mtd_info));
  192. error = cfi_mtd_set_erasesize(mtd, fi);
  193. if (error)
  194. continue;
  195. sprintf(cfi_mtd_names[i], "nor%d", i);
  196. mtd->name = cfi_mtd_names[i];
  197. mtd->type = MTD_NORFLASH;
  198. mtd->flags = MTD_CAP_NORFLASH;
  199. mtd->size = fi->size;
  200. mtd->writesize = 1;
  201. mtd->erase = cfi_mtd_erase;
  202. mtd->read = cfi_mtd_read;
  203. mtd->write = cfi_mtd_write;
  204. mtd->sync = cfi_mtd_sync;
  205. mtd->lock = cfi_mtd_lock;
  206. mtd->unlock = cfi_mtd_unlock;
  207. mtd->priv = fi;
  208. if (add_mtd_device(mtd))
  209. return -ENOMEM;
  210. mtd_list[devices_found++] = mtd;
  211. }
  212. #ifdef CONFIG_MTD_CONCAT
  213. if (devices_found > 1) {
  214. /*
  215. * We detected multiple devices. Concatenate them together.
  216. */
  217. sprintf(c_mtd_name, "nor%d", devices_found);
  218. mtd = mtd_concat_create(mtd_list, devices_found, c_mtd_name);
  219. if (mtd == NULL)
  220. return -ENXIO;
  221. if (add_mtd_device(mtd))
  222. return -ENOMEM;
  223. }
  224. #endif /* CONFIG_MTD_CONCAT */
  225. return 0;
  226. }