* [PATCH 01/12] cfi_flash: move intel real protect flash support to cfi_flash_intel.c
2010-11-26 19:43 [PATCH 0/12] cfi_flash: improvment Jean-Christophe PLAGNIOL-VILLARD
@ 2010-11-26 19:52 ` Jean-Christophe PLAGNIOL-VILLARD
2010-11-26 19:52 ` [PATCH 02/12] cfi_flash: add Atmel real protect flash support Jean-Christophe PLAGNIOL-VILLARD
` (11 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2010-11-26 19:52 UTC (permalink / raw)
To: barebox; +Cc: Nicolas Ferre, Patrice Vilchez
let an empty function for amd as we will add later atmel real protect flash
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/nor/cfi_flash.c | 10 ++++------
drivers/nor/cfi_flash.h | 1 +
drivers/nor/cfi_flash_amd.c | 6 ++++++
drivers/nor/cfi_flash_intel.c | 13 +++++++++++++
4 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/drivers/nor/cfi_flash.c b/drivers/nor/cfi_flash.c
index fa5e5ee..08e45ef 100644
--- a/drivers/nor/cfi_flash.c
+++ b/drivers/nor/cfi_flash.c
@@ -638,12 +638,10 @@ static int flash_real_protect (struct flash_info *info, long sector, int prot)
{
int retcode = 0;
- flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
- flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT);
- if (prot)
- flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_SET);
- else
- flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_CLEAR);
+ retcode = info->cfi_cmd_set->flash_real_protect(info, sector, prot);
+
+ if (retcode)
+ return retcode;
if ((retcode =
flash_status_check (info, sector, info->erase_blk_tout,
diff --git a/drivers/nor/cfi_flash.h b/drivers/nor/cfi_flash.h
index 057e56c..ee1a6f0 100644
--- a/drivers/nor/cfi_flash.h
+++ b/drivers/nor/cfi_flash.h
@@ -76,6 +76,7 @@ struct cfi_cmd_set {
void (*flash_read_jedec_ids) (struct flash_info *info);
void (*flash_prepare_write) (struct flash_info *info);
int (*flash_status_check) (struct flash_info *info, flash_sect_t sector, uint64_t tout, char *prompt);
+ int (*flash_real_protect) (struct flash_info *info, long sector, int prot);
};
extern struct cfi_cmd_set cfi_cmd_set_intel;
diff --git a/drivers/nor/cfi_flash_amd.c b/drivers/nor/cfi_flash_amd.c
index 45b7e5c..b10f7b2 100644
--- a/drivers/nor/cfi_flash_amd.c
+++ b/drivers/nor/cfi_flash_amd.c
@@ -133,6 +133,11 @@ static int amd_flash_write_cfibuffer (struct flash_info *info, ulong dest, const
#define amd_flash_write_cfibuffer NULL
#endif /* CONFIG_CFI_BUFFER_WRITE */
+static int amd_flash_real_protect (struct flash_info *info, long sector, int prot)
+{
+ return 0;
+}
+
struct cfi_cmd_set cfi_cmd_set_amd = {
.flash_write_cfibuffer = amd_flash_write_cfibuffer,
.flash_erase_one = amd_flash_erase_one,
@@ -140,5 +145,6 @@ struct cfi_cmd_set cfi_cmd_set_amd = {
.flash_read_jedec_ids = amd_read_jedec_ids,
.flash_prepare_write = amd_flash_prepare_write,
.flash_status_check = flash_generic_status_check,
+ .flash_real_protect = amd_flash_real_protect,
};
diff --git a/drivers/nor/cfi_flash_intel.c b/drivers/nor/cfi_flash_intel.c
index 4344760..a71f7c4 100644
--- a/drivers/nor/cfi_flash_intel.c
+++ b/drivers/nor/cfi_flash_intel.c
@@ -126,6 +126,18 @@ static int intel_flash_status_check (struct flash_info *info, flash_sect_t secto
return retcode;
}
+static int intel_flash_real_protect (struct flash_info *info, long sector, int prot)
+{
+ flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
+ flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT);
+ if (prot)
+ flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_SET);
+ else
+ flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_CLEAR);
+
+ return 0;
+}
+
struct cfi_cmd_set cfi_cmd_set_intel = {
.flash_write_cfibuffer = intel_flash_write_cfibuffer,
.flash_erase_one = intel_flash_erase_one,
@@ -133,5 +145,6 @@ struct cfi_cmd_set cfi_cmd_set_intel = {
.flash_read_jedec_ids = intel_read_jedec_ids,
.flash_prepare_write = intel_flash_prepare_write,
.flash_status_check = intel_flash_status_check,
+ .flash_real_protect = intel_flash_real_protect,
};
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 02/12] cfi_flash: add Atmel real protect flash support
2010-11-26 19:43 [PATCH 0/12] cfi_flash: improvment Jean-Christophe PLAGNIOL-VILLARD
2010-11-26 19:52 ` [PATCH 01/12] cfi_flash: move intel real protect flash support to cfi_flash_intel.c Jean-Christophe PLAGNIOL-VILLARD
@ 2010-11-26 19:52 ` Jean-Christophe PLAGNIOL-VILLARD
2010-11-26 19:52 ` [PATCH 03/12] cfi_flash: move flash_read_uchar from inline to noinline Jean-Christophe PLAGNIOL-VILLARD
` (10 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2010-11-26 19:52 UTC (permalink / raw)
To: barebox; +Cc: Nicolas Ferre, Patrice Vilchez
based on U-Boot
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/nor/cfi_flash.h | 4 ++++
drivers/nor/cfi_flash_amd.c | 17 +++++++++++++++++
2 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/drivers/nor/cfi_flash.h b/drivers/nor/cfi_flash.h
index ee1a6f0..047a035 100644
--- a/drivers/nor/cfi_flash.h
+++ b/drivers/nor/cfi_flash.h
@@ -121,6 +121,10 @@ extern struct cfi_cmd_set cfi_cmd_set_amd;
#define AMD_ADDR_START ((info->portwidth == FLASH_CFI_8BIT) ? 0xAAA : 0x555)
#define AMD_ADDR_ACK ((info->portwidth == FLASH_CFI_8BIT) ? 0x555 : 0x2AA)
+#define ATM_CMD_UNLOCK_SECT 0x70
+#define ATM_CMD_SOFTLOCK_START 0x80
+#define ATM_CMD_LOCK_SECT 0x40
+
#define FLASH_OFFSET_MANUFACTURER_ID 0x00
#define FLASH_OFFSET_DEVICE_ID 0x01
#define FLASH_OFFSET_DEVICE_ID2 0x0E
diff --git a/drivers/nor/cfi_flash_amd.c b/drivers/nor/cfi_flash_amd.c
index b10f7b2..dffd6f0 100644
--- a/drivers/nor/cfi_flash_amd.c
+++ b/drivers/nor/cfi_flash_amd.c
@@ -135,6 +135,23 @@ static int amd_flash_write_cfibuffer (struct flash_info *info, ulong dest, const
static int amd_flash_real_protect (struct flash_info *info, long sector, int prot)
{
+ if (info->manufacturer_id != (uchar)ATM_MANUFACT)
+ return 0;
+
+ if (prot) {
+ flash_unlock_seq (info);
+ flash_write_cmd (info, 0, AMD_ADDR_START,
+ ATM_CMD_SOFTLOCK_START);
+ flash_unlock_seq (info);
+ flash_write_cmd (info, sector, 0, ATM_CMD_LOCK_SECT);
+ } else {
+ flash_write_cmd (info, 0, AMD_ADDR_START,
+ AMD_CMD_UNLOCK_START);
+ if (info->device_id == ATM_ID_BV6416)
+ flash_write_cmd (info, sector, 0,
+ ATM_CMD_UNLOCK_SECT);
+ }
+
return 0;
}
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 03/12] cfi_flash: move flash_read_uchar from inline to noinline
2010-11-26 19:43 [PATCH 0/12] cfi_flash: improvment Jean-Christophe PLAGNIOL-VILLARD
2010-11-26 19:52 ` [PATCH 01/12] cfi_flash: move intel real protect flash support to cfi_flash_intel.c Jean-Christophe PLAGNIOL-VILLARD
2010-11-26 19:52 ` [PATCH 02/12] cfi_flash: add Atmel real protect flash support Jean-Christophe PLAGNIOL-VILLARD
@ 2010-11-26 19:52 ` Jean-Christophe PLAGNIOL-VILLARD
2010-11-26 19:52 ` [PATCH 04/12] cfi_flash: use amd and standard reset flash command at probing Jean-Christophe PLAGNIOL-VILLARD
` (9 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2010-11-26 19:52 UTC (permalink / raw)
To: barebox; +Cc: Nicolas Ferre, Patrice Vilchez
it will reduce the binary size of 28 bytes
and fix some issue observerd during the porting of the at91rm9200ek
when reading the device_id and manufacturor_id
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/nor/cfi_flash.c | 15 +++++++++++++++
drivers/nor/cfi_flash.h | 15 +--------------
2 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/drivers/nor/cfi_flash.c b/drivers/nor/cfi_flash.c
index 08e45ef..0efe0d4 100644
--- a/drivers/nor/cfi_flash.c
+++ b/drivers/nor/cfi_flash.c
@@ -186,6 +186,21 @@ static void flash_printqry (struct flash_info *info, flash_sect_t sect)
#endif
/*
+ * read a character at a port width address
+ */
+uchar flash_read_uchar (struct flash_info *info, uint offset)
+{
+ uchar *cp;
+
+ cp = flash_make_addr (info, 0, offset);
+#if defined(__LITTLE_ENDIAN)
+ return (cp[0]);
+#else
+ return (cp[info->portwidth - 1]);
+#endif
+}
+
+/*
* read a short word by swapping for ppc format.
*/
static ushort flash_read_ushort (struct flash_info *info, flash_sect_t sect, uint offset)
diff --git a/drivers/nor/cfi_flash.h b/drivers/nor/cfi_flash.h
index 047a035..9a299db 100644
--- a/drivers/nor/cfi_flash.h
+++ b/drivers/nor/cfi_flash.h
@@ -211,20 +211,7 @@ static inline uchar *flash_make_addr (struct flash_info *info, flash_sect_t sect
return ((uchar *) (info->start[sect] + (offset * info->portwidth)));
}
-/*
- * read a character at a port width address
- */
-static inline uchar flash_read_uchar (struct flash_info *info, uint offset)
-{
- uchar *cp;
-
- cp = flash_make_addr (info, 0, offset);
-#if defined(__LITTLE_ENDIAN)
- return (cp[0]);
-#else
- return (cp[info->portwidth - 1]);
-#endif
-}
+uchar flash_read_uchar (struct flash_info *info, uint offset);
#ifdef CONFIG_DRIVER_CFI_BANK_WIDTH_1
#define bankwidth_is_1(info) (info->portwidth == 1)
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 04/12] cfi_flash: use amd and standard reset flash command at probing
2010-11-26 19:43 [PATCH 0/12] cfi_flash: improvment Jean-Christophe PLAGNIOL-VILLARD
` (2 preceding siblings ...)
2010-11-26 19:52 ` [PATCH 03/12] cfi_flash: move flash_read_uchar from inline to noinline Jean-Christophe PLAGNIOL-VILLARD
@ 2010-11-26 19:52 ` Jean-Christophe PLAGNIOL-VILLARD
2010-11-26 19:52 ` [PATCH 05/12] cfi_flash: synchronize command offsets with Linux CFI driver Jean-Christophe PLAGNIOL-VILLARD
` (8 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2010-11-26 19:52 UTC (permalink / raw)
To: barebox; +Cc: Nicolas Ferre, Patrice Vilchez
as we do not known which flash we have yet
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/nor/cfi_flash.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/nor/cfi_flash.c b/drivers/nor/cfi_flash.c
index 0efe0d4..fb5935e 100644
--- a/drivers/nor/cfi_flash.c
+++ b/drivers/nor/cfi_flash.c
@@ -279,7 +279,8 @@ static int flash_detect_cfi (struct flash_info *info)
for (info->chipwidth = FLASH_CFI_BY8;
info->chipwidth <= info->portwidth;
info->chipwidth <<= 1) {
- flash_write_cmd (info, 0, 0, info->cmd_reset);
+ flash_write_cmd (info, 0, 0, AMD_CMD_RESET);
+ flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);
for (cfi_offset=0; cfi_offset < sizeof(flash_offset_cfi)/sizeof(uint); cfi_offset++) {
flash_write_cmd (info, 0, flash_offset_cfi[cfi_offset], FLASH_CMD_CFI);
if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 05/12] cfi_flash: synchronize command offsets with Linux CFI driver
2010-11-26 19:43 [PATCH 0/12] cfi_flash: improvment Jean-Christophe PLAGNIOL-VILLARD
` (3 preceding siblings ...)
2010-11-26 19:52 ` [PATCH 04/12] cfi_flash: use amd and standard reset flash command at probing Jean-Christophe PLAGNIOL-VILLARD
@ 2010-11-26 19:52 ` Jean-Christophe PLAGNIOL-VILLARD
2010-11-26 19:52 ` [PATCH 06/12] cfi_flash: update manufacturer id flash support Jean-Christophe PLAGNIOL-VILLARD
` (7 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2010-11-26 19:52 UTC (permalink / raw)
To: barebox; +Cc: Nicolas Ferre, Patrice Vilchez
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/nor/cfi_flash.h | 7 +++----
drivers/nor/cfi_flash_amd.c | 32 +++++++++++++++++++++++++-------
2 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/drivers/nor/cfi_flash.h b/drivers/nor/cfi_flash.h
index 9a299db..4094b02 100644
--- a/drivers/nor/cfi_flash.h
+++ b/drivers/nor/cfi_flash.h
@@ -59,6 +59,8 @@ struct flash_info {
ushort ext_addr; /* extended query table address */
ushort cfi_version; /* cfi version */
ushort cfi_offset; /* offset for cfi query */
+ ulong addr_unlock1; /* unlock address 1 for AMD flash roms */
+ ulong addr_unlock2; /* unlock address 2 for AMD flash roms */
struct cfi_cmd_set *cfi_cmd_set;
struct cdev cdev;
#ifdef CONFIG_PARTITION_NEED_MTD
@@ -117,10 +119,6 @@ extern struct cfi_cmd_set cfi_cmd_set_amd;
#define AMD_STATUS_TOGGLE 0x40
#define AMD_STATUS_ERROR 0x20
-#define AMD_ADDR_ERASE_START ((info->portwidth == FLASH_CFI_8BIT) ? 0xAAA : 0x555)
-#define AMD_ADDR_START ((info->portwidth == FLASH_CFI_8BIT) ? 0xAAA : 0x555)
-#define AMD_ADDR_ACK ((info->portwidth == FLASH_CFI_8BIT) ? 0x555 : 0x2AA)
-
#define ATM_CMD_UNLOCK_SECT 0x70
#define ATM_CMD_SOFTLOCK_START 0x80
#define ATM_CMD_LOCK_SECT 0x40
@@ -187,6 +185,7 @@ extern struct cfi_cmd_set cfi_cmd_set_amd;
#define FLASH_CFI_X8 0x00
#define FLASH_CFI_X16 0x01
#define FLASH_CFI_X8X16 0x02
+#define FLASH_CFI_X16X32 0x05
/* convert between bit value and numeric value */
#define CFI_FLASH_SHIFT_WIDTH 3
diff --git a/drivers/nor/cfi_flash_amd.c b/drivers/nor/cfi_flash_amd.c
index dffd6f0..c64377b 100644
--- a/drivers/nor/cfi_flash_amd.c
+++ b/drivers/nor/cfi_flash_amd.c
@@ -4,8 +4,8 @@
static void flash_unlock_seq (struct flash_info *info)
{
- flash_write_cmd (info, 0, AMD_ADDR_START, AMD_CMD_UNLOCK_START);
- flash_write_cmd (info, 0, AMD_ADDR_ACK, AMD_CMD_UNLOCK_ACK);
+ flash_write_cmd (info, 0, info->addr_unlock1, AMD_CMD_UNLOCK_START);
+ flash_write_cmd (info, 0, info->addr_unlock2, AMD_CMD_UNLOCK_ACK);
}
/*
@@ -20,9 +20,27 @@ static void amd_read_jedec_ids (struct flash_info *info)
info->device_id = 0;
info->device_id2 = 0;
+ /* calculate command offsets as in the Linux driver */
+ info->addr_unlock1 = 0x555;
+ info->addr_unlock2 = 0x2AA;
+
+ /*
+ * modify the unlock address if we are in compatibility mode
+ */
+ if ( /* x8/x16 in x8 mode */
+ ((info->chipwidth == FLASH_CFI_BY8) &&
+ (info->interface == FLASH_CFI_X8X16)) ||
+ /* x16/x32 in x16 mode */
+ ((info->chipwidth == FLASH_CFI_BY16) &&
+ (info->interface == FLASH_CFI_X16X32)))
+ {
+ info->addr_unlock1 = 0xaaa;
+ info->addr_unlock2 = 0x555;
+ }
+
flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
flash_unlock_seq(info);
- flash_write_cmd(info, 0, AMD_ADDR_START, FLASH_CMD_READ_ID);
+ flash_write_cmd(info, 0, info->addr_unlock1, FLASH_CMD_READ_ID);
udelay(1000); /* some flash are slow to respond */
info->manufacturer_id = flash_read_uchar (info,
FLASH_OFFSET_MANUFACTURER_ID);
@@ -74,7 +92,7 @@ static int amd_flash_is_busy (struct flash_info *info, flash_sect_t sect)
static int amd_flash_erase_one (struct flash_info *info, long sect)
{
flash_unlock_seq(info);
- flash_write_cmd (info, 0, AMD_ADDR_ERASE_START, AMD_CMD_ERASE_START);
+ flash_write_cmd (info, 0, info->addr_unlock1, AMD_CMD_ERASE_START);
flash_unlock_seq(info);
flash_write_cmd (info, sect, 0, AMD_CMD_ERASE_SECTOR);
@@ -84,7 +102,7 @@ static int amd_flash_erase_one (struct flash_info *info, long sect)
static void amd_flash_prepare_write(struct flash_info *info)
{
flash_unlock_seq(info);
- flash_write_cmd (info, 0, AMD_ADDR_START, AMD_CMD_WRITE);
+ flash_write_cmd (info, 0, info->addr_unlock1, AMD_CMD_WRITE);
}
#ifdef CONFIG_CFI_BUFFER_WRITE
@@ -140,12 +158,12 @@ static int amd_flash_real_protect (struct flash_info *info, long sector, int pro
if (prot) {
flash_unlock_seq (info);
- flash_write_cmd (info, 0, AMD_ADDR_START,
+ flash_write_cmd (info, 0, info->addr_unlock1,
ATM_CMD_SOFTLOCK_START);
flash_unlock_seq (info);
flash_write_cmd (info, sector, 0, ATM_CMD_LOCK_SECT);
} else {
- flash_write_cmd (info, 0, AMD_ADDR_START,
+ flash_write_cmd (info, 0, info->addr_unlock1,
AMD_CMD_UNLOCK_START);
if (info->device_id == ATM_ID_BV6416)
flash_write_cmd (info, sector, 0,
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 06/12] cfi_flash: update manufacturer id flash support
2010-11-26 19:43 [PATCH 0/12] cfi_flash: improvment Jean-Christophe PLAGNIOL-VILLARD
` (4 preceding siblings ...)
2010-11-26 19:52 ` [PATCH 05/12] cfi_flash: synchronize command offsets with Linux CFI driver Jean-Christophe PLAGNIOL-VILLARD
@ 2010-11-26 19:52 ` Jean-Christophe PLAGNIOL-VILLARD
2010-11-26 19:52 ` [PATCH 07/12] cfi_flash: Introduce read and write accessors Jean-Christophe PLAGNIOL-VILLARD
` (6 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2010-11-26 19:52 UTC (permalink / raw)
To: barebox; +Cc: Nicolas Ferre, Patrice Vilchez
several first banks can contain 0x7f instead of actual ID
support as done in linux
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/nor/cfi_flash.c | 18 ++++++++++++++++++
drivers/nor/cfi_flash.h | 3 +++
drivers/nor/cfi_flash_amd.c | 4 ++--
drivers/nor/cfi_flash_intel.c | 4 ++--
4 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/drivers/nor/cfi_flash.c b/drivers/nor/cfi_flash.c
index fb5935e..a1e0726 100644
--- a/drivers/nor/cfi_flash.c
+++ b/drivers/nor/cfi_flash.c
@@ -269,6 +269,24 @@ static ulong flash_read_long (struct flash_info *info, flash_sect_t sect, uint o
* http://www.jedec.org/download/search/jesd68.pdf
*
*/
+u32 jedec_read_mfr(struct flash_info *info)
+{
+ int bank = 0;
+ uchar mfr;
+
+ /* According to JEDEC "Standard Manufacturer's Identification Code"
+ * (http://www.jedec.org/download/search/jep106W.pdf)
+ * several first banks can contain 0x7f instead of actual ID
+ */
+ do {
+ mfr = flash_read_uchar (info,
+ (bank << 8) | FLASH_OFFSET_MANUFACTURER_ID);
+ bank++;
+ } while (mfr == FLASH_ID_CONTINUATION);
+
+ return mfr;
+}
+
static int flash_detect_cfi (struct flash_info *info)
{
int cfi_offset;
diff --git a/drivers/nor/cfi_flash.h b/drivers/nor/cfi_flash.h
index 4094b02..877822a 100644
--- a/drivers/nor/cfi_flash.h
+++ b/drivers/nor/cfi_flash.h
@@ -107,6 +107,8 @@ extern struct cfi_cmd_set cfi_cmd_set_amd;
#define FLASH_STATUS_R 0x01
#define FLASH_STATUS_PROTECT 0x01
+#define FLASH_ID_CONTINUATION 0x7F
+
#define AMD_CMD_RESET 0xF0
#define AMD_CMD_WRITE 0xA0
#define AMD_CMD_ERASE_START 0x80
@@ -211,6 +213,7 @@ static inline uchar *flash_make_addr (struct flash_info *info, flash_sect_t sect
}
uchar flash_read_uchar (struct flash_info *info, uint offset);
+u32 jedec_read_mfr(struct flash_info *info);
#ifdef CONFIG_DRIVER_CFI_BANK_WIDTH_1
#define bankwidth_is_1(info) (info->portwidth == 1)
diff --git a/drivers/nor/cfi_flash_amd.c b/drivers/nor/cfi_flash_amd.c
index c64377b..54e764d 100644
--- a/drivers/nor/cfi_flash_amd.c
+++ b/drivers/nor/cfi_flash_amd.c
@@ -42,8 +42,8 @@ static void amd_read_jedec_ids (struct flash_info *info)
flash_unlock_seq(info);
flash_write_cmd(info, 0, info->addr_unlock1, FLASH_CMD_READ_ID);
udelay(1000); /* some flash are slow to respond */
- info->manufacturer_id = flash_read_uchar (info,
- FLASH_OFFSET_MANUFACTURER_ID);
+
+ info->manufacturer_id = jedec_read_mfr(info);
info->device_id = flash_read_uchar (info,
FLASH_OFFSET_DEVICE_ID);
if (info->device_id == 0x7E) {
diff --git a/drivers/nor/cfi_flash_intel.c b/drivers/nor/cfi_flash_intel.c
index a71f7c4..649f83b 100644
--- a/drivers/nor/cfi_flash_intel.c
+++ b/drivers/nor/cfi_flash_intel.c
@@ -16,8 +16,8 @@ static void intel_read_jedec_ids (struct flash_info *info)
flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
flash_write_cmd(info, 0, 0, FLASH_CMD_READ_ID);
udelay(1000); /* some flash are slow to respond */
- info->manufacturer_id = flash_read_uchar (info,
- FLASH_OFFSET_MANUFACTURER_ID);
+
+ info->manufacturer_id = jedec_read_mfr(info);
info->device_id = flash_read_uchar (info,
FLASH_OFFSET_DEVICE_ID);
flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 07/12] cfi_flash: Introduce read and write accessors
2010-11-26 19:43 [PATCH 0/12] cfi_flash: improvment Jean-Christophe PLAGNIOL-VILLARD
` (5 preceding siblings ...)
2010-11-26 19:52 ` [PATCH 06/12] cfi_flash: update manufacturer id flash support Jean-Christophe PLAGNIOL-VILLARD
@ 2010-11-26 19:52 ` Jean-Christophe PLAGNIOL-VILLARD
2010-11-26 19:52 ` [PATCH 08/12] cfi_flash: Read whole QRY structure in one go Jean-Christophe PLAGNIOL-VILLARD
` (5 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2010-11-26 19:52 UTC (permalink / raw)
To: barebox; +Cc: Nicolas Ferre, Patrice Vilchez, Haavard Skinnemoen
Introduce flash_read{8,16,32,64) and flash_write{8,16,32,64} and use
them to access the flash memory. This makes it clearer when the flash
is actually being accessed; merely dereferencing a volatile pointer
looks just like any other kind of access.
based on U-Boot
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/nor/cfi_flash.c | 93 +++++++++++++++++++++--------------------
drivers/nor/cfi_flash.h | 58 +++++++++++++++++++++-----
drivers/nor/cfi_flash_amd.c | 39 +++++++++++-------
drivers/nor/cfi_flash_intel.c | 18 ++++----
4 files changed, 129 insertions(+), 79 deletions(-)
diff --git a/drivers/nor/cfi_flash.c b/drivers/nor/cfi_flash.c
index a1e0726..2ac4e7c 100644
--- a/drivers/nor/cfi_flash.c
+++ b/drivers/nor/cfi_flash.c
@@ -117,20 +117,20 @@ static void flash_add_byte (struct flash_info *info, cfiword_t * cword, uchar c)
static int flash_write_cfiword (struct flash_info *info, ulong dest,
cfiword_t cword)
{
- cfiptr_t cptr;
+ void *dstaddr;
int flag;
- cptr.cp = (uchar *) dest;
+ dstaddr = (uchar *) dest;
/* Check if Flash is (sufficiently) erased */
if (bankwidth_is_1(info)) {
- flag = ((cptr.cp[0] & cword.c) == cword.c);
+ flag = ((flash_read8(dstaddr) & cword.c) == cword.c);
} else if (bankwidth_is_2(info)) {
- flag = ((cptr.wp[0] & cword.w) == cword.w);
+ flag = ((flash_read16(dstaddr) & cword.w) == cword.w);
} else if (bankwidth_is_4(info)) {
- flag = ((cptr.lp[0] & cword.l) == cword.l);
+ flag = ((flash_read32(dstaddr) & cword.l) == cword.l);
} else if (bankwidth_is_8(info)) {
- flag = ((cptr.llp[0] & cword.ll) == cword.ll);
+ flag = ((flash_read64(dstaddr) & cword.ll) == cword.ll);
} else
return 2;
@@ -163,6 +163,7 @@ static void flash_printqry (struct flash_info *info, flash_sect_t sect)
{
cfiptr_t cptr;
int x, y;
+ unsigned char c;
for (x = 0; x < 0x40; x += 16U / info->portwidth) {
cptr.cp =
@@ -194,9 +195,9 @@ uchar flash_read_uchar (struct flash_info *info, uint offset)
cp = flash_make_addr (info, 0, offset);
#if defined(__LITTLE_ENDIAN)
- return (cp[0]);
+ return flash_read8(cp);
#else
- return (cp[info->portwidth - 1]);
+ return flash_read8(cp + info->portwidth - 1);
#endif
}
@@ -249,17 +250,19 @@ static ulong flash_read_long (struct flash_info *info, flash_sect_t sect, uint o
debug ("long addr is at %p info->portwidth = %d\n", addr,
info->portwidth);
for (x = 0; x < 4 * info->portwidth; x++) {
- debug ("addr[%x] = 0x%x\n", x, addr[x]);
+ debug ("addr[%x] = 0x%x\n", x, flash_read8(addr + x));
}
#endif
#if defined(__LITTLE_ENDIAN)
- retval = (addr[0] << 16) | (addr[(info->portwidth)] << 24) |
- (addr[(2 * info->portwidth)]) | (addr[(3 * info->portwidth)] << 8);
+ retval = ((flash_read8(addr) << 16) |
+ (flash_read8(addr + info->portwidth) << 24) |
+ (flash_read8(addr + 2 * info->portwidth)) |
+ (flash_read8(addr + 3 * info->portwidth) << 8));
#else
- retval = (addr[(2 * info->portwidth) - 1] << 24) |
- (addr[(info->portwidth) - 1] << 16) |
- (addr[(4 * info->portwidth) - 1] << 8) |
- addr[(3 * info->portwidth) - 1];
+ retval = ((flash_read8(addr + 2 * info->portwidth - 1) << 24) |
+ (flash_read8(addr + info->portwidth - 1) << 16) |
+ (flash_read8(addr + 4 * info->portwidth - 1) << 8) |
+ (flash_read8(addr + 3 * info->portwidth - 1)));
#endif
return retval;
}
@@ -576,7 +579,7 @@ static int cfi_erase(struct cdev *cdev, size_t count, unsigned long offset)
static int write_buff (struct flash_info *info, const uchar * src, ulong addr, ulong cnt)
{
ulong wp;
- ulong cp;
+ uchar *p;
int aln;
cfiword_t cword;
int i, rc;
@@ -585,28 +588,27 @@ static int write_buff (struct flash_info *info, const uchar * src, ulong addr, u
int buffered_size;
#endif
/* get lower aligned address */
- /* get lower aligned address */
wp = (addr & ~(info->portwidth - 1));
/* handle unaligned start */
if ((aln = addr - wp) != 0) {
cword.l = 0;
- cp = wp;
- for (i = 0; i < aln; ++i, ++cp)
- flash_add_byte (info, &cword, (*(uchar *) cp));
+ p = (uchar*)wp;
+ for (i = 0; i < aln; ++i)
+ flash_add_byte (info, &cword, flash_read8(p + i));
for (; (i < info->portwidth) && (cnt > 0); i++) {
flash_add_byte (info, &cword, *src++);
cnt--;
- cp++;
}
- for (; (cnt == 0) && (i < info->portwidth); ++i, ++cp)
- flash_add_byte (info, &cword, (*(uchar *) cp));
+ for (; (cnt == 0) && (i < info->portwidth); ++i)
+ flash_add_byte (info, &cword, flash_read8(p + i));
rc = flash_write_cfiword (info, wp, cword);
- if (rc)
+ if (rc != 0)
return rc;
- wp = cp;
+
+ wp += i;
}
/* handle the aligned part */
@@ -657,12 +659,13 @@ static int write_buff (struct flash_info *info, const uchar * src, ulong addr, u
* handle unaligned tail bytes
*/
cword.l = 0;
- for (i = 0, cp = wp; (i < info->portwidth) && (cnt > 0); ++i, ++cp) {
+ p = (uchar*)wp;
+ for (i = 0; (i < info->portwidth) && (cnt > 0); ++i) {
flash_add_byte (info, &cword, *src++);
--cnt;
}
- for (; i < info->portwidth; ++i, ++cp) {
- flash_add_byte (info, &cword, (*(uchar *) cp));
+ for (; i < info->portwidth; ++i) {
+ flash_add_byte (info, &cword, flash_read8(p + i));
}
return flash_write_cfiword (info, wp, cword);
@@ -920,35 +923,35 @@ void flash_write_cmd (struct flash_info *info, flash_sect_t sect, uint offset, u
int flash_isequal (struct flash_info *info, flash_sect_t sect, uint offset, uchar cmd)
{
- cfiptr_t cptr;
+ void *addr;
cfiword_t cword;
int retval;
- cptr.cp = flash_make_addr (info, sect, offset);
+ addr = flash_make_addr (info, sect, offset);
flash_make_cmd (info, cmd, &cword);
- debug ("is= cmd %x(%c) addr %p ", cmd, cmd, cptr.cp);
+ debug ("is= cmd %x(%c) addr %p ", cmd, cmd, addr);
if (bankwidth_is_1(info)) {
- debug ("is= %x %x\n", cptr.cp[0], cword.c);
- retval = (cptr.cp[0] == cword.c);
+ debug ("is= %x %x\n", flash_read8(addr), cword.c);
+ retval = (flash_read8(addr) == cword.c);
} else if (bankwidth_is_2(info)) {
- debug ("is= %4.4x %4.4x\n", cptr.wp[0], cword.w);
- retval = (cptr.wp[0] == cword.w);
+ debug ("is= %4.4x %4.4x\n", flash_read16(addr), cword.w);
+ retval = (flash_read16(addr) == cword.w);
} else if (bankwidth_is_4(info)) {
- debug ("is= %8.8lx %8.8lx\n", cptr.lp[0], cword.l);
- retval = (cptr.lp[0] == cword.l);
+ debug ("is= %8.8lx %8.8lx\n", flash_read32(addr), cword.l);
+ retval = (flash_read32(addr) == cword.l);
} else if (bankwidth_is_8(info)) {
#ifdef DEBUG
{
char str1[20];
char str2[20];
- print_longlong (str1, cptr.llp[0]);
+ print_longlong (str1, flash_read32(addr));
print_longlong (str2, cword.ll);
debug ("is= %s %s\n", str1, str2);
}
#endif
- retval = (cptr.llp[0] == cword.ll);
+ retval = (flash_read32(addr) == cword.ll);
} else
retval = 0;
@@ -957,20 +960,20 @@ int flash_isequal (struct flash_info *info, flash_sect_t sect, uint offset, ucha
int flash_isset (struct flash_info *info, flash_sect_t sect, uint offset, uchar cmd)
{
- cfiptr_t cptr;
+ void *addr;
cfiword_t cword;
int retval;
- cptr.cp = flash_make_addr (info, sect, offset);
+ addr = flash_make_addr (info, sect, offset);
flash_make_cmd (info, cmd, &cword);
if (bankwidth_is_1(info)) {
- retval = ((cptr.cp[0] & cword.c) == cword.c);
+ retval = ((flash_read8(addr) & cword.c) == cword.c);
} else if (bankwidth_is_2(info)) {
- retval = ((cptr.wp[0] & cword.w) == cword.w);
+ retval = ((flash_read16(addr) & cword.w) == cword.w);
} else if (bankwidth_is_4(info)) {
- retval = ((cptr.lp[0] & cword.l) == cword.l);
+ retval = ((flash_read32(addr) & cword.l) == cword.l);
} else if (bankwidth_is_8(info)) {
- retval = ((cptr.llp[0] & cword.ll) == cword.ll);
+ retval = ((flash_read64(addr) & cword.ll) == cword.ll);
} else
retval = 0;
diff --git a/drivers/nor/cfi_flash.h b/drivers/nor/cfi_flash.h
index 877822a..026654c 100644
--- a/drivers/nor/cfi_flash.h
+++ b/drivers/nor/cfi_flash.h
@@ -71,6 +71,8 @@ struct flash_info {
void *base;
};
+#define NUM_ERASE_REGIONS 4 /* max. number of erase regions */
+
struct cfi_cmd_set {
int (*flash_write_cfibuffer) (struct flash_info *info, ulong dest, const uchar * cp, int len);
int (*flash_erase_one) (struct flash_info *info, long sect);
@@ -204,6 +206,47 @@ int flash_generic_status_check (struct flash_info *info, flash_sect_t sector,
int flash_isequal (struct flash_info *info, flash_sect_t sect, uint offset, uchar cmd);
void flash_make_cmd (struct flash_info *info, uchar cmd, void *cmdbuf);
+static void flash_write8(u8 value, void *addr)
+{
+ __raw_writeb(value, addr);
+}
+
+static void flash_write16(u16 value, void *addr)
+{
+ __raw_writew(value, addr);
+}
+
+static void flash_write32(u32 value, void *addr)
+{
+ __raw_writel(value, addr);
+}
+
+static void flash_write64(u64 value, void *addr)
+{
+ memcpy((void *)addr, &value, 8);
+}
+
+static u8 flash_read8(void *addr)
+{
+ return __raw_readb(addr);
+}
+
+static u16 flash_read16(void *addr)
+{
+ return __raw_readw(addr);
+}
+
+static u32 flash_read32(void *addr)
+{
+ return __raw_readl(addr);
+}
+
+static u64 flash_read64(void *addr)
+{
+ /* No architectures currently implement __raw_readq() */
+ return *(volatile u64 *)addr;
+}
+
/*
* create an address based on the offset and the port width
*/
@@ -246,26 +289,19 @@ typedef union {
unsigned long long ll;
} cfiword_t;
-typedef union {
- volatile unsigned char *cp;
- volatile unsigned short *wp;
- volatile unsigned long *lp;
- volatile unsigned long long *llp;
-} cfiptr_t;
-
static inline void flash_write_word(struct flash_info *info, cfiword_t datum, void *addr)
{
if (bankwidth_is_1(info)) {
debug("fw addr %p val %02x\n", addr, datum.c);
- writeb(datum.c, addr);
+ flash_write8(datum.c, addr);
} else if (bankwidth_is_2(info)) {
debug("fw addr %p val %04x\n", addr, datum.w);
- writew(datum.w, addr);
+ flash_write16(datum.w, addr);
} else if (bankwidth_is_4(info)) {
debug("fw addr %p val %08x\n", addr, datum.l);
- writel(datum.l, addr);
+ flash_write32(datum.l, addr);
} else if (bankwidth_is_8(info)) {
- memcpy((void *)addr, &datum.ll, 8);
+ flash_write64(datum.ll, addr);
}
}
diff --git a/drivers/nor/cfi_flash_amd.c b/drivers/nor/cfi_flash_amd.c
index 54e764d..e9319b6 100644
--- a/drivers/nor/cfi_flash_amd.c
+++ b/drivers/nor/cfi_flash_amd.c
@@ -59,21 +59,20 @@ static void amd_read_jedec_ids (struct flash_info *info)
static int flash_toggle (struct flash_info *info, flash_sect_t sect, uint offset, uchar cmd)
{
- cfiptr_t cptr;
+ void *addr;
cfiword_t cword;
int retval;
- cptr.cp = flash_make_addr (info, sect, offset);
+ addr = flash_make_addr (info, sect, offset);
flash_make_cmd (info, cmd, &cword);
if (bankwidth_is_1(info)) {
- retval = ((cptr.cp[0] & cword.c) != (cptr.cp[0] & cword.c));
+ retval = flash_read8(addr) != flash_read8(addr);
} else if (bankwidth_is_2(info)) {
- retval = ((cptr.wp[0] & cword.w) != (cptr.wp[0] & cword.w));
+ retval = flash_read16(addr) != flash_read16(addr);
} else if (bankwidth_is_4(info)) {
- retval = ((cptr.lp[0] & cword.l) != (cptr.lp[0] & cword.l));
+ retval = flash_read32(addr) != flash_read32(addr);
} else if (bankwidth_is_8(info)) {
- retval = ((cptr.llp[0] & cword.ll) !=
- (cptr.llp[0] & cword.ll));
+ retval = flash_read64(addr) != flash_read64(addr);
} else
retval = 0;
@@ -112,12 +111,10 @@ static int amd_flash_write_cfibuffer (struct flash_info *info, ulong dest, const
flash_sect_t sector;
int cnt;
int retcode;
- volatile cfiptr_t src;
- volatile cfiptr_t dst;
+ void *src = (void*)cp;
+ void *dst = (void *)dest;
cfiword_t cword;
- src.cp = (uchar *)cp;
- dst.cp = (uchar *) dest;
sector = find_sector (info, dest);
flash_unlock_seq(info);
@@ -127,19 +124,31 @@ static int amd_flash_write_cfibuffer (struct flash_info *info, ulong dest, const
if (bankwidth_is_1(info)) {
cnt = len;
flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
- while (cnt-- > 0) *dst.cp++ = *src.cp++;
+ while (cnt-- > 0) {
+ flash_write8(flash_read8(src), dst);
+ src += 1, dst += 1;
+ }
} else if (bankwidth_is_2(info)) {
cnt = len >> 1;
flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
- while (cnt-- > 0) *dst.wp++ = *src.wp++;
+ while (cnt-- > 0) {
+ flash_write16(flash_read16(src), dst);
+ src += 2, dst += 2;
+ }
} else if (bankwidth_is_4(info)) {
cnt = len >> 2;
flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
- while (cnt-- > 0) *dst.lp++ = *src.lp++;
+ while (cnt-- > 0) {
+ flash_write32(flash_read32(src), dst);
+ src += 4, dst += 4;
+ }
} else if (bankwidth_is_8(info)) {
cnt = len >> 3;
flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
- while (cnt-- > 0) *dst.llp++ = *src.llp++;
+ while (cnt-- > 0) {
+ flash_write64(flash_read64(src), dst);
+ src += 8, dst += 8;
+ }
}
flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM);
diff --git a/drivers/nor/cfi_flash_intel.c b/drivers/nor/cfi_flash_intel.c
index 649f83b..f28301d 100644
--- a/drivers/nor/cfi_flash_intel.c
+++ b/drivers/nor/cfi_flash_intel.c
@@ -54,11 +54,9 @@ static int intel_flash_write_cfibuffer (struct flash_info *info, ulong dest, con
flash_sect_t sector;
int cnt;
int retcode;
- volatile cfiptr_t src;
- volatile cfiptr_t dst;
+ void *src = (void*)cp;
+ void *dst = (void *)dest;
- src.cp = (uchar *)cp;
- dst.cp = (uchar *) dest;
sector = find_sector (info, dest);
flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
@@ -74,13 +72,17 @@ static int intel_flash_write_cfibuffer (struct flash_info *info, ulong dest, con
flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
while (cnt-- > 0) {
if (bankwidth_is_1(info)) {
- *dst.cp++ = *src.cp++;
+ flash_write8(flash_read8(src), dst);
+ src += 1, dst += 1;
} else if (bankwidth_is_2(info)) {
- *dst.wp++ = *src.wp++;
+ flash_write16(flash_read16(src), dst);
+ src += 2, dst += 2;
} else if (bankwidth_is_4(info)) {
- *dst.lp++ = *src.lp++;
+ flash_write32(flash_read32(src), dst);
+ src += 4, dst += 4;
} else if (bankwidth_is_8(info)) {
- *dst.llp++ = *src.llp++;
+ flash_write64(flash_read64(src), dst);
+ src += 8, dst += 8;
}
}
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 08/12] cfi_flash: Read whole QRY structure in one go
2010-11-26 19:43 [PATCH 0/12] cfi_flash: improvment Jean-Christophe PLAGNIOL-VILLARD
` (6 preceding siblings ...)
2010-11-26 19:52 ` [PATCH 07/12] cfi_flash: Introduce read and write accessors Jean-Christophe PLAGNIOL-VILLARD
@ 2010-11-26 19:52 ` Jean-Christophe PLAGNIOL-VILLARD
2010-11-26 19:52 ` [PATCH 09/12] cfi_flash: do not reset flash when probe fails Jean-Christophe PLAGNIOL-VILLARD
` (4 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2010-11-26 19:52 UTC (permalink / raw)
To: barebox; +Cc: Nicolas Ferre, Patrice Vilchez, Haavard Skinnemoen
Read out the whole CFI Standard Query structure after successful cfi
identification. This allows subsequent code to access this information
directly without having to go through flash_read_uchar() and friends.
based on U-Boot
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/nor/cfi_flash.c | 149 ++++++++++++++++++------------------------
drivers/nor/cfi_flash.h | 33 ++++++++++
drivers/nor/cfi_flash_amd.c | 3 +-
3 files changed, 99 insertions(+), 86 deletions(-)
diff --git a/drivers/nor/cfi_flash.c b/drivers/nor/cfi_flash.c
index 2ac4e7c..041fb92 100644
--- a/drivers/nor/cfi_flash.c
+++ b/drivers/nor/cfi_flash.c
@@ -61,8 +61,6 @@
*
*/
-#define NUM_ERASE_REGIONS 4 /* max. number of erase regions */
-
static uint flash_offset_cfi[2]={FLASH_OFFSET_CFI,FLASH_OFFSET_CFI_ALT};
/*
@@ -159,29 +157,25 @@ void print_longlong (char *str, unsigned long long data)
sprintf (&str[i * 2], "%2.2x", *cp++);
}
-static void flash_printqry (struct flash_info *info, flash_sect_t sect)
+static void flash_printqry (struct cfi_qry *qry)
{
- cfiptr_t cptr;
+ u8 *p = (u8 *)qry;
int x, y;
unsigned char c;
- for (x = 0; x < 0x40; x += 16U / info->portwidth) {
- cptr.cp =
- flash_make_addr (info, sect,
- x + FLASH_OFFSET_CFI_RESP);
- debug ("%p : ", cptr.cp);
- for (y = 0; y < 16; y++) {
- debug ("%2.2x ", cptr.cp[y]);
- }
- debug (" ");
+ for (x = 0; x < sizeof(struct cfi_qry); x += 16) {
+ debug("%02x : ", x);
+ for (y = 0; y < 16; y++)
+ debug("%2.2x ", p[x + y]);
+ debug(" ");
for (y = 0; y < 16; y++) {
- if (cptr.cp[y] >= 0x20 && cptr.cp[y] <= 0x7e) {
- debug ("%c", cptr.cp[y]);
- } else {
- debug (".");
- }
+ c = p[x + y];
+ if (c >= 0x20 && c <= 0x7e)
+ debug("%c", c);
+ else
+ debug(".");
}
- debug ("\n");
+ debug("\n");
}
}
#endif
@@ -202,37 +196,6 @@ uchar flash_read_uchar (struct flash_info *info, uint offset)
}
/*
- * read a short word by swapping for ppc format.
- */
-static ushort flash_read_ushort (struct flash_info *info, flash_sect_t sect, uint offset)
-{
- uchar *addr;
- ushort retval;
-
-#ifdef DEBUG
- int x;
-#endif
- addr = flash_make_addr (info, sect, offset);
-
-#ifdef DEBUG
- debug ("ushort addr is at %p info->portwidth = %d\n", addr,
- info->portwidth);
- for (x = 0; x < 2 * info->portwidth; x++) {
- debug ("addr[%x] = 0x%x\n", x, addr[x]);
- }
-#endif
-#if defined(__LITTLE_ENDIAN)
- retval = ((addr[(info->portwidth)] << 8) | addr[0]);
-#else
- retval = ((addr[(2 * info->portwidth) - 1] << 8) |
- addr[info->portwidth - 1]);
-#endif
-
- debug ("retval = 0x%x\n", retval);
- return retval;
-}
-
-/*
* read a long word by picking the least significant byte of each maximum
* port size word. Swap for ppc format.
*/
@@ -290,7 +253,17 @@ u32 jedec_read_mfr(struct flash_info *info)
return mfr;
}
-static int flash_detect_cfi (struct flash_info *info)
+static void flash_read_cfi (struct flash_info *info, void *buf,
+ unsigned int start, size_t len)
+{
+ u8 *p = buf;
+ unsigned int i;
+
+ for (i = 0; i < len; i++)
+ p[i] = flash_read_uchar(info, start + i);
+}
+
+static int flash_detect_cfi (struct flash_info *info, struct cfi_qry *qry)
{
int cfi_offset;
debug ("flash detect cfi\n");
@@ -307,7 +280,10 @@ static int flash_detect_cfi (struct flash_info *info)
if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
&& flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R')
&& flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) {
- info->interface = flash_read_ushort (info, 0, FLASH_OFFSET_INTERFACE);
+ flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP,
+ sizeof(struct cfi_qry));
+ info->interface = le16_to_cpu(qry->interface_desc);
+
info->cfi_offset=flash_offset_cfi[cfi_offset];
debug ("device interface is %d\n",
info->interface);
@@ -340,6 +316,9 @@ static ulong flash_get_size (struct flash_info *info, ulong base)
int erase_region_count;
int geometry_reversed = 0;
int cur_offset = 0;
+ struct cfi_qry qry;
+
+ memset(&qry, 0, sizeof(qry));
info->ext_addr = 0;
info->cfi_version = 0;
@@ -353,9 +332,22 @@ static ulong flash_get_size (struct flash_info *info, ulong base)
info->start[0] = base;
info->protect = 0;
- if (flash_detect_cfi (info)) {
- info->vendor = flash_read_ushort (info, 0,
- FLASH_OFFSET_PRIMARY_VENDOR);
+ if (flash_detect_cfi (info, &qry)) {
+ info->vendor = le16_to_cpu(qry.p_id);
+ info->ext_addr = le16_to_cpu(qry.p_adr);
+ num_erase_regions = qry.num_erase_regions;
+
+ if (info->ext_addr) {
+ info->cfi_version = (ushort) flash_read_uchar (info,
+ info->ext_addr + 3) << 8;
+ info->cfi_version |= (ushort) flash_read_uchar (info,
+ info->ext_addr + 4);
+ }
+
+#ifdef DEBUG
+ flash_printqry (&qry);
+#endif
+
switch (info->vendor) {
#ifdef CONFIG_DRIVER_CFI_INTEL
case CFI_CMDSET_INTEL_EXTENDED:
@@ -375,19 +367,7 @@ static ulong flash_get_size (struct flash_info *info, ulong base)
}
info->cfi_cmd_set->flash_read_jedec_ids (info);
flash_write_cmd (info, 0, info->cfi_offset, FLASH_CMD_CFI);
- num_erase_regions = flash_read_uchar (info,
- FLASH_OFFSET_NUM_ERASE_REGIONS);
- info->ext_addr = flash_read_ushort (info, 0,
- FLASH_OFFSET_EXT_QUERY_T_P_ADDR);
- if (info->ext_addr) {
- info->cfi_version = (ushort) flash_read_uchar (info,
- info->ext_addr + 3) << 8;
- info->cfi_version |= (ushort) flash_read_uchar (info,
- info->ext_addr + 4);
- }
-#ifdef DEBUG
- flash_printqry (info, 0);
-#endif
+
switch (info->vendor) {
case CFI_CMDSET_INTEL_STANDARD:
case CFI_CMDSET_INTEL_EXTENDED:
@@ -445,6 +425,7 @@ static ulong flash_get_size (struct flash_info *info, ulong base)
sector = base;
for (i = 0; i < num_erase_regions; i++) {
+ unsigned int __region = i;
struct mtd_erase_region_info *region = &info->eraseregions[i];
if (i > NUM_ERASE_REGIONS) {
@@ -453,17 +434,15 @@ static ulong flash_get_size (struct flash_info *info, ulong base)
break;
}
if (geometry_reversed)
- tmp = flash_read_long (info, 0,
- FLASH_OFFSET_ERASE_REGIONS +
- (num_erase_regions - 1 - i) * 4);
- else
- tmp = flash_read_long (info, 0,
- FLASH_OFFSET_ERASE_REGIONS +
- i * 4);
+ __region = num_erase_regions - 1 - i;
+
+ tmp = le32_to_cpu(qry.erase_region_info[__region]);
+ debug("erase region %u: 0x%08lx\n", __region, tmp);
+
+ erase_region_count = (tmp & 0xffff) + 1;
+ tmp >>= 16;
erase_region_size =
(tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;
- tmp >>= 16;
- erase_region_count = (tmp & 0xffff) + 1;
debug ("erase_region_count = %d erase_region_size = %d\n",
erase_region_count, erase_region_size);
@@ -501,15 +480,15 @@ static ulong flash_get_size (struct flash_info *info, ulong base)
info->sector_count = sect_cnt;
/* multiply the size by the number of chips */
- info->size = (1 << flash_read_uchar (info, FLASH_OFFSET_SIZE)) * size_ratio;
- 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)) *
- (1 << flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT));
+ info->size = (1 << qry.dev_size) * size_ratio;
+ info->buffer_size = (1 << le16_to_cpu(qry.max_buf_write_size));
+ tmp = 1 << qry.block_erase_timeout_typ;
+ info->erase_blk_tout = (tmp * (1 << qry.block_erase_timeout_max));
+ tmp = (1 << qry.buf_write_timeout_typ) *
+ (1 << qry.buf_write_timeout_max);
info->buffer_write_tout = tmp * 1000;
- tmp = (1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT)) *
- (1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT));
+ tmp = (1 << qry.word_write_timeout_typ) *
+ (1 << qry.word_write_timeout_max);
info->write_tout = tmp * 1000;
info->flash_id = FLASH_MAN_CFI;
if ((info->interface == FLASH_CFI_X8X16) && (info->chipwidth == FLASH_CFI_BY8)) {
diff --git a/drivers/nor/cfi_flash.h b/drivers/nor/cfi_flash.h
index 026654c..4b3bd25 100644
--- a/drivers/nor/cfi_flash.h
+++ b/drivers/nor/cfi_flash.h
@@ -73,6 +73,39 @@ struct flash_info {
#define NUM_ERASE_REGIONS 4 /* max. number of erase regions */
+/* CFI standard query structure */
+struct cfi_qry {
+ u8 qry[3];
+ u16 p_id;
+ u16 p_adr;
+ u16 a_id;
+ u16 a_adr;
+ u8 vcc_min;
+ u8 vcc_max;
+ u8 vpp_min;
+ u8 vpp_max;
+ u8 word_write_timeout_typ;
+ u8 buf_write_timeout_typ;
+ u8 block_erase_timeout_typ;
+ u8 chip_erase_timeout_typ;
+ u8 word_write_timeout_max;
+ u8 buf_write_timeout_max;
+ u8 block_erase_timeout_max;
+ u8 chip_erase_timeout_max;
+ u8 dev_size;
+ u16 interface_desc;
+ u16 max_buf_write_size;
+ u8 num_erase_regions;
+ u32 erase_region_info[NUM_ERASE_REGIONS];
+} __attribute__((packed));
+
+struct cfi_pri_hdr {
+ u8 pri[3];
+ u8 major_version;
+ u8 minor_version;
+} __attribute__((packed));
+
+
struct cfi_cmd_set {
int (*flash_write_cfibuffer) (struct flash_info *info, ulong dest, const uchar * cp, int len);
int (*flash_erase_one) (struct flash_info *info, long sect);
diff --git a/drivers/nor/cfi_flash_amd.c b/drivers/nor/cfi_flash_amd.c
index e9319b6..738389c 100644
--- a/drivers/nor/cfi_flash_amd.c
+++ b/drivers/nor/cfi_flash_amd.c
@@ -72,7 +72,8 @@ static int flash_toggle (struct flash_info *info, flash_sect_t sect, uint offset
} else if (bankwidth_is_4(info)) {
retval = flash_read32(addr) != flash_read32(addr);
} else if (bankwidth_is_8(info)) {
- retval = flash_read64(addr) != flash_read64(addr);
+ retval = ( (flash_read32( addr ) != flash_read32( addr )) ||
+ (flash_read32(addr+4) != flash_read32(addr+4)) );
} else
retval = 0;
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 09/12] cfi_flash: do not reset flash when probe fails
2010-11-26 19:43 [PATCH 0/12] cfi_flash: improvment Jean-Christophe PLAGNIOL-VILLARD
` (7 preceding siblings ...)
2010-11-26 19:52 ` [PATCH 08/12] cfi_flash: Read whole QRY structure in one go Jean-Christophe PLAGNIOL-VILLARD
@ 2010-11-26 19:52 ` Jean-Christophe PLAGNIOL-VILLARD
2010-11-26 19:52 ` [PATCH 10/12] cfi_flash: move reset command assigment to specific chipset init function Jean-Christophe PLAGNIOL-VILLARD
` (3 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2010-11-26 19:52 UTC (permalink / raw)
To: barebox; +Cc: Mike Frysinger, Nicolas Ferre, Patrice Vilchez
The CFI flash driver starts at flash_init() which calls down into
flash_get_size(). This starts by calling flash_detect_cfi(). If said
function fails, flash_get_size() finishes by attempting to reset the
flash. Unfortunately, it does this with an info->portwidth set to 0x10
which filters down into flash_make_cmd() and that happily smashes the
stack by sticking info->portwidth bytes into a cfiword_t variable that
lives on the stack. On a 64bit system you probably won't notice, but
killing the last 8 bytes on a 32bit system usually leads to a corrupt
return address. Which is what happens on a Blackfin system.
based on U-Boot
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/nor/cfi_flash.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/nor/cfi_flash.c b/drivers/nor/cfi_flash.c
index 041fb92..a7df3b4 100644
--- a/drivers/nor/cfi_flash.c
+++ b/drivers/nor/cfi_flash.c
@@ -494,9 +494,9 @@ static ulong flash_get_size (struct flash_info *info, ulong base)
if ((info->interface == FLASH_CFI_X8X16) && (info->chipwidth == FLASH_CFI_BY8)) {
info->portwidth >>= 1; /* XXX - Need to test on x8/x16 in parallel. */
}
+ flash_write_cmd (info, 0, 0, info->cmd_reset);
}
- flash_write_cmd (info, 0, 0, info->cmd_reset);
return info->size;
}
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 10/12] cfi_flash: move reset command assigment to specific chipset init function
2010-11-26 19:43 [PATCH 0/12] cfi_flash: improvment Jean-Christophe PLAGNIOL-VILLARD
` (8 preceding siblings ...)
2010-11-26 19:52 ` [PATCH 09/12] cfi_flash: do not reset flash when probe fails Jean-Christophe PLAGNIOL-VILLARD
@ 2010-11-26 19:52 ` Jean-Christophe PLAGNIOL-VILLARD
2010-11-26 19:52 ` [PATCH 11/12] cfi_flash: introduce flash cmdset fixup Jean-Christophe PLAGNIOL-VILLARD
` (2 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2010-11-26 19:52 UTC (permalink / raw)
To: barebox; +Cc: Nicolas Ferre, Patrice Vilchez
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/nor/cfi_flash.c | 2 --
drivers/nor/cfi_flash_amd.c | 5 +++--
drivers/nor/cfi_flash_intel.c | 5 +++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/nor/cfi_flash.c b/drivers/nor/cfi_flash.c
index a7df3b4..6d22a53 100644
--- a/drivers/nor/cfi_flash.c
+++ b/drivers/nor/cfi_flash.c
@@ -372,7 +372,6 @@ static ulong flash_get_size (struct flash_info *info, ulong base)
case CFI_CMDSET_INTEL_STANDARD:
case CFI_CMDSET_INTEL_EXTENDED:
default:
- info->cmd_reset = FLASH_CMD_RESET;
#ifdef CFG_FLASH_PROTECTION
/* read legacy lock/unlock bit from intel flash */
if (info->ext_addr) {
@@ -383,7 +382,6 @@ static ulong flash_get_size (struct flash_info *info, ulong base)
break;
case CFI_CMDSET_AMD_STANDARD:
case CFI_CMDSET_AMD_EXTENDED:
- info->cmd_reset = AMD_CMD_RESET;
/* check if flash geometry needs reversal */
if (num_erase_regions <= 1)
break;
diff --git a/drivers/nor/cfi_flash_amd.c b/drivers/nor/cfi_flash_amd.c
index 738389c..f225757 100644
--- a/drivers/nor/cfi_flash_amd.c
+++ b/drivers/nor/cfi_flash_amd.c
@@ -16,6 +16,7 @@ static void flash_unlock_seq (struct flash_info *info)
*/
static void amd_read_jedec_ids (struct flash_info *info)
{
+ info->cmd_reset = AMD_CMD_RESET;
info->manufacturer_id = 0;
info->device_id = 0;
info->device_id2 = 0;
@@ -38,7 +39,7 @@ static void amd_read_jedec_ids (struct flash_info *info)
info->addr_unlock2 = 0x555;
}
- flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
+ flash_write_cmd(info, 0, 0, info->cmd_reset);
flash_unlock_seq(info);
flash_write_cmd(info, 0, info->addr_unlock1, FLASH_CMD_READ_ID);
udelay(1000); /* some flash are slow to respond */
@@ -54,7 +55,7 @@ static void amd_read_jedec_ids (struct flash_info *info)
info->device_id2 |= flash_read_uchar (info,
FLASH_OFFSET_DEVICE_ID3);
}
- flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
+ flash_write_cmd(info, 0, 0, info->cmd_reset);
}
static int flash_toggle (struct flash_info *info, flash_sect_t sect, uint offset, uchar cmd)
diff --git a/drivers/nor/cfi_flash_intel.c b/drivers/nor/cfi_flash_intel.c
index f28301d..8e8a820 100644
--- a/drivers/nor/cfi_flash_intel.c
+++ b/drivers/nor/cfi_flash_intel.c
@@ -9,18 +9,19 @@
*/
static void intel_read_jedec_ids (struct flash_info *info)
{
+ info->cmd_reset = FLASH_CMD_RESET;
info->manufacturer_id = 0;
info->device_id = 0;
info->device_id2 = 0;
- flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
+ flash_write_cmd(info, 0, 0, info->cmd_reset);
flash_write_cmd(info, 0, 0, FLASH_CMD_READ_ID);
udelay(1000); /* some flash are slow to respond */
info->manufacturer_id = jedec_read_mfr(info);
info->device_id = flash_read_uchar (info,
FLASH_OFFSET_DEVICE_ID);
- flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
+ flash_write_cmd(info, 0, 0, info->cmd_reset);
}
/*
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 11/12] cfi_flash: introduce flash cmdset fixup
2010-11-26 19:43 [PATCH 0/12] cfi_flash: improvment Jean-Christophe PLAGNIOL-VILLARD
` (9 preceding siblings ...)
2010-11-26 19:52 ` [PATCH 10/12] cfi_flash: move reset command assigment to specific chipset init function Jean-Christophe PLAGNIOL-VILLARD
@ 2010-11-26 19:52 ` Jean-Christophe PLAGNIOL-VILLARD
2010-11-26 19:52 ` [PATCH 12/12] cfi_flash_amd: Add manufacturer-specific fixups Jean-Christophe PLAGNIOL-VILLARD
2010-11-29 20:53 ` [PATCH 0/12] cfi_flash: improvment Sascha Hauer
12 siblings, 0 replies; 16+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2010-11-26 19:52 UTC (permalink / raw)
To: barebox; +Cc: Nicolas Ferre, Patrice Vilchez, Haavard Skinnemoen
Move fixing up like geometry reversal into separate functions.
The geometry reversal fixup is now performed
by altering the qry structure directly, which makes the sector init
code slightly cleaner.
based on U-Boot
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/nor/cfi_flash.c | 43 +++-------------------------------------
drivers/nor/cfi_flash.h | 1 +
drivers/nor/cfi_flash_amd.c | 35 +++++++++++++++++++++++++++++++++
drivers/nor/cfi_flash_intel.c | 12 +++++++++++
4 files changed, 52 insertions(+), 39 deletions(-)
diff --git a/drivers/nor/cfi_flash.c b/drivers/nor/cfi_flash.c
index 6d22a53..2fa2c6b 100644
--- a/drivers/nor/cfi_flash.c
+++ b/drivers/nor/cfi_flash.c
@@ -314,7 +314,6 @@ static ulong flash_get_size (struct flash_info *info, ulong base)
uchar num_erase_regions;
int erase_region_size;
int erase_region_count;
- int geometry_reversed = 0;
int cur_offset = 0;
struct cfi_qry qry;
@@ -368,38 +367,7 @@ static ulong flash_get_size (struct flash_info *info, ulong base)
info->cfi_cmd_set->flash_read_jedec_ids (info);
flash_write_cmd (info, 0, info->cfi_offset, FLASH_CMD_CFI);
- switch (info->vendor) {
- case CFI_CMDSET_INTEL_STANDARD:
- case CFI_CMDSET_INTEL_EXTENDED:
- default:
-#ifdef CFG_FLASH_PROTECTION
- /* read legacy lock/unlock bit from intel flash */
- if (info->ext_addr) {
- info->legacy_unlock = flash_read_uchar (info,
- info->ext_addr + 5) & 0x08;
- }
-#endif
- break;
- case CFI_CMDSET_AMD_STANDARD:
- case CFI_CMDSET_AMD_EXTENDED:
- /* check if flash geometry needs reversal */
- if (num_erase_regions <= 1)
- break;
- /* reverse geometry if top boot part */
- if (info->cfi_version < 0x3131) {
- /* CFI < 1.1, try to guess from device id */
- if ((info->device_id & 0x80) != 0) {
- geometry_reversed = 1;
- }
- break;
- }
- /* CFI >= 1.1, deduct from top/bottom flag */
- /* note: ext_addr is valid since cfi_version > 0 */
- if (flash_read_uchar(info, info->ext_addr + 0xf) == 3) {
- geometry_reversed = 1;
- }
- break;
- }
+ info->cfi_cmd_set->flash_fixup (info, &qry);
debug ("manufacturer is %d\n", info->vendor);
debug ("manufacturer id is 0x%x\n", info->manufacturer_id);
@@ -423,7 +391,6 @@ static ulong flash_get_size (struct flash_info *info, ulong base)
sector = base;
for (i = 0; i < num_erase_regions; i++) {
- unsigned int __region = i;
struct mtd_erase_region_info *region = &info->eraseregions[i];
if (i > NUM_ERASE_REGIONS) {
@@ -431,11 +398,9 @@ static ulong flash_get_size (struct flash_info *info, ulong base)
num_erase_regions, NUM_ERASE_REGIONS);
break;
}
- if (geometry_reversed)
- __region = num_erase_regions - 1 - i;
-
- tmp = le32_to_cpu(qry.erase_region_info[__region]);
- debug("erase region %u: 0x%08lx\n", __region, tmp);
+
+ tmp = le32_to_cpu(qry.erase_region_info[i]);
+ debug("erase region %u: 0x%08lx\n", i, tmp);
erase_region_count = (tmp & 0xffff) + 1;
tmp >>= 16;
diff --git a/drivers/nor/cfi_flash.h b/drivers/nor/cfi_flash.h
index 4b3bd25..1a3847d 100644
--- a/drivers/nor/cfi_flash.h
+++ b/drivers/nor/cfi_flash.h
@@ -114,6 +114,7 @@ struct cfi_cmd_set {
void (*flash_prepare_write) (struct flash_info *info);
int (*flash_status_check) (struct flash_info *info, flash_sect_t sector, uint64_t tout, char *prompt);
int (*flash_real_protect) (struct flash_info *info, long sector, int prot);
+ void (*flash_fixup) (struct flash_info *info, struct cfi_qry *qry);
};
extern struct cfi_cmd_set cfi_cmd_set_intel;
diff --git a/drivers/nor/cfi_flash_amd.c b/drivers/nor/cfi_flash_amd.c
index f225757..b50de22 100644
--- a/drivers/nor/cfi_flash_amd.c
+++ b/drivers/nor/cfi_flash_amd.c
@@ -2,6 +2,23 @@
#include <stdio.h>
#include "cfi_flash.h"
+/*-----------------------------------------------------------------------
+ * Reverse the order of the erase regions in the CFI QRY structure.
+ * This is needed for chips that are either a) correctly detected as
+ * top-boot, or b) buggy.
+ */
+static void cfi_reverse_geometry(struct cfi_qry *qry)
+{
+ unsigned int i, j;
+ u32 tmp;
+
+ for (i = 0, j = qry->num_erase_regions - 1; i < j; i++, j--) {
+ tmp = qry->erase_region_info[i];
+ qry->erase_region_info[i] = qry->erase_region_info[j];
+ qry->erase_region_info[j] = tmp;
+ }
+}
+
static void flash_unlock_seq (struct flash_info *info)
{
flash_write_cmd (info, 0, info->addr_unlock1, AMD_CMD_UNLOCK_START);
@@ -184,6 +201,23 @@ static int amd_flash_real_protect (struct flash_info *info, long sector, int pro
return 0;
}
+static void amd_flash_fixup (struct flash_info *info, struct cfi_qry *qry)
+{
+ /* check if flash geometry needs reversal */
+ if (qry->num_erase_regions > 1) {
+ /* reverse geometry if top boot part */
+ if (info->cfi_version < 0x3131) {
+ /* CFI < 1.1, try to guess from device id */
+ if ((info->device_id & 0x80) != 0)
+ cfi_reverse_geometry(qry);
+ } else if (flash_read_uchar(info, info->ext_addr + 0xf) == 3) {
+ /* CFI >= 1.1, deduct from top/bottom flag */
+ /* note: ext_addr is valid since cfi_version > 0 */
+ cfi_reverse_geometry(qry);
+ }
+ }
+}
+
struct cfi_cmd_set cfi_cmd_set_amd = {
.flash_write_cfibuffer = amd_flash_write_cfibuffer,
.flash_erase_one = amd_flash_erase_one,
@@ -192,5 +226,6 @@ struct cfi_cmd_set cfi_cmd_set_amd = {
.flash_prepare_write = amd_flash_prepare_write,
.flash_status_check = flash_generic_status_check,
.flash_real_protect = amd_flash_real_protect,
+ .flash_fixup = amd_flash_fixup,
};
diff --git a/drivers/nor/cfi_flash_intel.c b/drivers/nor/cfi_flash_intel.c
index 8e8a820..c3cbad5 100644
--- a/drivers/nor/cfi_flash_intel.c
+++ b/drivers/nor/cfi_flash_intel.c
@@ -141,6 +141,17 @@ static int intel_flash_real_protect (struct flash_info *info, long sector, int p
return 0;
}
+static void intel_flash_fixup (struct flash_info *info, struct cfi_qry *qry)
+{
+#ifdef CFG_FLASH_PROTECTION
+ /* read legacy lock/unlock bit from intel flash */
+ if (info->ext_addr) {
+ info->legacy_unlock = flash_read_uchar (info,
+ info->ext_addr + 5) & 0x08;
+ }
+#endif
+}
+
struct cfi_cmd_set cfi_cmd_set_intel = {
.flash_write_cfibuffer = intel_flash_write_cfibuffer,
.flash_erase_one = intel_flash_erase_one,
@@ -149,5 +160,6 @@ struct cfi_cmd_set cfi_cmd_set_intel = {
.flash_prepare_write = intel_flash_prepare_write,
.flash_status_check = intel_flash_status_check,
.flash_real_protect = intel_flash_real_protect,
+ .flash_fixup = intel_flash_fixup,
};
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 12/12] cfi_flash_amd: Add manufacturer-specific fixups
2010-11-26 19:43 [PATCH 0/12] cfi_flash: improvment Jean-Christophe PLAGNIOL-VILLARD
` (10 preceding siblings ...)
2010-11-26 19:52 ` [PATCH 11/12] cfi_flash: introduce flash cmdset fixup Jean-Christophe PLAGNIOL-VILLARD
@ 2010-11-26 19:52 ` Jean-Christophe PLAGNIOL-VILLARD
2010-11-29 20:53 ` [PATCH 0/12] cfi_flash: improvment Sascha Hauer
12 siblings, 0 replies; 16+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2010-11-26 19:52 UTC (permalink / raw)
To: barebox; +Cc: Nicolas Ferre, Patrice Vilchez, Haavard Skinnemoen
Run fixups based on the JEDEC manufacturer ID independent of the
command set ID.
This changes current behaviour: Previously, geometry reversal for AMD
chips were done based on the command set ID, while they are now done
based on the JEDEC manufacturer and device ID.
Also add fixup for top-boot Atmel chips.
based on U-Boot
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
drivers/nor/cfi_flash_amd.c | 39 ++++++++++++++++++++++++++++++++++++++-
1 files changed, 38 insertions(+), 1 deletions(-)
diff --git a/drivers/nor/cfi_flash_amd.c b/drivers/nor/cfi_flash_amd.c
index b50de22..b1d7070 100644
--- a/drivers/nor/cfi_flash_amd.c
+++ b/drivers/nor/cfi_flash_amd.c
@@ -201,7 +201,11 @@ static int amd_flash_real_protect (struct flash_info *info, long sector, int pro
return 0;
}
-static void amd_flash_fixup (struct flash_info *info, struct cfi_qry *qry)
+/*
+ * Manufacturer-specific quirks. Add workarounds for geometry
+ * reversal, etc. here.
+ */
+static void flash_fixup_amd (struct flash_info *info, struct cfi_qry *qry)
{
/* check if flash geometry needs reversal */
if (qry->num_erase_regions > 1) {
@@ -218,6 +222,39 @@ static void amd_flash_fixup (struct flash_info *info, struct cfi_qry *qry)
}
}
+static void flash_fixup_atmel(struct flash_info *info, struct cfi_qry *qry)
+{
+ int reverse_geometry = 0;
+
+ /* Check the "top boot" bit in the PRI */
+ if (info->ext_addr && !(flash_read_uchar(info, info->ext_addr + 6) & 1))
+ reverse_geometry = 1;
+
+ /* AT49BV6416(T) list the erase regions in the wrong order.
+ * However, the device ID is identical with the non-broken
+ * AT49BV642D since u-boot only reads the low byte (they
+ * differ in the high byte.) So leave out this fixup for now.
+ */
+ if (info->device_id == 0xd6 || info->device_id == 0xd2)
+ reverse_geometry = !reverse_geometry;
+
+ if (reverse_geometry)
+ cfi_reverse_geometry(qry);
+}
+
+static void amd_flash_fixup(struct flash_info *info, struct cfi_qry *qry)
+{
+ /* Do manufacturer-specific fixups */
+ switch (info->manufacturer_id) {
+ case 0x0001:
+ flash_fixup_amd(info, qry);
+ break;
+ case 0x001f:
+ flash_fixup_atmel(info, qry);
+ break;
+ }
+}
+
struct cfi_cmd_set cfi_cmd_set_amd = {
.flash_write_cfibuffer = amd_flash_write_cfibuffer,
.flash_erase_one = amd_flash_erase_one,
--
1.7.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 0/12] cfi_flash: improvment
2010-11-26 19:43 [PATCH 0/12] cfi_flash: improvment Jean-Christophe PLAGNIOL-VILLARD
` (11 preceding siblings ...)
2010-11-26 19:52 ` [PATCH 12/12] cfi_flash_amd: Add manufacturer-specific fixups Jean-Christophe PLAGNIOL-VILLARD
@ 2010-11-29 20:53 ` Sascha Hauer
2010-11-30 13:44 ` Jean-Christophe PLAGNIOL-VILLARD
2010-12-02 17:52 ` Jean-Christophe PLAGNIOL-VILLARD
12 siblings, 2 replies; 16+ messages in thread
From: Sascha Hauer @ 2010-11-29 20:53 UTC (permalink / raw)
To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox, Patrice Vilchez, Nicolas Ferre
Hi J,
On Fri, Nov 26, 2010 at 08:43:53PM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote:
> Hi,
>
> the following patch series improve the current flash
> by adding the atmel flash supportm fixing some issues and factorising
> more the code
>
> Found during the adding of the at91rm9200ek
>
> please pull
> The following changes since commit 53dbaf3fc7b8371ed1e24ef96715e41d60b8ebc3:
>
> Merge branch 'master' into next (2010-11-19 09:35:15 +0100)
Nice. I like this series.
Can we use readl/writel instead? The __raw_ versions do not exist on
architectures other than ARM.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 0/12] cfi_flash: improvment
2010-11-29 20:53 ` [PATCH 0/12] cfi_flash: improvment Sascha Hauer
@ 2010-11-30 13:44 ` Jean-Christophe PLAGNIOL-VILLARD
2010-12-02 17:52 ` Jean-Christophe PLAGNIOL-VILLARD
1 sibling, 0 replies; 16+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2010-11-30 13:44 UTC (permalink / raw)
To: Sascha Hauer; +Cc: barebox, Patrice Vilchez, Nicolas Ferre
On 21:53 Mon 29 Nov , Sascha Hauer wrote:
> Hi J,
>
> On Fri, Nov 26, 2010 at 08:43:53PM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > Hi,
> >
> > the following patch series improve the current flash
> > by adding the atmel flash supportm fixing some issues and factorising
> > more the code
> >
> > Found during the adding of the at91rm9200ek
> >
> > please pull
> > The following changes since commit 53dbaf3fc7b8371ed1e24ef96715e41d60b8ebc3:
> >
> > Merge branch 'master' into next (2010-11-19 09:35:15 +0100)
>
> Nice. I like this series.
>
> Can we use readl/writel instead? The __raw_ versions do not exist on
> architectures other than ARM.
yeah we can but __raw_ is supposed to exist on all arch IIRC
as u which
Best Regards,
J.
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 0/12] cfi_flash: improvment
2010-11-29 20:53 ` [PATCH 0/12] cfi_flash: improvment Sascha Hauer
2010-11-30 13:44 ` Jean-Christophe PLAGNIOL-VILLARD
@ 2010-12-02 17:52 ` Jean-Christophe PLAGNIOL-VILLARD
1 sibling, 0 replies; 16+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2010-12-02 17:52 UTC (permalink / raw)
To: Sascha Hauer; +Cc: barebox, Patrice Vilchez, Nicolas Ferre
Hi,
update without the __raw_
please pull
The following changes since commit 4a7f56056d6aa12a0449f03eb038e4d2bf7fdd49:
scripts: Adapt checkpatch.pl for barebox. (2010-11-29 21:56:05 +0100)
are available in the git repository at:
git://git.jcrosoft.org/barebox.git cfi
Jean-Christophe PLAGNIOL-VILLARD (12):
cfi_flash: move intel real protect flash support to cfi_flash_intel.c
cfi_flash: add Atmel real protect flash support
cfi_flash: move flash_read_uchar from inline to noinline
cfi_flash: use amd and standard reset flash command at probing
cfi_flash: synchronize command offsets with Linux CFI driver
cfi_flash: update manufacturer id flash support
cfi_flash: Introduce read and write accessors
cfi_flash: Read whole QRY structure in one go
cfi_flash: do not reset flash when probe fails
cfi_flash: move reset command assigment to specific chipset init function
cfi_flash: introduce flash cmdset fixup
cfi_flash_amd: Add manufacturer-specific fixups
drivers/nor/cfi_flash.c | 303 +++++++++++++++++++----------------------
drivers/nor/cfi_flash.h | 120 +++++++++++++----
drivers/nor/cfi_flash_amd.c | 172 ++++++++++++++++++++----
drivers/nor/cfi_flash_intel.c | 52 ++++++--
4 files changed, 420 insertions(+), 227 deletions(-)
Best Regards,
J.
On 21:53 Mon 29 Nov , Sascha Hauer wrote:
> Hi J,
>
> On Fri, Nov 26, 2010 at 08:43:53PM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > Hi,
> >
> > the following patch series improve the current flash
> > by adding the atmel flash supportm fixing some issues and factorising
> > more the code
> >
> > Found during the adding of the at91rm9200ek
> >
> > please pull
> > The following changes since commit 53dbaf3fc7b8371ed1e24ef96715e41d60b8ebc3:
> >
> > Merge branch 'master' into next (2010-11-19 09:35:15 +0100)
>
> Nice. I like this series.
>
> Can we use readl/writel instead? The __raw_ versions do not exist on
> architectures other than ARM.
>
> Sascha
>
>
> --
> Pengutronix e.K. | |
> Industrial Linux Solutions | http://www.pengutronix.de/ |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
> Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 16+ messages in thread