aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorStefan Roese <sr@denx.de>2012-03-16 05:19:31 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-03-26 20:01:07 -0400
commiteea628199d5b12429c47db17035a954b0062e554 (patch)
treeea2ddcd6df17d3c459f7d40477d06ddbc96abc7d /drivers/mtd
parent30053b87d5b97aca28dd7a59982cbb161eaf01c6 (diff)
mtd: Add device-tree support to fsmc_nand
This patch adds support to configure the FSMC NAND driver (used amongst others on SPEAr platforms) via device-tree instead of platform_data. Signed-off-by: Stefan Roese <sr@denx.de> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/fsmc_nand.c57
1 files changed, 56 insertions, 1 deletions
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 04901821309..1b8330e1155 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -31,6 +31,7 @@
31#include <linux/mtd/nand.h> 31#include <linux/mtd/nand.h>
32#include <linux/mtd/nand_ecc.h> 32#include <linux/mtd/nand_ecc.h>
33#include <linux/platform_device.h> 33#include <linux/platform_device.h>
34#include <linux/of.h>
34#include <linux/mtd/partitions.h> 35#include <linux/mtd/partitions.h>
35#include <linux/io.h> 36#include <linux/io.h>
36#include <linux/slab.h> 37#include <linux/slab.h>
@@ -854,6 +855,38 @@ static bool filter(struct dma_chan *chan, void *slave)
854 return true; 855 return true;
855} 856}
856 857
858#ifdef CONFIG_OF
859static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev,
860 struct device_node *np)
861{
862 struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
863 u32 val;
864
865 /* Set default NAND width to 8 bits */
866 pdata->width = 8;
867 if (!of_property_read_u32(np, "bank-width", &val)) {
868 if (val == 2) {
869 pdata->width = 16;
870 } else if (val != 1) {
871 dev_err(&pdev->dev, "invalid bank-width %u\n", val);
872 return -EINVAL;
873 }
874 }
875 of_property_read_u32(np, "st,ale-off", &pdata->ale_off);
876 of_property_read_u32(np, "st,cle-off", &pdata->cle_off);
877 if (of_get_property(np, "nand-skip-bbtscan", NULL))
878 pdata->options = NAND_SKIP_BBTSCAN;
879
880 return 0;
881}
882#else
883static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev,
884 struct device_node *np)
885{
886 return -ENOSYS;
887}
888#endif
889
857/* 890/*
858 * fsmc_nand_probe - Probe function 891 * fsmc_nand_probe - Probe function
859 * @pdev: platform device structure 892 * @pdev: platform device structure
@@ -861,6 +894,8 @@ static bool filter(struct dma_chan *chan, void *slave)
861static int __init fsmc_nand_probe(struct platform_device *pdev) 894static int __init fsmc_nand_probe(struct platform_device *pdev)
862{ 895{
863 struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); 896 struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
897 struct device_node __maybe_unused *np = pdev->dev.of_node;
898 struct mtd_part_parser_data ppdata = {};
864 struct fsmc_nand_data *host; 899 struct fsmc_nand_data *host;
865 struct mtd_info *mtd; 900 struct mtd_info *mtd;
866 struct nand_chip *nand; 901 struct nand_chip *nand;
@@ -870,6 +905,16 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
870 u32 pid; 905 u32 pid;
871 int i; 906 int i;
872 907
908 if (np) {
909 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
910 pdev->dev.platform_data = pdata;
911 ret = fsmc_nand_probe_config_dt(pdev, np);
912 if (ret) {
913 dev_err(&pdev->dev, "no platform data\n");
914 return -ENODEV;
915 }
916 }
917
873 if (!pdata) { 918 if (!pdata) {
874 dev_err(&pdev->dev, "platform data is NULL\n"); 919 dev_err(&pdev->dev, "platform data is NULL\n");
875 return -EINVAL; 920 return -EINVAL;
@@ -1113,7 +1158,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
1113 * Check for partition info passed 1158 * Check for partition info passed
1114 */ 1159 */
1115 host->mtd.name = "nand"; 1160 host->mtd.name = "nand";
1116 ret = mtd_device_parse_register(&host->mtd, NULL, NULL, 1161 ppdata.of_node = np;
1162 ret = mtd_device_parse_register(&host->mtd, NULL, &ppdata,
1117 host->partitions, host->nr_partitions); 1163 host->partitions, host->nr_partitions);
1118 if (ret) 1164 if (ret)
1119 goto err_probe; 1165 goto err_probe;
@@ -1183,11 +1229,20 @@ static int fsmc_nand_resume(struct device *dev)
1183static SIMPLE_DEV_PM_OPS(fsmc_nand_pm_ops, fsmc_nand_suspend, fsmc_nand_resume); 1229static SIMPLE_DEV_PM_OPS(fsmc_nand_pm_ops, fsmc_nand_suspend, fsmc_nand_resume);
1184#endif 1230#endif
1185 1231
1232#ifdef CONFIG_OF
1233static const struct of_device_id fsmc_nand_id_table[] = {
1234 { .compatible = "st,spear600-fsmc-nand" },
1235 {}
1236};
1237MODULE_DEVICE_TABLE(of, fsmc_nand_id_table);
1238#endif
1239
1186static struct platform_driver fsmc_nand_driver = { 1240static struct platform_driver fsmc_nand_driver = {
1187 .remove = fsmc_nand_remove, 1241 .remove = fsmc_nand_remove,
1188 .driver = { 1242 .driver = {
1189 .owner = THIS_MODULE, 1243 .owner = THIS_MODULE,
1190 .name = "fsmc-nand", 1244 .name = "fsmc-nand",
1245 .of_match_table = of_match_ptr(fsmc_nand_id_table),
1191#ifdef CONFIG_PM 1246#ifdef CONFIG_PM
1192 .pm = &fsmc_nand_pm_ops, 1247 .pm = &fsmc_nand_pm_ops,
1193#endif 1248#endif