flash.c 26 KB

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