aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Hunter <jon-hunter@ti.com>2013-02-08 17:46:13 -0500
committerJon Hunter <jon-hunter@ti.com>2013-04-03 21:13:38 -0400
commitcdd6928c589a2dcf084bd62fa5a2b7db1516187b (patch)
tree3ed13fd349ced1dd80c587c719cb7972236b8b86
parentd36b4cd46d23dd3c283c2e11de540e4cb875255d (diff)
ARM: OMAP2+: Add device-tree support for NOR flash
NOR flash is not currently supported when booting with device-tree on OMAP2+ devices. Add support to detect and configure NOR devices when booting with device-tree. Add documentation for the TI GPMC NOR binding. Signed-off-by: Jon Hunter <jon-hunter@ti.com> Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
-rw-r--r--Documentation/devicetree/bindings/mtd/gpmc-nor.txt98
-rw-r--r--arch/arm/mach-omap2/gpmc.c115
2 files changed, 213 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nor.txt b/Documentation/devicetree/bindings/mtd/gpmc-nor.txt
new file mode 100644
index 000000000000..420b3ab18890
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/gpmc-nor.txt
@@ -0,0 +1,98 @@
1Device tree bindings for NOR flash connect to TI GPMC
2
3NOR flash connected to the TI GPMC (found on OMAP boards) are represented as
4child nodes of the GPMC controller with a name of "nor".
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
10Required properties:
11- bank-width: Width of NOR flash in bytes. GPMC supports 8-bit and
12 16-bit devices and so must be either 1 or 2 bytes.
13- compatible: Documentation/devicetree/bindings/mtd/mtd-physmap.txt
14- gpmc,cs-on-ns: Chip-select assertion time
15- gpmc,cs-rd-off-ns: Chip-select de-assertion time for reads
16- gpmc,cs-wr-off-ns: Chip-select de-assertion time for writes
17- gpmc,oe-on-ns: Output-enable assertion time
18- gpmc,oe-off-ns: Output-enable de-assertion time
19- gpmc,we-on-ns Write-enable assertion time
20- gpmc,we-off-ns: Write-enable de-assertion time
21- gpmc,access-ns: Start cycle to first data capture (read access)
22- gpmc,rd-cycle-ns: Total read cycle time
23- gpmc,wr-cycle-ns: Total write cycle time
24- linux,mtd-name: Documentation/devicetree/bindings/mtd/mtd-physmap.txt
25- reg: Chip-select, base address (relative to chip-select)
26 and size of NOR flash. Note that base address will be
27 typically 0 as this is the start of the chip-select.
28
29Optional properties:
30- gpmc,XXX Additional GPMC timings and settings parameters. See
31 Documentation/devicetree/bindings/bus/ti-gpmc.txt
32
33Optional properties for partiton table parsing:
34- #address-cells: should be set to 1
35- #size-cells: should be set to 1
36
37Example:
38
39gpmc: gpmc@6e000000 {
40 compatible = "ti,omap3430-gpmc", "simple-bus";
41 ti,hwmods = "gpmc";
42 reg = <0x6e000000 0x1000>;
43 interrupts = <20>;
44 gpmc,num-cs = <8>;
45 gpmc,num-waitpins = <4>;
46 #address-cells = <2>;
47 #size-cells = <1>;
48
49 ranges = <0 0 0x10000000 0x08000000>;
50
51 nor@0,0 {
52 compatible = "cfi-flash";
53 linux,mtd-name= "intel,pf48f6000m0y1be";
54 #address-cells = <1>;
55 #size-cells = <1>;
56 reg = <0 0 0x08000000>;
57 bank-width = <2>;
58
59 gpmc,mux-add-data;
60 gpmc,cs-on-ns = <0>;
61 gpmc,cs-rd-off-ns = <186>;
62 gpmc,cs-wr-off-ns = <186>;
63 gpmc,adv-on-ns = <12>;
64 gpmc,adv-rd-off-ns = <48>;
65 gpmc,adv-wr-off-ns = <48>;
66 gpmc,oe-on-ns = <54>;
67 gpmc,oe-off-ns = <168>;
68 gpmc,we-on-ns = <54>;
69 gpmc,we-off-ns = <168>;
70 gpmc,rd-cycle-ns = <186>;
71 gpmc,wr-cycle-ns = <186>;
72 gpmc,access-ns = <114>;
73 gpmc,page-burst-access-ns = <6>;
74 gpmc,bus-turnaround-ns = <12>;
75 gpmc,cycle2cycle-delay-ns = <18>;
76 gpmc,wr-data-mux-bus-ns = <90>;
77 gpmc,wr-access-ns = <186>;
78 gpmc,cycle2cycle-samecsen;
79 gpmc,cycle2cycle-diffcsen;
80
81 partition@0 {
82 label = "bootloader-nor";
83 reg = <0 0x40000>;
84 };
85 partition@0x40000 {
86 label = "params-nor";
87 reg = <0x40000 0x40000>;
88 };
89 partition@0x80000 {
90 label = "kernel-nor";
91 reg = <0x80000 0x200000>;
92 };
93 partition@0x280000 {
94 label = "filesystem-nor";
95 reg = <0x240000 0x7d80000>;
96 };
97 };
98};
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index ab658eb1419b..c7bf6ddf04ed 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -26,6 +26,7 @@
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> 28#include <linux/of.h>
29#include <linux/of_address.h>
29#include <linux/of_mtd.h> 30#include <linux/of_mtd.h>
30#include <linux/of_device.h> 31#include <linux/of_device.h>
31#include <linux/mtd/nand.h> 32#include <linux/mtd/nand.h>
@@ -499,6 +500,37 @@ static int gpmc_cs_delete_mem(int cs)
499 return r; 500 return r;
500} 501}
501 502
503/**
504 * gpmc_cs_remap - remaps a chip-select physical base address
505 * @cs: chip-select to remap
506 * @base: physical base address to re-map chip-select to
507 *
508 * Re-maps a chip-select to a new physical base address specified by
509 * "base". Returns 0 on success and appropriate negative error code
510 * on failure.
511 */
512static int gpmc_cs_remap(int cs, u32 base)
513{
514 int ret;
515 u32 old_base, size;
516
517 if (cs > GPMC_CS_NUM)
518 return -ENODEV;
519 gpmc_cs_get_memconf(cs, &old_base, &size);
520 if (base == old_base)
521 return 0;
522 gpmc_cs_disable_mem(cs);
523 ret = gpmc_cs_delete_mem(cs);
524 if (ret < 0)
525 return ret;
526 ret = gpmc_cs_insert_mem(cs, base, size);
527 if (ret < 0)
528 return ret;
529 gpmc_cs_enable_mem(cs, base, size);
530
531 return 0;
532}
533
502int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) 534int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
503{ 535{
504 struct resource *res = &gpmc_cs_mem[cs]; 536 struct resource *res = &gpmc_cs_mem[cs];
@@ -1386,6 +1418,80 @@ static int gpmc_probe_onenand_child(struct platform_device *pdev,
1386} 1418}
1387#endif 1419#endif
1388 1420
1421/**
1422 * gpmc_probe_nor_child - configures the gpmc for a nor device
1423 * @pdev: pointer to gpmc platform device
1424 * @child: pointer to device-tree node for nor device
1425 *
1426 * Allocates and configures a GPMC chip-select for a NOR flash device.
1427 * Returns 0 on success and appropriate negative error code on failure.
1428 */
1429static int gpmc_probe_nor_child(struct platform_device *pdev,
1430 struct device_node *child)
1431{
1432 struct gpmc_settings gpmc_s;
1433 struct gpmc_timings gpmc_t;
1434 struct resource res;
1435 unsigned long base;
1436 int ret, cs;
1437
1438 if (of_property_read_u32(child, "reg", &cs) < 0) {
1439 dev_err(&pdev->dev, "%s has no 'reg' property\n",
1440 child->full_name);
1441 return -ENODEV;
1442 }
1443
1444 if (of_address_to_resource(child, 0, &res) < 0) {
1445 dev_err(&pdev->dev, "%s has malformed 'reg' property\n",
1446 child->full_name);
1447 return -ENODEV;
1448 }
1449
1450 ret = gpmc_cs_request(cs, resource_size(&res), &base);
1451 if (ret < 0) {
1452 dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs);
1453 return ret;
1454 }
1455
1456 /*
1457 * FIXME: gpmc_cs_request() will map the CS to an arbitary
1458 * location in the gpmc address space. When booting with
1459 * device-tree we want the NOR flash to be mapped to the
1460 * location specified in the device-tree blob. So remap the
1461 * CS to this location. Once DT migration is complete should
1462 * just make gpmc_cs_request() map a specific address.
1463 */
1464 ret = gpmc_cs_remap(cs, res.start);
1465 if (ret < 0) {
1466 dev_err(&pdev->dev, "cannot remap GPMC CS %d to 0x%x\n",
1467 cs, res.start);
1468 goto err;
1469 }
1470
1471 gpmc_read_settings_dt(child, &gpmc_s);
1472
1473 ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width);
1474 if (ret < 0)
1475 goto err;
1476
1477 ret = gpmc_cs_program_settings(cs, &gpmc_s);
1478 if (ret < 0)
1479 goto err;
1480
1481 gpmc_read_timings_dt(child, &gpmc_t);
1482 gpmc_cs_set_timings(cs, &gpmc_t);
1483
1484 if (of_platform_device_create(child, NULL, &pdev->dev))
1485 return 0;
1486
1487 dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name);
1488
1489err:
1490 gpmc_cs_free(cs);
1491
1492 return ret;
1493}
1494
1389static int gpmc_probe_dt(struct platform_device *pdev) 1495static int gpmc_probe_dt(struct platform_device *pdev)
1390{ 1496{
1391 int ret; 1497 int ret;
@@ -1418,6 +1524,15 @@ static int gpmc_probe_dt(struct platform_device *pdev)
1418 return ret; 1524 return ret;
1419 } 1525 }
1420 } 1526 }
1527
1528 for_each_node_by_name(child, "nor") {
1529 ret = gpmc_probe_nor_child(pdev, child);
1530 if (ret < 0) {
1531 of_node_put(child);
1532 return ret;
1533 }
1534 }
1535
1421 return 0; 1536 return 0;
1422} 1537}
1423#else 1538#else