ACPI / platform: create LPSS clocks if Lynxpoint devices are found during scan

Intel Lynxpoint LPSS peripheral drivers depend on LPSS clock tree being
created in order to function properly. The clock tree is exposed as a
platform driver that binds to a device named 'clk-lpt'.

To support this we modify the acpi_create_platform_device() to take one
additional parameter called flags. This is passed from
acpi_platform_device_ids[] array when acpi_create_platform_device() is
called.

We then introduce a new flag ACPI_PLATFORM_CLK which is used to tell
acpi_create_platform_device() to create the platform clocks as well.

Finally we set the ACPI_PLATFORM_CLK flags for all the Lynxpoint LPSS
devices and make sure that when this flag is set we create the
corresponding clock tree platform device.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Mika Westerberg 2013-01-18 13:46:01 +00:00 committed by Rafael J. Wysocki
parent 701190fd74
commit e375325ce5
3 changed files with 41 additions and 12 deletions

View 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>
@ -21,9 +22,25 @@
ACPI_MODULE_NAME("platform");
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.
* @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
* devices.
*
* 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
@ -31,7 +48,8 @@ ACPI_MODULE_NAME("platform");
*
* Name of the platform device will be the same as @adev's.
*/
struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
unsigned long flags)
{
struct platform_device *pdev = NULL;
struct acpi_device *acpi_parent;
@ -41,6 +59,11 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
struct resource *resources;
int count;
if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
dev_err(&adev->dev, "failed to create clocks\n");
return NULL;
}
/* If the ACPI node already has a physical device attached, skip it. */
if (adev->physical_node_count)
return NULL;

View File

@ -100,6 +100,10 @@ static inline void suspend_nvs_restore(void) {}
-------------------------------------------------------------------------- */
struct platform_device;
struct platform_device *acpi_create_platform_device(struct acpi_device *adev);
/* Flags for acpi_create_platform_device */
#define ACPI_PLATFORM_CLK BIT(0)
struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
unsigned long flags);
#endif /* _ACPI_INTERNAL_H_ */

View File

@ -38,14 +38,14 @@ static const struct acpi_device_id acpi_platform_device_ids[] = {
{ "PNP0D40" },
/* Haswell LPSS devices */
{ "INT33C0", 0 },
{ "INT33C1", 0 },
{ "INT33C2", 0 },
{ "INT33C3", 0 },
{ "INT33C4", 0 },
{ "INT33C5", 0 },
{ "INT33C6", 0 },
{ "INT33C7", 0 },
{ "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 },
{ }
};
@ -1553,6 +1553,7 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
void *not_used, void **ret_not_used)
{
const struct acpi_device_id *id;
acpi_status status = AE_OK;
struct acpi_device *device;
unsigned long long sta_not_used;
@ -1568,9 +1569,10 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
if (acpi_bus_get_device(handle, &device))
return AE_CTRL_DEPTH;
if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
id = __acpi_match_device(device, acpi_platform_device_ids);
if (id) {
/* This is a known good platform device. */
acpi_create_platform_device(device);
acpi_create_platform_device(device, id->driver_data);
} else if (device_attach(&device->dev) < 0) {
status = AE_CTRL_DEPTH;
}