flash.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. /*
  2. * (C) Copyright 2002
  3. * Lineo, Inc. <www.lineo.com>
  4. * Bernhard Kuhn <bkuhn@lineo.com>
  5. *
  6. * (C) Copyright 2002
  7. * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  8. * Alex Zuepke <azu@sysgo.de>
  9. *
  10. * See file CREDITS for list of people who contributed to this
  11. * project.
  12. *
  13. * This program is free software; you can redistribute it and/or
  14. * modify it under the terms of the GNU General Public License as
  15. * published by the Free Software Foundation; either version 2 of
  16. * the License, or (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  26. * MA 02111-1307 USA
  27. */
  28. #include <common.h>
  29. ulong myflush(void);
  30. #define FLASH_BANK_SIZE 0x200000 /* 2 MB */
  31. #define MAIN_SECT_SIZE 0x10000 /* 64 KB */
  32. flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
  33. #define CMD_READ_ARRAY 0x00F0
  34. #define CMD_UNLOCK1 0x00AA
  35. #define CMD_UNLOCK2 0x0055
  36. #define CMD_ERASE_SETUP 0x0080
  37. #define CMD_ERASE_CONFIRM 0x0030
  38. #define CMD_PROGRAM 0x00A0
  39. #define CMD_UNLOCK_BYPASS 0x0020
  40. #define MEM_FLASH_ADDR1 (*(volatile u16 *)(CFG_FLASH_BASE + (0x00005555<<1)))
  41. #define MEM_FLASH_ADDR2 (*(volatile u16 *)(CFG_FLASH_BASE + (0x00002AAA<<1)))
  42. #define BIT_ERASE_DONE 0x0080
  43. #define BIT_RDY_MASK 0x0080
  44. #define BIT_PROGRAM_ERROR 0x0020
  45. #define BIT_TIMEOUT 0x80000000 /* our flag */
  46. #define READY 1
  47. #define ERR 2
  48. #define TMO 4
  49. /*-----------------------------------------------------------------------
  50. */
  51. ulong flash_init(void)
  52. {
  53. int i, j;
  54. ulong size = 0;
  55. for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)
  56. {
  57. ulong flashbase = 0;
  58. flash_info[i].flash_id =
  59. (ATM_MANUFACT & FLASH_VENDMASK) |
  60. (ATM_ID_BV1614 & FLASH_TYPEMASK);
  61. flash_info[i].size = FLASH_BANK_SIZE;
  62. flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
  63. memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
  64. if (i == 0)
  65. flashbase = PHYS_FLASH_1;
  66. else
  67. panic("configured to many flash banks!\n");
  68. for (j = 0; j < flash_info[i].sector_count; j++)
  69. {
  70. if (j <= 9)
  71. {
  72. /* 1st to 8th are 8 KB */
  73. if (j <= 7)
  74. {
  75. flash_info[i].start[j] = flashbase + j*0x2000;
  76. }
  77. /* 9th and 10th are both 32 KB */
  78. if ((j == 8) || (j == 9))
  79. {
  80. flash_info[i].start[j] = flashbase + 0x10000 + (j-8)*0x8000;
  81. }
  82. }
  83. else
  84. {
  85. flash_info[i].start[j] = flashbase + (j-8)*MAIN_SECT_SIZE;
  86. }
  87. }
  88. size += flash_info[i].size;
  89. }
  90. flash_protect(FLAG_PROTECT_SET,
  91. CFG_FLASH_BASE,
  92. CFG_ENV_ADDR - 1,
  93. &flash_info[0]);
  94. flash_protect(FLAG_PROTECT_SET,
  95. CFG_ENV_ADDR,
  96. CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
  97. &flash_info[0]);
  98. return size;
  99. }
  100. /*-----------------------------------------------------------------------
  101. */
  102. void flash_print_info (flash_info_t *info)
  103. {
  104. int i;
  105. switch (info->flash_id & FLASH_VENDMASK)
  106. {
  107. case (ATM_MANUFACT & FLASH_VENDMASK):
  108. printf("Atmel: ");
  109. break;
  110. default:
  111. printf("Unknown Vendor ");
  112. break;
  113. }
  114. switch (info->flash_id & FLASH_TYPEMASK)
  115. {
  116. case (ATM_ID_BV1614 & FLASH_TYPEMASK):
  117. printf("AT49BV1614 (16Mbit)\n");
  118. break;
  119. default:
  120. printf("Unknown Chip Type\n");
  121. goto Done;
  122. break;
  123. }
  124. printf(" Size: %ld MB in %d Sectors\n",
  125. info->size >> 20, info->sector_count);
  126. printf(" Sector Start Addresses:");
  127. for (i = 0; i < info->sector_count; i++)
  128. {
  129. if ((i % 5) == 0)
  130. {
  131. printf ("\n ");
  132. }
  133. printf (" %08lX%s", info->start[i],
  134. info->protect[i] ? " (RO)" : " ");
  135. }
  136. printf ("\n");
  137. Done:
  138. }
  139. /*-----------------------------------------------------------------------
  140. */
  141. int flash_erase (flash_info_t *info, int s_first, int s_last)
  142. {
  143. ulong result;
  144. int iflag, cflag, prot, sect;
  145. int rc = ERR_OK;
  146. int chip1;
  147. /* first look for protection bits */
  148. if (info->flash_id == FLASH_UNKNOWN)
  149. return ERR_UNKNOWN_FLASH_TYPE;
  150. if ((s_first < 0) || (s_first > s_last)) {
  151. return ERR_INVAL;
  152. }
  153. if ((info->flash_id & FLASH_VENDMASK) !=
  154. (ATM_MANUFACT & FLASH_VENDMASK)) {
  155. return ERR_UNKNOWN_FLASH_VENDOR;
  156. }
  157. prot = 0;
  158. for (sect=s_first; sect<=s_last; ++sect) {
  159. if (info->protect[sect]) {
  160. prot++;
  161. }
  162. }
  163. if (prot)
  164. return ERR_PROTECTED;
  165. /*
  166. * Disable interrupts which might cause a timeout
  167. * here. Remember that our exception vectors are
  168. * at address 0 in the flash, and we don't want a
  169. * (ticker) exception to happen while the flash
  170. * chip is in programming mode.
  171. */
  172. cflag = icache_status();
  173. icache_disable();
  174. iflag = disable_interrupts();
  175. /* Start erase on unprotected sectors */
  176. for (sect = s_first; sect<=s_last && !ctrlc(); sect++)
  177. {
  178. printf("Erasing sector %2d ... ", sect);
  179. /* arm simple, non interrupt dependent timer */
  180. reset_timer_masked();
  181. if (info->protect[sect] == 0)
  182. { /* not protected */
  183. volatile u16 *addr = (volatile u16 *)(info->start[sect]);
  184. MEM_FLASH_ADDR1 = CMD_UNLOCK1;
  185. MEM_FLASH_ADDR2 = CMD_UNLOCK2;
  186. MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
  187. MEM_FLASH_ADDR1 = CMD_UNLOCK1;
  188. MEM_FLASH_ADDR2 = CMD_UNLOCK2;
  189. *addr = CMD_ERASE_CONFIRM;
  190. /* wait until flash is ready */
  191. chip1 = 0;
  192. do
  193. {
  194. result = *addr;
  195. /* check timeout */
  196. if (get_timer_masked() > CFG_FLASH_ERASE_TOUT)
  197. {
  198. MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
  199. chip1 = TMO;
  200. break;
  201. }
  202. if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE)
  203. chip1 = READY;
  204. } while (!chip1);
  205. MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
  206. if (chip1 == ERR)
  207. {
  208. rc = ERR_PROG_ERROR;
  209. goto outahere;
  210. }
  211. if (chip1 == TMO)
  212. {
  213. rc = ERR_TIMOUT;
  214. goto outahere;
  215. }
  216. printf("ok.\n");
  217. }
  218. else /* it was protected */
  219. {
  220. printf("protected!\n");
  221. }
  222. }
  223. if (ctrlc())
  224. printf("User Interrupt!\n");
  225. outahere:
  226. /* allow flash to settle - wait 10 ms */
  227. udelay_masked(10000);
  228. if (iflag)
  229. enable_interrupts();
  230. if (cflag)
  231. icache_enable();
  232. return rc;
  233. }
  234. /*-----------------------------------------------------------------------
  235. * Copy memory to flash
  236. */
  237. volatile static int write_word (flash_info_t *info, ulong dest, ulong data)
  238. {
  239. volatile u16 *addr = (volatile u16 *)dest;
  240. ulong result;
  241. int rc = ERR_OK;
  242. int cflag, iflag;
  243. int chip1;
  244. /*
  245. * Check if Flash is (sufficiently) erased
  246. */
  247. result = *addr;
  248. if ((result & data) != data)
  249. return ERR_NOT_ERASED;
  250. /*
  251. * Disable interrupts which might cause a timeout
  252. * here. Remember that our exception vectors are
  253. * at address 0 in the flash, and we don't want a
  254. * (ticker) exception to happen while the flash
  255. * chip is in programming mode.
  256. */
  257. cflag = icache_status();
  258. icache_disable();
  259. iflag = disable_interrupts();
  260. MEM_FLASH_ADDR1 = CMD_UNLOCK1;
  261. MEM_FLASH_ADDR2 = CMD_UNLOCK2;
  262. MEM_FLASH_ADDR1 = CMD_PROGRAM;
  263. *addr = data;
  264. /* arm simple, non interrupt dependent timer */
  265. reset_timer_masked();
  266. /* wait until flash is ready */
  267. chip1 = 0;
  268. do
  269. {
  270. result = *addr;
  271. /* check timeout */
  272. if (get_timer_masked() > CFG_FLASH_ERASE_TOUT)
  273. {
  274. chip1 = ERR | TMO;
  275. break;
  276. }
  277. if (!chip1 && ((result & 0x80) == (data & 0x80)))
  278. chip1 = READY;
  279. } while (!chip1);
  280. *addr = CMD_READ_ARRAY;
  281. if (chip1 == ERR || *addr != data)
  282. rc = ERR_PROG_ERROR;
  283. if (iflag)
  284. enable_interrupts();
  285. if (cflag)
  286. icache_enable();
  287. return rc;
  288. }
  289. /*-----------------------------------------------------------------------
  290. * Copy memory to flash.
  291. */
  292. int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
  293. {
  294. ulong wp, data;
  295. int rc;
  296. if(addr & 1) {
  297. printf("unaligned destination not supported\n");
  298. return ERR_ALIGN;
  299. };
  300. if((int)src & 1) {
  301. printf("unaligned source not supported\n");
  302. return ERR_ALIGN;
  303. };
  304. wp = addr;
  305. while (cnt >= 2) {
  306. data = *((volatile u16*)src);
  307. if ((rc = write_word(info, wp, data)) != 0) {
  308. return (rc);
  309. }
  310. src += 2;
  311. wp += 2;
  312. cnt -= 2;
  313. }
  314. if(cnt == 1) {
  315. data = (*((volatile u8*)src)) | (*((volatile u8*)(wp+1)) << 8);
  316. if ((rc = write_word(info, wp, data)) != 0) {
  317. return (rc);
  318. }
  319. src += 1;
  320. wp += 1;
  321. cnt -= 1;
  322. };
  323. return ERR_OK;
  324. }