aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/acpi/enumeration.txt27
-rw-r--r--drivers/mfd/mfd-core.c40
-rw-r--r--include/linux/mfd/core.h3
3 files changed, 70 insertions, 0 deletions
diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt
index e182be5e3c83..b60d2ab69497 100644
--- a/Documentation/acpi/enumeration.txt
+++ b/Documentation/acpi/enumeration.txt
@@ -312,3 +312,30 @@ a code like this:
312 312
313There are also devm_* versions of these functions which release the 313There are also devm_* versions of these functions which release the
314descriptors once the device is released. 314descriptors once the device is released.
315
316MFD devices
317~~~~~~~~~~~
318The MFD devices register their children as platform devices. For the child
319devices there needs to be an ACPI handle that they can use to reference
320parts of the ACPI namespace that relate to them. In the Linux MFD subsystem
321we provide two ways:
322
323 o The children share the parent ACPI handle.
324 o The MFD cell can specify the ACPI id of the device.
325
326For the first case, the MFD drivers do not need to do anything. The
327resulting child platform device will have its ACPI_COMPANION() set to point
328to the parent device.
329
330If the ACPI namespace has a device that we can match using an ACPI id,
331the id should be set like:
332
333 static struct mfd_cell my_subdevice_cell = {
334 .name = "my_subdevice",
335 /* set the resources relative to the parent */
336 .acpi_pnpid = "XYZ0001",
337 };
338
339The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under
340the MFD device and if found, that ACPI companion device is bound to the
341resulting child platform device.
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 5d0fbe1e097a..f3338fe9d069 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -78,6 +78,44 @@ static int mfd_platform_add_cell(struct platform_device *pdev,
78 return 0; 78 return 0;
79} 79}
80 80
81#if IS_ENABLED(CONFIG_ACPI)
82static void mfd_acpi_add_device(const struct mfd_cell *cell,
83 struct platform_device *pdev)
84{
85 struct acpi_device *parent_adev;
86 struct acpi_device *adev;
87
88 parent_adev = ACPI_COMPANION(pdev->dev.parent);
89 if (!parent_adev)
90 return;
91
92 /*
93 * MFD child device gets its ACPI handle either from the ACPI
94 * device directly under the parent that matches the acpi_pnpid or
95 * it will use the parent handle if is no acpi_pnpid is given.
96 */
97 adev = parent_adev;
98 if (cell->acpi_pnpid) {
99 struct acpi_device_id ids[2] = {};
100 struct acpi_device *child_adev;
101
102 strlcpy(ids[0].id, cell->acpi_pnpid, sizeof(ids[0].id));
103 list_for_each_entry(child_adev, &parent_adev->children, node)
104 if (acpi_match_device_ids(child_adev, ids)) {
105 adev = child_adev;
106 break;
107 }
108 }
109
110 ACPI_COMPANION_SET(&pdev->dev, adev);
111}
112#else
113static inline void mfd_acpi_add_device(const struct mfd_cell *cell,
114 struct platform_device *pdev)
115{
116}
117#endif
118
81static int mfd_add_device(struct device *parent, int id, 119static int mfd_add_device(struct device *parent, int id,
82 const struct mfd_cell *cell, atomic_t *usage_count, 120 const struct mfd_cell *cell, atomic_t *usage_count,
83 struct resource *mem_base, 121 struct resource *mem_base,
@@ -119,6 +157,8 @@ static int mfd_add_device(struct device *parent, int id,
119 } 157 }
120 } 158 }
121 159
160 mfd_acpi_add_device(cell, pdev);
161
122 if (cell->pdata_size) { 162 if (cell->pdata_size) {
123 ret = platform_device_add_data(pdev, 163 ret = platform_device_add_data(pdev,
124 cell->platform_data, cell->pdata_size); 164 cell->platform_data, cell->pdata_size);
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
index f543de91ce19..73e1709d4c09 100644
--- a/include/linux/mfd/core.h
+++ b/include/linux/mfd/core.h
@@ -44,6 +44,9 @@ struct mfd_cell {
44 */ 44 */
45 const char *of_compatible; 45 const char *of_compatible;
46 46
47 /* Matches ACPI PNP id, either _HID or _CID */
48 const char *acpi_pnpid;
49
47 /* 50 /*
48 * These resources can be specified relative to the parent device. 51 * These resources can be specified relative to the parent device.
49 * For accessing hardware you should use resources from the platform dev 52 * For accessing hardware you should use resources from the platform dev