Skip to content

Commit 6ab3430

Browse files
westeriLee Jones
authored andcommitted
mfd: Add ACPI support
If an MFD device is backed by ACPI namespace, we should allow subdevice drivers to access their corresponding ACPI companion devices through normal means (e.g using ACPI_COMPANION()). This patch adds such support to the MFD core. If the MFD parent device does not specify any ACPI _HID/_CID for the child device, the child device will share the parent ACPI companion device. Otherwise the child device will be assigned with the corresponding ACPI companion, if found in the namespace below the parent. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Darren Hart <dvhart@linux.intel.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
1 parent 7be180c commit 6ab3430

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

Documentation/acpi/enumeration.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,3 +312,30 @@ a code like this:
312312

313313
There are also devm_* versions of these functions which release the
314314
descriptors once the device is released.
315+
316+
MFD devices
317+
~~~~~~~~~~~
318+
The MFD devices register their children as platform devices. For the child
319+
devices there needs to be an ACPI handle that they can use to reference
320+
parts of the ACPI namespace that relate to them. In the Linux MFD subsystem
321+
we 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+
326+
For the first case, the MFD drivers do not need to do anything. The
327+
resulting child platform device will have its ACPI_COMPANION() set to point
328+
to the parent device.
329+
330+
If the ACPI namespace has a device that we can match using an ACPI id,
331+
the 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+
339+
The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under
340+
the MFD device and if found, that ACPI companion device is bound to the
341+
resulting child platform device.

drivers/mfd/mfd-core.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,44 @@ static int mfd_platform_add_cell(struct platform_device *pdev,
7878
return 0;
7979
}
8080

81+
#if IS_ENABLED(CONFIG_ACPI)
82+
static 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
113+
static inline void mfd_acpi_add_device(const struct mfd_cell *cell,
114+
struct platform_device *pdev)
115+
{
116+
}
117+
#endif
118+
81119
static int mfd_add_device(struct device *parent, int id,
82120
const struct mfd_cell *cell, atomic_t *usage_count,
83121
struct resource *mem_base,
@@ -119,6 +157,8 @@ static int mfd_add_device(struct device *parent, int id,
119157
}
120158
}
121159

160+
mfd_acpi_add_device(cell, pdev);
161+
122162
if (cell->pdata_size) {
123163
ret = platform_device_add_data(pdev,
124164
cell->platform_data, cell->pdata_size);

include/linux/mfd/core.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ struct mfd_cell {
4444
*/
4545
const char *of_compatible;
4646

47+
/* Matches ACPI PNP id, either _HID or _CID */
48+
const char *acpi_pnpid;
49+
4750
/*
4851
* These resources can be specified relative to the parent device.
4952
* For accessing hardware you should use resources from the platform dev

0 commit comments

Comments
 (0)