flash.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. /*
  2. * (C) Copyright 2006 Embedded Artists AB <www.embeddedartists.com>
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of
  7. * the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  17. * MA 02111-1307 USA
  18. */
  19. #include <common.h>
  20. #include <asm/arch/hardware.h>
  21. /* IAP commands use 32 bytes at the top of CPU internal sram, we
  22. use 512 bytes below that */
  23. #define COPY_BUFFER_LOCATION 0x40003de0
  24. #define IAP_LOCATION 0x7ffffff1
  25. #define IAP_CMD_PREPARE 50
  26. #define IAP_CMD_COPY 51
  27. #define IAP_CMD_ERASE 52
  28. #define IAP_CMD_CHECK 53
  29. #define IAP_CMD_ID 54
  30. #define IAP_CMD_VERSION 55
  31. #define IAP_CMD_COMPARE 56
  32. #define IAP_RET_CMD_SUCCESS 0
  33. #define SST_BASEADDR 0x80000000
  34. #define SST_ADDR1 ((volatile ushort*)(SST_BASEADDR + (0x5555 << 1)))
  35. #define SST_ADDR2 ((volatile ushort*)(SST_BASEADDR + (0x2AAA << 1)))
  36. static unsigned long command[5];
  37. static unsigned long result[2];
  38. flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
  39. extern void iap_entry(unsigned long * command, unsigned long * result);
  40. /*-----------------------------------------------------------------------
  41. *
  42. */
  43. int get_flash_sector(flash_info_t * info, ulong flash_addr)
  44. {
  45. int i;
  46. for(i=1; i < (info->sector_count); i++) {
  47. if (flash_addr < (info->start[i]))
  48. break;
  49. }
  50. return (i-1);
  51. }
  52. /*-----------------------------------------------------------------------
  53. * This function assumes that flash_addr is aligned on 512 bytes boundary
  54. * in flash. This function also assumes that prepare have been called
  55. * for the sector in question.
  56. */
  57. int copy_buffer_to_flash(flash_info_t * info, ulong flash_addr)
  58. {
  59. int first_sector;
  60. int last_sector;
  61. first_sector = get_flash_sector(info, flash_addr);
  62. last_sector = get_flash_sector(info, flash_addr + 512 - 1);
  63. /* prepare sectors for write */
  64. command[0] = IAP_CMD_PREPARE;
  65. command[1] = first_sector;
  66. command[2] = last_sector;
  67. iap_entry(command, result);
  68. if (result[0] != IAP_RET_CMD_SUCCESS) {
  69. printf("IAP prepare failed\n");
  70. return ERR_PROG_ERROR;
  71. }
  72. command[0] = IAP_CMD_COPY;
  73. command[1] = flash_addr;
  74. command[2] = COPY_BUFFER_LOCATION;
  75. command[3] = 512;
  76. command[4] = CFG_SYS_CLK_FREQ >> 10;
  77. iap_entry(command, result);
  78. if (result[0] != IAP_RET_CMD_SUCCESS) {
  79. printf("IAP copy failed\n");
  80. return 1;
  81. }
  82. return 0;
  83. }
  84. /*-----------------------------------------------------------------------
  85. *
  86. */
  87. void write_word_sst(ulong addr, ushort data)
  88. {
  89. ushort tmp;
  90. *SST_ADDR1 = 0x00AA;
  91. *SST_ADDR2 = 0x0055;
  92. *SST_ADDR1 = 0x00A0;
  93. *((volatile ushort*)addr) = data;
  94. /* do data polling */
  95. do {
  96. tmp = *((volatile ushort*)addr);
  97. } while (tmp != data);
  98. }
  99. /*-----------------------------------------------------------------------
  100. */
  101. ulong flash_init (void)
  102. {
  103. int j, k;
  104. ulong size = 0;
  105. ulong flashbase = 0;
  106. flash_info[0].flash_id = (PHILIPS_LPC2292 & FLASH_VENDMASK);
  107. flash_info[0].size = 0x003E000; /* 256 - 8 KB */
  108. flash_info[0].sector_count = 17;
  109. memset (flash_info[0].protect, 0, 17);
  110. flashbase = 0x00000000;
  111. for (j = 0, k = 0; j < 8; j++, k++) {
  112. flash_info[0].start[k] = flashbase;
  113. flashbase += 0x00002000;
  114. }
  115. for (j = 0; j < 2; j++, k++) {
  116. flash_info[0].start[k] = flashbase;
  117. flashbase += 0x00010000;
  118. }
  119. for (j = 0; j < 7; j++, k++) {
  120. flash_info[0].start[k] = flashbase;
  121. flashbase += 0x00002000;
  122. }
  123. size += flash_info[0].size;
  124. flash_info[1].flash_id = (SST_MANUFACT & FLASH_VENDMASK);
  125. flash_info[1].size = 0x00200000; /* 2 MB */
  126. flash_info[1].sector_count = 512;
  127. memset (flash_info[1].protect, 0, 512);
  128. flashbase = SST_BASEADDR;
  129. for (j=0; j<512; j++) {
  130. flash_info[1].start[j] = flashbase;
  131. flashbase += 0x1000; /* 4 KB sectors */
  132. }
  133. size += flash_info[1].size;
  134. /* Protect monitor and environment sectors */
  135. flash_protect (FLAG_PROTECT_SET,
  136. 0x0,
  137. 0x0 + monitor_flash_len - 1,
  138. &flash_info[0]);
  139. flash_protect (FLAG_PROTECT_SET,
  140. CFG_ENV_ADDR,
  141. CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
  142. &flash_info[0]);
  143. return size;
  144. }
  145. /*-----------------------------------------------------------------------
  146. */
  147. void flash_print_info (flash_info_t * info)
  148. {
  149. int i;
  150. int erased = 0;
  151. unsigned long j;
  152. unsigned long count;
  153. unsigned char *p;
  154. switch (info->flash_id & FLASH_VENDMASK) {
  155. case (SST_MANUFACT & FLASH_VENDMASK):
  156. printf("SST: ");
  157. break;
  158. case (PHILIPS_LPC2292 & FLASH_VENDMASK):
  159. printf("Philips: ");
  160. break;
  161. default:
  162. printf ("Unknown Vendor ");
  163. break;
  164. }
  165. printf (" Size: %ld KB in %d Sectors\n",
  166. info->size >> 10, info->sector_count);
  167. printf (" Sector Start Addresses:");
  168. for (i = 0; i < info->sector_count; i++) {
  169. if ((i % 5) == 0) {
  170. printf ("\n ");
  171. }
  172. if (i < (info->sector_count - 1)) {
  173. count = info->start[i+1] - info->start[i];
  174. }
  175. else {
  176. count = info->start[0] + info->size - info->start[i];
  177. }
  178. p = (unsigned char*)(info->start[i]);
  179. erased = 1;
  180. for (j = 0; j < count; j++) {
  181. if (*p != 0xFF) {
  182. erased = 0;
  183. break;
  184. }
  185. p++;
  186. }
  187. printf (" %08lX%s%s", info->start[i], info->protect[i] ? " RO" : " ",
  188. erased ? " E" : " ");
  189. }
  190. printf ("\n");
  191. }
  192. /*-----------------------------------------------------------------------
  193. */
  194. int flash_erase_philips (flash_info_t * info, int s_first, int s_last)
  195. {
  196. int flag;
  197. int prot;
  198. int sect;
  199. prot = 0;
  200. for (sect = s_first; sect <= s_last; ++sect) {
  201. if (info->protect[sect]) {
  202. prot++;
  203. }
  204. }
  205. if (prot)
  206. return ERR_PROTECTED;
  207. flag = disable_interrupts();
  208. printf ("Erasing %d sectors starting at sector %2d.\n"
  209. "This make take some time ... ",
  210. s_last - s_first + 1, s_first);
  211. command[0] = IAP_CMD_PREPARE;
  212. command[1] = s_first;
  213. command[2] = s_last;
  214. iap_entry(command, result);
  215. if (result[0] != IAP_RET_CMD_SUCCESS) {
  216. printf("IAP prepare failed\n");
  217. return ERR_PROTECTED;
  218. }
  219. command[0] = IAP_CMD_ERASE;
  220. command[1] = s_first;
  221. command[2] = s_last;
  222. command[3] = CFG_SYS_CLK_FREQ >> 10;
  223. iap_entry(command, result);
  224. if (result[0] != IAP_RET_CMD_SUCCESS) {
  225. printf("IAP erase failed\n");
  226. return ERR_PROTECTED;
  227. }
  228. if (flag)
  229. enable_interrupts();
  230. return ERR_OK;
  231. }
  232. int flash_erase_sst (flash_info_t * info, int s_first, int s_last)
  233. {
  234. int i;
  235. for (i = s_first; i <= s_last; i++) {
  236. *SST_ADDR1 = 0x00AA;
  237. *SST_ADDR2 = 0x0055;
  238. *SST_ADDR1 = 0x0080;
  239. *SST_ADDR1 = 0x00AA;
  240. *SST_ADDR2 = 0x0055;
  241. *((volatile ushort*)(info->start[i])) = 0x0030;
  242. /* wait for erase to finish */
  243. udelay(25000);
  244. }
  245. return ERR_OK;
  246. }
  247. int flash_erase (flash_info_t * info, int s_first, int s_last)
  248. {
  249. switch (info->flash_id & FLASH_VENDMASK) {
  250. case (SST_MANUFACT & FLASH_VENDMASK):
  251. return flash_erase_sst(info, s_first, s_last);
  252. case (PHILIPS_LPC2292 & FLASH_VENDMASK):
  253. return flash_erase_philips(info, s_first, s_last);
  254. default:
  255. return ERR_PROTECTED;
  256. }
  257. return ERR_PROTECTED;
  258. }
  259. /*-----------------------------------------------------------------------
  260. * Copy memory to flash.
  261. *
  262. * cnt is in bytes
  263. */
  264. int write_buff_sst (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
  265. {
  266. ushort tmp;
  267. ulong i;
  268. uchar* src_org;
  269. uchar* dst_org;
  270. ulong cnt_org = cnt;
  271. int ret = ERR_OK;
  272. src_org = src;
  273. dst_org = (uchar*)addr;
  274. if (addr & 1) { /* if odd address */
  275. tmp = *((uchar*)(addr - 1)); /* little endian */
  276. tmp |= (*src << 8);
  277. write_word_sst(addr - 1, tmp);
  278. addr += 1;
  279. cnt -= 1;
  280. src++;
  281. }
  282. while (cnt > 1) {
  283. tmp = ((*(src+1)) << 8) + (*src); /* little endian */
  284. write_word_sst(addr, tmp);
  285. addr += 2;
  286. src += 2;
  287. cnt -= 2;
  288. }
  289. if (cnt > 0) {
  290. tmp = (*((uchar*)(addr + 1))) << 8;
  291. tmp |= *src;
  292. write_word_sst(addr, tmp);
  293. }
  294. for (i = 0; i < cnt_org; i++) {
  295. if (*dst_org != *src_org) {
  296. printf("Write failed. Byte %lX differs\n", i);
  297. ret = ERR_PROG_ERROR;
  298. break;
  299. }
  300. dst_org++;
  301. src_org++;
  302. }
  303. return ret;
  304. }
  305. int write_buff_philips (flash_info_t * info,
  306. uchar * src,
  307. ulong addr,
  308. ulong cnt)
  309. {
  310. int first_copy_size;
  311. int last_copy_size;
  312. int first_block;
  313. int last_block;
  314. int nbr_mid_blocks;
  315. uchar memmap_value;
  316. ulong i;
  317. uchar* src_org;
  318. uchar* dst_org;
  319. int ret = ERR_OK;
  320. src_org = src;
  321. dst_org = (uchar*)addr;
  322. first_block = addr / 512;
  323. last_block = (addr + cnt) / 512;
  324. nbr_mid_blocks = last_block - first_block - 1;
  325. first_copy_size = 512 - (addr % 512);
  326. last_copy_size = (addr + cnt) % 512;
  327. #if 0
  328. printf("\ncopy first block: (1) %lX -> %lX 0x200 bytes, "
  329. "(2) %lX -> %lX 0x%X bytes, (3) %lX -> %lX 0x200 bytes\n",
  330. (ulong)(first_block * 512),
  331. (ulong)COPY_BUFFER_LOCATION,
  332. (ulong)src,
  333. (ulong)(COPY_BUFFER_LOCATION + 512 - first_copy_size),
  334. first_copy_size,
  335. (ulong)COPY_BUFFER_LOCATION,
  336. (ulong)(first_block * 512));
  337. #endif
  338. /* copy first block */
  339. memcpy((void*)COPY_BUFFER_LOCATION,
  340. (void*)(first_block * 512), 512);
  341. memcpy((void*)(COPY_BUFFER_LOCATION + 512 - first_copy_size),
  342. src, first_copy_size);
  343. copy_buffer_to_flash(info, first_block * 512);
  344. src += first_copy_size;
  345. addr += first_copy_size;
  346. /* copy middle blocks */
  347. for (i = 0; i < nbr_mid_blocks; i++) {
  348. #if 0
  349. printf("copy middle block: %lX -> %lX 512 bytes, "
  350. "%lX -> %lX 512 bytes\n",
  351. (ulong)src,
  352. (ulong)COPY_BUFFER_LOCATION,
  353. (ulong)COPY_BUFFER_LOCATION,
  354. (ulong)addr);
  355. #endif
  356. memcpy((void*)COPY_BUFFER_LOCATION, src, 512);
  357. copy_buffer_to_flash(info, addr);
  358. src += 512;
  359. addr += 512;
  360. }
  361. if (last_copy_size > 0) {
  362. #if 0
  363. printf("copy last block: (1) %lX -> %lX 0x200 bytes, "
  364. "(2) %lX -> %lX 0x%X bytes, (3) %lX -> %lX x200 bytes\n",
  365. (ulong)(last_block * 512),
  366. (ulong)COPY_BUFFER_LOCATION,
  367. (ulong)src,
  368. (ulong)(COPY_BUFFER_LOCATION),
  369. last_copy_size,
  370. (ulong)COPY_BUFFER_LOCATION,
  371. (ulong)addr);
  372. #endif
  373. /* copy last block */
  374. memcpy((void*)COPY_BUFFER_LOCATION,
  375. (void*)(last_block * 512), 512);
  376. memcpy((void*)COPY_BUFFER_LOCATION,
  377. src, last_copy_size);
  378. copy_buffer_to_flash(info, addr);
  379. }
  380. /* verify write */
  381. memmap_value = GET8(MEMMAP);
  382. disable_interrupts();
  383. PUT8(MEMMAP, 01); /* we must make sure that initial 64
  384. bytes are taken from flash when we
  385. do the compare */
  386. for (i = 0; i < cnt; i++) {
  387. if (*dst_org != *src_org){
  388. printf("Write failed. Byte %lX differs\n", i);
  389. ret = ERR_PROG_ERROR;
  390. break;
  391. }
  392. dst_org++;
  393. src_org++;
  394. }
  395. PUT8(MEMMAP, memmap_value);
  396. enable_interrupts();
  397. return ret;
  398. }
  399. int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
  400. {
  401. switch (info->flash_id & FLASH_VENDMASK) {
  402. case (SST_MANUFACT & FLASH_VENDMASK):
  403. return write_buff_sst(info, src, addr, cnt);
  404. case (PHILIPS_LPC2292 & FLASH_VENDMASK):
  405. return write_buff_philips(info, src, addr, cnt);
  406. default:
  407. return ERR_PROG_ERROR;
  408. }
  409. return ERR_PROG_ERROR;
  410. }