[Arm-dev] [PATCH v1 56/87] mfd: vexpress-sysreg Add ACPI support for probing to driver

Thu Aug 13 13:18:53 UTC 2015
Vadim Lomovtsev <Vadim.Lomovtsev at caviumnetworks.com>

From: Naresh Bhat <naresh.bhat at linaro.org>

Add match table and pointers for ACPI probing into vexpress-sysreg driver.

vexpress-sysreg is self-contained so it gets resources automatically
being platform driver. However, while it is not probed, it still should
provides base address so that other related drivers can take advantage
of it. Make it possible and find resources based on device HID.

Signed-off-by: Naresh Bhat <naresh.bhat at linaro.org>
Signed-off-by: Tomasz Nowicki <tomasz.nowicki at linaro.org>
Signed-off-by: Robert Richter <rrichter at cavium.com>
Signed-off-by: Vadim Lomovtsev <Vadim.Lomovtsev at caviumnetworks.com>
---
 drivers/mfd/vexpress-sysreg.c | 66 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 63 insertions(+), 3 deletions(-)

diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c
index 8f43ab8..0db1746 100644
--- a/drivers/mfd/vexpress-sysreg.c
+++ b/drivers/mfd/vexpress-sysreg.c
@@ -22,6 +22,7 @@
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/vexpress.h>
+#include <linux/acpi.h>
 
 #define SYS_ID			0x000
 #define SYS_SW			0x004
@@ -55,15 +56,66 @@
 
 static void __iomem *__vexpress_sysreg_base;
 
+#ifdef CONFIG_ACPI
+static acpi_status check_vexpress_resource(struct acpi_resource *res,
+					   void *data)
+{
+	struct resource *vexpress_res = data;
+
+	if (!acpi_dev_resource_memory(res, vexpress_res))
+		pr_err("Failed to map vexpress memory resource\n");
+
+	__vexpress_sysreg_base = ioremap(vexpress_res->start,
+					resource_size(vexpress_res));
+	if (__vexpress_sysreg_base)
+		return AE_CTRL_TERMINATE;
+
+	return AE_OK;
+}
+
+static acpi_status find_vexpress_resource(acpi_handle handle, u32 lvl,
+					  void *context, void **rv)
+{
+	struct resource *vexpress_res = context;
+
+	acpi_walk_resources(handle, METHOD_NAME__CRS,
+			    check_vexpress_resource, context);
+
+	if (vexpress_res->flags)
+		return AE_CTRL_TERMINATE;
+
+	return AE_OK;
+}
+
+static void acpi_vexpress_sysreg_base(void)
+{
+	struct resource vexpress_res;
+
+	acpi_get_devices("LNRO0009", find_vexpress_resource, &vexpress_res,
+			 NULL);
+}
+#else
+static inline void acpi_vexpress_sysreg_base(void)
+{
+}
+#endif
+
 static void __iomem *vexpress_sysreg_base(void)
 {
-	if (!__vexpress_sysreg_base) {
-		struct device_node *node = of_find_compatible_node(NULL, NULL,
-				"arm,vexpress-sysreg");
+	struct device_node *node;
+
+	if (__vexpress_sysreg_base)
+		goto ret;
 
+	node = of_find_compatible_node(NULL, NULL, "arm,vexpress-sysreg");
+	if (node) {
 		__vexpress_sysreg_base = of_iomap(node, 0);
+		goto ret;
 	}
 
+	acpi_vexpress_sysreg_base();
+
+ret:
 	WARN_ON(!__vexpress_sysreg_base);
 
 	return __vexpress_sysreg_base;
@@ -255,10 +307,18 @@ static const struct of_device_id vexpress_sysreg_match[] = {
 	{},
 };
 
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id vexpress_sysreg_acpi_match[] = {
+	{ "LNRO0009", },
+	{ }
+};
+#endif
+
 static struct platform_driver vexpress_sysreg_driver = {
 	.driver = {
 		.name = "vexpress-sysreg",
 		.of_match_table = vexpress_sysreg_match,
+		.acpi_match_table = ACPI_PTR(vexpress_sysreg_acpi_match),
 	},
 	.probe = vexpress_sysreg_probe,
 };
-- 
2.4.3