diff options
Diffstat (limited to 'drivers/acpi/acpi_lpss.c')
-rw-r--r-- | drivers/acpi/acpi_lpss.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 4804ae31b057..d1dd0ada14b7 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ACPI support for Intel Lynxpoint LPSS. | 2 | * ACPI support for Intel Lynxpoint LPSS. |
3 | * | 3 | * |
4 | * Copyright (C) 2013, Intel Corporation | 4 | * Copyright (C) 2013, 2014, Intel Corporation |
5 | * Authors: Mika Westerberg <mika.westerberg@linux.intel.com> | 5 | * Authors: Mika Westerberg <mika.westerberg@linux.intel.com> |
6 | * Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 6 | * Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
7 | * | 7 | * |
@@ -60,6 +60,8 @@ ACPI_MODULE_NAME("acpi_lpss"); | |||
60 | #define LPSS_CLK_DIVIDER BIT(2) | 60 | #define LPSS_CLK_DIVIDER BIT(2) |
61 | #define LPSS_LTR BIT(3) | 61 | #define LPSS_LTR BIT(3) |
62 | #define LPSS_SAVE_CTX BIT(4) | 62 | #define LPSS_SAVE_CTX BIT(4) |
63 | #define LPSS_DEV_PROXY BIT(5) | ||
64 | #define LPSS_PROXY_REQ BIT(6) | ||
63 | 65 | ||
64 | struct lpss_private_data; | 66 | struct lpss_private_data; |
65 | 67 | ||
@@ -70,8 +72,10 @@ struct lpss_device_desc { | |||
70 | void (*setup)(struct lpss_private_data *pdata); | 72 | void (*setup)(struct lpss_private_data *pdata); |
71 | }; | 73 | }; |
72 | 74 | ||
75 | static struct device *proxy_device; | ||
76 | |||
73 | static struct lpss_device_desc lpss_dma_desc = { | 77 | static struct lpss_device_desc lpss_dma_desc = { |
74 | .flags = LPSS_CLK, | 78 | .flags = LPSS_CLK | LPSS_PROXY_REQ, |
75 | }; | 79 | }; |
76 | 80 | ||
77 | struct lpss_private_data { | 81 | struct lpss_private_data { |
@@ -146,22 +150,24 @@ static struct lpss_device_desc byt_pwm_dev_desc = { | |||
146 | }; | 150 | }; |
147 | 151 | ||
148 | static struct lpss_device_desc byt_uart_dev_desc = { | 152 | static struct lpss_device_desc byt_uart_dev_desc = { |
149 | .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX, | 153 | .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX | |
154 | LPSS_DEV_PROXY, | ||
150 | .prv_offset = 0x800, | 155 | .prv_offset = 0x800, |
151 | .setup = lpss_uart_setup, | 156 | .setup = lpss_uart_setup, |
152 | }; | 157 | }; |
153 | 158 | ||
154 | static struct lpss_device_desc byt_spi_dev_desc = { | 159 | static struct lpss_device_desc byt_spi_dev_desc = { |
155 | .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX, | 160 | .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX | |
161 | LPSS_DEV_PROXY, | ||
156 | .prv_offset = 0x400, | 162 | .prv_offset = 0x400, |
157 | }; | 163 | }; |
158 | 164 | ||
159 | static struct lpss_device_desc byt_sdio_dev_desc = { | 165 | static struct lpss_device_desc byt_sdio_dev_desc = { |
160 | .flags = LPSS_CLK, | 166 | .flags = LPSS_CLK | LPSS_DEV_PROXY, |
161 | }; | 167 | }; |
162 | 168 | ||
163 | static struct lpss_device_desc byt_i2c_dev_desc = { | 169 | static struct lpss_device_desc byt_i2c_dev_desc = { |
164 | .flags = LPSS_CLK | LPSS_SAVE_CTX, | 170 | .flags = LPSS_CLK | LPSS_SAVE_CTX | LPSS_DEV_PROXY, |
165 | .prv_offset = 0x800, | 171 | .prv_offset = 0x800, |
166 | .setup = byt_i2c_setup, | 172 | .setup = byt_i2c_setup, |
167 | }; | 173 | }; |
@@ -368,6 +374,8 @@ static int acpi_lpss_create_device(struct acpi_device *adev, | |||
368 | adev->driver_data = pdata; | 374 | adev->driver_data = pdata; |
369 | pdev = acpi_create_platform_device(adev); | 375 | pdev = acpi_create_platform_device(adev); |
370 | if (!IS_ERR_OR_NULL(pdev)) { | 376 | if (!IS_ERR_OR_NULL(pdev)) { |
377 | if (!proxy_device && dev_desc->flags & LPSS_DEV_PROXY) | ||
378 | proxy_device = &pdev->dev; | ||
371 | return 1; | 379 | return 1; |
372 | } | 380 | } |
373 | 381 | ||
@@ -593,7 +601,14 @@ static int acpi_lpss_runtime_suspend(struct device *dev) | |||
593 | if (pdata->dev_desc->flags & LPSS_SAVE_CTX) | 601 | if (pdata->dev_desc->flags & LPSS_SAVE_CTX) |
594 | acpi_lpss_save_ctx(dev, pdata); | 602 | acpi_lpss_save_ctx(dev, pdata); |
595 | 603 | ||
596 | return acpi_dev_runtime_suspend(dev); | 604 | ret = acpi_dev_runtime_suspend(dev); |
605 | if (ret) | ||
606 | return ret; | ||
607 | |||
608 | if (pdata->dev_desc->flags & LPSS_PROXY_REQ && proxy_device) | ||
609 | return pm_runtime_put_sync_suspend(proxy_device); | ||
610 | |||
611 | return 0; | ||
597 | } | 612 | } |
598 | 613 | ||
599 | static int acpi_lpss_runtime_resume(struct device *dev) | 614 | static int acpi_lpss_runtime_resume(struct device *dev) |
@@ -601,6 +616,12 @@ static int acpi_lpss_runtime_resume(struct device *dev) | |||
601 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); | 616 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); |
602 | int ret; | 617 | int ret; |
603 | 618 | ||
619 | if (pdata->dev_desc->flags & LPSS_PROXY_REQ && proxy_device) { | ||
620 | ret = pm_runtime_get_sync(proxy_device); | ||
621 | if (ret) | ||
622 | return ret; | ||
623 | } | ||
624 | |||
604 | ret = acpi_dev_runtime_resume(dev); | 625 | ret = acpi_dev_runtime_resume(dev); |
605 | if (ret) | 626 | if (ret) |
606 | return ret; | 627 | return ret; |