From patchwork Sat Nov 1 11:19:11 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Eric W. Biederman" X-Patchwork-Id: 6789 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 F38C3DDDDB for ; Sat, 1 Nov 2008 22:29:33 +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 1KwEdy-0000T0-6u; Sat, 01 Nov 2008 11:27:50 +0000 Received: from out01.mta.xmission.com ([166.70.13.231]) by bombadil.infradead.org with esmtp (Exim 4.68 #1 (Red Hat Linux)) id 1KwEb9-0008P5-RH for linux-mtd@lists.infradead.org; Sat, 01 Nov 2008 11:25:08 +0000 Received: from mx04.mta.xmission.com ([166.70.13.214]) by out01.mta.xmission.com with esmtp (Exim 4.62) (envelope-from ) id 1KwEbB-0004j1-JQ; Sat, 01 Nov 2008 05:24:57 -0600 Received: from c-24-130-11-59.hsd1.ca.comcast.net ([24.130.11.59] helo=frodo.ebiederm.org) by mx04.mta.xmission.com with esmtpsa (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.63) (envelope-from ) id 1KwEb7-0007R7-5A; Sat, 01 Nov 2008 05:24:53 -0600 Received: from frodo.ebiederm.org (localhost [127.0.0.1]) by frodo.ebiederm.org (8.14.1/8.14.1/Debian-9) with ESMTP id mA1BJCLY001185; Sat, 1 Nov 2008 04:19:12 -0700 Received: (from eric@localhost) by frodo.ebiederm.org (8.14.1/8.14.1/Submit) id mA1BJBo4001184; Sat, 1 Nov 2008 04:19:11 -0700 X-Authentication-Warning: frodo.ebiederm.org: eric set sender to ebiederm@xmission.com using -f From: ebiederm@xmission.com (Eric W. Biederman) To: David Woodhouse References: <20081029195349.imqvyxcajuoko0wo@imap.linux.ibm.com> <1225463927.16774.106.camel@macbook.infradead.org> <1225524813.16774.140.camel@macbook.infradead.org> <1225529384.16774.162.camel@macbook.infradead.org> Date: Sat, 01 Nov 2008 04:19:11 -0700 In-Reply-To: (Eric W. Biederman's message of "Sat, 01 Nov 2008 03:29:17 -0700") Message-ID: User-Agent: Gnus/5.110006 (No Gnus v0.6) Emacs/21.4 (gnu/linux) MIME-Version: 1.0 X-XM-SPF: eid=; ; ; mid=; ; ; hst=mx04.mta.xmission.com; ; ; ip=24.130.11.59; ; ; frm=ebiederm@xmission.com; ; ; spf=neutral X-SA-Exim-Connect-IP: 24.130.11.59 X-SA-Exim-Rcpt-To: dwmw2@infradead.org, jwboyer@gmail.com, linux-mtd@lists.infradead.org, cschultz@linux.vnet.ibm.com X-SA-Exim-Mail-From: ebiederm@xmission.com X-Spam-DCC: XMission; sa03 1397; Body=1 Fuz1=1 Fuz2=1 X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on sa03.xmission.com X-Spam-Level: X-Spam-Status: No, score=-4.4 required=8.0 tests=ALL_TRUSTED,BAYES_00, DCC_CHECK_NEGATIVE, T_TM2_M_HEADER_IN_MSG, XM_SPF_Neutral autolearn=disabled version=3.2.5 X-Spam-Combo: ;David Woodhouse X-Spam-Relay-Country: X-Spam-Report: * -1.8 ALL_TRUSTED Passed through trusted hosts only via SMTP * 0.0 T_TM2_M_HEADER_IN_MSG BODY: T_TM2_M_HEADER_IN_MSG * -2.6 BAYES_00 BODY: Bayesian spam probability is 0 to 1% * [score: 0.0000] * -0.0 DCC_CHECK_NEGATIVE Not listed in DCC * [sa03 1397; Body=1 Fuz1=1 Fuz2=1] * 0.0 XM_SPF_Neutral SPF-Neutral Subject: [PATCH] mtd: Fix cfi_send_gen_cmd the handling of x16 devices in x8 mode v4 X-SA-Exim-Version: 4.2.1 (built Thu, 07 Dec 2006 04:40:56 +0000) X-SA-Exim-Scanned: Yes (on mx04.mta.xmission.com) X-Bad-Reply: References and In-Reply-To but no 'Re:' in Subject. X-Spam-Score: -1.0 (-) X-Spam-Report: SpamAssassin version 3.2.5 on bombadil.infradead.org summary: Content analysis details: (-1.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -1.0 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [166.70.13.231 listed in list.dnswl.org] X-Mailman-Approved-At: Sat, 01 Nov 2008 07:27:48 -0400 Cc: jwboyer@gmail.com, linux-mtd@lists.infradead.org, Corinna Schultz 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 cfi_send_gen_cmd is only passed in the addresses: 0, 0x55, 0x2aa, 0x555 and the addresses addr_unlock1 and addr_unlock2 from jeded_probe. The address 0, 0x55, and 0x555 will not be effected by this patch. For 16bit devices in 8bit compatibility mode we need to use the byte address: 0xaaa and 0x555. Which effectively match the word address 0x555 and 0x2aa. Except the last has it's low byte set. We need to set the low bit to maintain the alternating bit sequence. Likewise the addresses in jedec_probe whose word address ends in the bits 10 also need their low bit set. So generically modify cfi_build_cmd_addr to extend alternating bit sequences in addresses. And every current cfi_send_gen_cmd that assumes cfi_cmd_set_0002 (i.e. uses addresses 0x2aa and 0x555) needs to be updated. v4: Fix stupid typo in cfi_build_cmd_addr that failed to compile I'm writing this patch way to late at night. v3: Bring all of the work back into cfi_build_cmd_addr including calling of map_bankwidth(map) and cfi_interleave(cfi) So every caller doesn't need to. v2: Only modified the address if we our device_type is larger than our bus width. Signed-off-by: Eric W. Biederman --- drivers/mtd/chips/cfi_cmdset_0002.c | 13 ------------- drivers/mtd/chips/jedec_probe.c | 10 ++++------ include/linux/mtd/cfi.h | 22 +++++++++++++++++++--- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index a972cc6..9e7a236 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -362,19 +362,6 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) /* Set the default CFI lock/unlock addresses */ cfi->addr_unlock1 = 0x555; cfi->addr_unlock2 = 0x2aa; - /* Modify the unlock address if we are in compatibility mode */ - if ( /* x16 in x8 mode */ - ((cfi->device_type == CFI_DEVICETYPE_X8) && - (cfi->cfiq->InterfaceDesc == - CFI_INTERFACE_X8_BY_X16_ASYNC)) || - /* x32 in x16 mode */ - ((cfi->device_type == CFI_DEVICETYPE_X16) && - (cfi->cfiq->InterfaceDesc == - CFI_INTERFACE_X16_BY_X32_ASYNC))) - { - cfi->addr_unlock1 = 0xaaa; - cfi->addr_unlock2 = 0x555; - } } /* CFI mode */ else if (cfi->cfi_mode == CFI_MODE_JEDEC) { diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index f84ab61..2f3f2f7 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c @@ -1808,9 +1808,7 @@ static inline u32 jedec_read_mfr(struct map_info *map, uint32_t base, * several first banks can contain 0x7f instead of actual ID */ do { - uint32_t ofs = cfi_build_cmd_addr(0 + (bank << 8), - cfi_interleave(cfi), - cfi->device_type); + uint32_t ofs = cfi_build_cmd_addr(0 + (bank << 8), map, cfi); mask = (1 << (cfi->device_type * 8)) - 1; result = map_read(map, base + ofs); bank++; @@ -1824,7 +1822,7 @@ static inline u32 jedec_read_id(struct map_info *map, uint32_t base, { map_word result; unsigned long mask; - u32 ofs = cfi_build_cmd_addr(1, cfi_interleave(cfi), cfi->device_type); + u32 ofs = cfi_build_cmd_addr(1, map, cfi); mask = (1 << (cfi->device_type * 8)) -1; result = map_read(map, base + ofs); return result.x[0] & mask; @@ -2067,8 +2065,8 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, } /* Ensure the unlock addresses we try stay inside the map */ - probe_offset1 = cfi_build_cmd_addr(cfi->addr_unlock1, cfi_interleave(cfi), cfi->device_type); - probe_offset2 = cfi_build_cmd_addr(cfi->addr_unlock2, cfi_interleave(cfi), cfi->device_type); + probe_offset1 = cfi_build_cmd_addr(cfi->addr_unlock1, map, cfi); + probe_offset2 = cfi_build_cmd_addr(cfi->addr_unlock2, map, cfi); if ( ((base + probe_offset1 + map_bankwidth(map)) >= map->size) || ((base + probe_offset2 + map_bankwidth(map)) >= map->size)) goto retry; diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index d6fb115..52d2e11 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -281,9 +281,25 @@ struct cfi_private { /* * Returns the command address according to the given geometry. */ -static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, int interleave, int type) +static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, + struct map_info *map, struct cfi_private *cfi) { - return (cmd_ofs * type) * interleave; + unsigned bankwidth = map_bankwidth(map); + unsigned interleave = cfi_interleave(cfi); + unsigned type = cfi->device_type; + uint32_t addr; + + addr = (cmd_ofs * type) * interleave; + + /* Modify the unlock address if we are in compatiblity mode. + * For 16bit devices on 8 bit busses + * and 32bit devices on 16 bit busses + * set the low bit of the alternating bit sequence of the address. + */ + if (((type * interleave) > bankwidth) && (cmd_ofs & 2)) + addr |= (type >> 1)*interleave; + + return addr; } /* @@ -429,7 +445,7 @@ static inline uint32_t cfi_send_gen_cmd(u_char cmd, uint32_t cmd_addr, uint32_t int type, map_word *prev_val) { map_word val; - uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, cfi_interleave(cfi), type); + uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, map, cfi); val = cfi_build_cmd(cmd, map, cfi);