|
@@ -117,6 +117,7 @@
|
|
|
#define FLASH_OFFSET_CFI 0x55
|
|
|
#define FLASH_OFFSET_CFI_RESP 0x10
|
|
|
#define FLASH_OFFSET_PRIMARY_VENDOR 0x13
|
|
|
+#define FLASH_OFFSET_EXT_QUERY_T_P_ADDR 0x15 /* extended query table primary addr */
|
|
|
#define FLASH_OFFSET_WTOUT 0x1F
|
|
|
#define FLASH_OFFSET_WBTOUT 0x20
|
|
|
#define FLASH_OFFSET_ETOUT 0x21
|
|
@@ -346,6 +347,10 @@ unsigned long flash_init (void)
|
|
|
unsigned long size = 0;
|
|
|
int i;
|
|
|
|
|
|
+#ifdef CFG_FLASH_PROTECTION
|
|
|
+ char *s = getenv("unlock");
|
|
|
+#endif
|
|
|
+
|
|
|
/* Init: no FLASHes known */
|
|
|
for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
|
|
|
flash_info[i].flash_id = FLASH_UNKNOWN;
|
|
@@ -357,15 +362,39 @@ unsigned long flash_init (void)
|
|
|
#endif /* CFG_FLASH_QUIET_TEST */
|
|
|
}
|
|
|
#ifdef CFG_FLASH_PROTECTION
|
|
|
- else {
|
|
|
- char *s = getenv("unlock");
|
|
|
+ else if ((s != NULL) && (strcmp(s, "yes") == 0)) {
|
|
|
+ /*
|
|
|
+ * 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".
|
|
|
+ */
|
|
|
+ if (flash_info[i].legacy_unlock) {
|
|
|
+ int k;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Disable legacy_unlock temporarily, since
|
|
|
+ * flash_real_protect would relock all other sectors
|
|
|
+ * again otherwise.
|
|
|
+ */
|
|
|
+ flash_info[i].legacy_unlock = 0;
|
|
|
|
|
|
- if (((s = getenv("unlock")) != NULL) && (strcmp(s, "yes") == 0)) {
|
|
|
/*
|
|
|
- * 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".
|
|
|
+ * Legacy unlocking (e.g. Intel J3) -> unlock only one
|
|
|
+ * sector. This will unlock all sectors.
|
|
|
+ */
|
|
|
+ flash_real_protect (&flash_info[i], 0, 0);
|
|
|
+
|
|
|
+ flash_info[i].legacy_unlock = 1;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Manually mark other sectors as unlocked (unprotected)
|
|
|
+ */
|
|
|
+ for (k = 1; k < flash_info[i].sector_count; k++)
|
|
|
+ flash_info[i].protect[k] = 0;
|
|
|
+ } else {
|
|
|
+ /*
|
|
|
+ * No legancy unlocking -> unlock all sectors
|
|
|
*/
|
|
|
flash_protect (FLAG_PROTECT_CLEAR,
|
|
|
flash_info[i].start[0],
|
|
@@ -668,8 +697,12 @@ int flash_real_protect (flash_info_t * info, long sector, int prot)
|
|
|
prot ? "protect" : "unprotect")) == 0) {
|
|
|
|
|
|
info->protect[sector] = prot;
|
|
|
- /* Intel's unprotect unprotects all locking */
|
|
|
- if (prot == 0) {
|
|
|
+
|
|
|
+ /*
|
|
|
+ * On some of Intel's flash chips (marked via legacy_unlock)
|
|
|
+ * unprotect unprotects all locking.
|
|
|
+ */
|
|
|
+ if ((prot == 0) && (info->legacy_unlock)) {
|
|
|
flash_sect_t i;
|
|
|
|
|
|
for (i = 0; i < info->sector_count; i++) {
|
|
@@ -746,6 +779,10 @@ static int flash_status_check (flash_info_t * info, flash_sect_t sector,
|
|
|
{
|
|
|
ulong start;
|
|
|
|
|
|
+#if CFG_HZ != 1000
|
|
|
+ tout *= CFG_HZ/1000;
|
|
|
+#endif
|
|
|
+
|
|
|
/* Wait for command completion */
|
|
|
start = get_timer (0);
|
|
|
while (flash_is_busy (info, sector)) {
|
|
@@ -1082,6 +1119,10 @@ ulong flash_get_size (ulong base, int banknum)
|
|
|
uchar num_erase_regions;
|
|
|
int erase_region_size;
|
|
|
int erase_region_count;
|
|
|
+#ifdef CFG_FLASH_PROTECTION
|
|
|
+ int ext_addr;
|
|
|
+ info->legacy_unlock = 0;
|
|
|
+#endif
|
|
|
|
|
|
info->start[0] = base;
|
|
|
|
|
@@ -1095,6 +1136,13 @@ ulong flash_get_size (ulong base, int banknum)
|
|
|
case CFI_CMDSET_INTEL_EXTENDED:
|
|
|
default:
|
|
|
info->cmd_reset = FLASH_CMD_RESET;
|
|
|
+#ifdef CFG_FLASH_PROTECTION
|
|
|
+ /* read legacy lock/unlock bit from intel flash */
|
|
|
+ ext_addr = flash_read_ushort (info, 0,
|
|
|
+ FLASH_OFFSET_EXT_QUERY_T_P_ADDR);
|
|
|
+ info->legacy_unlock =
|
|
|
+ flash_read_uchar (info, ext_addr + 5) & 0x08;
|
|
|
+#endif
|
|
|
break;
|
|
|
case CFI_CMDSET_AMD_STANDARD:
|
|
|
case CFI_CMDSET_AMD_EXTENDED:
|
|
@@ -1160,8 +1208,9 @@ ulong flash_get_size (ulong base, int banknum)
|
|
|
info->buffer_size = (1 << flash_read_ushort (info, 0, FLASH_OFFSET_BUFFER_SIZE));
|
|
|
tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_ETOUT);
|
|
|
info->erase_blk_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_EMAX_TOUT)));
|
|
|
- tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WBTOUT);
|
|
|
- info->buffer_write_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT)));
|
|
|
+ tmp = (1 << flash_read_uchar (info, FLASH_OFFSET_WBTOUT)) *
|
|
|
+ (1 << flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT));
|
|
|
+ info->buffer_write_tout = tmp / 1000 + (tmp % 1000 ? 1 : 0); /* round up when converting to ms */
|
|
|
tmp = (1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT)) *
|
|
|
(1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT));
|
|
|
info->write_tout = tmp / 1000 + (tmp % 1000 ? 1 : 0); /* round up when converting to ms */
|