From patchwork Tue Mar 25 08:19:30 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lee Jones X-Patchwork-Id: 27007 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ob0-f199.google.com (mail-ob0-f199.google.com [209.85.214.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 3690320062 for ; Tue, 25 Mar 2014 08:44:57 +0000 (UTC) Received: by mail-ob0-f199.google.com with SMTP id wo20sf578890obc.6 for ; Tue, 25 Mar 2014 01:44:56 -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:cc:precedence:list-id:list-unsubscribe :list-archive:list-post:list-help:list-subscribe:mime-version:sender :errors-to:x-original-sender:x-original-authentication-results :mailing-list:content-type:content-transfer-encoding; bh=okKPynH/ilrJ/+8qwr0XXjMUSfA6JqGWoqmN8P7TgQQ=; b=Cdh2fNE1A08cnJwddFJ0iZgLOKzNKhqMAOO7ziqnGGWWutXdV208DJOd57SO1g9ZlD poNUDzeavOU+nDXVikRgupR+fAS5s7x9FOney/JpWa07nvBeLbSwUzDnMxa72Fz5chRZ tXhZX33+9fbyQ8tMiCas77ieN0X0RBxuRmGGy7/nCTqMBNOmHmwzMYA+gDJa+q9I+nRA vId4lJtFhxl0sEshvTbmOk7b8EXKjyEVPAhS5c0Damxf3kvKpwIBIIlk/4MYT36osZKe HTo1/jTesgm3Z9KFOLb3iV2SzJ7SagVfpVoPgEbUDcQDpNSo6iyQJYXo2T7/J+EiL1Ss g3Lw== X-Gm-Message-State: ALoCoQmVkM1+Bry5OZuDduFr1W/3kzF97IYMMxazlcnJqJ9aiflupoYgkNuzMIrPmgxNbpuDzLAZ X-Received: by 10.43.135.4 with SMTP id ie4mr24756928icc.1.1395737096743; Tue, 25 Mar 2014 01:44:56 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.102.1 with SMTP id v1ls139115qge.50.gmail; Tue, 25 Mar 2014 01:44:56 -0700 (PDT) X-Received: by 10.221.39.138 with SMTP id tm10mr54740960vcb.7.1395737096597; Tue, 25 Mar 2014 01:44:56 -0700 (PDT) Received: from mail-ve0-f174.google.com (mail-ve0-f174.google.com [209.85.128.174]) by mx.google.com with ESMTPS id a15si3592728vew.115.2014.03.25.01.44.56 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 25 Mar 2014 01:44:56 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.128.174 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.174; Received: by mail-ve0-f174.google.com with SMTP id oz11so146306veb.19 for ; Tue, 25 Mar 2014 01:44:56 -0700 (PDT) X-Received: by 10.221.26.10 with SMTP id rk10mr54895967vcb.0.1395737096521; Tue, 25 Mar 2014 01:44:56 -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.78.9 with SMTP id i9csp286600vck; Tue, 25 Mar 2014 01:44:55 -0700 (PDT) X-Received: by 10.180.189.139 with SMTP id gi11mr21358883wic.53.1395737095364; Tue, 25 Mar 2014 01:44:55 -0700 (PDT) Received: from casper.infradead.org (casper.infradead.org. [2001:770:15f::2]) by mx.google.com with ESMTPS id ne11si2846267wic.77.2014.03.25.01.44.54 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 25 Mar 2014 01:44:55 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-mtd-bounces+patch=linaro.org@lists.infradead.org designates 2001:770:15f::2 as permitted sender) client-ip=2001:770:15f::2; Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WSMxR-0002h5-4y; Tue, 25 Mar 2014 08:43:42 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WSMww-0003m9-0d; Tue, 25 Mar 2014 08:43:10 +0000 Received: from bombadil.infradead.org ([2001:1868:205::9]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WSMsO-0003B8-Ac for linux-mtd@merlin.infradead.org; Tue, 25 Mar 2014 08:38:28 +0000 Received: from mail-we0-f174.google.com ([74.125.82.174]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WSMba-00025F-Ak for linux-mtd@lists.infradead.org; Tue, 25 Mar 2014 08:21:07 +0000 Received: by mail-we0-f174.google.com with SMTP id t60so79221wes.33 for ; Tue, 25 Mar 2014 01:20:42 -0700 (PDT) X-Received: by 10.180.94.196 with SMTP id de4mr20256263wib.16.1395735642416; Tue, 25 Mar 2014 01:20:42 -0700 (PDT) Received: from lee--X1.home (host109-148-113-193.range109-148.btcentralplus.com. [109.148.113.193]) by mx.google.com with ESMTPSA id k4sm5567676wib.19.2014.03.25.01.20.40 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 25 Mar 2014 01:20:41 -0700 (PDT) From: Lee Jones To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [RFC 13/47] mtd: nand: stm_nand_bch: provide Device Tree support Date: Tue, 25 Mar 2014 08:19:30 +0000 Message-Id: <1395735604-26706-14-git-send-email-lee.jones@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1395735604-26706-1-git-send-email-lee.jones@linaro.org> References: <1395735604-26706-1-git-send-email-lee.jones@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140325_012106_674647_E3E006D3 X-CRM114-Status: GOOD ( 20.39 ) X-Spam-Score: -0.7 (/) X-Spam-Report: SpamAssassin version 3.3.2 on bombadil.infradead.org summary: Content analysis details: (-0.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [74.125.82.174 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record Cc: angus.clark@st.com, kernel@stlinux.com, lee.jones@linaro.org, linux-mtd@lists.infradead.org, pekon@ti.com, computersforpeace@gmail.com, dwmw2@infradead.org 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: , MIME-Version: 1.0 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: lee.jones@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.174 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) 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 Fetch platform specific data from Device Tree. Any functions which are useful to other STM NAND Controllers have been separated into a separate file so they can be easily referenced by them as they appear. Signed-off-by: Lee Jones --- drivers/mtd/nand/Kconfig | 7 ++ drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/stm_nand_bch.c | 68 ++++++++++++++++++- drivers/mtd/nand/stm_nand_dt.c | 146 ++++++++++++++++++++++++++++++++++++++++ drivers/mtd/nand/stm_nand_dt.h | 39 +++++++++++ include/linux/mtd/stm_nand.h | 9 +++ 6 files changed, 268 insertions(+), 2 deletions(-) create mode 100644 drivers/mtd/nand/stm_nand_dt.c create mode 100644 drivers/mtd/nand/stm_nand_dt.h diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 2bf972c..28155c0 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -516,4 +516,11 @@ config MTD_NAND_STM_BCH help Adds support for the STMicroelectronics NANDi BCH Controller. +config MTD_NAND_STM_BCH_DT + tristate "STMicroelectronics: NANDi BCH Controller Device Tree support" + default MTD_NAND_STM_BCH if OF + help + Adds support for the STMicroelectronics NANDi BCH Controller's + Device Tree component. + endif # MTD_NAND diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 94e7737..890f47f 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o obj-$(CONFIG_MTD_NAND_RICOH) += r852.o obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o obj-$(CONFIG_MTD_NAND_STM_BCH) += stm_nand_bch.o +obj-$(CONFIG_MTD_NAND_STM_BCH_DT) += stm_nand_dt.o obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ diff --git a/drivers/mtd/nand/stm_nand_bch.c b/drivers/mtd/nand/stm_nand_bch.c index 1de13bd..3115fb4 100644 --- a/drivers/mtd/nand/stm_nand_bch.c +++ b/drivers/mtd/nand/stm_nand_bch.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -23,8 +24,10 @@ #include #include #include +#include #include "stm_nand_regs.h" +#include "stm_nand_dt.h" /* Bad Block Table (BBT) */ struct nandi_bbt_info { @@ -365,9 +368,51 @@ nandi_init_resources(struct platform_device *pdev) return nandi; } +#ifdef CONFIG_OF +static void *stm_bch_dt_get_pdata(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct stm_plat_nand_bch_data *pdata; + const char *ecc_config; + int ret; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + of_property_read_string(np, "st,bch-ecc-mode", &ecc_config); + if (!strcmp("noecc", ecc_config)) + pdata->bch_ecc_cfg = BCH_NO_ECC; + else if (!strcmp("18bit", ecc_config)) + pdata->bch_ecc_cfg = BCH_18BIT_ECC; + else if (!strcmp("30bit", ecc_config)) + pdata->bch_ecc_cfg = BCH_30BIT_ECC; + else + pdata->bch_ecc_cfg = BCH_ECC_AUTO; + + ret = stm_of_get_nand_banks(&pdev->dev, np, &pdata->bank); + if (ret < 0) + return ERR_PTR(ret); + + pdata->flashss = of_property_read_bool(np, "st,nand-flashss"); + + of_property_read_u32(np, "st,bch-bitflip-threshold", + &pdata->bch_bitflip_threshold); + + return pdata; +} +#else +static void *stm_bch_dt_get_pdata(struct platform_device *pdev) +{ + return NULL; +} +#endif + static int stm_nand_bch_probe(struct platform_device *pdev) { struct stm_plat_nand_bch_data *pdata = pdev->dev.platform_data; + struct device_node *np = pdev->dev.of_node; + struct mtd_part_parser_data ppdata; struct stm_nand_bank_data *bank; struct nandi_bbt_info *bbt_info; struct nandi_controller *nandi; @@ -377,8 +422,18 @@ static int stm_nand_bch_probe(struct platform_device *pdev) int err; if (!pdata) { - dev_err(&pdev->dev, "no platform data found\n"); - return -EINVAL; + if (!np) { + dev_err(&pdev->dev, "no pdata or DT found\n"); + return -EINVAL; + } + + pdata = stm_bch_dt_get_pdata(pdev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + + ppdata.of_node = stm_of_get_partitions_node(np, 0); + + pdev->dev.platform_data = pdata; } nandi = nandi_init_resources(pdev); @@ -460,12 +515,21 @@ static const struct dev_pm_ops stm_nand_bch_pm_ops = { static const struct dev_pm_ops stm_nand_bch_pm_ops; #endif +#ifdef CONFIG_OF +static struct of_device_id nand_bch_match[] = { + { .compatible = "st,nand-bch", }, + {}, +}; +MODULE_DEVICE_TABLE(of, nand_bch_match); +#endif + static struct platform_driver stm_nand_bch_driver = { .probe = stm_nand_bch_probe , .remove = stm_nand_bch_remove, .driver = { .name = "stm-nand-bch", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(nand_bch_match), .pm = &stm_nand_bch_pm_ops, }, }; diff --git a/drivers/mtd/nand/stm_nand_dt.c b/drivers/mtd/nand/stm_nand_dt.c new file mode 100644 index 0000000..0e91bba --- /dev/null +++ b/drivers/mtd/nand/stm_nand_dt.c @@ -0,0 +1,146 @@ +/* + * drivers/mtd/nand/stm_nand_dt.c + * + * Support for NANDi BCH Controller Device Tree component + * + * Copyright (c) 2014 STMicroelectronics Limited + * Author: Author: Srinivas Kandagatla + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** +* stm_of_get_partitions_node - get partitions node from stm-nand type devices. +* +* @dev device pointer to use for devm allocations. +* @np device node of the driver. +* @bank_nr which bank number to use to get partitions. +* +* Returns a node pointer if found, with refcount incremented, use +* of_node_put() on it when done. +* +*/ +struct device_node *stm_of_get_partitions_node(struct device_node *np, + int bank_nr) +{ + struct device_node *banksnp, *banknp, *partsnp = NULL; + char name[10]; + + banksnp = of_parse_phandle(np, "st,nand-banks", 0); + if (!banksnp) + return NULL; + + sprintf(name, "bank%d", bank_nr); + banknp = of_get_child_by_name(banksnp, name); + if (banknp) + return NULL; + + partsnp = of_get_child_by_name(banknp, "partitions"); + of_node_put(banknp); + + return partsnp; +} +EXPORT_SYMBOL(stm_of_get_partitions_node); + +/** + * stm_of_get_nand_banks - Get nand banks info from a given device node. + * + * @dev device pointer to use for devm allocations. + * @np device node of the driver. + * @banksptr double pointer to banks which is allocated + * and filled with bank data. + * + * Returns a count of banks found in the given device node. + * + */ +int stm_of_get_nand_banks(struct device *dev, struct device_node *np, + struct stm_nand_bank_data **banksptr) +{ + struct stm_nand_bank_data *banks; + struct device_node *banknp, *banksnp; + int nr_banks = 0; + + if (!np) + return -ENODEV; + + banksnp = of_parse_phandle(np, "st,nand-banks", 0); + if (!banksnp) { + dev_warn(dev, "No NAND banks specified in DT: %s\n", + np->full_name); + return -ENODEV; + } + + for_each_child_of_node(banksnp, banknp) + nr_banks++; + + *banksptr = devm_kzalloc(dev, sizeof(*banks) * nr_banks, GFP_KERNEL); + banks = *banksptr; + banknp = NULL; + + for_each_child_of_node(banksnp, banknp) { + struct device_node *timingnp; + int bank = 0; + + of_property_read_u32(banknp, "st,nand-csn", &banks[bank].csn); + + if (of_get_nand_bus_width(banknp) == 16) + banks[bank].options |= NAND_BUSWIDTH_16; + if (of_get_nand_on_flash_bbt(banknp)) + banks[bank].bbt_options |= NAND_BBT_USE_FLASH; + + banks[bank].nr_partitions = 0; + banks[bank].partitions = NULL; + + timingnp = of_parse_phandle(banknp, "st,nand-timing-spec", 0); + if (timingnp) { + struct nand_timing_spec *ts; + + ts = devm_kzalloc(dev, sizeof(struct nand_timing_spec), + GFP_KERNEL); + + of_property_read_u32(timingnp, "tR", &ts->tR); + of_property_read_u32(timingnp, "tCLS", &ts->tCLS); + of_property_read_u32(timingnp, "tCS", &ts->tCS); + of_property_read_u32(timingnp, "tALS", &ts->tALS); + of_property_read_u32(timingnp, "tDS", &ts->tDS); + of_property_read_u32(timingnp, "tWP", &ts->tWP); + of_property_read_u32(timingnp, "tCLH", &ts->tCLH); + of_property_read_u32(timingnp, "tCH", &ts->tCH); + of_property_read_u32(timingnp, "tALH", &ts->tALH); + of_property_read_u32(timingnp, "tDH", &ts->tDH); + of_property_read_u32(timingnp, "tWB", &ts->tWB); + of_property_read_u32(timingnp, "tWH", &ts->tWH); + of_property_read_u32(timingnp, "tWC", &ts->tWC); + of_property_read_u32(timingnp, "tRP", &ts->tRP); + of_property_read_u32(timingnp, "tREH", &ts->tREH); + of_property_read_u32(timingnp, "tRC", &ts->tRC); + of_property_read_u32(timingnp, "tREA", &ts->tREA); + of_property_read_u32(timingnp, "tRHOH", &ts->tRHOH); + of_property_read_u32(timingnp, "tCEA", &ts->tCEA); + of_property_read_u32(timingnp, "tCOH", &ts->tCOH); + of_property_read_u32(timingnp, "tCHZ", &ts->tCHZ); + of_property_read_u32(timingnp, "tCSD", &ts->tCSD); + banks[bank].timing_spec = ts; + } + of_property_read_u32(banknp, "st,nand-timing-relax", + &banks[bank].timing_relax); + bank++; + } + + return nr_banks; +} +EXPORT_SYMBOL(stm_of_get_nand_banks); diff --git a/drivers/mtd/nand/stm_nand_dt.h b/drivers/mtd/nand/stm_nand_dt.h new file mode 100644 index 0000000..de4507c --- /dev/null +++ b/drivers/mtd/nand/stm_nand_dt.h @@ -0,0 +1,39 @@ +/* + * drivers/mtd/nand/stm_nand_dt.h + * + * Support for NANDi BCH Controller Device Tree component + * + * Copyright (c) 2014 STMicroelectronics Limited + * Author: Author: Srinivas Kandagatla + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef STM_NAND_DT_H +#define STM_NAND_DT_H + +#if defined(CONFIG_MTD_NAND_STM_BCH_DT) +struct device_node *stm_of_get_partitions_node(struct device_node *np, + int bank_nr); + +int stm_of_get_nand_banks(struct device *dev, struct device_node *np, + struct stm_nand_bank_data **banksp); +#else +static inline +struct device_node *stm_of_get_partitions_node(struct device_node *np, + int bank_nr) +{ + return NULL; +} + +static inline int stm_of_get_nand_banks(struct device *dev, + struct device_node *np, + struct stm_nand_bank_data **banksp) +{ + return 0; +} +#endif /* CONFIG_MTD_NAND_STM_BCH_DT */ +#endif /* STM_NAND_DT_H */ diff --git a/include/linux/mtd/stm_nand.h b/include/linux/mtd/stm_nand.h index 99a69ca..f82f9f7 100644 --- a/include/linux/mtd/stm_nand.h +++ b/include/linux/mtd/stm_nand.h @@ -37,6 +37,15 @@ struct stm_nand_bank_data { int timing_relax; }; +/* ECC Modes */ +enum stm_nand_bch_ecc_config { + BCH_18BIT_ECC = 0, + BCH_30BIT_ECC, + BCH_NO_ECC, + BCH_ECC_RSRV, + BCH_ECC_AUTO, +}; + struct stm_plat_nand_bch_data { struct stm_nand_bank_data *bank; enum stm_nand_bch_ecc_config bch_ecc_cfg;