summaryrefslogtreecommitdiff
path: root/drivers/cfi_flash.c
diff options
context:
space:
mode:
authorStefan Roese <sr@denx.de>2006-04-01 13:41:03 +0200
committerStefan Roese <sr@denx.de>2006-04-01 13:44:14 +0200
commit2662b40cace272da5759040622561d821c878d56 (patch)
treee1e0ab867abd8bec63720d5b5306ef1038de3510 /drivers/cfi_flash.c
parent05d8dce9d07cf4073ea15fbc448c1ce22b6baf0f (diff)
downloadu-boot-imx-2662b40cace272da5759040622561d821c878d56.zip
u-boot-imx-2662b40cace272da5759040622561d821c878d56.tar.gz
u-boot-imx-2662b40cace272da5759040622561d821c878d56.tar.bz2
* Changes/fixes for drivers/cfi_flash.c:
- Add Intel legacy lock/unlock support to common CFI driver On some Intel flash's (e.g. Intel J3) legacy unlocking is supported, meaning that unlocking of one sector will unlock all sectors of this bank. Using this feature, unlocking of all sectors upon startup (via env var "unlock=yes") will get much faster. - Fixed problem with multiple reads of envronment variable "unlock" as pointed out by Reinhard Arlt & Anders Larsen. - Removed unwanted linefeeds from "protect" command when CFG_FLASH_PROTECTION is enabled. - Changed p3p400 board to use CFG_FLASH_PROTECTION Patch by Stefan Roese, 01 Apr 2006 * Changes/fixes for drivers/cfi_flash.c: - Correctly handle the cases where CFG_HZ != 1000 (several XScale-based boards) - Fix the timeout calculation of buffered writes (off by a factor of 1000) Patch by Anders Larsen, 31 Mar 2006
Diffstat (limited to 'drivers/cfi_flash.c')
-rw-r--r--drivers/cfi_flash.c71
1 files changed, 60 insertions, 11 deletions
diff --git a/drivers/cfi_flash.c b/drivers/cfi_flash.c
index a989d34..2e37480 100644
--- a/drivers/cfi_flash.c
+++ b/drivers/cfi_flash.c
@@ -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 */