flash.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. /*
  2. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  3. *
  4. * See file CREDITS for list of people who contributed to this
  5. * project.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20. * MA 02111-1307 USA
  21. */
  22. #include <common.h>
  23. #include <mpc8xx.h>
  24. #ifndef CONFIG_ENV_ADDR
  25. #define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
  26. #endif
  27. flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
  28. /*-----------------------------------------------------------------------
  29. * Functions
  30. */
  31. static int write_word(flash_info_t *info, ulong dest, ulong data);
  32. #ifdef CONFIG_BOOT_8B
  33. static int my_in_8(unsigned char *addr);
  34. static void my_out_8(unsigned char *addr, int val);
  35. #endif
  36. #ifdef CONFIG_BOOT_16B
  37. static int my_in_be16(unsigned short *addr);
  38. static void my_out_be16(unsigned short *addr, int val);
  39. #endif
  40. #ifdef CONFIG_BOOT_32B
  41. static unsigned my_in_be32(unsigned *addr);
  42. static void my_out_be32(unsigned *addr, int val);
  43. #endif
  44. /*-----------------------------------------------------------------------
  45. */
  46. unsigned long flash_init(void)
  47. {
  48. volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
  49. volatile memctl8xx_t *memctl = &immap->im_memctl;
  50. unsigned long size_b0, size_b1;
  51. int i;
  52. size_b0 = 0;
  53. size_b1 = 0;
  54. /* Init: no FLASHes known */
  55. for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i)
  56. flash_info[i].flash_id = FLASH_UNKNOWN;
  57. #ifdef CONFIG_SYS_DOC_BASE
  58. #ifndef CONFIG_FEL8xx_AT
  59. /* 32k bytes */
  60. memctl->memc_or5 = (0xffff8000 | CONFIG_SYS_OR_TIMING_DOC);
  61. memctl->memc_br5 = CONFIG_SYS_DOC_BASE | 0x401;
  62. #else
  63. /* 32k bytes */
  64. memctl->memc_or3 = (0xffff8000 | CONFIG_SYS_OR_TIMING_DOC);
  65. memctl->memc_br3 = CONFIG_SYS_DOC_BASE | 0x401;
  66. #endif
  67. #endif
  68. #if defined(CONFIG_BOOT_8B)
  69. size_b0 = 0x80000; /* 512 K */
  70. flash_info[0].flash_id = FLASH_MAN_AMD | FLASH_AM040;
  71. flash_info[0].sector_count = 8;
  72. flash_info[0].size = 0x00080000;
  73. /* set up sector start address table */
  74. for (i = 0; i < flash_info[0].sector_count; i++)
  75. flash_info[0].start[i] = 0x40000000 + (i * 0x10000);
  76. /* protect all sectors */
  77. for (i = 0; i < flash_info[0].sector_count; i++)
  78. flash_info[0].protect[i] = 0x1;
  79. #elif defined(CONFIG_BOOT_16B)
  80. size_b0 = 0x400000; /* 4MB , assume AMD29LV320B */
  81. flash_info[0].flash_id = FLASH_MAN_AMD | FLASH_AM320B;
  82. flash_info[0].sector_count = 67;
  83. flash_info[0].size = 0x00400000;
  84. /* set up sector start address table */
  85. flash_info[0].start[0] = 0x40000000;
  86. flash_info[0].start[1] = 0x40000000 + 0x4000;
  87. flash_info[0].start[2] = 0x40000000 + 0x6000;
  88. flash_info[0].start[3] = 0x40000000 + 0x8000;
  89. for (i = 4; i < flash_info[0].sector_count; i++) {
  90. flash_info[0].start[i] =
  91. 0x40000000 + 0x10000 + ((i - 4) * 0x10000);
  92. }
  93. /* protect all sectors */
  94. for (i = 0; i < flash_info[0].sector_count; i++)
  95. flash_info[0].protect[i] = 0x1;
  96. #endif
  97. #ifdef CONFIG_BOOT_32B
  98. /* Static FLASH Bank configuration here - FIXME XXX */
  99. size_b0 = flash_get_size((vu_long *) FLASH_BASE0_PRELIM,
  100. &flash_info[0]);
  101. if (flash_info[0].flash_id == FLASH_UNKNOWN) {
  102. printf("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
  103. size_b0, size_b0 << 20);
  104. }
  105. size_b1 = flash_get_size((vu_long *) FLASH_BASE1_PRELIM,
  106. &flash_info[1]);
  107. if (size_b1 > size_b0) {
  108. printf("## ERROR: "
  109. "Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n",
  110. size_b1, size_b1 << 20, size_b0, size_b0 << 20);
  111. flash_info[0].flash_id = FLASH_UNKNOWN;
  112. flash_info[1].flash_id = FLASH_UNKNOWN;
  113. flash_info[0].sector_count = -1;
  114. flash_info[1].sector_count = -1;
  115. flash_info[0].size = 0;
  116. flash_info[1].size = 0;
  117. return 0;
  118. }
  119. /* Remap FLASH according to real size */
  120. memctl->memc_or0 = CONFIG_SYS_OR_TIMING_FLASH |
  121. (-size_b0 & OR_AM_MSK);
  122. memctl->memc_br0 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) |
  123. BR_MS_GPCM | BR_V;
  124. /* Re-do sizing to get full correct info */
  125. size_b0 = flash_get_size((vu_long *) CONFIG_SYS_FLASH_BASE,
  126. &flash_info[0]);
  127. flash_get_offsets(CONFIG_SYS_FLASH_BASE, &flash_info[0]);
  128. #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
  129. /* monitor protection ON by default */
  130. flash_protect(FLAG_PROTECT_SET,
  131. CONFIG_SYS_MONITOR_BASE,
  132. CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
  133. &flash_info[0]);
  134. #endif
  135. #ifdef CONFIG_ENV_IS_IN_FLASH
  136. /* ENV protection ON by default */
  137. flash_protect(FLAG_PROTECT_SET,
  138. CONFIG_ENV_ADDR,
  139. CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
  140. #endif
  141. if (size_b1) {
  142. memctl->memc_or1 = CONFIG_SYS_OR_TIMING_FLASH |
  143. (-size_b1 & 0xFFFF8000);
  144. memctl->memc_br1 = ((CONFIG_SYS_FLASH_BASE +
  145. size_b0) & BR_BA_MSK) | BR_MS_GPCM | BR_V;
  146. /* Re-do sizing to get full correct info */
  147. size_b1 = flash_get_size((vu_long *)(CONFIG_SYS_FLASH_BASE +
  148. size_b0), &flash_info[1]);
  149. flash_get_offsets(CONFIG_SYS_FLASH_BASE + size_b0,
  150. &flash_info[1]);
  151. #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
  152. /* monitor protection ON by default */
  153. flash_protect(FLAG_PROTECT_SET,
  154. CONFIG_SYS_MONITOR_BASE,
  155. CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
  156. &flash_info[1]);
  157. #endif
  158. #ifdef CONFIG_ENV_IS_IN_FLASH
  159. /* ENV protection ON by default */
  160. flash_protect(FLAG_PROTECT_SET,
  161. CONFIG_ENV_ADDR,
  162. CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
  163. &flash_info[1]);
  164. #endif
  165. } else {
  166. memctl->memc_br1 = 0; /* invalidate bank */
  167. flash_info[1].flash_id = FLASH_UNKNOWN;
  168. flash_info[1].sector_count = -1;
  169. }
  170. flash_info[0].size = size_b0;
  171. flash_info[1].size = size_b1;
  172. #endif /* CONFIG_BOOT_32B */
  173. return size_b0 + size_b1;
  174. }
  175. void flash_print_info(flash_info_t *info)
  176. {
  177. int i;
  178. if (info->flash_id == FLASH_UNKNOWN) {
  179. printf("missing or unknown FLASH type\n");
  180. return;
  181. }
  182. switch (info->flash_id & FLASH_VENDMASK) {
  183. case FLASH_MAN_AMD:
  184. printf("AMD ");
  185. break;
  186. case FLASH_MAN_FUJ:
  187. printf("FUJITSU ");
  188. break;
  189. default:
  190. printf("Unknown Vendor ");
  191. break;
  192. }
  193. switch (info->flash_id & FLASH_TYPEMASK) {
  194. case FLASH_AM400B:
  195. printf("AM29LV400B (4 Mbit, bottom boot sect)\n");
  196. break;
  197. case FLASH_AM400T:
  198. printf("AM29LV400T (4 Mbit, top boot sector)\n");
  199. break;
  200. case FLASH_AM800B:
  201. printf("AM29LV800B (8 Mbit, bottom boot sect)\n");
  202. break;
  203. case FLASH_AM800T:
  204. printf("AM29LV800T (8 Mbit, top boot sector)\n");
  205. break;
  206. case FLASH_AM160B:
  207. printf("AM29LV160B (16 Mbit, bottom boot sect)\n");
  208. break;
  209. case FLASH_AM160T:
  210. printf("AM29LV160T (16 Mbit, top boot sector)\n");
  211. break;
  212. case FLASH_AM320B:
  213. printf("AM29LV320B (32 Mbit, bottom boot sect)\n");
  214. break;
  215. case FLASH_AM320T:
  216. printf("AM29LV320T (32 Mbit, top boot sector)\n");
  217. break;
  218. default:
  219. printf("Unknown Chip Type\n");
  220. break;
  221. }
  222. printf(" Size: %ld MB in %d Sectors\n",
  223. info->size >> 20, info->sector_count);
  224. printf(" Sector Start Addresses:");
  225. for (i = 0; i < info->sector_count; ++i) {
  226. if ((i % 5) == 0)
  227. printf("\n ");
  228. printf(" %08lX%s",
  229. info->start[i], info->protect[i] ? " (RO)" : " ");
  230. }
  231. printf("\n");
  232. return;
  233. }
  234. /*
  235. * The following code cannot be run from FLASH!
  236. */
  237. int flash_erase(flash_info_t *info, int s_first, int s_last)
  238. {
  239. vu_long *addr = (vu_long *) (info->start[0]);
  240. int flag, prot, sect, l_sect, in_mid, in_did;
  241. ulong start, now, last;
  242. if ((s_first < 0) || (s_first > s_last)) {
  243. if (info->flash_id == FLASH_UNKNOWN)
  244. printf("- missing\n");
  245. else
  246. printf("- no sectors to erase\n");
  247. return 1;
  248. }
  249. if ((info->flash_id == FLASH_UNKNOWN) ||
  250. (info->flash_id > FLASH_AMD_COMP)) {
  251. printf("Can't erase unknown flash type %08lx - aborted\n",
  252. info->flash_id);
  253. return 1;
  254. }
  255. prot = 0;
  256. for (sect = s_first; sect <= s_last; ++sect) {
  257. if (info->protect[sect])
  258. prot++;
  259. }
  260. if (prot) {
  261. printf("- Warning: %d protected sectors will not be erased!\n",
  262. prot);
  263. } else {
  264. printf("\n");
  265. }
  266. l_sect = -1;
  267. /* Disable interrupts which might cause a timeout here */
  268. flag = disable_interrupts();
  269. #if defined(CONFIG_BOOT_8B)
  270. my_out_8((unsigned char *)((ulong)addr + 0x555), 0xaa);
  271. my_out_8((unsigned char *)((ulong)addr + 0x2aa), 0x55);
  272. my_out_8((unsigned char *)((ulong)addr + 0x555), 0x90);
  273. in_mid = my_in_8((unsigned char *)addr);
  274. in_did = my_in_8((unsigned char *)((ulong)addr + 1));
  275. printf(" man ID=0x%x, dev ID=0x%x.\n", in_mid, in_did);
  276. my_out_8((unsigned char *)addr, 0xf0);
  277. udelay(1);
  278. my_out_8((unsigned char *)((ulong)addr + 0x555), 0xaa);
  279. my_out_8((unsigned char *)((ulong)addr + 0x2aa), 0x55);
  280. my_out_8((unsigned char *)((ulong)addr + 0x555), 0x80);
  281. my_out_8((unsigned char *)((ulong)addr + 0x555), 0xaa);
  282. my_out_8((unsigned char *)((ulong)addr + 0x2aa), 0x55);
  283. /* Start erase on unprotected sectors */
  284. for (sect = s_first; sect <= s_last; sect++) {
  285. if (info->protect[sect] == 0) { /* not protected */
  286. addr = (vu_long *) (info->start[sect]);
  287. /*addr[0] = 0x00300030; */
  288. my_out_8((unsigned char *)((ulong)addr), 0x30);
  289. l_sect = sect;
  290. }
  291. }
  292. #elif defined(CONFIG_BOOT_16B)
  293. my_out_be16((unsigned short *)((ulong)addr + (0xaaa)), 0xaa);
  294. my_out_be16((unsigned short *)((ulong)addr + (0x554)), 0x55);
  295. my_out_be16((unsigned short *)((ulong)addr + (0xaaa)), 0x90);
  296. in_mid = my_in_be16((unsigned short *)addr);
  297. in_did = my_in_be16((unsigned short *)((ulong)addr + 2));
  298. printf(" man ID=0x%x, dev ID=0x%x.\n", in_mid, in_did);
  299. my_out_be16((unsigned short *)addr, 0xf0);
  300. udelay(1);
  301. my_out_be16((unsigned short *)((ulong)addr + 0xaaa), 0xaa);
  302. my_out_be16((unsigned short *)((ulong)addr + 0x554), 0x55);
  303. my_out_be16((unsigned short *)((ulong)addr + 0xaaa), 0x80);
  304. my_out_be16((unsigned short *)((ulong)addr + 0xaaa), 0xaa);
  305. my_out_be16((unsigned short *)((ulong)addr + 0x554), 0x55);
  306. /* Start erase on unprotected sectors */
  307. for (sect = s_first; sect <= s_last; sect++) {
  308. if (info->protect[sect] == 0) { /* not protected */
  309. addr = (vu_long *) (info->start[sect]);
  310. my_out_be16((unsigned short *)((ulong)addr), 0x30);
  311. l_sect = sect;
  312. }
  313. }
  314. #elif defined(CONFIG_BOOT_32B)
  315. my_out_be32((unsigned *)((ulong)addr + 0x1554), 0xaa);
  316. my_out_be32((unsigned *)((ulong)addr + 0xaa8), 0x55);
  317. my_out_be32((unsigned *)((ulong)addr + 0x1554), 0x90);
  318. in_mid = my_in_be32((unsigned *)addr);
  319. in_did = my_in_be32((unsigned *)((ulong)addr + 4));
  320. printf(" man ID=0x%x, dev ID=0x%x.\n", in_mid, in_did);
  321. my_out_be32((unsigned *) addr, 0xf0);
  322. udelay(1);
  323. my_out_be32((unsigned *)((ulong)addr + 0x1554), 0xaa);
  324. my_out_be32((unsigned *)((ulong)addr + 0xaa8), 0x55);
  325. my_out_be32((unsigned *)((ulong)addr + 0x1554), 0x80);
  326. my_out_be32((unsigned *)((ulong)addr + 0x1554), 0xaa);
  327. my_out_be32((unsigned *)((ulong)addr + 0xaa8), 0x55);
  328. /* Start erase on unprotected sectors */
  329. for (sect = s_first; sect <= s_last; sect++) {
  330. if (info->protect[sect] == 0) { /* not protected */
  331. addr = (vu_long *) (info->start[sect]);
  332. my_out_be32((unsigned *)((ulong)addr), 0x00300030);
  333. l_sect = sect;
  334. }
  335. }
  336. #else
  337. #error CONFIG_BOOT_(size)B missing.
  338. #endif
  339. /* re-enable interrupts if necessary */
  340. if (flag)
  341. enable_interrupts();
  342. /* wait at least 80us - let's wait 1 ms */
  343. udelay(1000);
  344. /*
  345. * We wait for the last triggered sector
  346. */
  347. if (l_sect < 0)
  348. goto DONE;
  349. start = get_timer(0);
  350. last = start;
  351. addr = (vu_long *) (info->start[l_sect]);
  352. #if defined(CONFIG_BOOT_8B)
  353. while ((my_in_8((unsigned char *) addr) & 0x80) != 0x80)
  354. #elif defined(CONFIG_BOOT_16B)
  355. while ((my_in_be16((unsigned short *) addr) & 0x0080) != 0x0080)
  356. #elif defined(CONFIG_BOOT_32B)
  357. while ((my_in_be32((unsigned *) addr) & 0x00800080) != 0x00800080)
  358. #else
  359. #error CONFIG_BOOT_(size)B missing.
  360. #endif
  361. {
  362. now = get_timer(start);
  363. if (now > CONFIG_SYS_FLASH_ERASE_TOUT) {
  364. printf("Timeout\n");
  365. return 1;
  366. }
  367. /* show that we're waiting */
  368. if ((now - last) > 1000) { /* every second */
  369. putc('.');
  370. last = now;
  371. }
  372. }
  373. DONE:
  374. /* reset to read mode */
  375. addr = (volatile unsigned long *) info->start[0];
  376. #if defined(CONFIG_BOOT_8B)
  377. my_out_8((unsigned char *) addr, 0xf0);
  378. #elif defined(CONFIG_BOOT_16B)
  379. my_out_be16((unsigned short *) addr, 0x00f0);
  380. #elif defined(CONFIG_BOOT_32B)
  381. my_out_be32((unsigned *) addr, 0x00F000F0); /* reset bank */
  382. #else
  383. #error CONFIG_BOOT_(size)B missing.
  384. #endif
  385. printf(" done\n");
  386. return 0;
  387. }
  388. /*
  389. * Copy memory to flash, returns:
  390. * 0 - OK
  391. * 1 - write timeout
  392. * 2 - Flash not erased
  393. */
  394. int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
  395. {
  396. ulong cp, wp, data;
  397. int i, l, rc;
  398. wp = (addr & ~3); /* get lower word aligned address */
  399. /*
  400. * handle unaligned start bytes
  401. */
  402. l = addr - wp;
  403. if (l != 0) {
  404. data = 0;
  405. for (i = 0, cp = wp; i < l; ++i, ++cp)
  406. data = (data << 8) | (*(uchar *) cp);
  407. for (; i < 4 && cnt > 0; ++i) {
  408. data = (data << 8) | *src++;
  409. --cnt;
  410. ++cp;
  411. }
  412. for (; cnt == 0 && i < 4; ++i, ++cp)
  413. data = (data << 8) | (*(uchar *) cp);
  414. rc = write_word(info, wp, data);
  415. if (rc != 0)
  416. return rc;
  417. wp += 4;
  418. }
  419. /*
  420. * handle word aligned part
  421. */
  422. while (cnt >= 4) {
  423. data = 0;
  424. for (i = 0; i < 4; ++i)
  425. data = (data << 8) | *src++;
  426. rc = write_word(info, wp, data);
  427. if (rc != 0)
  428. return rc;
  429. wp += 4;
  430. cnt -= 4;
  431. }
  432. if (cnt == 0)
  433. return 0;
  434. /*
  435. * handle unaligned tail bytes
  436. */
  437. data = 0;
  438. for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
  439. data = (data << 8) | *src++;
  440. --cnt;
  441. }
  442. for (; i < 4; ++i, ++cp)
  443. data = (data << 8) | (*(uchar *) cp);
  444. return write_word(info, wp, data);
  445. }
  446. /*
  447. * Write a word to Flash, returns:
  448. * 0 - OK
  449. * 1 - write timeout
  450. * 2 - Flash not erased
  451. */
  452. static int write_word(flash_info_t *info, ulong dest, ulong data)
  453. {
  454. ulong addr = (ulong) (info->start[0]);
  455. ulong start;
  456. int flag;
  457. ulong i;
  458. int data_short[2];
  459. /* Check if Flash is (sufficiently) erased */
  460. if (((ulong)*(ulong *)dest & data) != data)
  461. return 2;
  462. /* Disable interrupts which might cause a timeout here */
  463. flag = disable_interrupts();
  464. #if defined(CONFIG_BOOT_8B)
  465. #ifdef DEBUG
  466. {
  467. int in_mid, in_did;
  468. my_out_8((unsigned char *) (addr + 0x555), 0xaa);
  469. my_out_8((unsigned char *) (addr + 0x2aa), 0x55);
  470. my_out_8((unsigned char *) (addr + 0x555), 0x90);
  471. in_mid = my_in_8((unsigned char *) addr);
  472. in_did = my_in_8((unsigned char *) (addr + 1));
  473. printf(" man ID=0x%x, dev ID=0x%x.\n", in_mid, in_did);
  474. my_out_8((unsigned char *) addr, 0xf0);
  475. udelay(1);
  476. }
  477. #endif
  478. {
  479. int data_ch[4];
  480. data_ch[0] = (int) ((data >> 24) & 0xff);
  481. data_ch[1] = (int) ((data >> 16) & 0xff);
  482. data_ch[2] = (int) ((data >> 8) & 0xff);
  483. data_ch[3] = (int) (data & 0xff);
  484. for (i = 0; i < 4; i++) {
  485. my_out_8((unsigned char *) (addr + 0x555), 0xaa);
  486. my_out_8((unsigned char *) (addr + 0x2aa), 0x55);
  487. my_out_8((unsigned char *) (addr + 0x555), 0xa0);
  488. my_out_8((unsigned char *) (dest + i), data_ch[i]);
  489. /* re-enable interrupts if necessary */
  490. if (flag)
  491. enable_interrupts();
  492. start = get_timer(0);
  493. while ((my_in_8((unsigned char *)(dest + i))) !=
  494. (data_ch[i])) {
  495. if (get_timer(start) >
  496. CONFIG_SYS_FLASH_WRITE_TOUT) {
  497. return 1;
  498. }
  499. }
  500. } /* for */
  501. }
  502. #elif defined(CONFIG_BOOT_16B)
  503. data_short[0] = (int) (data >> 16) & 0xffff;
  504. data_short[1] = (int) data & 0xffff;
  505. for (i = 0; i < 2; i++) {
  506. my_out_be16((unsigned short *)((ulong)addr + 0xaaa), 0xaa);
  507. my_out_be16((unsigned short *)((ulong)addr + 0x554), 0x55);
  508. my_out_be16((unsigned short *)((ulong)addr + 0xaaa), 0xa0);
  509. my_out_be16((unsigned short *)(dest + (i * 2)),
  510. data_short[i]);
  511. /* re-enable interrupts if necessary */
  512. if (flag)
  513. enable_interrupts();
  514. start = get_timer(0);
  515. while ((my_in_be16((unsigned short *)(dest + (i * 2)))) !=
  516. (data_short[i])) {
  517. if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT)
  518. return 1;
  519. }
  520. }
  521. #elif defined(CONFIG_BOOT_32B)
  522. addr[0x0555] = 0x00AA00AA;
  523. addr[0x02AA] = 0x00550055;
  524. addr[0x0555] = 0x00A000A0;
  525. *((vu_long *)dest) = data;
  526. /* re-enable interrupts if necessary */
  527. if (flag)
  528. enable_interrupts();
  529. /* data polling for D7 */
  530. start = get_timer(0);
  531. while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
  532. if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT)
  533. return 1;
  534. }
  535. #endif
  536. return 0;
  537. }
  538. #ifdef CONFIG_BOOT_8B
  539. static int my_in_8(unsigned char *addr)
  540. {
  541. int ret;
  542. __asm__ __volatile__("lbz%U1%X1 %0,%1; eieio":"=r"(ret):"m"(*addr));
  543. return ret;
  544. }
  545. static void my_out_8(unsigned char *addr, int val)
  546. {
  547. __asm__ __volatile__("stb%U0%X0 %1,%0; eieio":"=m"(*addr):"r"(val));
  548. }
  549. #endif
  550. #ifdef CONFIG_BOOT_16B
  551. static int my_in_be16(unsigned short *addr)
  552. {
  553. int ret;
  554. __asm__ __volatile__("lhz%U1%X1 %0,%1; eieio":"=r"(ret):"m"(*addr));
  555. return ret;
  556. }
  557. static void my_out_be16(unsigned short *addr, int val)
  558. {
  559. __asm__ __volatile__("sth%U0%X0 %1,%0; eieio":"=m"(*addr):"r"(val));
  560. }
  561. #endif
  562. #ifdef CONFIG_BOOT_32B
  563. static unsigned my_in_be32(unsigned *addr)
  564. {
  565. unsigned ret;
  566. __asm__ __volatile__("lwz%U1%X1 %0,%1; eieio":"=r"(ret):"m"(*addr));
  567. return ret;
  568. }
  569. static void my_out_be32(unsigned *addr, int val)
  570. {
  571. __asm__ __volatile__("stw%U0%X0 %1,%0; eieio":"=m"(*addr):"r"(val));
  572. }
  573. #endif