mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-04-09 13:28:01 +07:00
mfd: core: redo ACPI matching of the children devices
There is at least one board on the market, i.e. Intel Galileo Gen2, that uses _ADR to distinguish the devices under one actual device. Due to this we have to improve the quirk in the MFD core to handle that board. Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
This commit is contained in:
parent
049e6dde7e
commit
98a3be44ff
@ -347,13 +347,18 @@ For the first case, the MFD drivers do not need to do anything. The
|
|||||||
resulting child platform device will have its ACPI_COMPANION() set to point
|
resulting child platform device will have its ACPI_COMPANION() set to point
|
||||||
to the parent device.
|
to the parent device.
|
||||||
|
|
||||||
If the ACPI namespace has a device that we can match using an ACPI id,
|
If the ACPI namespace has a device that we can match using an ACPI id or ACPI
|
||||||
the id should be set like:
|
adr, the cell should be set like:
|
||||||
|
|
||||||
|
static struct mfd_cell_acpi_match my_subdevice_cell_acpi_match = {
|
||||||
|
.pnpid = "XYZ0001",
|
||||||
|
.adr = 0,
|
||||||
|
};
|
||||||
|
|
||||||
static struct mfd_cell my_subdevice_cell = {
|
static struct mfd_cell my_subdevice_cell = {
|
||||||
.name = "my_subdevice",
|
.name = "my_subdevice",
|
||||||
/* set the resources relative to the parent */
|
/* set the resources relative to the parent */
|
||||||
.acpi_pnpid = "XYZ0001",
|
.acpi_match = &my_subdevice_cell_acpi_match,
|
||||||
};
|
};
|
||||||
|
|
||||||
The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under
|
The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under
|
||||||
|
@ -82,30 +82,50 @@ static int mfd_platform_add_cell(struct platform_device *pdev,
|
|||||||
static void mfd_acpi_add_device(const struct mfd_cell *cell,
|
static void mfd_acpi_add_device(const struct mfd_cell *cell,
|
||||||
struct platform_device *pdev)
|
struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct acpi_device *parent_adev;
|
const struct mfd_cell_acpi_match *match = cell->acpi_match;
|
||||||
|
struct acpi_device *parent, *child;
|
||||||
struct acpi_device *adev;
|
struct acpi_device *adev;
|
||||||
|
|
||||||
parent_adev = ACPI_COMPANION(pdev->dev.parent);
|
parent = ACPI_COMPANION(pdev->dev.parent);
|
||||||
if (!parent_adev)
|
if (!parent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MFD child device gets its ACPI handle either from the ACPI
|
* MFD child device gets its ACPI handle either from the ACPI device
|
||||||
* device directly under the parent that matches the acpi_pnpid or
|
* directly under the parent that matches the either _HID or _CID, or
|
||||||
* it will use the parent handle if is no acpi_pnpid is given.
|
* _ADR or it will use the parent handle if is no ID is given.
|
||||||
|
*
|
||||||
|
* Note that use of _ADR is a grey area in the ACPI specification,
|
||||||
|
* though Intel Galileo Gen2 is using it to distinguish the children
|
||||||
|
* devices.
|
||||||
*/
|
*/
|
||||||
adev = parent_adev;
|
adev = parent;
|
||||||
if (cell->acpi_pnpid) {
|
if (match) {
|
||||||
|
if (match->pnpid) {
|
||||||
struct acpi_device_id ids[2] = {};
|
struct acpi_device_id ids[2] = {};
|
||||||
struct acpi_device *child_adev;
|
|
||||||
|
|
||||||
strlcpy(ids[0].id, cell->acpi_pnpid, sizeof(ids[0].id));
|
strlcpy(ids[0].id, match->pnpid, sizeof(ids[0].id));
|
||||||
list_for_each_entry(child_adev, &parent_adev->children, node)
|
list_for_each_entry(child, &parent->children, node) {
|
||||||
if (acpi_match_device_ids(child_adev, ids)) {
|
if (acpi_match_device_ids(child, ids)) {
|
||||||
adev = child_adev;
|
adev = child;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
unsigned long long adr;
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
list_for_each_entry(child, &parent->children, node) {
|
||||||
|
status = acpi_evaluate_integer(child->handle,
|
||||||
|
"_ADR", NULL,
|
||||||
|
&adr);
|
||||||
|
if (ACPI_SUCCESS(status) && match->adr == adr) {
|
||||||
|
adev = child;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ACPI_COMPANION_SET(&pdev->dev, adev);
|
ACPI_COMPANION_SET(&pdev->dev, adev);
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,12 @@
|
|||||||
|
|
||||||
struct irq_domain;
|
struct irq_domain;
|
||||||
|
|
||||||
|
/* Matches ACPI PNP id, either _HID or _CID, or ACPI _ADR */
|
||||||
|
struct mfd_cell_acpi_match {
|
||||||
|
const char *pnpid;
|
||||||
|
const unsigned long long adr;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This struct describes the MFD part ("cell").
|
* This struct describes the MFD part ("cell").
|
||||||
* After registration the copy of this structure will become the platform data
|
* After registration the copy of this structure will become the platform data
|
||||||
@ -44,8 +50,8 @@ struct mfd_cell {
|
|||||||
*/
|
*/
|
||||||
const char *of_compatible;
|
const char *of_compatible;
|
||||||
|
|
||||||
/* Matches ACPI PNP id, either _HID or _CID */
|
/* Matches ACPI */
|
||||||
const char *acpi_pnpid;
|
const struct mfd_cell_acpi_match *acpi_match;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These resources can be specified relative to the parent device.
|
* These resources can be specified relative to the parent device.
|
||||||
|
Loading…
Reference in New Issue
Block a user