From: Florian Fainelli <ffainelli@freebox.fr>
To: "linux-mtd@lists.infradead.org" <linux-mtd@lists.infradead.org>,
David Woodhouse <dwmw2@infradead.org>,
Brian Norris <norris@broadcom.com>,
Matthieu CASTET <matthieu.castet@parrot.com>,
Maxime Bizon <mbizon@freebox.fr>
Subject: [PATCH] NAND: add support for reading ONFI parameters from NAND device
Date: Thu, 29 Jul 2010 00:47:05 +0200 [thread overview]
Message-ID: <201007290047.06394.ffainelli@freebox.fr> (raw)
A nand_chip which has valid ONFI parameters gets its options field updated
with the NAND_ONFI flag. In that case both the ONFI version (in BCD format)
as well as the complete page parameters is available in the struct nand_chip.
This allows for better detection of some new devices, as well as fine tuning of
NAND driver timings. This patch only adds support for ONFI 1.0 parameters.
Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
Signed-off-by: Florian Fainelli <ffainelli@freebox.fr>
---
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 4a7b864..c255cec 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2773,6 +2773,83 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
}
/*
+ * sanitize ONFI strings so we can safely print them
+ */
+static void sanitize_string(uint8_t *s, size_t len)
+{
+ ssize_t i;
+
+ /* null terminate */
+ s[len - 1] = 0;
+
+ /* remove non printable chars */
+ for (i = 0; i < len - 1; i++) {
+ if (s[i] < ' ' || s[i] > 127)
+ s[i] = '?';
+ }
+
+ /* remove trailing spaces */
+ for (i = len - 1; i >= 0; i--) {
+ if (s[i] && s[i] != ' ')
+ break;
+ s[i] = 0;
+ }
+}
+
+/*
+ * Check whether flash support ONFI and read ONFI parameters in that
+ * case
+ */
+static void nand_read_onfi(struct mtd_info *mtd, struct nand_chip *chip)
+{
+ struct nand_onfi_params *p;
+ uint8_t sig[4];
+ uint16_t val;
+
+ if (!chip->cmdfunc || !chip->read_buf)
+ return;
+
+ /* read ONFI signature */
+ chip->cmdfunc(mtd, NAND_CMD_READID, NAND_ADDR_ONFI_ID, -1);
+ chip->read_buf(mtd, sig, sizeof(sig));
+
+ if (memcmp(sig, "ONFI", sizeof(sig)))
+ return;
+
+ /* ONFI seems supported */
+ chip->cmdfunc(mtd, NAND_CMD_READ_ONFI_PARAMS, 0, -1);
+ p = &chip->onfi_params;
+ chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
+
+ /* recheck signature */
+ if (memcmp(p->sig, "ONFI", sizeof(p->sig))) {
+ printk(KERN_INFO "%s: bad ONFI params signature\n", __func__);
+ return;
+ }
+
+ /* check version */
+ val = le16_to_cpu(p->revision);
+ if (!is_power_of_2(val) || val == 1 || val > (1 << 4)) {
+ printk(KERN_INFO "%s: unsupported ONFI version\n", __func__);
+ return;
+ }
+
+ if (val & (1 << 1))
+ chip->onfi_version = 10;
+ else if (val & (1 << 2))
+ chip->onfi_version = 20;
+ else if (val & (1 << 3))
+ chip->onfi_version = 21;
+ else
+ chip->onfi_version = 22;
+
+ chip->options |= NAND_ONFI;
+
+ sanitize_string(p->manufacturer, sizeof(p->manufacturer));
+ sanitize_string(p->model, sizeof(p->model));
+}
+
+/*
* Get the flash and manufacturer id and lookup if the type is supported
*/
static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
@@ -2958,10 +3035,19 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
chip->cmdfunc = nand_command_lp;
+ nand_read_onfi(mtd, chip);
+
printk(KERN_INFO "NAND device: Manufacturer ID:"
" 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id,
nand_manuf_ids[maf_idx].name, type->name);
+ if (chip->options & NAND_ONFI)
+ printk(KERN_INFO "NAND is ONFI %d.%d compliant "
+ "(man:%s model:%s)\n",
+ chip->onfi_version / 10, chip->onfi_version % 10,
+ chip->onfi_params.manufacturer,
+ chip->onfi_params.model);
+
return type;
}
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index a81b185..ad7f58f 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -118,6 +118,10 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
#define NAND_CMD_STATUS_RESET 0x7f
#define NAND_CMD_STATUS_CLEAR 0xff
+/* Extended commands for ONFI devices */
+#define NAND_CMD_READ_ONFI_PARAMS 0xEC
+#define NAND_ADDR_ONFI_ID 0x20
+
#define NAND_CMD_NONE -1
/* Status bits */
@@ -190,6 +194,9 @@ typedef enum {
/* Device behaves just like nand, but is readonly */
#define NAND_ROM 0x00000800
+/* Chip supports ONFI */
+#define NAND_ONFI 0x00001000
+
/* Options valid for Samsung large page devices */
#define NAND_SAMSUNG_LP_OPTIONS \
(NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK)
@@ -229,6 +236,61 @@ typedef enum {
/* Keep gcc happy */
struct nand_chip;
+struct nand_onfi_params {
+ /* rev info and features block */
+ uint8_t sig[4]; /* 'O' 'N' 'F' 'I' */
+ uint16_t revision;
+ uint16_t features;
+ uint16_t opt_cmd;
+ uint8_t reserved[22];
+
+ /* manufacturer information block */
+ char manufacturer[12];
+ char model[20];
+ uint8_t jedec_id;
+ uint16_t date_code;
+ uint8_t reserved2[13];
+
+ /* memory organization block */
+ uint32_t byte_per_page;
+ uint16_t spare_bytes_per_page;
+ uint32_t data_bytes_per_ppage;
+ uint16_t sparre_bytes_per_ppage;
+ uint32_t pages_per_block;
+ uint32_t blocks_per_lun;
+ uint8_t lun_count;
+ uint8_t addr_cycles;
+ uint8_t bits_per_cell;
+ uint16_t bb_per_lun;
+ uint16_t block_endurance;
+ uint8_t guaranteed_good_blocks;
+ uint16_t guaranteed_block_endurance;
+ uint8_t programs_per_page;
+ uint8_t ppage_attr;
+ uint8_t ecc_bits;
+ uint8_t interleaved_bits;
+ uint8_t interleaved_ops;
+ uint8_t reserved3[13];
+ uint8_t io_pin_capacitance_max;
+
+ /* electrical parameter block */
+ uint16_t async_timing_mode;
+ uint16_t program_cache_timing_mode;
+ uint16_t t_prog;
+ uint16_t t_bers;
+ uint16_t t_r;
+ uint16_t t_ccs;
+ uint16_t src_sync_timing_mode;
+ uint16_t src_ssync_features;
+ uint16_t clk_pin_capacitance_typ;
+ uint16_t io_pin_capacitance_typ;
+ uint16_t input_pin_capacitance_typ;
+ uint8_t input_pin_capacitance_max;
+ uint8_t driver_strenght_support;
+ uint16_t t_int_r;
+ uint16_t t_ald;
+} __attribute__((packed));
+
/**
* struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices
* @lock: protection lock
@@ -354,6 +416,8 @@ struct nand_buffers {
* @chip_shift: [INTERN] number of address bits in one chip
* @options: [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
* special functionality. See the defines for further explanation
+ * @onfi_version: Supported ONFI version (10 => ONFI 1.0)
+ * @onfi_params: ONFI parameters
* @badblockpos: [INTERN] position of the bad block marker in the oob area
* @cellinfo: [INTERN] MLC/multichip data from chip ident
* @numchips: [INTERN] number of physical chips
@@ -413,6 +477,9 @@ struct nand_chip {
int badblockpos;
int badblockbits;
+ int onfi_version;
+ struct nand_onfi_params onfi_params;
+
flstate_t state;
uint8_t *oob_poi;
next reply other threads:[~2010-07-28 22:46 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-07-28 22:47 Florian Fainelli [this message]
2010-07-28 23:38 ` [PATCH] NAND: add support for reading ONFI parameters from NAND device Brian Norris
2010-07-29 8:10 ` Florian Fainelli
2010-07-29 7:54 ` Matthieu CASTET
2010-07-29 8:51 ` Florian Fainelli
2010-08-02 9:25 ` Matthieu CASTET
2010-08-02 11:55 ` Florian Fainelli
2010-08-09 9:25 ` Matthieu CASTET
2010-08-09 9:43 ` Florian Fainelli
2010-08-05 4:54 ` Artem Bityutskiy
2010-08-05 12:56 ` Maxime Bizon
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=201007290047.06394.ffainelli@freebox.fr \
--to=ffainelli@freebox.fr \
--cc=dwmw2@infradead.org \
--cc=linux-mtd@lists.infradead.org \
--cc=matthieu.castet@parrot.com \
--cc=mbizon@freebox.fr \
--cc=norris@broadcom.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.