Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pwm: lpss: Set enable-bit before waiting for update-bit to go low

At least on cherrytrail, the update bit will never go low when the
enabled bit is not set.

This causes the backlight on my cube iwork8 air tablet to never turn on
again after being turned off because in the pwm_lpss_apply enable path
pwm_lpss_update will fail causing an error exit and the enable-bit to
never get set. Any following pwm_lpss_apply calls will fail the
pwm_lpss_is_updating check.

Since the docs say that the update bit should be set before the
enable-bit, split pwm_lpss_update into setting the update-bit and
pwm_lpss_wait_for_update, and move the pwm_lpss_wait_for_update call
in the enable path to after setting the enable-bit.

Fixes: 10d56a4 ("pwm: lpss: Avoid reconfiguring while UPDATE bit...")
Cc: Ilkka Koskinen <ilkka.koskinen@intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>

authored by

Hans de Goede and committed by
Thierry Reding
b997e3ed 3c1460e9

+16 -6
+1
drivers/pwm/pwm-lpss-pci.c
··· 36 36 .clk_rate = 19200000, 37 37 .npwm = 4, 38 38 .base_unit_bits = 22, 39 + .bypass = true, 39 40 }; 40 41 41 42 /* Tangier */
+1
drivers/pwm/pwm-lpss-platform.c
··· 37 37 .clk_rate = 19200000, 38 38 .npwm = 4, 39 39 .base_unit_bits = 22, 40 + .bypass = true, 40 41 }; 41 42 42 43 static int pwm_lpss_probe_platform(struct platform_device *pdev)
+13 -6
drivers/pwm/pwm-lpss.c
··· 57 57 writel(value, lpwm->regs + pwm->hwpwm * PWM_SIZE + PWM); 58 58 } 59 59 60 - static int pwm_lpss_update(struct pwm_device *pwm) 60 + static int pwm_lpss_wait_for_update(struct pwm_device *pwm) 61 61 { 62 62 struct pwm_lpss_chip *lpwm = to_lpwm(pwm->chip); 63 63 const void __iomem *addr = lpwm->regs + pwm->hwpwm * PWM_SIZE + PWM; 64 64 const unsigned int ms = 500 * USEC_PER_MSEC; 65 65 u32 val; 66 66 int err; 67 - 68 - pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_SW_UPDATE); 69 67 70 68 /* 71 69 * PWM Configuration register has SW_UPDATE bit that is set when a new ··· 120 122 pwm_lpss_write(pwm, ctrl); 121 123 } 122 124 125 + static inline void pwm_lpss_cond_enable(struct pwm_device *pwm, bool cond) 126 + { 127 + if (cond) 128 + pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_ENABLE); 129 + } 130 + 123 131 static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm, 124 132 struct pwm_state *state) 125 133 { ··· 141 137 return ret; 142 138 } 143 139 pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); 144 - ret = pwm_lpss_update(pwm); 140 + pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_SW_UPDATE); 141 + pwm_lpss_cond_enable(pwm, lpwm->info->bypass == false); 142 + ret = pwm_lpss_wait_for_update(pwm); 145 143 if (ret) { 146 144 pm_runtime_put(chip->dev); 147 145 return ret; 148 146 } 149 - pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_ENABLE); 147 + pwm_lpss_cond_enable(pwm, lpwm->info->bypass == true); 150 148 } else { 151 149 ret = pwm_lpss_is_updating(pwm); 152 150 if (ret) 153 151 return ret; 154 152 pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); 155 - return pwm_lpss_update(pwm); 153 + pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_SW_UPDATE); 154 + return pwm_lpss_wait_for_update(pwm); 156 155 } 157 156 } else if (pwm_is_enabled(pwm)) { 158 157 pwm_lpss_write(pwm, pwm_lpss_read(pwm) & ~PWM_ENABLE);
+1
drivers/pwm/pwm-lpss.h
··· 22 22 unsigned long clk_rate; 23 23 unsigned int npwm; 24 24 unsigned long base_unit_bits; 25 + bool bypass; 25 26 }; 26 27 27 28 struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,