aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2013-02-05 17:03:31 -0500
committerOlof Johansson <olof@lixom.net>2013-02-05 17:03:45 -0500
commitb6a03d0492dedb5c10b8a5708ee92e04b0590c07 (patch)
tree21774ee93c50847fe1ea044f2cabae0746ac39d3 /arch/arm/mach-omap2
parent3e93093ecd0c144e86a86cc1f165221b6cd3e7fb (diff)
parent97c794a1e37b1ca128ef38f17c069186bfa5fb1b (diff)
Merge tag 'omap-for-v3.9/gpmc-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/drivers
From Tony Lindgren: OMAP GPMC (General Purpose Memory Controller) changes to add device tree bindings. * tag 'omap-for-v3.9/gpmc-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: ARM: OMAP2+: gpmc: Add device tree documentation for elm handle ARM: OMAP2+: gpmc: add DT bindings for OneNAND ARM: OMAP2+: gpmc-onenand: drop __init annotation mtd: omap-onenand: pass device_node in platform data ARM: OMAP2+: Prevent potential crash if GPMC probe fails ARM: OMAP2+: gpmc: Remove unneeded of_node_put() ARM: OMAP: gpmc: add DT bindings for GPMC timings and NAND ARM: OMAP: gpmc: enable hwecc for AM33xx SoCs ARM: OMAP: gpmc-nand: drop __init annotation mtd: omap-nand: pass device_node in platform data ARM: OMAP: gpmc: don't create devices from initcall on DT Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/gpmc-nand.c15
-rw-r--r--arch/arm/mach-omap2/gpmc-onenand.c2
-rw-r--r--arch/arm/mach-omap2/gpmc.c232
3 files changed, 240 insertions, 9 deletions
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index db969a5c4998..afc1e8c32d6c 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -89,20 +89,21 @@ static int omap2_nand_gpmc_retime(
89 return 0; 89 return 0;
90} 90}
91 91
92static bool __init gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt) 92static bool gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt)
93{ 93{
94 /* support only OMAP3 class */ 94 /* support only OMAP3 class */
95 if (!cpu_is_omap34xx()) { 95 if (!cpu_is_omap34xx() && !soc_is_am33xx()) {
96 pr_err("BCH ecc is not supported on this CPU\n"); 96 pr_err("BCH ecc is not supported on this CPU\n");
97 return 0; 97 return 0;
98 } 98 }
99 99
100 /* 100 /*
101 * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1. 101 * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1
102 * Other chips may be added if confirmed to work. 102 * and AM33xx derivates. Other chips may be added if confirmed to work.
103 */ 103 */
104 if ((ecc_opt == OMAP_ECC_BCH4_CODE_HW) && 104 if ((ecc_opt == OMAP_ECC_BCH4_CODE_HW) &&
105 (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0))) { 105 (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0)) &&
106 (!soc_is_am33xx())) {
106 pr_err("BCH 4-bit mode is not supported on this CPU\n"); 107 pr_err("BCH 4-bit mode is not supported on this CPU\n");
107 return 0; 108 return 0;
108 } 109 }
@@ -110,8 +111,8 @@ static bool __init gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt)
110 return 1; 111 return 1;
111} 112}
112 113
113int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, 114int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
114 struct gpmc_timings *gpmc_t) 115 struct gpmc_timings *gpmc_t)
115{ 116{
116 int err = 0; 117 int err = 0;
117 struct device *dev = &gpmc_nand_device.dev; 118 struct device *dev = &gpmc_nand_device.dev;
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index 94a349e4dc96..fadd87435cd0 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -356,7 +356,7 @@ static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
356 return ret; 356 return ret;
357} 357}
358 358
359void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) 359void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
360{ 360{
361 int err; 361 int err;
362 362
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 8033cb747c86..1adb2d4496f6 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -25,6 +25,10 @@
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/interrupt.h> 26#include <linux/interrupt.h>
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/of.h>
29#include <linux/of_mtd.h>
30#include <linux/of_device.h>
31#include <linux/mtd/nand.h>
28 32
29#include <linux/platform_data/mtd-nand-omap2.h> 33#include <linux/platform_data/mtd-nand-omap2.h>
30 34
@@ -34,6 +38,8 @@
34#include "common.h" 38#include "common.h"
35#include "omap_device.h" 39#include "omap_device.h"
36#include "gpmc.h" 40#include "gpmc.h"
41#include "gpmc-nand.h"
42#include "gpmc-onenand.h"
37 43
38#define DEVICE_NAME "omap-gpmc" 44#define DEVICE_NAME "omap-gpmc"
39 45
@@ -145,7 +151,8 @@ static unsigned gpmc_irq_start;
145static struct resource gpmc_mem_root; 151static struct resource gpmc_mem_root;
146static struct resource gpmc_cs_mem[GPMC_CS_NUM]; 152static struct resource gpmc_cs_mem[GPMC_CS_NUM];
147static DEFINE_SPINLOCK(gpmc_mem_lock); 153static DEFINE_SPINLOCK(gpmc_mem_lock);
148static unsigned int gpmc_cs_map; /* flag for cs which are initialized */ 154/* Define chip-selects as reserved by default until probe completes */
155static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1);
149static struct device *gpmc_dev; 156static struct device *gpmc_dev;
150static int gpmc_irq; 157static int gpmc_irq;
151static resource_size_t phys_base, mem_size; 158static resource_size_t phys_base, mem_size;
@@ -1118,9 +1125,216 @@ int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
1118 /* TODO: remove, see function definition */ 1125 /* TODO: remove, see function definition */
1119 gpmc_convert_ps_to_ns(gpmc_t); 1126 gpmc_convert_ps_to_ns(gpmc_t);
1120 1127
1128 /* Now the GPMC is initialised, unreserve the chip-selects */
1129 gpmc_cs_map = 0;
1130
1121 return 0; 1131 return 0;
1122} 1132}
1123 1133
1134#ifdef CONFIG_OF
1135static struct of_device_id gpmc_dt_ids[] = {
1136 { .compatible = "ti,omap2420-gpmc" },
1137 { .compatible = "ti,omap2430-gpmc" },
1138 { .compatible = "ti,omap3430-gpmc" }, /* omap3430 & omap3630 */
1139 { .compatible = "ti,omap4430-gpmc" }, /* omap4430 & omap4460 & omap543x */
1140 { .compatible = "ti,am3352-gpmc" }, /* am335x devices */
1141 { }
1142};
1143MODULE_DEVICE_TABLE(of, gpmc_dt_ids);
1144
1145static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
1146 struct gpmc_timings *gpmc_t)
1147{
1148 u32 val;
1149
1150 memset(gpmc_t, 0, sizeof(*gpmc_t));
1151
1152 /* minimum clock period for syncronous mode */
1153 if (!of_property_read_u32(np, "gpmc,sync-clk", &val))
1154 gpmc_t->sync_clk = val;
1155
1156 /* chip select timtings */
1157 if (!of_property_read_u32(np, "gpmc,cs-on", &val))
1158 gpmc_t->cs_on = val;
1159
1160 if (!of_property_read_u32(np, "gpmc,cs-rd-off", &val))
1161 gpmc_t->cs_rd_off = val;
1162
1163 if (!of_property_read_u32(np, "gpmc,cs-wr-off", &val))
1164 gpmc_t->cs_wr_off = val;
1165
1166 /* ADV signal timings */
1167 if (!of_property_read_u32(np, "gpmc,adv-on", &val))
1168 gpmc_t->adv_on = val;
1169
1170 if (!of_property_read_u32(np, "gpmc,adv-rd-off", &val))
1171 gpmc_t->adv_rd_off = val;
1172
1173 if (!of_property_read_u32(np, "gpmc,adv-wr-off", &val))
1174 gpmc_t->adv_wr_off = val;
1175
1176 /* WE signal timings */
1177 if (!of_property_read_u32(np, "gpmc,we-on", &val))
1178 gpmc_t->we_on = val;
1179
1180 if (!of_property_read_u32(np, "gpmc,we-off", &val))
1181 gpmc_t->we_off = val;
1182
1183 /* OE signal timings */
1184 if (!of_property_read_u32(np, "gpmc,oe-on", &val))
1185 gpmc_t->oe_on = val;
1186
1187 if (!of_property_read_u32(np, "gpmc,oe-off", &val))
1188 gpmc_t->oe_off = val;
1189
1190 /* access and cycle timings */
1191 if (!of_property_read_u32(np, "gpmc,page-burst-access", &val))
1192 gpmc_t->page_burst_access = val;
1193
1194 if (!of_property_read_u32(np, "gpmc,access", &val))
1195 gpmc_t->access = val;
1196
1197 if (!of_property_read_u32(np, "gpmc,rd-cycle", &val))
1198 gpmc_t->rd_cycle = val;
1199
1200 if (!of_property_read_u32(np, "gpmc,wr-cycle", &val))
1201 gpmc_t->wr_cycle = val;
1202
1203 /* only for OMAP3430 */
1204 if (!of_property_read_u32(np, "gpmc,wr-access", &val))
1205 gpmc_t->wr_access = val;
1206
1207 if (!of_property_read_u32(np, "gpmc,wr-data-mux-bus", &val))
1208 gpmc_t->wr_data_mux_bus = val;
1209}
1210
1211#ifdef CONFIG_MTD_NAND
1212
1213static const char * const nand_ecc_opts[] = {
1214 [OMAP_ECC_HAMMING_CODE_DEFAULT] = "sw",
1215 [OMAP_ECC_HAMMING_CODE_HW] = "hw",
1216 [OMAP_ECC_HAMMING_CODE_HW_ROMCODE] = "hw-romcode",
1217 [OMAP_ECC_BCH4_CODE_HW] = "bch4",
1218 [OMAP_ECC_BCH8_CODE_HW] = "bch8",
1219};
1220
1221static int gpmc_probe_nand_child(struct platform_device *pdev,
1222 struct device_node *child)
1223{
1224 u32 val;
1225 const char *s;
1226 struct gpmc_timings gpmc_t;
1227 struct omap_nand_platform_data *gpmc_nand_data;
1228
1229 if (of_property_read_u32(child, "reg", &val) < 0) {
1230 dev_err(&pdev->dev, "%s has no 'reg' property\n",
1231 child->full_name);
1232 return -ENODEV;
1233 }
1234
1235 gpmc_nand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_nand_data),
1236 GFP_KERNEL);
1237 if (!gpmc_nand_data)
1238 return -ENOMEM;
1239
1240 gpmc_nand_data->cs = val;
1241 gpmc_nand_data->of_node = child;
1242
1243 if (!of_property_read_string(child, "ti,nand-ecc-opt", &s))
1244 for (val = 0; val < ARRAY_SIZE(nand_ecc_opts); val++)
1245 if (!strcasecmp(s, nand_ecc_opts[val])) {
1246 gpmc_nand_data->ecc_opt = val;
1247 break;
1248 }
1249
1250 val = of_get_nand_bus_width(child);
1251 if (val == 16)
1252 gpmc_nand_data->devsize = NAND_BUSWIDTH_16;
1253
1254 gpmc_read_timings_dt(child, &gpmc_t);
1255 gpmc_nand_init(gpmc_nand_data, &gpmc_t);
1256
1257 return 0;
1258}
1259#else
1260static int gpmc_probe_nand_child(struct platform_device *pdev,
1261 struct device_node *child)
1262{
1263 return 0;
1264}
1265#endif
1266
1267#ifdef CONFIG_MTD_ONENAND
1268static int gpmc_probe_onenand_child(struct platform_device *pdev,
1269 struct device_node *child)
1270{
1271 u32 val;
1272 struct omap_onenand_platform_data *gpmc_onenand_data;
1273
1274 if (of_property_read_u32(child, "reg", &val) < 0) {
1275 dev_err(&pdev->dev, "%s has no 'reg' property\n",
1276 child->full_name);
1277 return -ENODEV;
1278 }
1279
1280 gpmc_onenand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_onenand_data),
1281 GFP_KERNEL);
1282 if (!gpmc_onenand_data)
1283 return -ENOMEM;
1284
1285 gpmc_onenand_data->cs = val;
1286 gpmc_onenand_data->of_node = child;
1287 gpmc_onenand_data->dma_channel = -1;
1288
1289 if (!of_property_read_u32(child, "dma-channel", &val))
1290 gpmc_onenand_data->dma_channel = val;
1291
1292 gpmc_onenand_init(gpmc_onenand_data);
1293
1294 return 0;
1295}
1296#else
1297static int gpmc_probe_onenand_child(struct platform_device *pdev,
1298 struct device_node *child)
1299{
1300 return 0;
1301}
1302#endif
1303
1304static int gpmc_probe_dt(struct platform_device *pdev)
1305{
1306 int ret;
1307 struct device_node *child;
1308 const struct of_device_id *of_id =
1309 of_match_device(gpmc_dt_ids, &pdev->dev);
1310
1311 if (!of_id)
1312 return 0;
1313
1314 for_each_node_by_name(child, "nand") {
1315 ret = gpmc_probe_nand_child(pdev, child);
1316 if (ret < 0) {
1317 of_node_put(child);
1318 return ret;
1319 }
1320 }
1321
1322 for_each_node_by_name(child, "onenand") {
1323 ret = gpmc_probe_onenand_child(pdev, child);
1324 if (ret < 0) {
1325 of_node_put(child);
1326 return ret;
1327 }
1328 }
1329 return 0;
1330}
1331#else
1332static int gpmc_probe_dt(struct platform_device *pdev)
1333{
1334 return 0;
1335}
1336#endif
1337
1124static int gpmc_probe(struct platform_device *pdev) 1338static int gpmc_probe(struct platform_device *pdev)
1125{ 1339{
1126 int rc; 1340 int rc;
@@ -1174,6 +1388,14 @@ static int gpmc_probe(struct platform_device *pdev)
1174 if (IS_ERR_VALUE(gpmc_setup_irq())) 1388 if (IS_ERR_VALUE(gpmc_setup_irq()))
1175 dev_warn(gpmc_dev, "gpmc_setup_irq failed\n"); 1389 dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
1176 1390
1391 rc = gpmc_probe_dt(pdev);
1392 if (rc < 0) {
1393 clk_disable_unprepare(gpmc_l3_clk);
1394 clk_put(gpmc_l3_clk);
1395 dev_err(gpmc_dev, "failed to probe DT parameters\n");
1396 return rc;
1397 }
1398
1177 return 0; 1399 return 0;
1178} 1400}
1179 1401
@@ -1191,6 +1413,7 @@ static struct platform_driver gpmc_driver = {
1191 .driver = { 1413 .driver = {
1192 .name = DEVICE_NAME, 1414 .name = DEVICE_NAME,
1193 .owner = THIS_MODULE, 1415 .owner = THIS_MODULE,
1416 .of_match_table = of_match_ptr(gpmc_dt_ids),
1194 }, 1417 },
1195}; 1418};
1196 1419
@@ -1214,6 +1437,13 @@ static int __init omap_gpmc_init(void)
1214 struct platform_device *pdev; 1437 struct platform_device *pdev;
1215 char *oh_name = "gpmc"; 1438 char *oh_name = "gpmc";
1216 1439
1440 /*
1441 * if the board boots up with a populated DT, do not
1442 * manually add the device from this initcall
1443 */
1444 if (of_have_populated_dt())
1445 return -ENODEV;
1446
1217 oh = omap_hwmod_lookup(oh_name); 1447 oh = omap_hwmod_lookup(oh_name);
1218 if (!oh) { 1448 if (!oh) {
1219 pr_err("Could not look up %s\n", oh_name); 1449 pr_err("Could not look up %s\n", oh_name);