@@ -9,6 +9,10 @@ Required properties (in root node):
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
-------------------------------------------------
@@ -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";
};
@@ -20,6 +20,7 @@ config ARCH_INTEGRATOR_CP
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.
@@ -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>
@@ -336,10 +337,62 @@ static struct of_dev_auxdata intcp_auxdata_lookup[] __initdata = {
{ /* sentinel */ },
};
+/* Base address to the CP controller */
+static void __iomem *intcp_con_base;
+
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[] = {
This hooks the Integrator/CP into the SoC bus when booting from device tree, by mapping the CP controller registers first, then registering the SoC device, and then populating the device tree with the SoC device as parent. Cc: Lee Jones <lee.jones@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> --- Documentation/devicetree/bindings/arm/arm-boards | 4 ++ arch/arm/boot/dts/integratorcp.dts | 5 +++ arch/arm/mach-integrator/Kconfig | 1 + arch/arm/mach-integrator/integrator_cp.c | 57 +++++++++++++++++++++++- 4 files changed, 65 insertions(+), 2 deletions(-)