| From 41a3da2b8e1639d983192e3650670df4ecc94cf7 Mon Sep 17 00:00:00 2001 |
| From: Heikki Krogerus <heikki.krogerus@linux.intel.com> |
| Date: Mon, 18 Apr 2016 15:14:56 +0300 |
| Subject: mfd: intel-lpss: Save register context on suspend |
| |
| From: Heikki Krogerus <heikki.krogerus@linux.intel.com> |
| |
| commit 41a3da2b8e1639d983192e3650670df4ecc94cf7 upstream. |
| |
| All configurations are lost and the registers will have |
| default values when the hardware is suspended and resumed, |
| so saving the private register space context on suspend, and |
| restoring it on resume. |
| |
| Fixes: 4b45efe85263 (mfd: Add support for Intel Sunrisepoint LPSS devices) |
| Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> |
| Signed-off-by: Lee Jones <lee.jones@linaro.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/mfd/intel-lpss.c | 19 ++++++++++++++++++- |
| 1 file changed, 18 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/mfd/intel-lpss.c |
| +++ b/drivers/mfd/intel-lpss.c |
| @@ -34,6 +34,7 @@ |
| #define LPSS_DEV_SIZE 0x200 |
| #define LPSS_PRIV_OFFSET 0x200 |
| #define LPSS_PRIV_SIZE 0x100 |
| +#define LPSS_PRIV_REG_COUNT (LPSS_PRIV_SIZE / 4) |
| #define LPSS_IDMA64_OFFSET 0x800 |
| #define LPSS_IDMA64_SIZE 0x800 |
| |
| @@ -76,6 +77,7 @@ struct intel_lpss { |
| struct mfd_cell *cell; |
| struct device *dev; |
| void __iomem *priv; |
| + u32 priv_ctx[LPSS_PRIV_REG_COUNT]; |
| int devid; |
| u32 caps; |
| u32 active_ltr; |
| @@ -493,6 +495,16 @@ EXPORT_SYMBOL_GPL(intel_lpss_prepare); |
| |
| int intel_lpss_suspend(struct device *dev) |
| { |
| + struct intel_lpss *lpss = dev_get_drvdata(dev); |
| + unsigned int i; |
| + |
| + /* Save device context */ |
| + for (i = 0; i < LPSS_PRIV_REG_COUNT; i++) |
| + lpss->priv_ctx[i] = readl(lpss->priv + i * 4); |
| + |
| + /* Put the device into reset state */ |
| + writel(0, lpss->priv + LPSS_PRIV_RESETS); |
| + |
| return 0; |
| } |
| EXPORT_SYMBOL_GPL(intel_lpss_suspend); |
| @@ -500,8 +512,13 @@ EXPORT_SYMBOL_GPL(intel_lpss_suspend); |
| int intel_lpss_resume(struct device *dev) |
| { |
| struct intel_lpss *lpss = dev_get_drvdata(dev); |
| + unsigned int i; |
| |
| - intel_lpss_init_dev(lpss); |
| + intel_lpss_deassert_reset(lpss); |
| + |
| + /* Restore device context */ |
| + for (i = 0; i < LPSS_PRIV_REG_COUNT; i++) |
| + writel(lpss->priv_ctx[i], lpss->priv + i * 4); |
| |
| return 0; |
| } |