Commit 79b4cda076069d04122f0d863bcb822b5e596c93

Authored by Stefan Roese
1 parent c81eb1f5f5

Major CFI-FLASH driver update:

* Add env-variable "unlock" to handle initial state of sectors
  (locked/unlocked).

  Only the U-Boot image and it's environment is protected,
  all other sectors are unprotected (unlocked) if flash
  hardware protection is used (CFG_FLASH_PROTECTION) and
  the environment variable "unlock" is set to "yes".

  Patch by Stefan Roese, 28 Feb 2006

* Update drivers/cfi_flash.c:
  - find_sector() called in both versions of flash_write_cfiword()
  Patch by Peter Pearse, 27th Feb 2006

* CFI support for a x8/x16 AMD/Spansion flash configured in x8 mode
  Patch by Jose Maria Lopez, 16 Jan 2006

* Add support for AMD/Spansion Flashes in flash_write_cfibuffer
  Patch by Alex Bastos and Thomas Schaefer, 2005-08-29

* Changes/fixes for drivers/cfi_flash.c:
  We *should* check if there are any error bits if the previous call
  returned ERR_OK (Otherwise we will have output an error message in
  flash_status_check() already.)  The original code would only check for
  error bits if flash_status_check() returns ERR_TIMEOUT.
  Patch by Marcus Hall, 23 Aug 2005

* Changes/fixes for drivers/cfi_flash.c:
  - Add CFG_FLASH_PROTECT_CLEAR on drivers/cfi_flash.c
  - Prohibit buffer write when buffer_size is 1 on drivers/cfi_flash.c
  Patch by Sangmoon Kim, 19 Aug 2005

* Fixes for drivers/cfi_flash.c:
  - Fix wrong timeout value usage in flash_status_check()
  - Round write_tout up when converting to msec in flash_get_size()
  - Remove clearing flash status at the end of flash_write_cfibuffer()
    which sets Intel 28F640J3 flash back to command mode on CSB472
  Patch by Tolunay Orkun, 02 July 2005

Showing 4 changed files with 199 additions and 71 deletions Side-by-side Diff

... ... @@ -2,6 +2,45 @@
2 2 Changes since U-Boot 1.1.4:
3 3 ======================================================================
4 4  
  5 +* Add env-variable "unlock" to handle initial state of sectors
  6 + (locked/unlocked).
  7 +
  8 + Only the U-Boot image and it's environment is protected,
  9 + all other sectors are unprotected (unlocked) if flash
  10 + hardware protection is used (CFG_FLASH_PROTECTION) and
  11 + the environment variable "unlock" is set to "yes".
  12 +
  13 + Patch by Stefan Roese, 28 Feb 2006
  14 +
  15 +* Update drivers/cfi_flash.c:
  16 + - find_sector() called in both versions of flash_write_cfiword()
  17 + Patch by Peter Pearse, 27th Feb 2006
  18 +
  19 +* CFI support for a x8/x16 AMD/Spansion flash configured in x8 mode
  20 + Patch by Jose Maria Lopez, 16 Jan 2006
  21 +
  22 +* Add support for AMD/Spansion Flashes in flash_write_cfibuffer
  23 + Patch by Alex Bastos and Thomas Schaefer, 2005-08-29
  24 +
  25 +* Changes/fixes for drivers/cfi_flash.c:
  26 + We *should* check if there are any error bits if the previous call
  27 + returned ERR_OK (Otherwise we will have output an error message in
  28 + flash_status_check() already.) The original code would only check for
  29 + error bits if flash_status_check() returns ERR_TIMEOUT.
  30 + Patch by Marcus Hall, 23 Aug 2005
  31 +
  32 +* Changes/fixes for drivers/cfi_flash.c:
  33 + - Add CFG_FLASH_PROTECT_CLEAR on drivers/cfi_flash.c
  34 + - Prohibit buffer write when buffer_size is 1 on drivers/cfi_flash.c
  35 + Patch by Sangmoon Kim, 19 Aug 2005
  36 +
  37 +* Fixes for drivers/cfi_flash.c:
  38 + - Fix wrong timeout value usage in flash_status_check()
  39 + - Round write_tout up when converting to msec in flash_get_size()
  40 + - Remove clearing flash status at the end of flash_write_cfibuffer()
  41 + which sets Intel 28F640J3 flash back to command mode on CSB472
  42 + Patch by Tolunay Orkun, 02 July 2005
  43 +
5 44 * Add GIT version information (commid ID) to untagged U-Boot versions
6 45  
7 46 As done in the linux kernel, the U-Boot version (U_BOOT_VERSION)
board/tqm85xx/tqm85xx.c
... ... @@ -40,7 +40,6 @@
40 40  
41 41 void local_bus_init (void);
42 42 long int fixed_sdram (void);
43   -ulong flash_get_size (ulong base, int banknum);
44 43  
45 44 #ifdef CONFIG_CPM2
46 45 /*
... ... @@ -296,7 +295,7 @@
296 295  
297 296 /* Monitor protection ON by default */
298 297 flash_protect (FLAG_PROTECT_SET,
299   - CFG_MONITOR_BASE, 0xffffffff,
  298 + CFG_MONITOR_BASE, CFG_MONITOR_BASE + monitor_flash_len - 1,
300 299 &flash_info[CFG_MAX_FLASH_BANKS - 1]);
301 300  
302 301 /* Environment protection ON by default */
... ... @@ -104,13 +104,16 @@
104 104 #define AMD_CMD_ERASE_SECTOR 0x30
105 105 #define AMD_CMD_UNLOCK_START 0xAA
106 106 #define AMD_CMD_UNLOCK_ACK 0x55
  107 +#define AMD_CMD_WRITE_TO_BUFFER 0x25
  108 +#define AMD_CMD_WRITE_BUFFER_CONFIRM 0x29
107 109  
108 110 #define AMD_STATUS_TOGGLE 0x40
109 111 #define AMD_STATUS_ERROR 0x20
110   -#define AMD_ADDR_ERASE_START 0x555
111   -#define AMD_ADDR_START 0x555
112   -#define AMD_ADDR_ACK 0x2AA
113 112  
  113 +#define AMD_ADDR_ERASE_START ((info->portwidth == FLASH_CFI_8BIT) ? 0xAAA : 0x555)
  114 +#define AMD_ADDR_START ((info->portwidth == FLASH_CFI_8BIT) ? 0xAAA : 0x555)
  115 +#define AMD_ADDR_ACK ((info->portwidth == FLASH_CFI_8BIT) ? 0x555 : 0x2AA)
  116 +
114 117 #define FLASH_OFFSET_CFI 0x55
115 118 #define FLASH_OFFSET_CFI_RESP 0x10
116 119 #define FLASH_OFFSET_PRIMARY_VENDOR 0x13
117 120  
... ... @@ -175,7 +178,14 @@
175 178 flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* FLASH chips info */
176 179 #endif
177 180  
  181 +/*
  182 + * Check if chip width is defined. If not, start detecting with 8bit.
  183 + */
  184 +#ifndef CFG_FLASH_CFI_WIDTH
  185 +#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT
  186 +#endif
178 187  
  188 +
179 189 /*-----------------------------------------------------------------------
180 190 * Functions
181 191 */
... ... @@ -190,7 +200,6 @@
190 200 static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
191 201 static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
192 202 static int flash_detect_cfi (flash_info_t * info);
193   -ulong flash_get_size (ulong base, int banknum);
194 203 static int flash_write_cfiword (flash_info_t * info, ulong dest, cfiword_t cword);
195 204 static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
196 205 ulong tout, char *prompt);
... ... @@ -328,6 +337,7 @@
328 337 return retval;
329 338 }
330 339  
  340 +
331 341 /*-----------------------------------------------------------------------
332 342 */
333 343 unsigned long flash_init (void)
... ... @@ -345,6 +355,24 @@
345 355 i, flash_info[i].size, flash_info[i].size << 20);
346 356 #endif /* CFG_FLASH_QUIET_TEST */
347 357 }
  358 +#ifdef CFG_FLASH_PROTECTION
  359 + else {
  360 + char *s = getenv("unlock");
  361 +
  362 + if (((s = getenv("unlock")) != NULL) && (strcmp(s, "yes") == 0)) {
  363 + /*
  364 + * Only the U-Boot image and it's environment is protected,
  365 + * all other sectors are unprotected (unlocked) if flash
  366 + * hardware protection is used (CFG_FLASH_PROTECTION) and
  367 + * the environment variable "unlock" is set to "yes".
  368 + */
  369 + flash_protect (FLAG_PROTECT_CLEAR,
  370 + flash_info[i].start[0],
  371 + flash_info[i].start[0] + flash_info[i].size - 1,
  372 + &flash_info[i]);
  373 + }
  374 + }
  375 +#endif /* CFG_FLASH_PROTECTION */
348 376 }
349 377  
350 378 /* Monitor protection ON by default */
... ... @@ -565,7 +593,22 @@
565 593 buffered_size = (info->portwidth / info->chipwidth);
566 594 buffered_size *= info->buffer_size;
567 595 while (cnt >= info->portwidth) {
568   - i = buffered_size > cnt ? cnt : buffered_size;
  596 + /* prohibit buffer write when buffer_size is 1 */
  597 + if (info->buffer_size == 1) {
  598 + cword.l = 0;
  599 + for (i = 0; i < info->portwidth; i++)
  600 + flash_add_byte (info, &cword, *src++);
  601 + if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
  602 + return rc;
  603 + wp += info->portwidth;
  604 + cnt -= info->portwidth;
  605 + continue;
  606 + }
  607 +
  608 + /* write buffer until next buffered_size aligned boundary */
  609 + i = buffered_size - (wp % buffered_size);
  610 + if (i > cnt)
  611 + i = cnt;
569 612 if ((rc = flash_write_cfibuffer (info, wp, src, i)) != ERR_OK)
570 613 return rc;
571 614 i -= i & (info->portwidth - 1);
... ... @@ -705,7 +748,7 @@
705 748 /* Wait for command completion */
706 749 start = get_timer (0);
707 750 while (flash_is_busy (info, sector)) {
708   - if (get_timer (start) > info->erase_blk_tout * CFG_HZ) {
  751 + if (get_timer (start) > tout) {
709 752 printf ("Flash %s timeout at address %lx data %lx\n",
710 753 prompt, info->start[sector],
711 754 flash_read_long (info, sector, 0));
... ... @@ -729,7 +772,7 @@
729 772 switch (info->vendor) {
730 773 case CFI_CMDSET_INTEL_EXTENDED:
731 774 case CFI_CMDSET_INTEL_STANDARD:
732   - if ((retcode != ERR_OK)
  775 + if ((retcode == ERR_OK)
733 776 && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) {
734 777 retcode = ERR_INVAL;
735 778 printf ("Flash %s error at address %lx\n", prompt,
... ... @@ -985,7 +1028,7 @@
985 1028 {
986 1029 debug ("flash detect cfi\n");
987 1030  
988   - for (info->portwidth = FLASH_CFI_8BIT;
  1031 + for (info->portwidth = CFG_FLASH_CFI_WIDTH;
989 1032 info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) {
990 1033 for (info->chipwidth = FLASH_CFI_BY8;
991 1034 info->chipwidth <= info->portwidth;
... ... @@ -1106,8 +1149,9 @@
1106 1149 info->erase_blk_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_EMAX_TOUT)));
1107 1150 tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WBTOUT);
1108 1151 info->buffer_write_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT)));
1109   - tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT);
1110   - info->write_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT))) / 1000;
  1152 + tmp = (1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT)) *
  1153 + (1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT));
  1154 + info->write_tout = tmp / 1000 + (tmp % 1000 ? 1 : 0); /* round up when converting to ms */
1111 1155 info->flash_id = FLASH_MAN_CFI;
1112 1156 if ((info->interface == FLASH_CFI_X8X16) && (info->chipwidth == FLASH_CFI_BY8)) {
1113 1157 info->portwidth >>= 1; /* XXX - Need to test on x8/x16 in parallel. */
1114 1158  
1115 1159  
... ... @@ -1118,13 +1162,26 @@
1118 1162 return (info->size);
1119 1163 }
1120 1164  
  1165 +/* loop through the sectors from the highest address
  1166 + * when the passed address is greater or equal to the sector address
  1167 + * we have a match
  1168 + */
  1169 +static flash_sect_t find_sector (flash_info_t * info, ulong addr)
  1170 +{
  1171 + flash_sect_t sector;
1121 1172  
  1173 + for (sector = info->sector_count - 1; sector >= 0; sector--) {
  1174 + if (addr >= info->start[sector])
  1175 + break;
  1176 + }
  1177 + return sector;
  1178 +}
  1179 +
1122 1180 /*-----------------------------------------------------------------------
1123 1181 */
1124 1182 static int flash_write_cfiword (flash_info_t * info, ulong dest,
1125 1183 cfiword_t cword)
1126 1184 {
1127   -
1128 1185 cfiptr_t ctladdr;
1129 1186 cfiptr_t cptr;
1130 1187 int flag;
1131 1188  
... ... @@ -1188,26 +1245,12 @@
1188 1245 if (flag)
1189 1246 enable_interrupts ();
1190 1247  
1191   - return flash_full_status_check (info, 0, info->write_tout, "write");
  1248 + return flash_full_status_check (info, find_sector (info, dest),
  1249 + info->write_tout, "write");
1192 1250 }
1193 1251  
1194 1252 #ifdef CFG_FLASH_USE_BUFFER_WRITE
1195 1253  
1196   -/* loop through the sectors from the highest address
1197   - * when the passed address is greater or equal to the sector address
1198   - * we have a match
1199   - */
1200   -static flash_sect_t find_sector (flash_info_t * info, ulong addr)
1201   -{
1202   - flash_sect_t sector;
1203   -
1204   - for (sector = info->sector_count - 1; sector >= 0; sector--) {
1205   - if (addr >= info->start[sector])
1206   - break;
1207   - }
1208   - return sector;
1209   -}
1210   -
1211 1254 static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
1212 1255 int len)
1213 1256 {
1214 1257  
1215 1258  
1216 1259  
1217 1260  
1218 1261  
1219 1262  
1220 1263  
1221 1264  
... ... @@ -1216,66 +1259,106 @@
1216 1259 int retcode;
1217 1260 volatile cfiptr_t src;
1218 1261 volatile cfiptr_t dst;
1219   - /* buffered writes in the AMD chip set is not supported yet */
1220   - if((info->vendor == CFI_CMDSET_AMD_STANDARD) ||
1221   - (info->vendor == CFI_CMDSET_AMD_EXTENDED))
1222   - return ERR_INVAL;
1223 1262  
1224   - src.cp = cp;
1225   - dst.cp = (uchar *) dest;
1226   - sector = find_sector (info, dest);
1227   - flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
1228   - flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
1229   - if ((retcode =
1230   - flash_status_check (info, sector, info->buffer_write_tout,
1231   - "write to buffer")) == ERR_OK) {
1232   - /* reduce the number of loops by the width of the port */
  1263 + switch (info->vendor) {
  1264 + case CFI_CMDSET_INTEL_STANDARD:
  1265 + case CFI_CMDSET_INTEL_EXTENDED:
  1266 + src.cp = cp;
  1267 + dst.cp = (uchar *) dest;
  1268 + sector = find_sector (info, dest);
  1269 + flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
  1270 + flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
  1271 + if ((retcode = flash_status_check (info, sector, info->buffer_write_tout,
  1272 + "write to buffer")) == ERR_OK) {
  1273 + /* reduce the number of loops by the width of the port */
  1274 + switch (info->portwidth) {
  1275 + case FLASH_CFI_8BIT:
  1276 + cnt = len;
  1277 + break;
  1278 + case FLASH_CFI_16BIT:
  1279 + cnt = len >> 1;
  1280 + break;
  1281 + case FLASH_CFI_32BIT:
  1282 + cnt = len >> 2;
  1283 + break;
  1284 + case FLASH_CFI_64BIT:
  1285 + cnt = len >> 3;
  1286 + break;
  1287 + default:
  1288 + return ERR_INVAL;
  1289 + break;
  1290 + }
  1291 + flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
  1292 + while (cnt-- > 0) {
  1293 + switch (info->portwidth) {
  1294 + case FLASH_CFI_8BIT:
  1295 + *dst.cp++ = *src.cp++;
  1296 + break;
  1297 + case FLASH_CFI_16BIT:
  1298 + *dst.wp++ = *src.wp++;
  1299 + break;
  1300 + case FLASH_CFI_32BIT:
  1301 + *dst.lp++ = *src.lp++;
  1302 + break;
  1303 + case FLASH_CFI_64BIT:
  1304 + *dst.llp++ = *src.llp++;
  1305 + break;
  1306 + default:
  1307 + return ERR_INVAL;
  1308 + break;
  1309 + }
  1310 + }
  1311 + flash_write_cmd (info, sector, 0,
  1312 + FLASH_CMD_WRITE_BUFFER_CONFIRM);
  1313 + retcode = flash_full_status_check (info, sector,
  1314 + info->buffer_write_tout,
  1315 + "buffer write");
  1316 + }
  1317 + return retcode;
  1318 +
  1319 + case CFI_CMDSET_AMD_STANDARD:
  1320 + case CFI_CMDSET_AMD_EXTENDED:
  1321 + src.cp = cp;
  1322 + dst.cp = (uchar *) dest;
  1323 + sector = find_sector (info, dest);
  1324 +
  1325 + flash_unlock_seq(info,0);
  1326 + flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_TO_BUFFER);
  1327 +
1233 1328 switch (info->portwidth) {
1234 1329 case FLASH_CFI_8BIT:
1235 1330 cnt = len;
  1331 + flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
  1332 + while (cnt-- > 0) *dst.cp++ = *src.cp++;
1236 1333 break;
1237 1334 case FLASH_CFI_16BIT:
1238 1335 cnt = len >> 1;
  1336 + flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
  1337 + while (cnt-- > 0) *dst.wp++ = *src.wp++;
1239 1338 break;
1240 1339 case FLASH_CFI_32BIT:
1241 1340 cnt = len >> 2;
  1341 + flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
  1342 + while (cnt-- > 0) *dst.lp++ = *src.lp++;
1242 1343 break;
1243 1344 case FLASH_CFI_64BIT:
1244 1345 cnt = len >> 3;
  1346 + flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
  1347 + while (cnt-- > 0) *dst.llp++ = *src.llp++;
1245 1348 break;
1246 1349 default:
1247 1350 return ERR_INVAL;
1248   - break;
1249 1351 }
1250   - flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
1251   - while (cnt-- > 0) {
1252   - switch (info->portwidth) {
1253   - case FLASH_CFI_8BIT:
1254   - *dst.cp++ = *src.cp++;
1255   - break;
1256   - case FLASH_CFI_16BIT:
1257   - *dst.wp++ = *src.wp++;
1258   - break;
1259   - case FLASH_CFI_32BIT:
1260   - *dst.lp++ = *src.lp++;
1261   - break;
1262   - case FLASH_CFI_64BIT:
1263   - *dst.llp++ = *src.llp++;
1264   - break;
1265   - default:
1266   - return ERR_INVAL;
1267   - break;
1268   - }
1269   - }
1270   - flash_write_cmd (info, sector, 0,
1271   - FLASH_CMD_WRITE_BUFFER_CONFIRM);
1272   - retcode =
1273   - flash_full_status_check (info, sector,
1274   - info->buffer_write_tout,
1275   - "buffer write");
  1352 +
  1353 + flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM);
  1354 + retcode = flash_full_status_check (info, sector, info->buffer_write_tout,
  1355 + "buffer write");
  1356 + return retcode;
  1357 +
  1358 + default:
  1359 + debug ("Unknown Command Set\n");
  1360 + return ERR_INVAL;
1276 1361 }
1277   - flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
1278   - return retcode;
1279 1362 }
1280 1363 #endif /* CFG_FLASH_USE_BUFFER_WRITE */
1281 1364 #endif /* CFG_FLASH_CFI */
... ... @@ -80,6 +80,7 @@
80 80 extern int flash_erase (flash_info_t *, int, int);
81 81 extern int flash_sect_erase (ulong addr_first, ulong addr_last);
82 82 extern int flash_sect_protect (int flag, ulong addr_first, ulong addr_last);
  83 +extern ulong flash_get_size (ulong base, int banknum);
83 84  
84 85 /* common/flash.c */
85 86 extern void flash_protect (int flag, ulong from, ulong to, flash_info_t *info);
... ... @@ -274,6 +275,12 @@
274 275 #define INTEL_ID_28F64K3 0x88018801 /* 64M = 32K x 255 + 32k x 4 */
275 276 #define INTEL_ID_28F128K3 0x88028802 /* 128M = 64K x 255 + 32k x 4 */
276 277 #define INTEL_ID_28F256K3 0x88038803 /* 256M = 128K x 255 + 32k x 4 */
  278 +#define INTEL_ID_28F64P30T 0x88178817 /* 64M = 32K x 255 + 32k x 4 */
  279 +#define INTEL_ID_28F64P30B 0x881A881A /* 64M = 32K x 255 + 32k x 4 */
  280 +#define INTEL_ID_28F128P30T 0x88188818 /* 128M = 64K x 255 + 32k x 4 */
  281 +#define INTEL_ID_28F128P30B 0x881B881B /* 128M = 64K x 255 + 32k x 4 */
  282 +#define INTEL_ID_28F256P30T 0x88198819 /* 256M = 128K x 255 + 32k x 4 */
  283 +#define INTEL_ID_28F256P30B 0x881C881C /* 256M = 128K x 255 + 32k x 4 */
277 284  
278 285 #define INTEL_ID_28F160S3 0x00D000D0 /* 16M = 512K x 32 (64kB x 32) */
279 286 #define INTEL_ID_28F320S3 0x00D400D4 /* 32M = 512K x 64 (64kB x 64) */