flash.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. /*
  2. * (C) Copyright 2001
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. * Keith Outwater, keith_outwater@mvsi.com
  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. #include <mpc8xx.h>
  26. #if defined(CFG_ENV_IS_IN_FLASH)
  27. # ifndef CFG_ENV_ADDR
  28. # define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET)
  29. # endif
  30. # ifndef CFG_ENV_SIZE
  31. # define CFG_ENV_SIZE CFG_ENV_SECT_SIZE
  32. # endif
  33. # ifndef CFG_ENV_SECT_SIZE
  34. # define CFG_ENV_SECT_SIZE CFG_ENV_SIZE
  35. # endif
  36. #endif
  37. /*
  38. * Use buffered writes to flash by default - they are about 32x faster than
  39. * single byte writes.
  40. */
  41. #ifndef CFG_GEN860T_FLASH_USE_WRITE_BUFFER
  42. #define CFG_GEN860T_FLASH_USE_WRITE_BUFFER
  43. #endif
  44. /*
  45. * Max time to wait (in mS) for flash device to allocate a write buffer.
  46. */
  47. #ifndef CFG_FLASH_ALLOC_BUFFER_TOUT
  48. #define CFG_FLASH_ALLOC_BUFFER_TOUT 100
  49. #endif
  50. /*
  51. * These functions support a single Intel StrataFlash device (28F128J3A)
  52. * in byte mode only!. The flash routines are very basic and simple
  53. * since there isn't really any remapping necessary.
  54. */
  55. /*
  56. * Intel SCS (Scalable Command Set) command definitions
  57. * (taken from 28F128J3A datasheet)
  58. */
  59. #define SCS_READ_CMD 0xff
  60. #define SCS_READ_ID_CMD 0x90
  61. #define SCS_QUERY_CMD 0x98
  62. #define SCS_READ_STATUS_CMD 0x70
  63. #define SCS_CLEAR_STATUS_CMD 0x50
  64. #define SCS_WRITE_BUF_CMD 0xe8
  65. #define SCS_PROGRAM_CMD 0x40
  66. #define SCS_BLOCK_ERASE_CMD 0x20
  67. #define SCS_BLOCK_ERASE_RESUME_CMD 0xd0
  68. #define SCS_PROGRAM_RESUME_CMD 0xd0
  69. #define SCS_BLOCK_ERASE_SUSPEND_CMD 0xb0
  70. #define SCS_SET_BLOCK_LOCK_CMD 0x60
  71. #define SCS_CLR_BLOCK_LOCK_CMD 0x60
  72. /*
  73. * SCS status/extended status register bit definitions
  74. */
  75. #define SCS_SR7 0x80
  76. #define SCS_XSR7 0x80
  77. /*---------------------------------------------------------------------*/
  78. #if 0
  79. #define DEBUG_FLASH
  80. #endif
  81. #ifdef DEBUG_FLASH
  82. #define PRINTF(fmt,args...) printf(fmt ,##args)
  83. #else
  84. #define PRINTF(fmt,args...)
  85. #endif
  86. /*---------------------------------------------------------------------*/
  87. flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
  88. /*-----------------------------------------------------------------------
  89. * Functions
  90. */
  91. static ulong flash_get_size (vu_char *addr, flash_info_t *info);
  92. static int write_data8 (flash_info_t *info, ulong dest, uchar data);
  93. static void flash_get_offsets (ulong base, flash_info_t *info);
  94. /*-----------------------------------------------------------------------
  95. * Initialize the flash memory.
  96. */
  97. unsigned long
  98. flash_init (void)
  99. {
  100. volatile immap_t *immap = (immap_t *)CFG_IMMR;
  101. volatile memctl8xx_t *memctl = &immap->im_memctl;
  102. unsigned long size_b0;
  103. int i;
  104. for (i= 0; i < CFG_MAX_FLASH_BANKS; ++i) {
  105. flash_info[i].flash_id = FLASH_UNKNOWN;
  106. }
  107. /*
  108. * The gen860t board only has one FLASH memory device, so the
  109. * FLASH Bank configuration is done statically.
  110. */
  111. PRINTF("\n## Get flash bank 1 size @ 0x%08x\n", FLASH_BASE0_PRELIM);
  112. size_b0 = flash_get_size((vu_char *)FLASH_BASE0_PRELIM, &flash_info[0]);
  113. if (flash_info[0].flash_id == FLASH_UNKNOWN) {
  114. printf ("## Unknown FLASH on Bank 0: "
  115. "ID 0x%lx, Size = 0x%08lx = %ld MB\n",
  116. flash_info[0].flash_id,size_b0, size_b0 << 20);
  117. }
  118. PRINTF("## Before remap:\n"
  119. " BR0: 0x%08x OR0: 0x%08x\n BR1: 0x%08x OR1: 0x%08x\n",
  120. memctl->memc_br0, memctl->memc_or0,
  121. memctl->memc_br1, memctl->memc_or1);
  122. /*
  123. * Remap FLASH according to real size
  124. */
  125. memctl->memc_or0 |= (-size_b0 & 0xFFFF8000);
  126. memctl->memc_br0 |= (CFG_FLASH_BASE & BR_BA_MSK);
  127. PRINTF("## After remap:\n"
  128. " BR0: 0x%08x OR0: 0x%08x\n", memctl->memc_br0, memctl->memc_or0);
  129. /*
  130. * Re-do sizing to get full correct info
  131. */
  132. size_b0 = flash_get_size ((vu_char *)CFG_FLASH_BASE, &flash_info[0]);
  133. flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
  134. flash_info[0].size = size_b0;
  135. #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
  136. /*
  137. * Monitor protection is ON by default
  138. */
  139. flash_protect(FLAG_PROTECT_SET,
  140. CFG_MONITOR_BASE,
  141. CFG_MONITOR_BASE + monitor_flash_len - 1,
  142. &flash_info[0]);
  143. #endif
  144. #ifdef CFG_ENV_IS_IN_FLASH
  145. /*
  146. * Environment protection ON by default
  147. */
  148. flash_protect(FLAG_PROTECT_SET,
  149. CFG_ENV_ADDR,
  150. CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1,
  151. &flash_info[0]);
  152. #endif
  153. PRINTF("## Final Flash bank size: 0x%08lx\n",size_b0);
  154. return (size_b0);
  155. }
  156. /*-----------------------------------------------------------------------
  157. * Fill in the FLASH offset table
  158. */
  159. static void
  160. flash_get_offsets (ulong base, flash_info_t *info)
  161. {
  162. int i;
  163. if (info->flash_id == FLASH_UNKNOWN) {
  164. return;
  165. }
  166. switch (info->flash_id & FLASH_VENDMASK) {
  167. case FLASH_MAN_INTEL:
  168. for (i = 0; i < info->sector_count; i++) {
  169. info->start[i] = base;
  170. base += 1024 * 128;
  171. }
  172. return;
  173. default:
  174. printf ("Don't know sector offsets for FLASH"
  175. " type 0x%lx\n", info->flash_id);
  176. return;
  177. }
  178. }
  179. /*-----------------------------------------------------------------------
  180. * Display FLASH device info
  181. */
  182. void
  183. flash_print_info (flash_info_t *info)
  184. {
  185. int i;
  186. if (info->flash_id == FLASH_UNKNOWN) {
  187. printf ("Missing or unknown FLASH type\n");
  188. return;
  189. }
  190. switch (info->flash_id & FLASH_VENDMASK) {
  191. case FLASH_MAN_INTEL:
  192. printf ("Intel ");
  193. break;
  194. default:
  195. printf ("Unknown Vendor ");
  196. break;
  197. }
  198. switch (info->flash_id & FLASH_TYPEMASK) {
  199. case FLASH_28F128J3A:
  200. printf ("28F128J3A (128Mbit = 128K x 128)\n");
  201. break;
  202. default:
  203. printf ("Unknown Chip Type\n");
  204. break;
  205. }
  206. if (info->size >= (1024 * 1024)) {
  207. i = 20;
  208. } else {
  209. i = 10;
  210. }
  211. printf (" Size: %ld %cB in %d Sectors\n",
  212. info->size >> i,
  213. (i == 20) ? 'M' : 'k',
  214. info->sector_count);
  215. printf (" Sector Start Addresses:");
  216. for (i=0; i<info->sector_count; ++i) {
  217. if ((i % 5) == 0)
  218. printf ("\n ");
  219. printf (" %08lX%s",
  220. info->start[i],
  221. info->protect[i] ? " (RO)" : " "
  222. );
  223. }
  224. printf ("\n");
  225. return;
  226. }
  227. /*-----------------------------------------------------------------------
  228. * Get size and other information for a FLASH device.
  229. * NOTE: The following code cannot be run from FLASH!
  230. */
  231. static
  232. ulong flash_get_size (vu_char *addr, flash_info_t *info)
  233. {
  234. #define NO_FLASH 0
  235. vu_char value[2];
  236. /*
  237. * Try to read the manufacturer ID
  238. */
  239. addr[0] = SCS_READ_CMD;
  240. addr[0] = SCS_READ_ID_CMD;
  241. value[0] = addr[0];
  242. value[1] = addr[2];
  243. addr[0] = SCS_READ_CMD;
  244. PRINTF("Manuf. ID @ 0x%08lx: 0x%02x\n", (ulong)addr, value[0]);
  245. switch (value[0]) {
  246. case (INTEL_MANUFACT & 0xff):
  247. info->flash_id = FLASH_MAN_INTEL;
  248. break;
  249. default:
  250. info->flash_id = FLASH_UNKNOWN;
  251. info->sector_count = 0;
  252. info->size = 0;
  253. return (NO_FLASH);
  254. }
  255. /*
  256. * Read the device ID
  257. */
  258. PRINTF("Device ID @ 0x%08lx: 0x%02x\n", (ulong)(&addr[2]), value[1]);
  259. switch (value[1]) {
  260. case (INTEL_ID_28F128J3A & 0xff):
  261. info->flash_id += FLASH_28F128J3A;
  262. info->sector_count = 128;
  263. info->size = 16 * 1024 * 1024;
  264. break;
  265. default:
  266. info->flash_id = FLASH_UNKNOWN;
  267. return (NO_FLASH);
  268. }
  269. if (info->sector_count > CFG_MAX_FLASH_SECT) {
  270. printf ("** ERROR: sector count %d > max (%d) **\n",
  271. info->sector_count, CFG_MAX_FLASH_SECT);
  272. info->sector_count = CFG_MAX_FLASH_SECT;
  273. }
  274. return (info->size);
  275. }
  276. /*-----------------------------------------------------------------------
  277. * Erase the specified sectors in the specified FLASH device
  278. */
  279. int
  280. flash_erase(flash_info_t *info, int s_first, int s_last)
  281. {
  282. int flag, prot, sect;
  283. ulong start, now, last;
  284. if ((s_first < 0) || (s_first > s_last)) {
  285. if (info->flash_id == FLASH_UNKNOWN) {
  286. printf ("- missing\n");
  287. } else {
  288. printf ("- no sectors to erase\n");
  289. }
  290. return 1;
  291. }
  292. if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) {
  293. printf ("Can erase only Intel flash types - aborted\n");
  294. return 1;
  295. }
  296. prot = 0;
  297. for (sect=s_first; sect<=s_last; ++sect) {
  298. if (info->protect[sect]) {
  299. prot++;
  300. }
  301. }
  302. if (prot) {
  303. printf ("- Warning: %d protected sectors will not be erased!\n",
  304. prot);
  305. } else {
  306. printf ("\n");
  307. }
  308. start = get_timer (0);
  309. last = start;
  310. /*
  311. * Start erase on unprotected sectors
  312. */
  313. for (sect = s_first; sect<=s_last; sect++) {
  314. if (info->protect[sect] == 0) { /* not protected */
  315. vu_char *addr = (uchar *)(info->start[sect]);
  316. vu_char status;
  317. /*
  318. * Disable interrupts which might cause a timeout
  319. */
  320. flag = disable_interrupts();
  321. *addr = SCS_CLEAR_STATUS_CMD;
  322. *addr = SCS_BLOCK_ERASE_CMD;
  323. *addr = SCS_BLOCK_ERASE_RESUME_CMD;
  324. /*
  325. * Re-enable interrupts if necessary
  326. */
  327. if (flag)
  328. enable_interrupts();
  329. /*
  330. * Wait at least 80us - let's wait 1 ms
  331. */
  332. udelay (1000);
  333. while (((status = *addr) & SCS_SR7) != SCS_SR7) {
  334. if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
  335. printf ("Timeout\n");
  336. *addr = SCS_BLOCK_ERASE_SUSPEND_CMD;
  337. *addr = SCS_READ_CMD;
  338. return 1;
  339. }
  340. /*
  341. * Show that we're waiting
  342. */
  343. if ((now - last) > 1000) { /* 1 second */
  344. putc ('.');
  345. last = now;
  346. }
  347. }
  348. *addr = SCS_READ_CMD;
  349. }
  350. }
  351. printf (" done\n");
  352. return 0;
  353. }
  354. #ifdef CFG_GEN860T_FLASH_USE_WRITE_BUFFER
  355. /*
  356. * Allocate a flash buffer, fill it with data and write it to the flash.
  357. * 0 - OK
  358. * 1 - Timeout on buffer request
  359. *
  360. * NOTE: After the last call to this function, WSM status needs to be checked!
  361. */
  362. static int
  363. write_flash_buffer8(flash_info_t *info_p, vu_char *src_p, vu_char *dest_p,
  364. uint count)
  365. {
  366. vu_char *block_addr_p = NULL;
  367. vu_char *start_addr_p = NULL;
  368. ulong blocksize = info_p->size / (ulong)info_p->sector_count;
  369. int i;
  370. uint time = get_timer(0);
  371. PRINTF("%s:%d: src: 0x%p dest: 0x%p count: %d\n",
  372. __FUNCTION__, __LINE__, src_p, dest_p, count);
  373. /*
  374. * What block are we in? We already know that the source address is
  375. * in the flash address range, but we also can't cross a block boundary.
  376. * We assume that the block does not cross a boundary (we'll check before
  377. * calling this function).
  378. */
  379. for (i = 0; i < info_p->sector_count; ++i) {
  380. if ( ((ulong)dest_p >= info_p->start[i]) &&
  381. ((ulong)dest_p < (info_p->start[i] + blocksize)) ) {
  382. PRINTF("%s:%d: Dest addr 0x%p is in block %d @ 0x%.8lx\n",
  383. __FUNCTION__, __LINE__, dest_p, i, info_p->start[i]);
  384. block_addr_p = (vu_char *)info_p->start[i];
  385. break;
  386. }
  387. }
  388. /*
  389. * Request a buffer
  390. */
  391. *block_addr_p = SCS_WRITE_BUF_CMD;
  392. while ((*block_addr_p & SCS_XSR7) != SCS_XSR7) {
  393. if (get_timer(time) > CFG_FLASH_ALLOC_BUFFER_TOUT) {
  394. PRINTF("%s:%d: Buffer allocation timeout @ 0x%p (waited %d mS)\n",
  395. __FUNCTION__, __LINE__, block_addr_p,
  396. CFG_FLASH_ALLOC_BUFFER_TOUT);
  397. return 1;
  398. }
  399. *block_addr_p = SCS_WRITE_BUF_CMD;
  400. }
  401. /*
  402. * Fill the buffer with data
  403. */
  404. start_addr_p = dest_p;
  405. *block_addr_p = count - 1; /* flash device wants count - 1 */
  406. PRINTF("%s:%d: Fill buffer at block addr 0x%p\n",
  407. __FUNCTION__, __LINE__, block_addr_p);
  408. for (i = 0; i < count; i++) {
  409. *start_addr_p++ = *src_p++;
  410. }
  411. /*
  412. * Flush buffer to flash
  413. */
  414. *block_addr_p = SCS_PROGRAM_RESUME_CMD;
  415. #if 1
  416. time = get_timer(0);
  417. while ((*block_addr_p & SCS_SR7) != SCS_SR7) {
  418. if (get_timer(time) > CFG_FLASH_WRITE_TOUT) {
  419. PRINTF("%s:%d: Write timeout @ 0x%p (waited %d mS)\n",
  420. __FUNCTION__, __LINE__, block_addr_p, CFG_FLASH_WRITE_TOUT);
  421. return 1;
  422. }
  423. }
  424. #endif
  425. return 0;
  426. }
  427. #endif
  428. /*-----------------------------------------------------------------------
  429. * Copy memory to flash, returns:
  430. * 0 - OK
  431. * 1 - write timeout
  432. * 2 - Flash not erased
  433. * 4 - Flash not identified
  434. */
  435. int
  436. write_buff(flash_info_t *info_p, uchar *src_p, ulong addr, ulong count)
  437. {
  438. int rc = 0;
  439. #ifdef CFG_GEN860T_FLASH_USE_WRITE_BUFFER
  440. #define FLASH_WRITE_BUF_SIZE 0x00000020 /* 32 bytes */
  441. int i;
  442. uint bufs;
  443. ulong buf_count;
  444. vu_char *sp;
  445. vu_char *dp;
  446. #else
  447. ulong wp;
  448. #endif
  449. PRINTF("\n%s:%d: src: 0x%.8lx dest: 0x%.8lx size: %d (0x%.8lx)\n",
  450. __FUNCTION__, __LINE__, (ulong)src_p, addr, (uint)count, count);
  451. if (info_p->flash_id == FLASH_UNKNOWN) {
  452. return 4;
  453. }
  454. #ifdef CFG_GEN860T_FLASH_USE_WRITE_BUFFER
  455. sp = src_p;
  456. dp = (uchar *)addr;
  457. /*
  458. * For maximum performance, we want to align the start address to
  459. * the beginning of a write buffer boundary (i.e. A4-A0 of the
  460. * start address = 0). See how many bytes are required to get to a
  461. * write-buffer-aligned address. If that number is non-zero, do
  462. * non buffered writes of the non-aligned data. By doing non-buffered
  463. * writes, we avoid the problem of crossing a block (sector) boundary
  464. * with buffered writes.
  465. */
  466. buf_count = FLASH_WRITE_BUF_SIZE - (addr & (FLASH_WRITE_BUF_SIZE - 1));
  467. if (buf_count == FLASH_WRITE_BUF_SIZE) { /* already on a boundary */
  468. buf_count = 0;
  469. }
  470. if (buf_count > count) { /* not a full buffers worth of data to write */
  471. buf_count = count;
  472. }
  473. count -= buf_count;
  474. PRINTF("%s:%d: Write buffer alignment count = %ld\n",
  475. __FUNCTION__, __LINE__, buf_count);
  476. while (buf_count-- >= 1) {
  477. if ((rc = write_data8(info_p, (ulong)dp++, *sp++)) != 0) {
  478. return (rc);
  479. }
  480. }
  481. PRINTF("%s:%d: count = %ld\n", __FUNCTION__, __LINE__, count);
  482. if (count == 0) { /* all done */
  483. PRINTF("%s:%d: Less than 1 buffer (%d) worth of bytes\n",
  484. __FUNCTION__, __LINE__, FLASH_WRITE_BUF_SIZE);
  485. return (rc);
  486. }
  487. /*
  488. * Now that we are write buffer aligned, write full or partial buffers.
  489. * The fact that we are write buffer aligned automatically avoids
  490. * crossing a block address during a write buffer operation.
  491. */
  492. bufs = count / FLASH_WRITE_BUF_SIZE;
  493. PRINTF("%s:%d: %d (0x%x) buffers to write\n", __FUNCTION__, __LINE__,
  494. bufs, bufs);
  495. while (bufs >= 1) {
  496. rc = write_flash_buffer8(info_p, sp, dp, FLASH_WRITE_BUF_SIZE);
  497. if (rc != 0) {
  498. PRINTF("%s:%d: ** Error writing buf %d\n",
  499. __FUNCTION__, __LINE__, bufs);
  500. return (rc);
  501. }
  502. bufs--;
  503. sp += FLASH_WRITE_BUF_SIZE;
  504. dp += FLASH_WRITE_BUF_SIZE;
  505. }
  506. /*
  507. * Do the leftovers
  508. */
  509. i = count % FLASH_WRITE_BUF_SIZE;
  510. PRINTF("%s:%d: %d (0x%x) leftover bytes\n", __FUNCTION__, __LINE__, i, i);
  511. if (i > 0) {
  512. rc = write_flash_buffer8(info_p, sp, dp, i);
  513. }
  514. sp = (vu_char*)info_p->start[0];
  515. *sp = SCS_READ_CMD;
  516. return (rc);
  517. #else
  518. wp = addr;
  519. while (count-- >= 1) {
  520. if((rc = write_data8(info_p, wp++, *src_p++)) != 0)
  521. return (rc);
  522. }
  523. return 0;
  524. #endif
  525. }
  526. /*-----------------------------------------------------------------------
  527. * Write a byte to Flash, returns:
  528. * 0 - OK
  529. * 1 - write timeout
  530. * 2 - Flash not erased
  531. */
  532. static int
  533. write_data8 (flash_info_t *info, ulong dest, uchar data)
  534. {
  535. vu_char *addr = (vu_char *)dest;
  536. vu_char status;
  537. ulong start;
  538. int flag;
  539. /* Check if Flash is (sufficiently) erased */
  540. if ((*addr & data) != data) {
  541. return (2);
  542. }
  543. /* Disable interrupts which might cause a timeout here */
  544. flag = disable_interrupts();
  545. *addr = SCS_PROGRAM_CMD;
  546. *addr = data;
  547. /* re-enable interrupts if necessary */
  548. if (flag)
  549. enable_interrupts();
  550. start = get_timer (0);
  551. while (((status = *addr) & SCS_SR7) != SCS_SR7) {
  552. if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
  553. *addr = SCS_READ_CMD;
  554. return (1);
  555. }
  556. }
  557. *addr = SCS_READ_CMD;
  558. return (0);
  559. }
  560. /* vim: set ts=4 sw=4 tw=78: */