From patchwork Wed May 21 11:20:58 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roger Quadros X-Patchwork-Id: 30541 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ve0-f200.google.com (mail-ve0-f200.google.com [209.85.128.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 10E3420671 for ; Wed, 21 May 2014 11:24:21 +0000 (UTC) Received: by mail-ve0-f200.google.com with SMTP id pa12sf6342168veb.11 for ; Wed, 21 May 2014 04:24:20 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:subject:date:message-id :in-reply-to:references:mime-version:cc:precedence:list-id :list-unsubscribe:list-archive:list-post:list-help:list-subscribe :sender:errors-to:x-original-sender :x-original-authentication-results:mailing-list:content-type :content-transfer-encoding; bh=VyIz/VZKGlHw+5vs8i6KI2UftVEuCLUAfjUFVK+HrLg=; b=eBvPQdrFEhMbB1ZOgLrXsZi5RrD/g6/hZfr8K9rL3ht2H+CZw5hQSPT4sXktkdK8c7 /rVBZb9SdenuJHGjncegjmn08QpcCNr/Ns6IUQ+f6YmDkMbrkyK2ap0jR6pPB6xwJB5b O6Su8fhnJkk7w6pjusXW2H2EyBcZI9jI7by/Nw96F8hay6dazngEJeF/FMIuoXmKJ7F2 uSJRsXpMes0Q8yLiYv472dighPJfcLdc6HUC3cG92YfXiSM9fz2+MJkGMvoLDkwYpNA2 7LVHrhrenfsYVt7sePgN/x619GF7msin0Q1vEryFPaBUjyCgRa/RkYiQA/VUuz3skQbi Ss2g== X-Gm-Message-State: ALoCoQkHHJOv16FaZq4VoKP4iMzBnPejD9hIA8sxUXj0SsS4LzXBZqT3s2DR7O+8pUtTGs2+bVMb X-Received: by 10.58.195.202 with SMTP id ig10mr9184217vec.38.1400671460739; Wed, 21 May 2014 04:24:20 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.101.4 with SMTP id t4ls692109qge.1.gmail; Wed, 21 May 2014 04:24:20 -0700 (PDT) X-Received: by 10.52.166.18 with SMTP id zc18mr57748vdb.65.1400671460584; Wed, 21 May 2014 04:24:20 -0700 (PDT) Received: from mail-vc0-f172.google.com (mail-vc0-f172.google.com [209.85.220.172]) by mx.google.com with ESMTPS id e4si2694934vci.96.2014.05.21.04.24.20 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 21 May 2014 04:24:20 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.172 as permitted sender) client-ip=209.85.220.172; Received: by mail-vc0-f172.google.com with SMTP id hr9so2324471vcb.3 for ; Wed, 21 May 2014 04:24:20 -0700 (PDT) X-Received: by 10.58.29.234 with SMTP id n10mr1251146veh.16.1400671460449; Wed, 21 May 2014 04:24:20 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.221.72 with SMTP id ib8csp104696vcb; Wed, 21 May 2014 04:24:20 -0700 (PDT) X-Received: by 10.224.54.68 with SMTP id p4mr66350233qag.47.1400671459893; Wed, 21 May 2014 04:24:19 -0700 (PDT) Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id f9si988785qaf.27.2014.05.21.04.24.19 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 May 2014 04:24:19 -0700 (PDT) Received-SPF: none (google.com: linux-mtd-bounces+patch=linaro.org@lists.infradead.org does not designate permitted sender hosts) client-ip=2001:1868:205::9; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Wn4bb-0000DS-8r; Wed, 21 May 2014 11:22:43 +0000 Received: from comal.ext.ti.com ([198.47.26.152]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Wn4bG-0008DQ-Uz; Wed, 21 May 2014 11:22:24 +0000 Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by comal.ext.ti.com (8.13.7/8.13.7) with ESMTP id s4LBLrAC024119; Wed, 21 May 2014 06:21:53 -0500 Received: from DLEE70.ent.ti.com (dlemailx.itg.ti.com [157.170.170.113]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id s4LBLqtY021190; Wed, 21 May 2014 06:21:52 -0500 Received: from dflp32.itg.ti.com (10.64.6.15) by DLEE70.ent.ti.com (157.170.170.113) with Microsoft SMTP Server id 14.3.174.1; Wed, 21 May 2014 06:21:52 -0500 Received: from localhost.localdomain (ileax41-snat.itg.ti.com [10.172.224.153]) by dflp32.itg.ti.com (8.14.3/8.13.8) with ESMTP id s4LBLAAf018495; Wed, 21 May 2014 06:21:49 -0500 From: Roger Quadros To: , Subject: [RFC PATCH 10/16] mtd: nand: omap: Move gpmc_update_nand_reg to nand driver Date: Wed, 21 May 2014 14:20:58 +0300 Message-ID: <1400671264-10702-11-git-send-email-rogerq@ti.com> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1400671264-10702-1-git-send-email-rogerq@ti.com> References: <1400671264-10702-1-git-send-email-rogerq@ti.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140521_042223_212842_62C28C57 X-CRM114-Status: GOOD ( 23.68 ) X-Spam-Score: -5.7 (-----) X-Spam-Report: SpamAssassin version 3.3.2 on bombadil.infradead.org summary: Content analysis details: (-5.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [198.47.26.152 listed in list.dnswl.org] -0.7 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -0.0 SPF_PASS SPF: sender matches SPF record Cc: devicetree@vger.kernel.org, robertcnelson@gmail.com, jg1.han@samsung.com, nsekhar@ti.com, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org, pekon@ti.com, ezequiel.garcia@free-electrons.com, javier@dowhile0.org, linux-omap@vger.kernel.org, dwmw2@infradead.org, Roger Quadros X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Sender: "linux-mtd" Errors-To: linux-mtd-bounces+patch=linaro.org@lists.infradead.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: rogerq@ti.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.172 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 GPMC and NAND drivers share the same register space but never use the same registers. As there is no clear address seperation between the registers for GPMC and NAND, we can't easily split it up into 2 regions i.e. one for GPMC and other for NAND. Instead, we simply remap the entire register space in both the drivers. The NAND driver doesn't re-request the region as it is already requested by the GPMC driver (parent). Signed-off-by: Roger Quadros --- arch/arm/mach-omap2/gpmc-nand.c | 7 +- arch/arm/mach-omap2/gpmc.c | 60 +++---------- arch/arm/mach-omap2/gpmc.h | 3 - drivers/mtd/nand/omap2.c | 123 ++++++++++++++++++++++++--- include/linux/platform_data/mtd-nand-omap2.h | 3 +- 5 files changed, 131 insertions(+), 65 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index 775b263..d916ec0 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -27,13 +27,18 @@ static struct resource gpmc_nand_resource[] = { /* GPMC driver will fixup all the resources, see gpmc_probe_legacy () */ { + /* GPMC I/O space */ .flags = IORESOURCE_MEM, .start = 0, .end = NAND_IO_SIZE - 1, }, { - .flags = IORESOURCE_IRQ, + /* GPMC register space */ + .flags = IORESOURCE_MEM, }, + { + .flags = IORESOURCE_IRQ, + } }; static struct platform_device gpmc_nand_device = { diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index e28864d..4207dc9 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -626,40 +626,6 @@ int gpmc_configure(int cmd, int wval) } EXPORT_SYMBOL(gpmc_configure); -void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs) -{ - int i; - - reg->gpmc_status = gpmc_base + GPMC_STATUS; - reg->gpmc_irqstatus = gpmc_base + GPMC_IRQSTATUS; - reg->gpmc_irqenable = gpmc_base + GPMC_IRQENABLE; - reg->gpmc_nand_command = gpmc_base + GPMC_CS0_OFFSET + - GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs; - reg->gpmc_nand_address = gpmc_base + GPMC_CS0_OFFSET + - GPMC_CS_NAND_ADDRESS + GPMC_CS_SIZE * cs; - reg->gpmc_nand_data = gpmc_base + GPMC_CS0_OFFSET + - GPMC_CS_NAND_DATA + GPMC_CS_SIZE * cs; - reg->gpmc_prefetch_config1 = gpmc_base + GPMC_PREFETCH_CONFIG1; - reg->gpmc_prefetch_config2 = gpmc_base + GPMC_PREFETCH_CONFIG2; - reg->gpmc_prefetch_control = gpmc_base + GPMC_PREFETCH_CONTROL; - reg->gpmc_prefetch_status = gpmc_base + GPMC_PREFETCH_STATUS; - reg->gpmc_ecc_config = gpmc_base + GPMC_ECC_CONFIG; - reg->gpmc_ecc_control = gpmc_base + GPMC_ECC_CONTROL; - reg->gpmc_ecc_size_config = gpmc_base + GPMC_ECC_SIZE_CONFIG; - reg->gpmc_ecc1_result = gpmc_base + GPMC_ECC1_RESULT; - - for (i = 0; i < GPMC_BCH_NUM_REMAINDER; i++) { - reg->gpmc_bch_result0[i] = gpmc_base + GPMC_ECC_BCH_RESULT_0 + - GPMC_BCH_SIZE * i; - reg->gpmc_bch_result1[i] = gpmc_base + GPMC_ECC_BCH_RESULT_1 + - GPMC_BCH_SIZE * i; - reg->gpmc_bch_result2[i] = gpmc_base + GPMC_ECC_BCH_RESULT_2 + - GPMC_BCH_SIZE * i; - reg->gpmc_bch_result3[i] = gpmc_base + GPMC_ECC_BCH_RESULT_3 + - GPMC_BCH_SIZE * i; - } -} - static void gpmc_mem_exit(void) { int cs; @@ -1499,21 +1465,25 @@ static int gpmc_probe_dt(struct platform_device *pdev) } #endif -static int gpmc_nand_setup(struct platform_device *pdev, +/* Configure nand device resources */ +static int gpmc_nand_setup(struct platform_device *parent_pdev, + struct platform_device *pdev, struct gpmc_settings *settings) { struct resource *res; int rc; - struct omap_nand_platform_data *gpmc_nand_data; + struct resource *res_mem; - gpmc_nand_data = pdev->dev.platform_data; - if (!gpmc_nand_data) + /* GPMC register space */ + res_mem = platform_get_resource(parent_pdev, IORESOURCE_MEM, 0); + if (!res_mem) return -EINVAL; res = pdev->resource; + res[1] = *res_mem; - /* setup IRQ resources */ - res[1].start = gpmc_irq; + /* IRQ resource */ + res[2].start = gpmc_irq; settings->device_nand = true; /* @@ -1524,9 +1494,6 @@ static int gpmc_nand_setup(struct platform_device *pdev, if (rc < 0) return rc; - /* update register addresses in NAND platform data */ - gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs); - return 0; } @@ -1539,10 +1506,11 @@ static int gpmc_nand_check_csdata(struct gpmc_omap_cs_data *cs) res = cs->pdev->resource; - if (cs->pdev->num_resources < 2) + if (cs->pdev->num_resources < 3) return -EINVAL; - if (resource_type(&res[1]) != IORESOURCE_IRQ) + if (resource_type(&res[1]) != IORESOURCE_MEM || + resource_type(&res[2]) != IORESOURCE_IRQ) return -EINVAL; if (!cs->settings) @@ -1608,7 +1576,7 @@ skip_mem: continue; } - rc = gpmc_nand_setup(cs->pdev, cs->settings); + rc = gpmc_nand_setup(pdev, cs->pdev, cs->settings); if (rc) { dev_err(dev, "Error setting up NAND on CS %d\n", i); diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h index 906eefe..05974f0 100644 --- a/arch/arm/mach-omap2/gpmc.h +++ b/arch/arm/mach-omap2/gpmc.h @@ -21,9 +21,6 @@ #define GPMC_CS_CONFIG5 0x10 #define GPMC_CS_CONFIG6 0x14 #define GPMC_CS_CONFIG7 0x18 -#define GPMC_CS_NAND_COMMAND 0x1c -#define GPMC_CS_NAND_ADDRESS 0x20 -#define GPMC_CS_NAND_DATA 0x24 /* Control Commands */ #define GPMC_CONFIG_WP 0x00000005 diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index ad9d28f..7d12d92 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -140,6 +140,36 @@ #define GPMC_IRQ_FIFOEVENT BIT(0) #define GPMC_IRQ_TERMCOUNT BIT(1) +/* GPMC register offsets */ +#define GPMC_REVISION 0x00 +#define GPMC_SYSCONFIG 0x10 +#define GPMC_SYSSTATUS 0x14 +#define GPMC_IRQSTATUS 0x18 +#define GPMC_IRQENABLE 0x1c +#define GPMC_TIMEOUT_CONTROL 0x40 +#define GPMC_ERR_ADDRESS 0x44 +#define GPMC_ERR_TYPE 0x48 +#define GPMC_CONFIG 0x50 +#define GPMC_STATUS 0x54 +#define GPMC_CS_NAND_COMMAND 0x7c +#define GPMC_CS_NAND_ADDRESS 0x80 +#define GPMC_CS_NAND_DATA 0x84 +#define GPMC_PREFETCH_CONFIG1 0x1e0 +#define GPMC_PREFETCH_CONFIG2 0x1e4 +#define GPMC_PREFETCH_CONTROL 0x1ec +#define GPMC_PREFETCH_STATUS 0x1f0 +#define GPMC_ECC_CONFIG 0x1f4 +#define GPMC_ECC_CONTROL 0x1f8 +#define GPMC_ECC_SIZE_CONFIG 0x1fc +#define GPMC_ECC1_RESULT 0x200 +#define GPMC_ECC_BCH_RESULT_0 0x240 /* not available on OMAP2 */ +#define GPMC_ECC_BCH_RESULT_1 0x244 /* not available on OMAP2 */ +#define GPMC_ECC_BCH_RESULT_2 0x248 /* not available on OMAP2 */ +#define GPMC_ECC_BCH_RESULT_3 0x24c /* not available on OMAP2 */ + +#define GPMC_CS_SIZE 0x30 +#define GPMC_BCH_SIZE 0x10 + #ifdef CONFIG_MTD_NAND_OMAP_BCH static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc, 0xac, 0x6b, 0xff, 0x99, 0x7b}; @@ -158,6 +188,7 @@ struct omap_nand_info { int gpmc_cs; unsigned long phys_base; + void __iomem *gpmc_base; enum omap_ecc ecc_opt; struct completion comp; struct dma_chan *dma; @@ -1584,20 +1615,58 @@ static int is_elm_present(struct omap_nand_info *info, } #endif /* CONFIG_MTD_NAND_ECC_BCH */ +static void gpmc_update_nand_reg(struct omap_nand_info *info) +{ + int i; + struct gpmc_nand_regs *reg = &info->reg; + int cs = info->gpmc_cs; + void __iomem *gpmc_base = info->gpmc_base; + + reg->gpmc_status = gpmc_base + GPMC_STATUS; + reg->gpmc_irqstatus = gpmc_base + GPMC_IRQSTATUS; + reg->gpmc_irqenable = gpmc_base + GPMC_IRQENABLE; + reg->gpmc_nand_command = gpmc_base + GPMC_CS_NAND_COMMAND + + GPMC_CS_SIZE * cs; + reg->gpmc_nand_address = gpmc_base + GPMC_CS_NAND_ADDRESS + + GPMC_CS_SIZE * cs; + reg->gpmc_nand_data = gpmc_base + GPMC_CS_NAND_DATA + + GPMC_CS_SIZE * cs; + reg->gpmc_prefetch_config1 = gpmc_base + GPMC_PREFETCH_CONFIG1; + reg->gpmc_prefetch_config2 = gpmc_base + GPMC_PREFETCH_CONFIG2; + reg->gpmc_prefetch_control = gpmc_base + GPMC_PREFETCH_CONTROL; + reg->gpmc_prefetch_status = gpmc_base + GPMC_PREFETCH_STATUS; + reg->gpmc_ecc_config = gpmc_base + GPMC_ECC_CONFIG; + reg->gpmc_ecc_control = gpmc_base + GPMC_ECC_CONTROL; + reg->gpmc_ecc_size_config = gpmc_base + GPMC_ECC_SIZE_CONFIG; + reg->gpmc_ecc1_result = gpmc_base + GPMC_ECC1_RESULT; + + for (i = 0; i < GPMC_BCH_NUM_REMAINDER; i++) { + reg->gpmc_bch_result0[i] = gpmc_base + GPMC_ECC_BCH_RESULT_0 + + GPMC_BCH_SIZE * i; + reg->gpmc_bch_result1[i] = gpmc_base + GPMC_ECC_BCH_RESULT_1 + + GPMC_BCH_SIZE * i; + reg->gpmc_bch_result2[i] = gpmc_base + GPMC_ECC_BCH_RESULT_2 + + GPMC_BCH_SIZE * i; + reg->gpmc_bch_result3[i] = gpmc_base + GPMC_ECC_BCH_RESULT_3 + + GPMC_BCH_SIZE * i; + } +} + static int omap_nand_probe(struct platform_device *pdev) { - struct omap_nand_info *info; - struct omap_nand_platform_data *pdata; - struct mtd_info *mtd; - struct nand_chip *nand_chip; - struct nand_ecclayout *ecclayout; - int err; - int i; - dma_cap_mask_t mask; - unsigned sig; - unsigned oob_index; - struct resource *res; - struct mtd_part_parser_data ppdata = {}; + struct omap_nand_info *info; + struct omap_nand_platform_data *pdata; + struct mtd_info *mtd; + struct nand_chip *nand_chip; + struct nand_ecclayout *ecclayout; + int err; + int i; + dma_cap_mask_t mask; + unsigned sig; + unsigned oob_index; + struct resource *res; + struct mtd_part_parser_data ppdata = {}; + struct device *dev = &pdev->dev; pdata = dev_get_platdata(&pdev->dev); if (pdata == NULL) { @@ -1617,7 +1686,6 @@ static int omap_nand_probe(struct platform_device *pdev) info->pdev = pdev; info->gpmc_cs = pdata->cs; - info->reg = pdata->reg; info->of_node = pdata->of_node; info->ecc_opt = pdata->ecc_opt; mtd = &info->mtd; @@ -1628,8 +1696,14 @@ static int omap_nand_probe(struct platform_device *pdev) nand_chip->ecc.priv = NULL; nand_chip->options |= NAND_SKIP_BBTSCAN; + /* GPMC external I/O space */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res); + if (!res) { + dev_err(dev, "Can't get memory resource 0\n"); + return -EINVAL; + } + + nand_chip->IO_ADDR_R = devm_ioremap_resource(dev, res); if (IS_ERR(nand_chip->IO_ADDR_R)) return PTR_ERR(nand_chip->IO_ADDR_R); @@ -1640,6 +1714,27 @@ static int omap_nand_probe(struct platform_device *pdev) nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R; nand_chip->cmd_ctrl = omap_hwcontrol; + /* GPMC internal registers */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) { + dev_err(dev, "Can't get memory resource 1\n"); + return -EINVAL; + } + + /* + * This resource is already requested by the GPMC driver + * so we can't request it again. Instead, we just ioremap it. + * This driver doesn't access the same registers as the GPMC + * driver so it is safe. + */ + info->gpmc_base = devm_ioremap(dev, res->start, resource_size(res)); + if (!info->gpmc_base) { + dev_err(dev, "Can't ioremap resource 1\n"); + return -EADDRNOTAVAIL; + } + + gpmc_update_nand_reg(info); + /* * If RDY/BSY line is connected to OMAP then use the omap ready * function and the generic nand_wait function which reads the status diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h index 97c9852..b71cfbd 100644 --- a/include/linux/platform_data/mtd-nand-omap2.h +++ b/include/linux/platform_data/mtd-nand-omap2.h @@ -62,10 +62,11 @@ struct omap_nand_platform_data { enum nand_io xfer_type; int devsize; enum omap_ecc ecc_opt; - struct gpmc_nand_regs reg; /* for passing the partitions */ struct device_node *of_node; struct device_node *elm_of_node; + + struct gpmc_nand_regs reg; /* deprecated */ }; #endif