ACPI: Allow drivers to match using Device Tree compatible property
authorMika Westerberg <mika.westerberg@linux.intel.com>
Tue, 21 Oct 2014 11:33:56 +0000 (13:33 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 4 Nov 2014 20:58:21 +0000 (21:58 +0100)
We have lots of existing Device Tree enabled drivers and allocating
separate _HID for each is not feasible. Instead we allocate special _HID
"PRP0001" that means that the match should be done using Device Tree
compatible property using driver's .of_match_table instead if the driver
is missing .acpi_match_table.

If there is a need to distinguish from where the device is enumerated
(DT/ACPI) driver can check dev->of_node or ACPI_COMPATION(dev).

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/acpi/property.c
drivers/acpi/scan.c
include/acpi/acpi_bus.h
include/linux/acpi.h

index 2541b1f..27add91 100644 (file)
@@ -76,6 +76,42 @@ static bool acpi_properties_format_valid(const union acpi_object *properties)
        return true;
 }
 
+static void acpi_init_of_compatible(struct acpi_device *adev)
+{
+       const union acpi_object *of_compatible;
+       struct acpi_hardware_id *hwid;
+       bool acpi_of = false;
+       int ret;
+
+       /*
+        * Check if the special PRP0001 ACPI ID is present and in that
+        * case we fill in Device Tree compatible properties for this
+        * device.
+        */
+       list_for_each_entry(hwid, &adev->pnp.ids, list) {
+               if (!strcmp(hwid->id, "PRP0001")) {
+                       acpi_of = true;
+                       break;
+               }
+       }
+
+       if (!acpi_of)
+               return;
+
+       ret = acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING,
+                                         &of_compatible);
+       if (ret) {
+               ret = acpi_dev_get_property(adev, "compatible",
+                                           ACPI_TYPE_STRING, &of_compatible);
+               if (ret) {
+                       acpi_handle_warn(adev->handle,
+                                        "PRP0001 requires compatible property\n");
+                       return;
+               }
+       }
+       adev->data.of_compatible = of_compatible;
+}
+
 void acpi_init_properties(struct acpi_device *adev)
 {
        struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
@@ -119,6 +155,8 @@ void acpi_init_properties(struct acpi_device *adev)
 
                adev->data.pointer = buf.pointer;
                adev->data.properties = properties;
+
+               acpi_init_of_compatible(adev);
                return;
        }
 
@@ -130,6 +168,7 @@ void acpi_init_properties(struct acpi_device *adev)
 void acpi_free_properties(struct acpi_device *adev)
 {
        ACPI_FREE((void *)adev->data.pointer);
+       adev->data.of_compatible = NULL;
        adev->data.pointer = NULL;
        adev->data.properties = NULL;
 }
Simple merge
Simple merge
Simple merge