flash.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. /*
  2. * (C) Copyright 2000-2003
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. *
  5. * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
  6. * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
  7. *
  8. * See file CREDITS for list of people who contributed to this
  9. * project.
  10. *
  11. * This program is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU General Public License as
  13. * published by the Free Software Foundation; either version 2 of
  14. * the License, or (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  24. * MA 02111-1307 USA
  25. */
  26. #include <common.h>
  27. #include <asm/immap.h>
  28. #ifndef CFG_FLASH_CFI
  29. typedef unsigned short FLASH_PORT_WIDTH;
  30. typedef volatile unsigned short FLASH_PORT_WIDTHV;
  31. #define FPW FLASH_PORT_WIDTH
  32. #define FPWV FLASH_PORT_WIDTHV
  33. #define FLASH_CYCLE1 0x5555
  34. #define FLASH_CYCLE2 0x2aaa
  35. #define SYNC __asm__("nop")
  36. /*-----------------------------------------------------------------------
  37. * Functions
  38. */
  39. ulong flash_get_size(FPWV * addr, flash_info_t * info);
  40. int flash_get_offsets(ulong base, flash_info_t * info);
  41. int write_word(flash_info_t * info, FPWV * dest, u16 data);
  42. void inline spin_wheel(void);
  43. flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
  44. ulong flash_init(void)
  45. {
  46. ulong size = 0;
  47. ulong fbase = 0;
  48. fbase = (ulong) CFG_FLASH_BASE;
  49. flash_get_size((FPWV *) fbase, &flash_info[0]);
  50. flash_get_offsets((ulong) fbase, &flash_info[0]);
  51. fbase += flash_info[0].size;
  52. size += flash_info[0].size;
  53. /* Protect monitor and environment sectors */
  54. flash_protect(FLAG_PROTECT_SET,
  55. CFG_MONITOR_BASE,
  56. CFG_MONITOR_BASE + monitor_flash_len - 1, &flash_info[0]);
  57. return size;
  58. }
  59. int flash_get_offsets(ulong base, flash_info_t * info)
  60. {
  61. int j, k;
  62. if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
  63. info->start[0] = base;
  64. for (k = 0, j = 0; j < CFG_SST_SECT; j++, k++) {
  65. info->start[k + 1] = info->start[k] + CFG_SST_SECTSZ;
  66. info->protect[k] = 0;
  67. }
  68. }
  69. return ERR_OK;
  70. }
  71. void flash_print_info(flash_info_t * info)
  72. {
  73. int i;
  74. switch (info->flash_id & FLASH_VENDMASK) {
  75. case FLASH_MAN_SST:
  76. printf("SST ");
  77. break;
  78. default:
  79. printf("Unknown Vendor ");
  80. break;
  81. }
  82. switch (info->flash_id & FLASH_TYPEMASK) {
  83. case FLASH_SST6401B:
  84. printf("SST39VF6401B\n");
  85. break;
  86. default:
  87. printf("Unknown Chip Type\n");
  88. return;
  89. }
  90. if (info->size > 0x100000) {
  91. int remainder;
  92. printf(" Size: %ld", info->size >> 20);
  93. remainder = (info->size % 0x100000);
  94. if (remainder) {
  95. remainder >>= 10;
  96. remainder = (int)((float)
  97. (((float)remainder / (float)1024) *
  98. 10000));
  99. printf(".%d ", remainder);
  100. }
  101. printf("MB in %d Sectors\n", info->sector_count);
  102. } else
  103. printf(" Size: %ld KB in %d Sectors\n",
  104. info->size >> 10, info->sector_count);
  105. printf(" Sector Start Addresses:");
  106. for (i = 0; i < info->sector_count; ++i) {
  107. if ((i % 5) == 0)
  108. printf("\n ");
  109. printf(" %08lX%s",
  110. info->start[i], info->protect[i] ? " (RO)" : " ");
  111. }
  112. printf("\n");
  113. }
  114. /*
  115. * The following code cannot be run from FLASH!
  116. */
  117. ulong flash_get_size(FPWV * addr, flash_info_t * info)
  118. {
  119. u16 value;
  120. addr[FLASH_CYCLE1] = (FPWV) 0x00AA00AA; /* for Atmel, Intel ignores this */
  121. addr[FLASH_CYCLE2] = (FPWV) 0x00550055; /* for Atmel, Intel ignores this */
  122. addr[FLASH_CYCLE1] = (FPWV) 0x00900090; /* selects Intel or Atmel */
  123. switch (addr[0] & 0xffff) {
  124. case (u8) SST_MANUFACT:
  125. info->flash_id = FLASH_MAN_SST;
  126. value = addr[1];
  127. break;
  128. default:
  129. printf("Unknown Flash\n");
  130. info->flash_id = FLASH_UNKNOWN;
  131. info->sector_count = 0;
  132. info->size = 0;
  133. *addr = (FPW) 0x00F000F0;
  134. return (0); /* no or unknown flash */
  135. }
  136. switch (value) {
  137. case (u16) SST_ID_xF6401B:
  138. info->flash_id += FLASH_SST6401B;
  139. break;
  140. default:
  141. info->flash_id = FLASH_UNKNOWN;
  142. break;
  143. }
  144. info->sector_count = 0;
  145. info->size = 0;
  146. info->sector_count = CFG_SST_SECT;
  147. info->size = CFG_SST_SECT * CFG_SST_SECTSZ;
  148. /* reset ID mode */
  149. *addr = (FPWV) 0x00F000F0;
  150. if (info->sector_count > CFG_MAX_FLASH_SECT) {
  151. printf("** ERROR: sector count %d > max (%d) **\n",
  152. info->sector_count, CFG_MAX_FLASH_SECT);
  153. info->sector_count = CFG_MAX_FLASH_SECT;
  154. }
  155. return (info->size);
  156. }
  157. int flash_erase(flash_info_t * info, int s_first, int s_last)
  158. {
  159. FPWV *addr;
  160. int flag, prot, sect, count;
  161. ulong type, start, last;
  162. int rcode = 0, flashtype = 0;
  163. if ((s_first < 0) || (s_first > s_last)) {
  164. if (info->flash_id == FLASH_UNKNOWN)
  165. printf("- missing\n");
  166. else
  167. printf("- no sectors to erase\n");
  168. return 1;
  169. }
  170. type = (info->flash_id & FLASH_VENDMASK);
  171. switch (type) {
  172. case FLASH_MAN_SST:
  173. flashtype = 1;
  174. break;
  175. default:
  176. type = (info->flash_id & FLASH_VENDMASK);
  177. printf("Can't erase unknown flash type %08lx - aborted\n",
  178. info->flash_id);
  179. return 1;
  180. }
  181. prot = 0;
  182. for (sect = s_first; sect <= s_last; ++sect) {
  183. if (info->protect[sect]) {
  184. prot++;
  185. }
  186. }
  187. if (prot)
  188. printf("- Warning: %d protected sectors will not be erased!\n",
  189. prot);
  190. else
  191. printf("\n");
  192. flag = disable_interrupts();
  193. start = get_timer(0);
  194. last = start;
  195. if ((s_last - s_first) == (CFG_SST_SECT - 1)) {
  196. if (prot == 0) {
  197. addr = (FPWV *) info->start[0];
  198. addr[FLASH_CYCLE1] = 0x00AA; /* unlock */
  199. addr[FLASH_CYCLE2] = 0x0055; /* unlock */
  200. addr[FLASH_CYCLE1] = 0x0080; /* erase mode */
  201. addr[FLASH_CYCLE1] = 0x00AA; /* unlock */
  202. addr[FLASH_CYCLE2] = 0x0055; /* unlock */
  203. *addr = 0x0030; /* erase chip */
  204. count = 0;
  205. start = get_timer(0);
  206. while ((*addr & 0x0080) != 0x0080) {
  207. if (count++ > 0x10000) {
  208. spin_wheel();
  209. count = 0;
  210. }
  211. if (get_timer(start) > CFG_FLASH_ERASE_TOUT) {
  212. printf("Timeout\n");
  213. *addr = 0x00F0; /* reset to read mode */
  214. return 1;
  215. }
  216. }
  217. *addr = 0x00F0; /* reset to read mode */
  218. printf("\b. done\n");
  219. if (flag)
  220. enable_interrupts();
  221. return 0;
  222. } else if (prot == CFG_SST_SECT) {
  223. return 1;
  224. }
  225. }
  226. /* Start erase on unprotected sectors */
  227. for (sect = s_first; sect <= s_last; sect++) {
  228. if (info->protect[sect] == 0) { /* not protected */
  229. addr = (FPWV *) (info->start[sect]);
  230. printf(".");
  231. /* arm simple, non interrupt dependent timer */
  232. start = get_timer(0);
  233. switch (flashtype) {
  234. case 1:
  235. {
  236. FPWV *base; /* first address in bank */
  237. flag = disable_interrupts();
  238. base = (FPWV *) (CFG_FLASH_BASE); /* First sector */
  239. base[FLASH_CYCLE1] = 0x00AA; /* unlock */
  240. base[FLASH_CYCLE2] = 0x0055; /* unlock */
  241. base[FLASH_CYCLE1] = 0x0080; /* erase mode */
  242. base[FLASH_CYCLE1] = 0x00AA; /* unlock */
  243. base[FLASH_CYCLE2] = 0x0055; /* unlock */
  244. *addr = 0x0050; /* erase sector */
  245. if (flag)
  246. enable_interrupts();
  247. while ((*addr & 0x0080) != 0x0080) {
  248. if (get_timer(start) >
  249. CFG_FLASH_ERASE_TOUT) {
  250. printf("Timeout\n");
  251. *addr = 0x00F0; /* reset to read mode */
  252. rcode = 1;
  253. break;
  254. }
  255. }
  256. *addr = 0x00F0; /* reset to read mode */
  257. break;
  258. }
  259. } /* switch (flashtype) */
  260. }
  261. }
  262. printf(" done\n");
  263. if (flag)
  264. enable_interrupts();
  265. return rcode;
  266. }
  267. int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
  268. {
  269. ulong wp, count;
  270. u16 data;
  271. int rc, port_width;
  272. if (info->flash_id == FLASH_UNKNOWN)
  273. return 4;
  274. /* get lower word aligned address */
  275. wp = addr;
  276. port_width = sizeof(FPW);
  277. /* handle unaligned start bytes */
  278. if (wp & 1) {
  279. data = *((FPWV *) wp);
  280. data = (data << 8) | *src;
  281. if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
  282. return (rc);
  283. wp++;
  284. cnt -= 1;
  285. src++;
  286. }
  287. while (cnt >= 2) {
  288. /*
  289. * handle word aligned part
  290. */
  291. count = 0;
  292. data = *((FPWV *) src);
  293. if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
  294. return (rc);
  295. wp += 2;
  296. src += 2;
  297. cnt -= 2;
  298. if (count++ > 0x800) {
  299. spin_wheel();
  300. count = 0;
  301. }
  302. }
  303. /* handle word aligned part */
  304. if (cnt) {
  305. /* handle word aligned part */
  306. count = 0;
  307. data = *((FPWV *) wp);
  308. data = (data & 0x00FF) | (*src << 8);
  309. if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
  310. return (rc);
  311. wp++;
  312. src++;
  313. cnt -= 1;
  314. if (count++ > 0x800) {
  315. spin_wheel();
  316. count = 0;
  317. }
  318. }
  319. if (cnt == 0)
  320. return ERR_OK;
  321. return ERR_OK;
  322. }
  323. /*-----------------------------------------------------------------------
  324. * Write a word to Flash
  325. * A word is 16 bits, whichever the bus width of the flash bank
  326. * (not an individual chip) is.
  327. *
  328. * returns:
  329. * 0 - OK
  330. * 1 - write timeout
  331. * 2 - Flash not erased
  332. */
  333. int write_word(flash_info_t * info, FPWV * dest, u16 data)
  334. {
  335. ulong start;
  336. int flag;
  337. int res = 0; /* result, assume success */
  338. FPWV *base; /* first address in flash bank */
  339. /* Check if Flash is (sufficiently) erased */
  340. if ((*dest & (u8) data) != (u8) data) {
  341. return (2);
  342. }
  343. base = (FPWV *) (CFG_FLASH_BASE);
  344. /* Disable interrupts which might cause a timeout here */
  345. flag = disable_interrupts();
  346. base[FLASH_CYCLE1] = (u8) 0x00AA00AA; /* unlock */
  347. base[FLASH_CYCLE2] = (u8) 0x00550055; /* unlock */
  348. base[FLASH_CYCLE1] = (u8) 0x00A000A0; /* selects program mode */
  349. *dest = data; /* start programming the data */
  350. /* re-enable interrupts if necessary */
  351. if (flag)
  352. enable_interrupts();
  353. start = get_timer(0);
  354. /* data polling for D7 */
  355. while (res == 0
  356. && (*dest & (u8) 0x00800080) != (data & (u8) 0x00800080)) {
  357. if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
  358. *dest = (u8) 0x00F000F0; /* reset bank */
  359. res = 1;
  360. }
  361. }
  362. *dest++ = (u8) 0x00F000F0; /* reset bank */
  363. return (res);
  364. }
  365. void inline spin_wheel(void)
  366. {
  367. static int p = 0;
  368. static char w[] = "\\/-";
  369. printf("\010%c", w[p]);
  370. (++p == 3) ? (p = 0) : 0;
  371. }
  372. #endif