flash.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. /*
  2. *
  3. * Copyright (c) 2004 Cucy Systems (http://www.cucy.com)
  4. * Curt Brune <curt@cucy.com>
  5. *
  6. * See file CREDITS for list of people who contributed to this
  7. * project.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation; either version 2 of
  12. * the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22. * MA 02111-1307 USA
  23. */
  24. #include <common.h>
  25. #include <asm/hardware.h>
  26. #include <flash.h>
  27. flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
  28. typedef enum {
  29. FLASH_DEV_U9_512KB = 0,
  30. FLASH_DEV_U7_2MB = 1
  31. } FLASH_DEV;
  32. #define FLASH_DQ7 (0x80)
  33. #define FLASH_DQ5 (0x20)
  34. #define PROG_ADDR (0xAAA)
  35. #define SETUP_ADDR (0xAAA)
  36. #define ID_ADDR (0xAAA)
  37. #define UNLOCK_ADDR1 (0xAAA)
  38. #define UNLOCK_ADDR2 (0x555)
  39. #define UNLOCK_CMD1 (0xAA)
  40. #define UNLOCK_CMD2 (0x55)
  41. #define ERASE_SUSPEND_CMD (0xB0)
  42. #define ERASE_RESUME_CMD (0x30)
  43. #define RESET_CMD (0xF0)
  44. #define ID_CMD (0x90)
  45. #define SELECT_CMD (0x90)
  46. #define CHIPERASE_CMD (0x10)
  47. #define BYPASS_CMD (0x20)
  48. #define SECERASE_CMD (0x30)
  49. #define PROG_CMD (0xa0)
  50. #define SETUP_CMD (0x80)
  51. #if 0
  52. #define WRITE_UNLOCK(addr) { \
  53. PUT__U8( addr + UNLOCK_ADDR1, UNLOCK_CMD1); \
  54. PUT__U8( addr + UNLOCK_ADDR2, UNLOCK_CMD2); \
  55. }
  56. /* auto select command */
  57. #define CMD_ID(addr) WRITE_UNLOCK(addr); { \
  58. PUT__U8( addr + ID_ADDR, ID_CMD); \
  59. }
  60. #define CMD_RESET(addr) WRITE_UNLOCK(addr); { \
  61. PUT__U8( addr + ID_ADDR, RESET_CMD); \
  62. }
  63. #define CMD_ERASE_SEC(base, addr) WRITE_UNLOCK(base); \
  64. PUT__U8( base + SETUP_ADDR, SETUP_CMD); \
  65. WRITE_UNLOCK(base); \
  66. PUT__U8( addr, SECERASE_CMD);
  67. #define CMD_ERASE_CHIP(base) WRITE_UNLOCK(base); \
  68. PUT__U8( base + SETUP_ADDR, SETUP_CMD); \
  69. WRITE_UNLOCK(base); \
  70. PUT__U8( base + SETUP_ADDR, CHIPERASE_CMD);
  71. /* prepare for bypass programming */
  72. #define CMD_UNLOCK_BYPASS(addr) WRITE_UNLOCK(addr); { \
  73. PUT__U8( addr + ID_ADDR, 0x20); \
  74. }
  75. /* terminate bypass programming */
  76. #define CMD_BYPASS_RESET(addr) { \
  77. PUT__U8(addr, 0x90); \
  78. PUT__U8(addr, 0x00); \
  79. }
  80. #endif
  81. inline static void FLASH_CMD_UNLOCK (FLASH_DEV dev, u32 base)
  82. {
  83. switch (dev) {
  84. case FLASH_DEV_U7_2MB:
  85. PUT__U8 (base + 0xAAA, 0xAA);
  86. PUT__U8 (base + 0x555, 0x55);
  87. break;
  88. case FLASH_DEV_U9_512KB:
  89. PUT__U8 (base + 0x555, 0xAA);
  90. PUT__U8 (base + 0x2AA, 0x55);
  91. break;
  92. }
  93. }
  94. inline static void FLASH_CMD_SELECT (FLASH_DEV dev, u32 base)
  95. {
  96. switch (dev) {
  97. case FLASH_DEV_U7_2MB:
  98. FLASH_CMD_UNLOCK (dev, base);
  99. PUT__U8 (base + 0xAAA, SELECT_CMD);
  100. break;
  101. case FLASH_DEV_U9_512KB:
  102. FLASH_CMD_UNLOCK (dev, base);
  103. PUT__U8 (base + 0x555, SELECT_CMD);
  104. break;
  105. }
  106. }
  107. inline static void FLASH_CMD_RESET (FLASH_DEV dev, u32 base)
  108. {
  109. switch (dev) {
  110. case FLASH_DEV_U7_2MB:
  111. FLASH_CMD_UNLOCK (dev, base);
  112. PUT__U8 (base + 0xAAA, RESET_CMD);
  113. break;
  114. case FLASH_DEV_U9_512KB:
  115. FLASH_CMD_UNLOCK (dev, base);
  116. PUT__U8 (base + 0x555, RESET_CMD);
  117. break;
  118. }
  119. }
  120. inline static void FLASH_CMD_ERASE_SEC (FLASH_DEV dev, u32 base, u32 addr)
  121. {
  122. switch (dev) {
  123. case FLASH_DEV_U7_2MB:
  124. FLASH_CMD_UNLOCK (dev, base);
  125. PUT__U8 (base + 0xAAA, SETUP_CMD);
  126. FLASH_CMD_UNLOCK (dev, base);
  127. PUT__U8 (addr, SECERASE_CMD);
  128. break;
  129. case FLASH_DEV_U9_512KB:
  130. FLASH_CMD_UNLOCK (dev, base);
  131. PUT__U8 (base + 0x555, SETUP_CMD);
  132. FLASH_CMD_UNLOCK (dev, base);
  133. PUT__U8 (addr, SECERASE_CMD);
  134. break;
  135. }
  136. }
  137. inline static void FLASH_CMD_ERASE_CHIP (FLASH_DEV dev, u32 base)
  138. {
  139. switch (dev) {
  140. case FLASH_DEV_U7_2MB:
  141. FLASH_CMD_UNLOCK (dev, base);
  142. PUT__U8 (base + 0xAAA, SETUP_CMD);
  143. FLASH_CMD_UNLOCK (dev, base);
  144. PUT__U8 (base, CHIPERASE_CMD);
  145. break;
  146. case FLASH_DEV_U9_512KB:
  147. FLASH_CMD_UNLOCK (dev, base);
  148. PUT__U8 (base + 0x555, SETUP_CMD);
  149. FLASH_CMD_UNLOCK (dev, base);
  150. PUT__U8 (base, CHIPERASE_CMD);
  151. break;
  152. }
  153. }
  154. inline static void FLASH_CMD_UNLOCK_BYPASS (FLASH_DEV dev, u32 base)
  155. {
  156. switch (dev) {
  157. case FLASH_DEV_U7_2MB:
  158. FLASH_CMD_UNLOCK (dev, base);
  159. PUT__U8 (base + 0xAAA, BYPASS_CMD);
  160. break;
  161. case FLASH_DEV_U9_512KB:
  162. FLASH_CMD_UNLOCK (dev, base);
  163. PUT__U8 (base + 0x555, BYPASS_CMD);
  164. break;
  165. }
  166. }
  167. inline static void FLASH_CMD_BYPASS_RESET (FLASH_DEV dev, u32 base)
  168. {
  169. PUT__U8 (base, SELECT_CMD);
  170. PUT__U8 (base, 0x0);
  171. }
  172. /* poll for flash command completion */
  173. static u16 _flash_poll (FLASH_DEV dev, u32 addr, u16 data, ulong timeOut)
  174. {
  175. u32 done = 0;
  176. ulong t0;
  177. u16 error = 0;
  178. volatile u16 flashData;
  179. data = data & 0xFF;
  180. t0 = get_timer (0);
  181. while (get_timer (t0) < timeOut) {
  182. /* for( i = 0; i < POLL_LOOPS; i++) { */
  183. /* Read the Data */
  184. flashData = GET__U8 (addr);
  185. /* FLASH_DQ7 = Data? */
  186. if ((flashData & FLASH_DQ7) == (data & FLASH_DQ7)) {
  187. done = 1;
  188. break;
  189. }
  190. /* Check Timeout (FLASH_DQ5==1) */
  191. if (flashData & FLASH_DQ5) {
  192. /* Read the Data */
  193. flashData = GET__U8 (addr);
  194. /* FLASH_DQ7 = Data? */
  195. if (!((flashData & FLASH_DQ7) == (data & FLASH_DQ7))) {
  196. printf ("_flash_poll(): FLASH_DQ7 & flashData not equal to write value\n");
  197. error = ERR_PROG_ERROR;
  198. }
  199. FLASH_CMD_RESET (dev, addr);
  200. done = 1;
  201. break;
  202. }
  203. /* spin delay */
  204. udelay (10);
  205. }
  206. /* error update */
  207. if (!done) {
  208. printf ("_flash_poll(): Timeout\n");
  209. error = ERR_TIMOUT;
  210. }
  211. /* Check the data */
  212. if (!error) {
  213. /* Read the Data */
  214. flashData = GET__U8 (addr);
  215. if (flashData != data) {
  216. error = ERR_PROG_ERROR;
  217. printf ("_flash_poll(): flashData(0x%04x) not equal to data(0x%04x)\n",
  218. flashData, data);
  219. }
  220. }
  221. return error;
  222. }
  223. /*-----------------------------------------------------------------------
  224. */
  225. static int _flash_check_protection (flash_info_t * info, int s_first, int s_last)
  226. {
  227. int sect, prot = 0;
  228. for (sect = s_first; sect <= s_last; sect++)
  229. if (info->protect[sect]) {
  230. printf (" Flash sector %d protected.\n", sect);
  231. prot++;
  232. }
  233. return prot;
  234. }
  235. static int _detectFlash (FLASH_DEV dev, u32 base, u8 venId, u8 devId)
  236. {
  237. u32 baseAddr = base | CACHE_DISABLE_MASK;
  238. u8 vendorId, deviceId;
  239. /* printf(__FUNCTION__"(): detecting flash @ 0x%08x\n", base); */
  240. /* Send auto select command and read manufacturer info */
  241. FLASH_CMD_SELECT (dev, baseAddr);
  242. vendorId = GET__U8 (baseAddr);
  243. FLASH_CMD_RESET (dev, baseAddr);
  244. /* Send auto select command and read device info */
  245. FLASH_CMD_SELECT (dev, baseAddr);
  246. if (dev == FLASH_DEV_U7_2MB) {
  247. deviceId = GET__U8 (baseAddr + 2);
  248. } else if (dev == FLASH_DEV_U9_512KB) {
  249. deviceId = GET__U8 (baseAddr + 1);
  250. } else {
  251. return 0;
  252. }
  253. FLASH_CMD_RESET (dev, baseAddr);
  254. /* printf (__FUNCTION__"(): found vendorId 0x%04x, deviceId 0x%04x\n",
  255. vendorId, deviceId);
  256. */
  257. return (vendorId == venId) && (deviceId == devId);
  258. }
  259. /******************************************************************************
  260. *
  261. * Public u-boot interface functions below
  262. *
  263. *****************************************************************************/
  264. /***************************************************************************
  265. *
  266. * Flash initialization
  267. *
  268. * This board has two banks of flash, but the base addresses depend on
  269. * how the board is jumpered.
  270. *
  271. * The two flash types are:
  272. *
  273. * AMD Am29LV160DB (2MB) sectors layout 16KB, 2x8KB, 32KB, 31x64KB
  274. *
  275. * AMD Am29LV040B (512KB) sectors: 8x64KB
  276. *****************************************************************************/
  277. unsigned long flash_init (void)
  278. {
  279. flash_info_t *info;
  280. u16 i;
  281. u32 flashtest;
  282. s16 amd160 = -1;
  283. u32 amd160base = 0;
  284. #if CFG_MAX_FLASH_BANKS == 2
  285. s16 amd040 = -1;
  286. u32 amd040base = 0;
  287. #endif
  288. /* configure PHYS_FLASH_1 */
  289. if (_detectFlash (FLASH_DEV_U7_2MB, PHYS_FLASH_1, 0x1, 0x49)) {
  290. amd160 = 0;
  291. amd160base = PHYS_FLASH_1;
  292. #if CFG_MAX_FLASH_BANKS == 1
  293. }
  294. #else
  295. if (_detectFlash
  296. (FLASH_DEV_U9_512KB, PHYS_FLASH_2, 0x1, 0x4F)) {
  297. amd040 = 1;
  298. amd040base = PHYS_FLASH_2;
  299. } else {
  300. printf (__FUNCTION__
  301. "(): Unable to detect PHYS_FLASH_2: 0x%08x\n",
  302. PHYS_FLASH_2);
  303. }
  304. } else if (_detectFlash (FLASH_DEV_U9_512KB, PHYS_FLASH_1, 0x1, 0x4F)) {
  305. amd040 = 0;
  306. amd040base = PHYS_FLASH_1;
  307. if (_detectFlash (FLASH_DEV_U7_2MB, PHYS_FLASH_2, 0x1, 0x49)) {
  308. amd160 = 1;
  309. amd160base = PHYS_FLASH_2;
  310. } else {
  311. printf (__FUNCTION__
  312. "(): Unable to detect PHYS_FLASH_2: 0x%08x\n",
  313. PHYS_FLASH_2);
  314. }
  315. }
  316. #endif
  317. else {
  318. printf ("flash_init(): Unable to detect PHYS_FLASH_1: 0x%08x\n",
  319. PHYS_FLASH_1);
  320. }
  321. /* Configure AMD Am29LV160DB (2MB) */
  322. info = &flash_info[amd160];
  323. info->flash_id = FLASH_DEV_U7_2MB;
  324. info->sector_count = 35;
  325. info->size = 2 * 1024 * 1024; /* 2MB */
  326. /* 1*16K Boot Block
  327. 2*8K Parameter Block
  328. 1*32K Small Main Block */
  329. info->start[0] = amd160base;
  330. info->start[1] = amd160base + 0x4000;
  331. info->start[2] = amd160base + 0x6000;
  332. info->start[3] = amd160base + 0x8000;
  333. for (i = 1; i < info->sector_count; i++)
  334. info->start[3 + i] = amd160base + i * (64 * 1024);
  335. for (i = 0; i < info->sector_count; i++) {
  336. /* Write auto select command sequence and query sector protection */
  337. FLASH_CMD_SELECT (info->flash_id,
  338. info->start[i] | CACHE_DISABLE_MASK);
  339. flashtest =
  340. GET__U8 (((info->start[i] + 4) | CACHE_DISABLE_MASK));
  341. FLASH_CMD_RESET (info->flash_id,
  342. amd160base | CACHE_DISABLE_MASK);
  343. info->protect[i] = (flashtest & 0x0001);
  344. }
  345. /*
  346. * protect monitor and environment sectors in 2MB flash
  347. */
  348. flash_protect (FLAG_PROTECT_SET,
  349. amd160base, amd160base + monitor_flash_len - 1, info);
  350. flash_protect (FLAG_PROTECT_SET,
  351. CFG_ENV_ADDR, CFG_ENV_ADDR + CFG_ENV_SIZE - 1, info);
  352. #if CFG_MAX_FLASH_BANKS == 2
  353. /* Configure AMD Am29LV040B (512KB) */
  354. info = &flash_info[amd040];
  355. info->flash_id = FLASH_DEV_U9_512KB;
  356. info->sector_count = 8;
  357. info->size = 512 * 1024; /* 512KB, 8 x 64KB */
  358. for (i = 0; i < info->sector_count; i++) {
  359. info->start[i] = amd040base + i * (64 * 1024);
  360. /* Write auto select command sequence and query sector protection */
  361. FLASH_CMD_SELECT (info->flash_id,
  362. info->start[i] | CACHE_DISABLE_MASK);
  363. flashtest =
  364. GET__U8 (((info->start[i] + 2) | CACHE_DISABLE_MASK));
  365. FLASH_CMD_RESET (info->flash_id,
  366. amd040base | CACHE_DISABLE_MASK);
  367. info->protect[i] = (flashtest & 0x0001);
  368. }
  369. #endif
  370. return flash_info[0].size
  371. #if CFG_MAX_FLASH_BANKS == 2
  372. + flash_info[1].size
  373. #endif
  374. ;
  375. }
  376. void flash_print_info (flash_info_t * info)
  377. {
  378. int i;
  379. if (info->flash_id == FLASH_DEV_U7_2MB) {
  380. printf ("AMD Am29LV160DB (2MB) 16KB,2x8KB,32KB,31x64KB\n");
  381. } else if (info->flash_id == FLASH_DEV_U9_512KB) {
  382. printf ("AMD Am29LV040B (512KB) 8x64KB\n");
  383. } else {
  384. printf ("Unknown flash_id ...\n");
  385. return;
  386. }
  387. printf (" Size: %ld KB in %d Sectors\n",
  388. info->size >> 10, info->sector_count);
  389. printf (" Sector Start Addresses:");
  390. for (i = 0; i < info->sector_count; i++) {
  391. if ((i % 4) == 0)
  392. printf ("\n ");
  393. printf (" S%02d @ 0x%08lX%s", i,
  394. info->start[i], info->protect[i] ? " !" : " ");
  395. }
  396. printf ("\n");
  397. }
  398. int flash_erase (flash_info_t * info, int s_first, int s_last)
  399. {
  400. u16 i, error = 0;
  401. printf ("\n");
  402. /* check flash protection bits */
  403. if (_flash_check_protection (info, s_first, s_last)) {
  404. printf (" Flash erase aborted due to protected sectors\n");
  405. return ERR_PROTECTED;
  406. }
  407. if ((s_first < info->sector_count) && (s_first <= s_last)) {
  408. for (i = s_first; i <= s_last && !error; i++) {
  409. printf (" Erasing Sector %d @ 0x%08lx ... ", i,
  410. info->start[i]);
  411. /* bypass the cache to access the flash memory */
  412. FLASH_CMD_ERASE_SEC (info->flash_id,
  413. (info->
  414. start[0] | CACHE_DISABLE_MASK),
  415. (info->
  416. start[i] | CACHE_DISABLE_MASK));
  417. /* look for sector to become 0xFF after erase */
  418. error = _flash_poll (info->flash_id,
  419. info->
  420. start[i] | CACHE_DISABLE_MASK,
  421. 0xFF, CFG_FLASH_ERASE_TOUT);
  422. FLASH_CMD_RESET (info->flash_id,
  423. (info->
  424. start[0] | CACHE_DISABLE_MASK));
  425. printf ("done\n");
  426. if (error) {
  427. break;
  428. }
  429. }
  430. } else
  431. error = ERR_INVAL;
  432. return error;
  433. }
  434. int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
  435. {
  436. u16 error = 0, i;
  437. u32 n;
  438. u8 *bp, *bps;
  439. /* Write Setup */
  440. /* bypass the cache to access the flash memory */
  441. FLASH_CMD_UNLOCK_BYPASS (info->flash_id,
  442. (info->start[0] | CACHE_DISABLE_MASK));
  443. /* Write the Data to Flash */
  444. bp = (u8 *) (addr | CACHE_DISABLE_MASK);
  445. bps = (u8 *) src;
  446. for (n = 0; n < cnt && !error; n++, bp++, bps++) {
  447. if (!(n % (cnt / 15))) {
  448. printf (".");
  449. }
  450. /* write the flash command for flash memory */
  451. *bp = 0xA0;
  452. /* Write the data */
  453. *bp = *bps;
  454. /* Check if the write is done */
  455. for (i = 0; i < 0xff; i++);
  456. error = _flash_poll (info->flash_id, (u32) bp, *bps,
  457. CFG_FLASH_WRITE_TOUT);
  458. if (error) {
  459. return error;
  460. }
  461. }
  462. /* Reset the Flash Mode to read */
  463. FLASH_CMD_BYPASS_RESET (info->flash_id, info->start[0]);
  464. printf (" ");
  465. return error;
  466. }