From patchwork Tue Dec 16 20:56:50 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Singer X-Patchwork-Id: 14352 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@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 29155DDEF5 for ; Wed, 17 Dec 2008 07:58:17 +1100 (EST) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.68 #1 (Red Hat Linux)) id 1LCgyJ-0005x0-8k; Tue, 16 Dec 2008 20:56:51 +0000 Received: from henry.synapsedev.com ([66.147.194.230] helo=henry.synapse.com) by bombadil.infradead.org with esmtps (Exim 4.68 #1 (Red Hat Linux)) id 1LCgyG-0005wv-SS for linux-mtd@lists.infradead.org; Tue, 16 Dec 2008 20:56:49 +0000 Received: from friendly.synapse.com (localhost.localdomain [127.0.0.1]) by henry.synapse.com (Postfix) with ESMTP id 0B0A5D2C1CF for ; Tue, 16 Dec 2008 12:56:48 -0800 (PST) Received: from friendly.synapse.com ([10.75.6.19] helo=friendly.synapse.com) by ASSP.nospam; 16 Dec 2008 12:56:48 -0800 Received: from zealous.synapse.com ([10.75.2.7]) by friendly.synapse.com with smtp (Exim 4.69) (envelope-from ) id 1LCgyF-0006Uo-0X for linux-mtd@lists.infradead.org; Tue, 16 Dec 2008 12:56:48 -0800 Received: by zealous.synapse.com (sSMTP sendmail emulation); Tue, 16 Dec 2008 12:56:50 -0800 From: "Marc Singer" Date: Tue, 16 Dec 2008 12:56:50 -0800 To: linux-mtd@lists.infradead.org Subject: [PATCH] Revised the detection for broken boot-region detection. MACRONIX parts have a custom implementation of the fixup. AMD implemtation restore to original version that has worked fine since 2001. Message-ID: <20081216205650.GA13729@zealous.synapse.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.18 (2008-05-17) X-Spam-Score: 0.0 (/) X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.9 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 Signed-off-by: Marc Singer --- drivers/mtd/chips/cfi_cmdset_0002.c | 96 ++++++++++++++++++++++------------- 1 files changed, 60 insertions(+), 36 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index d74ec46..4f1b445 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -136,7 +136,21 @@ static void cfi_tell_features(struct cfi_pri_amdstd *extp) #endif #ifdef AMD_BOOTLOC_BUG -/* Wheee. Bring me the head of someone at AMD. */ +/* Wheee. Bring me the head of someone at AMD, + and another from Macronix...just for good measure. */ + +/* Some early AMD NOR flash parts (AM29LV160D, e.g.) and much + * more recent and inexcusably broken Macronix parts, do not + * accurately report whether or not the device is top-boot or + * bottom-boot in the CFI PRI data. This detail is important + * to correctly sort the erase region information. So, for + * CFI versions < 1.1 where we do not trust the veracity of + * the CFI PRI data, we look for explicit manufacturer/device + * IDs when we know them or for the high bit of the device ID. + * The latter test has been working reliably since 2001 even + * though we don't have documentation to support this as a + * convention. */ + static void fixup_amd_bootblock(struct mtd_info *mtd, void* param) { struct map_info *map = mtd->priv; @@ -148,43 +162,53 @@ static void fixup_amd_bootblock(struct mtd_info *mtd, void* param) if (((major << 8) | minor) < 0x3131) { /* CFI version 1.0 => don't trust bootloc */ + extp->TopBottom = (cfi->id & 0x80) + ? 3 /* top-boot */ + : 2 /* bottom-boot */; + DEBUG(MTD_DEBUG_LEVEL1, - "%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n", - map->name, cfi->mfr, cfi->id); + "%s: CFI PRI V%c.%c has no boot block field;" + " deduced %s from Mfr/Device ID %0x/%0x\n", + map->name, major, minor, + extp->TopBottom == 2 ? "bottom" : "top", + cfi->mfr, cfi->id); + } +} - /* AFAICS all 29LV400 with a bottom boot block have a device ID - * of 0x22BA in 16-bit mode and 0xBA in 8-bit mode. - * These were badly detected as they have the 0x80 bit set - * so treat them as a special case. - */ - if (((cfi->id == 0xBA) || (cfi->id == 0x22BA)) && - - /* Macronix added CFI to their 2nd generation - * MX29LV400C B/T but AFAICS no other 29LV400 (AMD, - * Fujitsu, Spansion, EON, ESI and older Macronix) - * has CFI. - * - * Therefore also check the manufacturer. - * This reduces the risk of false detection due to - * the 8-bit device ID. - */ - (cfi->mfr == MANUFACTURER_MACRONIX)) { - DEBUG(MTD_DEBUG_LEVEL1, - "%s: Macronix MX29LV400C with bottom boot block" - " detected\n", map->name); - extp->TopBottom = 2; /* bottom boot */ - } else - if (cfi->id & 0x80) { - printk(KERN_WARNING "%s: JEDEC Device ID is 0x%02X. Assuming broken CFI table.\n", map->name, cfi->id); - extp->TopBottom = 3; /* top boot */ - } else { - extp->TopBottom = 2; /* bottom boot */ - } +static void fixup_macronix_bootblock(struct mtd_info *mtd, void* param) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + struct cfi_pri_amdstd *extp = cfi->cmdset_priv; + __u8 major = extp->MajorVersion; + __u8 minor = extp->MinorVersion; + + if (((major << 8) | minor) < 0x3131) { + /* CFI version 1.0 => don't trust bootloc */ + switch (cfi->id) { + /* Macronix MX29LV400CT */ + case 0x00ba: + case 0x22ba: + extp->TopBottom = 2; /* bottom-boot */ + break; + /* Macronix MX29LV400CB */ + case 0x00b9: + case 0x22b9: + extp->TopBottom = 3; /* top-boot */ + break; + default: + /* Fall back is to assume we have + * bottom-boot. */ + extp->TopBottom = 2; /* bottom-boot */ + break; + } DEBUG(MTD_DEBUG_LEVEL1, - "%s: AMD CFI PRI V%c.%c has no boot block field;" - " deduced %s from Device ID\n", map->name, major, minor, - extp->TopBottom == 2 ? "bottom" : "top"); + "%s: CFI PRI V%c.%c has no boot block field;" + " deduced %s from Mfr/Device ID %0x/%0x\n", + map->name, major, minor, + extp->TopBottom == 2 ? "bottom" : "top", + cfi->mfr, cfi->id); } } #endif @@ -286,7 +310,7 @@ static struct cfi_fixup cfi_fixup_table[] = { { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL }, #ifdef AMD_BOOTLOC_BUG { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL }, - { MANUFACTURER_MACRONIX, CFI_ID_ANY, fixup_amd_bootblock, NULL }, + { MANUFACTURER_MACRONIX, CFI_ID_ANY, fixup_macronix_bootblock, NULL }, #endif { CFI_MFR_AMD, 0x0050, fixup_use_secsi, NULL, }, { CFI_MFR_AMD, 0x0053, fixup_use_secsi, NULL, },