aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2012-12-14 05:36:44 -0500
committerTony Lindgren <tony@atomide.com>2013-01-15 17:50:15 -0500
commitbc6b1e7b86f5d8e4a6fc1c0189e64bba4077efe0 (patch)
treeddf01fdfc247be244e453139a10af05c7b50b602
parentf50a0380897d2a5e61b251b07c50ee48fa298cfd (diff)
ARM: OMAP: gpmc: add DT bindings for GPMC timings and NAND
This patch adds basic DT bindings for OMAP GPMC. The actual peripherals are instantiated from child nodes within the GPMC node, and the only type of device that is currently supported is NAND. Code was added to parse the generic GPMC timing parameters and some documentation with examples on how to use them. Successfully tested on an AM33xx board. Signed-off-by: Daniel Mack <zonque@gmail.com> Acked-by: Grant Likely <grant.likely@secretlab.ca> [tony@atomide.com: updated to apply] Signed-off-by: Tony Lindgren <tony@atomide.com>
-rw-r--r--Documentation/devicetree/bindings/bus/ti-gpmc.txt84
-rw-r--r--Documentation/devicetree/bindings/mtd/gpmc-nand.txt76
-rw-r--r--arch/arm/mach-omap2/gpmc.c173
3 files changed, 333 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/bus/ti-gpmc.txt b/Documentation/devicetree/bindings/bus/ti-gpmc.txt
new file mode 100644
index 000000000000..5ddb2e9efaaa
--- /dev/null
+++ b/Documentation/devicetree/bindings/bus/ti-gpmc.txt
@@ -0,0 +1,84 @@
1Device tree bindings for OMAP general purpose memory controllers (GPMC)
2
3The actual devices are instantiated from the child nodes of a GPMC node.
4
5Required properties:
6
7 - compatible: Should be set to one of the following:
8
9 ti,omap2420-gpmc (omap2420)
10 ti,omap2430-gpmc (omap2430)
11 ti,omap3430-gpmc (omap3430 & omap3630)
12 ti,omap4430-gpmc (omap4430 & omap4460 & omap543x)
13 ti,am3352-gpmc (am335x devices)
14
15 - reg: A resource specifier for the register space
16 (see the example below)
17 - ti,hwmods: Should be set to "ti,gpmc" until the DT transition is
18 completed.
19 - #address-cells: Must be set to 2 to allow memory address translation
20 - #size-cells: Must be set to 1 to allow CS address passing
21 - gpmc,num-cs: The maximum number of chip-select lines that controller
22 can support.
23 - gpmc,num-waitpins: The maximum number of wait pins that controller can
24 support.
25 - ranges: Must be set up to reflect the memory layout with four
26 integer values for each chip-select line in use:
27
28 <cs-number> 0 <physical address of mapping> <size>
29
30 Currently, calculated values derived from the contents
31 of the per-CS register GPMC_CONFIG7 (as set up by the
32 bootloader) are used for the physical address decoding.
33 As this will change in the future, filling correct
34 values here is a requirement.
35
36Timing properties for child nodes. All are optional and default to 0.
37
38 - gpmc,sync-clk: Minimum clock period for synchronous mode, in picoseconds
39
40 Chip-select signal timings corresponding to GPMC_CONFIG2:
41 - gpmc,cs-on: Assertion time
42 - gpmc,cs-rd-off: Read deassertion time
43 - gpmc,cs-wr-off: Write deassertion time
44
45 ADV signal timings corresponding to GPMC_CONFIG3:
46 - gpmc,adv-on: Assertion time
47 - gpmc,adv-rd-off: Read deassertion time
48 - gpmc,adv-wr-off: Write deassertion time
49
50 WE signals timings corresponding to GPMC_CONFIG4:
51 - gpmc,we-on: Assertion time
52 - gpmc,we-off: Deassertion time
53
54 OE signals timings corresponding to GPMC_CONFIG4:
55 - gpmc,oe-on: Assertion time
56 - gpmc,oe-off: Deassertion time
57
58 Access time and cycle time timings corresponding to GPMC_CONFIG5:
59 - gpmc,page-burst-access: Multiple access word delay
60 - gpmc,access: Start-cycle to first data valid delay
61 - gpmc,rd-cycle: Total read cycle time
62 - gpmc,wr-cycle: Total write cycle time
63
64The following are only applicable to OMAP3+ and AM335x:
65 - gpmc,wr-access
66 - gpmc,wr-data-mux-bus
67
68
69Example for an AM33xx board:
70
71 gpmc: gpmc@50000000 {
72 compatible = "ti,am3352-gpmc";
73 ti,hwmods = "gpmc";
74 reg = <0x50000000 0x2000>;
75 interrupts = <100>;
76
77 gpmc,num-cs = <8>;
78 gpmc,num-waitpins = <2>;
79 #address-cells = <2>;
80 #size-cells = <1>;
81 ranges = <0 0 0x08000000 0x10000000>; /* CS0 @addr 0x8000000, size 0x10000000 */
82
83 /* child nodes go here */
84 };
diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
new file mode 100644
index 000000000000..9f464f906ffb
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
@@ -0,0 +1,76 @@
1Device tree bindings for GPMC connected NANDs
2
3GPMC connected NAND (found on OMAP boards) are represented as child nodes of
4the GPMC controller with a name of "nand".
5
6All timing relevant properties as well as generic gpmc child properties are
7explained in a separate documents - please refer to
8Documentation/devicetree/bindings/bus/ti-gpmc.txt
9
10For NAND specific properties such as ECC modes or bus width, please refer to
11Documentation/devicetree/bindings/mtd/nand.txt
12
13
14Required properties:
15
16 - reg: The CS line the peripheral is connected to
17
18Optional properties:
19
20 - nand-bus-width: Set this numeric value to 16 if the hardware
21 is wired that way. If not specified, a bus
22 width of 8 is assumed.
23
24 - ti,nand-ecc-opt: A string setting the ECC layout to use. One of:
25
26 "sw" Software method (default)
27 "hw" Hardware method
28 "hw-romcode" gpmc hamming mode method & romcode layout
29 "bch4" 4-bit BCH ecc code
30 "bch8" 8-bit BCH ecc code
31
32For inline partiton table parsing (optional):
33
34 - #address-cells: should be set to 1
35 - #size-cells: should be set to 1
36
37Example for an AM33xx board:
38
39 gpmc: gpmc@50000000 {
40 compatible = "ti,am3352-gpmc";
41 ti,hwmods = "gpmc";
42 reg = <0x50000000 0x1000000>;
43 interrupts = <100>;
44 gpmc,num-cs = <8>;
45 gpmc,num-waitpins = <2>;
46 #address-cells = <2>;
47 #size-cells = <1>;
48 ranges = <0 0 0x08000000 0x2000>; /* CS0: NAND */
49
50 nand@0,0 {
51 reg = <0 0 0>; /* CS0, offset 0 */
52 nand-bus-width = <16>;
53 ti,nand-ecc-opt = "bch8";
54
55 gpmc,sync-clk = <0>;
56 gpmc,cs-on = <0>;
57 gpmc,cs-rd-off = <44>;
58 gpmc,cs-wr-off = <44>;
59 gpmc,adv-on = <6>;
60 gpmc,adv-rd-off = <34>;
61 gpmc,adv-wr-off = <44>;
62 gpmc,we-off = <40>;
63 gpmc,oe-off = <54>;
64 gpmc,access = <64>;
65 gpmc,rd-cycle = <82>;
66 gpmc,wr-cycle = <82>;
67 gpmc,wr-access = <40>;
68 gpmc,wr-data-mux-bus = <0>;
69
70 #address-cells = <1>;
71 #size-cells = <1>;
72
73 /* partitions go here */
74 };
75 };
76
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 1f0ec79aabf1..01ce462e265d 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,7 @@
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"
37 42
38#define DEVICE_NAME "omap-gpmc" 43#define DEVICE_NAME "omap-gpmc"
39 44
@@ -1121,6 +1126,165 @@ int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
1121 return 0; 1126 return 0;
1122} 1127}
1123 1128
1129#ifdef CONFIG_OF
1130static struct of_device_id gpmc_dt_ids[] = {
1131 { .compatible = "ti,omap2420-gpmc" },
1132 { .compatible = "ti,omap2430-gpmc" },
1133 { .compatible = "ti,omap3430-gpmc" }, /* omap3430 & omap3630 */
1134 { .compatible = "ti,omap4430-gpmc" }, /* omap4430 & omap4460 & omap543x */
1135 { .compatible = "ti,am3352-gpmc" }, /* am335x devices */
1136 { }
1137};
1138MODULE_DEVICE_TABLE(of, gpmc_dt_ids);
1139
1140static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
1141 struct gpmc_timings *gpmc_t)
1142{
1143 u32 val;
1144
1145 memset(gpmc_t, 0, sizeof(*gpmc_t));
1146
1147 /* minimum clock period for syncronous mode */
1148 if (!of_property_read_u32(np, "gpmc,sync-clk", &val))
1149 gpmc_t->sync_clk = val;
1150
1151 /* chip select timtings */
1152 if (!of_property_read_u32(np, "gpmc,cs-on", &val))
1153 gpmc_t->cs_on = val;
1154
1155 if (!of_property_read_u32(np, "gpmc,cs-rd-off", &val))
1156 gpmc_t->cs_rd_off = val;
1157
1158 if (!of_property_read_u32(np, "gpmc,cs-wr-off", &val))
1159 gpmc_t->cs_wr_off = val;
1160
1161 /* ADV signal timings */
1162 if (!of_property_read_u32(np, "gpmc,adv-on", &val))
1163 gpmc_t->adv_on = val;
1164
1165 if (!of_property_read_u32(np, "gpmc,adv-rd-off", &val))
1166 gpmc_t->adv_rd_off = val;
1167
1168 if (!of_property_read_u32(np, "gpmc,adv-wr-off", &val))
1169 gpmc_t->adv_wr_off = val;
1170
1171 /* WE signal timings */
1172 if (!of_property_read_u32(np, "gpmc,we-on", &val))
1173 gpmc_t->we_on = val;
1174
1175 if (!of_property_read_u32(np, "gpmc,we-off", &val))
1176 gpmc_t->we_off = val;
1177
1178 /* OE signal timings */
1179 if (!of_property_read_u32(np, "gpmc,oe-on", &val))
1180 gpmc_t->oe_on = val;
1181
1182 if (!of_property_read_u32(np, "gpmc,oe-off", &val))
1183 gpmc_t->oe_off = val;
1184
1185 /* access and cycle timings */
1186 if (!of_property_read_u32(np, "gpmc,page-burst-access", &val))
1187 gpmc_t->page_burst_access = val;
1188
1189 if (!of_property_read_u32(np, "gpmc,access", &val))
1190 gpmc_t->access = val;
1191
1192 if (!of_property_read_u32(np, "gpmc,rd-cycle", &val))
1193 gpmc_t->rd_cycle = val;
1194
1195 if (!of_property_read_u32(np, "gpmc,wr-cycle", &val))
1196 gpmc_t->wr_cycle = val;
1197
1198 /* only for OMAP3430 */
1199 if (!of_property_read_u32(np, "gpmc,wr-access", &val))
1200 gpmc_t->wr_access = val;
1201
1202 if (!of_property_read_u32(np, "gpmc,wr-data-mux-bus", &val))
1203 gpmc_t->wr_data_mux_bus = val;
1204}
1205
1206#ifdef CONFIG_MTD_NAND
1207
1208static const char * const nand_ecc_opts[] = {
1209 [OMAP_ECC_HAMMING_CODE_DEFAULT] = "sw",
1210 [OMAP_ECC_HAMMING_CODE_HW] = "hw",
1211 [OMAP_ECC_HAMMING_CODE_HW_ROMCODE] = "hw-romcode",
1212 [OMAP_ECC_BCH4_CODE_HW] = "bch4",
1213 [OMAP_ECC_BCH8_CODE_HW] = "bch8",
1214};
1215
1216static int gpmc_probe_nand_child(struct platform_device *pdev,
1217 struct device_node *child)
1218{
1219 u32 val;
1220 const char *s;
1221 struct gpmc_timings gpmc_t;
1222 struct omap_nand_platform_data *gpmc_nand_data;
1223
1224 if (of_property_read_u32(child, "reg", &val) < 0) {
1225 dev_err(&pdev->dev, "%s has no 'reg' property\n",
1226 child->full_name);
1227 return -ENODEV;
1228 }
1229
1230 gpmc_nand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_nand_data),
1231 GFP_KERNEL);
1232 if (!gpmc_nand_data)
1233 return -ENOMEM;
1234
1235 gpmc_nand_data->cs = val;
1236 gpmc_nand_data->of_node = child;
1237
1238 if (!of_property_read_string(child, "ti,nand-ecc-opt", &s))
1239 for (val = 0; val < ARRAY_SIZE(nand_ecc_opts); val++)
1240 if (!strcasecmp(s, nand_ecc_opts[val])) {
1241 gpmc_nand_data->ecc_opt = val;
1242 break;
1243 }
1244
1245 val = of_get_nand_bus_width(child);
1246 if (val == 16)
1247 gpmc_nand_data->devsize = NAND_BUSWIDTH_16;
1248
1249 gpmc_read_timings_dt(child, &gpmc_t);
1250 gpmc_nand_init(gpmc_nand_data, &gpmc_t);
1251
1252 return 0;
1253}
1254#else
1255static int gpmc_probe_nand_child(struct platform_device *pdev,
1256 struct device_node *child)
1257{
1258 return 0;
1259}
1260#endif
1261
1262static int gpmc_probe_dt(struct platform_device *pdev)
1263{
1264 int ret;
1265 struct device_node *child;
1266 const struct of_device_id *of_id =
1267 of_match_device(gpmc_dt_ids, &pdev->dev);
1268
1269 if (!of_id)
1270 return 0;
1271
1272 for_each_node_by_name(child, "nand") {
1273 ret = gpmc_probe_nand_child(pdev, child);
1274 of_node_put(child);
1275 if (ret < 0)
1276 return ret;
1277 }
1278
1279 return 0;
1280}
1281#else
1282static int gpmc_probe_dt(struct platform_device *pdev)
1283{
1284 return 0;
1285}
1286#endif
1287
1124static int gpmc_probe(struct platform_device *pdev) 1288static int gpmc_probe(struct platform_device *pdev)
1125{ 1289{
1126 int rc; 1290 int rc;
@@ -1174,6 +1338,14 @@ static int gpmc_probe(struct platform_device *pdev)
1174 if (IS_ERR_VALUE(gpmc_setup_irq())) 1338 if (IS_ERR_VALUE(gpmc_setup_irq()))
1175 dev_warn(gpmc_dev, "gpmc_setup_irq failed\n"); 1339 dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
1176 1340
1341 rc = gpmc_probe_dt(pdev);
1342 if (rc < 0) {
1343 clk_disable_unprepare(gpmc_l3_clk);
1344 clk_put(gpmc_l3_clk);
1345 dev_err(gpmc_dev, "failed to probe DT parameters\n");
1346 return rc;
1347 }
1348
1177 return 0; 1349 return 0;
1178} 1350}
1179 1351
@@ -1191,6 +1363,7 @@ static struct platform_driver gpmc_driver = {
1191 .driver = { 1363 .driver = {
1192 .name = DEVICE_NAME, 1364 .name = DEVICE_NAME,
1193 .owner = THIS_MODULE, 1365 .owner = THIS_MODULE,
1366 .of_match_table = of_match_ptr(gpmc_dt_ids),
1194 }, 1367 },
1195}; 1368};
1196 1369