flash.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. /*
  2. * (C) Copyright 2000
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. *
  23. * Hacked for the Hymod board by Murray.Jensen@cmst.csiro.au, 20-Oct-00
  24. */
  25. #include <common.h>
  26. #include <mpc8260.h>
  27. #include <board/hymod/flash.h>
  28. flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
  29. /*-----------------------------------------------------------------------
  30. * Protection Flags:
  31. */
  32. #define FLAG_PROTECT_SET 0x01
  33. #define FLAG_PROTECT_CLEAR 0x02
  34. /*-----------------------------------------------------------------------
  35. * Functions
  36. */
  37. #if 0
  38. static ulong flash_get_size (vu_long *addr, flash_info_t *info);
  39. static void flash_get_offsets (ulong base, flash_info_t *info);
  40. #endif
  41. static int write_word (flash_info_t *info, ulong dest, ulong data);
  42. /*-----------------------------------------------------------------------
  43. */
  44. /*
  45. * probe for the existence of flash at bank word address "addr"
  46. * 0 = yes, 1 = bad Manufacturer's Id, 2 = bad Device Id
  47. */
  48. static int
  49. bank_probe_word(bank_addr_t addr)
  50. {
  51. int retval;
  52. /* reset the flash */
  53. *addr = BANK_CMD_RST;
  54. /* check the manufacturer id */
  55. *addr = BANK_CMD_RD_ID;
  56. if (*BANK_ADDR_REG_MAN(addr) != BANK_RD_ID_MAN) {
  57. retval = -1;
  58. goto out;
  59. }
  60. /* check the device id */
  61. *addr = BANK_CMD_RD_ID;
  62. if (*BANK_ADDR_REG_DEV(addr) != BANK_RD_ID_DEV) {
  63. retval = -2;
  64. goto out;
  65. }
  66. retval = CFG_FLASH_TYPE;
  67. out:
  68. /* reset the flash again */
  69. *addr = BANK_CMD_RST;
  70. return retval;
  71. }
  72. /*
  73. * probe for flash banks at address "base" and store info for any found
  74. * into flash_info entry "fip". Must find at least one bank.
  75. */
  76. static void
  77. bank_probe(flash_info_t *fip, bank_addr_t base)
  78. {
  79. bank_addr_t addr, eaddr;
  80. int nbanks;
  81. fip->flash_id = FLASH_UNKNOWN;
  82. fip->size = 0L;
  83. fip->sector_count = 0;
  84. addr = base;
  85. eaddr = BANK_ADDR_BASE(addr, MAX_BANKS);
  86. nbanks = 0;
  87. while (addr < eaddr) {
  88. bank_addr_t addrw, eaddrw, addrb;
  89. int i, osc, nsc, curtype = -1;
  90. addrw = addr;
  91. eaddrw = BANK_ADDR_NEXT_WORD(addrw);
  92. while (addrw < eaddrw) {
  93. int thistype;
  94. #ifdef FLASH_DEBUG
  95. printf(" probing for flash at addr 0x%08lx\n",
  96. (unsigned long)addrw);
  97. #endif
  98. if ((thistype = bank_probe_word(addrw++)) < 0)
  99. goto out;
  100. if (curtype < 0)
  101. curtype = thistype;
  102. else {
  103. if (thistype != curtype) {
  104. printf("Differing flash type found!\n");
  105. goto out;
  106. }
  107. }
  108. }
  109. if (curtype < 0)
  110. goto out;
  111. /* bank exists - append info for this bank to *fip */
  112. fip->flash_id = FLASH_MAN_INTEL|curtype;
  113. fip->size += BANK_SIZE;
  114. osc = fip->sector_count;
  115. fip->sector_count += BANK_NBLOCKS;
  116. if ((nsc = fip->sector_count) >= CFG_MAX_FLASH_SECT)
  117. panic("Too many sectors in flash at address 0x%08lx\n",
  118. (unsigned long)base);
  119. addrb = addr;
  120. for (i = osc; i < nsc; i++) {
  121. fip->start[i] = (ulong)addrb;
  122. fip->protect[i] = 0;
  123. addrb = BANK_ADDR_NEXT_BLK(addrb);
  124. }
  125. addr = BANK_ADDR_NEXT_BANK(addr);
  126. nbanks++;
  127. }
  128. out:
  129. if (nbanks == 0)
  130. panic("ERROR: no flash found at address 0x%08lx\n",
  131. (unsigned long)base);
  132. }
  133. static void
  134. bank_reset(flash_info_t *info, int sect)
  135. {
  136. bank_addr_t addrw, eaddrw;
  137. addrw = (bank_addr_t)info->start[sect];
  138. eaddrw = BANK_ADDR_NEXT_WORD(addrw);
  139. while (addrw < eaddrw) {
  140. #ifdef FLASH_DEBUG
  141. printf(" writing reset cmd to addr 0x%08lx\n",
  142. (unsigned long)addrw);
  143. #endif
  144. *addrw = BANK_CMD_RST;
  145. addrw++;
  146. }
  147. }
  148. static void
  149. bank_erase_init(flash_info_t *info, int sect)
  150. {
  151. bank_addr_t addrw, saddrw, eaddrw;
  152. int flag;
  153. #ifdef FLASH_DEBUG
  154. printf("0x%08lx BANK_CMD_PROG\n", BANK_CMD_PROG);
  155. printf("0x%08lx BANK_CMD_ERASE1\n", BANK_CMD_ERASE1);
  156. printf("0x%08lx BANK_CMD_ERASE2\n", BANK_CMD_ERASE2);
  157. printf("0x%08lx BANK_CMD_CLR_STAT\n", BANK_CMD_CLR_STAT);
  158. printf("0x%08lx BANK_CMD_RST\n", BANK_CMD_RST);
  159. printf("0x%08lx BANK_STAT_RDY\n", BANK_STAT_RDY);
  160. printf("0x%08lx BANK_STAT_ERR\n", BANK_STAT_ERR);
  161. #endif
  162. saddrw = (bank_addr_t)info->start[sect];
  163. eaddrw = BANK_ADDR_NEXT_WORD(saddrw);
  164. #ifdef FLASH_DEBUG
  165. printf("erasing sector %d, start addr = 0x%08lx "
  166. "(bank next word addr = 0x%08lx)\n", sect,
  167. (unsigned long)saddrw, (unsigned long)eaddrw);
  168. #endif
  169. /* Disable intrs which might cause a timeout here */
  170. flag = disable_interrupts();
  171. for (addrw = saddrw; addrw < eaddrw; addrw++) {
  172. #ifdef FLASH_DEBUG
  173. printf(" writing erase cmd to addr 0x%08lx\n",
  174. (unsigned long)addrw);
  175. #endif
  176. *addrw = BANK_CMD_ERASE1;
  177. *addrw = BANK_CMD_ERASE2;
  178. }
  179. /* re-enable interrupts if necessary */
  180. if (flag)
  181. enable_interrupts();
  182. }
  183. static int
  184. bank_erase_poll(flash_info_t *info, int sect)
  185. {
  186. bank_addr_t addrw, saddrw, eaddrw;
  187. int sectdone, haderr;
  188. saddrw = (bank_addr_t)info->start[sect];
  189. eaddrw = BANK_ADDR_NEXT_WORD(saddrw);
  190. sectdone = 1;
  191. haderr = 0;
  192. for (addrw = saddrw; addrw < eaddrw; addrw++) {
  193. bank_word_t stat = *addrw;
  194. #ifdef FLASH_DEBUG
  195. printf(" checking status at addr "
  196. "0x%08lx [0x%08lx]\n",
  197. (unsigned long)addrw, stat);
  198. #endif
  199. if ((stat & BANK_STAT_RDY) != BANK_STAT_RDY)
  200. sectdone = 0;
  201. else if ((stat & BANK_STAT_ERR) != 0) {
  202. printf(" failed on sector %d "
  203. "(stat = 0x%08lx) at "
  204. "address 0x%08lx\n",
  205. sect, stat,
  206. (unsigned long)addrw);
  207. *addrw = BANK_CMD_CLR_STAT;
  208. haderr = 1;
  209. }
  210. }
  211. if (haderr)
  212. return (-1);
  213. else
  214. return (sectdone);
  215. }
  216. static int
  217. bank_write_word(bank_addr_t addr, bank_word_t value)
  218. {
  219. bank_word_t stat;
  220. ulong start;
  221. int flag, retval;
  222. /* Disable interrupts which might cause a timeout here */
  223. flag = disable_interrupts();
  224. *addr = BANK_CMD_PROG;
  225. *addr = value;
  226. /* re-enable interrupts if necessary */
  227. if (flag)
  228. enable_interrupts();
  229. retval = 0;
  230. /* data polling for D7 */
  231. start = get_timer (0);
  232. do {
  233. if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
  234. retval = 1;
  235. goto done;
  236. }
  237. stat = *addr;
  238. } while ((stat & BANK_STAT_RDY) != BANK_STAT_RDY);
  239. if ((stat & BANK_STAT_ERR) != 0) {
  240. printf("flash program failed (stat = 0x%08lx) "
  241. "at address 0x%08lx\n", (ulong)stat, (ulong)addr);
  242. *addr = BANK_CMD_CLR_STAT;
  243. retval = 3;
  244. }
  245. done:
  246. /* reset to read mode */
  247. *addr = BANK_CMD_RST;
  248. return (retval);
  249. }
  250. /*-----------------------------------------------------------------------
  251. */
  252. unsigned long
  253. flash_init(void)
  254. {
  255. int i;
  256. /* Init: no FLASHes known */
  257. for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
  258. flash_info[i].flash_id = FLASH_UNKNOWN;
  259. }
  260. bank_probe(&flash_info[0], (bank_addr_t)CFG_FLASH_BASE);
  261. /*
  262. * protect monitor and environment sectors
  263. */
  264. #if CFG_MONITOR_BASE == CFG_FLASH_BASE
  265. (void)flash_protect(FLAG_PROTECT_SET,
  266. CFG_MONITOR_BASE,
  267. CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
  268. &flash_info[0]);
  269. #endif
  270. #if defined(CFG_FLASH_ENV_ADDR)
  271. (void)flash_protect(FLAG_PROTECT_SET,
  272. CFG_FLASH_ENV_ADDR,
  273. #if defined(CFG_FLASH_ENV_BUF)
  274. CFG_FLASH_ENV_ADDR + CFG_FLASH_ENV_BUF - 1,
  275. #else
  276. CFG_FLASH_ENV_ADDR + CFG_FLASH_ENV_SIZE - 1,
  277. #endif
  278. &flash_info[0]);
  279. #endif
  280. return flash_info[0].size;
  281. }
  282. /*-----------------------------------------------------------------------
  283. */
  284. #if 0
  285. static void
  286. flash_get_offsets(ulong base, flash_info_t *info)
  287. {
  288. int i;
  289. /* set up sector start adress table */
  290. if (info->flash_id & FLASH_BTYPE) {
  291. /* set sector offsets for bottom boot block type */
  292. info->start[0] = base + 0x00000000;
  293. info->start[1] = base + 0x00008000;
  294. info->start[2] = base + 0x0000C000;
  295. info->start[3] = base + 0x00010000;
  296. for (i = 4; i < info->sector_count; i++) {
  297. info->start[i] = base + (i * 0x00020000) - 0x00060000;
  298. }
  299. } else {
  300. /* set sector offsets for top boot block type */
  301. i = info->sector_count - 1;
  302. info->start[i--] = base + info->size - 0x00008000;
  303. info->start[i--] = base + info->size - 0x0000C000;
  304. info->start[i--] = base + info->size - 0x00010000;
  305. for (; i >= 0; i--) {
  306. info->start[i] = base + i * 0x00020000;
  307. }
  308. }
  309. }
  310. #endif /* 0 */
  311. /*-----------------------------------------------------------------------
  312. */
  313. void
  314. flash_print_info(flash_info_t *info)
  315. {
  316. int i;
  317. if (info->flash_id == FLASH_UNKNOWN) {
  318. printf ("missing or unknown FLASH type\n");
  319. return;
  320. }
  321. switch (info->flash_id & FLASH_VENDMASK) {
  322. case FLASH_MAN_INTEL: printf ("INTEL "); break;
  323. default: printf ("Unknown Vendor "); break;
  324. }
  325. switch (info->flash_id & FLASH_TYPEMASK) {
  326. case FLASH_28F320J5: printf ("28F320J5 (32 Mbit, 2 x 16bit)\n");
  327. break;
  328. default: printf ("Unknown Chip Type\n");
  329. break;
  330. }
  331. printf (" Size: %ld MB in %d Sectors\n",
  332. info->size >> 20, info->sector_count);
  333. printf (" Sector Start Addresses:");
  334. for (i=0; i<info->sector_count; ++i) {
  335. if ((i % 5) == 0)
  336. printf ("\n ");
  337. printf (" %08lX%s",
  338. info->start[i],
  339. info->protect[i] ? " (RO)" : " "
  340. );
  341. }
  342. printf ("\n");
  343. return;
  344. }
  345. /*-----------------------------------------------------------------------
  346. */
  347. /*
  348. * The following code cannot be run from FLASH!
  349. */
  350. #if 0
  351. static ulong
  352. flash_get_size(vu_long *addr, flash_info_t *info)
  353. {
  354. short i;
  355. ulong value;
  356. ulong base = (ulong)addr;
  357. /* Write auto select command: read Manufacturer ID */
  358. addr[0x0555] = 0x00AA00AA;
  359. addr[0x02AA] = 0x00550055;
  360. addr[0x0555] = 0x00900090;
  361. value = addr[0];
  362. switch (value) {
  363. case AMD_MANUFACT:
  364. info->flash_id = FLASH_MAN_AMD;
  365. break;
  366. case FUJ_MANUFACT:
  367. info->flash_id = FLASH_MAN_FUJ;
  368. break;
  369. default:
  370. info->flash_id = FLASH_UNKNOWN;
  371. info->sector_count = 0;
  372. info->size = 0;
  373. return (0); /* no or unknown flash */
  374. }
  375. value = addr[1]; /* device ID */
  376. switch (value) {
  377. case AMD_ID_LV400T:
  378. info->flash_id += FLASH_AM400T;
  379. info->sector_count = 11;
  380. info->size = 0x00100000;
  381. break; /* => 1 MB */
  382. case AMD_ID_LV400B:
  383. info->flash_id += FLASH_AM400B;
  384. info->sector_count = 11;
  385. info->size = 0x00100000;
  386. break; /* => 1 MB */
  387. case AMD_ID_LV800T:
  388. info->flash_id += FLASH_AM800T;
  389. info->sector_count = 19;
  390. info->size = 0x00200000;
  391. break; /* => 2 MB */
  392. case AMD_ID_LV800B:
  393. info->flash_id += FLASH_AM800B;
  394. info->sector_count = 19;
  395. info->size = 0x00200000;
  396. break; /* => 2 MB */
  397. case AMD_ID_LV160T:
  398. info->flash_id += FLASH_AM160T;
  399. info->sector_count = 35;
  400. info->size = 0x00400000;
  401. break; /* => 4 MB */
  402. case AMD_ID_LV160B:
  403. info->flash_id += FLASH_AM160B;
  404. info->sector_count = 35;
  405. info->size = 0x00400000;
  406. break; /* => 4 MB */
  407. #if 0 /* enable when device IDs are available */
  408. case AMD_ID_LV320T:
  409. info->flash_id += FLASH_AM320T;
  410. info->sector_count = 67;
  411. info->size = 0x00800000;
  412. break; /* => 8 MB */
  413. case AMD_ID_LV320B:
  414. info->flash_id += FLASH_AM320B;
  415. info->sector_count = 67;
  416. info->size = 0x00800000;
  417. break; /* => 8 MB */
  418. #endif
  419. default:
  420. info->flash_id = FLASH_UNKNOWN;
  421. return (0); /* => no or unknown flash */
  422. }
  423. /* set up sector start adress table */
  424. if (info->flash_id & FLASH_BTYPE) {
  425. /* set sector offsets for bottom boot block type */
  426. info->start[0] = base + 0x00000000;
  427. info->start[1] = base + 0x00008000;
  428. info->start[2] = base + 0x0000C000;
  429. info->start[3] = base + 0x00010000;
  430. for (i = 4; i < info->sector_count; i++) {
  431. info->start[i] = base + (i * 0x00020000) - 0x00060000;
  432. }
  433. } else {
  434. /* set sector offsets for top boot block type */
  435. i = info->sector_count - 1;
  436. info->start[i--] = base + info->size - 0x00008000;
  437. info->start[i--] = base + info->size - 0x0000C000;
  438. info->start[i--] = base + info->size - 0x00010000;
  439. for (; i >= 0; i--) {
  440. info->start[i] = base + i * 0x00020000;
  441. }
  442. }
  443. /* check for protected sectors */
  444. for (i = 0; i < info->sector_count; i++) {
  445. /* read sector protection at sector address, (A7 .. A0) = 0x02 */
  446. /* D0 = 1 if protected */
  447. addr = (volatile unsigned long *)(info->start[i]);
  448. info->protect[i] = addr[2] & 1;
  449. }
  450. /*
  451. * Prevent writes to uninitialized FLASH.
  452. */
  453. if (info->flash_id != FLASH_UNKNOWN) {
  454. addr = (volatile unsigned long *)info->start[0];
  455. *addr = 0x00F000F0; /* reset bank */
  456. }
  457. return (info->size);
  458. }
  459. #endif /* 0 */
  460. /*-----------------------------------------------------------------------
  461. */
  462. int
  463. flash_erase(flash_info_t *info, int s_first, int s_last)
  464. {
  465. int prot, sect, haderr;
  466. ulong start, now, last;
  467. int rcode = 0;
  468. #ifdef FLASH_DEBUG
  469. printf("\nflash_erase: erase %d sectors (%d to %d incl.) from\n"
  470. " Bank # %d: ", s_last - s_first + 1, s_first, s_last,
  471. (info - flash_info) + 1);
  472. flash_print_info(info);
  473. #endif
  474. if ((s_first < 0) || (s_first > s_last)) {
  475. if (info->flash_id == FLASH_UNKNOWN) {
  476. printf ("- missing\n");
  477. } else {
  478. printf ("- no sectors to erase\n");
  479. }
  480. return 1;
  481. }
  482. prot = 0;
  483. for (sect=s_first; sect<=s_last; ++sect) {
  484. if (info->protect[sect]) {
  485. prot++;
  486. }
  487. }
  488. if (prot) {
  489. printf("- Warning: %d protected sector%s will not be erased!\n",
  490. prot, (prot > 1 ? "s" : ""));
  491. }
  492. start = get_timer (0);
  493. last = 0;
  494. haderr = 0;
  495. for (sect = s_first; sect <= s_last; sect++) {
  496. if (info->protect[sect] == 0) { /* not protected */
  497. ulong estart;
  498. int sectdone;
  499. bank_erase_init(info, sect);
  500. /* wait at least 80us - let's wait 1 ms */
  501. udelay (1000);
  502. estart = get_timer(start);
  503. do {
  504. now = get_timer(start);
  505. if (now - estart > CFG_FLASH_ERASE_TOUT) {
  506. printf ("Timeout (sect %d)\n", sect);
  507. haderr = 1;
  508. rcode = 1;
  509. break;
  510. }
  511. #ifndef FLASH_DEBUG
  512. /* show that we're waiting */
  513. if ((now - last) > 1000) { /* every second */
  514. putc ('.');
  515. last = now;
  516. }
  517. #endif
  518. sectdone = bank_erase_poll(info, sect);
  519. if (sectdone < 0) {
  520. haderr = 1;
  521. rcode = 1;
  522. break;
  523. }
  524. } while (!sectdone);
  525. if (haderr)
  526. break;
  527. }
  528. }
  529. if (haderr > 0)
  530. printf (" failed\n");
  531. else
  532. printf (" done\n");
  533. /* reset to read mode */
  534. for (sect = s_first; sect <= s_last; sect++) {
  535. if (info->protect[sect] == 0) { /* not protected */
  536. bank_reset(info, sect);
  537. }
  538. }
  539. return rcode;
  540. }
  541. /*-----------------------------------------------------------------------
  542. * Copy memory to flash, returns:
  543. * 0 - OK
  544. * 1 - write timeout
  545. * 2 - Flash not erased
  546. */
  547. int
  548. write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
  549. {
  550. ulong cp, wp, data;
  551. int i, l, rc;
  552. wp = (addr & ~3); /* get lower word aligned address */
  553. /*
  554. * handle unaligned start bytes
  555. */
  556. if ((l = addr - wp) != 0) {
  557. data = 0;
  558. for (i=0, cp=wp; i<l; ++i, ++cp) {
  559. data = (data << 8) | (*(uchar *)cp);
  560. }
  561. for (; i<4 && cnt>0; ++i) {
  562. data = (data << 8) | *src++;
  563. --cnt;
  564. ++cp;
  565. }
  566. for (; cnt==0 && i<4; ++i, ++cp) {
  567. data = (data << 8) | (*(uchar *)cp);
  568. }
  569. if ((rc = write_word(info, wp, data)) != 0) {
  570. return (rc);
  571. }
  572. wp += 4;
  573. }
  574. /*
  575. * handle word aligned part
  576. */
  577. while (cnt >= 4) {
  578. data = 0;
  579. for (i=0; i<4; ++i) {
  580. data = (data << 8) | *src++;
  581. }
  582. if ((rc = write_word(info, wp, data)) != 0) {
  583. return (rc);
  584. }
  585. wp += 4;
  586. cnt -= 4;
  587. }
  588. if (cnt == 0) {
  589. return (0);
  590. }
  591. /*
  592. * handle unaligned tail bytes
  593. */
  594. data = 0;
  595. for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
  596. data = (data << 8) | *src++;
  597. --cnt;
  598. }
  599. for (; i<4; ++i, ++cp) {
  600. data = (data << 8) | (*(uchar *)cp);
  601. }
  602. return (write_word(info, wp, data));
  603. }
  604. /*-----------------------------------------------------------------------
  605. * Write a word to Flash, returns:
  606. * 0 - OK
  607. * 1 - write timeout
  608. * 2 - Flash not erased
  609. */
  610. static int
  611. write_word(flash_info_t *info, ulong dest, ulong data)
  612. {
  613. int retval;
  614. /* Check if Flash is (sufficiently) erased */
  615. if ((*(ulong *)dest & data) != data) {
  616. return (2);
  617. }
  618. retval = bank_write_word((bank_addr_t)dest, (bank_word_t)data);
  619. return (retval);
  620. }
  621. /*-----------------------------------------------------------------------
  622. */