[PATCH v3 4/7] mfd: match acpi devices against PRP0001

Markus Probst via B4 Relay posted 7 patches 3 weeks, 3 days ago
There is a newer version of this series
[PATCH v3 4/7] mfd: match acpi devices against PRP0001
Posted by Markus Probst via B4 Relay 3 weeks, 3 days ago
From: Markus Probst <markus.probst@posteo.de>

PRP0001 can be used to provide DT-compatible device identification in
ACPI. If the mfd device is bound to a acpi fwnode and no acpi_match data
is provided by the driver, match against PRP0001 and the provided
`of_compatible` string.

Signed-off-by: Markus Probst <markus.probst@posteo.de>
---
 drivers/mfd/mfd-core.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 6be58eb5a746..29bf54664acf 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -39,6 +39,10 @@ struct match_ids_walk_data {
 	struct acpi_device_id *ids;
 	struct acpi_device *adev;
 };
+struct match_of_ids_walk_data {
+	const struct of_device_id *ids;
+	struct acpi_device *adev;
+};
 
 static int match_device_ids(struct acpi_device *adev, void *data)
 {
@@ -52,10 +56,23 @@ static int match_device_ids(struct acpi_device *adev, void *data)
 	return 0;
 }
 
+static int match_of_device_ids(struct acpi_device *adev, void *data)
+{
+	struct match_of_ids_walk_data *wd = data;
+
+	if (!acpi_of_match_device_ids(adev, wd->ids)) {
+		wd->adev = adev;
+		return 1;
+	}
+
+	return 0;
+}
+
 static void mfd_acpi_add_device(const struct mfd_cell *cell,
 				struct platform_device *pdev)
 {
 	const struct mfd_cell_acpi_match *match = cell->acpi_match;
+	const char *of_compatible = cell->of_compatible;
 	struct acpi_device *adev = NULL;
 	struct acpi_device *parent;
 
@@ -86,6 +103,16 @@ static void mfd_acpi_add_device(const struct mfd_cell *cell,
 		} else {
 			adev = acpi_find_child_device(parent, match->adr, false);
 		}
+	} else if (of_compatible) {
+		struct of_device_id ids[2] = {};
+		struct match_of_ids_walk_data wd = {
+			.adev = NULL,
+			.ids = ids,
+		};
+
+		strscpy(ids[0].compatible, of_compatible, sizeof(ids[0].compatible));
+		acpi_dev_for_each_child(parent, match_of_device_ids, &wd);
+		adev = wd.adev;
 	}
 
 	device_set_node(&pdev->dev, acpi_fwnode_handle(adev ?: parent));

-- 
2.52.0