strataflash.c 22 KB

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