#include <linux/byteorder/swab.h>
-flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
+flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
/* Board support for 1 or 2 flash devices */
#define FLASH_PORT_WIDTH8
#define FLASH_CYCLE2 0x02aa
#define WR_BLOCK 0x20
-
/*-----------------------------------------------------------------------
* Functions
*/
static int write_word_amd (flash_info_t * info, FPWV * dest, FPW data);
static void flash_get_offsets (ulong base, flash_info_t * info);
void inline spin_wheel (void);
+static void flash_sync_real_protect (flash_info_t * info);
+static unsigned char intel_sector_protected (flash_info_t *info, ushort sector);
+static unsigned char same_chip_banks (int bank1, int bank2);
/*-----------------------------------------------------------------------
*/
ulong size = 0;
ulong fsize = 0;
- for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
+ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
memset (&flash_info[i], 0, sizeof (flash_info_t));
switch (i) {
case 0:
- flash_get_size ((FPW *) CFG_FLASH1_BASE,
+ flash_get_size ((FPW *) CONFIG_SYS_FLASH1_BASE,
&flash_info[i]);
- flash_get_offsets (CFG_FLASH1_BASE, &flash_info[i]);
+ flash_get_offsets (CONFIG_SYS_FLASH1_BASE, &flash_info[i]);
break;
case 1:
- flash_get_size ((FPW *) CFG_FLASH1_BASE,
+ flash_get_size ((FPW *) CONFIG_SYS_FLASH1_BASE,
&flash_info[i]);
- fsize = CFG_FLASH1_BASE + flash_info[i - 1].size;
+ fsize = CONFIG_SYS_FLASH1_BASE + flash_info[i - 1].size;
flash_get_offsets (fsize, &flash_info[i]);
break;
case 2:
- flash_get_size ((FPW *) CFG_FLASH0_BASE,
+ flash_get_size ((FPW *) CONFIG_SYS_FLASH0_BASE,
&flash_info[i]);
- flash_get_offsets (CFG_FLASH0_BASE, &flash_info[i]);
+ flash_get_offsets (CONFIG_SYS_FLASH0_BASE, &flash_info[i]);
break;
case 3:
- flash_get_size ((FPW *) CFG_FLASH0_BASE,
+ flash_get_size ((FPW *) CONFIG_SYS_FLASH0_BASE,
&flash_info[i]);
- fsize = CFG_FLASH0_BASE + flash_info[i - 1].size;
+ fsize = CONFIG_SYS_FLASH0_BASE + flash_info[i - 1].size;
flash_get_offsets (fsize, &flash_info[i]);
break;
default:
break;
}
size += flash_info[i].size;
+
+ /* get the h/w and s/w protection status in sync */
+ flash_sync_real_protect(&flash_info[i]);
}
/* Protect monitor and environment sectors
*/
-#if defined (CFG_AMD_BOOT)
+#if defined (CONFIG_SYS_AMD_BOOT)
flash_protect (FLAG_PROTECT_SET,
- CFG_MONITOR_BASE,
- CFG_MONITOR_BASE + monitor_flash_len - 1,
+ CONFIG_SYS_MONITOR_BASE,
+ CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
&flash_info[2]);
flash_protect (FLAG_PROTECT_SET,
- CFG_INTEL_BASE,
- CFG_INTEL_BASE + monitor_flash_len - 1,
+ CONFIG_SYS_INTEL_BASE,
+ CONFIG_SYS_INTEL_BASE + monitor_flash_len - 1,
&flash_info[1]);
#else
flash_protect (FLAG_PROTECT_SET,
- CFG_MONITOR_BASE,
- CFG_MONITOR_BASE + monitor_flash_len - 1,
+ CONFIG_SYS_MONITOR_BASE,
+ CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
&flash_info[3]);
flash_protect (FLAG_PROTECT_SET,
- CFG_AMD_BASE,
- CFG_AMD_BASE + monitor_flash_len - 1, &flash_info[0]);
+ CONFIG_SYS_AMD_BASE,
+ CONFIG_SYS_AMD_BASE + monitor_flash_len - 1, &flash_info[0]);
#endif
flash_protect (FLAG_PROTECT_SET,
- CFG_ENV1_ADDR,
- CFG_ENV1_ADDR + CFG_ENV1_SIZE - 1, &flash_info[1]);
+ CONFIG_ENV1_ADDR,
+ CONFIG_ENV1_ADDR + CONFIG_ENV1_SIZE - 1, &flash_info[1]);
flash_protect (FLAG_PROTECT_SET,
- CFG_ENV_ADDR,
- CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[3]);
+ CONFIG_ENV_ADDR,
+ CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[3]);
return size;
}
if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
for (i = 0; i < info->sector_count; i++) {
info->start[i] = base + (i * PHYS_INTEL_SECT_SIZE);
- info->protect[i] = 0;
}
}
}
break;
}
- if (info->sector_count > CFG_MAX_FLASH_SECT) {
+ if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
printf ("** ERROR: sector count %d > max (%d) **\n",
- info->sector_count, CFG_MAX_FLASH_SECT);
- info->sector_count = CFG_MAX_FLASH_SECT;
+ info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
+ info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
}
if (value == (FPW) INTEL_ID_28F128J3A)
}
+/*
+ * This function gets the u-boot flash sector protection status
+ * (flash_info_t.protect[]) in sync with the sector protection
+ * status stored in hardware.
+ */
+static void flash_sync_real_protect (flash_info_t * info)
+{
+ int i;
+
+ switch (info->flash_id & FLASH_TYPEMASK) {
+ case FLASH_28F128J3A:
+ for (i = 0; i < info->sector_count; ++i) {
+ info->protect[i] = intel_sector_protected(info, i);
+ }
+ break;
+ case FLASH_AM040:
+ default:
+ /* no h/w protect support */
+ break;
+ }
+}
+
+
+/*
+ * checks if "sector" in bank "info" is protected. Should work on intel
+ * strata flash chips 28FxxxJ3x in 8-bit mode.
+ * Returns 1 if sector is protected (or timed-out while trying to read
+ * protection status), 0 if it is not.
+ */
+static unsigned char intel_sector_protected (flash_info_t *info, ushort sector)
+{
+ FPWV *addr;
+ FPWV *lock_conf_addr;
+ ulong start;
+ unsigned char ret;
+
+ /*
+ * first, wait for the WSM to be finished. The rationale for
+ * waiting for the WSM to become idle for at most
+ * CONFIG_SYS_FLASH_ERASE_TOUT is as follows. The WSM can be busy
+ * because of: (1) erase, (2) program or (3) lock bit
+ * configuration. So we just wait for the longest timeout of
+ * the (1)-(3), i.e. the erase timeout.
+ */
+
+ /* wait at least 35ns (W12) before issuing Read Status Register */
+ udelay(1);
+ addr = (FPWV *) info->start[sector];
+ *addr = (FPW) INTEL_STATUS;
+
+ start = get_timer (0);
+ while ((*addr & (FPW) INTEL_FINISHED) != (FPW) INTEL_FINISHED) {
+ if (get_timer (start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
+ *addr = (FPW) INTEL_RESET; /* restore read mode */
+ printf("WSM busy too long, can't get prot status\n");
+ return 1;
+ }
+ }
+
+ /* issue the Read Identifier Codes command */
+ *addr = (FPW) INTEL_READID;
+
+ /* wait at least 35ns (W12) before reading */
+ udelay(1);
+
+ /* Intel example code uses offset of 4 for 8-bit flash */
+ lock_conf_addr = (FPWV *) info->start[sector] + 4;
+ ret = (*lock_conf_addr & (FPW) INTEL_PROTECT) ? 1 : 0;
+
+ /* put flash back in read mode */
+ *addr = (FPW) INTEL_RESET;
+
+ return ret;
+}
+
+
+/*
+ * Checks if "bank1" and "bank2" are on the same chip. Returns 1 if they
+ * are and 0 otherwise.
+ */
+static unsigned char same_chip_banks (int bank1, int bank2)
+{
+ unsigned char same_chip[CONFIG_SYS_MAX_FLASH_BANKS][CONFIG_SYS_MAX_FLASH_BANKS] = {
+ {1, 1, 0, 0},
+ {1, 1, 0, 0},
+ {0, 0, 1, 1},
+ {0, 0, 1, 1}
+ };
+ return same_chip[bank1][bank2];
+}
+
+
/*-----------------------------------------------------------------------
*/
int flash_erase (flash_info_t * info, int s_first, int s_last)
} else {
FPWV *base; /* first address in bank */
- base = (FPWV *) (CFG_AMD_BASE);
+ base = (FPWV *) (CONFIG_SYS_AMD_BASE);
base[FLASH_CYCLE1] = (FPW) 0x00AA00AA; /* unlock */
base[FLASH_CYCLE2] = (FPW) 0x00550055; /* unlock */
base[FLASH_CYCLE1] = (FPW) 0x00800080; /* erase mode */
while (((status =
*addr) & (FPW) 0x00800080) !=
(FPW) 0x00800080) {
- if (get_timer (start) > CFG_FLASH_ERASE_TOUT) {
+ if (get_timer (start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
if (intel) {
*addr = (FPW) 0x00B000B0; /* suspend erase */
/* Check if Flash is (sufficiently) erased */
if ((*addr & data) != data) {
- printf ("not erased at %08lx (%lx)\n", (ulong) addr, *addr);
+ printf ("not erased at %08lx (%lx)\n", (ulong)addr, (ulong)*addr);
return (2);
}
/* Disable interrupts which might cause a timeout here */
/* wait while polling the status register */
while ((*addr & (FPW) 0x00800080) != (FPW) 0x00800080) {
- if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
+ if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
*addr = (FPW) 0x00FF00FF; /* restore read mode */
return (1);
}
for (i = 0; i < WR_BLOCK; i++)
if ((*dstaddr++ & 0xff) != 0xff) {
printf ("not erased at %08lx (%lx)\n",
- (ulong) dstaddr, *dstaddr);
+ (ulong)dstaddr, (ulong)*dstaddr);
return (2);
}
/* wait while polling the status register */
while ((*dstaddr & (FPW) 0x00800080) != (FPW) 0x00800080) {
- if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
+ if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
*dstaddr = (FPW) 0x00FF00FF; /* restore read mode */
return (1);
}
/* wait while polling the status register */
while ((*dstaddr & (FPW) 0x00800080) != (FPW) 0x00800080) {
- if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
+ if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
*dstaddr = (FPW) 0x00FF00FF; /* restore read mode */
return (1);
}
return (2);
}
- base = (FPWV *) (CFG_AMD_BASE);
+ base = (FPWV *) (CONFIG_SYS_AMD_BASE);
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts ();
/* data polling for D7 */
while (res == 0
&& (*dest & (FPW) 0x00800080) != (data & (FPW) 0x00800080)) {
- if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
+ if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
*dest = (FPW) 0x00F000F0; /* reset bank */
res = 1;
}
int flash_real_protect (flash_info_t * info, long sector, int prot)
{
ulong start;
- int i;
+ int i, j;
+ int curr_bank;
+ int bank;
int rc = 0;
FPWV *addr = (FPWV *) (info->start[sector]);
int flag = disable_interrupts ();
start = get_timer (0);
while ((*addr & INTEL_FINISHED) != INTEL_FINISHED) {
- if (get_timer (start) > CFG_FLASH_UNLOCK_TOUT) {
+ if (get_timer (start) > CONFIG_SYS_FLASH_UNLOCK_TOUT) {
printf ("Flash lock bit operation timed out\n");
rc = 1;
break;
* we have to restore lock bits of protected sectors.
*/
if (!prot) {
- for (i = 0; i < info->sector_count; i++) {
- if (info->protect[i]) {
- start = get_timer (0);
- addr = (FPWV *) (info->start[i]);
- *addr = INTEL_LOCKBIT; /* Sector lock bit */
- *addr = INTEL_PROTECT; /* set */
- while ((*addr & INTEL_FINISHED) !=
- INTEL_FINISHED) {
- if (get_timer (start) >
- CFG_FLASH_UNLOCK_TOUT) {
- printf ("Flash lock bit operation timed out\n");
- rc = 1;
- break;
+ /*
+ * re-locking must be done for all banks that belong on one
+ * FLASH chip, as all the sectors on the chip were unlocked
+ * by INTEL_LOCKBIT/INTEL_CONFIRM commands. (let's hope
+ * that banks never span chips, in particular chips which
+ * support h/w protection differently).
+ */
+
+ /* find the current bank number */
+ curr_bank = CONFIG_SYS_MAX_FLASH_BANKS + 1;
+ for (j = 0; j < CONFIG_SYS_MAX_FLASH_BANKS; ++j) {
+ if (&flash_info[j] == info) {
+ curr_bank = j;
+ }
+ }
+ if (curr_bank == CONFIG_SYS_MAX_FLASH_BANKS + 1) {
+ printf("Error: can't determine bank number!\n");
+ }
+
+ for (bank = 0; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
+ if (!same_chip_banks(curr_bank, bank)) {
+ continue;
+ }
+ info = &flash_info[bank];
+ for (i = 0; i < info->sector_count; i++) {
+ if (info->protect[i]) {
+ start = get_timer (0);
+ addr = (FPWV *) (info->start[i]);
+ *addr = INTEL_LOCKBIT; /* Sector lock bit */
+ *addr = INTEL_PROTECT; /* set */
+ while ((*addr & INTEL_FINISHED) !=
+ INTEL_FINISHED) {
+ if (get_timer (start) >
+ CONFIG_SYS_FLASH_UNLOCK_TOUT) {
+ printf ("Flash lock bit operation timed out\n");
+ rc = 1;
+ break;
+ }
}
}
}
}
+
+ /*
+ * get the s/w sector protection status in sync with the h/w,
+ * in case something went wrong during the re-locking.
+ */
+ flash_sync_real_protect(info); /* resets flash to read mode */
}
if (flag)