From patchwork Wed May 5 03:58:03 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Cernekee X-Patchwork-Id: 51647 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [18.85.46.34]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 53CBFB7D59 for ; Wed, 5 May 2010 14:15:17 +1000 (EST) Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) id 1O9Vzg-0004HA-PZ; Wed, 05 May 2010 04:13:57 +0000 Received: from [69.28.251.93] (helo=b32.net) by bombadil.infradead.org with esmtps (Exim 4.69 #1 (Red Hat Linux)) id 1O9Vze-0004GT-CI for linux-mtd@lists.infradead.org; Wed, 05 May 2010 04:13:55 +0000 Received: (qmail 30223 invoked from network); 5 May 2010 04:13:38 -0000 Received: from unknown (HELO vps-1001064-677.cp.jvds.com) (127.0.0.1) by 127.0.0.1 with (DHE-RSA-AES128-SHA encrypted) SMTP; 5 May 2010 04:13:38 -0000 Received: by vps-1001064-677.cp.jvds.com (sSMTP sendmail emulation); Tue, 04 May 2010 21:13:37 -0700 From: Kevin Cernekee Date: Tue, 4 May 2010 20:58:03 -0700 Subject: [PATCHv2 1/2] mtd: nand: Extend NAND flash detection to new MLC chips Message-Id: <10137ab89de6e6d229798d6f397688b0807024da@localhost.localdomain> In-Reply-To: <17c88de31cd52bb3794569c28cd2ae51996e6260@localhost.localdomain> References: <17c88de31cd52bb3794569c28cd2ae51996e6260@localhost.localdomain> To: User-Agent: vim 7.1 MIME-Version: 1.0 Content-Disposition: inline X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20100505_001354_664296_5BE131AD X-CRM114-Status: GOOD ( 14.54 ) X-Spam-Score: 2.5 (++) X-Spam-Report: SpamAssassin version 3.3.1 on bombadil.infradead.org summary: Content analysis details: (2.5 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 FREEMAIL_FROM Sender email is freemail (cernekee[at]gmail.com) 0.0 DKIM_ADSP_CUSTOM_MED No valid author signature, adsp_override is CUSTOM_MED 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS 1.2 NML_ADSP_CUSTOM_MED ADSP custom_med hit, and not from a mailing list Cc: linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org, Reuben.Dowle@navico.com X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-mtd-bounces@lists.infradead.org Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Some of the newer MLC devices have a 6-byte ID sequence in which several field definitions differ from older chips in a manner that is not backward compatible. For instance: Samsung K9GAG08U0M (5-byte sequence): ec d5 14 b6 74 4th byte, bits 1:0 encode the page size: 0=1KiB, 1=2KiB, 2=4KiB, 3=8KiB 4th byte, bits 5:4 encode the block size: 0=64KiB, 1=128KiB, ... 4th byte, bit 6 encodes the OOB size: 0=8B/512B, 1=16B/512B Samsung K9GAG08U0D (6-byte sequence): ec d5 94 29 34 41 4th byte, bits 1:0 encode the page size: 0=2KiB, 1=4KiB, 3=8KiB, 4=rsvd 4th byte, bits 7;5:4 encode the block size: 0=128KiB, 1=256KiB, ... 4th byte, bits 6;3:2 encode the OOB size: 1=128B/page, 2=218B/page This patch uses the new 6-byte scheme if the following conditions are all true: 1) The ID code wraps around after exactly 6 bytes 2) Manufacturer is Samsung 3) 6th byte is zero The patch also extends the maximum OOB size from 128B to 256B. Signed-off-by: Kevin Cernekee --- drivers/mtd/nand/nand_base.c | 64 ++++++++++++++++++++++++++++------------- include/linux/mtd/nand.h | 2 +- 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index b9dc65c..85891dc 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2774,8 +2774,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, int busw, int *maf_id, struct nand_flash_dev *type) { - int dev_id, maf_idx; - int tmp_id, tmp_manf; + int i, dev_id, maf_idx; + u8 id_data[8]; /* Select the device */ chip->select_chip(mtd, 0); @@ -2801,15 +2801,15 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); - /* Read manufacturer and device IDs */ + /* Read entire ID string */ - tmp_manf = chip->read_byte(mtd); - tmp_id = chip->read_byte(mtd); + for (i = 0; i < 8; i++) + id_data[i] = chip->read_byte(mtd); - if (tmp_manf != *maf_id || tmp_id != dev_id) { + if (id_data[0] != *maf_id || id_data[1] != dev_id) { printk(KERN_INFO "%s: second ID read did not match " "%02x,%02x against %02x,%02x\n", __func__, - *maf_id, dev_id, tmp_manf, tmp_id); + *maf_id, dev_id, id_data[0], id_data[1]); return ERR_PTR(-ENODEV); } @@ -2832,21 +2832,45 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, if (!type->pagesize) { int extid; /* The 3rd id byte holds MLC / multichip data */ - chip->cellinfo = chip->read_byte(mtd); + chip->cellinfo = id_data[2]; /* The 4th id byte is the important one */ - extid = chip->read_byte(mtd); - /* Calc pagesize */ - mtd->writesize = 1024 << (extid & 0x3); - extid >>= 2; - /* Calc oobsize */ - mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9); - extid >>= 2; - /* Calc blocksize. Blocksize is multiples of 64KiB */ - mtd->erasesize = (64 * 1024) << (extid & 0x03); - extid >>= 2; - /* Get buswidth information */ - busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; + extid = id_data[3]; + /* + * Field definitions are in the following datasheets: + * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) + * New style (6 byte ID): Samsung K9GAG08U0D (p.40) + * + * Check for wraparound + Samsung ID + nonzero 6th byte + * to decide what to do. + */ + if (id_data[0] == id_data[6] && id_data[1] == id_data[7] && + id_data[0] == NAND_MFR_SAMSUNG && + id_data[5] != 0x00) { + /* Calc pagesize */ + mtd->writesize = 2048 << (extid & 0x03); + extid >>= 2; + /* Calc oobsize */ + mtd->oobsize = (extid & 0x03) == 0x01 ? 128 : 218; + extid >>= 2; + /* Calc blocksize */ + mtd->erasesize = (128 * 1024) << + (((extid >> 1) & 0x04) | (extid & 0x03)); + busw = 0; + } else { + /* Calc pagesize */ + mtd->writesize = 1024 << (extid & 0x03); + extid >>= 2; + /* Calc oobsize */ + mtd->oobsize = (8 << (extid & 0x01)) * + (mtd->writesize >> 9); + extid >>= 2; + /* Calc blocksize. Blocksize is multiples of 64KiB */ + mtd->erasesize = (64 * 1024) << (extid & 0x03); + extid >>= 2; + /* Get buswidth information */ + busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; + } } else { /* * Old devices have chip data hardcoded in the device id table diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 8bdacb8..50f3aa0 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -53,7 +53,7 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); * is supported now. If you add a chip with bigger oobsize/page * adjust this accordingly. */ -#define NAND_MAX_OOBSIZE 128 +#define NAND_MAX_OOBSIZE 256 #define NAND_MAX_PAGESIZE 4096 /*