Received: by 2002:ac0:a581:0:0:0:0:0 with SMTP id m1-v6csp2991812imm; Sun, 1 Jul 2018 09:52:51 -0700 (PDT) X-Google-Smtp-Source: ADUXVKK1n9oi1MHjkpg6G/nkbn1LGfADjHGutVvTV3xSsiW1FmJVKyYi4Xgz9Zyt5w5qyx0BSSd2 X-Received: by 2002:a17:902:7896:: with SMTP id q22-v6mr22150340pll.243.1530463971933; Sun, 01 Jul 2018 09:52:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1530463971; cv=none; d=google.com; s=arc-20160816; b=XVJgr8y4ufXkyGdCYBoxKqspbUdJTop8mQFHelymG2xS7n6ZSzxWhad/sCc5+xTWgF RSZc2nFZay+DY0nokztxQhHO1kX0MEsUPzYPYXpksiZYlHA+Irz/vM8hQukh1aX4QvsJ XtHle+bOwkj9EcI/n4oiP2L+9jLIB6D1F/AGCa4+lrJ0Z0zsIrhj9sMuSt8wIu+e6HOy JCYurDz9s/+5QIov5uFk0f1cx5+49TsS+wr4QLORk6WlLUcnrQ1swYihvQWOpg8m+vwm pamAZin53feAV0zmmDyEJ8kKpJd1MLDBWwpROB8/JG92BE4NVOM/sGGlDepywieCyzGI NK3w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=aar8hnOexP0M5tw+B8yweTMGeWYQFAfPDaXTVaJLcdI=; b=08MZcTHmIWMc8IU6DKM/iIymSPvVi5yocy4JwDID+Xcn2OGwYSUudg7fIf51iAPOM7 iMDuN1KAyBCOBtX/wRzDG0n24D5AeXeIjG2lppUYpoACIBtuVy28w0dB4To5yNQbg6jQ PBa/iS+g8ik9Tyk/8sclnJz/62XuO9WwdEyZfH7cTugVesCBI8zfHuyoRHlAknqj4xG2 qtG/P4oVHouSrA6OVQGdzHFvNfpBQttnIh0AHqJZounz9J5f50OyoXTbvCtM9Me8epLv mE4TwF4xfIDPokuE7OlNu8gSb3iSpsFYuaD2kgigiwZSn7ryqNSdHQ+NvCUJOy24FJMQ 44qg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b5-v6si9090444pfo.54.2018.07.01.09.52.37; Sun, 01 Jul 2018 09:52:51 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753763AbeGAQqf (ORCPT + 99 others); Sun, 1 Jul 2018 12:46:35 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:38462 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753716AbeGAQqc (ORCPT ); Sun, 1 Jul 2018 12:46:32 -0400 Received: from localhost (LFbn-1-12247-202.w90-92.abo.wanadoo.fr [90.92.61.202]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id E1704ACC; Sun, 1 Jul 2018 16:46:31 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Hans de Goede , Andy Shevchenko , Thierry Reding Subject: [PATCH 4.17 188/220] pwm: lpss: platform: Save/restore the ctrl register over a suspend/resume Date: Sun, 1 Jul 2018 18:23:32 +0200 Message-Id: <20180701160916.057353759@linuxfoundation.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180701160908.272447118@linuxfoundation.org> References: <20180701160908.272447118@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.17-stable review patch. If anyone has any objections, please let me know. ------------------ From: Hans de Goede commit 1d375b58c12f08d8570b30b865def4734517f04f upstream. On some devices the contents of the ctrl register get lost over a suspend/resume and the PWM comes back up disabled after the resume. This is seen on some Bay Trail devices with the PWM in ACPI enumerated mode, so it shows up as a platform device instead of a PCI device. If we still think it is enabled and then try to change the duty-cycle after this, we end up with a "PWM_SW_UPDATE was not cleared" error and the PWM is stuck in that state from then on. This commit adds suspend and resume pm callbacks to the pwm-lpss-platform code, which save/restore the ctrl register over a suspend/resume, fixing this. Note that: 1) There is no need to do this over a runtime suspend, since we only runtime suspend when disabled and then we properly set the enable bit and reprogram the timings when we re-enable the PWM. 2) This may be happening on more systems then we realize, but has been covered up sofar by a bug in the acpi-lpss.c code which was save/restoring the regular device registers instead of the lpss private registers due to lpss_device_desc.prv_offset not being set. This is fixed by a later patch in this series. Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Thierry Reding Signed-off-by: Greg Kroah-Hartman --- drivers/pwm/pwm-lpss-platform.c | 5 +++++ drivers/pwm/pwm-lpss.c | 30 ++++++++++++++++++++++++++++++ drivers/pwm/pwm-lpss.h | 2 ++ 3 files changed, 37 insertions(+) --- a/drivers/pwm/pwm-lpss-platform.c +++ b/drivers/pwm/pwm-lpss-platform.c @@ -74,6 +74,10 @@ static int pwm_lpss_remove_platform(stru return pwm_lpss_remove(lpwm); } +static SIMPLE_DEV_PM_OPS(pwm_lpss_platform_pm_ops, + pwm_lpss_suspend, + pwm_lpss_resume); + static const struct acpi_device_id pwm_lpss_acpi_match[] = { { "80860F09", (unsigned long)&pwm_lpss_byt_info }, { "80862288", (unsigned long)&pwm_lpss_bsw_info }, @@ -86,6 +90,7 @@ static struct platform_driver pwm_lpss_d .driver = { .name = "pwm-lpss", .acpi_match_table = pwm_lpss_acpi_match, + .pm = &pwm_lpss_platform_pm_ops, }, .probe = pwm_lpss_probe_platform, .remove = pwm_lpss_remove_platform, --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c @@ -32,10 +32,13 @@ /* Size of each PWM register space if multiple */ #define PWM_SIZE 0x400 +#define MAX_PWMS 4 + struct pwm_lpss_chip { struct pwm_chip chip; void __iomem *regs; const struct pwm_lpss_boardinfo *info; + u32 saved_ctrl[MAX_PWMS]; }; static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip) @@ -177,6 +180,9 @@ struct pwm_lpss_chip *pwm_lpss_probe(str unsigned long c; int ret; + if (WARN_ON(info->npwm > MAX_PWMS)) + return ERR_PTR(-ENODEV); + lpwm = devm_kzalloc(dev, sizeof(*lpwm), GFP_KERNEL); if (!lpwm) return ERR_PTR(-ENOMEM); @@ -212,6 +218,30 @@ int pwm_lpss_remove(struct pwm_lpss_chip } EXPORT_SYMBOL_GPL(pwm_lpss_remove); +int pwm_lpss_suspend(struct device *dev) +{ + struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev); + int i; + + for (i = 0; i < lpwm->info->npwm; i++) + lpwm->saved_ctrl[i] = readl(lpwm->regs + i * PWM_SIZE + PWM); + + return 0; +} +EXPORT_SYMBOL_GPL(pwm_lpss_suspend); + +int pwm_lpss_resume(struct device *dev) +{ + struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev); + int i; + + for (i = 0; i < lpwm->info->npwm; i++) + writel(lpwm->saved_ctrl[i], lpwm->regs + i * PWM_SIZE + PWM); + + return 0; +} +EXPORT_SYMBOL_GPL(pwm_lpss_resume); + MODULE_DESCRIPTION("PWM driver for Intel LPSS"); MODULE_AUTHOR("Mika Westerberg "); MODULE_LICENSE("GPL v2"); --- a/drivers/pwm/pwm-lpss.h +++ b/drivers/pwm/pwm-lpss.h @@ -28,5 +28,7 @@ struct pwm_lpss_boardinfo { struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, const struct pwm_lpss_boardinfo *info); int pwm_lpss_remove(struct pwm_lpss_chip *lpwm); +int pwm_lpss_suspend(struct device *dev); +int pwm_lpss_resume(struct device *dev); #endif /* __PWM_LPSS_H */