pwm: Fixes for v4.11-rc7
This contain a fix for the atomic update support recently added to the Rockchip driver where the clock reference count would become unbalanced and result in the clock feeding the PWM to always be disabled. Another fix to the Intel LPSS driver that adds an update bit quirk required for a specific configuration. -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEEiOrDCAFJzPfAjcif3SOs138+s6EFAljuaUUZHHRoaWVycnku cmVkaW5nQGdtYWlsLmNvbQAKCRDdI6zXfz6zofCcEACFRVWCoLjrHSrPsr2HhjLU 2nQTSqXKUNdSxfH9vaGdIKcbogdRDxzynolGGIAPAUo0jarJcyUlRoceH6NwwYVp 0nydLks4hPW6G5Q7R9Wu3SX74C1Wlcgzq39TneuRMUZPhcvl0kqxgIeMkaKLzsWv a4Az/SxAgREhEz6QmjYBhrL2TXsXw7O4Yz/+2tbmA2f1P33P5NRXarrdFGkvXsyu zH6vuuyCkklb4OIs+SGzGGSd9v95ROTYJJ9kvlsCDI9vkNX2XIfPUZSl+1zdOE/O BBCyTledF0gjtNpy+B3VXt8lAw0f3YjSD33Nhm7fPTARZetCo75whAQPpbB8+iam BXnfhtBHx8vliMhjwdbpRn5aRQWxIjTYiRNTaAJKwZUePl2p5dyp/FHVQNZzXyd1 b7gd3ksXCbTkvMx+yuRVbWu8klQli7lGehatRvOqONz7iUI8DImUnUEFaLM1ol0O YrKetqxAzApjCsKe4bu9Q+9YnbauzLRa+Qu1eaJ0L3n8tWC64o0uNwcwqyW9Ad/f IGbXIFA0UprOdLdz6LmlRk/e8wuhuyu8iIywM9MQ4X9DfsU+n/ZzeVixXNfWeOtV dNJ5daaucSZP9pv72Dea0ZWMX02PHv+FNw4P72A0L+Zndu2wJY3OqBfJd5yQNYDh t9WREGgKCFdBG88ww3cDcQ== =ftQo -----END PGP SIGNATURE----- Merge tag 'pwm/for-4.11-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm Pull pwm fixes from Thierry Reding: "This contain a fix for the atomic update support recently added to the Rockchip driver where the clock reference count would become unbalanced and result in the clock feeding the PWM to always be disabled. Another fix to the Intel LPSS driver that adds an update bit quirk required for a specific configuration" * tag 'pwm/for-4.11-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: pwm: rockchip: State of PWM clock should synchronize with PWM enabled state pwm: lpss: Set enable-bit before waiting for update-bit to go low pwm: lpss: Split Tangier configuration
This commit is contained in:
commit
827c30a758
|
@ -36,6 +36,14 @@ static const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = {
|
|||
.clk_rate = 19200000,
|
||||
.npwm = 4,
|
||||
.base_unit_bits = 22,
|
||||
.bypass = true,
|
||||
};
|
||||
|
||||
/* Tangier */
|
||||
static const struct pwm_lpss_boardinfo pwm_lpss_tng_info = {
|
||||
.clk_rate = 19200000,
|
||||
.npwm = 4,
|
||||
.base_unit_bits = 22,
|
||||
};
|
||||
|
||||
static int pwm_lpss_probe_pci(struct pci_dev *pdev,
|
||||
|
@ -97,7 +105,7 @@ static const struct pci_device_id pwm_lpss_pci_ids[] = {
|
|||
{ PCI_VDEVICE(INTEL, 0x0ac8), (unsigned long)&pwm_lpss_bxt_info},
|
||||
{ PCI_VDEVICE(INTEL, 0x0f08), (unsigned long)&pwm_lpss_byt_info},
|
||||
{ PCI_VDEVICE(INTEL, 0x0f09), (unsigned long)&pwm_lpss_byt_info},
|
||||
{ PCI_VDEVICE(INTEL, 0x11a5), (unsigned long)&pwm_lpss_bxt_info},
|
||||
{ PCI_VDEVICE(INTEL, 0x11a5), (unsigned long)&pwm_lpss_tng_info},
|
||||
{ PCI_VDEVICE(INTEL, 0x1ac8), (unsigned long)&pwm_lpss_bxt_info},
|
||||
{ PCI_VDEVICE(INTEL, 0x2288), (unsigned long)&pwm_lpss_bsw_info},
|
||||
{ PCI_VDEVICE(INTEL, 0x2289), (unsigned long)&pwm_lpss_bsw_info},
|
||||
|
|
|
@ -37,6 +37,7 @@ static const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = {
|
|||
.clk_rate = 19200000,
|
||||
.npwm = 4,
|
||||
.base_unit_bits = 22,
|
||||
.bypass = true,
|
||||
};
|
||||
|
||||
static int pwm_lpss_probe_platform(struct platform_device *pdev)
|
||||
|
|
|
@ -57,7 +57,7 @@ static inline void pwm_lpss_write(const struct pwm_device *pwm, u32 value)
|
|||
writel(value, lpwm->regs + pwm->hwpwm * PWM_SIZE + PWM);
|
||||
}
|
||||
|
||||
static int pwm_lpss_update(struct pwm_device *pwm)
|
||||
static int pwm_lpss_wait_for_update(struct pwm_device *pwm)
|
||||
{
|
||||
struct pwm_lpss_chip *lpwm = to_lpwm(pwm->chip);
|
||||
const void __iomem *addr = lpwm->regs + pwm->hwpwm * PWM_SIZE + PWM;
|
||||
|
@ -65,8 +65,6 @@ static int pwm_lpss_update(struct pwm_device *pwm)
|
|||
u32 val;
|
||||
int err;
|
||||
|
||||
pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_SW_UPDATE);
|
||||
|
||||
/*
|
||||
* PWM Configuration register has SW_UPDATE bit that is set when a new
|
||||
* configuration is written to the register. The bit is automatically
|
||||
|
@ -122,6 +120,12 @@ static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm,
|
|||
pwm_lpss_write(pwm, ctrl);
|
||||
}
|
||||
|
||||
static inline void pwm_lpss_cond_enable(struct pwm_device *pwm, bool cond)
|
||||
{
|
||||
if (cond)
|
||||
pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_ENABLE);
|
||||
}
|
||||
|
||||
static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
struct pwm_state *state)
|
||||
{
|
||||
|
@ -137,18 +141,21 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
|||
return ret;
|
||||
}
|
||||
pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period);
|
||||
ret = pwm_lpss_update(pwm);
|
||||
pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_SW_UPDATE);
|
||||
pwm_lpss_cond_enable(pwm, lpwm->info->bypass == false);
|
||||
ret = pwm_lpss_wait_for_update(pwm);
|
||||
if (ret) {
|
||||
pm_runtime_put(chip->dev);
|
||||
return ret;
|
||||
}
|
||||
pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_ENABLE);
|
||||
pwm_lpss_cond_enable(pwm, lpwm->info->bypass == true);
|
||||
} else {
|
||||
ret = pwm_lpss_is_updating(pwm);
|
||||
if (ret)
|
||||
return ret;
|
||||
pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period);
|
||||
return pwm_lpss_update(pwm);
|
||||
pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_SW_UPDATE);
|
||||
return pwm_lpss_wait_for_update(pwm);
|
||||
}
|
||||
} else if (pwm_is_enabled(pwm)) {
|
||||
pwm_lpss_write(pwm, pwm_lpss_read(pwm) & ~PWM_ENABLE);
|
||||
|
|
|
@ -22,6 +22,7 @@ struct pwm_lpss_boardinfo {
|
|||
unsigned long clk_rate;
|
||||
unsigned int npwm;
|
||||
unsigned long base_unit_bits;
|
||||
bool bypass;
|
||||
};
|
||||
|
||||
struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
|
||||
|
|
|
@ -191,6 +191,28 @@ static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_pwm_enable(struct pwm_chip *chip,
|
||||
struct pwm_device *pwm,
|
||||
bool enable,
|
||||
enum pwm_polarity polarity)
|
||||
{
|
||||
struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
|
||||
int ret;
|
||||
|
||||
if (enable) {
|
||||
ret = clk_enable(pc->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pc->data->set_enable(chip, pwm, enable, polarity);
|
||||
|
||||
if (!enable)
|
||||
clk_disable(pc->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
struct pwm_state *state)
|
||||
{
|
||||
|
@ -207,22 +229,26 @@ static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
|||
return ret;
|
||||
|
||||
if (state->polarity != curstate.polarity && enabled) {
|
||||
pc->data->set_enable(chip, pwm, false, state->polarity);
|
||||
ret = rockchip_pwm_enable(chip, pwm, false, state->polarity);
|
||||
if (ret)
|
||||
goto out;
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
ret = rockchip_pwm_config(chip, pwm, state->duty_cycle, state->period);
|
||||
if (ret) {
|
||||
if (enabled != curstate.enabled)
|
||||
pc->data->set_enable(chip, pwm, !enabled,
|
||||
state->polarity);
|
||||
|
||||
rockchip_pwm_enable(chip, pwm, !enabled,
|
||||
state->polarity);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (state->enabled != enabled)
|
||||
pc->data->set_enable(chip, pwm, state->enabled,
|
||||
state->polarity);
|
||||
if (state->enabled != enabled) {
|
||||
ret = rockchip_pwm_enable(chip, pwm, state->enabled,
|
||||
state->polarity);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the state with the real hardware, which can differ a bit
|
||||
|
|
Loading…
Reference in New Issue