flash.c 9.3 KB

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