diff mbox

[11/14] ARM: OMAP2+: Add device-tree support for NOR flash

Message ID 513664EC.2050508@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Hunter, Jon March 5, 2013, 9:34 p.m. UTC
On 03/05/2013 11:30 AM, Jon Hunter wrote:
> On 03/05/2013 10:20 AM, Mark Jackson wrote:

[snip]

>> But I can see in physmap_of.c that the device gets registered without any call to
>> devm_pinctrl_get_select_default() and hence no probe deferring takes place is the
>> pinctrl device hasn't yet been started (which it hasn't).
>>
>> Does probe deferral need adding to physmap_of.c, or should the pinctrl device really
>> be registered sooner ?
> 
> I see, so the pinctrl driver is not getting probed until later.

Can you give this version of the patch a go? I have re-worked the patch
so the NOR device will only be registered after the GPMC probe completes.

By the way, with this version you should remove "simple-bus" from your
gpmc node compatible strings. I now call of_platform_device_create() to
create the child device during the GPMC probe. I think that this is a
safer approach.

Cheers
Jon

From 278ef0ac538da720fc15896ad6c3666e0f518633 Mon Sep 17 00:00:00 2001
From: Jon Hunter <jon-hunter@ti.com>
Date: Fri, 8 Feb 2013 16:46:13 -0600
Subject: [PATCH] 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>
---
 Documentation/devicetree/bindings/mtd/gpmc-nor.txt |   98 +++++++++++++++++
 arch/arm/mach-omap2/gpmc.c                         |  113 ++++++++++++++++++++
 2 files changed, 211 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/gpmc-nor.txt

Comments

Mark Jackson March 6, 2013, 10:23 a.m. UTC | #1
On 05/03/13 21:34, Jon Hunter wrote:
> 
> On 03/05/2013 11:30 AM, Jon Hunter wrote:
>> On 03/05/2013 10:20 AM, Mark Jackson wrote:
> 
> [snip]
> 
>>> But I can see in physmap_of.c that the device gets registered without any call to
>>> devm_pinctrl_get_select_default() and hence no probe deferring takes place is the
>>> pinctrl device hasn't yet been started (which it hasn't).
>>>
>>> Does probe deferral need adding to physmap_of.c, or should the pinctrl device really
>>> be registered sooner ?
>>
>> I see, so the pinctrl driver is not getting probed until later.
> 
> Can you give this version of the patch a go? I have re-worked the patch
> so the NOR device will only be registered after the GPMC probe completes.
> 
> By the way, with this version you should remove "simple-bus" from your
> gpmc node compatible strings. I now call of_platform_device_create() to
> create the child device during the GPMC probe. I think that this is a
> safer approach.

This is better in that the probe *is* now delayed until the gpmc has been setup,
but I still get an oops.

However, this time it's in the actual cfi query code.

I've traced it down to when it tries to physically access the memory associated
with the chip select in question (in this case CS3 @ 0x1a000000).

I printed some debug info to show that the GPMC CONFIG7 register is being setup
correctly, and I show the physical to virtual memory mapping values, as performed
in of_flash_probe(), but when I try to do a test raw_readw() on the virtual address,
I get the following:-

[    1.222950] omap-gpmc 50000000.gpmc: GPMC revision 6.0
[    1.229002] gpmc_read_settings_dt: read/write wait monitoring not enabled!
[    1.237916] enabling NAND BCH ecc with 8-bit correction
[    1.243843] ONFI param page 0 valid
[    1.247531] ONFI flash detected
[    1.250856] NAND device: Manufacturer ID: 0x2c, Chip ID: 0xda (Micron MT29F2G08ABAEAWP), 256MiB, page size: 2048, OOB size: 64
[    1.263149] 8 ofpart partitions found on MTD device omap2-nand.0
[    1.269492] Creating 8 MTD partitions on "omap2-nand.0":
[    1.275150] 0x000000000000-0x000000020000 : "spl1"
[    1.282593] 0x000000020000-0x000000040000 : "spl2"
[    1.288524] 0x000000040000-0x000000060000 : "spl3"
[    1.294456] 0x000000060000-0x000000080000 : "spl4"
[    1.300270] 0x000000080000-0x0000001e0000 : "boot"
[    1.307224] 0x0000001e0000-0x000000200000 : "env"
[    1.313093] 0x000000200000-0x000004200000 : "rootfs"
[    1.373589] 0x000004200000-0x000010000000 : "data"
[    1.541884] gpmc_probe_nor_child 1
[    1.545483] GPMC_CS_CONFIG7_0 : 00000f48
[    1.549621] GPMC_CS_CONFIG7_1 : 00000f58
[    1.553812] GPMC_CS_CONFIG7_2 : 00000f00
[    1.557951] GPMC_CS_CONFIG7_3 : 00000c5a
[    1.564789] of_flash_probe ioremap : phys 1a000000 -> virt d3000000
[    1.571468] of_flash_probe test read d3000000 ...
[    1.576440] Unhandled fault: external abort on non-linefetch (0x1028) at 0xd3000000
[    1.584525] Internal error: : 1028 [#1] ARM
[    1.588946] CPU: 0    Not tainted  (3.9.0-rc1-12191-ga00d6d1-dirty #57)
[    1.595943] PC is at of_flash_probe+0x22c/0x5dc
[    1.600724] LR is at of_flash_probe+0x228/0x5dc
[    1.605506] pc : [<c023b28c>]    lr : [<c023b288>]    psr: 20000113
[    1.605506] sp : cf077ba0  ip : cf06c080  fp : c0492150
[    1.617621] r10: 04000000  r9 : cf2ac6d0  r8 : 00000000
[    1.623135] r7 : cf2ac6d0  r6 : cf2b9010  r5 : cf2b9000  r4 : c0c81f60
[    1.630027] r3 : d3000000  r2 : 00000000  r1 : cf06c4d8  r0 : 00000025
[    1.636921] Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
[    1.644635] Control: 10c5387d  Table: 80004019  DAC: 00000015
[    1.650703] Process kworker/u:0 (pid: 6, stack limit = 0xcf076238)
[    1.657225] Stack: (0xcf077ba0 to 0xcf078000)

Any ideas ?

Cheers
Mark J.
Ezequiel Garcia March 6, 2013, 11:58 a.m. UTC | #2
Jon,

On Tue, Mar 5, 2013 at 6:34 PM, Jon Hunter <jon-hunter@ti.com> wrote:
>
> By the way, with this version you should remove "simple-bus" from your
> gpmc node compatible strings. I now call of_platform_device_create() to
> create the child device during the GPMC probe. I think that this is a
> safer approach.
>

FWIW, using of_platform_device_create() works for my driver.
It seems as simple as using a compatible 'simple-bus',
with the advantage that it allows to create and probe the
child device from its parent.

I'll submit this driver by the end of this week, in case you want
to take a look at it.

Thanks a lot,
Mark Jackson March 6, 2013, 1:30 p.m. UTC | #3
On 06/03/13 10:23, Mark Jackson wrote:
> On 05/03/13 21:34, Jon Hunter wrote:
>>
>> On 03/05/2013 11:30 AM, Jon Hunter wrote:
>>> On 03/05/2013 10:20 AM, Mark Jackson wrote:
>>
>> [snip]
>>
>>>> But I can see in physmap_of.c that the device gets registered without any call to
>>>> devm_pinctrl_get_select_default() and hence no probe deferring takes place is the
>>>> pinctrl device hasn't yet been started (which it hasn't).
>>>>
>>>> Does probe deferral need adding to physmap_of.c, or should the pinctrl device really
>>>> be registered sooner ?
>>>
>>> I see, so the pinctrl driver is not getting probed until later.
>>
>> Can you give this version of the patch a go? I have re-worked the patch
>> so the NOR device will only be registered after the GPMC probe completes.
>>
>> By the way, with this version you should remove "simple-bus" from your
>> gpmc node compatible strings. I now call of_platform_device_create() to
>> create the child device during the GPMC probe. I think that this is a
>> safer approach.
> 
> This is better in that the probe *is* now delayed until the gpmc has been setup,
> but I still get an oops.
> 
> However, this time it's in the actual cfi query code.
> 
> I've traced it down to when it tries to physically access the memory associated
> with the chip select in question (in this case CS3 @ 0x1a000000).
> 
> I printed some debug info to show that the GPMC CONFIG7 register is being setup
> correctly, and I show the physical to virtual memory mapping values, as performed
> in of_flash_probe(), but when I try to do a test raw_readw() on the virtual address,
> I get the following:-
> 
> [    1.222950] omap-gpmc 50000000.gpmc: GPMC revision 6.0
> [    1.229002] gpmc_read_settings_dt: read/write wait monitoring not enabled!
> [    1.237916] enabling NAND BCH ecc with 8-bit correction
> [    1.243843] ONFI param page 0 valid
> [    1.247531] ONFI flash detected
> [    1.250856] NAND device: Manufacturer ID: 0x2c, Chip ID: 0xda (Micron MT29F2G08ABAEAWP), 256MiB, page size: 2048, OOB size: 64
> [    1.263149] 8 ofpart partitions found on MTD device omap2-nand.0
> [    1.269492] Creating 8 MTD partitions on "omap2-nand.0":
> [    1.275150] 0x000000000000-0x000000020000 : "spl1"
> [    1.282593] 0x000000020000-0x000000040000 : "spl2"
> [    1.288524] 0x000000040000-0x000000060000 : "spl3"
> [    1.294456] 0x000000060000-0x000000080000 : "spl4"
> [    1.300270] 0x000000080000-0x0000001e0000 : "boot"
> [    1.307224] 0x0000001e0000-0x000000200000 : "env"
> [    1.313093] 0x000000200000-0x000004200000 : "rootfs"
> [    1.373589] 0x000004200000-0x000010000000 : "data"
> [    1.541884] gpmc_probe_nor_child 1
> [    1.545483] GPMC_CS_CONFIG7_0 : 00000f48
> [    1.549621] GPMC_CS_CONFIG7_1 : 00000f58
> [    1.553812] GPMC_CS_CONFIG7_2 : 00000f00
> [    1.557951] GPMC_CS_CONFIG7_3 : 00000c5a

0x00000c5a is an invalid mode !!

I'm trying to use a 64MB address space but not on a 64MB boundary ... oops.
Hunter, Jon March 6, 2013, 4:44 p.m. UTC | #4
On 03/06/2013 07:30 AM, Mark Jackson wrote:
> On 06/03/13 10:23, Mark Jackson wrote:
>> On 05/03/13 21:34, Jon Hunter wrote:
>>>
>>> On 03/05/2013 11:30 AM, Jon Hunter wrote:
>>>> On 03/05/2013 10:20 AM, Mark Jackson wrote:
>>>
>>> [snip]
>>>
>>>>> But I can see in physmap_of.c that the device gets registered without any call to
>>>>> devm_pinctrl_get_select_default() and hence no probe deferring takes place is the
>>>>> pinctrl device hasn't yet been started (which it hasn't).
>>>>>
>>>>> Does probe deferral need adding to physmap_of.c, or should the pinctrl device really
>>>>> be registered sooner ?
>>>>
>>>> I see, so the pinctrl driver is not getting probed until later.
>>>
>>> Can you give this version of the patch a go? I have re-worked the patch
>>> so the NOR device will only be registered after the GPMC probe completes.
>>>
>>> By the way, with this version you should remove "simple-bus" from your
>>> gpmc node compatible strings. I now call of_platform_device_create() to
>>> create the child device during the GPMC probe. I think that this is a
>>> safer approach.
>>
>> This is better in that the probe *is* now delayed until the gpmc has been setup,
>> but I still get an oops.
>>
>> However, this time it's in the actual cfi query code.
>>
>> I've traced it down to when it tries to physically access the memory associated
>> with the chip select in question (in this case CS3 @ 0x1a000000).
>>
>> I printed some debug info to show that the GPMC CONFIG7 register is being setup
>> correctly, and I show the physical to virtual memory mapping values, as performed
>> in of_flash_probe(), but when I try to do a test raw_readw() on the virtual address,
>> I get the following:-
>>
>> [    1.222950] omap-gpmc 50000000.gpmc: GPMC revision 6.0
>> [    1.229002] gpmc_read_settings_dt: read/write wait monitoring not enabled!
>> [    1.237916] enabling NAND BCH ecc with 8-bit correction
>> [    1.243843] ONFI param page 0 valid
>> [    1.247531] ONFI flash detected
>> [    1.250856] NAND device: Manufacturer ID: 0x2c, Chip ID: 0xda (Micron MT29F2G08ABAEAWP), 256MiB, page size: 2048, OOB size: 64
>> [    1.263149] 8 ofpart partitions found on MTD device omap2-nand.0
>> [    1.269492] Creating 8 MTD partitions on "omap2-nand.0":
>> [    1.275150] 0x000000000000-0x000000020000 : "spl1"
>> [    1.282593] 0x000000020000-0x000000040000 : "spl2"
>> [    1.288524] 0x000000040000-0x000000060000 : "spl3"
>> [    1.294456] 0x000000060000-0x000000080000 : "spl4"
>> [    1.300270] 0x000000080000-0x0000001e0000 : "boot"
>> [    1.307224] 0x0000001e0000-0x000000200000 : "env"
>> [    1.313093] 0x000000200000-0x000004200000 : "rootfs"
>> [    1.373589] 0x000004200000-0x000010000000 : "data"
>> [    1.541884] gpmc_probe_nor_child 1
>> [    1.545483] GPMC_CS_CONFIG7_0 : 00000f48
>> [    1.549621] GPMC_CS_CONFIG7_1 : 00000f58
>> [    1.553812] GPMC_CS_CONFIG7_2 : 00000f00
>> [    1.557951] GPMC_CS_CONFIG7_3 : 00000c5a
> 
> 0x00000c5a is an invalid mode !!
> 
> I'm trying to use a 64MB address space but not on a 64MB boundary ... oops.

Good catch. So this is now working for you then?

Thanks
Jon
Hunter, Jon March 6, 2013, 4:46 p.m. UTC | #5
On 03/06/2013 05:58 AM, Ezequiel Garcia wrote:
> Jon,
> 
> On Tue, Mar 5, 2013 at 6:34 PM, Jon Hunter <jon-hunter@ti.com> wrote:
>>
>> By the way, with this version you should remove "simple-bus" from your
>> gpmc node compatible strings. I now call of_platform_device_create() to
>> create the child device during the GPMC probe. I think that this is a
>> safer approach.
>>
> 
> FWIW, using of_platform_device_create() works for my driver.
> It seems as simple as using a compatible 'simple-bus',
> with the advantage that it allows to create and probe the
> child device from its parent.

Yes and I think that is safer for these type of drivers.

> I'll submit this driver by the end of this week, in case you want
> to take a look at it.

Ok, but this is not for omap right?

Cheers
Jon
Mark Jackson March 6, 2013, 4:48 p.m. UTC | #6
On 06/03/13 16:44, Jon Hunter wrote:
> 
> On 03/06/2013 07:30 AM, Mark Jackson wrote:
>> On 06/03/13 10:23, Mark Jackson wrote:

<snip>

>>> [    1.541884] gpmc_probe_nor_child 1
>>> [    1.545483] GPMC_CS_CONFIG7_0 : 00000f48
>>> [    1.549621] GPMC_CS_CONFIG7_1 : 00000f58
>>> [    1.553812] GPMC_CS_CONFIG7_2 : 00000f00
>>> [    1.557951] GPMC_CS_CONFIG7_3 : 00000c5a
>>
>> 0x00000c5a is an invalid mode !!
>>
>> I'm trying to use a 64MB address space but not on a 64MB boundary ... oops.
> 
> Good catch. So this is now working for you then?

Not yet ... I got distracted by something else !?!

I'll take another look tomorrow.

Do you think it might be worth adding some sanity checking to the cs config
routines to trap similar errors ?

Cheers
Mark J.
Ezequiel Garcia March 6, 2013, 4:54 p.m. UTC | #7
On Wed, Mar 6, 2013 at 1:46 PM, Jon Hunter <jon-hunter@ti.com> wrote:
>
> On 03/06/2013 05:58 AM, Ezequiel Garcia wrote:
>> I'll submit this driver by the end of this week, in case you want
>> to take a look at it.
>
> Ok, but this is not for omap right?
>

No, this is a new driver for a memory controller that's available on
some Marvell SoC. It will be located in drivers/memory/.

I don't have any omap boards with a NOR device to test this,
but the discussion and the patches were really helpful!

Thanks,
Hunter, Jon March 6, 2013, 5 p.m. UTC | #8
On 03/06/2013 10:48 AM, Mark Jackson wrote:
> On 06/03/13 16:44, Jon Hunter wrote:
>>
>> On 03/06/2013 07:30 AM, Mark Jackson wrote:
>>> On 06/03/13 10:23, Mark Jackson wrote:
> 
> <snip>
> 
>>>> [    1.541884] gpmc_probe_nor_child 1
>>>> [    1.545483] GPMC_CS_CONFIG7_0 : 00000f48
>>>> [    1.549621] GPMC_CS_CONFIG7_1 : 00000f58
>>>> [    1.553812] GPMC_CS_CONFIG7_2 : 00000f00
>>>> [    1.557951] GPMC_CS_CONFIG7_3 : 00000c5a
>>>
>>> 0x00000c5a is an invalid mode !!
>>>
>>> I'm trying to use a 64MB address space but not on a 64MB boundary ... oops.
>>
>> Good catch. So this is now working for you then?
> 
> Not yet ... I got distracted by something else !?!
> 
> I'll take another look tomorrow.
> 
> Do you think it might be worth adding some sanity checking to the cs config
> routines to trap similar errors ?

Yes, I see what you mean. We should check to ensure that the the base is
aligned on a boundary that matches the size being configured.

I can add some checking for this case.

Cheers
Jon
Ezequiel Garcia March 7, 2013, 1:02 p.m. UTC | #9
On Wed, Mar 6, 2013 at 1:54 PM, Ezequiel Garcia <elezegarcia@gmail.com> wrote:
> On Wed, Mar 6, 2013 at 1:46 PM, Jon Hunter <jon-hunter@ti.com> wrote:
>>
>> On 03/06/2013 05:58 AM, Ezequiel Garcia wrote:
>>> I'll submit this driver by the end of this week, in case you want
>>> to take a look at it.
>>
>> Ok, but this is not for omap right?
>>
>
> No, this is a new driver for a memory controller that's available on
> some Marvell SoC. It will be located in drivers/memory/.
>

Slightly OT: if anyone wants to see the memory-controller driver
for mvebu platforms, I just posted in lakml.

It's this patchset:

"[PATCH 0/5] Device Bus support for Marvell EBU SoC"
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nor.txt b/Documentation/devicetree/bindings/mtd/gpmc-nor.txt
new file mode 100644
index 0000000..8c638fc
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/gpmc-nor.txt
@@ -0,0 +1,98 @@ 
+Device tree bindings for NOR flash connect to TI GPMC
+
+NOR flash connected to the TI GPMC (found on OMAP boards) are represented as
+child nodes of the GPMC controller with a name of "nor".
+
+All timing relevant properties as well as generic GPMC child properties are
+explained in a separate documents. Please refer to
+Documentation/devicetree/bindings/bus/ti-gpmc.txt
+
+Required properties:
+- bank-width: 		Width of NOR flash in bytes. GPMC supports 8-bit and
+			16-bit devices and so must be either 1 or 2 bytes.
+- compatible:		Documentation/devicetree/bindings/mtd/mtd-physmap.txt
+- gpmc,cs-on:		Chip-select assertion time
+- gpmc,cs-rd-off:	Chip-select de-assertion time for reads
+- gpmc,cs-wr-off:	Chip-select de-assertion time for writes
+- gpmc,oe-on:		Output-enable assertion time
+- gpmc,oe-off		Output-enable de-assertion time
+- gpmc,we-on:		Write-enable assertion time
+- gpmc,we-off:		Write-enable de-assertion time
+- gpmc,access:		Start cycle to first data capture (read access)
+- gpmc,rd-cycle:	Total read cycle time
+- gpmc,wr-cycle:	Total write cycle time
+- linux,mtd-name:	Documentation/devicetree/bindings/mtd/mtd-physmap.txt
+- reg:			Chip-select, base address (relative to chip-select)
+			and size of NOR flash. Note that base address will be
+			typically 0 as this is the start of the chip-select.
+
+Optional properties:
+- gpmc,XXX		Additional GPMC timings and settings parameters. See
+			Documentation/devicetree/bindings/bus/ti-gpmc.txt
+
+Optional properties for partiton table parsing:
+- #address-cells: should be set to 1
+- #size-cells: should be set to 1
+
+Example:
+
+gpmc: gpmc@6e000000 {
+	compatible = "ti,omap3430-gpmc", "simple-bus";
+	ti,hwmods = "gpmc";
+	reg = <0x6e000000 0x1000>;
+	interrupts = <20>;
+	gpmc,num-cs = <8>;
+	gpmc,num-waitpins = <4>;
+	#address-cells = <2>;
+	#size-cells = <1>;
+
+	ranges = <0 0 0x10000000 0x08000000>;
+
+	nor@0,0 {
+		compatible = "cfi-flash";
+		linux,mtd-name= "intel,pf48f6000m0y1be";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0 0 0x08000000>;
+		bank-width = <2>;
+
+		gpmc,mux-add-data;
+		gpmc,cs-on = <0>;
+		gpmc,cs-rd-off = <186>;
+		gpmc,cs-wr-off = <186>;
+		gpmc,adv-on = <12>;
+		gpmc,adv-rd-off = <48>;
+		gpmc,adv-wr-off = <48>;
+		gpmc,oe-on = <54>;
+		gpmc,oe-off = <168>;
+		gpmc,we-on = <54>;
+		gpmc,we-off = <168>;
+		gpmc,rd-cycle = <186>;
+		gpmc,wr-cycle = <186>;
+		gpmc,access = <114>;
+		gpmc,page-burst-access = <6>;
+		gpmc,bus-turnaround = <12>;
+		gpmc,cycle2cycle-delay = <18>;
+		gpmc,wr-data-mux-bus = <90>;
+		gpmc,wr-access = <186>;
+		gpmc,cycle2cycle-samecsen;
+		gpmc,cycle2cycle-diffcsen;
+
+		partition@0 {
+			label = "bootloader-nor";
+			reg = <0 0x40000>;
+		};
+		partition@0x40000 {
+			label = "params-nor";
+			reg = <0x40000 0x40000>;
+		};
+		partition@0x80000 {
+			label = "kernel-nor";
+			reg = <0x80000 0x200000>;
+		};
+		partition@0x280000 {
+			label = "filesystem-nor";
+			reg = <0x240000 0x7d80000>;
+		};
+	};
+};
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index e822d2b..c217a38 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -26,6 +26,7 @@ 
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_mtd.h>
 #include <linux/of_device.h>
 #include <linux/mtd/nand.h>
@@ -513,6 +514,37 @@  static int gpmc_cs_delete_mem(int cs)
 	return r;
 }
 
+/**
+ * gpmc_cs_remap - remaps a chip-select physical base address
+ * @cs:		chip-select to remap
+ * @base:	physical base address to re-map chip-select to
+ *
+ * Re-maps a chip-select to a new physical base address specified by
+ * "base". Returns 0 on success and appropriate negative error code
+ * on failure.
+ */
+static int gpmc_cs_remap(int cs, u32 base)
+{
+	int ret;
+	u32 old_base, size;
+
+	if (cs > GPMC_CS_NUM)
+		return -ENODEV;
+	gpmc_cs_get_memconf(cs, &old_base, &size);
+	if (base == old_base)
+		return 0;
+	gpmc_cs_disable_mem(cs);
+	ret = gpmc_cs_delete_mem(cs);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+	ret = gpmc_cs_insert_mem(cs, base, size);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+	gpmc_cs_enable_mem(cs, base, size);
+
+	return 0;
+}
+
 int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 {
 	struct resource *res = &gpmc_cs_mem[cs];
@@ -1391,6 +1423,78 @@  static int gpmc_probe_onenand_child(struct platform_device *pdev,
 }
 #endif
 
+/**
+ * gpmc_probe_nor_child - configures the gpmc for a nor device
+ * @pdev:	pointer to gpmc platform device
+ * @child:	pointer to device-tree node for nor device
+ *
+ * Allocates and configures a GPMC chip-select for a NOR flash device.
+ * Returns 0 on success and appropriate negative error code on failure.
+ */
+static int gpmc_probe_nor_child(struct platform_device *pdev,
+				struct device_node *child)
+{
+	struct gpmc_settings gpmc_s;
+	struct gpmc_timings gpmc_t;
+	struct resource res;
+	unsigned long base;
+	int ret, cs;
+
+	if (of_property_read_u32(child, "reg", &cs) < 0) {
+		dev_err(&pdev->dev, "%s has no 'reg' property\n",
+			child->full_name);
+		return -ENODEV;
+	}
+
+	if (of_address_to_resource(child, 0, &res)) {
+		dev_err(&pdev->dev, "%s has malformed 'reg' property\n",
+			child->full_name);
+		return -ENODEV;
+	}
+
+	ret = gpmc_cs_request(cs, res.end - res.start, &base);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs);
+		return ret;
+	}
+
+	/*
+	 * FIXME: gpmc_cs_request() will map the CS to an arbitary
+	 * location in the gpmc address space. When booting with
+	 * device-tree we want the NOR flash to be mapped to the
+	 * location specified in the device-tree blob. So remap the
+	 * CS to this location. Once DT migration is complete should
+	 * just make gpmc_cs_request() map a specific address.
+	 */
+	ret = gpmc_cs_remap(cs, res.start);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(&pdev->dev, "cannot remap GPMC CS %d to 0x%x\n",
+			cs, res.start);
+		goto err1;
+	}
+
+	gpmc_read_settings_dt(child, &gpmc_s);
+
+	ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width);
+	if (IS_ERR_VALUE(ret))
+		goto err1;
+
+	ret = gpmc_cs_program_settings(cs, &gpmc_s);
+	if (IS_ERR_VALUE(ret))
+		goto err1;
+
+	gpmc_read_timings_dt(child, &gpmc_t);
+	gpmc_cs_set_timings(cs, &gpmc_t);
+
+	of_platform_device_create(child, NULL, &pdev->dev);
+
+	return 0;
+err1:
+	gpmc_cs_free(cs);
+
+	return ret;
+}
+
 static int gpmc_probe_dt(struct platform_device *pdev)
 {
 	int ret;
@@ -1424,6 +1528,15 @@  static int gpmc_probe_dt(struct platform_device *pdev)
 			return ret;
 		}
 	}
+
+	for_each_node_by_name(child, "nor") {
+		ret = gpmc_probe_nor_child(pdev, child);
+		if (ret < 0) {
+			of_node_put(child);
+			return ret;
+		}
+	}
+
 	return 0;
 }
 #else