strataflash.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. /*
  2. * (C) Copyright 2002
  3. * Brad Kemp, Seranoa Networks, Brad.Kemp@seranoa.com
  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. #include <common.h>
  24. #include <asm/processor.h>
  25. #include <asm/cache.h>
  26. #undef DEBUG_FLASH
  27. /*
  28. * This file implements a Common Flash Interface (CFI) driver for U-Boot.
  29. * The width of the port and the width of the chips are determined at initialization.
  30. * These widths are used to calculate the address for access CFI data structures.
  31. * It has been tested on an Intel Strataflash implementation.
  32. *
  33. * References
  34. * JEDEC Standard JESD68 - Common Flash Interface (CFI)
  35. * JEDEC Standard JEP137-A Common Flash Interface (CFI) ID Codes
  36. * Intel Application Note 646 Common Flash Interface (CFI) and Command Sets
  37. * Intel 290667-008 3 Volt Intel StrataFlash Memory datasheet
  38. *
  39. * TODO
  40. * Use Primary Extended Query table (PRI) and Alternate Algorithm Query Table (ALT) to determine if protection is available
  41. * Add support for other command sets Use the PRI and ALT to determine command set
  42. * Verify erase and program timeouts.
  43. */
  44. #define FLASH_CMD_CFI 0x98
  45. #define FLASH_CMD_READ_ID 0x90
  46. #define FLASH_CMD_RESET 0xff
  47. #define FLASH_CMD_BLOCK_ERASE 0x20
  48. #define FLASH_CMD_ERASE_CONFIRM 0xD0
  49. #define FLASH_CMD_WRITE 0x40
  50. #define FLASH_CMD_PROTECT 0x60
  51. #define FLASH_CMD_PROTECT_SET 0x01
  52. #define FLASH_CMD_PROTECT_CLEAR 0xD0
  53. #define FLASH_CMD_CLEAR_STATUS 0x50
  54. #define FLASH_CMD_WRITE_TO_BUFFER 0xE8
  55. #define FLASH_CMD_WRITE_BUFFER_CONFIRM 0xD0
  56. #define FLASH_STATUS_DONE 0x80
  57. #define FLASH_STATUS_ESS 0x40
  58. #define FLASH_STATUS_ECLBS 0x20
  59. #define FLASH_STATUS_PSLBS 0x10
  60. #define FLASH_STATUS_VPENS 0x08
  61. #define FLASH_STATUS_PSS 0x04
  62. #define FLASH_STATUS_DPS 0x02
  63. #define FLASH_STATUS_R 0x01
  64. #define FLASH_STATUS_PROTECT 0x01
  65. #define FLASH_OFFSET_CFI 0x55
  66. #define FLASH_OFFSET_CFI_RESP 0x10
  67. #define FLASH_OFFSET_WTOUT 0x1F
  68. #define FLASH_OFFSET_WBTOUT 0x20
  69. #define FLASH_OFFSET_ETOUT 0x21
  70. #define FLASH_OFFSET_CETOUT 0x22
  71. #define FLASH_OFFSET_WMAX_TOUT 0x23
  72. #define FLASH_OFFSET_WBMAX_TOUT 0x24
  73. #define FLASH_OFFSET_EMAX_TOUT 0x25
  74. #define FLASH_OFFSET_CEMAX_TOUT 0x26
  75. #define FLASH_OFFSET_SIZE 0x27
  76. #define FLASH_OFFSET_INTERFACE 0x28
  77. #define FLASH_OFFSET_BUFFER_SIZE 0x2A
  78. #define FLASH_OFFSET_NUM_ERASE_REGIONS 0x2C
  79. #define FLASH_OFFSET_ERASE_REGIONS 0x2D
  80. #define FLASH_OFFSET_PROTECT 0x02
  81. #define FLASH_OFFSET_USER_PROTECTION 0x85
  82. #define FLASH_OFFSET_INTEL_PROTECTION 0x81
  83. #define FLASH_MAN_CFI 0x01000000
  84. typedef union {
  85. unsigned char c;
  86. unsigned short w;
  87. unsigned long l;
  88. } cfiword_t;
  89. typedef union {
  90. unsigned char *cp;
  91. unsigned short *wp;
  92. unsigned long *lp;
  93. } cfiptr_t;
  94. #define NUM_ERASE_REGIONS 4
  95. flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  96. /*-----------------------------------------------------------------------
  97. * Functions
  98. */
  99. static void flash_add_byte(flash_info_t * info, cfiword_t * cword, uchar c);
  100. static void flash_make_cmd(flash_info_t * info, uchar cmd, void *cmdbuf);
  101. static void flash_write_cmd(flash_info_t * info, int sect, uchar offset,
  102. uchar cmd);
  103. static int flash_isequal(flash_info_t * info, int sect, uchar offset,
  104. uchar cmd);
  105. static int flash_isset(flash_info_t * info, int sect, uchar offset, uchar cmd);
  106. static int flash_detect_cfi(flash_info_t * info);
  107. static ulong flash_get_size(ulong base, int banknum);
  108. static int flash_write_cfiword(flash_info_t * info, ulong dest,
  109. cfiword_t cword);
  110. static int flash_full_status_check(flash_info_t * info, ulong sector,
  111. ulong tout, char *prompt);
  112. #ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
  113. static int flash_write_cfibuffer(flash_info_t * info, ulong dest, uchar * cp,
  114. int len);
  115. #endif
  116. /*-----------------------------------------------------------------------
  117. * create an address based on the offset and the port width
  118. */
  119. inline uchar *flash_make_addr(flash_info_t * info, int sect, int offset)
  120. {
  121. return ((uchar *) (info->start[sect] + (offset * info->portwidth)));
  122. }
  123. /*-----------------------------------------------------------------------
  124. * read a character at a port width address
  125. */
  126. inline uchar flash_read_uchar(flash_info_t * info, uchar offset)
  127. {
  128. uchar *cp;
  129. cp = flash_make_addr(info, 0, offset);
  130. return (cp[info->portwidth - 1]);
  131. }
  132. /*-----------------------------------------------------------------------
  133. * read a short word by swapping for ppc format.
  134. */
  135. ushort flash_read_ushort(flash_info_t * info, int sect, uchar offset)
  136. {
  137. uchar *addr;
  138. addr = flash_make_addr(info, sect, offset);
  139. return ((addr[(2 * info->portwidth) - 1] << 8) |
  140. addr[info->portwidth - 1]);
  141. }
  142. /*-----------------------------------------------------------------------
  143. * read a long word by picking the least significant byte of each maiximum
  144. * port size word. Swap for ppc format.
  145. */
  146. ulong flash_read_long(flash_info_t * info, int sect, uchar offset)
  147. {
  148. uchar *addr;
  149. addr = flash_make_addr(info, sect, offset);
  150. return ((addr[(2 * info->portwidth) - 1] << 24) |
  151. (addr[(info->portwidth) - 1] << 16) |
  152. (addr[(4 * info->portwidth) - 1] << 8) |
  153. addr[(3 * info->portwidth) - 1]);
  154. }
  155. /*-----------------------------------------------------------------------
  156. */
  157. unsigned long flash_init(void)
  158. {
  159. unsigned long size;
  160. int i;
  161. unsigned long address;
  162. /* The flash is positioned back to back, with the demultiplexing of the chip
  163. * based on the A24 address line.
  164. *
  165. */
  166. address = CONFIG_SYS_FLASH_BASE;
  167. size = 0;
  168. /* Init: no FLASHes known */
  169. for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
  170. flash_info[i].flash_id = FLASH_UNKNOWN;
  171. size += flash_info[i].size = flash_get_size(address, i);
  172. address += CONFIG_SYS_FLASH_INCREMENT;
  173. if (flash_info[i].flash_id == FLASH_UNKNOWN) {
  174. printf
  175. ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
  176. i, flash_info[0].size, flash_info[i].size << 20);
  177. }
  178. }
  179. #if 0 /* test-only */
  180. /* Monitor protection ON by default */
  181. #if (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE)
  182. for (i = 0;
  183. flash_info[0].start[i] < CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1;
  184. i++)
  185. (void)flash_real_protect(&flash_info[0], i, 1);
  186. #endif
  187. #endif
  188. return (size);
  189. }
  190. /*-----------------------------------------------------------------------
  191. */
  192. int flash_erase(flash_info_t * info, int s_first, int s_last)
  193. {
  194. int rcode = 0;
  195. int prot;
  196. int sect;
  197. if (info->flash_id != FLASH_MAN_CFI) {
  198. printf("Can't erase unknown flash type - aborted\n");
  199. return 1;
  200. }
  201. if ((s_first < 0) || (s_first > s_last)) {
  202. printf("- no sectors to erase\n");
  203. return 1;
  204. }
  205. prot = 0;
  206. for (sect = s_first; sect <= s_last; ++sect) {
  207. if (info->protect[sect]) {
  208. prot++;
  209. }
  210. }
  211. if (prot) {
  212. printf("- Warning: %d protected sectors will not be erased!\n",
  213. prot);
  214. } else {
  215. printf("\n");
  216. }
  217. for (sect = s_first; sect <= s_last; sect++) {
  218. if (info->protect[sect] == 0) { /* not protected */
  219. flash_write_cmd(info, sect, 0, FLASH_CMD_CLEAR_STATUS);
  220. flash_write_cmd(info, sect, 0, FLASH_CMD_BLOCK_ERASE);
  221. flash_write_cmd(info, sect, 0, FLASH_CMD_ERASE_CONFIRM);
  222. if (flash_full_status_check
  223. (info, sect, info->erase_blk_tout, "erase")) {
  224. rcode = 1;
  225. } else
  226. printf(".");
  227. }
  228. }
  229. printf(" done\n");
  230. return rcode;
  231. }
  232. /*-----------------------------------------------------------------------
  233. */
  234. void flash_print_info(flash_info_t * info)
  235. {
  236. int i;
  237. if (info->flash_id != FLASH_MAN_CFI) {
  238. printf("missing or unknown FLASH type\n");
  239. return;
  240. }
  241. printf("CFI conformant FLASH (%d x %d)",
  242. (info->portwidth << 3), (info->chipwidth << 3));
  243. printf(" Size: %ld MB in %d Sectors\n",
  244. info->size >> 20, info->sector_count);
  245. printf
  246. (" Erase timeout %ld ms, write timeout %ld ms, buffer write timeout %ld ms, buffer size %d\n",
  247. info->erase_blk_tout, info->write_tout, info->buffer_write_tout,
  248. info->buffer_size);
  249. printf(" Sector Start Addresses:");
  250. for (i = 0; i < info->sector_count; ++i) {
  251. if ((i % 5) == 0)
  252. printf("\n");
  253. printf(" %08lX%5s",
  254. info->start[i], info->protect[i] ? " (RO)" : " ");
  255. }
  256. printf("\n");
  257. return;
  258. }
  259. /*-----------------------------------------------------------------------
  260. * Copy memory to flash, returns:
  261. * 0 - OK
  262. * 1 - write timeout
  263. * 2 - Flash not erased
  264. */
  265. int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
  266. {
  267. ulong wp;
  268. ulong cp;
  269. int aln;
  270. cfiword_t cword;
  271. int i, rc;
  272. /* get lower aligned address */
  273. wp = (addr & ~(info->portwidth - 1));
  274. /* handle unaligned start */
  275. if ((aln = addr - wp) != 0) {
  276. cword.l = 0;
  277. cp = wp;
  278. for (i = 0; i < aln; ++i, ++cp)
  279. flash_add_byte(info, &cword, (*(uchar *) cp));
  280. for (; (i < info->portwidth) && (cnt > 0); i++) {
  281. flash_add_byte(info, &cword, *src++);
  282. cnt--;
  283. cp++;
  284. }
  285. for (; (cnt == 0) && (i < info->portwidth); ++i, ++cp)
  286. flash_add_byte(info, &cword, (*(uchar *) cp));
  287. if ((rc = flash_write_cfiword(info, wp, cword)) != 0)
  288. return rc;
  289. wp = cp;
  290. }
  291. #ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
  292. while (cnt >= info->portwidth) {
  293. i = info->buffer_size > cnt ? cnt : info->buffer_size;
  294. if ((rc = flash_write_cfibuffer(info, wp, src, i)) != ERR_OK)
  295. return rc;
  296. wp += i;
  297. src += i;
  298. cnt -= i;
  299. }
  300. #else
  301. /* handle the aligned part */
  302. while (cnt >= info->portwidth) {
  303. cword.l = 0;
  304. for (i = 0; i < info->portwidth; i++) {
  305. flash_add_byte(info, &cword, *src++);
  306. }
  307. if ((rc = flash_write_cfiword(info, wp, cword)) != 0)
  308. return rc;
  309. wp += info->portwidth;
  310. cnt -= info->portwidth;
  311. }
  312. #endif /* CONFIG_SYS_FLASH_USE_BUFFER_WRITE */
  313. if (cnt == 0) {
  314. return (0);
  315. }
  316. /*
  317. * handle unaligned tail bytes
  318. */
  319. cword.l = 0;
  320. for (i = 0, cp = wp; (i < info->portwidth) && (cnt > 0); ++i, ++cp) {
  321. flash_add_byte(info, &cword, *src++);
  322. --cnt;
  323. }
  324. for (; i < info->portwidth; ++i, ++cp) {
  325. flash_add_byte(info, &cword, (*(uchar *) cp));
  326. }
  327. return flash_write_cfiword(info, wp, cword);
  328. }
  329. /*-----------------------------------------------------------------------
  330. */
  331. int flash_real_protect(flash_info_t * info, long sector, int prot)
  332. {
  333. int retcode = 0;
  334. flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS);
  335. flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT);
  336. if (prot)
  337. flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_SET);
  338. else
  339. flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_CLEAR);
  340. if ((retcode =
  341. flash_full_status_check(info, sector, info->erase_blk_tout,
  342. prot ? "protect" : "unprotect")) == 0) {
  343. info->protect[sector] = prot;
  344. /* Intel's unprotect unprotects all locking */
  345. if (prot == 0) {
  346. int i;
  347. for (i = 0; i < info->sector_count; i++) {
  348. if (info->protect[i])
  349. flash_real_protect(info, i, 1);
  350. }
  351. }
  352. }
  353. return retcode;
  354. }
  355. /*-----------------------------------------------------------------------
  356. * wait for XSR.7 to be set. Time out with an error if it does not.
  357. * This routine does not set the flash to read-array mode.
  358. */
  359. static int flash_status_check(flash_info_t * info, ulong sector, ulong tout,
  360. char *prompt)
  361. {
  362. ulong start;
  363. /* Wait for command completion */
  364. start = get_timer(0);
  365. while (!flash_isset(info, sector, 0, FLASH_STATUS_DONE)) {
  366. if (get_timer(start) > info->erase_blk_tout) {
  367. printf("Flash %s timeout at address %lx\n", prompt,
  368. info->start[sector]);
  369. flash_write_cmd(info, sector, 0, FLASH_CMD_RESET);
  370. return ERR_TIMOUT;
  371. }
  372. }
  373. return ERR_OK;
  374. }
  375. /*-----------------------------------------------------------------------
  376. * Wait for XSR.7 to be set, if it times out print an error, otherwise do a full status check.
  377. * This routine sets the flash to read-array mode.
  378. */
  379. static int flash_full_status_check(flash_info_t * info, ulong sector,
  380. ulong tout, char *prompt)
  381. {
  382. int retcode;
  383. retcode = flash_status_check(info, sector, tout, prompt);
  384. if ((retcode == ERR_OK)
  385. && !flash_isequal(info, sector, 0, FLASH_STATUS_DONE)) {
  386. retcode = ERR_INVAL;
  387. printf("Flash %s error at address %lx\n", prompt,
  388. info->start[sector]);
  389. if (flash_isset
  390. (info, sector, 0,
  391. FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)) {
  392. printf("Command Sequence Error.\n");
  393. } else if (flash_isset(info, sector, 0, FLASH_STATUS_ECLBS)) {
  394. printf("Block Erase Error.\n");
  395. retcode = ERR_NOT_ERASED;
  396. } else if (flash_isset(info, sector, 0, FLASH_STATUS_PSLBS)) {
  397. printf("Locking Error\n");
  398. }
  399. if (flash_isset(info, sector, 0, FLASH_STATUS_DPS)) {
  400. printf("Block locked.\n");
  401. retcode = ERR_PROTECTED;
  402. }
  403. if (flash_isset(info, sector, 0, FLASH_STATUS_VPENS))
  404. printf("Vpp Low Error.\n");
  405. }
  406. flash_write_cmd(info, sector, 0, FLASH_CMD_RESET);
  407. return retcode;
  408. }
  409. /*-----------------------------------------------------------------------
  410. */
  411. static void flash_add_byte(flash_info_t * info, cfiword_t * cword, uchar c)
  412. {
  413. switch (info->portwidth) {
  414. case FLASH_CFI_8BIT:
  415. cword->c = c;
  416. break;
  417. case FLASH_CFI_16BIT:
  418. cword->w = (cword->w << 8) | c;
  419. break;
  420. case FLASH_CFI_32BIT:
  421. cword->l = (cword->l << 8) | c;
  422. }
  423. }
  424. /*-----------------------------------------------------------------------
  425. * make a proper sized command based on the port and chip widths
  426. */
  427. static void flash_make_cmd(flash_info_t * info, uchar cmd, void *cmdbuf)
  428. {
  429. int i;
  430. uchar *cp = (uchar *) cmdbuf;
  431. for (i = 0; i < info->portwidth; i++)
  432. *cp++ = ((i + 1) % info->chipwidth) ? '\0' : cmd;
  433. }
  434. /*
  435. * Write a proper sized command to the correct address
  436. */
  437. static void flash_write_cmd(flash_info_t * info, int sect, uchar offset,
  438. uchar cmd)
  439. {
  440. volatile cfiptr_t addr;
  441. cfiword_t cword;
  442. addr.cp = flash_make_addr(info, sect, offset);
  443. flash_make_cmd(info, cmd, &cword);
  444. switch (info->portwidth) {
  445. case FLASH_CFI_8BIT:
  446. *addr.cp = cword.c;
  447. break;
  448. case FLASH_CFI_16BIT:
  449. *addr.wp = cword.w;
  450. break;
  451. case FLASH_CFI_32BIT:
  452. *addr.lp = cword.l;
  453. break;
  454. }
  455. }
  456. /*-----------------------------------------------------------------------
  457. */
  458. static int flash_isequal(flash_info_t * info, int sect, uchar offset, uchar cmd)
  459. {
  460. cfiptr_t cptr;
  461. cfiword_t cword;
  462. int retval;
  463. cptr.cp = flash_make_addr(info, sect, offset);
  464. flash_make_cmd(info, cmd, &cword);
  465. switch (info->portwidth) {
  466. case FLASH_CFI_8BIT:
  467. retval = (cptr.cp[0] == cword.c);
  468. break;
  469. case FLASH_CFI_16BIT:
  470. retval = (cptr.wp[0] == cword.w);
  471. break;
  472. case FLASH_CFI_32BIT:
  473. retval = (cptr.lp[0] == cword.l);
  474. break;
  475. default:
  476. retval = 0;
  477. break;
  478. }
  479. return retval;
  480. }
  481. /*-----------------------------------------------------------------------
  482. */
  483. static int flash_isset(flash_info_t * info, int sect, uchar offset, uchar cmd)
  484. {
  485. cfiptr_t cptr;
  486. cfiword_t cword;
  487. int retval;
  488. cptr.cp = flash_make_addr(info, sect, offset);
  489. flash_make_cmd(info, cmd, &cword);
  490. switch (info->portwidth) {
  491. case FLASH_CFI_8BIT:
  492. retval = ((cptr.cp[0] & cword.c) == cword.c);
  493. break;
  494. case FLASH_CFI_16BIT:
  495. retval = ((cptr.wp[0] & cword.w) == cword.w);
  496. break;
  497. case FLASH_CFI_32BIT:
  498. retval = ((cptr.lp[0] & cword.l) == cword.l);
  499. break;
  500. default:
  501. retval = 0;
  502. break;
  503. }
  504. return retval;
  505. }
  506. /*-----------------------------------------------------------------------
  507. * detect if flash is compatible with the Common Flash Interface (CFI)
  508. * http://www.jedec.org/download/search/jesd68.pdf
  509. *
  510. */
  511. static int flash_detect_cfi(flash_info_t * info)
  512. {
  513. for (info->portwidth = FLASH_CFI_8BIT;
  514. info->portwidth <= FLASH_CFI_32BIT; info->portwidth <<= 1) {
  515. for (info->chipwidth = FLASH_CFI_BY8;
  516. info->chipwidth <= info->portwidth;
  517. info->chipwidth <<= 1) {
  518. flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
  519. flash_write_cmd(info, 0, FLASH_OFFSET_CFI,
  520. FLASH_CMD_CFI);
  521. if (flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
  522. && flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 1,
  523. 'R')
  524. && flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 2,
  525. 'Y'))
  526. return 1;
  527. }
  528. }
  529. return 0;
  530. }
  531. /*
  532. * The following code cannot be run from FLASH!
  533. *
  534. */
  535. static ulong flash_get_size(ulong base, int banknum)
  536. {
  537. flash_info_t *info = &flash_info[banknum];
  538. int i, j;
  539. int sect_cnt;
  540. unsigned long sector;
  541. unsigned long tmp;
  542. int size_ratio = 0;
  543. uchar num_erase_regions;
  544. int erase_region_size;
  545. int erase_region_count;
  546. info->start[0] = base;
  547. #if 0
  548. invalidate_dcache_range(base, base + 0x400);
  549. #endif
  550. if (flash_detect_cfi(info)) {
  551. size_ratio = info->portwidth / info->chipwidth;
  552. num_erase_regions =
  553. flash_read_uchar(info, FLASH_OFFSET_NUM_ERASE_REGIONS);
  554. sect_cnt = 0;
  555. sector = base;
  556. for (i = 0; i < num_erase_regions; i++) {
  557. if (i > NUM_ERASE_REGIONS) {
  558. printf("%d erase regions found, only %d used\n",
  559. num_erase_regions, NUM_ERASE_REGIONS);
  560. break;
  561. }
  562. tmp =
  563. flash_read_long(info, 0,
  564. FLASH_OFFSET_ERASE_REGIONS);
  565. erase_region_size =
  566. (tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;
  567. tmp >>= 16;
  568. erase_region_count = (tmp & 0xffff) + 1;
  569. for (j = 0; j < erase_region_count; j++) {
  570. info->start[sect_cnt] = sector;
  571. sector += (erase_region_size * size_ratio);
  572. info->protect[sect_cnt] =
  573. flash_isset(info, sect_cnt,
  574. FLASH_OFFSET_PROTECT,
  575. FLASH_STATUS_PROTECT);
  576. sect_cnt++;
  577. }
  578. }
  579. info->sector_count = sect_cnt;
  580. /* multiply the size by the number of chips */
  581. info->size =
  582. (1 << flash_read_uchar(info, FLASH_OFFSET_SIZE)) *
  583. size_ratio;
  584. info->buffer_size =
  585. (1 << flash_read_ushort(info, 0, FLASH_OFFSET_BUFFER_SIZE));
  586. tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_ETOUT);
  587. info->erase_blk_tout =
  588. (tmp *
  589. (1 << flash_read_uchar(info, FLASH_OFFSET_EMAX_TOUT)));
  590. tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_WBTOUT);
  591. info->buffer_write_tout =
  592. (tmp *
  593. (1 << flash_read_uchar(info, FLASH_OFFSET_WBMAX_TOUT)));
  594. tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_WTOUT);
  595. info->write_tout =
  596. (tmp *
  597. (1 << flash_read_uchar(info, FLASH_OFFSET_WMAX_TOUT))) /
  598. 1000;
  599. info->flash_id = FLASH_MAN_CFI;
  600. }
  601. flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
  602. #ifdef DEBUG_FLASH
  603. printf("portwidth=%d chipwidth=%d\n", info->portwidth, info->chipwidth); /* test-only */
  604. #endif
  605. #ifdef DEBUG_FLASH
  606. printf("found %d erase regions\n", num_erase_regions);
  607. #endif
  608. #ifdef DEBUG_FLASH
  609. printf("size=%08x sectors=%08x \n", info->size, info->sector_count);
  610. #endif
  611. return (info->size);
  612. }
  613. /*-----------------------------------------------------------------------
  614. */
  615. static int flash_write_cfiword(flash_info_t * info, ulong dest, cfiword_t cword)
  616. {
  617. cfiptr_t ctladdr;
  618. cfiptr_t cptr;
  619. int flag;
  620. ctladdr.cp = flash_make_addr(info, 0, 0);
  621. cptr.cp = (uchar *) dest;
  622. /* Check if Flash is (sufficiently) erased */
  623. switch (info->portwidth) {
  624. case FLASH_CFI_8BIT:
  625. flag = ((cptr.cp[0] & cword.c) == cword.c);
  626. break;
  627. case FLASH_CFI_16BIT:
  628. flag = ((cptr.wp[0] & cword.w) == cword.w);
  629. break;
  630. case FLASH_CFI_32BIT:
  631. flag = ((cptr.lp[0] & cword.l) == cword.l);
  632. break;
  633. default:
  634. return 2;
  635. }
  636. if (!flag)
  637. return 2;
  638. /* Disable interrupts which might cause a timeout here */
  639. flag = disable_interrupts();
  640. flash_write_cmd(info, 0, 0, FLASH_CMD_CLEAR_STATUS);
  641. flash_write_cmd(info, 0, 0, FLASH_CMD_WRITE);
  642. switch (info->portwidth) {
  643. case FLASH_CFI_8BIT:
  644. cptr.cp[0] = cword.c;
  645. break;
  646. case FLASH_CFI_16BIT:
  647. cptr.wp[0] = cword.w;
  648. break;
  649. case FLASH_CFI_32BIT:
  650. cptr.lp[0] = cword.l;
  651. break;
  652. }
  653. /* re-enable interrupts if necessary */
  654. if (flag)
  655. enable_interrupts();
  656. return flash_full_status_check(info, 0, info->write_tout, "write");
  657. }
  658. #ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
  659. /* loop through the sectors from the highest address
  660. * when the passed address is greater or equal to the sector address
  661. * we have a match
  662. */
  663. static int find_sector(flash_info_t * info, ulong addr)
  664. {
  665. int sector;
  666. for (sector = info->sector_count - 1; sector >= 0; sector--) {
  667. if (addr >= info->start[sector])
  668. break;
  669. }
  670. return sector;
  671. }
  672. static int flash_write_cfibuffer(flash_info_t * info, ulong dest, uchar * cp,
  673. int len)
  674. {
  675. int sector;
  676. int cnt;
  677. int retcode;
  678. volatile cfiptr_t src;
  679. volatile cfiptr_t dst;
  680. src.cp = cp;
  681. dst.cp = (uchar *) dest;
  682. sector = find_sector(info, dest);
  683. flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS);
  684. flash_write_cmd(info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
  685. if ((retcode = flash_status_check(info, sector, info->buffer_write_tout,
  686. "write to buffer")) == ERR_OK) {
  687. switch (info->portwidth) {
  688. case FLASH_CFI_8BIT:
  689. cnt = len;
  690. break;
  691. case FLASH_CFI_16BIT:
  692. cnt = len >> 1;
  693. break;
  694. case FLASH_CFI_32BIT:
  695. cnt = len >> 2;
  696. break;
  697. default:
  698. return ERR_INVAL;
  699. break;
  700. }
  701. flash_write_cmd(info, sector, 0, (uchar) cnt - 1);
  702. while (cnt-- > 0) {
  703. switch (info->portwidth) {
  704. case FLASH_CFI_8BIT:
  705. *dst.cp++ = *src.cp++;
  706. break;
  707. case FLASH_CFI_16BIT:
  708. *dst.wp++ = *src.wp++;
  709. break;
  710. case FLASH_CFI_32BIT:
  711. *dst.lp++ = *src.lp++;
  712. break;
  713. default:
  714. return ERR_INVAL;
  715. break;
  716. }
  717. }
  718. flash_write_cmd(info, sector, 0,
  719. FLASH_CMD_WRITE_BUFFER_CONFIRM);
  720. retcode =
  721. flash_full_status_check(info, sector,
  722. info->buffer_write_tout,
  723. "buffer write");
  724. }
  725. flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS);
  726. return retcode;
  727. }
  728. #endif /* CONFIG_SYS_USE_FLASH_BUFFER_WRITE */