[ARM] 3226/1: IXP4xx runtime expansion bus window size configuration

Patch from Deepak Saxena

The expansion bus on the IXP46x NPU can be configured for either 32MiB or
16MiB windows and changing the configuration causes the base address for
each chip select for each region to change. Because of this, we cannot
hardcode the physical base as we currently do. This patch checks the
expansion bus configuration registers at runtime to determine the
appropriate window size. Note that this requires that the bootloader
already configured the device sizes appropriately, but I feel that is
valid assumption to make as the bootloader must configure and access
the flash window, the output display (LCD, LEDs, etc) window, and
other expansion bus devices.

Signed-off-by: Deepak Saxena <dsaxena@plexity.net>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 9f33cb2..6b39369 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -332,11 +332,27 @@
 	&ixp46x_i2c_controller
 };
 
+unsigned long ixp4xx_exp_bus_size;
+
 void __init ixp4xx_sys_init(void)
 {
+	ixp4xx_exp_bus_size = SZ_16M;
+
 	if (cpu_is_ixp46x()) {
+		int region;
+
 		platform_add_devices(ixp46x_devices,
 				ARRAY_SIZE(ixp46x_devices));
+
+		for (region = 0; region < 7; region++) {
+			if((*(IXP4XX_EXP_REG(0x4 * region)) & 0x200)) {
+				ixp4xx_exp_bus_size = SZ_32M;
+				break;
+			}
+		}
 	}
+
+	printk("IXP4xx: Using %uMiB expansion bus window size\n",
+			ixp4xx_exp_bus_size >> 20);
 }
 
diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c
index 050c927..679594a 100644
--- a/arch/arm/mach-ixp4xx/coyote-setup.c
+++ b/arch/arm/mach-ixp4xx/coyote-setup.c
@@ -14,6 +14,7 @@
 #include <linux/serial.h>
 #include <linux/tty.h>
 #include <linux/serial_8250.h>
+#include <linux/slab.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -30,8 +31,6 @@
 };
 
 static struct resource coyote_flash_resource = {
-	.start		= COYOTE_FLASH_BASE,
-	.end		= COYOTE_FLASH_BASE + COYOTE_FLASH_SIZE - 1,
 	.flags		= IORESOURCE_MEM,
 };
 
@@ -81,6 +80,11 @@
 
 static void __init coyote_init(void)
 {
+	ixp4xx_sys_init();
+
+	coyote_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	coyote_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
+
 	*IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
 	*IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
 
@@ -91,8 +95,6 @@
 		coyote_uart_data[0].irq = IRQ_IXP4XX_UART1;
 	}
 
-
-	ixp4xx_sys_init();
 	platform_add_devices(coyote_devices, ARRAY_SIZE(coyote_devices));
 }
 
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
index 29a6d02..0386704 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
@@ -27,6 +27,7 @@
 #include <linux/serial.h>
 #include <linux/tty.h>
 #include <linux/serial_8250.h>
+#include <linux/slab.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -106,11 +107,9 @@
 	.width		= 2,
 };
 
-static struct resource gtwx5715_flash_resource = {
-	.start		= GTWX5715_FLASH_BASE,
-	.end		= GTWX5715_FLASH_BASE + GTWX5715_FLASH_SIZE - 1,
+static struct gtw5715_flash_resource = {
 	.flags		= IORESOURCE_MEM,
-};
+}
 
 static struct platform_device gtwx5715_flash = {
 	.name		= "IXP4XX-Flash",
@@ -129,6 +128,14 @@
 
 static void __init gtwx5715_init(void)
 {
+	ixp4xx_sys_init();
+
+	if (!flash_resource)
+		printk(KERN_ERR "Could not allocate flash resource\n");
+
+	gtwx5715_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	gtwx5715_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_8M - 1;
+
 	platform_add_devices(gtwx5715_devices, ARRAY_SIZE(gtwx5715_devices));
 }
 
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index 3a22d84e..c2e105c 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -14,6 +14,7 @@
 #include <linux/serial.h>
 #include <linux/tty.h>
 #include <linux/serial_8250.h>
+#include <linux/slab.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -30,8 +31,6 @@
 };
 
 static struct resource ixdp425_flash_resource = {
-	.start		= IXDP425_FLASH_BASE,
-	.end		= IXDP425_FLASH_BASE + IXDP425_FLASH_SIZE - 1,
 	.flags		= IORESOURCE_MEM,
 };
 
@@ -108,17 +107,13 @@
 	&ixdp425_uart
 };
 
-
 static void __init ixdp425_init(void)
 {
 	ixp4xx_sys_init();
 
-	/*
-	 * IXP465 has 32MB window
-	 */
-	if (machine_is_ixdp465()) {
-		ixdp425_flash_resource.end += IXDP425_FLASH_SIZE;
-	}
+	ixdp425_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	ixdp425_flash_resource.end =
+		IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
 
 	platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices));
 }
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index bde9648..49998a8 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -26,8 +26,6 @@
 };
 
 static struct resource nas100d_flash_resource = {
-	.start			= NAS100D_FLASH_BASE,
-	.end			= NAS100D_FLASH_BASE + NAS100D_FLASH_SIZE,
 	.flags			= IORESOURCE_MEM,
 };
 
@@ -115,6 +113,10 @@
 {
 	ixp4xx_sys_init();
 
+	nas100d_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	nas100d_flash_resource.end =
+		IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+
 	pm_power_off = nas100d_power_off;
 
 	platform_add_devices(nas100d_devices, ARRAY_SIZE(nas100d_devices));
diff --git a/include/asm-arm/arch-ixp4xx/coyote.h b/include/asm-arm/arch-ixp4xx/coyote.h
index dd0c2d2..7ac9ba2c 100644
--- a/include/asm-arm/arch-ixp4xx/coyote.h
+++ b/include/asm-arm/arch-ixp4xx/coyote.h
@@ -16,9 +16,6 @@
 #error "Do not include this directly, instead #include <asm/hardware.h>"
 #endif
 
-#define	COYOTE_FLASH_BASE	IXP4XX_EXP_BUS_CS0_BASE_PHYS
-#define	COYOTE_FLASH_SIZE	IXP4XX_EXP_BUS_CSX_REGION_SIZE * 2
-
 /* PCI controller GPIO to IRQ pin mappings */
 #define	COYOTE_PCI_SLOT0_PIN	6
 #define	COYOTE_PCI_SLOT1_PIN	11
@@ -26,7 +23,7 @@
 #define	COYOTE_PCI_SLOT0_DEVID	14
 #define	COYOTE_PCI_SLOT1_DEVID	15
 
-#define	COYOTE_IDE_BASE_PHYS	IXP4XX_EXP_BUS_CS3_BASE_PHYS
+#define	COYOTE_IDE_BASE_PHYS	IXP4XX_EXP_BUS_BASE(3)
 #define	COYOTE_IDE_BASE_VIRT	0xFFFE1000
 #define	COYOTE_IDE_REGION_SIZE	0x1000
 
diff --git a/include/asm-arm/arch-ixp4xx/gtwx5715.h b/include/asm-arm/arch-ixp4xx/gtwx5715.h
index fc460af7..c3069d6 100644
--- a/include/asm-arm/arch-ixp4xx/gtwx5715.h
+++ b/include/asm-arm/arch-ixp4xx/gtwx5715.h
@@ -57,10 +57,6 @@
 #define GTWX5715_GPIO13_IRQ		IRQ_IXP4XX_SW_INT1
 #define GTWX5715_GPIO14_IRQ		IRQ_IXP4XX_SW_INT2
 
-
-#define	GTWX5715_FLASH_BASE	IXP4XX_EXP_BUS_CS0_BASE_PHYS
-#define	GTWX5715_FLASH_SIZE	(0x00800000)
-
 /* PCI controller GPIO to IRQ pin mappings
 
 			INTA	INTB
diff --git a/include/asm-arm/arch-ixp4xx/ixdp425.h b/include/asm-arm/arch-ixp4xx/ixdp425.h
index 7d21bf9..3d3820d 100644
--- a/include/asm-arm/arch-ixp4xx/ixdp425.h
+++ b/include/asm-arm/arch-ixp4xx/ixdp425.h
@@ -16,9 +16,6 @@
 #error "Do not include this directly, instead #include <asm/hardware.h>"
 #endif
 
-#define	IXDP425_FLASH_BASE	IXP4XX_EXP_BUS_CS0_BASE_PHYS
-#define	IXDP425_FLASH_SIZE	IXP4XX_EXP_BUS_CSX_REGION_SIZE
-
 #define	IXDP425_SDA_PIN		7
 #define	IXDP425_SCL_PIN		6
 
diff --git a/include/asm-arm/arch-ixp4xx/nas100d.h b/include/asm-arm/arch-ixp4xx/nas100d.h
index ce7a86a..51ac018 100644
--- a/include/asm-arm/arch-ixp4xx/nas100d.h
+++ b/include/asm-arm/arch-ixp4xx/nas100d.h
@@ -19,9 +19,6 @@
 #error "Do not include this directly, instead #include <asm/hardware.h>"
 #endif
 
-#define NAS100D_FLASH_BASE	IXP4XX_EXP_BUS_CS0_BASE_PHYS
-#define NAS100D_FLASH_SIZE	IXP4XX_EXP_BUS_CSX_REGION_SIZE
-
 #define NAS100D_SDA_PIN		6
 #define NAS100D_SCL_PIN		5
 
diff --git a/include/asm-arm/arch-ixp4xx/nslu2.h b/include/asm-arm/arch-ixp4xx/nslu2.h
index b8b347a..4281838 100644
--- a/include/asm-arm/arch-ixp4xx/nslu2.h
+++ b/include/asm-arm/arch-ixp4xx/nslu2.h
@@ -18,9 +18,6 @@
 #error "Do not include this directly, instead #include <asm/hardware.h>"
 #endif
 
-#define NSLU2_FLASH_BASE	IXP4XX_EXP_BUS_CS0_BASE_PHYS
-#define NSLU2_FLASH_SIZE	IXP4XX_EXP_BUS_CSX_REGION_SIZE
-
 #define NSLU2_SDA_PIN		7
 #define NSLU2_SCL_PIN		6
 
diff --git a/include/asm-arm/arch-ixp4xx/platform.h b/include/asm-arm/arch-ixp4xx/platform.h
index 6b77ed2..daf9790 100644
--- a/include/asm-arm/arch-ixp4xx/platform.h
+++ b/include/asm-arm/arch-ixp4xx/platform.h
@@ -26,16 +26,17 @@
  */
 #define IXP4XX_EXP_BUS_BASE_PHYS	(0x50000000)
 
-#define	IXP4XX_EXP_BUS_CSX_REGION_SIZE	(0x01000000)
+/*
+ * The expansion bus on the IXP4xx can be configured for either 16 or
+ * 32MB windows and the CS offset for each region changes based on the
+ * current configuration. This means that we cannot simply hardcode
+ * each offset. ixp4xx_sys_init() looks at the expansion bus configuration
+ * as setup by the bootloader to determine our window size.
+ */
+extern unsigned long ixp4xx_exp_bus_size;
 
-#define IXP4XX_EXP_BUS_CS0_BASE_PHYS	(IXP4XX_EXP_BUS_BASE_PHYS + 0x00000000)
-#define IXP4XX_EXP_BUS_CS1_BASE_PHYS	(IXP4XX_EXP_BUS_BASE_PHYS + 0x01000000)
-#define IXP4XX_EXP_BUS_CS2_BASE_PHYS	(IXP4XX_EXP_BUS_BASE_PHYS + 0x02000000)
-#define IXP4XX_EXP_BUS_CS3_BASE_PHYS	(IXP4XX_EXP_BUS_BASE_PHYS + 0x03000000)
-#define IXP4XX_EXP_BUS_CS4_BASE_PHYS	(IXP4XX_EXP_BUS_BASE_PHYS + 0x04000000)
-#define IXP4XX_EXP_BUS_CS5_BASE_PHYS	(IXP4XX_EXP_BUS_BASE_PHYS + 0x05000000)
-#define IXP4XX_EXP_BUS_CS6_BASE_PHYS	(IXP4XX_EXP_BUS_BASE_PHYS + 0x06000000)
-#define IXP4XX_EXP_BUS_CS7_BASE_PHYS	(IXP4XX_EXP_BUS_BASE_PHYS + 0x07000000)
+#define	IXP4XX_EXP_BUS_BASE(region)\
+		(IXP4XX_EXP_BUS_BASE_PHYS + ((region) * ixp4xx_exp_bus_size))
 
 #define IXP4XX_FLASH_WRITABLE	(0x2)
 #define IXP4XX_FLASH_DEFAULT	(0xbcd23c40)