aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2012-07-22 13:51:02 -0400
committerHaojian Zhuang <haojian.zhuang@gmail.com>2012-08-16 04:14:24 -0400
commit1e7ba630d4aeabef8e022a4099b20ab9f660d37d (patch)
treeaaafa789d13ab154e42367cfc3f599d0b09610aa
parent9020b7cc27439e23a0e993f79ef8632fea5e88d5 (diff)
MTD: pxa3xx-nand: add devicetree bindings
This patch contains a hack to get the DMA resources of the device when probed from a devicetree node. This can be removed once a generic DMA controller framework lands. A mtd_part_parser_data is passed mtd_device_parse_register which contains a reference to the device node, so MTD partitions can be added as children. Signed-off-by: Daniel Mack <zonque@gmail.com> Cc: David Woodhouse <dwmw2@infradead.org> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Haojian Zhuang <haojian.zhuang@gmail.com>
-rw-r--r--Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt31
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c85
2 files changed, 102 insertions, 14 deletions
diff --git a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
new file mode 100644
index 000000000000..f1421e2bbab7
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
@@ -0,0 +1,31 @@
1PXA3xx NAND DT bindings
2
3Required properties:
4
5 - compatible: Should be "marvell,pxa3xx-nand"
6 - reg: The register base for the controller
7 - interrupts: The interrupt to map
8 - #address-cells: Set to <1> if the node includes partitions
9
10Optional properties:
11
12 - marvell,nand-enable-arbiter: Set to enable the bus arbiter
13 - marvell,nand-keep-config: Set to keep the NAND controller config as set
14 by the bootloader
15 - num-cs: Number of chipselect lines to usw
16
17Example:
18
19 nand0: nand@43100000 {
20 compatible = "marvell,pxa3xx-nand";
21 reg = <0x43100000 90>;
22 interrupts = <45>;
23 #address-cells = <1>;
24
25 marvell,nand-enable-arbiter;
26 marvell,nand-keep-config;
27 num-cs = <1>;
28
29 /* partitions (optional) */
30 };
31
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 252aaefcacfa..b0319d8934ad 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -22,6 +22,8 @@
22#include <linux/io.h> 22#include <linux/io.h>
23#include <linux/irq.h> 23#include <linux/irq.h>
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/of.h>
26#include <linux/of_device.h>
25 27
26#include <mach/dma.h> 28#include <mach/dma.h>
27#include <plat/pxa3xx_nand.h> 29#include <plat/pxa3xx_nand.h>
@@ -1081,21 +1083,31 @@ static int alloc_nand_resource(struct platform_device *pdev)
1081 } 1083 }
1082 clk_enable(info->clk); 1084 clk_enable(info->clk);
1083 1085
1084 r = platform_get_resource(pdev, IORESOURCE_DMA, 0); 1086 /*
1085 if (r == NULL) { 1087 * This is a dirty hack to make this driver work from devicetree
1086 dev_err(&pdev->dev, "no resource defined for data DMA\n"); 1088 * bindings. It can be removed once we have a prober DMA controller
1087 ret = -ENXIO; 1089 * framework for DT.
1088 goto fail_put_clk; 1090 */
1089 } 1091 if (pdev->dev.of_node && cpu_is_pxa3xx()) {
1090 info->drcmr_dat = r->start; 1092 info->drcmr_dat = 97;
1093 info->drcmr_cmd = 99;
1094 } else {
1095 r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
1096 if (r == NULL) {
1097 dev_err(&pdev->dev, "no resource defined for data DMA\n");
1098 ret = -ENXIO;
1099 goto fail_put_clk;
1100 }
1101 info->drcmr_dat = r->start;
1091 1102
1092 r = platform_get_resource(pdev, IORESOURCE_DMA, 1); 1103 r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
1093 if (r == NULL) { 1104 if (r == NULL) {
1094 dev_err(&pdev->dev, "no resource defined for command DMA\n"); 1105 dev_err(&pdev->dev, "no resource defined for command DMA\n");
1095 ret = -ENXIO; 1106 ret = -ENXIO;
1096 goto fail_put_clk; 1107 goto fail_put_clk;
1108 }
1109 info->drcmr_cmd = r->start;
1097 } 1110 }
1098 info->drcmr_cmd = r->start;
1099 1111
1100 irq = platform_get_irq(pdev, 0); 1112 irq = platform_get_irq(pdev, 0);
1101 if (irq < 0) { 1113 if (irq < 0) {
@@ -1200,12 +1212,55 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
1200 return 0; 1212 return 0;
1201} 1213}
1202 1214
1215#ifdef CONFIG_OF
1216static struct of_device_id pxa3xx_nand_dt_ids[] = {
1217 { .compatible = "marvell,pxa3xx-nand" },
1218 {}
1219};
1220MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids);
1221
1222static int pxa3xx_nand_probe_dt(struct platform_device *pdev)
1223{
1224 struct pxa3xx_nand_platform_data *pdata;
1225 struct device_node *np = pdev->dev.of_node;
1226 const struct of_device_id *of_id =
1227 of_match_device(pxa3xx_nand_dt_ids, &pdev->dev);
1228
1229 if (!of_id)
1230 return 0;
1231
1232 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
1233 if (!pdata)
1234 return -ENOMEM;
1235
1236 if (of_get_property(np, "marvell,nand-enable-arbiter", NULL))
1237 pdata->enable_arbiter = 1;
1238 if (of_get_property(np, "marvell,nand-keep-config", NULL))
1239 pdata->keep_config = 1;
1240 of_property_read_u32(np, "num-cs", &pdata->num_cs);
1241
1242 pdev->dev.platform_data = pdata;
1243
1244 return 0;
1245}
1246#else
1247static inline int pxa3xx_nand_probe_dt(struct platform_device *)
1248{
1249 return 0;
1250}
1251#endif
1252
1203static int pxa3xx_nand_probe(struct platform_device *pdev) 1253static int pxa3xx_nand_probe(struct platform_device *pdev)
1204{ 1254{
1205 struct pxa3xx_nand_platform_data *pdata; 1255 struct pxa3xx_nand_platform_data *pdata;
1256 struct mtd_part_parser_data ppdata = {};
1206 struct pxa3xx_nand_info *info; 1257 struct pxa3xx_nand_info *info;
1207 int ret, cs, probe_success; 1258 int ret, cs, probe_success;
1208 1259
1260 ret = pxa3xx_nand_probe_dt(pdev);
1261 if (ret)
1262 return ret;
1263
1209 pdata = pdev->dev.platform_data; 1264 pdata = pdev->dev.platform_data;
1210 if (!pdata) { 1265 if (!pdata) {
1211 dev_err(&pdev->dev, "no platform data defined\n"); 1266 dev_err(&pdev->dev, "no platform data defined\n");
@@ -1229,8 +1284,9 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
1229 continue; 1284 continue;
1230 } 1285 }
1231 1286
1287 ppdata.of_node = pdev->dev.of_node;
1232 ret = mtd_device_parse_register(info->host[cs]->mtd, NULL, 1288 ret = mtd_device_parse_register(info->host[cs]->mtd, NULL,
1233 NULL, pdata->parts[cs], 1289 &ppdata, pdata->parts[cs],
1234 pdata->nr_parts[cs]); 1290 pdata->nr_parts[cs]);
1235 if (!ret) 1291 if (!ret)
1236 probe_success = 1; 1292 probe_success = 1;
@@ -1306,6 +1362,7 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
1306static struct platform_driver pxa3xx_nand_driver = { 1362static struct platform_driver pxa3xx_nand_driver = {
1307 .driver = { 1363 .driver = {
1308 .name = "pxa3xx-nand", 1364 .name = "pxa3xx-nand",
1365 .of_match_table = of_match_ptr(pxa3xx_nand_dt_ids),
1309 }, 1366 },
1310 .probe = pxa3xx_nand_probe, 1367 .probe = pxa3xx_nand_probe,
1311 .remove = pxa3xx_nand_remove, 1368 .remove = pxa3xx_nand_remove,