flash.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /*
  2. * (C) Copyright 2002
  3. * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  4. * Marius Groeger <mgroeger@sysgo.de>
  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. #include <common.h>
  25. #define FLASH_BANK_SIZE 0x800000
  26. #define MAIN_SECT_SIZE 0x20000
  27. #define PARAM_SECT_SIZE 0x4000
  28. flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
  29. /*-----------------------------------------------------------------------
  30. */
  31. ulong flash_init (void)
  32. {
  33. int i, j;
  34. ulong size = 0;
  35. for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
  36. ulong flashbase = 0;
  37. flash_info[i].flash_id =
  38. (INTEL_MANUFACT & FLASH_VENDMASK) |
  39. (INTEL_ID_28F320B3T & FLASH_TYPEMASK);
  40. flash_info[i].size = FLASH_BANK_SIZE;
  41. flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
  42. memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
  43. if (i == 0)
  44. flashbase = PHYS_FLASH_1;
  45. else if (i == 1)
  46. flashbase = PHYS_FLASH_2;
  47. else
  48. panic ("configured too many flash banks!\n");
  49. for (j = 0; j < flash_info[i].sector_count; j++) {
  50. if (j <= 7) {
  51. flash_info[i].start[j] =
  52. flashbase + j * PARAM_SECT_SIZE;
  53. } else {
  54. flash_info[i].start[j] =
  55. flashbase + (j - 7) * MAIN_SECT_SIZE;
  56. }
  57. }
  58. size += flash_info[i].size;
  59. }
  60. /* Protect monitor and environment sectors
  61. */
  62. flash_protect (FLAG_PROTECT_SET,
  63. CFG_FLASH_BASE,
  64. CFG_FLASH_BASE + monitor_flash_len - 1,
  65. &flash_info[0]);
  66. flash_protect (FLAG_PROTECT_SET,
  67. CONFIG_ENV_ADDR,
  68. CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
  69. return size;
  70. }
  71. /*-----------------------------------------------------------------------
  72. */
  73. void flash_print_info (flash_info_t * info)
  74. {
  75. int i;
  76. switch (info->flash_id & FLASH_VENDMASK) {
  77. case (INTEL_MANUFACT & FLASH_VENDMASK):
  78. printf ("Intel: ");
  79. break;
  80. default:
  81. printf ("Unknown Vendor ");
  82. break;
  83. }
  84. switch (info->flash_id & FLASH_TYPEMASK) {
  85. case (INTEL_ID_28F320B3T & FLASH_TYPEMASK):
  86. printf ("28F320F3B (16Mbit)\n");
  87. break;
  88. default:
  89. printf ("Unknown Chip Type\n");
  90. goto Done;
  91. break;
  92. }
  93. printf (" Size: %ld MB in %d Sectors\n",
  94. info->size >> 20, info->sector_count);
  95. printf (" Sector Start Addresses:");
  96. for (i = 0; i < info->sector_count; i++) {
  97. if ((i % 5) == 0) {
  98. printf ("\n ");
  99. }
  100. printf (" %08lX%s", info->start[i],
  101. info->protect[i] ? " (RO)" : " ");
  102. }
  103. printf ("\n");
  104. Done:;
  105. }
  106. /*-----------------------------------------------------------------------
  107. */
  108. int flash_erase (flash_info_t * info, int s_first, int s_last)
  109. {
  110. int flag, prot, sect;
  111. int rc = ERR_OK;
  112. if (info->flash_id == FLASH_UNKNOWN)
  113. return ERR_UNKNOWN_FLASH_TYPE;
  114. if ((s_first < 0) || (s_first > s_last)) {
  115. return ERR_INVAL;
  116. }
  117. if ((info->flash_id & FLASH_VENDMASK) !=
  118. (INTEL_MANUFACT & FLASH_VENDMASK)) {
  119. return ERR_UNKNOWN_FLASH_VENDOR;
  120. }
  121. prot = 0;
  122. for (sect = s_first; sect <= s_last; ++sect) {
  123. if (info->protect[sect]) {
  124. prot++;
  125. }
  126. }
  127. if (prot)
  128. return ERR_PROTECTED;
  129. /*
  130. * Disable interrupts which might cause a timeout
  131. * here. Remember that our exception vectors are
  132. * at address 0 in the flash, and we don't want a
  133. * (ticker) exception to happen while the flash
  134. * chip is in programming mode.
  135. */
  136. flag = disable_interrupts ();
  137. /* Start erase on unprotected sectors */
  138. for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
  139. printf ("Erasing sector %2d ... ", sect);
  140. /* arm simple, non interrupt dependent timer */
  141. reset_timer_masked ();
  142. if (info->protect[sect] == 0) { /* not protected */
  143. vu_long *addr = (vu_long *) (info->start[sect]);
  144. *addr = 0x00200020; /* erase setup */
  145. *addr = 0x00D000D0; /* erase confirm */
  146. while ((*addr & 0x00800080) != 0x00800080) {
  147. if (get_timer_masked () >
  148. CFG_FLASH_ERASE_TOUT) {
  149. *addr = 0x00B000B0; /* suspend erase */
  150. *addr = 0x00FF00FF; /* reset to read mode */
  151. rc = ERR_TIMOUT;
  152. goto outahere;
  153. }
  154. }
  155. *addr = 0x00FF00FF; /* reset to read mode */
  156. }
  157. printf ("ok.\n");
  158. }
  159. if (ctrlc ())
  160. printf ("User Interrupt!\n");
  161. outahere:
  162. /* allow flash to settle - wait 10 ms */
  163. udelay_masked (10000);
  164. if (flag)
  165. enable_interrupts ();
  166. return rc;
  167. }
  168. /*-----------------------------------------------------------------------
  169. * Copy memory to flash
  170. */
  171. static int write_word (flash_info_t * info, ulong dest, ulong data)
  172. {
  173. vu_long *addr = (vu_long *) dest;
  174. ulong barf;
  175. int rc = ERR_OK;
  176. int flag;
  177. /* Check if Flash is (sufficiently) erased
  178. */
  179. if ((*addr & data) != data)
  180. return ERR_NOT_ERASED;
  181. /*
  182. * Disable interrupts which might cause a timeout
  183. * here. Remember that our exception vectors are
  184. * at address 0 in the flash, and we don't want a
  185. * (ticker) exception to happen while the flash
  186. * chip is in programming mode.
  187. */
  188. flag = disable_interrupts ();
  189. /* clear status register command */
  190. *addr = 0x00500050;
  191. /* program set-up command */
  192. *addr = 0x00400040;
  193. /* latch address/data */
  194. *addr = data;
  195. /* arm simple, non interrupt dependent timer */
  196. reset_timer_masked ();
  197. /* read status register command */
  198. *addr = 0x00700070;
  199. /* wait while polling the status register */
  200. while ((*addr & 0x00800080) != 0x00800080) {
  201. if (get_timer_masked () > CFG_FLASH_WRITE_TOUT) {
  202. rc = ERR_TIMOUT;
  203. /* suspend program command */
  204. *addr = 0x00B000B0;
  205. goto outahere;
  206. }
  207. if (*addr & 0x003A003A) { /* check for error */
  208. barf = *addr;
  209. if (barf & 0x003A0000) {
  210. barf >>= 16;
  211. } else {
  212. barf &= 0x0000003A;
  213. }
  214. printf ("\nFlash write error %02lx at address %08lx\n", barf, (unsigned long) dest);
  215. if (barf & 0x0002) {
  216. printf ("Block locked, not erased.\n");
  217. rc = ERR_NOT_ERASED;
  218. goto outahere;
  219. }
  220. if (barf & 0x0010) {
  221. printf ("Programming error.\n");
  222. rc = ERR_PROG_ERROR;
  223. goto outahere;
  224. }
  225. if (barf & 0x0008) {
  226. printf ("Vpp Low error.\n");
  227. rc = ERR_PROG_ERROR;
  228. goto outahere;
  229. }
  230. rc = ERR_PROG_ERROR;
  231. goto outahere;
  232. }
  233. }
  234. outahere:
  235. /* read array command */
  236. *addr = 0x00FF00FF;
  237. if (flag)
  238. enable_interrupts ();
  239. return rc;
  240. }
  241. /*-----------------------------------------------------------------------
  242. * Copy memory to flash.
  243. */
  244. int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
  245. {
  246. ulong cp, wp, data;
  247. int l;
  248. int i, rc;
  249. wp = (addr & ~3); /* get lower word aligned address */
  250. /*
  251. * handle unaligned start bytes
  252. */
  253. if ((l = addr - wp) != 0) {
  254. data = 0;
  255. for (i = 0, cp = wp; i < l; ++i, ++cp) {
  256. data = (data >> 8) | (*(uchar *) cp << 24);
  257. }
  258. for (; i < 4 && cnt > 0; ++i) {
  259. data = (data >> 8) | (*src++ << 24);
  260. --cnt;
  261. ++cp;
  262. }
  263. for (; cnt == 0 && i < 4; ++i, ++cp) {
  264. data = (data >> 8) | (*(uchar *) cp << 24);
  265. }
  266. if ((rc = write_word (info, wp, data)) != 0) {
  267. return (rc);
  268. }
  269. wp += 4;
  270. }
  271. /*
  272. * handle word aligned part
  273. */
  274. while (cnt >= 4) {
  275. data = *((vu_long *) src);
  276. if ((rc = write_word (info, wp, data)) != 0) {
  277. return (rc);
  278. }
  279. src += 4;
  280. wp += 4;
  281. cnt -= 4;
  282. }
  283. if (cnt == 0) {
  284. return ERR_OK;
  285. }
  286. /*
  287. * handle unaligned tail bytes
  288. */
  289. data = 0;
  290. for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
  291. data = (data >> 8) | (*src++ << 24);
  292. --cnt;
  293. }
  294. for (; i < 4; ++i, ++cp) {
  295. data = (data >> 8) | (*(uchar *) cp << 24);
  296. }
  297. return write_word (info, wp, data);
  298. }