flash.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. * (C) Copyright 2006 Embedded Artists AB <www.embeddedartists.com>
  3. *
  4. * Modified to use the routines in cpu/arm720t/lpc2292/flash.c 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. #define SST_BASEADDR 0x80000000
  25. #define SST_ADDR1 ((volatile ushort*)(SST_BASEADDR + (0x5555 << 1)))
  26. #define SST_ADDR2 ((volatile ushort*)(SST_BASEADDR + (0x2AAA << 1)))
  27. flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
  28. extern int lpc2292_copy_buffer_to_flash(flash_info_t *, ulong);
  29. extern int lpc2292_flash_erase(flash_info_t *, int, int);
  30. extern int lpc2292_write_buff (flash_info_t *, uchar *, ulong, ulong);
  31. /*-----------------------------------------------------------------------
  32. *
  33. */
  34. void write_word_sst(ulong addr, ushort data)
  35. {
  36. ushort tmp;
  37. *SST_ADDR1 = 0x00AA;
  38. *SST_ADDR2 = 0x0055;
  39. *SST_ADDR1 = 0x00A0;
  40. *((volatile ushort*)addr) = data;
  41. /* do data polling */
  42. do {
  43. tmp = *((volatile ushort*)addr);
  44. } while (tmp != data);
  45. }
  46. /*-----------------------------------------------------------------------
  47. */
  48. ulong flash_init (void)
  49. {
  50. int j, k;
  51. ulong size = 0;
  52. ulong flashbase = 0;
  53. flash_info[0].flash_id = (PHILIPS_LPC2292 & FLASH_VENDMASK);
  54. flash_info[0].size = 0x003E000; /* 256 - 8 KB */
  55. flash_info[0].sector_count = 17;
  56. memset (flash_info[0].protect, 0, 17);
  57. flashbase = 0x00000000;
  58. for (j = 0, k = 0; j < 8; j++, k++) {
  59. flash_info[0].start[k] = flashbase;
  60. flashbase += 0x00002000;
  61. }
  62. for (j = 0; j < 2; j++, k++) {
  63. flash_info[0].start[k] = flashbase;
  64. flashbase += 0x00010000;
  65. }
  66. for (j = 0; j < 7; j++, k++) {
  67. flash_info[0].start[k] = flashbase;
  68. flashbase += 0x00002000;
  69. }
  70. size += flash_info[0].size;
  71. flash_info[1].flash_id = (SST_MANUFACT & FLASH_VENDMASK);
  72. flash_info[1].size = 0x00200000; /* 2 MB */
  73. flash_info[1].sector_count = 512;
  74. memset (flash_info[1].protect, 0, 512);
  75. flashbase = SST_BASEADDR;
  76. for (j=0; j<512; j++) {
  77. flash_info[1].start[j] = flashbase;
  78. flashbase += 0x1000; /* 4 KB sectors */
  79. }
  80. size += flash_info[1].size;
  81. /* Protect monitor and environment sectors */
  82. flash_protect (FLAG_PROTECT_SET,
  83. 0x0,
  84. 0x0 + monitor_flash_len - 1,
  85. &flash_info[0]);
  86. flash_protect (FLAG_PROTECT_SET,
  87. CONFIG_ENV_ADDR,
  88. CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
  89. &flash_info[0]);
  90. return size;
  91. }
  92. /*-----------------------------------------------------------------------
  93. */
  94. void flash_print_info (flash_info_t * info)
  95. {
  96. int i;
  97. int erased = 0;
  98. unsigned long j;
  99. unsigned long count;
  100. unsigned char *p;
  101. switch (info->flash_id & FLASH_VENDMASK) {
  102. case (SST_MANUFACT & FLASH_VENDMASK):
  103. printf("SST: ");
  104. break;
  105. case (PHILIPS_LPC2292 & FLASH_VENDMASK):
  106. printf("Philips: ");
  107. break;
  108. default:
  109. printf ("Unknown Vendor ");
  110. break;
  111. }
  112. printf (" Size: %ld KB in %d Sectors\n",
  113. info->size >> 10, info->sector_count);
  114. printf (" Sector Start Addresses:");
  115. for (i = 0; i < info->sector_count; i++) {
  116. if ((i % 5) == 0) {
  117. printf ("\n ");
  118. }
  119. if (i < (info->sector_count - 1)) {
  120. count = info->start[i+1] - info->start[i];
  121. }
  122. else {
  123. count = info->start[0] + info->size - info->start[i];
  124. }
  125. p = (unsigned char*)(info->start[i]);
  126. erased = 1;
  127. for (j = 0; j < count; j++) {
  128. if (*p != 0xFF) {
  129. erased = 0;
  130. break;
  131. }
  132. p++;
  133. }
  134. printf (" %08lX%s%s", info->start[i], info->protect[i] ? " RO" : " ",
  135. erased ? " E" : " ");
  136. }
  137. printf ("\n");
  138. }
  139. int flash_erase_sst (flash_info_t * info, int s_first, int s_last)
  140. {
  141. int i;
  142. for (i = s_first; i <= s_last; i++) {
  143. *SST_ADDR1 = 0x00AA;
  144. *SST_ADDR2 = 0x0055;
  145. *SST_ADDR1 = 0x0080;
  146. *SST_ADDR1 = 0x00AA;
  147. *SST_ADDR2 = 0x0055;
  148. *((volatile ushort*)(info->start[i])) = 0x0030;
  149. /* wait for erase to finish */
  150. udelay(25000);
  151. }
  152. return ERR_OK;
  153. }
  154. int flash_erase (flash_info_t * info, int s_first, int s_last)
  155. {
  156. switch (info->flash_id & FLASH_VENDMASK) {
  157. case (SST_MANUFACT & FLASH_VENDMASK):
  158. return flash_erase_sst(info, s_first, s_last);
  159. case (PHILIPS_LPC2292 & FLASH_VENDMASK):
  160. return lpc2292_flash_erase(info, s_first, s_last);
  161. default:
  162. return ERR_PROTECTED;
  163. }
  164. return ERR_PROTECTED;
  165. }
  166. /*-----------------------------------------------------------------------
  167. * Copy memory to flash.
  168. *
  169. * cnt is in bytes
  170. */
  171. int write_buff_sst (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
  172. {
  173. ushort tmp;
  174. ulong i;
  175. uchar* src_org;
  176. uchar* dst_org;
  177. ulong cnt_org = cnt;
  178. int ret = ERR_OK;
  179. src_org = src;
  180. dst_org = (uchar*)addr;
  181. if (addr & 1) { /* if odd address */
  182. tmp = *((uchar*)(addr - 1)); /* little endian */
  183. tmp |= (*src << 8);
  184. write_word_sst(addr - 1, tmp);
  185. addr += 1;
  186. cnt -= 1;
  187. src++;
  188. }
  189. while (cnt > 1) {
  190. tmp = ((*(src+1)) << 8) + (*src); /* little endian */
  191. write_word_sst(addr, tmp);
  192. addr += 2;
  193. src += 2;
  194. cnt -= 2;
  195. }
  196. if (cnt > 0) {
  197. tmp = (*((uchar*)(addr + 1))) << 8;
  198. tmp |= *src;
  199. write_word_sst(addr, tmp);
  200. }
  201. for (i = 0; i < cnt_org; i++) {
  202. if (*dst_org != *src_org) {
  203. printf("Write failed. Byte %lX differs\n", i);
  204. ret = ERR_PROG_ERROR;
  205. break;
  206. }
  207. dst_org++;
  208. src_org++;
  209. }
  210. return ret;
  211. }
  212. int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
  213. {
  214. switch (info->flash_id & FLASH_VENDMASK) {
  215. case (SST_MANUFACT & FLASH_VENDMASK):
  216. return write_buff_sst(info, src, addr, cnt);
  217. case (PHILIPS_LPC2292 & FLASH_VENDMASK):
  218. return lpc2292_write_buff(info, src, addr, cnt);
  219. default:
  220. return ERR_PROG_ERROR;
  221. }
  222. return ERR_PROG_ERROR;
  223. }