aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorBastian Hecht <hechtb@googlemail.com>2012-10-19 06:15:36 -0400
committerArtem Bityutskiy <artem.bityutskiy@linux.intel.com>2012-11-15 08:37:50 -0500
commit7c8f680e96edbd9896b13b5e6ff39bc5852dce2a (patch)
treeb9739bdc2f32c413b58d8599415aa76d525c1911 /drivers/mtd
parent83738d87e3a0a4096e1419a65b8228130d183df6 (diff)
mtd: sh_flctl: Add device tree support
The flctl can now be probed via device tree setup in addition to the existing platform data way. SoC specific setup data is set in the .data member of the OF match, so kept within the driver itself, while board/user specific setup - like partitioning - is taken from the device tree. Actual configuration is added for the SoC sh7372. Signed-off-by: Bastian Hecht <hechtb@gmail.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/sh_flctl.c94
1 files changed, 87 insertions, 7 deletions
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index 6dc0369aa44b..d51e3c15d379 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -29,6 +29,9 @@
29#include <linux/dma-mapping.h> 29#include <linux/dma-mapping.h>
30#include <linux/interrupt.h> 30#include <linux/interrupt.h>
31#include <linux/io.h> 31#include <linux/io.h>
32#include <linux/of.h>
33#include <linux/of_device.h>
34#include <linux/of_mtd.h>
32#include <linux/platform_device.h> 35#include <linux/platform_device.h>
33#include <linux/pm_runtime.h> 36#include <linux/pm_runtime.h>
34#include <linux/sh_dma.h> 37#include <linux/sh_dma.h>
@@ -1016,6 +1019,73 @@ static irqreturn_t flctl_handle_flste(int irq, void *dev_id)
1016 return IRQ_HANDLED; 1019 return IRQ_HANDLED;
1017} 1020}
1018 1021
1022#ifdef CONFIG_OF
1023struct flctl_soc_config {
1024 unsigned long flcmncr_val;
1025 unsigned has_hwecc:1;
1026 unsigned use_holden:1;
1027};
1028
1029static struct flctl_soc_config flctl_sh7372_config = {
1030 .flcmncr_val = CLK_16B_12L_4H | TYPESEL_SET | SHBUSSEL,
1031 .has_hwecc = 1,
1032 .use_holden = 1,
1033};
1034
1035static const struct of_device_id of_flctl_match[] = {
1036 { .compatible = "renesas,shmobile-flctl-sh7372",
1037 .data = &flctl_sh7372_config },
1038 {},
1039};
1040MODULE_DEVICE_TABLE(of, of_flctl_match);
1041
1042static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
1043{
1044 const struct of_device_id *match;
1045 struct flctl_soc_config *config;
1046 struct sh_flctl_platform_data *pdata;
1047 struct device_node *dn = dev->of_node;
1048 int ret;
1049
1050 match = of_match_device(of_flctl_match, dev);
1051 if (match)
1052 config = (struct flctl_soc_config *)match->data;
1053 else {
1054 dev_err(dev, "%s: no OF configuration attached\n", __func__);
1055 return NULL;
1056 }
1057
1058 pdata = devm_kzalloc(dev, sizeof(struct sh_flctl_platform_data),
1059 GFP_KERNEL);
1060 if (!pdata) {
1061 dev_err(dev, "%s: failed to allocate config data\n", __func__);
1062 return NULL;
1063 }
1064
1065 /* set SoC specific options */
1066 pdata->flcmncr_val = config->flcmncr_val;
1067 pdata->has_hwecc = config->has_hwecc;
1068 pdata->use_holden = config->use_holden;
1069
1070 /* parse user defined options */
1071 ret = of_get_nand_bus_width(dn);
1072 if (ret == 16)
1073 pdata->flcmncr_val |= SEL_16BIT;
1074 else if (ret != 8) {
1075 dev_err(dev, "%s: invalid bus width\n", __func__);
1076 return NULL;
1077 }
1078
1079 return pdata;
1080}
1081#else /* CONFIG_OF */
1082#define of_flctl_match NULL
1083static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
1084{
1085 return NULL;
1086}
1087#endif /* CONFIG_OF */
1088
1019static int __devinit flctl_probe(struct platform_device *pdev) 1089static int __devinit flctl_probe(struct platform_device *pdev)
1020{ 1090{
1021 struct resource *res; 1091 struct resource *res;
@@ -1025,12 +1095,7 @@ static int __devinit flctl_probe(struct platform_device *pdev)
1025 struct sh_flctl_platform_data *pdata; 1095 struct sh_flctl_platform_data *pdata;
1026 int ret = -ENXIO; 1096 int ret = -ENXIO;
1027 int irq; 1097 int irq;
1028 1098 struct mtd_part_parser_data ppdata = {};
1029 pdata = pdev->dev.platform_data;
1030 if (pdata == NULL) {
1031 dev_err(&pdev->dev, "no platform data defined\n");
1032 return -EINVAL;
1033 }
1034 1099
1035 flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL); 1100 flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL);
1036 if (!flctl) { 1101 if (!flctl) {
@@ -1062,6 +1127,17 @@ static int __devinit flctl_probe(struct platform_device *pdev)
1062 goto err_flste; 1127 goto err_flste;
1063 } 1128 }
1064 1129
1130 if (pdev->dev.of_node)
1131 pdata = flctl_parse_dt(&pdev->dev);
1132 else
1133 pdata = pdev->dev.platform_data;
1134
1135 if (!pdata) {
1136 dev_err(&pdev->dev, "no setup data defined\n");
1137 ret = -EINVAL;
1138 goto err_pdata;
1139 }
1140
1065 platform_set_drvdata(pdev, flctl); 1141 platform_set_drvdata(pdev, flctl);
1066 flctl_mtd = &flctl->mtd; 1142 flctl_mtd = &flctl->mtd;
1067 nand = &flctl->chip; 1143 nand = &flctl->chip;
@@ -1104,13 +1180,16 @@ static int __devinit flctl_probe(struct platform_device *pdev)
1104 if (ret) 1180 if (ret)
1105 goto err_chip; 1181 goto err_chip;
1106 1182
1107 mtd_device_register(flctl_mtd, pdata->parts, pdata->nr_parts); 1183 ppdata.of_node = pdev->dev.of_node;
1184 ret = mtd_device_parse_register(flctl_mtd, NULL, &ppdata, pdata->parts,
1185 pdata->nr_parts);
1108 1186
1109 return 0; 1187 return 0;
1110 1188
1111err_chip: 1189err_chip:
1112 flctl_release_dma(flctl); 1190 flctl_release_dma(flctl);
1113 pm_runtime_disable(&pdev->dev); 1191 pm_runtime_disable(&pdev->dev);
1192err_pdata:
1114 free_irq(irq, flctl); 1193 free_irq(irq, flctl);
1115err_flste: 1194err_flste:
1116 iounmap(flctl->reg); 1195 iounmap(flctl->reg);
@@ -1138,6 +1217,7 @@ static struct platform_driver flctl_driver = {
1138 .driver = { 1217 .driver = {
1139 .name = "sh_flctl", 1218 .name = "sh_flctl",
1140 .owner = THIS_MODULE, 1219 .owner = THIS_MODULE,
1220 .of_match_table = of_flctl_match,
1141 }, 1221 },
1142}; 1222};
1143 1223