flash.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * (C) Copyright 2006 Embedded Artists AB <www.embeddedartists.com>
  3. *
  4. * Modified to remove all but the IAP-command related code by
  5. * Gary Jennejohn <garyj@denx.de>
  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 <asm/arch/hardware.h>
  24. /* IAP commands use 32 bytes at the top of CPU internal sram, we
  25. use 512 bytes below that */
  26. #define COPY_BUFFER_LOCATION 0x40003de0
  27. #define IAP_LOCATION 0x7ffffff1
  28. #define IAP_CMD_PREPARE 50
  29. #define IAP_CMD_COPY 51
  30. #define IAP_CMD_ERASE 52
  31. #define IAP_CMD_CHECK 53
  32. #define IAP_CMD_ID 54
  33. #define IAP_CMD_VERSION 55
  34. #define IAP_CMD_COMPARE 56
  35. #define IAP_RET_CMD_SUCCESS 0
  36. static unsigned long command[5];
  37. static unsigned long result[2];
  38. extern void iap_entry(unsigned long * command, unsigned long * result);
  39. /*-----------------------------------------------------------------------
  40. *
  41. */
  42. static int get_flash_sector(flash_info_t * info, ulong flash_addr)
  43. {
  44. int i;
  45. for(i = 1; i < (info->sector_count); i++) {
  46. if (flash_addr < (info->start[i]))
  47. break;
  48. }
  49. return (i-1);
  50. }
  51. /*-----------------------------------------------------------------------
  52. * This function assumes that flash_addr is aligned on 512 bytes boundary
  53. * in flash. This function also assumes that prepare have been called
  54. * for the sector in question.
  55. */
  56. int lpc2292_copy_buffer_to_flash(flash_info_t * info, ulong flash_addr)
  57. {
  58. int first_sector;
  59. int last_sector;
  60. first_sector = get_flash_sector(info, flash_addr);
  61. last_sector = get_flash_sector(info, flash_addr + 512 - 1);
  62. /* prepare sectors for write */
  63. command[0] = IAP_CMD_PREPARE;
  64. command[1] = first_sector;
  65. command[2] = last_sector;
  66. iap_entry(command, result);
  67. if (result[0] != IAP_RET_CMD_SUCCESS) {
  68. printf("IAP prepare failed\n");
  69. return ERR_PROG_ERROR;
  70. }
  71. command[0] = IAP_CMD_COPY;
  72. command[1] = flash_addr;
  73. command[2] = COPY_BUFFER_LOCATION;
  74. command[3] = 512;
  75. command[4] = CFG_SYS_CLK_FREQ >> 10;
  76. iap_entry(command, result);
  77. if (result[0] != IAP_RET_CMD_SUCCESS) {
  78. printf("IAP copy failed\n");
  79. return 1;
  80. }
  81. return 0;
  82. }
  83. /*-----------------------------------------------------------------------
  84. */
  85. int lpc2292_flash_erase (flash_info_t * info, int s_first, int s_last)
  86. {
  87. int flag;
  88. int prot;
  89. int sect;
  90. prot = 0;
  91. for (sect = s_first; sect <= s_last; ++sect) {
  92. if (info->protect[sect]) {
  93. prot++;
  94. }
  95. }
  96. if (prot)
  97. return ERR_PROTECTED;
  98. flag = disable_interrupts();
  99. printf ("Erasing %d sectors starting at sector %2d.\n"
  100. "This make take some time ... ",
  101. s_last - s_first + 1, s_first);
  102. command[0] = IAP_CMD_PREPARE;
  103. command[1] = s_first;
  104. command[2] = s_last;
  105. iap_entry(command, result);
  106. if (result[0] != IAP_RET_CMD_SUCCESS) {
  107. printf("IAP prepare failed\n");
  108. return ERR_PROTECTED;
  109. }
  110. command[0] = IAP_CMD_ERASE;
  111. command[1] = s_first;
  112. command[2] = s_last;
  113. command[3] = CFG_SYS_CLK_FREQ >> 10;
  114. iap_entry(command, result);
  115. if (result[0] != IAP_RET_CMD_SUCCESS) {
  116. printf("IAP erase failed\n");
  117. return ERR_PROTECTED;
  118. }
  119. if (flag)
  120. enable_interrupts();
  121. return ERR_OK;
  122. }
  123. int lpc2292_write_buff (flash_info_t * info, uchar * src, ulong addr,
  124. ulong cnt)
  125. {
  126. int first_copy_size;
  127. int last_copy_size;
  128. int first_block;
  129. int last_block;
  130. int nbr_mid_blocks;
  131. uchar memmap_value;
  132. ulong i;
  133. uchar* src_org;
  134. uchar* dst_org;
  135. int ret = ERR_OK;
  136. src_org = src;
  137. dst_org = (uchar*)addr;
  138. first_block = addr / 512;
  139. last_block = (addr + cnt) / 512;
  140. nbr_mid_blocks = last_block - first_block - 1;
  141. first_copy_size = 512 - (addr % 512);
  142. last_copy_size = (addr + cnt) % 512;
  143. debug("\ncopy first block: (1) %lX -> %lX 0x200 bytes, "
  144. "(2) %lX -> %lX 0x%X bytes, (3) %lX -> %lX 0x200 bytes\n",
  145. (ulong)(first_block * 512),
  146. (ulong)COPY_BUFFER_LOCATION,
  147. (ulong)src,
  148. (ulong)(COPY_BUFFER_LOCATION + 512 - first_copy_size),
  149. first_copy_size,
  150. (ulong)COPY_BUFFER_LOCATION,
  151. (ulong)(first_block * 512));
  152. /* copy first block */
  153. memcpy((void*)COPY_BUFFER_LOCATION,
  154. (void*)(first_block * 512), 512);
  155. memcpy((void*)(COPY_BUFFER_LOCATION + 512 - first_copy_size),
  156. src, first_copy_size);
  157. lpc2292_copy_buffer_to_flash(info, first_block * 512);
  158. src += first_copy_size;
  159. addr += first_copy_size;
  160. /* copy middle blocks */
  161. for (i = 0; i < nbr_mid_blocks; i++) {
  162. debug("copy middle block: %lX -> %lX 512 bytes, "
  163. "%lX -> %lX 512 bytes\n",
  164. (ulong)src,
  165. (ulong)COPY_BUFFER_LOCATION,
  166. (ulong)COPY_BUFFER_LOCATION,
  167. (ulong)addr);
  168. memcpy((void*)COPY_BUFFER_LOCATION, src, 512);
  169. lpc2292_copy_buffer_to_flash(info, addr);
  170. src += 512;
  171. addr += 512;
  172. }
  173. if (last_copy_size > 0) {
  174. debug("copy last block: (1) %lX -> %lX 0x200 bytes, "
  175. "(2) %lX -> %lX 0x%X bytes, (3) %lX -> %lX x200 bytes\n",
  176. (ulong)(last_block * 512),
  177. (ulong)COPY_BUFFER_LOCATION,
  178. (ulong)src,
  179. (ulong)(COPY_BUFFER_LOCATION),
  180. last_copy_size,
  181. (ulong)COPY_BUFFER_LOCATION,
  182. (ulong)addr);
  183. /* copy last block */
  184. memcpy((void*)COPY_BUFFER_LOCATION,
  185. (void*)(last_block * 512), 512);
  186. memcpy((void*)COPY_BUFFER_LOCATION,
  187. src, last_copy_size);
  188. lpc2292_copy_buffer_to_flash(info, addr);
  189. }
  190. /* verify write */
  191. memmap_value = GET8(MEMMAP);
  192. disable_interrupts();
  193. PUT8(MEMMAP, 01); /* we must make sure that initial 64
  194. bytes are taken from flash when we
  195. do the compare */
  196. for (i = 0; i < cnt; i++) {
  197. if (*dst_org != *src_org){
  198. printf("Write failed. Byte %lX differs\n", i);
  199. ret = ERR_PROG_ERROR;
  200. break;
  201. }
  202. dst_org++;
  203. src_org++;
  204. }
  205. PUT8(MEMMAP, memmap_value);
  206. enable_interrupts();
  207. return ret;
  208. }