From patchwork Wed Mar 22 14:07:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 95778 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp263007qgd; Wed, 22 Mar 2017 07:21:29 -0700 (PDT) X-Received: by 10.84.175.132 with SMTP id t4mr29939193plb.38.1490192489150; Wed, 22 Mar 2017 07:21:29 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y23si2010433pge.8.2017.03.22.07.21.28; Wed, 22 Mar 2017 07:21:29 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@nifty.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935031AbdCVOVU (ORCPT + 11 others); Wed, 22 Mar 2017 10:21:20 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:47146 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1759745AbdCVOLH (ORCPT ); Wed, 22 Mar 2017 10:11:07 -0400 Received: from pug.jp.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2ME8LDP010154; Wed, 22 Mar 2017 23:08:30 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2ME8LDP010154 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490191712; bh=sYMvXOoGOJZ8hbnok9r9LRTppg6Zo/oq3jVDyyalZI8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eIWy3jm89pB8dEf5+oFQ6Gw+rZYa5TFejZPznemkkNHIys2aPj10wzTT5CSEUDWNt xvQ7boL+MaDVqMTiOrwYbv6Ee0paJfPzBDQr+Uw+FwXzAtsVfZHd1SsYZ3o7nkE7/D gkG2IvyUbpsJJr2bQY67WmoC60a2OeaT+Lw/VXRmHX2YSwIMvkgbAdhMmM/C87glhn IVSDZFWRY4AqS9llfFIneyGXvq95zbFfe+DPFSMUpMksZqH3muKfXltJX3WfiaUGfH mJIPWPiEzdkJkdbKrcUk8ifjrIM5bOvrPXQSA4t9TXcynApuzYz2GwvyQDIXbjWhkj AU7J4VdWX4aFw== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: laurent.monat@idquantique.com, thorsten.christiansson@idquantique.com, Enrico Jorns , Jason Roberts , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Brian Norris , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Richard Weinberger , Cyrille Pitchen Subject: [PATCH v2 06/53] mtd: nand: denali: fix comment of denali_nand_info::flash_mem Date: Wed, 22 Mar 2017 23:07:13 +0900 Message-Id: <1490191680-14481-7-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490191680-14481-1-git-send-email-yamada.masahiro@socionext.com> References: <1490191680-14481-1-git-send-email-yamada.masahiro@socionext.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The same comment "Mapped io reg base address" for flash_reg and flash_mem probably due to the mistake of copy-paste work. Of course, the latter is not the register base address. Reword the comments using the terminology in the Denali User's Guide. Signed-off-by: Masahiro Yamada --- Changes in v2: None drivers/mtd/nand/denali.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 6573ea5..403a7c8 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -351,8 +351,8 @@ struct denali_nand_info { struct device *dev; int total_used_banks; uint16_t page; - void __iomem *flash_reg; /* Mapped io reg base address */ - void __iomem *flash_mem; /* Mapped io reg base address */ + void __iomem *flash_reg; /* Register Interface */ + void __iomem *flash_mem; /* Host Data/Command Interface */ /* elements used by ISR */ struct completion complete; From patchwork Wed Mar 22 14:07:14 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 95768 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp258353qgd; Wed, 22 Mar 2017 07:11:59 -0700 (PDT) X-Received: by 10.99.166.17 with SMTP id t17mr44803413pge.196.1490191919623; Wed, 22 Mar 2017 07:11:59 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d10si1986344pgf.3.2017.03.22.07.11.59; Wed, 22 Mar 2017 07:11:59 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@nifty.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934828AbdCVOLt (ORCPT + 11 others); Wed, 22 Mar 2017 10:11:49 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:46883 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934355AbdCVOK6 (ORCPT ); Wed, 22 Mar 2017 10:10:58 -0400 Received: from pug.jp.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2ME8LDQ010154; Wed, 22 Mar 2017 23:08:32 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2ME8LDQ010154 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490191713; bh=yDhaih8HScIkQBmryb+HebglCf4qFlW3Sd8/pEb9UCg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VRJOrop0aFftlExFFLYyxpSZV80kN6TN3HN4elCArF/wRjrXnpSrZ/hzS5I4Dlh5A iANVeaoA/sX+iMtE6YKGlJT7hoPrfMt41GWYl1YuuvGgz9qzSdsyfJ+GKNiPvfKwoy Jv+fzuzCyFIvQileY1BdbrpLTZS1SdGJypmY63OhoubNrQWjS5X4JaLacKevbRUEYT i1lGCKIjIjZXAl78dXNfCe0HzPDT3ixaNpNYTGYXyGWNqVe7U5K+Nl4AQo+gy8UohL gUnvQvsCAohTBW7lEL12g6HTz2qz54zfZU07SVtR7Bg6CCk6CNbvIheJTIa9XTtFXf X/x/sCdiXdNOA== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: laurent.monat@idquantique.com, thorsten.christiansson@idquantique.com, Enrico Jorns , Jason Roberts , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Brian Norris , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Richard Weinberger , Cyrille Pitchen Subject: [PATCH v2 07/53] mtd: nand: denali: consolidate INTR_STATUS__* and INTR_EN__* macros Date: Wed, 22 Mar 2017 23:07:14 +0900 Message-Id: <1490191680-14481-8-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490191680-14481-1-git-send-email-yamada.masahiro@socionext.com> References: <1490191680-14481-1-git-send-email-yamada.masahiro@socionext.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The interrupts are enabled by INTR_EN register, then asserted interrupts can be observed via INTR_STATUS register. The bit fields are identical between INTR_EN and INTR_STATUS, so we can merge the bit field macros. Likewise for DATA_INTR. Signed-off-by: Masahiro Yamada --- Changes in v2: - Newly added drivers/mtd/nand/denali.c | 56 ++++++++++++++++++++----------------------- drivers/mtd/nand/denali.h | 61 ++++++++++++++--------------------------------- 2 files changed, 44 insertions(+), 73 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index c9806e6..2c59eb3 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -45,16 +45,16 @@ MODULE_PARM_DESC(onfi_timing_mode, * We define a macro here that combines all interrupts this driver uses into * a single constant value, for convenience. */ -#define DENALI_IRQ_ALL (INTR_STATUS__DMA_CMD_COMP | \ - INTR_STATUS__ECC_TRANSACTION_DONE | \ - INTR_STATUS__ECC_ERR | \ - INTR_STATUS__PROGRAM_FAIL | \ - INTR_STATUS__LOAD_COMP | \ - INTR_STATUS__PROGRAM_COMP | \ - INTR_STATUS__TIME_OUT | \ - INTR_STATUS__ERASE_FAIL | \ - INTR_STATUS__RST_COMP | \ - INTR_STATUS__ERASE_COMP) +#define DENALI_IRQ_ALL (INTR__DMA_CMD_COMP | \ + INTR__ECC_TRANSACTION_DONE | \ + INTR__ECC_ERR | \ + INTR__PROGRAM_FAIL | \ + INTR__LOAD_COMP | \ + INTR__PROGRAM_COMP | \ + INTR__TIME_OUT | \ + INTR__ERASE_FAIL | \ + INTR__RST_COMP | \ + INTR__ERASE_COMP) /* * indicates whether or not the internal value for the flash bank is @@ -159,7 +159,7 @@ static void read_status(struct denali_nand_info *denali) static void reset_bank(struct denali_nand_info *denali) { uint32_t irq_status; - uint32_t irq_mask = INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT; + uint32_t irq_mask = INTR__RST_COMP | INTR__TIME_OUT; clear_interrupts(denali); @@ -167,7 +167,7 @@ static void reset_bank(struct denali_nand_info *denali) irq_status = wait_for_irq(denali, irq_mask); - if (irq_status & INTR_STATUS__TIME_OUT) + if (irq_status & INTR__TIME_OUT) dev_err(denali->dev, "reset bank failed.\n"); } @@ -177,22 +177,22 @@ static uint16_t denali_nand_reset(struct denali_nand_info *denali) int i; for (i = 0; i < denali->max_banks; i++) - iowrite32(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT, + iowrite32(INTR__RST_COMP | INTR__TIME_OUT, denali->flash_reg + INTR_STATUS(i)); for (i = 0; i < denali->max_banks; i++) { iowrite32(1 << i, denali->flash_reg + DEVICE_RESET); while (!(ioread32(denali->flash_reg + INTR_STATUS(i)) & - (INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT))) + (INTR__RST_COMP | INTR__TIME_OUT))) cpu_relax(); if (ioread32(denali->flash_reg + INTR_STATUS(i)) & - INTR_STATUS__TIME_OUT) + INTR__TIME_OUT) dev_dbg(denali->dev, "NAND Reset operation timed out on bank %d\n", i); } for (i = 0; i < denali->max_banks; i++) - iowrite32(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT, + iowrite32(INTR__RST_COMP | INTR__TIME_OUT, denali->flash_reg + INTR_STATUS(i)); return PASS; @@ -716,7 +716,7 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali, uint32_t addr, cmd, irq_status, irq_mask; if (op == DENALI_READ) - irq_mask = INTR_STATUS__LOAD_COMP; + irq_mask = INTR__LOAD_COMP; else if (op == DENALI_WRITE) irq_mask = 0; else @@ -823,8 +823,7 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) { struct denali_nand_info *denali = mtd_to_denali(mtd); uint32_t irq_status; - uint32_t irq_mask = INTR_STATUS__PROGRAM_COMP | - INTR_STATUS__PROGRAM_FAIL; + uint32_t irq_mask = INTR__PROGRAM_COMP | INTR__PROGRAM_FAIL; int status = 0; denali->page = page; @@ -851,7 +850,7 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) { struct denali_nand_info *denali = mtd_to_denali(mtd); - uint32_t irq_mask = INTR_STATUS__LOAD_COMP; + uint32_t irq_mask = INTR__LOAD_COMP; uint32_t irq_status, addr, cmd; denali->page = page; @@ -912,7 +911,7 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, bool check_erased_page = false; unsigned int bitflips = 0; - if (irq_status & INTR_STATUS__ECC_ERR) { + if (irq_status & INTR__ECC_ERR) { /* read the ECC errors. we'll ignore them for now */ uint32_t err_address, err_correction_info, err_byte, err_sector, err_device, err_correction_value; @@ -969,7 +968,7 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, * for a while for this interrupt */ while (!(read_interrupt_status(denali) & - INTR_STATUS__ECC_TRANSACTION_DONE)) + INTR__ECC_TRANSACTION_DONE)) cpu_relax(); clear_interrupts(denali); denali_set_intr_modes(denali, true); @@ -1020,8 +1019,7 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *chip, dma_addr_t addr = denali->buf.dma_buf; size_t size = mtd->writesize + mtd->oobsize; uint32_t irq_status; - uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP | - INTR_STATUS__PROGRAM_FAIL; + uint32_t irq_mask = INTR__DMA_CMD_COMP | INTR__PROGRAM_FAIL; /* * if it is a raw xfer, we want to disable ecc and send the spare area. @@ -1119,8 +1117,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, size_t size = mtd->writesize + mtd->oobsize; uint32_t irq_status; - uint32_t irq_mask = INTR_STATUS__ECC_TRANSACTION_DONE | - INTR_STATUS__ECC_ERR; + uint32_t irq_mask = INTR__ECC_TRANSACTION_DONE | INTR__ECC_ERR; bool check_erased_page = false; if (page != denali->page) { @@ -1168,7 +1165,7 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, struct denali_nand_info *denali = mtd_to_denali(mtd); dma_addr_t addr = denali->buf.dma_buf; size_t size = mtd->writesize + mtd->oobsize; - uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP; + uint32_t irq_mask = INTR__DMA_CMD_COMP; if (page != denali->page) { dev_err(denali->dev, @@ -1241,10 +1238,9 @@ static int denali_erase(struct mtd_info *mtd, int page) index_addr(denali, cmd, 0x1); /* wait for erase to complete or failure to occur */ - irq_status = wait_for_irq(denali, INTR_STATUS__ERASE_COMP | - INTR_STATUS__ERASE_FAIL); + irq_status = wait_for_irq(denali, INTR__ERASE_COMP | INTR__ERASE_FAIL); - return irq_status & INTR_STATUS__ERASE_FAIL ? NAND_STATUS_FAIL : PASS; + return irq_status & INTR__ERASE_FAIL ? NAND_STATUS_FAIL : PASS; } static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 403a7c8..8df2285 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -218,40 +218,22 @@ #define INTR_STATUS(__bank) (0x410 + ((__bank) * 0x50)) #define INTR_EN(__bank) (0x420 + ((__bank) * 0x50)) - -#define INTR_STATUS__ECC_TRANSACTION_DONE 0x0001 -#define INTR_STATUS__ECC_ERR 0x0002 -#define INTR_STATUS__DMA_CMD_COMP 0x0004 -#define INTR_STATUS__TIME_OUT 0x0008 -#define INTR_STATUS__PROGRAM_FAIL 0x0010 -#define INTR_STATUS__ERASE_FAIL 0x0020 -#define INTR_STATUS__LOAD_COMP 0x0040 -#define INTR_STATUS__PROGRAM_COMP 0x0080 -#define INTR_STATUS__ERASE_COMP 0x0100 -#define INTR_STATUS__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_STATUS__LOCKED_BLK 0x0400 -#define INTR_STATUS__UNSUP_CMD 0x0800 -#define INTR_STATUS__INT_ACT 0x1000 -#define INTR_STATUS__RST_COMP 0x2000 -#define INTR_STATUS__PIPE_CMD_ERR 0x4000 -#define INTR_STATUS__PAGE_XFER_INC 0x8000 - -#define INTR_EN__ECC_TRANSACTION_DONE 0x0001 -#define INTR_EN__ECC_ERR 0x0002 -#define INTR_EN__DMA_CMD_COMP 0x0004 -#define INTR_EN__TIME_OUT 0x0008 -#define INTR_EN__PROGRAM_FAIL 0x0010 -#define INTR_EN__ERASE_FAIL 0x0020 -#define INTR_EN__LOAD_COMP 0x0040 -#define INTR_EN__PROGRAM_COMP 0x0080 -#define INTR_EN__ERASE_COMP 0x0100 -#define INTR_EN__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_EN__LOCKED_BLK 0x0400 -#define INTR_EN__UNSUP_CMD 0x0800 -#define INTR_EN__INT_ACT 0x1000 -#define INTR_EN__RST_COMP 0x2000 -#define INTR_EN__PIPE_CMD_ERR 0x4000 -#define INTR_EN__PAGE_XFER_INC 0x8000 +#define INTR__ECC_TRANSACTION_DONE 0x0001 +#define INTR__ECC_ERR 0x0002 +#define INTR__DMA_CMD_COMP 0x0004 +#define INTR__TIME_OUT 0x0008 +#define INTR__PROGRAM_FAIL 0x0010 +#define INTR__ERASE_FAIL 0x0020 +#define INTR__LOAD_COMP 0x0040 +#define INTR__PROGRAM_COMP 0x0080 +#define INTR__ERASE_COMP 0x0100 +#define INTR__PIPE_CPYBCK_CMD_COMP 0x0200 +#define INTR__LOCKED_BLK 0x0400 +#define INTR__UNSUP_CMD 0x0800 +#define INTR__INT_ACT 0x1000 +#define INTR__RST_COMP 0x2000 +#define INTR__PIPE_CMD_ERR 0x4000 +#define INTR__PAGE_XFER_INC 0x8000 #define PAGE_CNT(__bank) (0x430 + ((__bank) * 0x50)) #define ERR_PAGE_ADDR(__bank) (0x440 + ((__bank) * 0x50)) @@ -284,20 +266,13 @@ #define IGNORE_ECC_DONE__FLAG 0x0001 #define DMA_INTR 0x720 +#define DMA_INTR_EN 0x730 #define DMA_INTR__TARGET_ERROR 0x0001 #define DMA_INTR__DESC_COMP_CHANNEL0 0x0002 #define DMA_INTR__DESC_COMP_CHANNEL1 0x0004 #define DMA_INTR__DESC_COMP_CHANNEL2 0x0008 #define DMA_INTR__DESC_COMP_CHANNEL3 0x0010 -#define DMA_INTR__MEMCOPY_DESC_COMP 0x0020 - -#define DMA_INTR_EN 0x730 -#define DMA_INTR_EN__TARGET_ERROR 0x0001 -#define DMA_INTR_EN__DESC_COMP_CHANNEL0 0x0002 -#define DMA_INTR_EN__DESC_COMP_CHANNEL1 0x0004 -#define DMA_INTR_EN__DESC_COMP_CHANNEL2 0x0008 -#define DMA_INTR_EN__DESC_COMP_CHANNEL3 0x0010 -#define DMA_INTR_EN__MEMCOPY_DESC_COMP 0x0020 +#define DMA_INTR__MEMCOPY_DESC_COMP 0x0020 #define TARGET_ERR_ADDR_LO 0x740 #define TARGET_ERR_ADDR_LO__VALUE 0xffff From patchwork Wed Mar 22 14:07:15 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 95765 Delivered-To: patch@linaro.org Received: by 10.182.3.34 with SMTP id 2csp233643obz; Wed, 22 Mar 2017 07:11:35 -0700 (PDT) X-Received: by 10.99.121.195 with SMTP id u186mr43820588pgc.96.1490191895482; Wed, 22 Mar 2017 07:11:35 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 33si1978287plk.81.2017.03.22.07.11.35; Wed, 22 Mar 2017 07:11:35 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@nifty.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934506AbdCVOL3 (ORCPT + 11 others); Wed, 22 Mar 2017 10:11:29 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:46850 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934334AbdCVOK5 (ORCPT ); Wed, 22 Mar 2017 10:10:57 -0400 Received: from pug.jp.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2ME8LDR010154; Wed, 22 Mar 2017 23:08:34 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2ME8LDR010154 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490191715; bh=jriKrUNelDflGN2Y8S4wdpmJl8Y2pz1fU4VdZEfL4c0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tg5j7LFtR+y6K5ZyM/JeMlC7Exzj6x/7xmJ6w/pkcEqp/DllpY0yk+WkyxmOaoguv ae12ZXtmIfm8vXRE8JQNPj+R4bbJUbMJbTm72vYnUgRVir3vkEIOIfOgzNmOYTez9L PQdL6Nop1WZZlMmf+AHaJwXWG2SYmGh8qD7W96hvP33srAj2fzxrHFs9WBqKp1J9y4 SQ3IBLi6SRH35rhGJNWtgqS0kfdij74kyX2fFVP153pfvXR0vBO395XCGNQ3jDbG5q buRBMOdGAcdPgfB6taqK1GF2PswlZDHglvkO8oWlOD61FG2ptkf4LbyBLvMPWFvWaT QvcOYheQpJXzA== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: laurent.monat@idquantique.com, thorsten.christiansson@idquantique.com, Enrico Jorns , Jason Roberts , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Brian Norris , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Richard Weinberger , Cyrille Pitchen Subject: [PATCH v2 08/53] mtd: nand: denali: introduce capability flag Date: Wed, 22 Mar 2017 23:07:15 +0900 Message-Id: <1490191680-14481-9-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490191680-14481-1-git-send-email-yamada.masahiro@socionext.com> References: <1490191680-14481-1-git-send-email-yamada.masahiro@socionext.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The Denali NAND controller IP has various customizable features. SoC vendors can choose desired functions when a delivery RTL is created. It means there are several variants for this IP. For example, the Intel version is equipped with 32bit DMA, whereas the IP for UniPhier SoC family with 64bit DMA. This driver was originally written for some Intel platforms with Intel specific things hard-coded. What is worse, the revision register of this IP does not work to distinguish such features. We need to do something to make the driver available for other SoCs. Let's introduce a caps member to the denali_nand_info structure to switch on/off various features. Also, add struct denali_dt_data to store the capability associated with compatible string. Boris suggested this approach in discussion [1] instead of a new DT property for every feature. [1] https://lkml.org/lkml/2016/3/29/142 Signed-off-by: Masahiro Yamada --- Changes in v2: None drivers/mtd/nand/denali.h | 1 + drivers/mtd/nand/denali_dt.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 8df2285..eed001d 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -338,6 +338,7 @@ struct denali_nand_info { uint32_t devnum; /* represent how many nands connected */ uint32_t bbtskipbytes; uint32_t max_banks; + unsigned int caps; }; extern int denali_init(struct denali_nand_info *denali); diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c index 5607fcd..293ddb8 100644 --- a/drivers/mtd/nand/denali_dt.c +++ b/drivers/mtd/nand/denali_dt.c @@ -29,6 +29,10 @@ struct denali_dt { struct clk *clk; }; +struct denali_dt_data { + unsigned int caps; +}; + static const struct of_device_id denali_nand_dt_ids[] = { { .compatible = "denali,denali-nand-dt" }, { /* sentinel */ } @@ -42,23 +46,19 @@ static int denali_dt_probe(struct platform_device *ofdev) { struct resource *denali_reg, *nand_data; struct denali_dt *dt; + const struct denali_dt_data *data; struct denali_nand_info *denali; int ret; - const struct of_device_id *of_id; - - of_id = of_match_device(denali_nand_dt_ids, &ofdev->dev); - if (of_id) { - ofdev->id_entry = of_id->data; - } else { - pr_err("Failed to find the right device id.\n"); - return -ENOMEM; - } dt = devm_kzalloc(&ofdev->dev, sizeof(*dt), GFP_KERNEL); if (!dt) return -ENOMEM; denali = &dt->denali; + data = of_device_get_match_data(&ofdev->dev); + if (data) + denali->caps = data->caps; + denali->platform = DT; denali->dev = &ofdev->dev; denali->irq = platform_get_irq(ofdev, 0); From patchwork Wed Mar 22 14:07:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 95764 Delivered-To: patch@linaro.org Received: by 10.182.3.34 with SMTP id 2csp233630obz; Wed, 22 Mar 2017 07:11:34 -0700 (PDT) X-Received: by 10.98.91.130 with SMTP id p124mr43948754pfb.165.1490191894388; Wed, 22 Mar 2017 07:11:34 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 33si1978287plk.81.2017.03.22.07.11.34; Wed, 22 Mar 2017 07:11:34 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@nifty.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934426AbdCVOLU (ORCPT + 11 others); Wed, 22 Mar 2017 10:11:20 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:46837 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934333AbdCVOK5 (ORCPT ); Wed, 22 Mar 2017 10:10:57 -0400 Received: from pug.jp.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2ME8LDT010154; Wed, 22 Mar 2017 23:08:37 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2ME8LDT010154 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490191718; bh=4fY1lO0n4sY5X3gRy4Dunpb62ZCGHW++MXJt5PFaI3g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mVPTKaO0XH/a92AJtvJbQsCdZ9EleLvwwrhvIY3Ay7CXX+HGSE25QPwmF9Y8q4OHn CPQzyLSEbyGeFRRlUeGUZYQf2bW/PeT4VZiq4BJ+NsbSSYHc5ozGd78k7qJM+sLQ8f DQ46Eh0R14MvYd1iW2cWuZ2A/OIb9zX28IVnu0BBjlv+mCZxHgUFXXz+0MJACjfV12 xkRTSP6qVJu/onoQ9NXLSDMiOlTIokj6/wjay660mF0nAmMklNpM8ECtDmjGNOiiH2 J6b3LlWWHoOItf3TzoTRWCw/PnNiyQXUUPc0yADloZQkD7h3x0uUMp8in5RkmpvPPP HeW6Te102MKAw== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: laurent.monat@idquantique.com, thorsten.christiansson@idquantique.com, Enrico Jorns , Jason Roberts , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Brian Norris , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Richard Weinberger , Cyrille Pitchen Subject: [PATCH v2 10/53] mtd: nand: denali: fix erased page checking Date: Wed, 22 Mar 2017 23:07:17 +0900 Message-Id: <1490191680-14481-11-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490191680-14481-1-git-send-email-yamada.masahiro@socionext.com> References: <1490191680-14481-1-git-send-email-yamada.masahiro@socionext.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This part is wrong in multiple ways: [1] is_erased() is called against "buf" twice, so the second one is meaningless. The second call should check chip->oob_poi. [2] This code block is nested by double "if (check_erase_page)". The inner one is redundant. [3] Erased page checking without threshold is false-positive. Basically, there are two ways for erased page checking: - read the whole of page + oob in raw transfer, then check if all the data are 0xFF. - read the ECC-corrected page + oob, then check if *almost* all the data are 0xFF (bit-flips less than ecc.strength are allowed) While here, it checks if all data in ECC-corrected page are 0xFF. This is too strong because not all of the data are 0xFF after they are manipulated by the ECC engine. Proper threshold must be taken into account to avoid false-positive ecc_stats.failed increments. [4] positive return value for uncorrectable bitflips The comment of ecc->read_page() says it should return "0 if bitflips uncorrectable", but the current code could return a positive value in the case. This commit solves the problems above. The nand framework provides a helper nand_check_erased_ecc_chunk() for erased page check with threshold. The driver's own helper is unneeded. Signed-off-by: Masahiro Yamada --- Changes in v2: - Squash some patches into one. - Use nand_check_erased_ecc_chunk() with threshold drivers/mtd/nand/denali.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 2c59eb3..86381ac 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -883,19 +883,6 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) } } -/* - * this function examines buffers to see if they contain data that - * indicate that the buffer is part of an erased region of flash. - */ -static bool is_erased(uint8_t *buf, int len) -{ - int i; - - for (i = 0; i < len; i++) - if (buf[i] != 0xFF) - return false; - return true; -} #define ECC_SECTOR_SIZE 512 #define ECC_SECTOR(x) (((x) & ECC_ERROR_ADDRESS__SECTOR_NR) >> 12) @@ -1119,6 +1106,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint32_t irq_status; uint32_t irq_mask = INTR__ECC_TRANSACTION_DONE | INTR__ECC_ERR; bool check_erased_page = false; + int stat; if (page != denali->page) { dev_err(denali->dev, @@ -1148,12 +1136,15 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, if (check_erased_page) { read_oob_data(mtd, chip->oob_poi, denali->page); - /* check ECC failures that may have occurred on erased pages */ - if (check_erased_page) { - if (!is_erased(buf, mtd->writesize)) - mtd->ecc_stats.failed++; - if (!is_erased(buf, mtd->oobsize)) - mtd->ecc_stats.failed++; + stat = nand_check_erased_ecc_chunk( + buf, mtd->writesize, + chip->oob_poi, mtd->oobsize, + NULL, 0, + chip->ecc.strength * chip->ecc.steps); + if (stat < 0) { + mtd->ecc_stats.failed++; + /* return 0 for uncorrectable bitflips */ + max_bitflips = 0; } } return max_bitflips; From patchwork Wed Mar 22 14:07:18 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 95776 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp262273qgd; Wed, 22 Mar 2017 07:20:00 -0700 (PDT) X-Received: by 10.99.121.195 with SMTP id u186mr43863967pgc.96.1490192400871; Wed, 22 Mar 2017 07:20:00 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n85si1399672pfi.356.2017.03.22.07.20.00; Wed, 22 Mar 2017 07:20:00 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@nifty.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1760008AbdCVOTx (ORCPT + 11 others); Wed, 22 Mar 2017 10:19:53 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:47421 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934377AbdCVOLT (ORCPT ); Wed, 22 Mar 2017 10:11:19 -0400 Received: from pug.jp.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2ME8LDU010154; Wed, 22 Mar 2017 23:08:38 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2ME8LDU010154 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490191720; bh=qYbsLp7Yfe0wPu41bq2nDxLiTJkmpwAeFevL0dSGe0g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uBGvrvptfizWqXnH8K5DKsm5JYvuqH5rQv0L827CJzdcyRCchbrujVT7S80wg0Edv I5yIBLcmRQcq4IXREYR5XbRVbk6ze0BWsXOv0GZjNAaa3X2H+flmLD+BF+DjFacHm9 HUQWTJ7fs6KJaOiCLsgj9ZKzx9/XR/tKOrHYyXfWg0/wTAPYhEtr/DGP1ZGCPx2P3a oKk256ZZbL+nzwZeR9N1tXbkseyawhv8extaRPOvpdV9be7F0tSiPNnd6A2k6l0BrS pSmILN6PczpLluxUccbRyuEZWbNpgCSrFBsI1J/W6qQcpTv67Fw1B91TV+WJcAZG6l 7gFwLM3sNJyOA== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: laurent.monat@idquantique.com, thorsten.christiansson@idquantique.com, Enrico Jorns , Jason Roberts , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Brian Norris , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Richard Weinberger , Cyrille Pitchen Subject: [PATCH v2 11/53] mtd: nand: denali: fix bitflips calculation in handle_ecc() Date: Wed, 22 Mar 2017 23:07:18 +0900 Message-Id: <1490191680-14481-12-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490191680-14481-1-git-send-email-yamada.masahiro@socionext.com> References: <1490191680-14481-1-git-send-email-yamada.masahiro@socionext.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This function is wrong in multiple ways: [1] Counting corrected bytes instead of corrected bits. The following code is counting the number of corrected _bytes_. /* correct the ECC error */ buf[offset] ^= err_cor_value; mtd->ecc_stats.corrected++; bitflips++; What the core framework expects is the number of corrected _bits_. They can be different if multiple bitflips occur within one byte. [2] total number of errors instead of max of per-sector errors The core framework expects that corrected errors are counted per sector, then the max value should be taken. The current code simply iterates over the whole page, i.e. counts the total number of correction in the page. This means "too many bitflips" is triggered earlier than it should be, i.e. the NAND device is worn out sooner. Besides those bugs, this function is unreadable due to the deep nesting. Notice the whole code in this function is wrapped in if (irq_status & INTR__ECC_ERR), so this conditional can be moved out of the function. Also, use shorter names for local variables. Re-work the function to fix all the issues. Signed-off-by: Masahiro Yamada --- Changes in v2: - Use shorter names for local variables. - Fix bugs addressed by [1], [2] drivers/mtd/nand/denali.c | 157 ++++++++++++++++++++++++---------------------- 1 file changed, 82 insertions(+), 75 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 86381ac..608fe6f 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -888,80 +888,87 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) #define ECC_SECTOR(x) (((x) & ECC_ERROR_ADDRESS__SECTOR_NR) >> 12) #define ECC_BYTE(x) (((x) & ECC_ERROR_ADDRESS__OFFSET)) #define ECC_CORRECTION_VALUE(x) ((x) & ERR_CORRECTION_INFO__BYTEMASK) -#define ECC_ERROR_CORRECTABLE(x) (!((x) & ERR_CORRECTION_INFO__ERROR_TYPE)) +#define ECC_ERROR_UNCORRECTABLE(x) ((x) & ERR_CORRECTION_INFO__ERROR_TYPE) #define ECC_ERR_DEVICE(x) (((x) & ERR_CORRECTION_INFO__DEVICE_NR) >> 8) #define ECC_LAST_ERR(x) ((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO) -static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, - uint32_t irq_status, unsigned int *max_bitflips) +static int handle_ecc(struct mtd_info *mtd, + struct denali_nand_info *denali, uint8_t *buf) { - bool check_erased_page = false; unsigned int bitflips = 0; + unsigned int max_bitflips = 0; + unsigned int total_bitflips = 0; + uint32_t err_addr, err_cor_info; + unsigned int err_byte, err_sector, err_device; + uint8_t err_cor_value; + unsigned int prev_sector = 0; + int ret = 0; + + /* read the ECC errors. we'll ignore them for now */ + denali_set_intr_modes(denali, false); - if (irq_status & INTR__ECC_ERR) { - /* read the ECC errors. we'll ignore them for now */ - uint32_t err_address, err_correction_info, err_byte, - err_sector, err_device, err_correction_value; - denali_set_intr_modes(denali, false); - - do { - err_address = ioread32(denali->flash_reg + - ECC_ERROR_ADDRESS); - err_sector = ECC_SECTOR(err_address); - err_byte = ECC_BYTE(err_address); - - err_correction_info = ioread32(denali->flash_reg + - ERR_CORRECTION_INFO); - err_correction_value = - ECC_CORRECTION_VALUE(err_correction_info); - err_device = ECC_ERR_DEVICE(err_correction_info); - - if (ECC_ERROR_CORRECTABLE(err_correction_info)) { - /* - * If err_byte is larger than ECC_SECTOR_SIZE, - * means error happened in OOB, so we ignore - * it. It's no need for us to correct it - * err_device is represented the NAND error - * bits are happened in if there are more - * than one NAND connected. - */ - if (err_byte < ECC_SECTOR_SIZE) { - struct mtd_info *mtd = - nand_to_mtd(&denali->nand); - int offset; - - offset = (err_sector * - ECC_SECTOR_SIZE + - err_byte) * - denali->devnum + - err_device; - /* correct the ECC error */ - buf[offset] ^= err_correction_value; - mtd->ecc_stats.corrected++; - bitflips++; - } - } else { - /* - * if the error is not correctable, need to - * look at the page to see if it is an erased - * page. if so, then it's not a real ECC error - */ - check_erased_page = true; - } - } while (!ECC_LAST_ERR(err_correction_info)); - /* - * Once handle all ecc errors, controller will triger - * a ECC_TRANSACTION_DONE interrupt, so here just wait - * for a while for this interrupt - */ - while (!(read_interrupt_status(denali) & - INTR__ECC_TRANSACTION_DONE)) - cpu_relax(); - clear_interrupts(denali); - denali_set_intr_modes(denali, true); - } - *max_bitflips = bitflips; - return check_erased_page; + do { + err_addr = ioread32(denali->flash_reg + ECC_ERROR_ADDRESS); + err_sector = ECC_SECTOR(err_addr); + err_byte = ECC_BYTE(err_addr); + + err_cor_info = ioread32(denali->flash_reg + ERR_CORRECTION_INFO); + err_cor_value = ECC_CORRECTION_VALUE(err_cor_info); + err_device = ECC_ERR_DEVICE(err_cor_info); + + /* reset the bitflip counter when crossing ECC sector */ + if (err_sector != prev_sector) + bitflips = 0; + + if (ECC_ERROR_UNCORRECTABLE(err_cor_info)) { + /* + * if the error is not correctable, need to look at the + * page to see if it is an erased page. if so, then + * it's not a real ECC error + */ + ret = -EBADMSG; + } else if (err_byte < ECC_SECTOR_SIZE) { + /* + * If err_byte is larger than ECC_SECTOR_SIZE, means error + * happened in OOB, so we ignore it. It's no need for + * us to correct it err_device is represented the NAND + * error bits are happened in if there are more than + * one NAND connected. + */ + int offset; + unsigned int flips_in_byte; + + offset = (err_sector * ECC_SECTOR_SIZE + err_byte) * + denali->devnum + err_device; + + /* correct the ECC error */ + flips_in_byte = hweight8(buf[offset] ^ err_cor_value); + bitflips += flips_in_byte; + total_bitflips += flips_in_byte; + buf[offset] ^= err_cor_value; + + max_bitflips = max(max_bitflips, bitflips); + } + + prev_sector = err_sector; + } while (!ECC_LAST_ERR(err_cor_info)); + + /* + * Once handle all ecc errors, controller will trigger a + * ECC_TRANSACTION_DONE interrupt, so here just wait for + * a while for this interrupt + */ + while (!(read_interrupt_status(denali) & INTR__ECC_TRANSACTION_DONE)) + cpu_relax(); + clear_interrupts(denali); + denali_set_intr_modes(denali, true); + + if (ret) + return ret; + + mtd->ecc_stats.corrected += total_bitflips; + + return max_bitflips; } /* programs the controller to either enable/disable DMA transfers */ @@ -1097,7 +1104,6 @@ static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip, static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - unsigned int max_bitflips; struct denali_nand_info *denali = mtd_to_denali(mtd); dma_addr_t addr = denali->buf.dma_buf; @@ -1105,8 +1111,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint32_t irq_status; uint32_t irq_mask = INTR__ECC_TRANSACTION_DONE | INTR__ECC_ERR; - bool check_erased_page = false; - int stat; + int stat = 0; if (page != denali->page) { dev_err(denali->dev, @@ -1130,10 +1135,11 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, memcpy(buf, denali->buf.buf, mtd->writesize); - check_erased_page = handle_ecc(denali, buf, irq_status, &max_bitflips); + if (irq_status & INTR__ECC_ERR) + stat = handle_ecc(mtd, denali, buf); denali_enable_dma(denali, false); - if (check_erased_page) { + if (stat == -EBADMSG) { read_oob_data(mtd, chip->oob_poi, denali->page); stat = nand_check_erased_ecc_chunk( @@ -1144,10 +1150,11 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, if (stat < 0) { mtd->ecc_stats.failed++; /* return 0 for uncorrectable bitflips */ - max_bitflips = 0; + stat = 0; } } - return max_bitflips; + + return stat; } static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, From patchwork Wed Mar 22 14:07:28 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 95777 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp263003qgd; Wed, 22 Mar 2017 07:21:28 -0700 (PDT) X-Received: by 10.99.163.72 with SMTP id v8mr33291887pgn.115.1490192488522; Wed, 22 Mar 2017 07:21:28 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y23si2010433pge.8.2017.03.22.07.21.28; Wed, 22 Mar 2017 07:21:28 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@nifty.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934901AbdCVOVK (ORCPT + 11 others); Wed, 22 Mar 2017 10:21:10 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:47370 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1759919AbdCVOLN (ORCPT ); Wed, 22 Mar 2017 10:11:13 -0400 Received: from pug.jp.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2ME8LDe010154; Wed, 22 Mar 2017 23:08:54 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2ME8LDe010154 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490191735; bh=+BdYgaCimnBuNwXJS61p9WaED1bYNvo9IRK2uAAiokc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NJndboOhLvQeNG09a+b0XbpDASWM81tSGUMm3t1CJpmsfxyIuqUsVDJEk6YZyPwUL whyon/KLHCFPxeAsWj0jZAWpocUwEfAEMUj4S10vww+zfut2qFcTKdpfWFZs/WtB0y 9NEhfbRsuH2VAkFPh6gTceb782E4mL/0jknVEWsdUUPJZgUo3K3iIrTQvAIRGSMN9A UfkTMxeRjVZAHWj/yDUwLnh8Ot5wMyyMdCrn5nN1Id3FNVDTB2lUPE2Ei3frq7z6zK IPYJWyHNimO5RIa7Nh6qGH+5GbYOCOAiPEtguRQa1n6bvnitDH14pqZRLvAQV8Bw1L LXVjDUZyz2ffg== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: laurent.monat@idquantique.com, thorsten.christiansson@idquantique.com, Enrico Jorns , Jason Roberts , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Brian Norris , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Richard Weinberger , Cyrille Pitchen Subject: [PATCH v2 21/53] mtd: nand: denali: move multi device fixup code to a helper function Date: Wed, 22 Mar 2017 23:07:28 +0900 Message-Id: <1490191680-14481-22-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490191680-14481-1-git-send-email-yamada.masahiro@socionext.com> References: <1490191680-14481-1-git-send-email-yamada.masahiro@socionext.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Collect multi NAND fixups into a helper function instead of scattering them in denali_init(). I am rewording the comment block to clearly explain what is called "multi device". Signed-off-by: Masahiro Yamada --- Changes in v2: - Reword the comment block for clarification drivers/mtd/nand/denali.c | 54 +++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 21 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 1706975..4e63d57 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -1458,6 +1458,36 @@ static void denali_drv_init(struct denali_nand_info *denali) denali->irq_status = 0; } +static void denali_multidev_fixup(struct denali_nand_info *denali) +{ + struct nand_chip *chip = &denali->nand; + struct mtd_info *mtd = nand_to_mtd(chip); + + /* + * Support for multi device: + * When the IP configuration is x16 capable and two x8 chips are + * connected in parallel, DEVICES_CONNECTED should be set to 2. + * In this case, the core framework knows nothing about this fact, + * so we should tell it the _logical_ pagesize and anything necessary. + */ + denali->devnum = ioread32(denali->flash_reg + DEVICES_CONNECTED); + + mtd->size <<= denali->devnum - 1; + mtd->erasesize <<= denali->devnum - 1; + mtd->writesize <<= denali->devnum - 1; + mtd->oobsize <<= denali->devnum - 1; + chip->chipsize <<= denali->devnum - 1; + chip->page_shift += denali->devnum - 1; + chip->phys_erase_shift += denali->devnum - 1; + chip->bbt_erase_shift += denali->devnum - 1; + chip->chip_shift += denali->devnum - 1; + chip->pagemask <<= denali->devnum - 1; + chip->ecc.size *= denali->devnum; + chip->ecc.bytes *= denali->devnum; + chip->ecc.strength *= denali->devnum; + denali->bbtskipbytes *= denali->devnum; +} + int denali_init(struct denali_nand_info *denali) { struct nand_chip *chip = &denali->nand; @@ -1540,24 +1570,6 @@ int denali_init(struct denali_nand_info *denali) } /* - * support for multi nand - * MTD known nothing about multi nand, so we should tell it - * the real pagesize and anything necessery - */ - denali->devnum = ioread32(denali->flash_reg + DEVICES_CONNECTED); - chip->chipsize <<= denali->devnum - 1; - chip->page_shift += denali->devnum - 1; - chip->pagemask = (chip->chipsize >> chip->page_shift) - 1; - chip->bbt_erase_shift += denali->devnum - 1; - chip->phys_erase_shift = chip->bbt_erase_shift; - chip->chip_shift += denali->devnum - 1; - mtd->writesize <<= denali->devnum - 1; - mtd->oobsize <<= denali->devnum - 1; - mtd->erasesize <<= denali->devnum - 1; - mtd->size = chip->numchips * chip->chipsize; - denali->bbtskipbytes *= denali->devnum; - - /* * second stage of the NAND scan * this stage requires information regarding ECC and * bad block management. @@ -1600,11 +1612,9 @@ int denali_init(struct denali_nand_info *denali) } mtd_set_ooblayout(mtd, &denali_ooblayout_ops); - chip->ecc.bytes *= denali->devnum; - chip->ecc.strength *= denali->devnum; /* override the default read operations */ - chip->ecc.size = ECC_SECTOR_SIZE * denali->devnum; + chip->ecc.size = ECC_SECTOR_SIZE; chip->ecc.read_page = denali_read_page; chip->ecc.read_page_raw = denali_read_page_raw; chip->ecc.write_page = denali_write_page; @@ -1613,6 +1623,8 @@ int denali_init(struct denali_nand_info *denali) chip->ecc.write_oob = denali_write_oob; chip->erase = denali_erase; + denali_multidev_fixup(denali); + ret = nand_scan_tail(mtd); if (ret) goto failed_req_irq;