ACPI / LPSS: Power up LPSS devices during enumeration
Commit 7cd8407
(ACPI / PM: Do not execute _PS0 for devices without
_PSC during initialization) introduced a regression on some systems
with Intel Lynxpoint Low-Power Subsystem (LPSS) where some devices
need to be powered up during initialization, but their device objects
in the ACPI namespace have _PS0 and _PS3 only (without _PSC or power
resources).
To work around this problem, make the ACPI LPSS driver power up
devices it knows about by using a new helper function
acpi_device_fix_up_power() that does all of the necessary
sanity checks and calls acpi_dev_pm_explicit_set() to put the
device into D0.
Reported-and-tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Родитель
6ee22e9d59
Коммит
b9e95fc65e
|
@ -164,15 +164,24 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
|
||||||
if (dev_desc->clk_required) {
|
if (dev_desc->clk_required) {
|
||||||
ret = register_device_clock(adev, pdata);
|
ret = register_device_clock(adev, pdata);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/*
|
/* Skip the device, but continue the namespace scan. */
|
||||||
* Skip the device, but don't terminate the namespace
|
ret = 0;
|
||||||
* scan.
|
goto err_out;
|
||||||
*/
|
|
||||||
kfree(pdata);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This works around a known issue in ACPI tables where LPSS devices
|
||||||
|
* have _PS0 and _PS3 without _PSC (and no power resources), so
|
||||||
|
* acpi_bus_init_power() will assume that the BIOS has put them into D0.
|
||||||
|
*/
|
||||||
|
ret = acpi_device_fix_up_power(adev);
|
||||||
|
if (ret) {
|
||||||
|
/* Skip the device, but continue the namespace scan. */
|
||||||
|
ret = 0;
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
adev->driver_data = pdata;
|
adev->driver_data = pdata;
|
||||||
ret = acpi_create_platform_device(adev, id);
|
ret = acpi_create_platform_device(adev, id);
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
|
|
|
@ -290,6 +290,26 @@ int acpi_bus_init_power(struct acpi_device *device)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* acpi_device_fix_up_power - Force device with missing _PSC into D0.
|
||||||
|
* @device: Device object whose power state is to be fixed up.
|
||||||
|
*
|
||||||
|
* Devices without power resources and _PSC, but having _PS0 and _PS3 defined,
|
||||||
|
* are assumed to be put into D0 by the BIOS. However, in some cases that may
|
||||||
|
* not be the case and this function should be used then.
|
||||||
|
*/
|
||||||
|
int acpi_device_fix_up_power(struct acpi_device *device)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!device->power.flags.power_resources
|
||||||
|
&& !device->power.flags.explicit_get
|
||||||
|
&& device->power.state == ACPI_STATE_D0)
|
||||||
|
ret = acpi_dev_pm_explicit_set(device, ACPI_STATE_D0);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int acpi_bus_update_power(acpi_handle handle, int *state_p)
|
int acpi_bus_update_power(acpi_handle handle, int *state_p)
|
||||||
{
|
{
|
||||||
struct acpi_device *device;
|
struct acpi_device *device;
|
||||||
|
|
|
@ -382,6 +382,7 @@ const char *acpi_power_state_string(int state);
|
||||||
int acpi_device_get_power(struct acpi_device *device, int *state);
|
int acpi_device_get_power(struct acpi_device *device, int *state);
|
||||||
int acpi_device_set_power(struct acpi_device *device, int state);
|
int acpi_device_set_power(struct acpi_device *device, int state);
|
||||||
int acpi_bus_init_power(struct acpi_device *device);
|
int acpi_bus_init_power(struct acpi_device *device);
|
||||||
|
int acpi_device_fix_up_power(struct acpi_device *device);
|
||||||
int acpi_bus_update_power(acpi_handle handle, int *state_p);
|
int acpi_bus_update_power(acpi_handle handle, int *state_p);
|
||||||
bool acpi_bus_power_manageable(acpi_handle handle);
|
bool acpi_bus_power_manageable(acpi_handle handle);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче