Merge tag 'integrator-for-arm-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator into next/cleanup

From Linus Walleij <linus.walleij@linaro.org>:

This series will do the following:
- Switch the Integrator/AP and /CP to use the SoC bus
  when booting from device tree.
- Group all devices on the SoC below this bus so as to
  set a good example of how to do this. The bus was
  invented by Lee Jones, let's show how it's to be used
  on a DT:ed SoC.
- Fetch the special system controller offsets from two
  special device tree nodes for each case and replace
  the static mappings with these at boot.
- Move some static remaps to the ATAG-only code path
  and delete some static maps that aren't used.
- Push dependencies on system controller remaps down
  to the Integrator/AP board file and the PCIv3 driver
  respectively and use only dynamic remappings.
- Fix up conditional BUG() usage in the PCIv3 driver
  to be simpler and more to the point.

* tag 'integrator-for-arm-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator:
  ARM: integrator: use BUG_ON where possible
  ARM: integrator: push down SC dependencies
  ARM: integrator: delete static UART1 mapping
  ARM: integrator: delete SC mapping on the CP
  ARM: integrator: remove static CP syscon mapping
  ARM: integrator: remove static AP syscon mapping
  ARM: integrator: hook the CP into the SoC bus
  ARM: integrator: hook the AP into the SoC bus

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
diff --git a/Documentation/devicetree/bindings/arm/arm-boards b/Documentation/devicetree/bindings/arm/arm-boards
index fc81a7d..db5858e 100644
--- a/Documentation/devicetree/bindings/arm/arm-boards
+++ b/Documentation/devicetree/bindings/arm/arm-boards
@@ -9,6 +9,10 @@
 
 FPGA type interrupt controllers, see the versatile-fpga-irq binding doc.
 
+In the root node the Integrator/CP must have a /cpcon node pointing
+to the CP control registers, and the Integrator/AP must have a
+/syscon node pointing to the Integrator/AP system controller.
+
 
 ARM Versatile Application and Platform Baseboards
 -------------------------------------------------
diff --git a/arch/arm/boot/dts/integratorap.dts b/arch/arm/boot/dts/integratorap.dts
index 6176775..c9c3fa3 100644
--- a/arch/arm/boot/dts/integratorap.dts
+++ b/arch/arm/boot/dts/integratorap.dts
@@ -18,6 +18,11 @@
 		bootargs = "root=/dev/ram0 console=ttyAM0,38400n8 earlyprintk";
 	};
 
+	syscon {
+		/* AP system controller registers */
+		reg = <0x11000000 0x100>;
+	};
+
 	timer0: timer@13000000 {
 		compatible = "arm,integrator-timer";
 	};
diff --git a/arch/arm/boot/dts/integratorcp.dts b/arch/arm/boot/dts/integratorcp.dts
index 2dd5e4e..8b11939 100644
--- a/arch/arm/boot/dts/integratorcp.dts
+++ b/arch/arm/boot/dts/integratorcp.dts
@@ -18,6 +18,11 @@
 		bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk";
 	};
 
+	cpcon {
+		/* CP controller registers */
+		reg = <0xcb000000 0x100>;
+	};
+
 	timer0: timer@13000000 {
 		compatible = "arm,sp804", "arm,primecell";
 	};
diff --git a/arch/arm/mach-integrator/Kconfig b/arch/arm/mach-integrator/Kconfig
index 350e266..abeff25 100644
--- a/arch/arm/mach-integrator/Kconfig
+++ b/arch/arm/mach-integrator/Kconfig
@@ -8,6 +8,7 @@
 	select MIGHT_HAVE_PCI
 	select SERIAL_AMBA_PL010
 	select SERIAL_AMBA_PL010_CONSOLE
+	select SOC_BUS
 	help
 	  Include support for the ARM(R) Integrator/AP and
 	  Integrator/PP2 platforms.
@@ -19,6 +20,7 @@
 	select PLAT_VERSATILE_CLCD
 	select SERIAL_AMBA_PL011
 	select SERIAL_AMBA_PL011_CONSOLE
+	select SOC_BUS
 	help
 	  Include support for the ARM(R) Integrator CP platform.
 
diff --git a/arch/arm/mach-integrator/common.h b/arch/arm/mach-integrator/common.h
index c3ff21b..79197d8 100644
--- a/arch/arm/mach-integrator/common.h
+++ b/arch/arm/mach-integrator/common.h
@@ -1,6 +1,12 @@
 #include <linux/amba/serial.h>
-extern struct amba_pl010_data integrator_uart_data;
+#ifdef CONFIG_ARCH_INTEGRATOR_AP
+extern struct amba_pl010_data ap_uart_data;
+#else
+/* Not used without Integrator/AP support anyway */
+struct amba_pl010_data ap_uart_data {};
+#endif
 void integrator_init_early(void);
 int integrator_init(bool is_cp);
 void integrator_reserve(void);
 void integrator_restart(char, const char *);
+void integrator_init_sysfs(struct device *parent, u32 id);
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index ea22a17..39c060f 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -18,10 +18,10 @@
 #include <linux/memblock.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
-#include <linux/termios.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/serial.h>
 #include <linux/io.h>
+#include <linux/stat.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
@@ -46,10 +46,10 @@
 	INTEGRATOR_RTC_BASE, INTEGRATOR_RTC_IRQ, NULL);
 
 static AMBA_APB_DEVICE(uart0, "uart0", 0,
-	INTEGRATOR_UART0_BASE, INTEGRATOR_UART0_IRQ, &integrator_uart_data);
+	INTEGRATOR_UART0_BASE, INTEGRATOR_UART0_IRQ, NULL);
 
 static AMBA_APB_DEVICE(uart1, "uart1", 0,
-	INTEGRATOR_UART1_BASE, INTEGRATOR_UART1_IRQ, &integrator_uart_data);
+	INTEGRATOR_UART1_BASE, INTEGRATOR_UART1_IRQ, NULL);
 
 static AMBA_APB_DEVICE(kmi0, "kmi0", 0, KMI0_BASE, KMI0_IRQ, NULL);
 static AMBA_APB_DEVICE(kmi1, "kmi1", 0, KMI1_BASE, KMI1_IRQ, NULL);
@@ -77,6 +77,8 @@
 		uart1_device.periphid	= 0x00041010;
 		kmi0_device.periphid	= 0x00041050;
 		kmi1_device.periphid	= 0x00041050;
+		uart0_device.dev.platform_data = &ap_uart_data;
+		uart1_device.dev.platform_data = &ap_uart_data;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
@@ -89,49 +91,6 @@
 
 #endif
 
-/*
- * On the Integrator platform, the port RTS and DTR are provided by
- * bits in the following SC_CTRLS register bits:
- *        RTS  DTR
- *  UART0  7    6
- *  UART1  5    4
- */
-#define SC_CTRLC	__io_address(INTEGRATOR_SC_CTRLC)
-#define SC_CTRLS	__io_address(INTEGRATOR_SC_CTRLS)
-
-static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *base, unsigned int mctrl)
-{
-	unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask;
-	u32 phybase = dev->res.start;
-
-	if (phybase == INTEGRATOR_UART0_BASE) {
-		/* UART0 */
-		rts_mask = 1 << 4;
-		dtr_mask = 1 << 5;
-	} else {
-		/* UART1 */
-		rts_mask = 1 << 6;
-		dtr_mask = 1 << 7;
-	}
-
-	if (mctrl & TIOCM_RTS)
-		ctrlc |= rts_mask;
-	else
-		ctrls |= rts_mask;
-
-	if (mctrl & TIOCM_DTR)
-		ctrlc |= dtr_mask;
-	else
-		ctrls |= dtr_mask;
-
-	__raw_writel(ctrls, SC_CTRLS);
-	__raw_writel(ctrlc, SC_CTRLC);
-}
-
-struct amba_pl010_data integrator_uart_data = {
-	.set_mctrl = integrator_uart_set_mctrl,
-};
-
 static DEFINE_RAW_SPINLOCK(cm_lock);
 
 /**
@@ -169,3 +128,93 @@
 {
 	cm_control(CM_CTRL_RESET, CM_CTRL_RESET);
 }
+
+static u32 integrator_id;
+
+static ssize_t intcp_get_manf(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	return sprintf(buf, "%02x\n", integrator_id >> 24);
+}
+
+static struct device_attribute intcp_manf_attr =
+	__ATTR(manufacturer,  S_IRUGO, intcp_get_manf,  NULL);
+
+static ssize_t intcp_get_arch(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	const char *arch;
+
+	switch ((integrator_id >> 16) & 0xff) {
+	case 0x00:
+		arch = "ASB little-endian";
+		break;
+	case 0x01:
+		arch = "AHB little-endian";
+		break;
+	case 0x03:
+		arch = "AHB-Lite system bus, bi-endian";
+		break;
+	case 0x04:
+		arch = "AHB";
+		break;
+	default:
+		arch = "Unknown";
+		break;
+	}
+
+	return sprintf(buf, "%s\n", arch);
+}
+
+static struct device_attribute intcp_arch_attr =
+	__ATTR(architecture,  S_IRUGO, intcp_get_arch,  NULL);
+
+static ssize_t intcp_get_fpga(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	const char *fpga;
+
+	switch ((integrator_id >> 12) & 0xf) {
+	case 0x01:
+		fpga = "XC4062";
+		break;
+	case 0x02:
+		fpga = "XC4085";
+		break;
+	case 0x04:
+		fpga = "EPM7256AE (Altera PLD)";
+		break;
+	default:
+		fpga = "Unknown";
+		break;
+	}
+
+	return sprintf(buf, "%s\n", fpga);
+}
+
+static struct device_attribute intcp_fpga_attr =
+	__ATTR(fpga,  S_IRUGO, intcp_get_fpga,  NULL);
+
+static ssize_t intcp_get_build(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	return sprintf(buf, "%02x\n", (integrator_id >> 4) & 0xFF);
+}
+
+static struct device_attribute intcp_build_attr =
+	__ATTR(build,  S_IRUGO, intcp_get_build,  NULL);
+
+
+
+void integrator_init_sysfs(struct device *parent, u32 id)
+{
+	integrator_id = id;
+	device_create_file(parent, &intcp_manf_attr);
+	device_create_file(parent, &intcp_arch_attr);
+	device_create_file(parent, &intcp_fpga_attr);
+	device_create_file(parent, &intcp_build_attr);
+}
diff --git a/arch/arm/mach-integrator/include/mach/platform.h b/arch/arm/mach-integrator/include/mach/platform.h
index efeac5d..be5859e 100644
--- a/arch/arm/mach-integrator/include/mach/platform.h
+++ b/arch/arm/mach-integrator/include/mach/platform.h
@@ -190,7 +190,6 @@
 #define INTEGRATOR_SC_CTRLC_OFFSET      0x0C
 #define INTEGRATOR_SC_DEC_OFFSET        0x10
 #define INTEGRATOR_SC_ARB_OFFSET        0x14
-#define INTEGRATOR_SC_PCIENABLE_OFFSET  0x18
 #define INTEGRATOR_SC_LOCK_OFFSET       0x1C
 
 #define INTEGRATOR_SC_BASE              0x11000000
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index e6617c1..a0a7cbb 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -37,6 +37,9 @@
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
+#include <linux/stat.h>
+#include <linux/sys_soc.h>
+#include <linux/termios.h>
 #include <video/vga.h>
 
 #include <mach/hardware.h>
@@ -60,7 +63,10 @@
 
 #include "common.h"
 
-/* 
+/* Base address to the AP system controller */
+void __iomem *ap_syscon_base;
+
+/*
  * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx
  * is the (PA >> 12).
  *
@@ -68,7 +74,6 @@
  * just for now).
  */
 #define VA_IC_BASE	__io_address(INTEGRATOR_IC_BASE)
-#define VA_SC_BASE	__io_address(INTEGRATOR_SC_BASE)
 #define VA_EBI_BASE	__io_address(INTEGRATOR_EBI_BASE)
 #define VA_CMIC_BASE	__io_address(INTEGRATOR_HDR_IC)
 
@@ -97,11 +102,6 @@
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
-		.virtual	= IO_ADDRESS(INTEGRATOR_SC_BASE),
-		.pfn		= __phys_to_pfn(INTEGRATOR_SC_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE
-	}, {
 		.virtual	= IO_ADDRESS(INTEGRATOR_EBI_BASE),
 		.pfn		= __phys_to_pfn(INTEGRATOR_EBI_BASE),
 		.length		= SZ_4K,
@@ -122,11 +122,6 @@
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
-		.virtual	= IO_ADDRESS(INTEGRATOR_UART1_BASE),
-		.pfn		= __phys_to_pfn(INTEGRATOR_UART1_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE
-	}, {
 		.virtual	= IO_ADDRESS(INTEGRATOR_DBG_BASE),
 		.pfn		= __phys_to_pfn(INTEGRATOR_DBG_BASE),
 		.length		= SZ_4K,
@@ -201,8 +196,6 @@
 /*
  * Flash handling.
  */
-#define SC_CTRLC (VA_SC_BASE + INTEGRATOR_SC_CTRLC_OFFSET)
-#define SC_CTRLS (VA_SC_BASE + INTEGRATOR_SC_CTRLS_OFFSET)
 #define EBI_CSR1 (VA_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET)
 #define EBI_LOCK (VA_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET)
 
@@ -210,7 +203,8 @@
 {
 	u32 tmp;
 
-	writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
+	writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP,
+	       ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET);
 
 	tmp = readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE;
 	writel(tmp, EBI_CSR1);
@@ -227,7 +221,8 @@
 {
 	u32 tmp;
 
-	writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
+	writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP,
+	       ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET);
 
 	tmp = readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE;
 	writel(tmp, EBI_CSR1);
@@ -241,9 +236,12 @@
 
 static void ap_flash_set_vpp(struct platform_device *pdev, int on)
 {
-	void __iomem *reg = on ? SC_CTRLS : SC_CTRLC;
-
-	writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg);
+	if (on)
+		writel(INTEGRATOR_SC_CTRL_nFLVPPEN,
+		       ap_syscon_base + INTEGRATOR_SC_CTRLS_OFFSET);
+	else
+		writel(INTEGRATOR_SC_CTRL_nFLVPPEN,
+		       ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET);
 }
 
 static struct physmap_flash_data ap_flash_data = {
@@ -254,6 +252,45 @@
 };
 
 /*
+ * For the PL010 found in the Integrator/AP some of the UART control is
+ * implemented in the system controller and accessed using a callback
+ * from the driver.
+ */
+static void integrator_uart_set_mctrl(struct amba_device *dev,
+				void __iomem *base, unsigned int mctrl)
+{
+	unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask;
+	u32 phybase = dev->res.start;
+
+	if (phybase == INTEGRATOR_UART0_BASE) {
+		/* UART0 */
+		rts_mask = 1 << 4;
+		dtr_mask = 1 << 5;
+	} else {
+		/* UART1 */
+		rts_mask = 1 << 6;
+		dtr_mask = 1 << 7;
+	}
+
+	if (mctrl & TIOCM_RTS)
+		ctrlc |= rts_mask;
+	else
+		ctrls |= rts_mask;
+
+	if (mctrl & TIOCM_DTR)
+		ctrlc |= dtr_mask;
+	else
+		ctrls |= dtr_mask;
+
+	__raw_writel(ctrls, ap_syscon_base + INTEGRATOR_SC_CTRLS_OFFSET);
+	__raw_writel(ctrlc, ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET);
+}
+
+struct amba_pl010_data ap_uart_data = {
+	.set_mctrl = integrator_uart_set_mctrl,
+};
+
+/*
  * Where is the timer (VA)?
  */
 #define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE)
@@ -450,9 +487,9 @@
 	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_RTC_BASE,
 		"rtc", NULL),
 	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART0_BASE,
-		"uart0", &integrator_uart_data),
+		"uart0", &ap_uart_data),
 	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE,
-		"uart1", &integrator_uart_data),
+		"uart1", &ap_uart_data),
 	OF_DEV_AUXDATA("arm,primecell", KMI0_BASE,
 		"kmi0", NULL),
 	OF_DEV_AUXDATA("arm,primecell", KMI1_BASE,
@@ -465,12 +502,60 @@
 static void __init ap_init_of(void)
 {
 	unsigned long sc_dec;
+	struct device_node *root;
+	struct device_node *syscon;
+	struct device *parent;
+	struct soc_device *soc_dev;
+	struct soc_device_attribute *soc_dev_attr;
+	u32 ap_sc_id;
+	int err;
 	int i;
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			ap_auxdata_lookup, NULL);
+	/* Here we create an SoC device for the root node */
+	root = of_find_node_by_path("/");
+	if (!root)
+		return;
+	syscon = of_find_node_by_path("/syscon");
+	if (!syscon)
+		return;
 
-	sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
+	ap_syscon_base = of_iomap(syscon, 0);
+	if (!ap_syscon_base)
+		return;
+
+	ap_sc_id = readl(ap_syscon_base);
+
+	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+	if (!soc_dev_attr)
+		return;
+
+	err = of_property_read_string(root, "compatible",
+				      &soc_dev_attr->soc_id);
+	if (err)
+		return;
+	err = of_property_read_string(root, "model", &soc_dev_attr->machine);
+	if (err)
+		return;
+	soc_dev_attr->family = "Integrator";
+	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c",
+					   'A' + (ap_sc_id & 0x0f));
+
+	soc_dev = soc_device_register(soc_dev_attr);
+	if (IS_ERR_OR_NULL(soc_dev)) {
+		kfree(soc_dev_attr->revision);
+		kfree(soc_dev_attr);
+		return;
+	}
+
+	parent = soc_device_to_device(soc_dev);
+
+	if (!IS_ERR_OR_NULL(parent))
+		integrator_init_sysfs(parent, ap_sc_id);
+
+	of_platform_populate(root, of_default_bus_match_table,
+			ap_auxdata_lookup, parent);
+
+	sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET);
 	for (i = 0; i < 4; i++) {
 		struct lm_device *lmdev;
 
@@ -514,6 +599,27 @@
 #ifdef CONFIG_ATAGS
 
 /*
+ * For the ATAG boot some static mappings are needed. This will
+ * go away with the ATAG support down the road.
+ */
+
+static struct map_desc ap_io_desc_atag[] __initdata = {
+	{
+		.virtual	= IO_ADDRESS(INTEGRATOR_SC_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_SC_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	},
+};
+
+static void __init ap_map_io_atag(void)
+{
+	iotable_init(ap_io_desc_atag, ARRAY_SIZE(ap_io_desc_atag));
+	ap_syscon_base = __io_address(INTEGRATOR_SC_BASE);
+	ap_map_io();
+}
+
+/*
  * This is where non-devicetree initialization code is collected and stashed
  * for eventual deletion.
  */
@@ -581,7 +687,7 @@
 
 	platform_device_register(&cfi_flash_device);
 
-	sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
+	sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET);
 	for (i = 0; i < 4; i++) {
 		struct lm_device *lmdev;
 
@@ -608,7 +714,7 @@
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
 	.atag_offset	= 0x100,
 	.reserve	= integrator_reserve,
-	.map_io		= ap_map_io,
+	.map_io		= ap_map_io_atag,
 	.nr_irqs	= NR_IRQS_INTEGRATOR_AP,
 	.init_early	= ap_init_early,
 	.init_irq	= ap_init_irq,
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 5b08e8e..29df06b 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -26,6 +26,7 @@
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
+#include <linux/sys_soc.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
@@ -51,11 +52,13 @@
 
 #include "common.h"
 
+/* Base address to the CP controller */
+static void __iomem *intcp_con_base;
+
 #define INTCP_PA_FLASH_BASE		0x24000000
 
 #define INTCP_PA_CLCD_BASE		0xc0000000
 
-#define INTCP_VA_CTRL_BASE		__io_address(INTEGRATOR_CP_CTL_BASE)
 #define INTCP_FLASHPROG			0x04
 #define CINTEGRATOR_FLASHPROG_FLVPPEN	(1 << 0)
 #define CINTEGRATOR_FLASHPROG_FLWREN	(1 << 1)
@@ -82,11 +85,6 @@
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
-		.virtual	= IO_ADDRESS(INTEGRATOR_SC_BASE),
-		.pfn		= __phys_to_pfn(INTEGRATOR_SC_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE
-	}, {
 		.virtual	= IO_ADDRESS(INTEGRATOR_EBI_BASE),
 		.pfn		= __phys_to_pfn(INTEGRATOR_EBI_BASE),
 		.length		= SZ_4K,
@@ -107,11 +105,6 @@
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
-		.virtual	= IO_ADDRESS(INTEGRATOR_UART1_BASE),
-		.pfn		= __phys_to_pfn(INTEGRATOR_UART1_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE
-	}, {
 		.virtual	= IO_ADDRESS(INTEGRATOR_DBG_BASE),
 		.pfn		= __phys_to_pfn(INTEGRATOR_DBG_BASE),
 		.length		= SZ_4K,
@@ -126,11 +119,6 @@
 		.pfn		= __phys_to_pfn(INTEGRATOR_CP_SIC_BASE),
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
-	}, {
-		.virtual	= IO_ADDRESS(INTEGRATOR_CP_CTL_BASE),
-		.pfn		= __phys_to_pfn(INTEGRATOR_CP_CTL_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE
 	}
 };
 
@@ -146,9 +134,9 @@
 {
 	u32 val;
 
-	val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+	val = readl(intcp_con_base + INTCP_FLASHPROG);
 	val |= CINTEGRATOR_FLASHPROG_FLWREN;
-	writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+	writel(val, intcp_con_base + INTCP_FLASHPROG);
 
 	return 0;
 }
@@ -157,21 +145,21 @@
 {
 	u32 val;
 
-	val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+	val = readl(intcp_con_base + INTCP_FLASHPROG);
 	val &= ~(CINTEGRATOR_FLASHPROG_FLVPPEN|CINTEGRATOR_FLASHPROG_FLWREN);
-	writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+	writel(val, intcp_con_base + INTCP_FLASHPROG);
 }
 
 static void intcp_flash_set_vpp(struct platform_device *pdev, int on)
 {
 	u32 val;
 
-	val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+	val = readl(intcp_con_base + INTCP_FLASHPROG);
 	if (on)
 		val |= CINTEGRATOR_FLASHPROG_FLVPPEN;
 	else
 		val &= ~CINTEGRATOR_FLASHPROG_FLVPPEN;
-	writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
+	writel(val, intcp_con_base + INTCP_FLASHPROG);
 }
 
 static struct physmap_flash_data intcp_flash_data = {
@@ -190,7 +178,7 @@
 static unsigned int mmc_status(struct device *dev)
 {
 	unsigned int status = readl(__io_address(0xca000000 + 4));
-	writel(8, __io_address(INTEGRATOR_CP_CTL_BASE + 8));
+	writel(8, intcp_con_base + 8);
 
 	return status & 8;
 }
@@ -318,9 +306,9 @@
 	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_RTC_BASE,
 		"rtc", NULL),
 	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART0_BASE,
-		"uart0", &integrator_uart_data),
+		"uart0", NULL),
 	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE,
-		"uart1", &integrator_uart_data),
+		"uart1", NULL),
 	OF_DEV_AUXDATA("arm,primecell", KMI0_BASE,
 		"kmi0", NULL),
 	OF_DEV_AUXDATA("arm,primecell", KMI1_BASE,
@@ -338,8 +326,57 @@
 
 static void __init intcp_init_of(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table,
-			intcp_auxdata_lookup, NULL);
+	struct device_node *root;
+	struct device_node *cpcon;
+	struct device *parent;
+	struct soc_device *soc_dev;
+	struct soc_device_attribute *soc_dev_attr;
+	u32 intcp_sc_id;
+	int err;
+
+	/* Here we create an SoC device for the root node */
+	root = of_find_node_by_path("/");
+	if (!root)
+		return;
+	cpcon = of_find_node_by_path("/cpcon");
+	if (!cpcon)
+		return;
+
+	intcp_con_base = of_iomap(cpcon, 0);
+	if (!intcp_con_base)
+		return;
+
+	intcp_sc_id = readl(intcp_con_base);
+
+	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+	if (!soc_dev_attr)
+		return;
+
+	err = of_property_read_string(root, "compatible",
+				      &soc_dev_attr->soc_id);
+	if (err)
+		return;
+	err = of_property_read_string(root, "model", &soc_dev_attr->machine);
+	if (err)
+		return;
+	soc_dev_attr->family = "Integrator";
+	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c",
+					   'A' + (intcp_sc_id & 0x0f));
+
+	soc_dev = soc_device_register(soc_dev_attr);
+	if (IS_ERR_OR_NULL(soc_dev)) {
+		kfree(soc_dev_attr->revision);
+		kfree(soc_dev_attr);
+		return;
+	}
+
+	parent = soc_device_to_device(soc_dev);
+
+	if (!IS_ERR_OR_NULL(parent))
+		integrator_init_sysfs(parent, intcp_sc_id);
+
+	of_platform_populate(root, of_default_bus_match_table,
+			intcp_auxdata_lookup, parent);
 }
 
 static const char * intcp_dt_board_compat[] = {
@@ -365,6 +402,28 @@
 #ifdef CONFIG_ATAGS
 
 /*
+ * For the ATAG boot some static mappings are needed. This will
+ * go away with the ATAG support down the road.
+ */
+
+static struct map_desc intcp_io_desc_atag[] __initdata = {
+	{
+		.virtual	= IO_ADDRESS(INTEGRATOR_CP_CTL_BASE),
+		.pfn		= __phys_to_pfn(INTEGRATOR_CP_CTL_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+	},
+};
+
+static void __init intcp_map_io_atag(void)
+{
+	iotable_init(intcp_io_desc_atag, ARRAY_SIZE(intcp_io_desc_atag));
+	intcp_con_base = __io_address(INTEGRATOR_CP_CTL_BASE);
+	intcp_map_io();
+}
+
+
+/*
  * This is where non-devicetree initialization code is collected and stashed
  * for eventual deletion.
  */
@@ -503,7 +562,7 @@
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
 	.atag_offset	= 0x100,
 	.reserve	= integrator_reserve,
-	.map_io		= intcp_map_io,
+	.map_io		= intcp_map_io_atag,
 	.nr_irqs	= NR_IRQS_INTEGRATOR_CP,
 	.init_early	= intcp_init_early,
 	.init_irq	= intcp_init_irq,
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index bbeca59..be50e79 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -191,12 +191,9 @@
 	/*
 	 * Trap out illegal values
 	 */
-	if (offset > 255)
-		BUG();
-	if (busnr > 255)
-		BUG();
-	if (devfn > 255)
-		BUG();
+	BUG_ON(offset > 255);
+	BUG_ON(busnr > 255);
+	BUG_ON(devfn > 255);
 
 	if (busnr == 0) {
 		int slot = PCI_SLOT(devfn);
@@ -388,9 +385,10 @@
  * means I can't get additional information on the reason for the pm2fb
  * problems.  I suppose I'll just have to mind-meld with the machine. ;)
  */
-#define SC_PCI     __io_address(INTEGRATOR_SC_PCIENABLE)
-#define SC_LBFADDR __io_address(INTEGRATOR_SC_BASE + 0x20)
-#define SC_LBFCODE __io_address(INTEGRATOR_SC_BASE + 0x24)
+static void __iomem *ap_syscon_base;
+#define INTEGRATOR_SC_PCIENABLE_OFFSET	0x18
+#define INTEGRATOR_SC_LBFADDR_OFFSET	0x20
+#define INTEGRATOR_SC_LBFCODE_OFFSET	0x24
 
 static int
 v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
@@ -401,13 +399,13 @@
 	char buf[128];
 
 	sprintf(buf, "V3 fault: addr 0x%08lx, FSR 0x%03x, PC 0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n",
-		addr, fsr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255,
+		addr, fsr, pc, instr, __raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFADDR_OFFSET), __raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFCODE_OFFSET) & 255,
 		v3_readb(V3_LB_ISTAT));
 	printk(KERN_DEBUG "%s", buf);
 #endif
 
 	v3_writeb(V3_LB_ISTAT, 0);
-	__raw_writel(3, SC_PCI);
+	__raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET);
 
 	/*
 	 * If the instruction being executed was a read,
@@ -449,15 +447,15 @@
 
 	sprintf(buf, "V3 int %d: pc=0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x "
 		"ISTAT=%02x\n", IRQ_AP_V3INT, pc, instr,
-		__raw_readl(SC_LBFADDR),
-		__raw_readl(SC_LBFCODE) & 255,
+		__raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFADDR_OFFSET),
+		__raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFCODE_OFFSET) & 255,
 		v3_readb(V3_LB_ISTAT));
 	printascii(buf);
 #endif
 
 	v3_writew(V3_PCI_STAT, 0xf000);
 	v3_writeb(V3_LB_ISTAT, 0);
-	__raw_writel(3, SC_PCI);
+	__raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET);
 
 #ifdef CONFIG_DEBUG_LL
 	/*
@@ -480,6 +478,10 @@
 	if (nr == 0) {
 		sys->mem_offset = PHYS_PCI_MEM_BASE;
 		ret = pci_v3_setup_resources(sys);
+		/* Remap the Integrator system controller */
+		ap_syscon_base = ioremap(INTEGRATOR_SC_BASE, 0x100);
+		if (!ap_syscon_base)
+			return -EINVAL;
 	}
 
 	return ret;
@@ -568,7 +570,7 @@
 	v3_writeb(V3_LB_ISTAT, 0);
 	v3_writew(V3_LB_CFG, v3_readw(V3_LB_CFG) | (1 << 10));
 	v3_writeb(V3_LB_IMASK, 0x28);
-	__raw_writel(3, SC_PCI);
+	__raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET);
 
 	/*
 	 * Grab the PCI error interrupt.