strataflash.c 21 KB

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