Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e67ae6be authored by Linus Walleij's avatar Linus Walleij
Browse files

ARM: integrator: hook the AP into the SoC bus



This hooks the Integrator/AP into the SoC bus when booting from
device tree, by mapping the AP controller registers first,
then registering the SoC device, and then populating the device
tree with the SoC device as parent.

Introduce some helpers in the core to provide sysfs files
detailing the use of the SoC ID which will later be reused by
the Integrator/CP patch for the same bus grouping.

Cc: Lee Jones <lee.jones@linaro.org>
Acked-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 6f0c0580
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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";
	};
+1 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ config ARCH_INTEGRATOR_AP
	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.
+1 −0
Original line number Diff line number Diff line
@@ -4,3 +4,4 @@ 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);
+91 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#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>
@@ -169,3 +170,93 @@ void integrator_restart(char mode, const char *cmd)
{
	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);
}
+55 −2
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@
#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 <video/vga.h>

#include <mach/hardware.h>
@@ -462,13 +464,64 @@ static struct of_dev_auxdata ap_auxdata_lookup[] __initdata = {
	{ /* sentinel */ },
};

/* Base address to the AP system controller */
static void __iomem *ap_syscon_base;

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;

	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(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
	for (i = 0; i < 4; i++) {