diff options
Diffstat (limited to 'drivers/mtd')
| -rw-r--r-- | drivers/mtd/nand/pxa3xx_nand.c | 87 |
1 files changed, 72 insertions, 15 deletions
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 252aaefcacfa..d944d6ef7da8 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> |
| @@ -1032,7 +1034,7 @@ static int alloc_nand_resource(struct platform_device *pdev) | |||
| 1032 | struct pxa3xx_nand_platform_data *pdata; | 1034 | struct pxa3xx_nand_platform_data *pdata; |
| 1033 | struct pxa3xx_nand_info *info; | 1035 | struct pxa3xx_nand_info *info; |
| 1034 | struct pxa3xx_nand_host *host; | 1036 | struct pxa3xx_nand_host *host; |
| 1035 | struct nand_chip *chip; | 1037 | struct nand_chip *chip = NULL; |
| 1036 | struct mtd_info *mtd; | 1038 | struct mtd_info *mtd; |
| 1037 | struct resource *r; | 1039 | struct resource *r; |
| 1038 | int ret, irq, cs; | 1040 | int ret, irq, cs; |
| @@ -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 | ||
| 1216 | static struct of_device_id pxa3xx_nand_dt_ids[] = { | ||
| 1217 | { .compatible = "marvell,pxa3xx-nand" }, | ||
| 1218 | {} | ||
| 1219 | }; | ||
| 1220 | MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids); | ||
| 1221 | |||
| 1222 | static 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 | ||
| 1247 | static inline int pxa3xx_nand_probe_dt(struct platform_device *pdev) | ||
| 1248 | { | ||
| 1249 | return 0; | ||
| 1250 | } | ||
| 1251 | #endif | ||
| 1252 | |||
| 1203 | static int pxa3xx_nand_probe(struct platform_device *pdev) | 1253 | static 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) | |||
| 1306 | static struct platform_driver pxa3xx_nand_driver = { | 1362 | static 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, |
