From patchwork Fri Jun 18 05:38:03 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haojian Zhuang X-Patchwork-Id: 56133 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 0F3EA1007DE for ; Fri, 18 Jun 2010 15:48:21 +1000 (EST) Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.72 #1 (Red Hat Linux)) id 1OPUPR-0005PE-88; Fri, 18 Jun 2010 05:46:33 +0000 Received: from mail-pw0-f49.google.com ([209.85.160.49]) by bombadil.infradead.org with esmtp (Exim 4.72 #1 (Red Hat Linux)) id 1OPUHE-0002CW-Py; Fri, 18 Jun 2010 05:38:06 +0000 Received: by pwj6 with SMTP id 6so355188pwj.36 for ; Thu, 17 Jun 2010 22:38:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:received:date:message-id :subject:from:to:content-type; bh=dPApYTF4+iOi3n936nDLXTT2MwP3D87fk3R7Nk1zWWc=; b=qSwk+TJReE4rKGxwVdaDZQnl2uzf8MEzc8P4eYUVtBj5Ln4YCmoTYjAjcpwxCPGiF1 0bjA0J5iW2XkxscCGq9s3sweJthYPv7YyRKblnAw45h/AQ7YJd50ngY0rw5FAwROxvk3 YwrGxSg6fpzjrzkK1lei1ktKmWKng0RYIT7CU= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; b=i03crp5pekg1HAFNzU55s3BDr99kmuC1O9V/+Xc5EAk13i8n37ZFjkEO4C7eLXtSeT eW0vJ3pnG4CirQ1bDwAlE4b5G2FNs2rHY4VHV2UrtbO6477xZGWio/4kVeO065cZRkEb PfAEEKrCNsfIi/rZi2KoIpqnrJTo9WB4+lj8Q= MIME-Version: 1.0 Received: by 10.143.178.6 with SMTP id f6mr365122wfp.342.1276839483855; Thu, 17 Jun 2010 22:38:03 -0700 (PDT) Received: by 10.142.114.3 with HTTP; Thu, 17 Jun 2010 22:38:03 -0700 (PDT) Date: Fri, 18 Jun 2010 13:38:03 +0800 Message-ID: Subject: [PATCH 24/25] pxa3xx_nand: fix write oob bug From: Haojian Zhuang To: Marc Kleine-Budde , David Woodhouse , David Woodhouse , linux-mtd@lists.infradead.org, Eric Miao , linux-arm-kernel X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20100618_013805_648047_A0F2B959 X-CRM114-Status: GOOD ( 20.48 ) X-Spam-Score: -0.1 (/) X-Spam-Report: SpamAssassin version 3.3.1 on bombadil.infradead.org summary: Content analysis details: (-0.1 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.160.49 listed in list.dnswl.org] 0.0 FREEMAIL_FROM Sender email is freemail (haojian.zhuang[at]gmail.com) -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 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 From 9a73b885f3ab4d1bf92da847aefbfa30c75cf292 Mon Sep 17 00:00:00 2001 From: Lei Wen Date: Wed, 9 Jun 2010 16:55:14 +0800 Subject: [PATCH 24/25] pxa3xx_nand: fix write oob bug For column addressing is only used to subpage and oob operation, and the fact that our controller is performing poor at such two operations, disable the column addressing in writing the ndcb1. If not add this patch, write_oob function would fail. Signed-off-by: Lei Wen --- drivers/mtd/nand/pxa3xx_nand.c | 42 +++++++++++++++++++++++++++++++-------- 1 files changed, 33 insertions(+), 9 deletions(-) #define NDTR0_tADL(c) (min_t(uint32_t, (c), 31) << 27) @@ -599,13 +613,19 @@ static void start_data_dma(struct pxa3xx_nand *nand, int dir_out) desc_oob->ddadr = desc->ddadr = DDADR_STOP; desc_oob->dcmd = desc->dcmd = DCMD_WIDTH4 | DCMD_BURST32; if (dir_out) { + if (nand->oob_size > 0) { + desc_oob->dsadr = nand->dma_buff_phys + info->page_size + nand->oob_column; + desc_oob->dcmd |= DCMD_ENDIRQEN | DCMD_INCSRCADDR | DCMD_FLOWTRG | oob_len; + desc->ddadr = nand->dma_desc_addr + sizeof(struct pxa_dma_desc); + desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG | data_len; + } + else + desc->dcmd |= DCMD_ENDIRQEN | DCMD_INCSRCADDR | DCMD_FLOWTRG | data_len; desc->dsadr = nand->dma_buff_phys + nand->data_column; - desc->dtadr = nand->mmio_phys + NDDB; - desc->dcmd |= DCMD_ENDIRQEN | DCMD_INCSRCADDR | DCMD_FLOWTRG | (data_len + oob_len); + desc_oob->dtadr = desc->dtadr = nand->mmio_phys + NDDB; } else { if (nand->oob_size > 0) { - desc_oob->dtadr = nand->dma_buff_phys - + info->page_size + nand->oob_column; + desc_oob->dtadr = nand->dma_buff_phys + info->page_size + nand->oob_column; desc_oob->dcmd |= DCMD_ENDIRQEN | DCMD_INCTRGADDR | DCMD_FLOWSRC | oob_len; desc->ddadr = nand->dma_desc_addr + sizeof(struct pxa_dma_desc); desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC | data_len; @@ -766,11 +786,13 @@ static int prepare_command_pool(struct pxa3xx_nand *nand, int command, uint16_t cmd; int addr_cycle, exec_cmd, ndcb0, i, chunks = 0; struct mtd_info *mtd; + struct nand_chip *chip; struct pxa3xx_nand_info *info = nand->info[nand->chip_select]; struct platform_device *pdev = nand->pdev; struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; mtd = get_mtd_by_info(info); + chip = mtd->priv; ndcb0 = (nand->chip_select) ? NDCB0_CSEL : 0;; addr_cycle = 0; exec_cmd = 1; @@ -825,11 +847,9 @@ static int prepare_command_pool(struct pxa3xx_nand *nand, int command, info->page_addr = page_addr; /* small page addr setting */ if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) - nand->ndcb1[0] = ((page_addr & 0xFFFFFF) << 8) - | (column & 0xFF); + nand->ndcb1[0] = ((page_addr & 0xFFFFFF) << 8); else { - nand->ndcb1[0] = ((page_addr & 0xFFFF) << 16) - | (column & 0xFFFF); + nand->ndcb1[0] = ((page_addr & 0xFFFF) << 16); if (page_addr & 0xFF0000) nand->ndcb2 = (page_addr & 0xFF0000) >> 16; @@ -892,7 +912,9 @@ static int prepare_command_pool(struct pxa3xx_nand *nand, int command, break; case NAND_CMD_PAGEPROG: - if (is_buf_blank(nand->data_buff, (mtd->writesize + mtd->oobsize))) { + if (is_buf_blank(nand->data_buff, mtd->writesize) && + is_buf_blank(nand->oob_buff + chip->ecc.layout->oobfree[0].offset, + chip->ecc.layout->oobfree[0].length)) { exec_cmd = 0; break; } @@ -1394,6 +1416,8 @@ static int __devinit pxa3xx_nand_scan(struct mtd_info *mtd) } pxa3xx_nand_config_flash(info, f); + if (f->page_size == 4096 && f->ecc_strength == 4) + chip->ecc.layout = &nand_oob_128_BCH; pxa3xx_flash_ids[0].name = f->name; pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff; pxa3xx_flash_ids[0].pagesize = f->page_size; diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 99f4088..96b46e1 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -314,6 +314,20 @@ static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { { "256MiB 16-bit", 0xba20, 0xffff, 64, 2048, 16, 16, 1, 2048, &timing[3], }, }; +static struct nand_ecclayout nand_oob_128_BCH = { + .eccbytes = 64, + .eccpos = { + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127}, + .oobfree = { + {.offset = 2, + .length = 62}} +}; + static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL};