flash.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  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[CONFIG_SYS_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,
  109. uchar cmd);
  110. static int flash_isequal (flash_info_t * info, int sect, uchar offset,
  111. uchar cmd);
  112. static int flash_isset (flash_info_t * info, int sect, uchar offset,
  113. uchar cmd);
  114. static int flash_detect_cfi (flash_info_t * info);
  115. static ulong flash_get_size (ulong base, int banknum);
  116. static int flash_write_cfiword (flash_info_t * info, ulong dest,
  117. cfiword_t cword);
  118. static int flash_full_status_check (flash_info_t * info, ulong sector,
  119. ulong tout, char *prompt);
  120. #ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
  121. static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
  122. int len);
  123. #endif
  124. /*-----------------------------------------------------------------------
  125. * create an address based on the offset and the port width
  126. */
  127. uchar *flash_make_addr (flash_info_t * info, int sect, int offset)
  128. {
  129. return ((uchar *) (info->start[sect] + (offset * info->chipwidth)));
  130. }
  131. /*-----------------------------------------------------------------------
  132. * read a character at a port width address
  133. */
  134. uchar flash_read_uchar (flash_info_t * info, uchar offset)
  135. {
  136. if (info->portwidth == FLASH_CFI_8BIT) {
  137. volatile uchar *cp;
  138. uchar c;
  139. cp = flash_make_addr (info, 0, offset);
  140. c = *cp;
  141. #ifdef DEBUG_FLASH
  142. printf ("flash_read_uchar offset=%04x ptr=%08x c=%02x\n",
  143. offset, (unsigned int) cp, c);
  144. #endif
  145. return (c);
  146. } else if (info->portwidth == FLASH_CFI_16BIT) {
  147. volatile ushort *sp;
  148. ushort s;
  149. uchar c;
  150. sp = (ushort *) flash_make_addr (info, 0, offset);
  151. s = *sp;
  152. c = (uchar) s;
  153. #ifdef DEBUG_FLASH
  154. printf ("flash_read_uchar offset=%04x ptr=%08x s=%04x c=%02x\n", offset, (unsigned int) sp, s, c);
  155. #endif
  156. return (c);
  157. }
  158. return 0;
  159. }
  160. /*-----------------------------------------------------------------------
  161. * read a short word by swapping for ppc format.
  162. */
  163. ushort flash_read_ushort (flash_info_t * info, int sect, uchar offset)
  164. {
  165. if (info->portwidth == FLASH_CFI_8BIT) {
  166. volatile uchar *cp;
  167. uchar c0, c1;
  168. ushort s;
  169. cp = flash_make_addr (info, 0, offset);
  170. c1 = cp[2];
  171. c0 = cp[0];
  172. s = c1 << 8 | c0;
  173. #ifdef DEBUG_FLASH
  174. printf ("flash_read_ushort offset=%04x ptr=%08x c1=%02x c0=%02x s=%04x\n", offset, (unsigned int) cp, c1, c0, s);
  175. #endif
  176. return (s);
  177. } else if (info->portwidth == FLASH_CFI_16BIT) {
  178. volatile ushort *sp;
  179. ushort s;
  180. uchar c0, c1;
  181. sp = (ushort *) flash_make_addr (info, 0, offset);
  182. s = *sp;
  183. c1 = (uchar) sp[1];
  184. c0 = (uchar) sp[0];
  185. s = c1 << 8 | c0;
  186. #ifdef DEBUG_FLASH
  187. printf ("flash_read_ushort offset=%04x ptr=%08x c1=%02x c0=%02x s=%04x\n", offset, (unsigned int) sp, c1, c0, s);
  188. #endif
  189. return (s);
  190. }
  191. return 0;
  192. }
  193. /*-----------------------------------------------------------------------
  194. * read a long word by picking the least significant byte of each maiximum
  195. * port size word. Swap for ppc format.
  196. */
  197. ulong flash_read_long (flash_info_t * info, int sect, uchar offset)
  198. {
  199. if (info->portwidth == FLASH_CFI_8BIT) {
  200. volatile uchar *cp;
  201. uchar c0, c1, c2, c3;
  202. ulong l;
  203. cp = flash_make_addr (info, 0, offset);
  204. c3 = cp[6];
  205. c2 = cp[4];
  206. c1 = cp[2];
  207. c0 = cp[0];
  208. l = c3 << 24 | c2 << 16 | c1 << 8 | c0;
  209. #ifdef DEBUG_FLASH
  210. printf ("flash_read_long offset=%04x ptr=%08x c3=%02x c2=%02x c1=%02x c0=%02x l=%08x\n", offset, (unsigned int) cp, c3, c2, c1, c0, l);
  211. #endif
  212. return (l);
  213. } else if (info->portwidth == FLASH_CFI_16BIT) {
  214. volatile ushort *sp;
  215. uchar c0, c1, c2, c3;
  216. ulong l;
  217. sp = (ushort *) flash_make_addr (info, 0, offset);
  218. c3 = (uchar) sp[3];
  219. c2 = (uchar) sp[2];
  220. c1 = (uchar) sp[1];
  221. c0 = (uchar) sp[0];
  222. l = c3 << 24 | c2 << 16 | c1 << 8 | c0;
  223. #ifdef DEBUG_FLASH
  224. printf ("flash_read_long offset=%04x ptr=%08x c3=%02x c2=%02x c1=%02x c0=%02x l=%08x\n", offset, (unsigned int) sp, c3, c2, c1, c0, l);
  225. #endif
  226. return (l);
  227. }
  228. return 0;
  229. }
  230. /*-----------------------------------------------------------------------
  231. */
  232. unsigned long flash_init (void)
  233. {
  234. unsigned long size;
  235. size = 0;
  236. flash_info[0].flash_id = FLASH_UNKNOWN;
  237. flash_info[0].portwidth = FLASH_CFI_16BIT;
  238. flash_info[0].chipwidth = FLASH_CFI_16BIT;
  239. size += flash_info[0].size = flash_get_size (CONFIG_SYS_PROGFLASH_BASE, 0);
  240. if (flash_info[0].flash_id == FLASH_UNKNOWN) {
  241. printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n", 1, 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 (CONFIG_SYS_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, flash_info[1].size, flash_info[1].size << 20);
  249. };
  250. return (size);
  251. }
  252. /*-----------------------------------------------------------------------
  253. */
  254. int flash_erase (flash_info_t * info, int s_first, int s_last)
  255. {
  256. int rcode = 0;
  257. int prot;
  258. int sect;
  259. if (info->flash_id != FLASH_MAN_CFI) {
  260. printf ("Can't erase unknown flash type - aborted\n");
  261. return 1;
  262. }
  263. if ((s_first < 0) || (s_first > s_last)) {
  264. printf ("- no sectors to erase\n");
  265. return 1;
  266. }
  267. prot = 0;
  268. for (sect = s_first; sect <= s_last; ++sect) {
  269. if (info->protect[sect]) {
  270. prot++;
  271. }
  272. }
  273. if (prot) {
  274. printf ("- Warning: %d protected sectors will not be erased!\n", prot);
  275. } else {
  276. printf ("\n");
  277. }
  278. for (sect = s_first; sect <= s_last; sect++) {
  279. if (info->protect[sect] == 0) { /* not protected */
  280. flash_write_cmd (info, sect, 0,
  281. FLASH_CMD_CLEAR_STATUS);
  282. flash_write_cmd (info, sect, 0,
  283. FLASH_CMD_BLOCK_ERASE);
  284. flash_write_cmd (info, sect, 0,
  285. FLASH_CMD_ERASE_CONFIRM);
  286. if (flash_full_status_check
  287. (info, sect, info->erase_blk_tout, "erase")) {
  288. rcode = 1;
  289. } else
  290. printf (".");
  291. }
  292. }
  293. printf (" done\n");
  294. return rcode;
  295. }
  296. /*-----------------------------------------------------------------------
  297. */
  298. void flash_print_info (flash_info_t * info)
  299. {
  300. int i;
  301. if (info->flash_id != FLASH_MAN_CFI) {
  302. printf ("missing or unknown FLASH type\n");
  303. return;
  304. }
  305. printf ("CFI conformant FLASH (x%d device in x%d mode)",
  306. (info->chipwidth << 3), (info->portwidth << 3));
  307. printf (" Size: %ld MB in %d Sectors\n",
  308. info->size >> 20, info->sector_count);
  309. printf (" Erase timeout %ld ms, write timeout %ld ms, buffer write timeout %ld ms, buffer size %d\n", info->erase_blk_tout, info->write_tout, info->buffer_write_tout, info->buffer_size);
  310. printf (" Sector Start Addresses:");
  311. for (i = 0; i < info->sector_count; ++i) {
  312. if ((i % 5) == 0)
  313. printf ("\n");
  314. printf (" %08lX%5s",
  315. info->start[i], info->protect[i] ? " (RO)" : " ");
  316. }
  317. printf ("\n");
  318. return;
  319. }
  320. /*-----------------------------------------------------------------------
  321. * Copy memory to flash, returns:
  322. * 0 - OK
  323. * 1 - write timeout
  324. * 2 - Flash not erased
  325. */
  326. int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
  327. {
  328. ulong wp;
  329. ulong cp;
  330. int aln;
  331. cfiword_t cword;
  332. int i, rc;
  333. /* get lower aligned address */
  334. wp = (addr & ~(info->portwidth - 1));
  335. /* handle unaligned start */
  336. if ((aln = addr - wp) != 0) {
  337. cword.l = 0;
  338. cp = wp;
  339. for (i = 0; i < aln; ++i, ++cp)
  340. flash_add_byte (info, &cword, (*(uchar *) cp));
  341. for (; (i < info->portwidth) && (cnt > 0); i++) {
  342. flash_add_byte (info, &cword, *src++);
  343. cnt--;
  344. cp++;
  345. }
  346. for (; (cnt == 0) && (i < info->portwidth); ++i, ++cp)
  347. flash_add_byte (info, &cword, (*(uchar *) cp));
  348. if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
  349. return rc;
  350. wp = cp;
  351. }
  352. #ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
  353. while (cnt >= info->portwidth) {
  354. i = info->buffer_size > cnt ? cnt : info->buffer_size;
  355. if ((rc = flash_write_cfibuffer (info, wp, src, i)) != ERR_OK)
  356. return rc;
  357. wp += i;
  358. src += i;
  359. cnt -= i;
  360. }
  361. #else
  362. /* handle the aligned part */
  363. while (cnt >= info->portwidth) {
  364. cword.l = 0;
  365. for (i = 0; i < info->portwidth; i++) {
  366. flash_add_byte (info, &cword, *src++);
  367. }
  368. if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
  369. return rc;
  370. wp += info->portwidth;
  371. cnt -= info->portwidth;
  372. }
  373. #endif /* CONFIG_SYS_FLASH_USE_BUFFER_WRITE */
  374. if (cnt == 0) {
  375. return (0);
  376. }
  377. /*
  378. * handle unaligned tail bytes
  379. */
  380. cword.l = 0;
  381. for (i = 0, cp = wp; (i < info->portwidth) && (cnt > 0); ++i, ++cp) {
  382. flash_add_byte (info, &cword, *src++);
  383. --cnt;
  384. }
  385. for (; i < info->portwidth; ++i, ++cp) {
  386. flash_add_byte (info, &cword, (*(uchar *) cp));
  387. }
  388. return flash_write_cfiword (info, wp, cword);
  389. }
  390. /*-----------------------------------------------------------------------
  391. */
  392. int flash_real_protect (flash_info_t * info, long sector, int prot)
  393. {
  394. int retcode = 0;
  395. flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
  396. flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT);
  397. if (prot)
  398. flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_SET);
  399. else
  400. flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_CLEAR);
  401. if ((retcode =
  402. 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,
  421. char *prompt)
  422. {
  423. ulong start;
  424. /* Wait for command completion */
  425. start = get_timer (0);
  426. while (!flash_isset (info, sector, 0, FLASH_STATUS_DONE)) {
  427. if (get_timer (start) > info->erase_blk_tout) {
  428. printf ("Flash %s timeout at address %lx\n", prompt,
  429. info->start[sector]);
  430. flash_write_cmd (info, sector, 0, FLASH_CMD_RESET);
  431. return ERR_TIMOUT;
  432. }
  433. }
  434. return ERR_OK;
  435. }
  436. /*-----------------------------------------------------------------------
  437. * Wait for XSR.7 to be set, if it times out print an error, otherwise do a full status check.
  438. * This routine sets the flash to read-array mode.
  439. */
  440. static int flash_full_status_check (flash_info_t * info, ulong sector,
  441. ulong tout, char *prompt)
  442. {
  443. int retcode;
  444. retcode = flash_status_check (info, sector, tout, prompt);
  445. if ((retcode == ERR_OK)
  446. && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) {
  447. retcode = ERR_INVAL;
  448. printf ("Flash %s error at address %lx\n", prompt,
  449. info->start[sector]);
  450. if (flash_isset
  451. (info, sector, 0,
  452. FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)) {
  453. printf ("Command Sequence Error.\n");
  454. } else if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS)) {
  455. printf ("Block Erase Error.\n");
  456. retcode = ERR_NOT_ERASED;
  457. } else if (flash_isset (info, sector, 0, FLASH_STATUS_PSLBS)) {
  458. printf ("Locking Error\n");
  459. }
  460. if (flash_isset (info, sector, 0, FLASH_STATUS_DPS)) {
  461. printf ("Block locked.\n");
  462. retcode = ERR_PROTECTED;
  463. }
  464. if (flash_isset (info, sector, 0, FLASH_STATUS_VPENS))
  465. printf ("Vpp Low Error.\n");
  466. }
  467. flash_write_cmd (info, sector, 0, FLASH_CMD_RESET);
  468. return retcode;
  469. }
  470. /*-----------------------------------------------------------------------
  471. */
  472. static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c)
  473. {
  474. switch (info->portwidth) {
  475. case FLASH_CFI_8BIT:
  476. cword->c = c;
  477. break;
  478. case FLASH_CFI_16BIT:
  479. cword->w = (cword->w << 8) | c;
  480. break;
  481. case FLASH_CFI_32BIT:
  482. cword->l = (cword->l << 8) | c;
  483. }
  484. }
  485. /*-----------------------------------------------------------------------
  486. * make a proper sized command based on the port and chip widths
  487. */
  488. static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf)
  489. {
  490. /*int i; */
  491. uchar *cp = (uchar *) cmdbuf;
  492. /* for(i=0; i< info->portwidth; i++) */
  493. /* *cp++ = ((i+1) % info->chipwidth) ? '\0':cmd; */
  494. if (info->portwidth == FLASH_CFI_8BIT
  495. && info->chipwidth == FLASH_CFI_16BIT) {
  496. cp[0] = cmd;
  497. } else if (info->portwidth == FLASH_CFI_16BIT
  498. && info->chipwidth == FLASH_CFI_16BIT) {
  499. cp[0] = '\0';
  500. cp[1] = cmd;
  501. };
  502. }
  503. /*
  504. * Write a proper sized command to the correct address
  505. */
  506. static void flash_write_cmd (flash_info_t * info, int sect, uchar offset,
  507. uchar cmd)
  508. {
  509. volatile cfiptr_t addr;
  510. cfiword_t cword;
  511. addr.cp = flash_make_addr (info, sect, offset);
  512. flash_make_cmd (info, cmd, &cword);
  513. switch (info->portwidth) {
  514. case FLASH_CFI_8BIT:
  515. *addr.cp = cword.c;
  516. break;
  517. case FLASH_CFI_16BIT:
  518. *addr.wp = cword.w;
  519. break;
  520. case FLASH_CFI_32BIT:
  521. *addr.lp = cword.l;
  522. break;
  523. }
  524. }
  525. /*-----------------------------------------------------------------------
  526. */
  527. static int flash_isequal (flash_info_t * info, int sect, uchar offset,
  528. uchar cmd)
  529. {
  530. cfiptr_t cptr;
  531. cfiword_t cword;
  532. int retval;
  533. cptr.cp = flash_make_addr (info, sect, offset);
  534. flash_make_cmd (info, cmd, &cword);
  535. switch (info->portwidth) {
  536. case FLASH_CFI_8BIT:
  537. retval = (cptr.cp[0] == cword.c);
  538. break;
  539. case FLASH_CFI_16BIT:
  540. retval = (cptr.wp[0] == cword.w);
  541. break;
  542. case FLASH_CFI_32BIT:
  543. retval = (cptr.lp[0] == cword.l);
  544. break;
  545. default:
  546. retval = 0;
  547. break;
  548. }
  549. return retval;
  550. }
  551. /*-----------------------------------------------------------------------
  552. */
  553. static int flash_isset (flash_info_t * info, int sect, uchar offset,
  554. uchar cmd)
  555. {
  556. cfiptr_t cptr;
  557. cfiword_t cword;
  558. int retval;
  559. cptr.cp = flash_make_addr (info, sect, offset);
  560. flash_make_cmd (info, cmd, &cword);
  561. switch (info->portwidth) {
  562. case FLASH_CFI_8BIT:
  563. retval = ((cptr.cp[0] & cword.c) == cword.c);
  564. break;
  565. case FLASH_CFI_16BIT:
  566. retval = ((cptr.wp[0] & cword.w) == cword.w);
  567. break;
  568. case FLASH_CFI_32BIT:
  569. retval = ((cptr.lp[0] & cword.l) == cword.l);
  570. break;
  571. default:
  572. retval = 0;
  573. break;
  574. }
  575. return retval;
  576. }
  577. /*-----------------------------------------------------------------------
  578. * detect if flash is compatible with the Common Flash Interface (CFI)
  579. * http://www.jedec.org/download/search/jesd68.pdf
  580. *
  581. */
  582. static int flash_detect_cfi (flash_info_t * info)
  583. {
  584. #if 0
  585. for (info->portwidth = FLASH_CFI_8BIT;
  586. info->portwidth <= FLASH_CFI_32BIT; info->portwidth <<= 1) {
  587. for (info->chipwidth = FLASH_CFI_BY8;
  588. info->chipwidth <= info->portwidth;
  589. info->chipwidth <<= 1) {
  590. flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);
  591. flash_write_cmd (info, 0, FLASH_OFFSET_CFI,
  592. FLASH_CMD_CFI);
  593. if (flash_isequal
  594. (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
  595. && flash_isequal (info, 0,
  596. FLASH_OFFSET_CFI_RESP + 1, 'R')
  597. && flash_isequal (info, 0,
  598. FLASH_OFFSET_CFI_RESP + 2, 'Y'))
  599. return 1;
  600. }
  601. }
  602. #endif
  603. flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);
  604. flash_write_cmd (info, 0, FLASH_OFFSET_CFI, FLASH_CMD_CFI);
  605. if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q') &&
  606. flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R') &&
  607. flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) {
  608. return 1;
  609. } else {
  610. return 0;
  611. };
  612. }
  613. /*
  614. * The following code cannot be run from FLASH!
  615. *
  616. */
  617. static ulong flash_get_size (ulong base, int banknum)
  618. {
  619. flash_info_t *info = &flash_info[banknum];
  620. int i, j;
  621. int sect_cnt;
  622. unsigned long sector;
  623. unsigned long tmp;
  624. int size_ratio;
  625. uchar num_erase_regions;
  626. int erase_region_size;
  627. int erase_region_count;
  628. info->start[0] = base;
  629. if (flash_detect_cfi (info)) {
  630. #ifdef DEBUG_FLASH
  631. printf ("portwidth=%d chipwidth=%d\n", info->portwidth, info->chipwidth); /* test-only */
  632. #endif
  633. size_ratio = 1; /* info->portwidth / info->chipwidth; */
  634. num_erase_regions =
  635. flash_read_uchar (info,
  636. FLASH_OFFSET_NUM_ERASE_REGIONS);
  637. #ifdef DEBUG_FLASH
  638. printf ("found %d erase regions\n", num_erase_regions);
  639. #endif
  640. sect_cnt = 0;
  641. sector = base;
  642. for (i = 0; i < num_erase_regions; i++) {
  643. if (i > NUM_ERASE_REGIONS) {
  644. printf ("%d erase regions found, only %d used\n", num_erase_regions, NUM_ERASE_REGIONS);
  645. break;
  646. }
  647. tmp = flash_read_long (info, 0,
  648. FLASH_OFFSET_ERASE_REGIONS);
  649. erase_region_count = (tmp & 0xffff) + 1;
  650. tmp >>= 16;
  651. erase_region_size =
  652. (tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;
  653. for (j = 0; j < erase_region_count; j++) {
  654. info->start[sect_cnt] = sector;
  655. sector += (erase_region_size * size_ratio);
  656. info->protect[sect_cnt] =
  657. flash_isset (info, sect_cnt,
  658. FLASH_OFFSET_PROTECT,
  659. FLASH_STATUS_PROTECT);
  660. sect_cnt++;
  661. }
  662. }
  663. info->sector_count = sect_cnt;
  664. /* multiply the size by the number of chips */
  665. info->size =
  666. (1 << flash_read_uchar (info, FLASH_OFFSET_SIZE)) *
  667. size_ratio;
  668. info->buffer_size =
  669. (1 <<
  670. flash_read_ushort (info, 0,
  671. FLASH_OFFSET_BUFFER_SIZE));
  672. tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_ETOUT);
  673. info->erase_blk_tout =
  674. (tmp *
  675. (1 <<
  676. flash_read_uchar (info, FLASH_OFFSET_EMAX_TOUT)));
  677. tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WBTOUT);
  678. info->buffer_write_tout =
  679. (tmp *
  680. (1 <<
  681. flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT)));
  682. tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT);
  683. info->write_tout =
  684. (tmp *
  685. (1 <<
  686. flash_read_uchar (info,
  687. FLASH_OFFSET_WMAX_TOUT))) / 1000;
  688. info->flash_id = FLASH_MAN_CFI;
  689. }
  690. flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);
  691. return (info->size);
  692. }
  693. /*-----------------------------------------------------------------------
  694. */
  695. static int flash_write_cfiword (flash_info_t * info, ulong dest,
  696. cfiword_t cword)
  697. {
  698. cfiptr_t ctladdr;
  699. cfiptr_t cptr;
  700. int flag;
  701. ctladdr.cp = flash_make_addr (info, 0, 0);
  702. cptr.cp = (uchar *) dest;
  703. /* Check if Flash is (sufficiently) erased */
  704. switch (info->portwidth) {
  705. case FLASH_CFI_8BIT:
  706. flag = ((cptr.cp[0] & cword.c) == cword.c);
  707. break;
  708. case FLASH_CFI_16BIT:
  709. flag = ((cptr.wp[0] & cword.w) == cword.w);
  710. break;
  711. case FLASH_CFI_32BIT:
  712. flag = ((cptr.lp[0] & cword.l) == cword.l);
  713. break;
  714. default:
  715. return 2;
  716. }
  717. if (!flag)
  718. return 2;
  719. /* Disable interrupts which might cause a timeout here */
  720. flag = disable_interrupts ();
  721. flash_write_cmd (info, 0, 0, FLASH_CMD_CLEAR_STATUS);
  722. flash_write_cmd (info, 0, 0, FLASH_CMD_WRITE);
  723. switch (info->portwidth) {
  724. case FLASH_CFI_8BIT:
  725. cptr.cp[0] = cword.c;
  726. break;
  727. case FLASH_CFI_16BIT:
  728. cptr.wp[0] = cword.w;
  729. break;
  730. case FLASH_CFI_32BIT:
  731. cptr.lp[0] = cword.l;
  732. break;
  733. }
  734. /* re-enable interrupts if necessary */
  735. if (flag)
  736. enable_interrupts ();
  737. return flash_full_status_check (info, 0, info->write_tout, "write");
  738. }
  739. #ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
  740. /* loop through the sectors from the highest address
  741. * when the passed address is greater or equal to the sector address
  742. * we have a match
  743. */
  744. static int find_sector (flash_info_t * info, ulong addr)
  745. {
  746. int sector;
  747. for (sector = info->sector_count - 1; sector >= 0; sector--) {
  748. if (addr >= info->start[sector])
  749. break;
  750. }
  751. return sector;
  752. }
  753. static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
  754. int len)
  755. {
  756. int sector;
  757. int cnt;
  758. int retcode;
  759. volatile cfiptr_t src;
  760. volatile cfiptr_t dst;
  761. src.cp = cp;
  762. dst.cp = (uchar *) dest;
  763. sector = find_sector (info, dest);
  764. flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
  765. flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
  766. if ((retcode =
  767. flash_status_check (info, sector, info->buffer_write_tout,
  768. "write to buffer")) == ERR_OK) {
  769. switch (info->portwidth) {
  770. case FLASH_CFI_8BIT:
  771. cnt = len;
  772. break;
  773. case FLASH_CFI_16BIT:
  774. cnt = len >> 1;
  775. break;
  776. case FLASH_CFI_32BIT:
  777. cnt = len >> 2;
  778. break;
  779. default:
  780. return ERR_INVAL;
  781. break;
  782. }
  783. flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
  784. while (cnt-- > 0) {
  785. switch (info->portwidth) {
  786. case FLASH_CFI_8BIT:
  787. *dst.cp++ = *src.cp++;
  788. break;
  789. case FLASH_CFI_16BIT:
  790. *dst.wp++ = *src.wp++;
  791. break;
  792. case FLASH_CFI_32BIT:
  793. *dst.lp++ = *src.lp++;
  794. break;
  795. default:
  796. return ERR_INVAL;
  797. break;
  798. }
  799. }
  800. flash_write_cmd (info, sector, 0,
  801. FLASH_CMD_WRITE_BUFFER_CONFIRM);
  802. retcode =
  803. flash_full_status_check (info, sector,
  804. info->buffer_write_tout,
  805. "buffer write");
  806. }
  807. flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
  808. return retcode;
  809. }
  810. #endif /* CONFIG_SYS_USE_FLASH_BUFFER_WRITE */