]> Pileus Git - ~andy/linux/blobdiff - drivers/acpi/acpi_platform.c
Merge git://git.infradead.org/users/willy/linux-nvme
[~andy/linux] / drivers / acpi / acpi_platform.c
index db129b9f52cba6c8634439fd2f753ec10bc1246e..26fce4b8a632a3b8537f4baa16ae36f84d6530d1 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/acpi.h>
 #include <linux/device.h>
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
 ACPI_MODULE_NAME("platform");
 
+/* Flags for acpi_create_platform_device */
+#define ACPI_PLATFORM_CLK      BIT(0)
+
+/*
+ * The following ACPI IDs are known to be suitable for representing as
+ * platform devices.
+ */
+static const struct acpi_device_id acpi_platform_device_ids[] = {
+
+       { "PNP0D40" },
+
+       /* Haswell LPSS devices */
+       { "INT33C0", ACPI_PLATFORM_CLK },
+       { "INT33C1", ACPI_PLATFORM_CLK },
+       { "INT33C2", ACPI_PLATFORM_CLK },
+       { "INT33C3", ACPI_PLATFORM_CLK },
+       { "INT33C4", ACPI_PLATFORM_CLK },
+       { "INT33C5", ACPI_PLATFORM_CLK },
+       { "INT33C6", ACPI_PLATFORM_CLK },
+       { "INT33C7", ACPI_PLATFORM_CLK },
+
+       { }
+};
+
+static int acpi_create_platform_clks(struct acpi_device *adev)
+{
+       static struct platform_device *pdev;
+
+       /* Create Lynxpoint LPSS clocks */
+       if (!pdev && !strncmp(acpi_device_hid(adev), "INT33C", 6)) {
+               pdev = platform_device_register_simple("clk-lpt", -1, NULL, 0);
+               if (IS_ERR(pdev))
+                       return PTR_ERR(pdev);
+       }
+
+       return 0;
+}
+
 /**
  * acpi_create_platform_device - Create platform device for ACPI device node
  * @adev: ACPI device node to create a platform device for.
+ * @id: ACPI device ID used to match @adev.
  *
  * Check if the given @adev can be represented as a platform device and, if
  * that's the case, create and register a platform device, populate its common
  * resources and returns a pointer to it.  Otherwise, return %NULL.
  *
- * The platform device's name will be taken from the @adev's _HID and _UID.
+ * Name of the platform device will be the same as @adev's.
  */
-struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
+static int acpi_create_platform_device(struct acpi_device *adev,
+                                      const struct acpi_device_id *id)
 {
+       unsigned long flags = id->driver_data;
        struct platform_device *pdev = NULL;
        struct acpi_device *acpi_parent;
        struct platform_device_info pdevinfo;
@@ -41,20 +83,28 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
        struct resource *resources;
        int count;
 
+       if (flags & ACPI_PLATFORM_CLK) {
+               int ret = acpi_create_platform_clks(adev);
+               if (ret) {
+                       dev_err(&adev->dev, "failed to create clocks\n");
+                       return ret;
+               }
+       }
+
        /* If the ACPI node already has a physical device attached, skip it. */
        if (adev->physical_node_count)
-               return NULL;
+               return 0;
 
        INIT_LIST_HEAD(&resource_list);
        count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
        if (count <= 0)
-               return NULL;
+               return 0;
 
        resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL);
        if (!resources) {
                dev_err(&adev->dev, "No memory for resources\n");
                acpi_dev_free_resource_list(&resource_list);
-               return NULL;
+               return -ENOMEM;
        }
        count = 0;
        list_for_each_entry(rentry, &resource_list, node)
@@ -100,5 +150,15 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
        }
 
        kfree(resources);
-       return pdev;
+       return 1;
+}
+
+static struct acpi_scan_handler platform_handler = {
+       .ids = acpi_platform_device_ids,
+       .attach = acpi_create_platform_device,
+};
+
+void __init acpi_platform_init(void)
+{
+       acpi_scan_add_handler(&platform_handler);
 }