|
@@ -82,29 +82,49 @@ 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);
|
|
|
|
- if (!parent_adev)
|
|
|
|
|
|
+ parent = ACPI_COMPANION(pdev->dev.parent);
|
|
|
|
+ if (!parent)
|
|
return;
|
|
return;
|
|
|
|
|
|
/*
|
|
/*
|
|
- * MFD child device gets its ACPI handle either from the ACPI
|
|
|
|
- * device directly under the parent that matches the acpi_pnpid or
|
|
|
|
- * it will use the parent handle if is no acpi_pnpid is given.
|
|
|
|
|
|
+ * MFD child device gets its ACPI handle either from the ACPI device
|
|
|
|
+ * directly under the parent that matches the either _HID or _CID, or
|
|
|
|
+ * _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;
|
|
|
|
- if (cell->acpi_pnpid) {
|
|
|
|
- struct acpi_device_id ids[2] = {};
|
|
|
|
- struct acpi_device *child_adev;
|
|
|
|
-
|
|
|
|
- strlcpy(ids[0].id, cell->acpi_pnpid, sizeof(ids[0].id));
|
|
|
|
- list_for_each_entry(child_adev, &parent_adev->children, node)
|
|
|
|
- if (acpi_match_device_ids(child_adev, ids)) {
|
|
|
|
- adev = child_adev;
|
|
|
|
- break;
|
|
|
|
|
|
+ adev = parent;
|
|
|
|
+ if (match) {
|
|
|
|
+ if (match->pnpid) {
|
|
|
|
+ struct acpi_device_id ids[2] = {};
|
|
|
|
+
|
|
|
|
+ strlcpy(ids[0].id, match->pnpid, sizeof(ids[0].id));
|
|
|
|
+ list_for_each_entry(child, &parent->children, node) {
|
|
|
|
+ if (acpi_match_device_ids(child, ids)) {
|
|
|
|
+ adev = child;
|
|
|
|
+ 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);
|