Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/nor - dump raw QRY and/or JEDEC data depending on CF...
details: https://anonhg.NetBSD.org/src/rev/1bdc36109f0c
branches: trunk
changeset: 767577:1bdc36109f0c
user: cliff <cliff%NetBSD.org@localhost>
date: Sat Jul 23 06:27:40 2011 +0000
description:
- dump raw QRY and/or JEDEC data depending on CFI_DEBUG_QRY, CFI_DEBUG_JEDEC
- add ability to emulate CFI based on table lookup keyed by JEDEC IDs.
- warn if CFI command set is unknown
diffstat:
sys/dev/nor/cfi.c | 311 +++++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 276 insertions(+), 35 deletions(-)
diffs (truncated from 492 to 300 lines):
diff -r 0e0830816d1e -r 1bdc36109f0c sys/dev/nor/cfi.c
--- a/sys/dev/nor/cfi.c Sat Jul 23 06:27:09 2011 +0000
+++ b/sys/dev/nor/cfi.c Sat Jul 23 06:27:40 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cfi.c,v 1.3 2011/07/19 20:52:10 cliff Exp $ */
+/* $NetBSD: cfi.c,v 1.4 2011/07/23 06:27:40 cliff Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -28,11 +28,12 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include "opt_flash.h"
#include "opt_nor.h"
-#include "opt_flash.h"
+#include "opt_cfi.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cfi.c,v 1.3 2011/07/19 20:52:10 cliff Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cfi.c,v 1.4 2011/07/23 06:27:40 cliff Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -63,7 +64,18 @@
static void cfi_write_buf_1(device_t, flash_off_t, const uint8_t *, size_t);
static void cfi_write_buf_2(device_t, flash_off_t, const uint16_t *, size_t);
static void cfi_write_buf_4(device_t, flash_off_t, const uint32_t *, size_t);
+static void cfi_jedec_id_1(struct cfi * const );
+static void cfi_jedec_id_2(struct cfi * const );
+static void cfi_jedec_id_4(struct cfi * const );
static bool cfi_jedec_id(struct cfi * const);
+static bool cfi_emulate(struct cfi * const);
+static const struct cfi_jedec_tab * cfi_jedec_search(struct cfi *);
+static void cfi_jedec_fill(struct cfi * const,
+ const struct cfi_jedec_tab *);
+#if defined(CFI_DEBUG_JEDEC) || defined(CFI_DEBUG_QRY)
+static void cfi_hexdump(flash_off_t, void * const, u_int, u_int);
+#endif
+
/*
@@ -99,6 +111,70 @@
};
+#define LOG2_64K 16
+#define LOG2_128K 17
+#define LOG2_256K 18
+#define LOG2_512K 19
+#define LOG2_1M 20
+#define LOG2_2M 21
+#define LOG2_4M 22
+#define LOG2_8M 23
+#define LOG2_16M 24
+#define LOG2_32M 25
+#define LOG2_64M 26
+#define LOG2_128M 27
+#define LOG2_256M 28
+#define LOG2_512M 29
+#define LOG2_1G 30
+#define LOG2_2G 31
+const struct cfi_jedec_tab cfi_jedec_tab[] = {
+ {
+ .jt_name = "Pm39LV512",
+ .jt_mid = 0x9d,
+ .jt_did = 0x1b,
+ .jt_id_pri = 0, /* XXX */
+ .jt_id_alt = 0, /* XXX */
+ .jt_device_size = LOG2_64K,
+ .jt_interface_code_desc = CFI_IFCODE_X8,
+ .jt_erase_blk_regions = 1,
+ .jt_erase_blk_info = {
+ { 4096/256, (64/4)-1 },
+ },
+ .jt_write_word_time_typ = 40,
+ .jt_write_nbyte_time_typ = 0,
+ .jt_erase_blk_time_typ = 55,
+ .jt_erase_chip_time_typ = 55,
+ .jt_write_word_time_max = 1,
+ .jt_write_nbyte_time_max = 0,
+ .jt_erase_blk_time_max = 1,
+ .jt_erase_chip_time_max = 1,
+ .jt_opmode = &cfi_opmodes_1[0],
+ },
+ {
+ .jt_name = "Pm39LV010",
+ .jt_mid = 0x9d,
+ .jt_did = 0x1c,
+ .jt_id_pri = 0, /* XXX */
+ .jt_id_alt = 0, /* XXX */
+ .jt_device_size = LOG2_128K,
+ .jt_interface_code_desc = CFI_IFCODE_X8,
+ .jt_erase_blk_regions = 1,
+ .jt_erase_blk_info = {
+ { 4096/256, (128/4)-1 },
+ },
+ .jt_write_word_time_typ = 40,
+ .jt_write_nbyte_time_typ = 0,
+ .jt_erase_blk_time_typ = 55,
+ .jt_erase_chip_time_typ = 55,
+ .jt_write_word_time_max = 1,
+ .jt_write_nbyte_time_max = 0,
+ .jt_erase_blk_time_max = 1,
+ .jt_erase_chip_time_max = 1,
+ .jt_opmode = &cfi_opmodes_1[0],
+ },
+};
+
+
const struct nor_interface nor_interface_cfi = {
.scan_media = cfi_scan_media,
.init = cfi_init,
@@ -157,11 +233,11 @@
(qryp)->write_word_time_typ = cfi_unpack_1(data[0x1f]); \
(qryp)->write_nbyte_time_typ = cfi_unpack_1(data[0x20]); \
(qryp)->erase_blk_time_typ = cfi_unpack_1(data[0x21]); \
- (qryp)->erase_chiptime_typ = cfi_unpack_1(data[0x22]); \
+ (qryp)->erase_chip_time_typ = cfi_unpack_1(data[0x22]); \
(qryp)->write_word_time_max = cfi_unpack_1(data[0x23]); \
(qryp)->write_nbyte_time_max = cfi_unpack_1(data[0x24]); \
(qryp)->erase_blk_time_max = cfi_unpack_1(data[0x25]); \
- (qryp)->erase_chiptime_max = cfi_unpack_1(data[0x26]); \
+ (qryp)->erase_chip_time_max = cfi_unpack_1(data[0x26]); \
(qryp)->device_size = cfi_unpack_1(data[0x27]); \
(qryp)->interface_code_desc = \
be16toh(cfi_unpack_2(data[0x28], data[0x29])); \
@@ -239,6 +315,27 @@
} \
} while (0)
+#ifdef CFI_DEBUG_QRY
+# define CFI_DUMP_QRY(off, p, sz, stride) \
+ do { \
+ printf("%s: QRY data\n", __func__); \
+ cfi_hexdump(off, p, sz, stride); \
+ } while (0)
+#else
+# define CFI_DUMP_QRY(off, p, sz, stride)
+#endif
+
+#ifdef CFI_DEBUG_JEDEC
+# define CFI_DUMP_JEDEC(off, p, sz, stride) \
+ do { \
+ printf("%s: JEDEC data\n", __func__); \
+ cfi_hexdump(off, p, sz, stride); \
+ } while (0)
+#else
+# define CFI_DUMP_JEDEC(off, p, sz, stride)
+#endif
+
+
/*
* cfi_chip_query_opmode - determine operational mode based on QRY signature
*/
@@ -263,6 +360,8 @@
bus_space_read_region_1(cfi->cfi_bst, cfi->cfi_bsh, 0, data,
__arraycount(data));
+ CFI_DUMP_QRY(0, data, sizeof(data), 1);
+
bool found = cfi_chip_query_opmode(cfi, data, cfi_opmodes_1,
__arraycount(cfi_opmodes_1));
@@ -281,6 +380,8 @@
bus_space_read_region_2(cfi->cfi_bst, cfi->cfi_bsh, 0, data,
__arraycount(data));
+ CFI_DUMP_QRY(0, data, sizeof(data), 2);
+
bool found = cfi_chip_query_opmode(cfi, (uint8_t *)data,
cfi_opmodes_2, __arraycount(cfi_opmodes_2));
@@ -299,6 +400,8 @@
bus_space_read_region_4(cfi->cfi_bst, cfi->cfi_bsh, 0, data,
__arraycount(data));
+ CFI_DUMP_QRY(0, data, sizeof(data), 4);
+
bool found = cfi_chip_query_opmode(cfi, (uint8_t *)data,
cfi_opmodes_4, __arraycount(cfi_opmodes_4));
@@ -318,6 +421,8 @@
bus_space_read_region_8(cfi->cfi_bst, cfi->cfi_bsh, 0, data,
__arraycount(data));
+ CFI_DUMP_QRY(0, data, sizeof(data), 8);
+
bool found = cfi_chip_query_opmode(cfi, (uint8_t *)data,
cfi_opmodes_8, __arraycount(cfi_opmodes_8));
@@ -372,12 +477,20 @@
}
}
+ if (found)
+ cfi->cfi_emulated = false;
+
return found;
}
/*
* cfi_probe - search for a CFI NOR trying various port & chip widths
*
+ * - gather CFI QRY and PRI data
+ * - gather JEDEC ID data
+ * - if cfi_chip_query() fails, emulate CFI using table data if possible,
+ * otherwise fail.
+ *
* NOTE:
* striped NOR chips design not supported yet,
* so force portwidth=chipwidth for now
@@ -394,10 +507,13 @@
cfi->cfi_portwidth = /* XXX */
cfi->cfi_chipwidth = cw;
found = cfi_chip_query(cfi);
+ cfi_jedec_id(cfi);
+ if (! found)
+ found = cfi_emulate(cfi);
if (found)
- goto out;
+ break;
}
- out:
+
cfi_reset_default(cfi); /* exit QRY mode */
return found;
}
@@ -407,7 +523,7 @@
{
const bus_space_tag_t bst = cfi->cfi_bst;
const bus_space_handle_t bsh = cfi->cfi_bsh;
- bool found = true;
+ bool found;
KASSERT(cfi != NULL);
KASSERT(bst != NULL);
@@ -416,20 +532,8 @@
cfi->cfi_bst = bst; /* restore bus space */
cfi->cfi_bsh = bsh; /* " " " */
- /* gather CFI PRQ and PRI data */
- if (! cfi_probe(cfi)) {
- aprint_debug("%s: cfi_probe failed\n", __func__);
- found = false;
- goto out;
- }
+ found = cfi_probe(cfi);
- /* gather ID data if possible */
- if (! cfi_jedec_id(cfi)) {
- aprint_debug("%s: cfi_jedec_id failed\n", __func__);
- goto out;
- }
-
- out:
cfi_reset_default(cfi); /* exit QRY mode */
return found;
@@ -466,6 +570,8 @@
cfi_0002_init(sc, cfi, chip);
break;
default:
+ aprint_error_dev(self, "unsupported CFI cmdset %#04x\n",
+ cfi->cfi_qry_data.id_pri);
return -1;
}
@@ -607,6 +713,30 @@
}
static void
+cfi_jedec_id_1(struct cfi * const cfi)
+{
+ struct cfi_jedec_id_data *idp = &cfi->cfi_id_data;
+ uint8_t data[0x10];
+
+ bus_space_read_region_1(cfi->cfi_bst, cfi->cfi_bsh, 0, data,
+ __arraycount(data));
+
+ CFI_DUMP_JEDEC(0, data, sizeof(data), 1);
+
+ idp->id_mid = (uint16_t)data[0];
+ idp->id_did[0] = (uint16_t)data[1];
+ idp->id_did[1] = (uint16_t)data[0xe];
+ idp->id_did[2] = (uint16_t)data[0xf];
+ idp->id_prot_state = (uint16_t)data[2];
+ idp->id_indicators = (uint16_t)data[3];
+
+ /* software bits, upper and lower */
+ idp->id_swb_lo = data[0xc];
+ idp->id_swb_hi = data[0xd];
+
+}
+
+static void
cfi_jedec_id_2(struct cfi * const cfi)
{
struct cfi_jedec_id_data *idp = &cfi->cfi_id_data;
Home |
Main Index |
Thread Index |
Old Index