From patchwork Thu Mar 30 06:45:47 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 96229 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp102253qgd; Wed, 29 Mar 2017 23:49:10 -0700 (PDT) X-Received: by 10.98.50.5 with SMTP id y5mr4401572pfy.169.1490856550628; Wed, 29 Mar 2017 23:49:10 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s26si1236143pgd.313.2017.03.29.23.49.10; Wed, 29 Mar 2017 23:49:10 -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 S932945AbdC3GtJ (ORCPT + 22 others); Thu, 30 Mar 2017 02:49:09 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:39928 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932215AbdC3GtF (ORCPT ); Thu, 30 Mar 2017 02:49:05 -0400 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2U6kUcP015463; Thu, 30 Mar 2017 15:46:32 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2U6kUcP015463 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490856393; bh=1CBcEIafwY3CJeycM20szkRU62MG/pxqt6n3nvIVYDw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=2ghd8pj1/lHSRnMqF3QvUcuAB4CT+Rh9phfDgL4xcwP9pULAqlSqHoA1UjdTjWt8k ju1ZWZJli3XzItnxo0vcoknN5g/Wsca4X7K5lcOaWFt+B9tRVMuWJnRlOFQ6hktkOn cXMWGYv6Br73VPRbk8gKxZImNazdH103U/WqsbawUl5r3uKYJdJkDkLIsGkMZ/LAG6 Pe6J+Safm5cDii5cOjUVy9eqO51t8vQS4k0pKW4QBuGhVsUOuhQa/kGeYOQAlOSFFY bWFkbgnxl2OcGfLoaI/Xdof+OgnjTQxdpMx9HQMYvtUDGxceYPUscNnpUoDfvMxdda mT1dwWYMb2wyw== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: Enrico Jorns , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Brian Norris , Richard Weinberger , Cyrille Pitchen Subject: [PATCH v3 01/37] mtd: nand: relax ecc.read_page() return value for uncorrectable ECC Date: Thu, 30 Mar 2017 15:45:47 +0900 Message-Id: <1490856383-31560-2-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490856383-31560-1-git-send-email-yamada.masahiro@socionext.com> References: <1490856383-31560-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 comment for ecc.read_page() requires that it should return "0 if bitflips uncorrectable". Actually, drivers could return positive values when uncorrectable bitflips occur. For example, nand_read_page_swecc() is the case. If ecc.correct() returns -EBADMSG for the first ECC sector, and a positive value for the second one, nand_read_page_swecc() returns a positive max_bitflips and increments ecc_stats.failed for the same page. The requirement can be relaxed by tweaking nand_do_read_ops(). Move the max_bitflips calculation below the retry. Signed-off-by: Masahiro Yamada Suggested-by: Boris Brezillon --- Changes in v3: - Newly added Changes in v2: None drivers/mtd/nand/nand_base.c | 3 +-- include/linux/mtd/nand.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index e13f959..f828ad7 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1993,8 +1993,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, break; } - max_bitflips = max_t(unsigned int, max_bitflips, ret); - /* Transfer not aligned data */ if (use_bufpoi) { if (!NAND_HAS_SUBPAGE_READ(chip) && !oob && @@ -2045,6 +2043,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, } buf += bytes; + max_bitflips = max_t(unsigned int, max_bitflips, ret); } else { memcpy(buf, chip->buffers->databuf + col, bytes); buf += bytes; diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 9591e0f..69cccd1 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -525,7 +525,7 @@ static inline void nand_hw_control_init(struct nand_hw_control *nfc) * out-of-band data). * @read_page: function to read a page according to the ECC generator * requirements; returns maximum number of bitflips corrected in - * any single ECC step, 0 if bitflips uncorrectable, -EIO hw error + * any single ECC step, -EIO hw error * @read_subpage: function to read parts of the page covered by ECC; * returns same as read_page() * @write_subpage: function to write parts of the page covered by ECC. From patchwork Thu Mar 30 06:45:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 96231 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp102319qgd; Wed, 29 Mar 2017 23:49:24 -0700 (PDT) X-Received: by 10.98.133.153 with SMTP id m25mr4406109pfk.263.1490856564615; Wed, 29 Mar 2017 23:49:24 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g10si1224666pge.420.2017.03.29.23.49.23; Wed, 29 Mar 2017 23:49:24 -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 S933015AbdC3GtN (ORCPT + 22 others); Thu, 30 Mar 2017 02:49:13 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:40083 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932915AbdC3GtJ (ORCPT ); Thu, 30 Mar 2017 02:49:09 -0400 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2U6kUcV015463; Thu, 30 Mar 2017 15:46:40 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2U6kUcV015463 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490856401; bh=XoJxKkSECZ5JPq9ngbIsGUlJ8XBjSF1yPSrc53t4yxs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=1Kp5BVM0O7KkwVBTLtpcZUtZJQ8XxgearxlW2BJg3AVHp6Czk0f56+bKNF64M77P3 661IhiAcRbPV5hPQWA3up7u5vWYeh7Zx4eZUXwyJZz71imPvRcpFcfisC0LKmAZT7S gcsDr9EjzaL8TiXI6VUA68oC6tnw55NhDlgKr2Met4MomF9fzVa3UbUtOIRgGBQaqd QBS+ki9cCUw0Ta9HzMeOYboXTij2+YxF1fOGFvgmEM9X2ezIK335M0zOhdQJpPqqJE //8o49g6Fx3385Z0BsERmUSuqpPTK7RQWx4WbnAaD2PgY9JdEx2LogJegYtZOjC3D9 lDuTN14viuKPg== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: Enrico Jorns , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Brian Norris , Richard Weinberger , Cyrille Pitchen , Rob Herring , Mark Rutland Subject: [PATCH v3 07/37] mtd: nand: denali_dt: enable HW_ECC_FIXUP for Altera SOCFPGA variant Date: Thu, 30 Mar 2017 15:45:53 +0900 Message-Id: <1490856383-31560-8-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490856383-31560-1-git-send-email-yamada.masahiro@socionext.com> References: <1490856383-31560-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 There are various customizable parameters, so several variants for this IP. A generic compatible like "denali,denali-nand-dt" is useless. Moreover, there are multiple things wrong with this string. (Refer to Rob's comment [1]) The "denali,denali-nand-dt" was added by Altera for the SOCFPGA port. Replace it with a more specific string "altr,socfpga-denali-nand". There are no users (in upstream) of the old compatible string. The Denali IP on SOCFPGA incorporates the hardware ECC fixup engine. So, this capability should be associated with the compatible. [1] https://lkml.org/lkml/2016/12/1/450 Signed-off-by: Masahiro Yamada Acked-by: Rob Herring --- Changes in v3: - Update git-log to mention there are no users of the old binding. Changes in v2: - Add caps flag to of_device_id data, not hard-code in driver code - Add Altera-specific compatible. Documentation/devicetree/bindings/mtd/denali-nand.txt | 5 +++-- drivers/mtd/nand/denali_dt.c | 14 ++++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) -- 2.7.4 diff --git a/Documentation/devicetree/bindings/mtd/denali-nand.txt b/Documentation/devicetree/bindings/mtd/denali-nand.txt index b04d03a..6f4ab4c 100644 --- a/Documentation/devicetree/bindings/mtd/denali-nand.txt +++ b/Documentation/devicetree/bindings/mtd/denali-nand.txt @@ -1,7 +1,8 @@ * Denali NAND controller Required properties: - - compatible : should be "denali,denali-nand-dt" + - compatible : should be one of the following: + "altr,socfpga-denali-nand" - for Altera SOCFPGA - reg : should contain registers location and length for data and reg. - reg-names: Should contain the reg names "nand_data" and "denali_reg" - interrupts : The interrupt number. @@ -15,7 +16,7 @@ Examples: nand: nand@ff900000 { #address-cells = <1>; #size-cells = <1>; - compatible = "denali,denali-nand-dt"; + compatible = "altr,socfpga-denali-nand"; reg = <0xff900000 0x100000>, <0xffb80000 0x10000>; reg-names = "nand_data", "denali_reg"; interrupts = <0 144 4>; diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c index 293ddb8..9577bfd 100644 --- a/drivers/mtd/nand/denali_dt.c +++ b/drivers/mtd/nand/denali_dt.c @@ -33,11 +33,17 @@ struct denali_dt_data { unsigned int caps; }; -static const struct of_device_id denali_nand_dt_ids[] = { - { .compatible = "denali,denali-nand-dt" }, - { /* sentinel */ } - }; +static const struct denali_dt_data denali_socfpga_data = { + .caps = DENALI_CAP_HW_ECC_FIXUP, +}; +static const struct of_device_id denali_nand_dt_ids[] = { + { + .compatible = "altr,socfpga-denali-nand", + .data = &denali_socfpga_data, + }, + { /* sentinel */ } +}; MODULE_DEVICE_TABLE(of, denali_nand_dt_ids); static u64 denali_dma_mask; From patchwork Thu Mar 30 06:45:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 96246 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp103179qgd; Wed, 29 Mar 2017 23:52:31 -0700 (PDT) X-Received: by 10.84.231.143 with SMTP id g15mr5176868plk.110.1490856751750; Wed, 29 Mar 2017 23:52:31 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id x11si1262657pfj.58.2017.03.29.23.52.31; Wed, 29 Mar 2017 23:52:31 -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 S933394AbdC3Gwa (ORCPT + 22 others); Thu, 30 Mar 2017 02:52:30 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:40527 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933017AbdC3GtZ (ORCPT ); Thu, 30 Mar 2017 02:49:25 -0400 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2U6kUcX015463; Thu, 30 Mar 2017 15:46:42 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2U6kUcX015463 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490856404; bh=+y4Wc/E/f095agrteuzD99bz3BNsdye4u50/m/tTVMM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ug13U6VIB48neSFikj5r8AKgF22I5nt7UKkwrIxMDtH3pegO3UnEwOtIThhrxGnak pJnkjimeQPYQ0itdfGZzEZRqljo+XAEE1OOeA30PeeZIVSaB6dB3HpfVbX5fFAclte BoQ78JRe5apuGT1q5/38SW+pAOfDxqObgErhAKI4MqrYNCPZQZCYaKWUQg8TY7zZAu VuOWKnn0blxCPpGHTkOUehs5ALqUbmQV4jDSmZa9lt2a6i7NY028Kq4LqQ8JGllfh2 VM8ZHpQoHyMxkNSl+butLNpKf1jTuARS6bfZ7YhoN5XlLq+12AJ1TJagQwR0I+Y9KP iF0IK2I+UAFmg== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: Enrico Jorns , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Brian Norris , Richard Weinberger , Cyrille Pitchen , Rob Herring , Mark Rutland Subject: [PATCH v3 09/37] mtd: nand: denali_dt: remove dma-mask DT property Date: Thu, 30 Mar 2017 15:45:55 +0900 Message-Id: <1490856383-31560-10-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490856383-31560-1-git-send-email-yamada.masahiro@socionext.com> References: <1490856383-31560-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 driver sets appropriate DMA mask. Delete the "dma-mask" DT property. See [1] for negative comments for this binding. [1] https://lkml.org/lkml/2016/2/8/57 Signed-off-by: Masahiro Yamada Acked-by: Rob Herring --- Changes in v3: None Changes in v2: None Documentation/devicetree/bindings/mtd/denali-nand.txt | 2 -- drivers/mtd/nand/denali_dt.c | 9 --------- 2 files changed, 11 deletions(-) -- 2.7.4 diff --git a/Documentation/devicetree/bindings/mtd/denali-nand.txt b/Documentation/devicetree/bindings/mtd/denali-nand.txt index 6f4ab4c..e593bbe 100644 --- a/Documentation/devicetree/bindings/mtd/denali-nand.txt +++ b/Documentation/devicetree/bindings/mtd/denali-nand.txt @@ -6,7 +6,6 @@ Required properties: - reg : should contain registers location and length for data and reg. - reg-names: Should contain the reg names "nand_data" and "denali_reg" - interrupts : The interrupt number. - - dm-mask : DMA bit mask The device tree may optionally contain sub-nodes describing partitions of the address space. See partition.txt for more detail. @@ -20,5 +19,4 @@ nand: nand@ff900000 { reg = <0xff900000 0x100000>, <0xffb80000 0x10000>; reg-names = "nand_data", "denali_reg"; interrupts = <0 144 4>; - dma-mask = <0xffffffff>; }; diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c index 9577bfd..b8a8284 100644 --- a/drivers/mtd/nand/denali_dt.c +++ b/drivers/mtd/nand/denali_dt.c @@ -46,8 +46,6 @@ static const struct of_device_id denali_nand_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, denali_nand_dt_ids); -static u64 denali_dma_mask; - static int denali_dt_probe(struct platform_device *ofdev) { struct resource *denali_reg, *nand_data; @@ -83,13 +81,6 @@ static int denali_dt_probe(struct platform_device *ofdev) if (IS_ERR(denali->flash_mem)) return PTR_ERR(denali->flash_mem); - if (!of_property_read_u32(ofdev->dev.of_node, - "dma-mask", (u32 *)&denali_dma_mask)) { - denali->dev->dma_mask = &denali_dma_mask; - } else { - denali->dev->dma_mask = NULL; - } - dt->clk = devm_clk_get(&ofdev->dev, NULL); if (IS_ERR(dt->clk)) { dev_err(&ofdev->dev, "no clk available\n"); From patchwork Thu Mar 30 06:46:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 96250 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp103957qgd; Wed, 29 Mar 2017 23:55:31 -0700 (PDT) X-Received: by 10.98.48.196 with SMTP id w187mr4323540pfw.179.1490856931605; Wed, 29 Mar 2017 23:55:31 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s5si1253528pgo.231.2017.03.29.23.55.31; Wed, 29 Mar 2017 23:55:31 -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 S933355AbdC3Gza (ORCPT + 22 others); Thu, 30 Mar 2017 02:55:30 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:39998 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932755AbdC3GtH (ORCPT ); Thu, 30 Mar 2017 02:49:07 -0400 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2U6kUce015463; Thu, 30 Mar 2017 15:46:52 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2U6kUce015463 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490856413; bh=Kj+y1uySyRo+8B6I7Y642NVgoXKgjiH8NH0SH0vpqRE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AGfd8HQXc+Pc/gTAyB9mx7V3HRYhoqCWpxdzC7DFsRcigqenKTGPolH0feme3Al2t ZsptcpUzC6YSBxIn+VES+FULW/s6St3Pi26oy41AWVUsydaxNLInSMRLFh2ZCh8Fjq 8mYoBdK6V6yhYH+2Mfm3CEoRwhW4CurOcTRfPE4mBZAogv4LN/y1feQzMfYqKiGTdx AeFMz3+1ETj9tY3nDYCXy6sbaVu/JGi4f7uMZXhvF7J1pPD3xuSg8dY6l+sOqK/tpc X37w09jPsL2Heilj/JgZWejkCQlssml9A8hY8L18Q6QlnlW53RDNVSO+uIF59bFyXs IVPl2yQnIgstA== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: Enrico Jorns , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Brian Norris , Richard Weinberger , Cyrille Pitchen , Rob Herring , Mark Rutland Subject: [PATCH v3 16/37] mtd: nand: denali_dt: add compatible strings for UniPhier SoC variants Date: Thu, 30 Mar 2017 15:46:02 +0900 Message-Id: <1490856383-31560-17-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490856383-31560-1-git-send-email-yamada.masahiro@socionext.com> References: <1490856383-31560-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 Add two compatible strings for UniPhier SoCs. "socionext,uniphier-denali-nand-v5a" is used on UniPhier sLD3, LD4, Pro4, sLD8 SoCs. "socionext,uniphier-denali-nand-v5b" is used on UniPhier Pro5, PXs2, LD6b, LD11, LD20 SoCs. Signed-off-by: Masahiro Yamada --- Changes in v3: None Changes in v2: - Change the compatible strings - Fix the ecc_strength_capability - Override revision number for the newer one .../devicetree/bindings/mtd/denali-nand.txt | 6 ++++++ drivers/mtd/nand/denali_dt.c | 23 ++++++++++++++++++++++ 2 files changed, 29 insertions(+) -- 2.7.4 diff --git a/Documentation/devicetree/bindings/mtd/denali-nand.txt b/Documentation/devicetree/bindings/mtd/denali-nand.txt index 647618e..0b08ea5 100644 --- a/Documentation/devicetree/bindings/mtd/denali-nand.txt +++ b/Documentation/devicetree/bindings/mtd/denali-nand.txt @@ -3,6 +3,8 @@ Required properties: - compatible : should be one of the following: "altr,socfpga-denali-nand" - for Altera SOCFPGA + "socionext,uniphier-denali-nand-v5a" - for Socionext UniPhier (v5a) + "socionext,uniphier-denali-nand-v5b" - for Socionext UniPhier (v5b) - reg : should contain registers location and length for data and reg. - reg-names: Should contain the reg names "nand_data" and "denali_reg" - interrupts : The interrupt number. @@ -10,9 +12,13 @@ Required properties: Optional properties: - nand-ecc-step-size: must be 512 or 1024. If not specified, default to: 512 for "altr,socfpga-denali-nand" + 1024 for "socionext,uniphier-denali-nand-v5a" + 1024 for "socionext,uniphier-denali-nand-v5b" see nand.txt for details. - nand-ecc-strength: see nand.txt for details. Available values are: 8, 15 for "altr,socfpga-denali-nand" + 8, 16, 24 for "socionext,uniphier-denali-nand-v5a" + 8, 16 for "socionext,uniphier-denali-nand-v5b" - nand-ecc-maximize: see nand.txt for details Note: diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c index c3bc333..1f2f68a 100644 --- a/drivers/mtd/nand/denali_dt.c +++ b/drivers/mtd/nand/denali_dt.c @@ -41,11 +41,34 @@ static const struct denali_dt_data denali_socfpga_data = { DENALI_CAP_ECC_SIZE_512, }; +static const struct denali_dt_data denali_uniphier_v5a_data = { + .ecc_strength_avail = BIT(24) | BIT(16) | BIT(8), + .caps = DENALI_CAP_HW_ECC_FIXUP | + DENALI_CAP_DMA_64BIT | + DENALI_CAP_ECC_SIZE_1024, +}; + +static const struct denali_dt_data denali_uniphier_v5b_data = { + .revision = 0x0501, + .ecc_strength_avail = BIT(16) | BIT(8), + .caps = DENALI_CAP_HW_ECC_FIXUP | + DENALI_CAP_DMA_64BIT | + DENALI_CAP_ECC_SIZE_1024, +}; + static const struct of_device_id denali_nand_dt_ids[] = { { .compatible = "altr,socfpga-denali-nand", .data = &denali_socfpga_data, }, + { + .compatible = "socionext,uniphier-denali-nand-v5a", + .data = &denali_uniphier_v5a_data, + }, + { + .compatible = "socionext,uniphier-denali-nand-v5b", + .data = &denali_uniphier_v5b_data, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, denali_nand_dt_ids); From patchwork Thu Mar 30 06:46:03 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 96233 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp102344qgd; Wed, 29 Mar 2017 23:49:30 -0700 (PDT) X-Received: by 10.99.146.7 with SMTP id o7mr4417708pgd.6.1490856570204; Wed, 29 Mar 2017 23:49:30 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g10si1224666pge.420.2017.03.29.23.49.29; Wed, 29 Mar 2017 23:49:30 -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 S933211AbdC3Gt2 (ORCPT + 22 others); Thu, 30 Mar 2017 02:49:28 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:40641 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933126AbdC3GtX (ORCPT ); Thu, 30 Mar 2017 02:49:23 -0400 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2U6kUcf015463; Thu, 30 Mar 2017 15:46:53 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2U6kUcf015463 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490856414; bh=lQMgVyZtgeI1Sp9dfY5WSzW6JM5Gj64stvq+x/r9Nbc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=r7Lrk/kbvA2tpMuXlvJaVyxiOi7eu8U34HbTjD7JDXHc2Nz0PEvKI+3lWxJSWY31L KUs3zXQO5KMPkqr6vM+wG2bNomQ3Lhfjusz2RSJBjzgj7H480OwWtVGBQlU/MV6mcA 1Wi4iM0e9DV1zxU3L2ZYSdzl+KyCydXwElpwhe6v61ofgwLAjbv0h5zgVU/di1iwGi JRn3XkfVIaSfnfQBfDXF/bRq+wWYYJ9VSYRtfgmHyQqzQ5QWEjM5O4ZOaushxhqbwq NIX3onmGJIkpyHGWs5krTDuR2EEXbNneW/jQ/EbkIZQ9O8we8n/g+GNlp/oTCqpKJg lnN64AzN0eo2A== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: Enrico Jorns , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Brian Norris , Richard Weinberger , Cyrille Pitchen Subject: [PATCH v3 17/37] mtd: nand: denali: set NAND_ECC_CUSTOM_PAGE_ACCESS Date: Thu, 30 Mar 2017 15:46:03 +0900 Message-Id: <1490856383-31560-18-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490856383-31560-1-git-send-email-yamada.masahiro@socionext.com> References: <1490856383-31560-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_cmdfunc() actually does nothing valuable for NAND_CMD_{PAGEPROG,READ0,SEQIN}. For NAND_CMD_{READ0,SEQIN}, it copies "page" to "denali->page", then denali_read_page() and denali_read_page_raw() compare them to check if the NAND framework called the callbacks in correct order. (Inconsistently, this check is missing from the denali_write_page() and denali_write_page_raw().) The framework is widely tested by many drivers, so this kind of sanity check is unneeded. The Denali controller is equipped with high level interface for read/write, so let's skip unneeded call of cmdfunc(). Signed-off-by: Masahiro Yamada --- Changes in v3: None Changes in v2: - Newly added drivers/mtd/nand/denali.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 2b20232..79851ca 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -998,7 +998,7 @@ static void denali_setup_dma(struct denali_nand_info *denali, int op) * configuration details. */ static int write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, bool raw_xfer) + const uint8_t *buf, int page, bool raw_xfer) { struct denali_nand_info *denali = mtd_to_denali(mtd); dma_addr_t addr = denali->buf.dma_buf; @@ -1006,6 +1006,8 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *chip, uint32_t irq_status; uint32_t irq_mask = INTR__DMA_CMD_COMP | INTR__PROGRAM_FAIL; + denali->page = page; + /* * if it is a raw xfer, we want to disable ecc and send the spare area. * !raw_xfer - enable ecc @@ -1059,7 +1061,7 @@ static int denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, * for regular page writes, we let HW handle all the ECC * data written to the device. */ - return write_page(mtd, chip, buf, false); + return write_page(mtd, chip, buf, page, false); } /* @@ -1075,7 +1077,7 @@ static int denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, * for raw page writes, we want to disable ECC and simply write * whatever data is in the buffer. */ - return write_page(mtd, chip, buf, true); + return write_page(mtd, chip, buf, page, true); } static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip, @@ -1105,12 +1107,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, unsigned long uncor_ecc_flags = 0; int stat = 0; - if (page != denali->page) { - dev_err(denali->dev, - "IN %s: page %d is not equal to denali->page %d", - __func__, page, denali->page); - BUG(); - } + denali->page = page; setup_ecc_for_xfer(denali, true, false); @@ -1154,12 +1151,7 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, size_t size = mtd->writesize + mtd->oobsize; uint32_t irq_mask = INTR__DMA_CMD_COMP; - if (page != denali->page) { - dev_err(denali->dev, - "IN %s: page %d is not equal to denali->page %d", - __func__, page, denali->page); - BUG(); - } + denali->page = page; setup_ecc_for_xfer(denali, false, true); denali_enable_dma(denali, true); @@ -1238,8 +1230,6 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, int i; switch (cmd) { - case NAND_CMD_PAGEPROG: - break; case NAND_CMD_STATUS: read_status(denali); break; @@ -1259,10 +1249,6 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, write_byte_to_buf(denali, id); } break; - case NAND_CMD_READ0: - case NAND_CMD_SEQIN: - denali->page = page; - break; case NAND_CMD_RESET: reset_bank(denali); break; @@ -1644,6 +1630,7 @@ int denali_init(struct denali_nand_info *denali) mtd_set_ooblayout(mtd, &denali_ooblayout_ops); + chip->ecc.options |= NAND_ECC_CUSTOM_PAGE_ACCESS; chip->ecc.read_page = denali_read_page; chip->ecc.read_page_raw = denali_read_page_raw; chip->ecc.write_page = denali_write_page; From patchwork Thu Mar 30 06:46:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 96237 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp102427qgd; Wed, 29 Mar 2017 23:49:49 -0700 (PDT) X-Received: by 10.99.140.27 with SMTP id m27mr4506645pgd.174.1490856589356; Wed, 29 Mar 2017 23:49:49 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i64si1228899pfa.421.2017.03.29.23.49.49; Wed, 29 Mar 2017 23:49:49 -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 S933274AbdC3Gtq (ORCPT + 22 others); Thu, 30 Mar 2017 02:49:46 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:41051 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755652AbdC3Gti (ORCPT ); Thu, 30 Mar 2017 02:49:38 -0400 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2U6kUch015463; Thu, 30 Mar 2017 15:46:56 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2U6kUch015463 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490856417; bh=KtnnLF2FC+ATKyPv0QG/x4C4IYKy+HKHZI3ZJdBBKtE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GAbuvZyT9CGjlgxDZCCJ1okW2H4+wLpMuMnVCDQUPRrvHQWG0WszFpp7qRE+6m4Dh KB8DK9h596/iBUMDDdAm8eOr7N3R10q57x5S3rYLxMnDs2tLvhpurc7RTJWidcC1Q4 90r7F8QokoWROqrDh2RlF+aGYH5IAWZKXBUK8Zk73zSKi/MFRHmWNRsoT43VLRBM6S pKm33ZnFdNwtw2WDaO5eGNU6I2QOdWyNTgsFFzQZpP/crKPQz/yKW2YaJBFCUfm+bf 1LYigXoSERZxtdNXVTg1Dw6ROHfMrcVDjQU/t9bsNtBghGmu8M6+LlK0PoGOMnjttt vnDxaGgo69Mbw== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: Enrico Jorns , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Brian Norris , Richard Weinberger , Cyrille Pitchen Subject: [PATCH v3 19/37] mtd: nand: denali: use BIT() and GENMASK() for register macros Date: Thu, 30 Mar 2017 15:46:05 +0900 Message-Id: <1490856383-31560-20-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490856383-31560-1-git-send-email-yamada.masahiro@socionext.com> References: <1490856383-31560-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 Make register field macros more readable especially for comparing the macros and the register description in the Denali User's Guide. Signed-off-by: Masahiro Yamada --- Changes in v3: None Changes in v2: - Newly added drivers/mtd/nand/denali.h | 244 ++++++++++++++++++++++------------------------ 1 file changed, 119 insertions(+), 125 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 9e2b787..610b013 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -24,246 +24,240 @@ #include #define DEVICE_RESET 0x0 -#define DEVICE_RESET__BANK0 0x0001 -#define DEVICE_RESET__BANK1 0x0002 -#define DEVICE_RESET__BANK2 0x0004 -#define DEVICE_RESET__BANK3 0x0008 +#define DEVICE_RESET__BANK(bank) BIT(bank) #define TRANSFER_SPARE_REG 0x10 -#define TRANSFER_SPARE_REG__FLAG 0x0001 +#define TRANSFER_SPARE_REG__FLAG BIT(0) #define LOAD_WAIT_CNT 0x20 -#define LOAD_WAIT_CNT__VALUE 0xffff +#define LOAD_WAIT_CNT__VALUE GENMASK(15, 0) #define PROGRAM_WAIT_CNT 0x30 -#define PROGRAM_WAIT_CNT__VALUE 0xffff +#define PROGRAM_WAIT_CNT__VALUE GENMASK(15, 0) #define ERASE_WAIT_CNT 0x40 -#define ERASE_WAIT_CNT__VALUE 0xffff +#define ERASE_WAIT_CNT__VALUE GENMASK(15, 0) #define INT_MON_CYCCNT 0x50 -#define INT_MON_CYCCNT__VALUE 0xffff +#define INT_MON_CYCCNT__VALUE GENMASK(15, 0) #define RB_PIN_ENABLED 0x60 -#define RB_PIN_ENABLED__BANK0 0x0001 -#define RB_PIN_ENABLED__BANK1 0x0002 -#define RB_PIN_ENABLED__BANK2 0x0004 -#define RB_PIN_ENABLED__BANK3 0x0008 +#define RB_PIN_ENABLED__BANK(bank) BIT(bank) #define MULTIPLANE_OPERATION 0x70 -#define MULTIPLANE_OPERATION__FLAG 0x0001 +#define MULTIPLANE_OPERATION__FLAG BIT(0) #define MULTIPLANE_READ_ENABLE 0x80 -#define MULTIPLANE_READ_ENABLE__FLAG 0x0001 +#define MULTIPLANE_READ_ENABLE__FLAG BIT(0) #define COPYBACK_DISABLE 0x90 -#define COPYBACK_DISABLE__FLAG 0x0001 +#define COPYBACK_DISABLE__FLAG BIT(0) #define CACHE_WRITE_ENABLE 0xa0 -#define CACHE_WRITE_ENABLE__FLAG 0x0001 +#define CACHE_WRITE_ENABLE__FLAG BIT(0) #define CACHE_READ_ENABLE 0xb0 -#define CACHE_READ_ENABLE__FLAG 0x0001 +#define CACHE_READ_ENABLE__FLAG BIT(0) #define PREFETCH_MODE 0xc0 -#define PREFETCH_MODE__PREFETCH_EN 0x0001 -#define PREFETCH_MODE__PREFETCH_BURST_LENGTH 0xfff0 +#define PREFETCH_MODE__PREFETCH_EN BIT(0) +#define PREFETCH_MODE__PREFETCH_BURST_LENGTH GENMASK(15, 4) #define CHIP_ENABLE_DONT_CARE 0xd0 -#define CHIP_EN_DONT_CARE__FLAG 0x01 +#define CHIP_EN_DONT_CARE__FLAG BIT(0) #define ECC_ENABLE 0xe0 -#define ECC_ENABLE__FLAG 0x0001 +#define ECC_ENABLE__FLAG BIT(0) #define GLOBAL_INT_ENABLE 0xf0 -#define GLOBAL_INT_EN_FLAG 0x01 +#define GLOBAL_INT_EN_FLAG BIT(0) #define WE_2_RE 0x100 -#define WE_2_RE__VALUE 0x003f +#define WE_2_RE__VALUE GENMASK(5, 0) #define ADDR_2_DATA 0x110 -#define ADDR_2_DATA__VALUE 0x003f +#define ADDR_2_DATA__VALUE GENMASK(5, 0) #define RE_2_WE 0x120 -#define RE_2_WE__VALUE 0x003f +#define RE_2_WE__VALUE GENMASK(5, 0) #define ACC_CLKS 0x130 -#define ACC_CLKS__VALUE 0x000f +#define ACC_CLKS__VALUE GENMASK(3, 0) #define NUMBER_OF_PLANES 0x140 -#define NUMBER_OF_PLANES__VALUE 0x0007 +#define NUMBER_OF_PLANES__VALUE GENMASK(2, 0) #define PAGES_PER_BLOCK 0x150 -#define PAGES_PER_BLOCK__VALUE 0xffff +#define PAGES_PER_BLOCK__VALUE GENMASK(15, 0) #define DEVICE_WIDTH 0x160 -#define DEVICE_WIDTH__VALUE 0x0003 +#define DEVICE_WIDTH__VALUE GENMASK(1, 0) #define DEVICE_MAIN_AREA_SIZE 0x170 -#define DEVICE_MAIN_AREA_SIZE__VALUE 0xffff +#define DEVICE_MAIN_AREA_SIZE__VALUE GENMASK(15, 0) #define DEVICE_SPARE_AREA_SIZE 0x180 -#define DEVICE_SPARE_AREA_SIZE__VALUE 0xffff +#define DEVICE_SPARE_AREA_SIZE__VALUE GENMASK(15, 0) #define TWO_ROW_ADDR_CYCLES 0x190 -#define TWO_ROW_ADDR_CYCLES__FLAG 0x0001 +#define TWO_ROW_ADDR_CYCLES__FLAG BIT(0) #define MULTIPLANE_ADDR_RESTRICT 0x1a0 -#define MULTIPLANE_ADDR_RESTRICT__FLAG 0x0001 +#define MULTIPLANE_ADDR_RESTRICT__FLAG BIT(0) #define ECC_CORRECTION 0x1b0 -#define ECC_CORRECTION__VALUE 0x001f +#define ECC_CORRECTION__VALUE GENMASK(4, 0) #define READ_MODE 0x1c0 -#define READ_MODE__VALUE 0x000f +#define READ_MODE__VALUE GENMASK(3, 0) #define WRITE_MODE 0x1d0 -#define WRITE_MODE__VALUE 0x000f +#define WRITE_MODE__VALUE GENMASK(3, 0) #define COPYBACK_MODE 0x1e0 -#define COPYBACK_MODE__VALUE 0x000f +#define COPYBACK_MODE__VALUE GENMASK(3, 0) #define RDWR_EN_LO_CNT 0x1f0 -#define RDWR_EN_LO_CNT__VALUE 0x001f +#define RDWR_EN_LO_CNT__VALUE GENMASK(4, 0) #define RDWR_EN_HI_CNT 0x200 -#define RDWR_EN_HI_CNT__VALUE 0x001f +#define RDWR_EN_HI_CNT__VALUE GENMASK(4, 0) #define MAX_RD_DELAY 0x210 -#define MAX_RD_DELAY__VALUE 0x000f +#define MAX_RD_DELAY__VALUE GENMASK(3, 0) #define CS_SETUP_CNT 0x220 -#define CS_SETUP_CNT__VALUE 0x001f +#define CS_SETUP_CNT__VALUE GENMASK(4, 0) #define SPARE_AREA_SKIP_BYTES 0x230 -#define SPARE_AREA_SKIP_BYTES__VALUE 0x003f +#define SPARE_AREA_SKIP_BYTES__VALUE GENMASK(5, 0) #define SPARE_AREA_MARKER 0x240 -#define SPARE_AREA_MARKER__VALUE 0xffff +#define SPARE_AREA_MARKER__VALUE GENMASK(15, 0) #define DEVICES_CONNECTED 0x250 -#define DEVICES_CONNECTED__VALUE 0x0007 +#define DEVICES_CONNECTED__VALUE GENMASK(2, 0) #define DIE_MASK 0x260 -#define DIE_MASK__VALUE 0x00ff +#define DIE_MASK__VALUE GENMASK(7, 0) #define FIRST_BLOCK_OF_NEXT_PLANE 0x270 -#define FIRST_BLOCK_OF_NEXT_PLANE__VALUE 0xffff +#define FIRST_BLOCK_OF_NEXT_PLANE__VALUE GENMASK(15, 0) #define WRITE_PROTECT 0x280 -#define WRITE_PROTECT__FLAG 0x0001 +#define WRITE_PROTECT__FLAG BIT(0) #define RE_2_RE 0x290 -#define RE_2_RE__VALUE 0x003f +#define RE_2_RE__VALUE GENMASK(5, 0) #define MANUFACTURER_ID 0x300 -#define MANUFACTURER_ID__VALUE 0x00ff +#define MANUFACTURER_ID__VALUE GENMASK(7, 0) #define DEVICE_ID 0x310 -#define DEVICE_ID__VALUE 0x00ff +#define DEVICE_ID__VALUE GENMASK(7, 0) #define DEVICE_PARAM_0 0x320 -#define DEVICE_PARAM_0__VALUE 0x00ff +#define DEVICE_PARAM_0__VALUE GENMASK(7, 0) #define DEVICE_PARAM_1 0x330 -#define DEVICE_PARAM_1__VALUE 0x00ff +#define DEVICE_PARAM_1__VALUE GENMASK(7, 0) #define DEVICE_PARAM_2 0x340 -#define DEVICE_PARAM_2__VALUE 0x00ff +#define DEVICE_PARAM_2__VALUE GENMASK(7, 0) #define LOGICAL_PAGE_DATA_SIZE 0x350 -#define LOGICAL_PAGE_DATA_SIZE__VALUE 0xffff +#define LOGICAL_PAGE_DATA_SIZE__VALUE GENMASK(15, 0) #define LOGICAL_PAGE_SPARE_SIZE 0x360 -#define LOGICAL_PAGE_SPARE_SIZE__VALUE 0xffff +#define LOGICAL_PAGE_SPARE_SIZE__VALUE GENMASK(15, 0) #define REVISION 0x370 -#define REVISION__VALUE 0xffff +#define REVISION__VALUE GENMASK(15, 0) #define ONFI_DEVICE_FEATURES 0x380 -#define ONFI_DEVICE_FEATURES__VALUE 0x003f +#define ONFI_DEVICE_FEATURES__VALUE GENMASK(5, 0) #define ONFI_OPTIONAL_COMMANDS 0x390 -#define ONFI_OPTIONAL_COMMANDS__VALUE 0x003f +#define ONFI_OPTIONAL_COMMANDS__VALUE GENMASK(5, 0) #define ONFI_TIMING_MODE 0x3a0 -#define ONFI_TIMING_MODE__VALUE 0x003f +#define ONFI_TIMING_MODE__VALUE GENMASK(5, 0) #define ONFI_PGM_CACHE_TIMING_MODE 0x3b0 -#define ONFI_PGM_CACHE_TIMING_MODE__VALUE 0x003f +#define ONFI_PGM_CACHE_TIMING_MODE__VALUE GENMASK(5, 0) #define ONFI_DEVICE_NO_OF_LUNS 0x3c0 -#define ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS 0x00ff -#define ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE 0x0100 +#define ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS GENMASK(7, 0) +#define ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE BIT(8) #define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L 0x3d0 -#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L__VALUE 0xffff +#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L__VALUE GENMASK(15, 0) #define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U 0x3e0 -#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U__VALUE 0xffff - -#define FEATURES 0x3f0 -#define FEATURES__N_BANKS 0x0003 -#define FEATURES__ECC_MAX_ERR 0x003c -#define FEATURES__DMA 0x0040 -#define FEATURES__CMD_DMA 0x0080 -#define FEATURES__PARTITION 0x0100 -#define FEATURES__XDMA_SIDEBAND 0x0200 -#define FEATURES__GPREG 0x0400 -#define FEATURES__INDEX_ADDR 0x0800 +#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U__VALUE GENMASK(15, 0) + +#define FEATURES 0x3f0 +#define FEATURES__N_BANKS GENMASK(1, 0) +#define FEATURES__ECC_MAX_ERR GENMASK(5, 2) +#define FEATURES__DMA BIT(6) +#define FEATURES__CMD_DMA BIT(7) +#define FEATURES__PARTITION BIT(8) +#define FEATURES__XDMA_SIDEBAND BIT(9) +#define FEATURES__GPREG BIT(10) +#define FEATURES__INDEX_ADDR BIT(11) #define TRANSFER_MODE 0x400 -#define TRANSFER_MODE__VALUE 0x0003 +#define TRANSFER_MODE__VALUE GENMASK(1, 0) -#define INTR_STATUS(__bank) (0x410 + ((__bank) * 0x50)) -#define INTR_EN(__bank) (0x420 + ((__bank) * 0x50)) +#define INTR_STATUS(bank) (0x410 + (bank) * 0x50) +#define INTR_EN(bank) (0x420 + (bank) * 0x50) /* bit[1:0] is used differently depending on IP version */ -#define INTR__ECC_UNCOR_ERR 0x0001 /* new IP */ -#define INTR__ECC_TRANSACTION_DONE 0x0001 /* old IP */ -#define INTR__ECC_ERR 0x0002 /* old IP */ -#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)) -#define ERR_BLOCK_ADDR(__bank) (0x450 + ((__bank) * 0x50)) +#define INTR__ECC_UNCOR_ERR BIT(0) /* new IP */ +#define INTR__ECC_TRANSACTION_DONE BIT(0) /* old IP */ +#define INTR__ECC_ERR BIT(1) /* old IP */ +#define INTR__DMA_CMD_COMP BIT(2) +#define INTR__TIME_OUT BIT(3) +#define INTR__PROGRAM_FAIL BIT(4) +#define INTR__ERASE_FAIL BIT(5) +#define INTR__LOAD_COMP BIT(6) +#define INTR__PROGRAM_COMP BIT(7) +#define INTR__ERASE_COMP BIT(8) +#define INTR__PIPE_CPYBCK_CMD_COMP BIT(9) +#define INTR__LOCKED_BLK BIT(10) +#define INTR__UNSUP_CMD BIT(11) +#define INTR__INT_ACT BIT(12) +#define INTR__RST_COMP BIT(13) +#define INTR__PIPE_CMD_ERR BIT(14) +#define INTR__PAGE_XFER_INC BIT(15) + +#define PAGE_CNT(bank) (0x430 + (bank) * 0x50) +#define ERR_PAGE_ADDR(bank) (0x440 + (bank) * 0x50) +#define ERR_BLOCK_ADDR(bank) (0x450 + (bank) * 0x50) #define ECC_THRESHOLD 0x600 -#define ECC_THRESHOLD__VALUE 0x03ff +#define ECC_THRESHOLD__VALUE GENMASK(9, 0) #define ECC_ERROR_BLOCK_ADDRESS 0x610 -#define ECC_ERROR_BLOCK_ADDRESS__VALUE 0xffff +#define ECC_ERROR_BLOCK_ADDRESS__VALUE GENMASK(15, 0) #define ECC_ERROR_PAGE_ADDRESS 0x620 -#define ECC_ERROR_PAGE_ADDRESS__VALUE 0x0fff -#define ECC_ERROR_PAGE_ADDRESS__BANK 0xf000 +#define ECC_ERROR_PAGE_ADDRESS__VALUE GENMASK(11, 0) +#define ECC_ERROR_PAGE_ADDRESS__BANK GENMASK(15, 12) #define ECC_ERROR_ADDRESS 0x630 -#define ECC_ERROR_ADDRESS__OFFSET 0x0fff -#define ECC_ERROR_ADDRESS__SECTOR_NR 0xf000 +#define ECC_ERROR_ADDRESS__OFFSET GENMASK(11, 0) +#define ECC_ERROR_ADDRESS__SECTOR_NR GENMASK(15, 12) #define ERR_CORRECTION_INFO 0x640 -#define ERR_CORRECTION_INFO__BYTEMASK 0x00ff -#define ERR_CORRECTION_INFO__DEVICE_NR 0x0f00 -#define ERR_CORRECTION_INFO__ERROR_TYPE 0x4000 -#define ERR_CORRECTION_INFO__LAST_ERR_INFO 0x8000 +#define ERR_CORRECTION_INFO__BYTEMASK GENMASK(7, 0) +#define ERR_CORRECTION_INFO__DEVICE_NR GENMASK(11, 8) +#define ERR_CORRECTION_INFO__ERROR_TYPE BIT(14) +#define ERR_CORRECTION_INFO__LAST_ERR_INFO BIT(15) #define ECC_COR_INFO(bank) (0x650 + (bank) / 2 * 0x10) #define ECC_COR_INFO__SHIFT(bank) ((bank) % 2 * 8) -#define ECC_COR_INFO__MAX_ERRORS 0x007f -#define ECC_COR_INFO__UNCOR_ERR 0x0080 +#define ECC_COR_INFO__MAX_ERRORS GENMASK(6, 0) +#define ECC_COR_INFO__UNCOR_ERR BIT(7) #define CFG_DATA_BLOCK_SIZE 0x6b0 @@ -274,31 +268,31 @@ #define CFG_META_DATA_SIZE 0x6e0 #define DMA_ENABLE 0x700 -#define DMA_ENABLE__FLAG 0x0001 +#define DMA_ENABLE__FLAG BIT(0) #define IGNORE_ECC_DONE 0x710 -#define IGNORE_ECC_DONE__FLAG 0x0001 +#define IGNORE_ECC_DONE__FLAG BIT(0) #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__TARGET_ERROR BIT(0) +#define DMA_INTR__DESC_COMP_CHANNEL0 BIT(1) +#define DMA_INTR__DESC_COMP_CHANNEL1 BIT(2) +#define DMA_INTR__DESC_COMP_CHANNEL2 BIT(3) +#define DMA_INTR__DESC_COMP_CHANNEL3 BIT(4) +#define DMA_INTR__MEMCOPY_DESC_COMP BIT(5) #define TARGET_ERR_ADDR_LO 0x740 -#define TARGET_ERR_ADDR_LO__VALUE 0xffff +#define TARGET_ERR_ADDR_LO__VALUE GENMASK(15, 0) #define TARGET_ERR_ADDR_HI 0x750 -#define TARGET_ERR_ADDR_HI__VALUE 0xffff +#define TARGET_ERR_ADDR_HI__VALUE GENMASK(15, 0) #define CHNL_ACTIVE 0x760 -#define CHNL_ACTIVE__CHANNEL0 0x0001 -#define CHNL_ACTIVE__CHANNEL1 0x0002 -#define CHNL_ACTIVE__CHANNEL2 0x0004 -#define CHNL_ACTIVE__CHANNEL3 0x0008 +#define CHNL_ACTIVE__CHANNEL0 BIT(0) +#define CHNL_ACTIVE__CHANNEL1 BIT(1) +#define CHNL_ACTIVE__CHANNEL2 BIT(2) +#define CHNL_ACTIVE__CHANNEL3 BIT(3) #define FAIL 1 /*failed flag*/ #define PASS 0 /*success flag*/ From patchwork Thu Mar 30 06:46:06 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 96235 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp102419qgd; Wed, 29 Mar 2017 23:49:48 -0700 (PDT) X-Received: by 10.99.106.71 with SMTP id f68mr4534591pgc.227.1490856588399; Wed, 29 Mar 2017 23:49:48 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i64si1228899pfa.421.2017.03.29.23.49.48; Wed, 29 Mar 2017 23:49:48 -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 S1755674AbdC3Gtj (ORCPT + 22 others); Thu, 30 Mar 2017 02:49:39 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:40683 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933126AbdC3Gt3 (ORCPT ); Thu, 30 Mar 2017 02:49:29 -0400 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2U6kUci015463; Thu, 30 Mar 2017 15:46:57 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2U6kUci015463 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490856418; bh=eC4lEffolqw3YxVid3RJa5fJ9tdIQVyk4Z3NuLqiG3E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OjOe0qKrCz/3XdzQpVQ6MnDrDbmSioPuLNocVrwBlkpbdyCMA9vmlyzsaqXPYSQ40 iVq48XMBqTHRiI/2yltlwRKQ3LZcqxWb8mY9B5qX1v3tMJJdYjthWMw/H8ylIg4AEs 4DXl6XUmbfURC+Bv3lyRLBgGt6Hvx6goylUeIGPDLo6PNW1e+6ibxWAOhvOR3W7psd HXWD0C9WvvS7IytzvJc7EkP5nEJ/EcBoID6zFar3FKybh/tkkM+oGpUTMkl1tL9BT4 BDJ8nUdW6NC8py9cDgB9gEOLiN339ftEweqlQErip6FKdHjhUR9D8eDph1MRHOf1II bUq4t1Hse71iA== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: Enrico Jorns , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Brian Norris , Richard Weinberger , Cyrille Pitchen Subject: [PATCH v3 20/37] mtd: nand: denali: remove unneeded find_valid_banks() Date: Thu, 30 Mar 2017 15:46:06 +0900 Message-Id: <1490856383-31560-21-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490856383-31560-1-git-send-email-yamada.masahiro@socionext.com> References: <1490856383-31560-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 function find_valid_banks() issues the Read ID (0x90) command, then compares the first byte (Manufacturer ID) of each bank with the one of bank0. This is equivalent to what nand_scan_ident() does. The number of chips is detected there, so this is unneeded. What is worse for find_valid_banks() is that, if multiple chips are connected to INTEL_CE4100 platform, it crashes the kernel by BUG(). This is what we should avoid. This function is just harmful and unneeded. Signed-off-by: Masahiro Yamada --- Changes in v3: None Changes in v2: - Newly added drivers/mtd/nand/denali.c | 47 ----------------------------------------------- drivers/mtd/nand/denali.h | 1 - 2 files changed, 48 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 5da8156..0c93a07 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -338,51 +338,6 @@ static void get_samsung_nand_para(struct denali_nand_info *denali, } /* - * determines how many NAND chips are connected to the controller. Note for - * Intel CE4100 devices we don't support more than one device. - */ -static void find_valid_banks(struct denali_nand_info *denali) -{ - uint32_t id[denali->max_banks]; - int i; - - denali->total_used_banks = 1; - for (i = 0; i < denali->max_banks; i++) { - index_addr(denali, MODE_11 | (i << 24) | 0, 0x90); - index_addr(denali, MODE_11 | (i << 24) | 1, 0); - index_addr_read_data(denali, MODE_11 | (i << 24) | 2, &id[i]); - - dev_dbg(denali->dev, - "Return 1st ID for bank[%d]: %x\n", i, id[i]); - - if (i == 0) { - if (!(id[i] & 0x0ff)) - break; /* WTF? */ - } else { - if ((id[i] & 0x0ff) == (id[0] & 0x0ff)) - denali->total_used_banks++; - else - break; - } - } - - if (denali->platform == INTEL_CE4100) { - /* - * Platform limitations of the CE4100 device limit - * users to a single chip solution for NAND. - * Multichip support is not enabled. - */ - if (denali->total_used_banks != 1) { - dev_err(denali->dev, - "Sorry, Intel CE4100 only supports a single NAND device.\n"); - BUG(); - } - } - dev_dbg(denali->dev, - "denali->total_used_banks: %d\n", denali->total_used_banks); -} - -/* * Use the configuration feature register to determine the maximum number of * banks that the hardware supports. */ @@ -439,8 +394,6 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali) ioread32(denali->flash_reg + RDWR_EN_HI_CNT), ioread32(denali->flash_reg + CS_SETUP_CNT)); - find_valid_banks(denali); - /* * If the user specified to override the default timings * with a specific ONFI mode, we apply those changes here. diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 610b013..1f0a85a 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -326,7 +326,6 @@ struct denali_nand_info { int platform; struct nand_buf buf; struct device *dev; - int total_used_banks; int page; void __iomem *flash_reg; /* Register Interface */ void __iomem *flash_mem; /* Host Data/Command Interface */ From patchwork Thu Mar 30 06:46:08 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 96251 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp104165qgd; Wed, 29 Mar 2017 23:56:20 -0700 (PDT) X-Received: by 10.84.218.68 with SMTP id f4mr5214246plm.146.1490856979927; Wed, 29 Mar 2017 23:56:19 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m18si1261179pfi.254.2017.03.29.23.56.19; Wed, 29 Mar 2017 23:56:19 -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 S933434AbdC3G4E (ORCPT + 22 others); Thu, 30 Mar 2017 02:56:04 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:39950 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932388AbdC3GtG (ORCPT ); Thu, 30 Mar 2017 02:49:06 -0400 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2U6kUck015463; Thu, 30 Mar 2017 15:47:00 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2U6kUck015463 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490856421; bh=NUgafsAfTwZcPHIrgHuotzPrmpCKbeeSZtA9usUyhOA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Cc7YzdsOrujY0otodCUxTApOgNJlzHc9xRXNEE/IXRv2Usew7hWZHWstncJgBrrBb djB6OsQKiy9qdsHEO7f1cIc3PUzq95sqs27Y2IuntwuxKyKZPtGlPjN0JIqNYXgt5U jB6vNF+ROjyyo5Q90iJV4aeqnfI0JdgKpQhVccKEP4wOxRc8CfreS8hsaIdgtY4A2x gcfJPYUas6Tg3DGwrrvd5g1zS0b3esG59HRPafK51QpkSATVaTDmQbZMlKMxmDn/Qv vDNwx39K2+SMBELHFWIk5wVSMVzZ4X6rRfetU8FaYOa7f0ke5wES+KMPuOpSpYJ26H ihKv4707rKTnA== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: Enrico Jorns , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Brian Norris , Richard Weinberger , Cyrille Pitchen Subject: [PATCH v3 22/37] mtd: nand: denali: rework interrupt handling Date: Thu, 30 Mar 2017 15:46:08 +0900 Message-Id: <1490856383-31560-23-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490856383-31560-1-git-send-email-yamada.masahiro@socionext.com> References: <1490856383-31560-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 Simplify the interrupt handling and fix issues: - The register field view of INTR_EN / INTR_STATUS is different among IP versions. The global macro DENALI_IRQ_ALL is hard-coded for Intel platforms. The interrupt mask should be determined at run-time depending on the running platform. - wait_for_irq() loops do {} while() until interested flags are asserted. The logic can be simplified. - The spin_lock() guard seems too complex (and suspicious in a race condition if wait_for_completion_timeout() bails out by timeout). - denali->complete is reused again and again, but reinit_completion() is missing. Add it. Re-work the code to make it more robust and easier to handle. While we are here, also rename the jump label "failed_req_irq" to more appropriate "disable_irq". Signed-off-by: Masahiro Yamada --- Changes in v3: None Changes in v2: - Newly added drivers/mtd/nand/denali.c | 320 +++++++++++++++++----------------------------- drivers/mtd/nand/denali.h | 1 + 2 files changed, 118 insertions(+), 203 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index ea566ea..75b045e0 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -31,21 +31,6 @@ MODULE_LICENSE("GPL"); #define DENALI_NAND_NAME "denali-nand" /* - * We define a macro here that combines all interrupts this driver uses into - * a single constant value, for convenience. - */ -#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 * valid or not */ @@ -71,20 +56,14 @@ static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd) #define DENALI_READ 0 #define DENALI_WRITE 0x100 +#define DENALI_NR_BANKS 4 + /* * this is a helper macro that allows us to * format the bank into the proper bits for the controller */ #define BANK(x) ((x) << 24) -/* forward declarations */ -static void clear_interrupts(struct denali_nand_info *denali); -static uint32_t wait_for_irq(struct denali_nand_info *denali, - uint32_t irq_mask); -static void denali_irq_enable(struct denali_nand_info *denali, - uint32_t int_mask); -static uint32_t read_interrupt_status(struct denali_nand_info *denali); - /* * The bus interface clock, clk_x, is phase aligned with the core clock. The * clk_x is an integral multiple N of the core clk. The value N is configured @@ -143,22 +122,6 @@ static void read_status(struct denali_nand_info *denali) write_byte_to_buf(denali, 0); } -/* resets a specific device connected to the core */ -static void reset_bank(struct denali_nand_info *denali) -{ - uint32_t irq_status; - uint32_t irq_mask = INTR__RST_COMP | INTR__TIME_OUT; - - clear_interrupts(denali); - - iowrite32(1 << denali->flash_bank, denali->flash_reg + DEVICE_RESET); - - irq_status = wait_for_irq(denali, irq_mask); - - if (irq_status & INTR__TIME_OUT) - dev_err(denali->dev, "reset bank failed.\n"); -} - /* Reset the flash controller */ static uint16_t denali_nand_reset(struct denali_nand_info *denali) { @@ -201,169 +164,123 @@ static void detect_max_banks(struct denali_nand_info *denali) denali->max_banks <<= 1; } -static void denali_set_intr_modes(struct denali_nand_info *denali, - uint16_t INT_ENABLE) +static void denali_enable_irq(struct denali_nand_info *denali) { - if (INT_ENABLE) - iowrite32(1, denali->flash_reg + GLOBAL_INT_ENABLE); - else - iowrite32(0, denali->flash_reg + GLOBAL_INT_ENABLE); -} + int i; -/* - * validation function to verify that the controlling software is making - * a valid request - */ -static inline bool is_flash_bank_valid(int flash_bank) -{ - return flash_bank >= 0 && flash_bank < 4; + for (i = 0; i < DENALI_NR_BANKS; i++) + iowrite32(U32_MAX, denali->flash_reg + INTR_EN(i)); + iowrite32(GLOBAL_INT_EN_FLAG, denali->flash_reg + GLOBAL_INT_ENABLE); } -static void denali_irq_init(struct denali_nand_info *denali) +static void denali_disable_irq(struct denali_nand_info *denali) { - uint32_t int_mask; int i; - /* Disable global interrupts */ - denali_set_intr_modes(denali, false); - - int_mask = DENALI_IRQ_ALL; - - /* Clear all status bits */ - for (i = 0; i < denali->max_banks; ++i) - iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS(i)); - - denali_irq_enable(denali, int_mask); + for (i = 0; i < DENALI_NR_BANKS; i++) + iowrite32(0, denali->flash_reg + INTR_EN(i)); + iowrite32(0, denali->flash_reg + GLOBAL_INT_ENABLE); } -static void denali_irq_cleanup(int irqnum, struct denali_nand_info *denali) +static void denali_clear_irq(struct denali_nand_info *denali, + int bank, uint32_t irq_status) { - denali_set_intr_modes(denali, false); + /* write one to clear bits */ + iowrite32(irq_status, denali->flash_reg + INTR_STATUS(bank)); } -static void denali_irq_enable(struct denali_nand_info *denali, - uint32_t int_mask) +static void denali_clear_irq_all(struct denali_nand_info *denali) { int i; - for (i = 0; i < denali->max_banks; ++i) - iowrite32(int_mask, denali->flash_reg + INTR_EN(i)); + for (i = 0; i < DENALI_NR_BANKS; i++) + denali_clear_irq(denali, i, U32_MAX); } -/* - * This function only returns when an interrupt that this driver cares about - * occurs. This is to reduce the overhead of servicing interrupts - */ -static inline uint32_t denali_irq_detected(struct denali_nand_info *denali) +static irqreturn_t denali_isr(int irq, void *dev_id) { - return read_interrupt_status(denali) & DENALI_IRQ_ALL; -} + struct denali_nand_info *denali = dev_id; + irqreturn_t ret = IRQ_NONE; + uint32_t irq_status; + int i; -/* Interrupts are cleared by writing a 1 to the appropriate status bit */ -static inline void clear_interrupt(struct denali_nand_info *denali, - uint32_t irq_mask) -{ - uint32_t intr_status_reg; + spin_lock(&denali->irq_lock); - intr_status_reg = INTR_STATUS(denali->flash_bank); + for (i = 0; i < DENALI_NR_BANKS; i++) { + irq_status = ioread32(denali->flash_reg + INTR_STATUS(i)); + if (irq_status) + ret = IRQ_HANDLED; - iowrite32(irq_mask, denali->flash_reg + intr_status_reg); -} + denali_clear_irq(denali, i, irq_status); -static void clear_interrupts(struct denali_nand_info *denali) -{ - uint32_t status; + if (i != denali->flash_bank) + continue; - spin_lock_irq(&denali->irq_lock); + denali->irq_status |= irq_status; - status = read_interrupt_status(denali); - clear_interrupt(denali, status); + if (denali->irq_status & denali->irq_mask) + complete(&denali->complete); + } + + spin_unlock(&denali->irq_lock); - denali->irq_status = 0x0; - spin_unlock_irq(&denali->irq_lock); + return ret; } -static uint32_t read_interrupt_status(struct denali_nand_info *denali) +static void denali_reset_irq(struct denali_nand_info *denali) { - uint32_t intr_status_reg; - - intr_status_reg = INTR_STATUS(denali->flash_bank); + unsigned long flags; - return ioread32(denali->flash_reg + intr_status_reg); + spin_lock_irqsave(&denali->irq_lock, flags); + denali->irq_status = 0; + denali->irq_mask = 0; + spin_unlock_irqrestore(&denali->irq_lock, flags); } -/* - * This is the interrupt service routine. It handles all interrupts - * sent to this device. Note that on CE4100, this is a shared interrupt. - */ -static irqreturn_t denali_isr(int irq, void *dev_id) +static uint32_t denali_wait_for_irq(struct denali_nand_info *denali, + uint32_t irq_mask) { - struct denali_nand_info *denali = dev_id; + unsigned long time_left, flags; uint32_t irq_status; - irqreturn_t result = IRQ_NONE; - spin_lock(&denali->irq_lock); + spin_lock_irqsave(&denali->irq_lock, flags); - /* check to see if a valid NAND chip has been selected. */ - if (is_flash_bank_valid(denali->flash_bank)) { - /* - * check to see if controller generated the interrupt, - * since this is a shared interrupt - */ - irq_status = denali_irq_detected(denali); - if (irq_status != 0) { - /* handle interrupt */ - /* first acknowledge it */ - clear_interrupt(denali, irq_status); - /* - * store the status in the device context for someone - * to read - */ - denali->irq_status |= irq_status; - /* notify anyone who cares that it happened */ - complete(&denali->complete); - /* tell the OS that we've handled this */ - result = IRQ_HANDLED; - } + irq_status = denali->irq_status; + + if (irq_mask & irq_status) { + spin_unlock_irqrestore(&denali->irq_lock, flags); + return irq_status; } - spin_unlock(&denali->irq_lock); - return result; + + denali->irq_mask = irq_mask; + reinit_completion(&denali->complete); + spin_unlock_irqrestore(&denali->irq_lock, flags); + + time_left = wait_for_completion_timeout(&denali->complete, + msecs_to_jiffies(1000)); + if (!time_left) { + dev_err(denali->dev, "timeout while waiting for irq 0x%x\n", + denali->irq_mask); + return 0; + } + + return denali->irq_status; } -static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask) +/* resets a specific device connected to the core */ +static void reset_bank(struct denali_nand_info *denali) { - unsigned long comp_res; - uint32_t intr_status; - unsigned long timeout = msecs_to_jiffies(1000); + uint32_t irq_status; - do { - comp_res = - wait_for_completion_timeout(&denali->complete, timeout); - spin_lock_irq(&denali->irq_lock); - intr_status = denali->irq_status; - - if (intr_status & irq_mask) { - denali->irq_status &= ~irq_mask; - spin_unlock_irq(&denali->irq_lock); - /* our interrupt was detected */ - break; - } + denali_reset_irq(denali); - /* - * these are not the interrupts you are looking for - - * need to wait again - */ - spin_unlock_irq(&denali->irq_lock); - } while (comp_res != 0); + iowrite32(1 << denali->flash_bank, denali->flash_reg + DEVICE_RESET); - if (comp_res == 0) { - /* timeout */ - pr_err("timeout occurred, status = 0x%x, mask = 0x%x\n", - intr_status, irq_mask); + irq_status = denali_wait_for_irq(denali, + INTR__RST_COMP | INTR__TIME_OUT); - intr_status = 0; - } - return intr_status; + if (!(irq_status & INTR__RST_COMP)) + dev_err(denali->dev, "reset bank failed.\n"); } /* @@ -397,7 +314,7 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali, setup_ecc_for_xfer(denali, ecc_en, transfer_spare); - clear_interrupts(denali); + denali_reset_irq(denali); addr = BANK(denali->flash_bank) | denali->page; @@ -479,9 +396,9 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) write_data_to_flash_mem(denali, buf, mtd->oobsize); /* wait for operation to complete */ - irq_status = wait_for_irq(denali, irq_mask); + irq_status = denali_wait_for_irq(denali, irq_mask); - if (irq_status == 0) { + if (!(irq_status & INTR__PROGRAM_COMP)) { dev_err(denali->dev, "OOB write failed\n"); status = -EIO; } @@ -510,9 +427,9 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) * can always use status0 bit as the * mask is identical for each bank. */ - irq_status = wait_for_irq(denali, irq_mask); + irq_status = denali_wait_for_irq(denali, irq_mask); - if (irq_status == 0) + if (!(irq_status & INTR__LOAD_COMP)) dev_err(denali->dev, "page on OOB timeout %d\n", denali->page); @@ -620,9 +537,9 @@ static int denali_sw_ecc_fixup(struct mtd_info *mtd, unsigned int err_byte, err_sector, err_device; uint8_t err_cor_value; unsigned int prev_sector = 0; + uint32_t irq_status; - /* read the ECC errors. we'll ignore them for now */ - denali_set_intr_modes(denali, false); + denali_reset_irq(denali); do { err_addr = ioread32(denali->flash_reg + ECC_ERROR_ADDRESS); @@ -674,10 +591,9 @@ static int denali_sw_ecc_fixup(struct mtd_info *mtd, * 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); + irq_status = denali_wait_for_irq(denali, INTR__ECC_TRANSACTION_DONE); + if (!(irq_status & INTR__ECC_TRANSACTION_DONE)) + return -EIO; return max_bitflips; } @@ -778,15 +694,14 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *chip, dma_sync_single_for_device(denali->dev, addr, size, DMA_TO_DEVICE); - clear_interrupts(denali); + denali_reset_irq(denali); denali_enable_dma(denali, true); denali_setup_dma(denali, DENALI_WRITE); /* wait for operation to complete */ - irq_status = wait_for_irq(denali, irq_mask); - - if (irq_status == 0) { + irq_status = denali_wait_for_irq(denali, irq_mask); + if (!(irq_status & INTR__DMA_CMD_COMP)) { dev_err(denali->dev, "timeout on write_page (type = %d)\n", raw_xfer); ret = -EIO; @@ -865,11 +780,11 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, denali_enable_dma(denali, true); dma_sync_single_for_device(denali->dev, addr, size, DMA_FROM_DEVICE); - clear_interrupts(denali); + denali_reset_irq(denali); denali_setup_dma(denali, DENALI_READ); /* wait for operation to complete */ - irq_status = wait_for_irq(denali, irq_mask); + irq_status = denali_wait_for_irq(denali, irq_mask); dma_sync_single_for_cpu(denali->dev, addr, size, DMA_FROM_DEVICE); @@ -901,6 +816,7 @@ static int denali_read_page_raw(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_mask = INTR__DMA_CMD_COMP; + uint32_t irq_status; denali->page = page; @@ -909,11 +825,13 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, dma_sync_single_for_device(denali->dev, addr, size, DMA_FROM_DEVICE); - clear_interrupts(denali); + denali_reset_irq(denali); denali_setup_dma(denali, DENALI_READ); /* wait for operation to complete */ - wait_for_irq(denali, irq_mask); + irq_status = denali_wait_for_irq(denali, irq_mask); + if (irq_status & INTR__DMA_CMD_COMP) + return -ETIMEDOUT; dma_sync_single_for_cpu(denali->dev, addr, size, DMA_FROM_DEVICE); @@ -940,9 +858,7 @@ static void denali_select_chip(struct mtd_info *mtd, int chip) { struct denali_nand_info *denali = mtd_to_denali(mtd); - spin_lock_irq(&denali->irq_lock); denali->flash_bank = chip; - spin_unlock_irq(&denali->irq_lock); } static int denali_waitfunc(struct mtd_info *mtd, struct nand_chip *chip) @@ -953,19 +869,19 @@ static int denali_waitfunc(struct mtd_info *mtd, struct nand_chip *chip) static int denali_erase(struct mtd_info *mtd, int page) { struct denali_nand_info *denali = mtd_to_denali(mtd); - uint32_t cmd, irq_status; - clear_interrupts(denali); + denali_reset_irq(denali); /* setup page read request for access type */ cmd = MODE_10 | BANK(denali->flash_bank) | page; index_addr(denali, cmd, 0x1); /* wait for erase to complete or failure to occur */ - irq_status = wait_for_irq(denali, INTR__ERASE_COMP | INTR__ERASE_FAIL); + irq_status = denali_wait_for_irq(denali, + INTR__ERASE_COMP | INTR__ERASE_FAIL); - return irq_status & INTR__ERASE_FAIL ? NAND_STATUS_FAIL : PASS; + return irq_status & INTR__ERASE_COMP ? 0 : NAND_STATUS_FAIL; } static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, @@ -1153,7 +1069,6 @@ static void denali_hw_init(struct denali_nand_info *denali) /* Should set value for these registers when init */ iowrite32(0, denali->flash_reg + TWO_ROW_ADDR_CYCLES); iowrite32(1, denali->flash_reg + ECC_ENABLE); - denali_irq_init(denali); } static int denali_calc_ecc_bytes(int ecc_size, int ecc_strength) @@ -1271,9 +1186,6 @@ static void denali_drv_init(struct denali_nand_info *denali) /* indicate that MTD has not selected a valid bank yet */ denali->flash_bank = CHIP_SELECT_INVALID; - - /* initialize our irq_status variable to indicate no interrupts */ - denali->irq_status = 0; } static int denali_multidev_fixup(struct denali_nand_info *denali) @@ -1343,6 +1255,8 @@ int denali_init(struct denali_nand_info *denali) denali_hw_init(denali); denali_drv_init(denali); + denali_clear_irq_all(denali); + /* Request IRQ after all the hardware initialization is finished */ ret = devm_request_irq(denali->dev, denali->irq, denali_isr, IRQF_SHARED, DENALI_NAND_NAME, denali); @@ -1351,8 +1265,8 @@ int denali_init(struct denali_nand_info *denali) return ret; } - /* now that our ISR is registered, we can enable interrupts */ - denali_set_intr_modes(denali, true); + denali_enable_irq(denali); + nand_set_flash_node(chip, denali->dev->of_node); /* Fallback to the default name if DT did not give "label" property */ if (!mtd->name) @@ -1374,7 +1288,7 @@ int denali_init(struct denali_nand_info *denali) */ ret = nand_scan_ident(mtd, denali->max_banks, NULL); if (ret) - goto failed_req_irq; + goto disable_irq; /* allocate the right size buffer now */ devm_kfree(denali->dev, denali->buf.buf); @@ -1383,7 +1297,7 @@ int denali_init(struct denali_nand_info *denali) GFP_KERNEL); if (!denali->buf.buf) { ret = -ENOMEM; - goto failed_req_irq; + goto disable_irq; } ret = dma_set_mask(denali->dev, @@ -1391,7 +1305,7 @@ int denali_init(struct denali_nand_info *denali) 64 : 32)); if (ret) { dev_err(denali->dev, "No usable DMA configuration\n"); - goto failed_req_irq; + goto disable_irq; } denali->buf.dma_buf = dma_map_single(denali->dev, denali->buf.buf, @@ -1400,7 +1314,7 @@ int denali_init(struct denali_nand_info *denali) if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) { dev_err(denali->dev, "Failed to map DMA buffer\n"); ret = -EIO; - goto failed_req_irq; + goto disable_irq; } /* @@ -1442,7 +1356,7 @@ int denali_init(struct denali_nand_info *denali) !(chip->ecc.size == 1024 && denali->caps & DENALI_CAP_ECC_SIZE_1024)) { dev_err(denali->dev, "ECC size %d is not supported on this controller", chip->ecc.size); - goto failed_req_irq; + goto disable_irq; } if (!chip->ecc.strength && !(chip->ecc.options & NAND_ECC_MAXIMIZE)) { @@ -1454,13 +1368,13 @@ int denali_init(struct denali_nand_info *denali) if (chip->ecc.options & NAND_ECC_MAXIMIZE) { ret = denali_set_max_ecc_strength(denali); if (ret) - goto failed_req_irq; + goto disable_irq; } else if (!(denali->ecc_strength_avail & BIT(chip->ecc.strength))) { dev_err(denali->dev, "ECC strength %d is not supported on this controller.\n", chip->ecc.strength); ret = -EINVAL; - goto failed_req_irq; + goto disable_irq; } chip->ecc.bytes = denali_calc_ecc_bytes(chip->ecc.size, @@ -1493,21 +1407,21 @@ int denali_init(struct denali_nand_info *denali) ret = denali_multidev_fixup(denali); if (ret) - goto failed_req_irq; + goto disable_irq; ret = nand_scan_tail(mtd); if (ret) - goto failed_req_irq; + goto disable_irq; ret = mtd_device_register(mtd, NULL, 0); if (ret) { dev_err(denali->dev, "Failed to register MTD: %d\n", ret); - goto failed_req_irq; + goto disable_irq; } return 0; -failed_req_irq: - denali_irq_cleanup(denali->irq, denali); +disable_irq: + denali_disable_irq(denali); return ret; } @@ -1525,7 +1439,7 @@ void denali_remove(struct denali_nand_info *denali) int bufsize = mtd->writesize + mtd->oobsize; nand_release(mtd); - denali_irq_cleanup(denali->irq, denali); + denali_disable_irq(denali); dma_unmap_single(denali->dev, denali->buf.dma_buf, bufsize, DMA_BIDIRECTIONAL); } diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index e55bb2e..7797340 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -326,6 +326,7 @@ struct denali_nand_info { /* elements used by ISR */ struct completion complete; spinlock_t irq_lock; + uint32_t irq_mask; uint32_t irq_status; int irq; From patchwork Thu Mar 30 06:46:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 96249 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp103835qgd; Wed, 29 Mar 2017 23:55:04 -0700 (PDT) X-Received: by 10.98.217.140 with SMTP id b12mr4448654pfl.136.1490856904356; Wed, 29 Mar 2017 23:55:04 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t9si1262655pfa.157.2017.03.29.23.55.04; Wed, 29 Mar 2017 23:55:04 -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 S933386AbdC3GzB (ORCPT + 22 others); Thu, 30 Mar 2017 02:55:01 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:40040 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932899AbdC3GtI (ORCPT ); Thu, 30 Mar 2017 02:49:08 -0400 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2U6kUcl015463; Thu, 30 Mar 2017 15:47:01 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2U6kUcl015463 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490856422; bh=QXb6nxWz0TYDDVdmwj+kDkL9EAQ3dwIVcJKSz15trWs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=13Jv/UwcStczx9bfNkLNcP5mEUbGWJMNJbU4cdqRKyoZg9fOo+9DXXFlRXIfhEABk lGHHObp5W4QhXQ0YyjxnUpmypRvQTkyOPh0JpLVZvFctT8rWJ6xkn41tbRUsXIucCL wTx/edkecK9zInb7nGYNKz9EtiApcqdilwAjXgVq6Jmi7Mo0ILKflWE2ekJVKmNHpe 343HV3URXHIYwZg1Qf4dnyI3RSuZmGogPARMbrXQhop8FrY7TyVpTfu8u1sWRuuh4i MhK28Fa2BArN9yiqorbmMserMVyFJeabY1kQoP/uNqyYX+zcZ7+/l+1NBdHUhzDiUW iy3sMUWll2QKQ== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: Enrico Jorns , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Brian Norris , Richard Weinberger , Cyrille Pitchen Subject: [PATCH v3 23/37] mtd: nand: denali: fix NAND_CMD_STATUS handling Date: Thu, 30 Mar 2017 15:46:09 +0900 Message-Id: <1490856383-31560-24-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490856383-31560-1-git-send-email-yamada.masahiro@socionext.com> References: <1490856383-31560-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 current NAND_CMD_STATUS handling is weird; it just reads the WRITE_PROTECT register, and returns NAND_STATUS_WP if it is set. It does not send Read Status (0x70) command, so it is not helpful for checking the current device status. Signed-off-by: Masahiro Yamada --- Changes in v3: None Changes in v2: - Newly added drivers/mtd/nand/denali.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 75b045e0..bca4fcd 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -107,21 +107,6 @@ static void write_byte_to_buf(struct denali_nand_info *denali, uint8_t byte) denali->buf.buf[denali->buf.tail++] = byte; } -/* reads the status of the device */ -static void read_status(struct denali_nand_info *denali) -{ - uint32_t cmd; - - /* initialize the data buffer to store status */ - reset_buf(denali); - - cmd = ioread32(denali->flash_reg + WRITE_PROTECT); - if (cmd) - write_byte_to_buf(denali, NAND_STATUS_WP); - else - write_byte_to_buf(denali, 0); -} - /* Reset the flash controller */ static uint16_t denali_nand_reset(struct denali_nand_info *denali) { @@ -893,7 +878,11 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, switch (cmd) { case NAND_CMD_STATUS: - read_status(denali); + reset_buf(denali); + addr = MODE_11 | BANK(denali->flash_bank); + index_addr(denali, addr | 0, cmd); + index_addr_read_data(denali, addr | 2, &id); + write_byte_to_buf(denali, id); break; case NAND_CMD_READID: case NAND_CMD_PARAM: From patchwork Thu Mar 30 06:46:10 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 96252 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp104285qgd; Wed, 29 Mar 2017 23:56:52 -0700 (PDT) X-Received: by 10.99.150.1 with SMTP id c1mr4467095pge.160.1490857011968; Wed, 29 Mar 2017 23:56:51 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g21si1255511pgj.268.2017.03.29.23.56.51; Wed, 29 Mar 2017 23:56:51 -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 S933388AbdC3G4B (ORCPT + 22 others); Thu, 30 Mar 2017 02:56:01 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:39988 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932698AbdC3GtG (ORCPT ); Thu, 30 Mar 2017 02:49:06 -0400 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2U6kUcm015463; Thu, 30 Mar 2017 15:47:02 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2U6kUcm015463 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490856423; bh=Q2kZXsEea5dtFRr0k+7G+HYTzBnfxEa7j/iDm5UfBHM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=k5LZEwajuhE6Z6WktPeUnQWEbRiNJFhCpqPp+rpuVnmT9YXIW4dlyR92wVCtwBeVX QgAbEqsCKq2t301QjZBj8PypW54CKHrv8PmHNLea2Mhz8DsGuglE2KxLOC4d//VCRk Nk2WReNtjaxAQjg29UxNS0gjUeM96y9Kjd4gTor7ff8fXTtjeLuQr1pb2dToJKyo0s FSRV5pN4Quk9/Xl+awTPcQ6YnS4o4g/98VTgajB4IvNQaTjhcUW6r22fSb2sVej39a afndwXLV8Fbdn15o6OT7fh90Rk/WD/+tC4WY1cTF3gCA8EXTqlCJ/+anM05NEFtkq4 WB8BRipl9Wg0A== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: Enrico Jorns , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Brian Norris , Richard Weinberger , Cyrille Pitchen Subject: [PATCH v3 24/37] mtd: nand: denali: fix NAND_CMD_PARAM handling Date: Thu, 30 Mar 2017 15:46:10 +0900 Message-Id: <1490856383-31560-25-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490856383-31560-1-git-send-email-yamada.masahiro@socionext.com> References: <1490856383-31560-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 NAND_CMD_PARAM is not working at all due to multiple bugs. [1] The command 0x90 issued instead of 0xec The command code 0x90 is hard-code as index_addr(denali, addr | 0, 0x90) So, Read ID (0x90) command is sent to the device instead of Read Parameter Page (0xec). [2] only first 8 bytes are read Even if [1] is fixed, the current implementation is problematic. The only first 8 bytes are read by MAP11 command, and put into the temporal buffer: for (i = 0; i < 8; i++) { index_addr_read_data(denali, addr | 2, &id); write_byte_to_buf(denali, id); } Obviously, this is not sufficient for NAND_CMD_PARAM; the ONFi parameters are 256-byte long. This is still insufficient. As you see in nand_flash_detect_onfi() reads out (256 * 3) bytes at maximum (Redundant Parameter Pages). However, changing the loop to for (i = 0; i < 768; i++) is a crazy idea. At the point of the chip->cmdfunc() call, we cannot know how many times chip->read_byte() will be called. So, pre-reading enough number of bytes in the chip->cmdfunc() is a design mistake. [3] no wait for R/B# The current code handles NAND_CMD_READID and NAND_CMD_PARAM in the same way, but this is also wrong. The difference between them is that Read ID command does not toggle R/B# whereas the Read Parameter Page command requires R/B#. Without the wait for R/B# interrupt, wrong data are retrieved. In order to fix those problems, data read cycle of the MAP11 command has been moved to chip->read_byte(). Data are read out as needed. Another good thing is early temporal buffer is not needed any more. The ugly devm_kzalloc()/devm_kfree() dance has been killed. Signed-off-by: Masahiro Yamada --- Changes in v3: None Changes in v2: - Newly added drivers/mtd/nand/denali.c | 95 +++++++++++++++-------------------------------- drivers/mtd/nand/denali.h | 2 - 2 files changed, 30 insertions(+), 67 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index bca4fcd..0e5e490 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -85,28 +85,6 @@ static void index_addr(struct denali_nand_info *denali, iowrite32(data, denali->flash_mem + 0x10); } -/* Perform an indexed read of the device */ -static void index_addr_read_data(struct denali_nand_info *denali, - uint32_t address, uint32_t *pdata) -{ - iowrite32(address, denali->flash_mem); - *pdata = ioread32(denali->flash_mem + 0x10); -} - -/* - * We need to buffer some data for some of the NAND core routines. - * The operations manage buffering that data. - */ -static void reset_buf(struct denali_nand_info *denali) -{ - denali->buf.head = denali->buf.tail = 0; -} - -static void write_byte_to_buf(struct denali_nand_info *denali, uint8_t byte) -{ - denali->buf.buf[denali->buf.tail++] = byte; -} - /* Reset the flash controller */ static uint16_t denali_nand_reset(struct denali_nand_info *denali) { @@ -286,6 +264,15 @@ static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_en, iowrite32(transfer_spare_flag, denali->flash_reg + TRANSFER_SPARE_REG); } +static uint8_t denali_read_byte(struct mtd_info *mtd) +{ + struct denali_nand_info *denali = mtd_to_denali(mtd); + + iowrite32(MODE_11 | BANK(denali->flash_bank) | 2, denali->flash_mem); + + return ioread32(denali->flash_mem + 0x10); +} + /* * sends a pipeline command operation to the controller. See the Denali NAND * controller's user guide for more information (section 4.2.3.6). @@ -828,17 +815,6 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, return 0; } -static uint8_t denali_read_byte(struct mtd_info *mtd) -{ - struct denali_nand_info *denali = mtd_to_denali(mtd); - uint8_t result = 0xff; - - if (denali->buf.head < denali->buf.tail) - result = denali->buf.buf[denali->buf.head++]; - - return result; -} - static void denali_select_chip(struct mtd_info *mtd, int chip) { struct denali_nand_info *denali = mtd_to_denali(mtd); @@ -873,43 +849,40 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, int page) { struct denali_nand_info *denali = mtd_to_denali(mtd); - uint32_t addr, id; - int i; + uint32_t addr, irq_status; + int wait_ready = 0; switch (cmd) { - case NAND_CMD_STATUS: - reset_buf(denali); - addr = MODE_11 | BANK(denali->flash_bank); - index_addr(denali, addr | 0, cmd); - index_addr_read_data(denali, addr | 2, &id); - write_byte_to_buf(denali, id); + case NAND_CMD_PARAM: + wait_ready = 1; break; + case NAND_CMD_STATUS: case NAND_CMD_READID: - case NAND_CMD_PARAM: - reset_buf(denali); - /* - * sometimes ManufactureId read from register is not right - * e.g. some of Micron MT29F32G08QAA MLC NAND chips - * So here we send READID cmd to NAND insteand - */ - addr = MODE_11 | BANK(denali->flash_bank); - index_addr(denali, addr | 0, 0x90); - index_addr(denali, addr | 1, col); - for (i = 0; i < 8; i++) { - index_addr_read_data(denali, addr | 2, &id); - write_byte_to_buf(denali, id); - } break; case NAND_CMD_RESET: reset_bank(denali); break; case NAND_CMD_READOOB: /* TODO: Read OOB data */ - break; + return; default: pr_err(": unsupported command received 0x%x\n", cmd); - break; + return; } + + denali_reset_irq(denali); + + addr = MODE_11 | BANK(denali->flash_bank); + index_addr(denali, addr | 0, cmd); + if (col != -1) + index_addr(denali, addr | 1, col); + + if (!wait_ready) + return; + + irq_status = denali_wait_for_irq(denali, INTR__INT_ACT); + if (!(irq_status & INTR__INT_ACT)) + dev_err(denali->dev, "failed to issue command 0x%x\n", cmd); } #define DIV_ROUND_DOWN_ULL(ll, d) \ @@ -1234,12 +1207,6 @@ int denali_init(struct denali_nand_info *denali) struct mtd_info *mtd = nand_to_mtd(chip); int ret; - /* allocate a temporary buffer for nand_scan_ident() */ - denali->buf.buf = devm_kzalloc(denali->dev, PAGE_SIZE, - GFP_DMA | GFP_KERNEL); - if (!denali->buf.buf) - return -ENOMEM; - mtd->dev.parent = denali->dev; denali_hw_init(denali); denali_drv_init(denali); @@ -1279,8 +1246,6 @@ int denali_init(struct denali_nand_info *denali) if (ret) goto disable_irq; - /* allocate the right size buffer now */ - devm_kfree(denali->dev, denali->buf.buf); denali->buf.buf = devm_kzalloc(denali->dev, mtd->writesize + mtd->oobsize, GFP_KERNEL); diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 7797340..7d64167 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -307,8 +307,6 @@ #define MODE_11 0x0C000000 struct nand_buf { - int head; - int tail; uint8_t *buf; dma_addr_t dma_buf; }; From patchwork Thu Mar 30 06:46:11 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 96236 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp102422qgd; Wed, 29 Mar 2017 23:49:49 -0700 (PDT) X-Received: by 10.99.136.199 with SMTP id l190mr4428160pgd.92.1490856589013; Wed, 29 Mar 2017 23:49:49 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i64si1228899pfa.421.2017.03.29.23.49.48; Wed, 29 Mar 2017 23:49:49 -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 S933244AbdC3Gtn (ORCPT + 22 others); Thu, 30 Mar 2017 02:49:43 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:41270 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755553AbdC3Gtk (ORCPT ); Thu, 30 Mar 2017 02:49:40 -0400 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2U6kUcn015463; Thu, 30 Mar 2017 15:47:03 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2U6kUcn015463 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490856424; bh=XEQkIiG+YB0fvSZIpGJk5vOZlMs8QLhBeJ2yRzMYbc8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qLaZXCEuPEvVyc2qIGvD3N3PP7atdR7c3HMIMOlYD+S7UGzU32LafMxLE6qkPI0tE 3r67TdGZTV4q72VmUew6WY9IRzhrw35eVBGYQAgptQiRDzKRMU3u48f5CRBegksPOC v6i6UR6IeXFaIRWt/SBgkfObk6xt0SjujtYEwKW2fGivnMpc5cBwgaDVnrno61vQkt bxBsi12TKAClP2vbv0LSCjhdDzCthrt1F3OHtqoCj66uVF1aaL/1MbVPI+W7Q2USWk JMdY51xOzs41oEwWPAQ7M3ssJsPMn6jA9UifUA4mbKrRapWVZ5s5xo0LWzVLJDrCY5 7sLDERNCnfesQ== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: Enrico Jorns , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Brian Norris , Richard Weinberger , Cyrille Pitchen Subject: [PATCH v3 25/37] mtd: nand: denali: switch over to cmd_ctrl instead of cmdfunc Date: Thu, 30 Mar 2017 15:46:11 +0900 Message-Id: <1490856383-31560-26-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490856383-31560-1-git-send-email-yamada.masahiro@socionext.com> References: <1490856383-31560-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 NAND_CMD_SET_FEATURES support is missing from denali_cmdfunc(). This is needed for nand_onfi_set_features(). Besides, we see /* TODO: Read OOB data */ comment line. It would be possible to add more commands along with the current implementation, but having ->cmd_ctrl() seems a better approach from the discussion with Boris [1]. Rely on the default ->cmdfunc() from the framework and implement the driver's own ->cmd_ctrl(). Also add ->write_byte(), which is needed for write direction commands. [1] https://lkml.org/lkml/2017/3/15/97 Signed-off-by: Masahiro Yamada --- Changes in v3: None Changes in v2: - Newly added drivers/mtd/nand/denali.c | 104 +++++++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 52 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 0e5e490..86b7c75 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -230,20 +230,16 @@ static uint32_t denali_wait_for_irq(struct denali_nand_info *denali, return denali->irq_status; } -/* resets a specific device connected to the core */ -static void reset_bank(struct denali_nand_info *denali) +static uint32_t denali_check_irq(struct denali_nand_info *denali) { + unsigned long flags; uint32_t irq_status; - denali_reset_irq(denali); - - iowrite32(1 << denali->flash_bank, denali->flash_reg + DEVICE_RESET); - - irq_status = denali_wait_for_irq(denali, - INTR__RST_COMP | INTR__TIME_OUT); + spin_lock_irqsave(&denali->irq_lock, flags); + irq_status = denali->irq_status; + spin_unlock_irqrestore(&denali->irq_lock, flags); - if (!(irq_status & INTR__RST_COMP)) - dev_err(denali->dev, "reset bank failed.\n"); + return irq_status; } /* @@ -273,6 +269,42 @@ static uint8_t denali_read_byte(struct mtd_info *mtd) return ioread32(denali->flash_mem + 0x10); } +static void denali_write_byte(struct mtd_info *mtd, uint8_t byte) +{ + struct denali_nand_info *denali = mtd_to_denali(mtd); + + index_addr(denali, MODE_11 | BANK(denali->flash_bank) | 2, byte); +} + +static void denali_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) +{ + struct denali_nand_info *denali = mtd_to_denali(mtd); + uint32_t type; + + if (ctrl & NAND_CLE) + type = 0; + else if (ctrl & NAND_ALE) + type = 1; + else + return; + + /* + * Some commands are followed by chip->dev_ready or chip->waitfunc. + * irq_status must be cleared here to catch the R/B# interrupt later. + */ + if (ctrl & NAND_CTRL_CHANGE) + denali_reset_irq(denali); + + index_addr(denali, MODE_11 | BANK(denali->flash_bank) | type, dat); +} + +static int denali_dev_ready(struct mtd_info *mtd) +{ + struct denali_nand_info *denali = mtd_to_denali(mtd); + + return !!(denali_check_irq(denali) & INTR__INT_ACT); +} + /* * sends a pipeline command operation to the controller. See the Denali NAND * controller's user guide for more information (section 4.2.3.6). @@ -824,7 +856,13 @@ static void denali_select_chip(struct mtd_info *mtd, int chip) static int denali_waitfunc(struct mtd_info *mtd, struct nand_chip *chip) { - return 0; + struct denali_nand_info *denali = mtd_to_denali(mtd); + uint32_t irq_status; + + /* R/B# pin transitioned from low to high? */ + irq_status = denali_wait_for_irq(denali, INTR__INT_ACT); + + return irq_status & INTR__INT_ACT ? 0 : NAND_STATUS_FAIL; } static int denali_erase(struct mtd_info *mtd, int page) @@ -845,46 +883,6 @@ static int denali_erase(struct mtd_info *mtd, int page) return irq_status & INTR__ERASE_COMP ? 0 : NAND_STATUS_FAIL; } -static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, - int page) -{ - struct denali_nand_info *denali = mtd_to_denali(mtd); - uint32_t addr, irq_status; - int wait_ready = 0; - - switch (cmd) { - case NAND_CMD_PARAM: - wait_ready = 1; - break; - case NAND_CMD_STATUS: - case NAND_CMD_READID: - break; - case NAND_CMD_RESET: - reset_bank(denali); - break; - case NAND_CMD_READOOB: - /* TODO: Read OOB data */ - return; - default: - pr_err(": unsupported command received 0x%x\n", cmd); - return; - } - - denali_reset_irq(denali); - - addr = MODE_11 | BANK(denali->flash_bank); - index_addr(denali, addr | 0, cmd); - if (col != -1) - index_addr(denali, addr | 1, col); - - if (!wait_ready) - return; - - irq_status = denali_wait_for_irq(denali, INTR__INT_ACT); - if (!(irq_status & INTR__INT_ACT)) - dev_err(denali->dev, "failed to issue command 0x%x\n", cmd); -} - #define DIV_ROUND_DOWN_ULL(ll, d) \ ({ unsigned long long _tmp = (ll); do_div(_tmp, d); _tmp; }) @@ -1230,8 +1228,10 @@ int denali_init(struct denali_nand_info *denali) /* register the driver with the NAND core subsystem */ chip->select_chip = denali_select_chip; - chip->cmdfunc = denali_cmdfunc; chip->read_byte = denali_read_byte; + chip->write_byte = denali_write_byte; + chip->cmd_ctrl = denali_cmd_ctrl; + chip->dev_ready = denali_dev_ready; chip->waitfunc = denali_waitfunc; /* clk rate info is needed for setup_data_interface */ if (denali->clk_x_rate) From patchwork Thu Mar 30 06:46:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 96238 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp102431qgd; Wed, 29 Mar 2017 23:49:49 -0700 (PDT) X-Received: by 10.98.156.23 with SMTP id f23mr4381168pfe.3.1490856589695; Wed, 29 Mar 2017 23:49:49 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i64si1228899pfa.421.2017.03.29.23.49.49; Wed, 29 Mar 2017 23:49:49 -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 S933299AbdC3Gts (ORCPT + 22 others); Thu, 30 Mar 2017 02:49:48 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:41115 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932719AbdC3Gtk (ORCPT ); Thu, 30 Mar 2017 02:49:40 -0400 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2U6kUco015463; Thu, 30 Mar 2017 15:47:05 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2U6kUco015463 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490856426; bh=+MmBerOP8guKRZN1RZaJxxQpPu8T2jj7Icsz0Bq5Yjk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TQgFceuoZFH1gwF76zJKT3YC2UU4YrX1chIzuYffyMHMKJt1q18MeN5tEg3g/eQBv s+ATkHVQBYTLx60lYFcc34ty1Ek91KsZHvdvz9QFfygiW/pH6rdVxa+bQCUuSvyu8M cFBgsO5LuTmWcd7Wf40dszjLRoEMRCYU5adWC4bOjrDbwuAu6IXApovpLsPsroUelA taTY3RymmyxSsfkYgkmS4KO0bpoyYsUB0CMqNdoZpoXuETNDKf0Xe7S1Po8riAzLs7 rtnidXe8qH/NfXWVFpwQaVLux2SZSHg8apSzU3N/AvP+gd3w9rLNKS9rKSVCjVI86+ xtCCZWzUjmfsQ== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: Enrico Jorns , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Brian Norris , Richard Weinberger , Cyrille Pitchen Subject: [PATCH v3 26/37] mtd: nand: denali: fix bank reset function Date: Thu, 30 Mar 2017 15:46:12 +0900 Message-Id: <1490856383-31560-27-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490856383-31560-1-git-send-email-yamada.masahiro@socionext.com> References: <1490856383-31560-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 function denali_nand_reset() is called during the driver probe, and polls the INTR__RST_COMP and INTR__TIME_OUT bits. However, INTR__RST_COMP is set anyway even if no NAND device is connected to that bank. This can be a problem for ONFi devices. The nand_scan_ident() iterates over maxchips, and calls nand_reset() for each chip. Now, this driver implements ->setup_data_interface() method, so nand_setup_data_interface() issues Set Features (0xEF) command to each chip. This can cause time-out error since denali_nand_reset() did not check the chip existence. If no chip there, the controller will wait long for R/B# response, which we know never happens. (The timeout error is correctly handled in this driver, so the driver will be successfully probed anyway, but it will take longer than needed.) The Reset (0xFF) command also toggles the R/B# pin, and it sets INTR__INT_ACT bit. The driver should check this bit to see if the chip has responded, then it can update denali->max_banks. Signed-off-by: Masahiro Yamada --- Changes in v3: None Changes in v2: - Newly added drivers/mtd/nand/denali.c | 52 +++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 29 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 86b7c75..e4f2699 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -85,33 +85,6 @@ static void index_addr(struct denali_nand_info *denali, iowrite32(data, denali->flash_mem + 0x10); } -/* Reset the flash controller */ -static uint16_t denali_nand_reset(struct denali_nand_info *denali) -{ - int i; - - for (i = 0; i < denali->max_banks; i++) - 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__RST_COMP | INTR__TIME_OUT))) - cpu_relax(); - if (ioread32(denali->flash_reg + INTR_STATUS(i)) & - 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__RST_COMP | INTR__TIME_OUT, - denali->flash_reg + INTR_STATUS(i)); - - return PASS; -} - /* * Use the configuration feature register to determine the maximum number of * banks that the hardware supports. @@ -999,7 +972,28 @@ static int denali_setup_data_interface(struct mtd_info *mtd, return 0; } -/* Initialization code to bring the device up to a known good state */ +static void denali_reset_banks(struct denali_nand_info *denali) +{ + int i; + + denali_clear_irq_all(denali); + + 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__RST_COMP | INTR__TIME_OUT))) + cpu_relax(); + if (!(ioread32(denali->flash_reg + INTR_STATUS(i)) & + INTR__INT_ACT)) + break; + } + + dev_dbg(denali->dev, "%d chips connected\n", i); + denali->max_banks = i; + + denali_clear_irq_all(denali); +} + static void denali_hw_init(struct denali_nand_info *denali) { /* @@ -1019,7 +1013,7 @@ static void denali_hw_init(struct denali_nand_info *denali) denali->bbtskipbytes = ioread32(denali->flash_reg + SPARE_AREA_SKIP_BYTES); detect_max_banks(denali); - denali_nand_reset(denali); + denali_reset_banks(denali); iowrite32(0x0F, denali->flash_reg + RB_PIN_ENABLED); iowrite32(CHIP_EN_DONT_CARE__FLAG, denali->flash_reg + CHIP_ENABLE_DONT_CARE); From patchwork Thu Mar 30 06:46: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: 96245 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp102913qgd; Wed, 29 Mar 2017 23:51:37 -0700 (PDT) X-Received: by 10.99.218.69 with SMTP id l5mr4414282pgj.219.1490856697801; Wed, 29 Mar 2017 23:51:37 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e5si1256112pga.100.2017.03.29.23.51.37; Wed, 29 Mar 2017 23:51:37 -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 S933338AbdC3Gvd (ORCPT + 22 others); Thu, 30 Mar 2017 02:51:33 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:41109 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755498AbdC3Gtf (ORCPT ); Thu, 30 Mar 2017 02:49:35 -0400 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2U6kUcp015463; Thu, 30 Mar 2017 15:47:06 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2U6kUcp015463 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490856427; bh=p/YevX4QshDRAsOvoTj2B6AK0KvMKhhE2Q2XAiz2NOc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VDwzzDpNhVQL34Ozgm0PdutEsGyWOfBeT/8IGNGl6lKvcPScv7L7n69O4W9da4aNr qK/3V88+75E08DsKBGUk+pZnBahUBCQchTZek9+YDJuhygckDIEXxmEOPSg7EsfNmC zVojoKBWwoQRVoqOf4vgXw4xnhmWIrsVlpdOwwLtb/0eqSOy65ZH+RJPHgXyMov2m3 XXLZpE05a+JHfGyViNt6ndVhvbch2bMBvzfuC+NimcnI/gHbFYk4adjq9g+Ut7XrEq x5p/U6ZXnmEaMzAWuyc7r5/to/Te0gPe3ZPOeFqcgJ4JV/P53irnq4o8uh415LMbBa fw6LOlQ1dbaGQ== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: Enrico Jorns , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Brian Norris , Richard Weinberger , Cyrille Pitchen Subject: [PATCH v3 27/37] mtd: nand: denali: use interrupt instead of polling for bank reset Date: Thu, 30 Mar 2017 15:46:13 +0900 Message-Id: <1490856383-31560-28-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490856383-31560-1-git-send-email-yamada.masahiro@socionext.com> References: <1490856383-31560-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 current bank reset implementation polls the INTR_STATUS register until interested bits are set. This is not good because: - it simply wastes time-slice of the thread which the driver module is loaded from. - The while() loop may continue eternally if no bit is set, for example, due to the controller problem. The denali_wait_for_irq() uses wait_for_completion_timeout(), which is safer. We can use interrupt by moving the denali_reset_bank() call below the interrupt setup. Signed-off-by: Masahiro Yamada --- Changes in v3: None Changes in v2: - Newly added drivers/mtd/nand/denali.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index e4f2699..9dfed20 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -974,24 +974,25 @@ static int denali_setup_data_interface(struct mtd_info *mtd, static void denali_reset_banks(struct denali_nand_info *denali) { + u32 irq_status; int i; - denali_clear_irq_all(denali); - 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__RST_COMP | INTR__TIME_OUT))) - cpu_relax(); - if (!(ioread32(denali->flash_reg + INTR_STATUS(i)) & - INTR__INT_ACT)) + denali->flash_bank = i; + + denali_reset_irq(denali); + + iowrite32(DEVICE_RESET__BANK(i), + denali->flash_reg + DEVICE_RESET); + + irq_status = denali_wait_for_irq(denali, + INTR__RST_COMP | INTR__INT_ACT | INTR__TIME_OUT); + if (!(irq_status & INTR__INT_ACT)) break; } dev_dbg(denali->dev, "%d chips connected\n", i); denali->max_banks = i; - - denali_clear_irq_all(denali); } static void denali_hw_init(struct denali_nand_info *denali) @@ -1013,7 +1014,6 @@ static void denali_hw_init(struct denali_nand_info *denali) denali->bbtskipbytes = ioread32(denali->flash_reg + SPARE_AREA_SKIP_BYTES); detect_max_banks(denali); - denali_reset_banks(denali); iowrite32(0x0F, denali->flash_reg + RB_PIN_ENABLED); iowrite32(CHIP_EN_DONT_CARE__FLAG, denali->flash_reg + CHIP_ENABLE_DONT_CARE); @@ -1137,9 +1137,6 @@ static void denali_drv_init(struct denali_nand_info *denali) * element that might be access shared data (interrupt status) */ spin_lock_init(&denali->irq_lock); - - /* indicate that MTD has not selected a valid bank yet */ - denali->flash_bank = CHIP_SELECT_INVALID; } static int denali_multidev_fixup(struct denali_nand_info *denali) @@ -1214,6 +1211,9 @@ int denali_init(struct denali_nand_info *denali) } denali_enable_irq(denali); + denali_reset_banks(denali); + + denali->flash_bank = CHIP_SELECT_INVALID; nand_set_flash_node(chip, denali->dev->of_node); /* Fallback to the default name if DT did not give "label" property */ From patchwork Thu Mar 30 06:46: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: 96242 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp102650qgd; Wed, 29 Mar 2017 23:50:40 -0700 (PDT) X-Received: by 10.99.108.199 with SMTP id h190mr4300492pgc.99.1490856640244; Wed, 29 Mar 2017 23:50:40 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t21si1248484pgi.166.2017.03.29.23.50.39; Wed, 29 Mar 2017 23:50:40 -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 S933329AbdC3Guj (ORCPT + 22 others); Thu, 30 Mar 2017 02:50:39 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:41061 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933245AbdC3Gto (ORCPT ); Thu, 30 Mar 2017 02:49:44 -0400 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2U6kUcq015463; Thu, 30 Mar 2017 15:47:07 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2U6kUcq015463 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490856428; bh=quzVOdh05ztrD613z7LYor5zJDLB8dV36vgvH7FSyk0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ve++MYWCbWF9LT325lSYx5ezzM0PLT38jclsuPa/xtJVBkfCAZ8V+F3JOSbbSJR6Y MUQWblnqF2zs7IgueaCn+hwuirkjId1Hb8P29WrIHyVjCsvGXoNMBgIV0/khBAeAYS Vv7EK4SDnKWwVF2FO18pOy9vpHA1wMbe2p8Uf/ntsisuqyLu6Z5qRzj1v35A1vsa+w XV/07cLOku/WZfVjcCc8HOj7iPkevGlJQsmqUayQY0Y19wkfdi3LUgSCwucfDp/CQp nTP5abcarnp+mjkYfp6wMtw12rxPrqy/+Vt1ACEce/0LASsGZH7f3SLODfpqU5Uwg4 J7Kal32bflxug== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: Enrico Jorns , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Brian Norris , Richard Weinberger , Cyrille Pitchen Subject: [PATCH v3 28/37] mtd: nand: denali: propagate page to helpers via function argument Date: Thu, 30 Mar 2017 15:46:14 +0900 Message-Id: <1490856383-31560-29-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490856383-31560-1-git-send-email-yamada.masahiro@socionext.com> References: <1490856383-31560-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 driver stores the currently addressed page into denali->page, which is later read out by helper functions. While I am tackling on this driver, I often missed to insert "denali->page = page;" where necessary. This makes page_read/write callbacks to get access to a wrong page, which is a bug hard to figure out. Instead, I'd rather pass the page via function argument because the compiler's prototype checks will help to detect bugs. For the same reason, propagate dma_addr to the DMA helpers instead of denali->buf.dma_buf . Signed-off-by: Masahiro Yamada --- Changes in v3: None Changes in v2: - Newly added drivers/mtd/nand/denali.c | 58 ++++++++++++++++++++--------------------------- drivers/mtd/nand/denali.h | 1 - 2 files changed, 24 insertions(+), 35 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 9dfed20..00d0e9d 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -282,7 +282,7 @@ static int denali_dev_ready(struct mtd_info *mtd) * sends a pipeline command operation to the controller. See the Denali NAND * controller's user guide for more information (section 4.2.3.6). */ -static int denali_send_pipeline_cmd(struct denali_nand_info *denali, +static int denali_send_pipeline_cmd(struct denali_nand_info *denali, int page, bool ecc_en, bool transfer_spare, int access_type, int op) { @@ -293,7 +293,7 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali, denali_reset_irq(denali); - addr = BANK(denali->flash_bank) | denali->page; + addr = BANK(denali->flash_bank) | page; if (op == DENALI_WRITE && access_type != SPARE_ACCESS) { cmd = MODE_01 | addr; @@ -366,9 +366,7 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) uint32_t irq_mask = INTR__PROGRAM_COMP | INTR__PROGRAM_FAIL; int status = 0; - denali->page = page; - - if (denali_send_pipeline_cmd(denali, false, false, SPARE_ACCESS, + if (denali_send_pipeline_cmd(denali, page, false, false, SPARE_ACCESS, DENALI_WRITE) == PASS) { write_data_to_flash_mem(denali, buf, mtd->oobsize); @@ -393,9 +391,7 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) uint32_t irq_mask = INTR__LOAD_COMP; uint32_t irq_status, addr, cmd; - denali->page = page; - - if (denali_send_pipeline_cmd(denali, false, true, SPARE_ACCESS, + if (denali_send_pipeline_cmd(denali, page, false, true, SPARE_ACCESS, DENALI_READ) == PASS) { read_data_from_flash_mem(denali, buf, mtd->oobsize); @@ -407,8 +403,7 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) irq_status = denali_wait_for_irq(denali, irq_mask); if (!(irq_status & INTR__LOAD_COMP)) - dev_err(denali->dev, "page on OOB timeout %d\n", - denali->page); + dev_err(denali->dev, "page on OOB timeout %d\n", page); /* * We set the device back to MAIN_ACCESS here as I observed @@ -417,7 +412,7 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) * is reliable (according to the MTD test infrastructure) * if you are in MAIN_ACCESS. */ - addr = BANK(denali->flash_bank) | denali->page; + addr = BANK(denali->flash_bank) | page; cmd = MODE_10 | addr; index_addr(denali, cmd, MAIN_ACCESS); } @@ -582,13 +577,13 @@ static void denali_enable_dma(struct denali_nand_info *denali, bool en) ioread32(denali->flash_reg + DMA_ENABLE); } -static void denali_setup_dma64(struct denali_nand_info *denali, int op) +static void denali_setup_dma64(struct denali_nand_info *denali, + dma_addr_t dma_addr, int page, int op) { uint32_t mode; const int page_count = 1; - uint64_t addr = denali->buf.dma_buf; - mode = MODE_10 | BANK(denali->flash_bank) | denali->page; + mode = MODE_10 | BANK(denali->flash_bank) | page; /* DMA is a three step process */ @@ -599,41 +594,42 @@ static void denali_setup_dma64(struct denali_nand_info *denali, int op) index_addr(denali, mode, 0x01002000 | (64 << 16) | op | page_count); /* 2. set memory low address */ - index_addr(denali, mode, addr); + index_addr(denali, mode, dma_addr); /* 3. set memory high address */ - index_addr(denali, mode, addr >> 32); + index_addr(denali, mode, (uint64_t)dma_addr >> 32); } -static void denali_setup_dma32(struct denali_nand_info *denali, int op) +static void denali_setup_dma32(struct denali_nand_info *denali, + dma_addr_t dma_addr, int page, int op) { uint32_t mode; const int page_count = 1; - uint32_t addr = denali->buf.dma_buf; mode = MODE_10 | BANK(denali->flash_bank); /* DMA is a four step process */ /* 1. setup transfer type and # of pages */ - index_addr(denali, mode | denali->page, 0x2000 | op | page_count); + index_addr(denali, mode | page, 0x2000 | op | page_count); /* 2. set memory high address bits 23:8 */ - index_addr(denali, mode | ((addr >> 16) << 8), 0x2200); + index_addr(denali, mode | ((dma_addr >> 16) << 8), 0x2200); /* 3. set memory low address bits 23:8 */ - index_addr(denali, mode | ((addr & 0xffff) << 8), 0x2300); + index_addr(denali, mode | ((dma_addr & 0xffff) << 8), 0x2300); /* 4. interrupt when complete, burst len = 64 bytes */ index_addr(denali, mode | 0x14000, 0x2400); } -static void denali_setup_dma(struct denali_nand_info *denali, int op) +static void denali_setup_dma(struct denali_nand_info *denali, + dma_addr_t dma_addr, int page, int op) { if (denali->caps & DENALI_CAP_DMA_64BIT) - denali_setup_dma64(denali, op); + denali_setup_dma64(denali, dma_addr, page, op); else - denali_setup_dma32(denali, op); + denali_setup_dma32(denali, dma_addr, page, op); } /* @@ -650,8 +646,6 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *chip, uint32_t irq_mask = INTR__DMA_CMD_COMP | INTR__PROGRAM_FAIL; int ret = 0; - denali->page = page; - /* * if it is a raw xfer, we want to disable ecc and send the spare area. * !raw_xfer - enable ecc @@ -674,7 +668,7 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *chip, denali_reset_irq(denali); denali_enable_dma(denali, true); - denali_setup_dma(denali, DENALI_WRITE); + denali_setup_dma(denali, addr, page, DENALI_WRITE); /* wait for operation to complete */ irq_status = denali_wait_for_irq(denali, irq_mask); @@ -750,15 +744,13 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, unsigned long uncor_ecc_flags = 0; int stat = 0; - denali->page = page; - setup_ecc_for_xfer(denali, true, false); denali_enable_dma(denali, true); dma_sync_single_for_device(denali->dev, addr, size, DMA_FROM_DEVICE); denali_reset_irq(denali); - denali_setup_dma(denali, DENALI_READ); + denali_setup_dma(denali, addr, page, DENALI_READ); /* wait for operation to complete */ irq_status = denali_wait_for_irq(denali, irq_mask); @@ -777,7 +769,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, return stat; if (uncor_ecc_flags) { - read_oob_data(mtd, chip->oob_poi, denali->page); + read_oob_data(mtd, chip->oob_poi, page); stat = denali_check_erased_page(mtd, chip, buf, uncor_ecc_flags, stat); @@ -795,15 +787,13 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, uint32_t irq_mask = INTR__DMA_CMD_COMP; uint32_t irq_status; - denali->page = page; - setup_ecc_for_xfer(denali, false, true); denali_enable_dma(denali, true); dma_sync_single_for_device(denali->dev, addr, size, DMA_FROM_DEVICE); denali_reset_irq(denali); - denali_setup_dma(denali, DENALI_READ); + denali_setup_dma(denali, addr, page, DENALI_READ); /* wait for operation to complete */ irq_status = denali_wait_for_irq(denali, irq_mask); diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 7d64167..5f917a0 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -317,7 +317,6 @@ struct denali_nand_info { int flash_bank; /* currently selected chip */ struct nand_buf buf; struct device *dev; - int page; void __iomem *flash_reg; /* Register Interface */ void __iomem *flash_mem; /* Host Data/Command Interface */ From patchwork Thu Mar 30 06:46:16 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 96243 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp102795qgd; Wed, 29 Mar 2017 23:51:10 -0700 (PDT) X-Received: by 10.99.103.5 with SMTP id b5mr1875879pgc.100.1490856670355; Wed, 29 Mar 2017 23:51:10 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d23si1261085pgn.60.2017.03.29.23.51.10; Wed, 29 Mar 2017 23:51:10 -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 S933336AbdC3GvI (ORCPT + 22 others); Thu, 30 Mar 2017 02:51:08 -0400 Received: from conuserg-07.nifty.com ([210.131.2.74]:41028 "EHLO conuserg-07.nifty.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755647AbdC3Gti (ORCPT ); Thu, 30 Mar 2017 02:49:38 -0400 Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-07.nifty.com with ESMTP id v2U6kUcs015463; Thu, 30 Mar 2017 15:47:10 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com v2U6kUcs015463 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1490856431; bh=yR1q1HCbxq+/yaxZ+/k+xTD+pbzxfk5XrjcPKBsGtGo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QE0LJzXNCk2zlSQQp/nStpnz5ETivWR7povjbdIPJWQtV7E1SY+6FdDqAOujhlyds Gb7sB8vO669xZ+SUChK/hmdhpkQTQ2XeYSeHvfDkqSZrAdH2cFQzWEJZCzURykiIWA rNdv47sAcZl9h4zMAJtDR4VKQJ315PpmiWY+qAw01vUcfppu8pEdTRVem0/L2dcTxu QXzA6qZLf1+5DCa35Qbef7ZWbTJ8T6YfT+77BK0HO0/Ihqol5id+wYmhOgoCsSXpsw Gx/J4CdmY233QJxl9oKT96c19up9gWx9lasIGmVHc/uKh80v1ECW7LhWJG641Ip32g Lm+XH+YyPpFew== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: linux-mtd@lists.infradead.org Cc: Enrico Jorns , Artem Bityutskiy , Dinh Nguyen , Boris Brezillon , Marek Vasut , Graham Moore , David Woodhouse , Masami Hiramatsu , Chuanxiao Dong , Jassi Brar , Masahiro Yamada , linux-kernel@vger.kernel.org, Brian Norris , Richard Weinberger , Cyrille Pitchen Subject: [PATCH v3 30/37] mtd: nand: denali: use flag instead of register macro for direction Date: Thu, 30 Mar 2017 15:46:16 +0900 Message-Id: <1490856383-31560-31-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490856383-31560-1-git-send-email-yamada.masahiro@socionext.com> References: <1490856383-31560-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 It is not a good idea to re-use macros that represent a specific register bit field for the transfer direction. It is true that bit 8 indicates the direction for the MAP10 pipeline operation and the data DMA operation, but this is not valid across the IP. Use a simple flag (write: 1, read: 0) for the direction. Signed-off-by: Masahiro Yamada --- Changes in v3: None Changes in v2: - Newly added drivers/mtd/nand/denali.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) -- 2.7.4 diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 5feeaf5..6843cfc 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -53,9 +53,6 @@ static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd) #define MAIN_ACCESS 0x42 #define MAIN_SPARE_ACCESS 0x43 -#define DENALI_READ 0 -#define DENALI_WRITE 0x100 - #define DENALI_NR_BANKS 4 /* @@ -284,7 +281,7 @@ static int denali_dev_ready(struct mtd_info *mtd) */ static int denali_send_pipeline_cmd(struct denali_nand_info *denali, int page, bool ecc_en, bool transfer_spare, - int access_type, int op) + int access_type, int write) { int status = PASS; uint32_t addr, cmd; @@ -295,17 +292,17 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali, int page, addr = BANK(denali->flash_bank) | page; - if (op == DENALI_WRITE && access_type != SPARE_ACCESS) { + if (write && access_type != SPARE_ACCESS) { cmd = MODE_01 | addr; iowrite32(cmd, denali->flash_mem); - } else if (op == DENALI_WRITE && access_type == SPARE_ACCESS) { + } else if (write && access_type == SPARE_ACCESS) { /* read spare area */ cmd = MODE_10 | addr; index_addr(denali, cmd, access_type); cmd = MODE_01 | addr; iowrite32(cmd, denali->flash_mem); - } else if (op == DENALI_READ) { + } else { /* setup page read request for access type */ cmd = MODE_10 | addr; index_addr(denali, cmd, access_type); @@ -367,7 +364,7 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) int status = 0; if (denali_send_pipeline_cmd(denali, page, false, false, SPARE_ACCESS, - DENALI_WRITE) == PASS) { + 1) == PASS) { write_data_to_flash_mem(denali, buf, mtd->oobsize); /* wait for operation to complete */ @@ -392,7 +389,7 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) uint32_t irq_status, addr, cmd; if (denali_send_pipeline_cmd(denali, page, false, true, SPARE_ACCESS, - DENALI_READ) == PASS) { + 0) == PASS) { read_data_from_flash_mem(denali, buf, mtd->oobsize); /* @@ -578,7 +575,7 @@ static void denali_enable_dma(struct denali_nand_info *denali, bool en) } static void denali_setup_dma64(struct denali_nand_info *denali, - dma_addr_t dma_addr, int page, int op) + dma_addr_t dma_addr, int page, int write) { uint32_t mode; const int page_count = 1; @@ -591,7 +588,8 @@ static void denali_setup_dma64(struct denali_nand_info *denali, * 1. setup transfer type, interrupt when complete, * burst len = 64 bytes, the number of pages */ - index_addr(denali, mode, 0x01002000 | (64 << 16) | op | page_count); + index_addr(denali, mode, + 0x01002000 | (64 << 16) | (write << 8) | page_count); /* 2. set memory low address */ index_addr(denali, mode, dma_addr); @@ -601,7 +599,7 @@ static void denali_setup_dma64(struct denali_nand_info *denali, } static void denali_setup_dma32(struct denali_nand_info *denali, - dma_addr_t dma_addr, int page, int op) + dma_addr_t dma_addr, int page, int write) { uint32_t mode; const int page_count = 1; @@ -611,7 +609,7 @@ static void denali_setup_dma32(struct denali_nand_info *denali, /* DMA is a four step process */ /* 1. setup transfer type and # of pages */ - index_addr(denali, mode | page, 0x2000 | op | page_count); + index_addr(denali, mode | page, 0x2000 | (write << 8) | page_count); /* 2. set memory high address bits 23:8 */ index_addr(denali, mode | ((dma_addr >> 16) << 8), 0x2200); @@ -624,12 +622,12 @@ static void denali_setup_dma32(struct denali_nand_info *denali, } static void denali_setup_dma(struct denali_nand_info *denali, - dma_addr_t dma_addr, int page, int op) + dma_addr_t dma_addr, int page, int write) { if (denali->caps & DENALI_CAP_DMA_64BIT) - denali_setup_dma64(denali, dma_addr, page, op); + denali_setup_dma64(denali, dma_addr, page, write); else - denali_setup_dma32(denali, dma_addr, page, op); + denali_setup_dma32(denali, dma_addr, page, write); } /* @@ -668,7 +666,7 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *chip, denali_reset_irq(denali); denali_enable_dma(denali, true); - denali_setup_dma(denali, addr, page, DENALI_WRITE); + denali_setup_dma(denali, addr, page, 1); /* wait for operation to complete */ irq_status = denali_wait_for_irq(denali, irq_mask); @@ -750,7 +748,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, dma_sync_single_for_device(denali->dev, addr, size, DMA_FROM_DEVICE); denali_reset_irq(denali); - denali_setup_dma(denali, addr, page, DENALI_READ); + denali_setup_dma(denali, addr, page, 0); /* wait for operation to complete */ irq_status = denali_wait_for_irq(denali, irq_mask); @@ -793,7 +791,7 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, dma_sync_single_for_device(denali->dev, addr, size, DMA_FROM_DEVICE); denali_reset_irq(denali); - denali_setup_dma(denali, addr, page, DENALI_READ); + denali_setup_dma(denali, addr, page, 0); /* wait for operation to complete */ irq_status = denali_wait_for_irq(denali, irq_mask);