From patchwork Thu May 1 09:56:21 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lee Jones X-Patchwork-Id: 29457 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-yk0-f200.google.com (mail-yk0-f200.google.com [209.85.160.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id C0301203F3 for ; Thu, 1 May 2014 09:57:37 +0000 (UTC) Received: by mail-yk0-f200.google.com with SMTP id q200sf6259272ykb.11 for ; Thu, 01 May 2014 02:57:37 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=piplp+lM8babSjq3waHYzreLYogE8x285hlYeG0c7Uk=; b=Oksx8s/u/9iR69Pf5VvE9oAHfqMJ8MQ4F7ipaJGFwsWeWDfNGsJT9muOoa6ffTt1QV z/YeeerK1Ijwal0K84RP57thAZcb+OFDxgmjDnI866zD/P0Lr+XuRIJY3e+GSwqtl5o+ SWN4Yl5ecR6UdLCyR2kzAvTg7QG1Dthxo+87BiVeg5HrtkHOrKvYEGZv9XnfWcAJGyDe tGE4qLk8clQ4ydey16rgKWH13kBcD8+u0YKi/5vzgEiCh0rlexwY55ZGo2GjD2tGDGdf 0NEcaxgyEfNnOuSXaZNeluKZoETmORGoPdMG8VIID9FmKcf2ezIb1T/TjTIx5OWDAA8I tMUw== X-Gm-Message-State: ALoCoQmuGexzoBVMfEUsgz5tNYBnANKDowlgrDYiev3aXzqnS2UP6YacnMjJ/ObbePnYI/VH17ll X-Received: by 10.58.95.98 with SMTP id dj2mr4908032veb.30.1398938257526; Thu, 01 May 2014 02:57:37 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.88.134 with SMTP id t6ls969688qgd.20.gmail; Thu, 01 May 2014 02:57:37 -0700 (PDT) X-Received: by 10.52.99.168 with SMTP id er8mr6938065vdb.26.1398938257441; Thu, 01 May 2014 02:57:37 -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 sw4si5952272vdc.102.2014.05.01.02.57.37 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 01 May 2014 02:57:37 -0700 (PDT) Received-SPF: none (google.com: patch+caf_=patchwork-forward=linaro.org@linaro.org does not designate permitted sender hosts) client-ip=209.85.220.172; Received: by mail-vc0-f172.google.com with SMTP id id10so3703279vcb.31 for ; Thu, 01 May 2014 02:57:37 -0700 (PDT) X-Received: by 10.220.59.65 with SMTP id k1mr8107868vch.22.1398938257345; Thu, 01 May 2014 02:57:37 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.221.72 with SMTP id ib8csp12913vcb; Thu, 1 May 2014 02:57:36 -0700 (PDT) X-Received: by 10.194.175.70 with SMTP id by6mr8175685wjc.3.1398938256165; Thu, 01 May 2014 02:57:36 -0700 (PDT) Received: from mail-wi0-f170.google.com (mail-wi0-f170.google.com [209.85.212.170]) by mx.google.com with ESMTPS id r9si566957wia.103.2014.05.01.02.57.35 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 01 May 2014 02:57:36 -0700 (PDT) Received-SPF: none (google.com: lee.jones@linaro.org does not designate permitted sender hosts) client-ip=209.85.212.170; Received: by mail-wi0-f170.google.com with SMTP id f8so450296wiw.1 for ; Thu, 01 May 2014 02:57:35 -0700 (PDT) X-Received: by 10.180.77.165 with SMTP id t5mr1557291wiw.38.1398938255599; Thu, 01 May 2014 02:57:35 -0700 (PDT) Received: from lee--X1.home (host109-148-238-223.range109-148.btcentralplus.com. [109.148.238.223]) by mx.google.com with ESMTPSA id bj5sm2696494wib.3.2014.05.01.02.57.33 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 01 May 2014 02:57:34 -0700 (PDT) From: Lee Jones To: linux-kernel@vger.kernel.org Cc: computersforpeace@gmail.com, linux-mtd@lists.infradead.org, kernel@stlinux.com, Lee Jones Subject: [PATCH 14/47] mtd: nand: stm_nand_bch: provide Device Tree support Date: Thu, 1 May 2014 10:56:21 +0100 Message-Id: <1398938214-17847-15-git-send-email-lee.jones@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1398938214-17847-1-git-send-email-lee.jones@linaro.org> References: <1398938214-17847-1-git-send-email-lee.jones@linaro.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: patch+caf_=patchwork-forward=linaro.org@linaro.org does not designate permitted sender hosts) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , 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 | 56 +++++++++++++++ drivers/mtd/nand/stm_nand_dt.c | 149 ++++++++++++++++++++++++++++++++++++++++ drivers/mtd/nand/stm_nand_dt.h | 39 +++++++++++ include/linux/mtd/stm_nand.h | 9 +++ 6 files changed, 261 insertions(+) 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 7b1352a..119aed5 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -517,4 +517,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 2670cec..b1de66e 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 { @@ -523,9 +526,42 @@ nandi_init_resources(struct platform_device *pdev) return nandi; } +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; + int ecc_strength; + int ret; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + of_property_read_u32(np, "nand-ecc-strength", &ecc_strength); + if (ecc_strength == 0) + pdata->bch_ecc_cfg = BCH_NO_ECC; + else if (ecc_strength == 18) + pdata->bch_ecc_cfg = BCH_18BIT_ECC; + else if (ecc_strength == 30) + 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); + + of_property_read_u32(np, "st,bch-bitflip-threshold", + &pdata->bch_bitflip_threshold); + + return pdata; +} + 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; @@ -534,6 +570,19 @@ static int stm_nand_bch_probe(struct platform_device *pdev) struct mtd_info *mtd; int err; + if (!np) { + dev_err(&pdev->dev, "DT node 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); if (IS_ERR(nandi)) { dev_err(&pdev->dev, "failed to initialise NANDi resources\n"); @@ -613,12 +662,19 @@ static const struct dev_pm_ops stm_nand_bch_pm_ops = { static const struct dev_pm_ops stm_nand_bch_pm_ops; #endif +static struct of_device_id nand_bch_match[] = { + { .compatible = "st,nand-bch", }, + {}, +}; +MODULE_DEVICE_TABLE(of, nand_bch_match); + 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..75ff131 --- /dev/null +++ b/drivers/mtd/nand/stm_nand_dt.c @@ -0,0 +1,149 @@ +/* + * 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 + +#include "stm_nand_regs.h" + +/** +* 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;