diff mbox

[2/2] ARM: OMAP2: Fix GPMC memory initialisation

Message ID 51103A25.9010401@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Hunter, Jon Feb. 4, 2013, 10:45 p.m. UTC
On 02/04/2013 04:12 PM, Jon Hunter wrote:
> 
> On 02/01/2013 03:51 PM, Tony Lindgren wrote:
> 
>> How about let's fix this properly to start with so we don't add
>> more blockers moving this code to drivers/bus?
>>
>> Looks like gpmc_mem_init() gets called from gpmc_probe() so
>> we can pass that information in pdev.
> 
> I have re-worked this a bit to use platform data. I have also update
> the logic for testing internal/external boot on omap2430 which is
> different from omap2420 (according to the TRM). However, I have only
> boot tested on omap2420. 
> 
> Do you know why this was changed in the first place? See below ...
> 
> http://permalink.gmane.org/gmane.linux.kernel.commits.head/95931
> 
> Heres what I have now ...

Updated patch (I was missing a kfree()). By the way, this is based
upon the apollon removal patch. I understand probably needs to be
rebased on your latest gpmc series too.

Jon

From 643656e3754ed949d9a8af31b22ed3727e0962f6 Mon Sep 17 00:00:00 2001
From: Jon Hunter <jon-hunter@ti.com>
Date: Thu, 31 Jan 2013 15:56:08 -0600
Subject: [PATCH] ARM: OMAP2: Fix GPMC memory initialisation

OMAP2+ devices have an internal ROM that by default is typically mapped
to the first 1MB of the GPMC address space (0x0).

For OMAP24xx devices, GPMC chip-select 0 (CS0) may be mapped to address
0x0 instead of the internal ROM if configured for an external boot mode.
If configured for an internal boot mode then the internal ROM is mapped
to 0x0.

Currently, the function gpmc_mem_init() function reserves the first 1MB
of GPMC address space for the internal OMAP ROM. This prevents any
device (ethernet chip, flash memories, etc) from using this address
range. This causes the GPMC probe to fail on the OMAP2420 H4 when NOR
flash is mapped to address 0x0. Fix this by checking the SYS_BOOT pin
setting for OMAP24xx devices, to see the device is configured for
an internal or external boot and pass the amount of ROM mapped to
address 0x0 to the GPMC driver via platform data.

Please note that for OMAP3-5 devices, when booting from NOR or NAND
memories connected to CS0, these memories are always mapped to address
0x08000000 and so reserving this memory range does not present any
problems for these devices.

Signed-off-by: Jon Hunter <jon-hunter@ti.com>
---
 arch/arm/mach-omap2/gpmc.c |   60 ++++++++++++++++++++++++++++++++++++--------
 arch/arm/mach-omap2/gpmc.h |    5 ++++
 2 files changed, 54 insertions(+), 11 deletions(-)

Comments

Tony Lindgren Feb. 5, 2013, 11:34 p.m. UTC | #1
* Jon Hunter <jon-hunter@ti.com> [130204 14:49]:
> 
> On 02/04/2013 04:12 PM, Jon Hunter wrote:
> > 
> > On 02/01/2013 03:51 PM, Tony Lindgren wrote:
> > 
> >> How about let's fix this properly to start with so we don't add
> >> more blockers moving this code to drivers/bus?
> >>
> >> Looks like gpmc_mem_init() gets called from gpmc_probe() so
> >> we can pass that information in pdev.
> > 
> > I have re-worked this a bit to use platform data. I have also update
> > the logic for testing internal/external boot on omap2430 which is
> > different from omap2420 (according to the TRM). However, I have only
> > boot tested on omap2420. 
> > 
> > Do you know why this was changed in the first place? See below ...
> > 
> > http://permalink.gmane.org/gmane.linux.kernel.commits.head/95931
> > 
> > Heres what I have now ...
> 
> Updated patch (I was missing a kfree()). By the way, this is based
> upon the apollon removal patch. I understand probably needs to be
> rebased on your latest gpmc series too.

Yeah makes sense to me thanks. I'll figure out where to apply this
so we don't get too many dependencies.

Regards,

Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Hunter, Jon Feb. 6, 2013, 12:22 a.m. UTC | #2
On 02/05/2013 05:34 PM, Tony Lindgren wrote:
> * Jon Hunter <jon-hunter@ti.com> [130204 14:49]:
>>
>> On 02/04/2013 04:12 PM, Jon Hunter wrote:
>>>
>>> On 02/01/2013 03:51 PM, Tony Lindgren wrote:
>>>
>>>> How about let's fix this properly to start with so we don't add
>>>> more blockers moving this code to drivers/bus?
>>>>
>>>> Looks like gpmc_mem_init() gets called from gpmc_probe() so
>>>> we can pass that information in pdev.
>>>
>>> I have re-worked this a bit to use platform data. I have also update
>>> the logic for testing internal/external boot on omap2430 which is
>>> different from omap2420 (according to the TRM). However, I have only
>>> boot tested on omap2420. 
>>>
>>> Do you know why this was changed in the first place? See below ...
>>>
>>> http://permalink.gmane.org/gmane.linux.kernel.commits.head/95931
>>>
>>> Heres what I have now ...
>>
>> Updated patch (I was missing a kfree()). By the way, this is based
>> upon the apollon removal patch. I understand probably needs to be
>> rebased on your latest gpmc series too.
> 
> Yeah makes sense to me thanks. I'll figure out where to apply this
> so we don't get too many dependencies.

Actually, let me look into this a bit more. It appears that for all
omap2+ devices NOR should be mapped to CS0 at 0x08000000. So I am
wondering if the boot-loader is re-mapping the CS0 space. If it is then
may be we can avoid having such hacks in the kernel by fixing the
bootloader. To date only the apollon board has really had this problem
and I need to check what I have on my H4 (which has been hacked by me ;-)

Cheers
Jon
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tony Lindgren Feb. 6, 2013, 5:28 p.m. UTC | #3
* Jon Hunter <jon-hunter@ti.com> [130205 16:26]:
> 
> Actually, let me look into this a bit more. It appears that for all
> omap2+ devices NOR should be mapped to CS0 at 0x08000000. So I am
> wondering if the boot-loader is re-mapping the CS0 space. If it is then
> may be we can avoid having such hacks in the kernel by fixing the
> bootloader. To date only the apollon board has really had this problem
> and I need to check what I have on my H4 (which has been hacked by me ;-)

OK. Yeah sorry I don't remember the history of why the different
mappings were needed. It could be it was just needed to keep some
devices working that were only initialized in the bootloader like
you're suspecting.

Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index a124849..aa58258 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -20,6 +20,7 @@ 
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/ioport.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/module.h>
@@ -32,6 +33,7 @@ 
 
 #include "soc.h"
 #include "common.h"
+#include "control.h"
 #include "omap_device.h"
 #include "gpmc.h"
 
@@ -87,7 +89,6 @@ 
 
 #define GPMC_MEM_START		0x00000000
 #define GPMC_MEM_END		0x3FFFFFFF
-#define BOOT_ROM_SPACE		0x100000	/* 1MB */
 
 #define GPMC_CHUNK_SHIFT	24		/* 16 MB */
 #define GPMC_SECTION_SHIFT	28		/* 128 MB */
@@ -775,16 +776,11 @@  static void gpmc_mem_exit(void)
 
 }
 
-static int gpmc_mem_init(void)
+static int gpmc_mem_init(u32 offset)
 {
 	int cs, rc;
-	unsigned long boot_rom_space = 0;
 
-	/* never allocate the first page, to facilitate bug detection;
-	 * even if we didn't boot from ROM.
-	 */
-	boot_rom_space = BOOT_ROM_SPACE;
-	gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space;
+	gpmc_mem_root.start = GPMC_MEM_START + offset;
 	gpmc_mem_root.end = GPMC_MEM_END;
 
 	/* Reserve all regions that has been set up by bootloader */
@@ -1124,6 +1120,12 @@  static int gpmc_probe(struct platform_device *pdev)
 	int rc;
 	u32 l;
 	struct resource *res;
+	struct gpmc_platform_data *pdata = pdev->dev.platform_data;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
+		return -ENODEV;
+	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res == NULL)
@@ -1161,7 +1163,7 @@  static int gpmc_probe(struct platform_device *pdev)
 	dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l),
 		 GPMC_REVISION_MINOR(l));
 
-	rc = gpmc_mem_init();
+	rc = gpmc_mem_init(pdata->gpmc_rom_space);
 	if (IS_ERR_VALUE(rc)) {
 		clk_disable_unprepare(gpmc_l3_clk);
 		clk_put(gpmc_l3_clk);
@@ -1213,18 +1215,54 @@  static int __init omap_gpmc_init(void)
 {
 	struct omap_hwmod *oh;
 	struct platform_device *pdev;
+	struct gpmc_platform_data *pdata;
 	char *oh_name = "gpmc";
 
+	pdata = kzalloc(sizeof(struct gpmc_platform_data), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("%s: No memory for gpmc\n", __func__);
+		return -ENOMEM;
+	}
+
+	/*
+	 * The first 1MB of GPMC address space is mapped to the internal
+	 * ROM. OMAP2 devices are an exception to this where the first
+	 * 1MB may be mapped to the GPMC. OMAP2 devices that boot from
+	 * external memory devices, will map CS0 to the start of the
+	 * GPMC address space (0x0). We can test this by checking the
+	 * SYS_BOOT pins.
+	 *
+	 * OMAP2420 SYS_BOOT[3] = 1b, then GPMC CS0 is mapped to 0x0.
+	 * OMAP2430 SYS_BOOT[2:1] = 00b, then GPMC CS0 is mapped to 0x0.
+	 */
+	pdata->gpmc_rom_space = SZ_1M;
+
+	if (cpu_is_omap242x()) {
+		if (!(omap_ctrl_readl(OMAP24XX_CONTROL_STATUS) &
+		      OMAP2_SYSBOOT_3_MASK))
+			pdata->gpmc_rom_space = 0;
+	} else if (cpu_is_omap243x()) {
+		if (!(omap_ctrl_readl(OMAP24XX_CONTROL_STATUS) &
+		      (OMAP2_SYSBOOT_2_MASK | OMAP2_SYSBOOT_1_MASK)))
+			pdata->gpmc_rom_space = 0;
+	}
+
 	oh = omap_hwmod_lookup(oh_name);
 	if (!oh) {
 		pr_err("Could not look up %s\n", oh_name);
 		return -ENODEV;
 	}
 
-	pdev = omap_device_build(DEVICE_NAME, -1, oh, NULL, 0, NULL, 0, 0);
+	pdev = omap_device_build(DEVICE_NAME, -1, oh, pdata, sizeof(*pdata),
+				 NULL, 0, 0);
 	WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
 
-	return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
+	if (IS_ERR(pdev)) {
+		kfree(pdata);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
 }
 postcore_initcall(omap_gpmc_init);
 
diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h
index fe0a844..b33ef26 100644
--- a/arch/arm/mach-omap2/gpmc.h
+++ b/arch/arm/mach-omap2/gpmc.h
@@ -189,6 +189,11 @@  struct gpmc_device_timings {
 	bool we_xdelay;
 };
 
+/* GPMC platform data */
+struct gpmc_platform_data {
+	u32 gpmc_rom_space;
+};
+
 extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
 				struct gpmc_device_timings *dev_t);