Commit 6701e7e7 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pwm/for-5.15-rc1' of...

Merge tag 'pwm/for-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm

Pull pwm updates from Thierry Reding:
 "The changes this time around are mostly janitorial in nature. A lot of
  this is simplifications of drivers using device-managed functions and
  improving compilation coverage.

  The Mediatek display PWM driver now supports the atomic API.

  Cleanups and minor fixes make up the remainder of this set"

* tag 'pwm/for-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: (54 commits)
  pwm: mtk-disp: Implement atomic API .get_state()
  pwm: mtk-disp: Fix overflow in period and duty calculation
  pwm: mtk-disp: Implement atomic API .apply()
  pwm: mtk-disp: Adjust the clocks to avoid them mismatch
  dt-bindings: pwm: rockchip: Add description for rk3568
  pwm: Make pwmchip_remove() return void
  pwm: sun4i: Don't check the return code of pwmchip_remove()
  pwm: sifive: Don't check the return code of pwmchip_remove()
  pwm: samsung: Don't check the return code of pwmchip_remove()
  pwm: renesas-tpu: Don't check the return code of pwmchip_remove()
  pwm: rcar: Don't check the return code of pwmchip_remove()
  pwm: pca9685: Don't check the return code of pwmchip_remove()
  pwm: omap-dmtimer: Don't check the return code of pwmchip_remove()
  pwm: mtk-disp: Don't check the return code of pwmchip_remove()
  pwm: imx-tpm: Don't check the return code of pwmchip_remove()
  pwm: img: Don't check the return code of pwmchip_remove()
  pwm: cros-ec: Don't check the return code of pwmchip_remove()
  pwm: brcmstb: Don't check the return code of pwmchip_remove()
  pwm: atmel-tcb: Don't check the return code of pwmchip_remove()
  pwm: atmel-hlcdc: Don't check the return code of pwmchip_remove()
  ...
parents dd470387 3f2b1673
...@@ -29,6 +29,7 @@ properties: ...@@ -29,6 +29,7 @@ properties:
- enum: - enum:
- rockchip,px30-pwm - rockchip,px30-pwm
- rockchip,rk3308-pwm - rockchip,rk3308-pwm
- rockchip,rk3568-pwm
- const: rockchip,rk3328-pwm - const: rockchip,rk3328-pwm
reg: reg:
......
...@@ -272,7 +272,7 @@ config PWM_IQS620A ...@@ -272,7 +272,7 @@ config PWM_IQS620A
config PWM_JZ4740 config PWM_JZ4740
tristate "Ingenic JZ47xx PWM support" tristate "Ingenic JZ47xx PWM support"
depends on MIPS depends on MIPS || COMPILE_TEST
depends on COMMON_CLK depends on COMMON_CLK
select MFD_SYSCON select MFD_SYSCON
help help
...@@ -284,7 +284,8 @@ config PWM_JZ4740 ...@@ -284,7 +284,8 @@ config PWM_JZ4740
config PWM_KEEMBAY config PWM_KEEMBAY
tristate "Intel Keem Bay PWM driver" tristate "Intel Keem Bay PWM driver"
depends on ARCH_KEEMBAY || (ARM64 && COMPILE_TEST) depends on ARCH_KEEMBAY || COMPILE_TEST
depends on COMMON_CLK && HAS_IOMEM
help help
The platform driver for Intel Keem Bay PWM controller. The platform driver for Intel Keem Bay PWM controller.
......
...@@ -304,7 +304,7 @@ EXPORT_SYMBOL_GPL(pwmchip_add); ...@@ -304,7 +304,7 @@ EXPORT_SYMBOL_GPL(pwmchip_add);
* *
* Returns: 0 on success or a negative error code on failure. * Returns: 0 on success or a negative error code on failure.
*/ */
int pwmchip_remove(struct pwm_chip *chip) void pwmchip_remove(struct pwm_chip *chip)
{ {
pwmchip_sysfs_unexport(chip); pwmchip_sysfs_unexport(chip);
...@@ -318,8 +318,6 @@ int pwmchip_remove(struct pwm_chip *chip) ...@@ -318,8 +318,6 @@ int pwmchip_remove(struct pwm_chip *chip)
free_pwms(chip); free_pwms(chip);
mutex_unlock(&pwm_lock); mutex_unlock(&pwm_lock);
return 0;
} }
EXPORT_SYMBOL_GPL(pwmchip_remove); EXPORT_SYMBOL_GPL(pwmchip_remove);
......
...@@ -22,14 +22,21 @@ ...@@ -22,14 +22,21 @@
struct ab8500_pwm_chip { struct ab8500_pwm_chip {
struct pwm_chip chip; struct pwm_chip chip;
unsigned int hwid;
}; };
static struct ab8500_pwm_chip *ab8500_pwm_from_chip(struct pwm_chip *chip)
{
return container_of(chip, struct ab8500_pwm_chip, chip);
}
static int ab8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, static int ab8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state) const struct pwm_state *state)
{ {
int ret; int ret;
u8 reg; u8 reg;
unsigned int higher_val, lower_val; unsigned int higher_val, lower_val;
struct ab8500_pwm_chip *ab8500 = ab8500_pwm_from_chip(chip);
if (state->polarity != PWM_POLARITY_NORMAL) if (state->polarity != PWM_POLARITY_NORMAL)
return -EINVAL; return -EINVAL;
...@@ -37,7 +44,7 @@ static int ab8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -37,7 +44,7 @@ static int ab8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (!state->enabled) { if (!state->enabled) {
ret = abx500_mask_and_set_register_interruptible(chip->dev, ret = abx500_mask_and_set_register_interruptible(chip->dev,
AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG, AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
1 << (chip->base - 1), 0); 1 << ab8500->hwid, 0);
if (ret < 0) if (ret < 0)
dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n", dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
...@@ -56,7 +63,7 @@ static int ab8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -56,7 +63,7 @@ static int ab8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
*/ */
higher_val = ((state->duty_cycle & 0x0300) >> 8); higher_val = ((state->duty_cycle & 0x0300) >> 8);
reg = AB8500_PWM_OUT_CTRL1_REG + ((chip->base - 1) * 2); reg = AB8500_PWM_OUT_CTRL1_REG + (ab8500->hwid * 2);
ret = abx500_set_register_interruptible(chip->dev, AB8500_MISC, ret = abx500_set_register_interruptible(chip->dev, AB8500_MISC,
reg, (u8)lower_val); reg, (u8)lower_val);
...@@ -70,7 +77,7 @@ static int ab8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -70,7 +77,7 @@ static int ab8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
ret = abx500_mask_and_set_register_interruptible(chip->dev, ret = abx500_mask_and_set_register_interruptible(chip->dev,
AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG, AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
1 << (chip->base - 1), 1 << (chip->base - 1)); 1 << ab8500->hwid, 1 << ab8500->hwid);
if (ret < 0) if (ret < 0)
dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n", dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n",
pwm->label, ret); pwm->label, ret);
...@@ -88,6 +95,9 @@ static int ab8500_pwm_probe(struct platform_device *pdev) ...@@ -88,6 +95,9 @@ static int ab8500_pwm_probe(struct platform_device *pdev)
struct ab8500_pwm_chip *ab8500; struct ab8500_pwm_chip *ab8500;
int err; int err;
if (pdev->id < 1 || pdev->id > 31)
return dev_err_probe(&pdev->dev, EINVAL, "Invalid device id %d\n", pdev->id);
/* /*
* Nothing to be done in probe, this is required to get the * Nothing to be done in probe, this is required to get the
* device which is required for ab8500 read and write * device which is required for ab8500 read and write
...@@ -99,27 +109,13 @@ static int ab8500_pwm_probe(struct platform_device *pdev) ...@@ -99,27 +109,13 @@ static int ab8500_pwm_probe(struct platform_device *pdev)
ab8500->chip.dev = &pdev->dev; ab8500->chip.dev = &pdev->dev;
ab8500->chip.ops = &ab8500_pwm_ops; ab8500->chip.ops = &ab8500_pwm_ops;
ab8500->chip.npwm = 1; ab8500->chip.npwm = 1;
ab8500->hwid = pdev->id - 1;
err = pwmchip_add(&ab8500->chip); err = devm_pwmchip_add(&pdev->dev, &ab8500->chip);
if (err < 0) if (err < 0)
return dev_err_probe(&pdev->dev, err, "Failed to add pwm chip\n"); return dev_err_probe(&pdev->dev, err, "Failed to add pwm chip\n");
dev_dbg(&pdev->dev, "pwm probe successful\n"); dev_dbg(&pdev->dev, "pwm probe successful\n");
platform_set_drvdata(pdev, ab8500);
return 0;
}
static int ab8500_pwm_remove(struct platform_device *pdev)
{
struct ab8500_pwm_chip *ab8500 = platform_get_drvdata(pdev);
int err;
err = pwmchip_remove(&ab8500->chip);
if (err < 0)
return err;
dev_dbg(&pdev->dev, "pwm driver removed\n");
return 0; return 0;
} }
...@@ -129,7 +125,6 @@ static struct platform_driver ab8500_pwm_driver = { ...@@ -129,7 +125,6 @@ static struct platform_driver ab8500_pwm_driver = {
.name = "ab8500-pwm", .name = "ab8500-pwm",
}, },
.probe = ab8500_pwm_probe, .probe = ab8500_pwm_probe,
.remove = ab8500_pwm_remove,
}; };
module_platform_driver(ab8500_pwm_driver); module_platform_driver(ab8500_pwm_driver);
......
...@@ -281,11 +281,8 @@ static int atmel_hlcdc_pwm_probe(struct platform_device *pdev) ...@@ -281,11 +281,8 @@ static int atmel_hlcdc_pwm_probe(struct platform_device *pdev)
static int atmel_hlcdc_pwm_remove(struct platform_device *pdev) static int atmel_hlcdc_pwm_remove(struct platform_device *pdev)
{ {
struct atmel_hlcdc_pwm *chip = platform_get_drvdata(pdev); struct atmel_hlcdc_pwm *chip = platform_get_drvdata(pdev);
int ret;
ret = pwmchip_remove(&chip->chip); pwmchip_remove(&chip->chip);
if (ret)
return ret;
clk_disable_unprepare(chip->hlcdc->periph_clk); clk_disable_unprepare(chip->hlcdc->periph_clk);
......
...@@ -503,11 +503,8 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev) ...@@ -503,11 +503,8 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev)
static int atmel_tcb_pwm_remove(struct platform_device *pdev) static int atmel_tcb_pwm_remove(struct platform_device *pdev)
{ {
struct atmel_tcb_pwm_chip *tcbpwm = platform_get_drvdata(pdev); struct atmel_tcb_pwm_chip *tcbpwm = platform_get_drvdata(pdev);
int err;
err = pwmchip_remove(&tcbpwm->chip); pwmchip_remove(&tcbpwm->chip);
if (err < 0)
return err;
clk_disable_unprepare(tcbpwm->slow_clk); clk_disable_unprepare(tcbpwm->slow_clk);
clk_put(tcbpwm->slow_clk); clk_put(tcbpwm->slow_clk);
......
...@@ -84,9 +84,19 @@ struct atmel_pwm_chip { ...@@ -84,9 +84,19 @@ struct atmel_pwm_chip {
void __iomem *base; void __iomem *base;
const struct atmel_pwm_data *data; const struct atmel_pwm_data *data;
unsigned int updated_pwms; /*
/* ISR is cleared when read, ensure only one thread does that */ * The hardware supports a mechanism to update a channel's duty cycle at
struct mutex isr_lock; * the end of the currently running period. When such an update is
* pending we delay disabling the PWM until the new configuration is
* active because otherwise pmw_config(duty_cycle=0); pwm_disable();
* might not result in an inactive output.
* This bitmask tracks for which channels an update is pending in
* hardware.
*/
u32 update_pending;
/* Protects .update_pending */
spinlock_t lock;
}; };
static inline struct atmel_pwm_chip *to_atmel_pwm_chip(struct pwm_chip *chip) static inline struct atmel_pwm_chip *to_atmel_pwm_chip(struct pwm_chip *chip)
...@@ -123,6 +133,64 @@ static inline void atmel_pwm_ch_writel(struct atmel_pwm_chip *chip, ...@@ -123,6 +133,64 @@ static inline void atmel_pwm_ch_writel(struct atmel_pwm_chip *chip,
atmel_pwm_writel(chip, base + offset, val); atmel_pwm_writel(chip, base + offset, val);
} }
static void atmel_pwm_update_pending(struct atmel_pwm_chip *chip)
{
/*
* Each channel that has its bit in ISR set started a new period since
* ISR was cleared and so there is no more update pending. Note that
* reading ISR clears it, so this needs to handle all channels to not
* loose information.
*/
u32 isr = atmel_pwm_readl(chip, PWM_ISR);
chip->update_pending &= ~isr;
}
static void atmel_pwm_set_pending(struct atmel_pwm_chip *chip, unsigned int ch)
{
spin_lock(&chip->lock);
/*
* Clear pending flags in hardware because otherwise there might still
* be a stale flag in ISR.
*/
atmel_pwm_update_pending(chip);
chip->update_pending |= (1 << ch);
spin_unlock(&chip->lock);
}
static int atmel_pwm_test_pending(struct atmel_pwm_chip *chip, unsigned int ch)
{
int ret = 0;
spin_lock(&chip->lock);
if (chip->update_pending & (1 << ch)) {
atmel_pwm_update_pending(chip);
if (chip->update_pending & (1 << ch))
ret = 1;
}
spin_unlock(&chip->lock);
return ret;
}
static int atmel_pwm_wait_nonpending(struct atmel_pwm_chip *chip, unsigned int ch)
{
unsigned long timeout = jiffies + 2 * HZ;
int ret;
while ((ret = atmel_pwm_test_pending(chip, ch)) &&
time_before(jiffies, timeout))
usleep_range(10, 100);
return ret ? -ETIMEDOUT : 0;
}
static int atmel_pwm_calculate_cprd_and_pres(struct pwm_chip *chip, static int atmel_pwm_calculate_cprd_and_pres(struct pwm_chip *chip,
unsigned long clkrate, unsigned long clkrate,
const struct pwm_state *state, const struct pwm_state *state,
...@@ -185,6 +253,7 @@ static void atmel_pwm_update_cdty(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -185,6 +253,7 @@ static void atmel_pwm_update_cdty(struct pwm_chip *chip, struct pwm_device *pwm,
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm,
atmel_pwm->data->regs.duty_upd, cdty); atmel_pwm->data->regs.duty_upd, cdty);
atmel_pwm_set_pending(atmel_pwm, pwm->hwpwm);
} }
static void atmel_pwm_set_cprd_cdty(struct pwm_chip *chip, static void atmel_pwm_set_cprd_cdty(struct pwm_chip *chip,
...@@ -205,20 +274,8 @@ static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -205,20 +274,8 @@ static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm,
struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
unsigned long timeout = jiffies + 2 * HZ; unsigned long timeout = jiffies + 2 * HZ;
/* atmel_pwm_wait_nonpending(atmel_pwm, pwm->hwpwm);
* Wait for at least a complete period to have passed before disabling a
* channel to be sure that CDTY has been updated
*/
mutex_lock(&atmel_pwm->isr_lock);
atmel_pwm->updated_pwms |= atmel_pwm_readl(atmel_pwm, PWM_ISR);
while (!(atmel_pwm->updated_pwms & (1 << pwm->hwpwm)) &&
time_before(jiffies, timeout)) {
usleep_range(10, 100);
atmel_pwm->updated_pwms |= atmel_pwm_readl(atmel_pwm, PWM_ISR);
}
mutex_unlock(&atmel_pwm->isr_lock);
atmel_pwm_writel(atmel_pwm, PWM_DIS, 1 << pwm->hwpwm); atmel_pwm_writel(atmel_pwm, PWM_DIS, 1 << pwm->hwpwm);
/* /*
...@@ -292,10 +349,6 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -292,10 +349,6 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
val |= PWM_CMR_CPOL; val |= PWM_CMR_CPOL;
atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val); atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
atmel_pwm_set_cprd_cdty(chip, pwm, cprd, cdty); atmel_pwm_set_cprd_cdty(chip, pwm, cprd, cdty);
mutex_lock(&atmel_pwm->isr_lock);
atmel_pwm->updated_pwms |= atmel_pwm_readl(atmel_pwm, PWM_ISR);
atmel_pwm->updated_pwms &= ~(1 << pwm->hwpwm);
mutex_unlock(&atmel_pwm->isr_lock);
atmel_pwm_writel(atmel_pwm, PWM_ENA, 1 << pwm->hwpwm); atmel_pwm_writel(atmel_pwm, PWM_ENA, 1 << pwm->hwpwm);
} else if (cstate.enabled) { } else if (cstate.enabled) {
atmel_pwm_disable(chip, pwm, true); atmel_pwm_disable(chip, pwm, true);
...@@ -326,6 +379,9 @@ static void atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -326,6 +379,9 @@ static void atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
tmp <<= pres; tmp <<= pres;
state->period = DIV64_U64_ROUND_UP(tmp, rate); state->period = DIV64_U64_ROUND_UP(tmp, rate);
/* Wait for an updated duty_cycle queued in hardware */
atmel_pwm_wait_nonpending(atmel_pwm, pwm->hwpwm);
cdty = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, cdty = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm,
atmel_pwm->data->regs.duty); atmel_pwm->data->regs.duty);
tmp = (u64)(cprd - cdty) * NSEC_PER_SEC; tmp = (u64)(cprd - cdty) * NSEC_PER_SEC;
...@@ -416,9 +472,10 @@ static int atmel_pwm_probe(struct platform_device *pdev) ...@@ -416,9 +472,10 @@ static int atmel_pwm_probe(struct platform_device *pdev)
if (!atmel_pwm) if (!atmel_pwm)
return -ENOMEM; return -ENOMEM;
mutex_init(&atmel_pwm->isr_lock);
atmel_pwm->data = of_device_get_match_data(&pdev->dev); atmel_pwm->data = of_device_get_match_data(&pdev->dev);
atmel_pwm->updated_pwms = 0;
atmel_pwm->update_pending = 0;
spin_lock_init(&atmel_pwm->lock);
atmel_pwm->base = devm_platform_ioremap_resource(pdev, 0); atmel_pwm->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(atmel_pwm->base)) if (IS_ERR(atmel_pwm->base))
...@@ -460,7 +517,6 @@ static int atmel_pwm_remove(struct platform_device *pdev) ...@@ -460,7 +517,6 @@ static int atmel_pwm_remove(struct platform_device *pdev)
pwmchip_remove(&atmel_pwm->chip); pwmchip_remove(&atmel_pwm->chip);
clk_unprepare(atmel_pwm->clk); clk_unprepare(atmel_pwm->clk);
mutex_destroy(&atmel_pwm->isr_lock);
return 0; return 0;
} }
......
...@@ -267,8 +267,6 @@ static int kona_pwmc_probe(struct platform_device *pdev) ...@@ -267,8 +267,6 @@ static int kona_pwmc_probe(struct platform_device *pdev)
if (kp == NULL) if (kp == NULL)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(pdev, kp);
kp->chip.dev = &pdev->dev; kp->chip.dev = &pdev->dev;
kp->chip.ops = &kona_pwm_ops; kp->chip.ops = &kona_pwm_ops;
kp->chip.npwm = 6; kp->chip.npwm = 6;
...@@ -298,20 +296,13 @@ static int kona_pwmc_probe(struct platform_device *pdev) ...@@ -298,20 +296,13 @@ static int kona_pwmc_probe(struct platform_device *pdev)
clk_disable_unprepare(kp->clk); clk_disable_unprepare(kp->clk);
ret = pwmchip_add(&kp->chip); ret = devm_pwmchip_add(&pdev->dev, &kp->chip);
if (ret < 0) if (ret < 0)
dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret); dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
return ret; return ret;
} }
static int kona_pwmc_remove(struct platform_device *pdev)
{
struct kona_pwmc *kp = platform_get_drvdata(pdev);
return pwmchip_remove(&kp->chip);
}
static const struct of_device_id bcm_kona_pwmc_dt[] = { static const struct of_device_id bcm_kona_pwmc_dt[] = {
{ .compatible = "brcm,kona-pwm" }, { .compatible = "brcm,kona-pwm" },
{ }, { },
...@@ -324,7 +315,6 @@ static struct platform_driver kona_pwmc_driver = { ...@@ -324,7 +315,6 @@ static struct platform_driver kona_pwmc_driver = {
.of_match_table = bcm_kona_pwmc_dt, .of_match_table = bcm_kona_pwmc_dt,
}, },
.probe = kona_pwmc_probe, .probe = kona_pwmc_probe,
.remove = kona_pwmc_remove,
}; };
module_platform_driver(kona_pwmc_driver); module_platform_driver(kona_pwmc_driver);
......
...@@ -282,12 +282,11 @@ static int brcmstb_pwm_probe(struct platform_device *pdev) ...@@ -282,12 +282,11 @@ static int brcmstb_pwm_probe(struct platform_device *pdev)
static int brcmstb_pwm_remove(struct platform_device *pdev) static int brcmstb_pwm_remove(struct platform_device *pdev)
{ {
struct brcmstb_pwm *p = platform_get_drvdata(pdev); struct brcmstb_pwm *p = platform_get_drvdata(pdev);
int ret;
ret = pwmchip_remove(&p->chip); pwmchip_remove(&p->chip);
clk_disable_unprepare(p->clk); clk_disable_unprepare(p->clk);
return ret; return 0;
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
......
...@@ -280,7 +280,9 @@ static int cros_ec_pwm_remove(struct platform_device *dev) ...@@ -280,7 +280,9 @@ static int cros_ec_pwm_remove(struct platform_device *dev)
struct cros_ec_pwm_device *ec_pwm = platform_get_drvdata(dev); struct cros_ec_pwm_device *ec_pwm = platform_get_drvdata(dev);
struct pwm_chip *chip = &ec_pwm->chip; struct pwm_chip *chip = &ec_pwm->chip;
return pwmchip_remove(chip); pwmchip_remove(chip);
return 0;
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
......
...@@ -183,27 +183,18 @@ static int ep93xx_pwm_probe(struct platform_device *pdev) ...@@ -183,27 +183,18 @@ static int ep93xx_pwm_probe(struct platform_device *pdev)
ep93xx_pwm->chip.ops = &ep93xx_pwm_ops; ep93xx_pwm->chip.ops = &ep93xx_pwm_ops;
ep93xx_pwm->chip.npwm = 1; ep93xx_pwm->chip.npwm = 1;
ret = pwmchip_add(&ep93xx_pwm->chip); ret = devm_pwmchip_add(&pdev->dev, &ep93xx_pwm->chip);
if (ret < 0) if (ret < 0)
return ret; return ret;
platform_set_drvdata(pdev, ep93xx_pwm);
return 0; return 0;
} }
static int ep93xx_pwm_remove(struct platform_device *pdev)
{
struct ep93xx_pwm *ep93xx_pwm = platform_get_drvdata(pdev);
return pwmchip_remove(&ep93xx_pwm->chip);
}
static struct platform_driver ep93xx_pwm_driver = { static struct platform_driver ep93xx_pwm_driver = {
.driver = { .driver = {
.name = "ep93xx-pwm", .name = "ep93xx-pwm",
}, },
.probe = ep93xx_pwm_probe, .probe = ep93xx_pwm_probe,
.remove = ep93xx_pwm_remove,
}; };
module_platform_driver(ep93xx_pwm_driver); module_platform_driver(ep93xx_pwm_driver);
......
...@@ -453,7 +453,7 @@ static int fsl_pwm_probe(struct platform_device *pdev) ...@@ -453,7 +453,7 @@ static int fsl_pwm_probe(struct platform_device *pdev)
fpc->chip.ops = &fsl_pwm_ops; fpc->chip.ops = &fsl_pwm_ops;
fpc->chip.npwm = 8; fpc->chip.npwm = 8;
ret = pwmchip_add(&fpc->chip); ret = devm_pwmchip_add(&pdev->dev, &fpc->chip);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret); dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
return ret; return ret;
...@@ -464,13 +464,6 @@ static int fsl_pwm_probe(struct platform_device *pdev) ...@@ -464,13 +464,6 @@ static int fsl_pwm_probe(struct platform_device *pdev)
return fsl_pwm_init(fpc); return fsl_pwm_init(fpc);
} }
static int fsl_pwm_remove(struct platform_device *pdev)
{
struct fsl_pwm_chip *fpc = platform_get_drvdata(pdev);
return pwmchip_remove(&fpc->chip);
}
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int fsl_pwm_suspend(struct device *dev) static int fsl_pwm_suspend(struct device *dev)
{ {
...@@ -552,7 +545,6 @@ static struct platform_driver fsl_pwm_driver = { ...@@ -552,7 +545,6 @@ static struct platform_driver fsl_pwm_driver = {
.pm = &fsl_pwm_pm_ops, .pm = &fsl_pwm_pm_ops,
}, },
.probe = fsl_pwm_probe, .probe = fsl_pwm_probe,
.remove = fsl_pwm_remove,
}; };
module_platform_driver(fsl_pwm_driver); module_platform_driver(fsl_pwm_driver);
......
...@@ -248,13 +248,15 @@ static int hibvt_pwm_remove(struct platform_device *pdev) ...@@ -248,13 +248,15 @@ static int hibvt_pwm_remove(struct platform_device *pdev)
pwm_chip = platform_get_drvdata(pdev); pwm_chip = platform_get_drvdata(pdev);
pwmchip_remove(&pwm_chip->chip);
reset_control_assert(pwm_chip->rstc); reset_control_assert(pwm_chip->rstc);
msleep(30); msleep(30);
reset_control_deassert(pwm_chip->rstc); reset_control_deassert(pwm_chip->rstc);
clk_disable_unprepare(pwm_chip->clk); clk_disable_unprepare(pwm_chip->clk);
return pwmchip_remove(&pwm_chip->chip); return 0;
} }
static const struct of_device_id hibvt_pwm_of_match[] = { static const struct of_device_id hibvt_pwm_of_match[] = {
......
...@@ -326,28 +326,14 @@ static int img_pwm_probe(struct platform_device *pdev) ...@@ -326,28 +326,14 @@ static int img_pwm_probe(struct platform_device *pdev)
static int img_pwm_remove(struct platform_device *pdev) static int img_pwm_remove(struct platform_device *pdev)
{ {
struct img_pwm_chip *pwm_chip = platform_get_drvdata(pdev); struct img_pwm_chip *pwm_chip = platform_get_drvdata(pdev);
u32 val;
unsigned int i;
int ret;
ret = pm_runtime_get_sync(&pdev->dev);
if (ret < 0) {
pm_runtime_put(&pdev->dev);
return ret;
}
for (i = 0; i < pwm_chip->chip.npwm; i++) {
val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG);
val &= ~BIT(i);
img_pwm_writel(pwm_chip, PWM_CTRL_CFG, val);
}
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev)) if (!pm_runtime_status_suspended(&pdev->dev))
img_pwm_runtime_suspend(&pdev->dev); img_pwm_runtime_suspend(&pdev->dev);
return pwmchip_remove(&pwm_chip->chip); pwmchip_remove(&pwm_chip->chip);
return 0;
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
......
...@@ -382,11 +382,12 @@ static int pwm_imx_tpm_probe(struct platform_device *pdev) ...@@ -382,11 +382,12 @@ static int pwm_imx_tpm_probe(struct platform_device *pdev)
static int pwm_imx_tpm_remove(struct platform_device *pdev) static int pwm_imx_tpm_remove(struct platform_device *pdev)
{ {
struct imx_tpm_pwm_chip *tpm = platform_get_drvdata(pdev); struct imx_tpm_pwm_chip *tpm = platform_get_drvdata(pdev);
int ret = pwmchip_remove(&tpm->chip);
pwmchip_remove(&tpm->chip);
clk_disable_unprepare(tpm->clk); clk_disable_unprepare(tpm->clk);
return ret; return 0;
} }
static int __maybe_unused pwm_imx_tpm_suspend(struct device *dev) static int __maybe_unused pwm_imx_tpm_suspend(struct device *dev)
......
...@@ -313,8 +313,6 @@ static int pwm_imx27_probe(struct platform_device *pdev) ...@@ -313,8 +313,6 @@ static int pwm_imx27_probe(struct platform_device *pdev)
if (imx == NULL) if (imx == NULL)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(pdev, imx);
imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(imx->clk_ipg)) if (IS_ERR(imx->clk_ipg))
return dev_err_probe(&pdev->dev, PTR_ERR(imx->clk_ipg), return dev_err_probe(&pdev->dev, PTR_ERR(imx->clk_ipg),
...@@ -342,16 +340,7 @@ static int pwm_imx27_probe(struct platform_device *pdev) ...@@ -342,16 +340,7 @@ static int pwm_imx27_probe(struct platform_device *pdev)
if (!(pwmcr & MX3_PWMCR_EN)) if (!(pwmcr & MX3_PWMCR_EN))
pwm_imx27_clk_disable_unprepare(imx); pwm_imx27_clk_disable_unprepare(imx);
return pwmchip_add(&imx->chip); return devm_pwmchip_add(&pdev->dev, &imx->chip);
}
static int pwm_imx27_remove(struct platform_device *pdev)
{
struct pwm_imx27_chip *imx;
imx = platform_get_drvdata(pdev);
return pwmchip_remove(&imx->chip);
} }
static struct platform_driver imx_pwm_driver = { static struct platform_driver imx_pwm_driver = {
...@@ -360,7 +349,6 @@ static struct platform_driver imx_pwm_driver = { ...@@ -360,7 +349,6 @@ static struct platform_driver imx_pwm_driver = {
.of_match_table = pwm_imx27_dt_ids, .of_match_table = pwm_imx27_dt_ids,
}, },
.probe = pwm_imx27_probe, .probe = pwm_imx27_probe,
.remove = pwm_imx27_remove,
}; };
module_platform_driver(imx_pwm_driver); module_platform_driver(imx_pwm_driver);
......
...@@ -176,8 +176,6 @@ static int lgm_pwm_probe(struct platform_device *pdev) ...@@ -176,8 +176,6 @@ static int lgm_pwm_probe(struct platform_device *pdev)
if (!pc) if (!pc)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(pdev, pc);
io_base = devm_platform_ioremap_resource(pdev, 0); io_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(io_base)) if (IS_ERR(io_base))
return PTR_ERR(io_base); return PTR_ERR(io_base);
...@@ -210,20 +208,13 @@ static int lgm_pwm_probe(struct platform_device *pdev) ...@@ -210,20 +208,13 @@ static int lgm_pwm_probe(struct platform_device *pdev)
lgm_pwm_init(pc); lgm_pwm_init(pc);
ret = pwmchip_add(&pc->chip); ret = devm_pwmchip_add(dev, &pc->chip);
if (ret < 0) if (ret < 0)
return dev_err_probe(dev, ret, "failed to add PWM chip\n"); return dev_err_probe(dev, ret, "failed to add PWM chip\n");
return 0; return 0;
} }
static int lgm_pwm_remove(struct platform_device *pdev)
{
struct lgm_pwm_chip *pc = platform_get_drvdata(pdev);
return pwmchip_remove(&pc->chip);
}
static const struct of_device_id lgm_pwm_of_match[] = { static const struct of_device_id lgm_pwm_of_match[] = {
{ .compatible = "intel,lgm-pwm" }, { .compatible = "intel,lgm-pwm" },
{ } { }
...@@ -236,7 +227,6 @@ static struct platform_driver lgm_pwm_driver = { ...@@ -236,7 +227,6 @@ static struct platform_driver lgm_pwm_driver = {
.of_match_table = lgm_pwm_of_match, .of_match_table = lgm_pwm_of_match,
}, },
.probe = lgm_pwm_probe, .probe = lgm_pwm_probe,
.remove = lgm_pwm_remove,
}; };
module_platform_driver(lgm_pwm_driver); module_platform_driver(lgm_pwm_driver);
......
...@@ -189,7 +189,6 @@ static int iqs620_pwm_probe(struct platform_device *pdev) ...@@ -189,7 +189,6 @@ static int iqs620_pwm_probe(struct platform_device *pdev)
if (!iqs620_pwm) if (!iqs620_pwm)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(pdev, iqs620_pwm);
iqs620_pwm->iqs62x = iqs62x; iqs620_pwm->iqs62x = iqs62x;
ret = regmap_read(iqs62x->regmap, IQS620_PWR_SETTINGS, &val); ret = regmap_read(iqs62x->regmap, IQS620_PWR_SETTINGS, &val);
...@@ -224,31 +223,18 @@ static int iqs620_pwm_probe(struct platform_device *pdev) ...@@ -224,31 +223,18 @@ static int iqs620_pwm_probe(struct platform_device *pdev)
if (ret) if (ret)
return ret; return ret;
ret = pwmchip_add(&iqs620_pwm->chip); ret = devm_pwmchip_add(&pdev->dev, &iqs620_pwm->chip);
if (ret) if (ret)
dev_err(&pdev->dev, "Failed to add device: %d\n", ret); dev_err(&pdev->dev, "Failed to add device: %d\n", ret);
return ret; return ret;
} }
static int iqs620_pwm_remove(struct platform_device *pdev)
{
struct iqs620_pwm_private *iqs620_pwm = platform_get_drvdata(pdev);
int ret;
ret = pwmchip_remove(&iqs620_pwm->chip);
if (ret)
dev_err(&pdev->dev, "Failed to remove device: %d\n", ret);
return ret;
}
static struct platform_driver iqs620_pwm_platform_driver = { static struct platform_driver iqs620_pwm_platform_driver = {
.driver = { .driver = {
.name = "iqs620a-pwm", .name = "iqs620a-pwm",
}, },
.probe = iqs620_pwm_probe, .probe = iqs620_pwm_probe,
.remove = iqs620_pwm_remove,
}; };
module_platform_driver(iqs620_pwm_platform_driver); module_platform_driver(iqs620_pwm_platform_driver);
......
...@@ -245,16 +245,7 @@ static int jz4740_pwm_probe(struct platform_device *pdev) ...@@ -245,16 +245,7 @@ static int jz4740_pwm_probe(struct platform_device *pdev)
jz4740->chip.ops = &jz4740_pwm_ops; jz4740->chip.ops = &jz4740_pwm_ops;
jz4740->chip.npwm = info->num_pwms; jz4740->chip.npwm = info->num_pwms;
platform_set_drvdata(pdev, jz4740); return devm_pwmchip_add(dev, &jz4740->chip);
return pwmchip_add(&jz4740->chip);
}
static int jz4740_pwm_remove(struct platform_device *pdev)
{
struct jz4740_pwm_chip *jz4740 = platform_get_drvdata(pdev);
return pwmchip_remove(&jz4740->chip);
} }
static const struct soc_info __maybe_unused jz4740_soc_info = { static const struct soc_info __maybe_unused jz4740_soc_info = {
...@@ -280,7 +271,6 @@ static struct platform_driver jz4740_pwm_driver = { ...@@ -280,7 +271,6 @@ static struct platform_driver jz4740_pwm_driver = {
.of_match_table = of_match_ptr(jz4740_pwm_dt_ids), .of_match_table = of_match_ptr(jz4740_pwm_dt_ids),
}, },
.probe = jz4740_pwm_probe, .probe = jz4740_pwm_probe,
.remove = jz4740_pwm_remove,
}; };
module_platform_driver(jz4740_pwm_driver); module_platform_driver(jz4740_pwm_driver);
......
...@@ -207,22 +207,13 @@ static int keembay_pwm_probe(struct platform_device *pdev) ...@@ -207,22 +207,13 @@ static int keembay_pwm_probe(struct platform_device *pdev)
priv->chip.ops = &keembay_pwm_ops; priv->chip.ops = &keembay_pwm_ops;
priv->chip.npwm = KMB_TOTAL_PWM_CHANNELS; priv->chip.npwm = KMB_TOTAL_PWM_CHANNELS;
ret = pwmchip_add(&priv->chip); ret = devm_pwmchip_add(dev, &priv->chip);
if (ret) if (ret)
return dev_err_probe(dev, ret, "Failed to add PWM chip\n"); return dev_err_probe(dev, ret, "Failed to add PWM chip\n");
platform_set_drvdata(pdev, priv);
return 0; return 0;
} }
static int keembay_pwm_remove(struct platform_device *pdev)
{
struct keembay_pwm *priv = platform_get_drvdata(pdev);
return pwmchip_remove(&priv->chip);
}
static const struct of_device_id keembay_pwm_of_match[] = { static const struct of_device_id keembay_pwm_of_match[] = {
{ .compatible = "intel,keembay-pwm" }, { .compatible = "intel,keembay-pwm" },
{ } { }
...@@ -231,7 +222,6 @@ MODULE_DEVICE_TABLE(of, keembay_pwm_of_match); ...@@ -231,7 +222,6 @@ MODULE_DEVICE_TABLE(of, keembay_pwm_of_match);
static struct platform_driver keembay_pwm_driver = { static struct platform_driver keembay_pwm_driver = {
.probe = keembay_pwm_probe, .probe = keembay_pwm_probe,
.remove = keembay_pwm_remove,
.driver = { .driver = {
.name = "pwm-keembay", .name = "pwm-keembay",
.of_match_table = keembay_pwm_of_match, .of_match_table = keembay_pwm_of_match,
......
...@@ -276,16 +276,7 @@ static int lp3943_pwm_probe(struct platform_device *pdev) ...@@ -276,16 +276,7 @@ static int lp3943_pwm_probe(struct platform_device *pdev)
lp3943_pwm->chip.ops = &lp3943_pwm_ops; lp3943_pwm->chip.ops = &lp3943_pwm_ops;
lp3943_pwm->chip.npwm = LP3943_NUM_PWMS; lp3943_pwm->chip.npwm = LP3943_NUM_PWMS;
platform_set_drvdata(pdev, lp3943_pwm); return devm_pwmchip_add(&pdev->dev, &lp3943_pwm->chip);
return pwmchip_add(&lp3943_pwm->chip);
}
static int lp3943_pwm_remove(struct platform_device *pdev)
{
struct lp3943_pwm *lp3943_pwm = platform_get_drvdata(pdev);
return pwmchip_remove(&lp3943_pwm->chip);
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
...@@ -298,7 +289,6 @@ MODULE_DEVICE_TABLE(of, lp3943_pwm_of_match); ...@@ -298,7 +289,6 @@ MODULE_DEVICE_TABLE(of, lp3943_pwm_of_match);
static struct platform_driver lp3943_pwm_driver = { static struct platform_driver lp3943_pwm_driver = {
.probe = lp3943_pwm_probe, .probe = lp3943_pwm_probe,
.remove = lp3943_pwm_remove,
.driver = { .driver = {
.name = "lp3943-pwm", .name = "lp3943-pwm",
.of_match_table = of_match_ptr(lp3943_pwm_of_match), .of_match_table = of_match_ptr(lp3943_pwm_of_match),
......
...@@ -117,29 +117,20 @@ static int lpc32xx_pwm_probe(struct platform_device *pdev) ...@@ -117,29 +117,20 @@ static int lpc32xx_pwm_probe(struct platform_device *pdev)
lpc32xx->chip.ops = &lpc32xx_pwm_ops; lpc32xx->chip.ops = &lpc32xx_pwm_ops;
lpc32xx->chip.npwm = 1; lpc32xx->chip.npwm = 1;
ret = pwmchip_add(&lpc32xx->chip); /* If PWM is disabled, configure the output to the default value */
if (ret < 0) {
dev_err(&pdev->dev, "failed to add PWM chip, error %d\n", ret);
return ret;
}
/* When PWM is disable, configure the output to the default value */
val = readl(lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2)); val = readl(lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2));
val &= ~PWM_PIN_LEVEL; val &= ~PWM_PIN_LEVEL;
writel(val, lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2)); writel(val, lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2));
platform_set_drvdata(pdev, lpc32xx); ret = devm_pwmchip_add(&pdev->dev, &lpc32xx->chip);
if (ret < 0) {
dev_err(&pdev->dev, "failed to add PWM chip, error %d\n", ret);
return ret;
}
return 0; return 0;
} }
static int lpc32xx_pwm_remove(struct platform_device *pdev)
{
struct lpc32xx_pwm_chip *lpc32xx = platform_get_drvdata(pdev);
return pwmchip_remove(&lpc32xx->chip);
}
static const struct of_device_id lpc32xx_pwm_dt_ids[] = { static const struct of_device_id lpc32xx_pwm_dt_ids[] = {
{ .compatible = "nxp,lpc3220-pwm", }, { .compatible = "nxp,lpc3220-pwm", },
{ /* sentinel */ } { /* sentinel */ }
...@@ -152,7 +143,6 @@ static struct platform_driver lpc32xx_pwm_driver = { ...@@ -152,7 +143,6 @@ static struct platform_driver lpc32xx_pwm_driver = {
.of_match_table = lpc32xx_pwm_dt_ids, .of_match_table = lpc32xx_pwm_dt_ids,
}, },
.probe = lpc32xx_pwm_probe, .probe = lpc32xx_pwm_probe,
.remove = lpc32xx_pwm_remove,
}; };
module_platform_driver(lpc32xx_pwm_driver); module_platform_driver(lpc32xx_pwm_driver);
......
...@@ -253,13 +253,11 @@ static int pwm_mediatek_probe(struct platform_device *pdev) ...@@ -253,13 +253,11 @@ static int pwm_mediatek_probe(struct platform_device *pdev)
} }
} }
platform_set_drvdata(pdev, pc);
pc->chip.dev = &pdev->dev; pc->chip.dev = &pdev->dev;
pc->chip.ops = &pwm_mediatek_ops; pc->chip.ops = &pwm_mediatek_ops;
pc->chip.npwm = pc->soc->num_pwms; pc->chip.npwm = pc->soc->num_pwms;
ret = pwmchip_add(&pc->chip); ret = devm_pwmchip_add(&pdev->dev, &pc->chip);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
return ret; return ret;
...@@ -268,13 +266,6 @@ static int pwm_mediatek_probe(struct platform_device *pdev) ...@@ -268,13 +266,6 @@ static int pwm_mediatek_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int pwm_mediatek_remove(struct platform_device *pdev)
{
struct pwm_mediatek_chip *pc = platform_get_drvdata(pdev);
return pwmchip_remove(&pc->chip);
}
static const struct pwm_mediatek_of_data mt2712_pwm_data = { static const struct pwm_mediatek_of_data mt2712_pwm_data = {
.num_pwms = 8, .num_pwms = 8,
.pwm45_fixup = false, .pwm45_fixup = false,
...@@ -335,7 +326,6 @@ static struct platform_driver pwm_mediatek_driver = { ...@@ -335,7 +326,6 @@ static struct platform_driver pwm_mediatek_driver = {
.of_match_table = pwm_mediatek_of_match, .of_match_table = pwm_mediatek_of_match,
}, },
.probe = pwm_mediatek_probe, .probe = pwm_mediatek_probe,
.remove = pwm_mediatek_remove,
}; };
module_platform_driver(pwm_mediatek_driver); module_platform_driver(pwm_mediatek_driver);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* Author: YH Huang <yh.huang@mediatek.com> * Author: YH Huang <yh.huang@mediatek.com>
*/ */
#include <linux/bitfield.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/io.h> #include <linux/io.h>
...@@ -47,6 +48,7 @@ struct mtk_disp_pwm { ...@@ -47,6 +48,7 @@ struct mtk_disp_pwm {
struct clk *clk_main; struct clk *clk_main;
struct clk *clk_mm; struct clk *clk_mm;
void __iomem *base; void __iomem *base;
bool enabled;
}; };
static inline struct mtk_disp_pwm *to_mtk_disp_pwm(struct pwm_chip *chip) static inline struct mtk_disp_pwm *to_mtk_disp_pwm(struct pwm_chip *chip)
...@@ -66,14 +68,47 @@ static void mtk_disp_pwm_update_bits(struct mtk_disp_pwm *mdp, u32 offset, ...@@ -66,14 +68,47 @@ static void mtk_disp_pwm_update_bits(struct mtk_disp_pwm *mdp, u32 offset,
writel(value, address); writel(value, address);
} }
static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, static int mtk_disp_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
int duty_ns, int period_ns) const struct pwm_state *state)
{ {
struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip); struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
u32 clk_div, period, high_width, value; u32 clk_div, period, high_width, value;
u64 div, rate; u64 div, rate;
int err; int err;
if (state->polarity != PWM_POLARITY_NORMAL)
return -EINVAL;
if (!state->enabled) {
mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask,
0x0);
if (mdp->enabled) {
clk_disable_unprepare(mdp->clk_mm);
clk_disable_unprepare(mdp->clk_main);
}
mdp->enabled = false;
return 0;
}
if (!mdp->enabled) {
err = clk_prepare_enable(mdp->clk_main);
if (err < 0) {
dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n",
ERR_PTR(err));
return err;
}
err = clk_prepare_enable(mdp->clk_mm);
if (err < 0) {
dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n",
ERR_PTR(err));
clk_disable_unprepare(mdp->clk_main);
return err;
}
}
/* /*
* Find period, high_width and clk_div to suit duty_ns and period_ns. * Find period, high_width and clk_div to suit duty_ns and period_ns.
* Calculate proper div value to keep period value in the bound. * Calculate proper div value to keep period value in the bound.
...@@ -85,29 +120,24 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -85,29 +120,24 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
* high_width = (PWM_CLK_RATE * duty_ns) / (10^9 * (clk_div + 1)) * high_width = (PWM_CLK_RATE * duty_ns) / (10^9 * (clk_div + 1))
*/ */
rate = clk_get_rate(mdp->clk_main); rate = clk_get_rate(mdp->clk_main);
clk_div = div_u64(rate * period_ns, NSEC_PER_SEC) >> clk_div = mul_u64_u64_div_u64(state->period, rate, NSEC_PER_SEC) >>
PWM_PERIOD_BIT_WIDTH; PWM_PERIOD_BIT_WIDTH;
if (clk_div > PWM_CLKDIV_MAX) if (clk_div > PWM_CLKDIV_MAX) {
if (!mdp->enabled) {
clk_disable_unprepare(mdp->clk_mm);
clk_disable_unprepare(mdp->clk_main);
}
return -EINVAL; return -EINVAL;
}
div = NSEC_PER_SEC * (clk_div + 1); div = NSEC_PER_SEC * (clk_div + 1);
period = div64_u64(rate * period_ns, div); period = mul_u64_u64_div_u64(state->period, rate, div);
if (period > 0) if (period > 0)
period--; period--;
high_width = div64_u64(rate * duty_ns, div); high_width = mul_u64_u64_div_u64(state->duty_cycle, rate, div);
value = period | (high_width << PWM_HIGH_WIDTH_SHIFT); value = period | (high_width << PWM_HIGH_WIDTH_SHIFT);
err = clk_enable(mdp->clk_main);
if (err < 0)
return err;
err = clk_enable(mdp->clk_mm);
if (err < 0) {
clk_disable(mdp->clk_main);
return err;
}
mtk_disp_pwm_update_bits(mdp, mdp->data->con0, mtk_disp_pwm_update_bits(mdp, mdp->data->con0,
PWM_CLKDIV_MASK, PWM_CLKDIV_MASK,
clk_div << PWM_CLKDIV_SHIFT); clk_div << PWM_CLKDIV_SHIFT);
...@@ -122,50 +152,70 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -122,50 +152,70 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
mtk_disp_pwm_update_bits(mdp, mdp->data->commit, mtk_disp_pwm_update_bits(mdp, mdp->data->commit,
mdp->data->commit_mask, mdp->data->commit_mask,
0x0); 0x0);
} else {
/*
* For MT2701, disable double buffer before writing register
* and select manual mode and use PWM_PERIOD/PWM_HIGH_WIDTH.
*/
mtk_disp_pwm_update_bits(mdp, mdp->data->bls_debug,
mdp->data->bls_debug_mask,
mdp->data->bls_debug_mask);
mtk_disp_pwm_update_bits(mdp, mdp->data->con0,
mdp->data->con0_sel,
mdp->data->con0_sel);
} }
clk_disable(mdp->clk_mm); mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask,
clk_disable(mdp->clk_main); mdp->data->enable_mask);
mdp->enabled = true;
return 0; return 0;
} }
static int mtk_disp_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) static void mtk_disp_pwm_get_state(struct pwm_chip *chip,
struct pwm_device *pwm,
struct pwm_state *state)
{ {
struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip); struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
u64 rate, period, high_width;
u32 clk_div, con0, con1;
int err; int err;
err = clk_enable(mdp->clk_main); err = clk_prepare_enable(mdp->clk_main);
if (err < 0)
return err;
err = clk_enable(mdp->clk_mm);
if (err < 0) { if (err < 0) {
clk_disable(mdp->clk_main); dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n", ERR_PTR(err));
return err; return;
} }
mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask, err = clk_prepare_enable(mdp->clk_mm);
mdp->data->enable_mask); if (err < 0) {
dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n", ERR_PTR(err));
return 0; clk_disable_unprepare(mdp->clk_main);
} return;
}
static void mtk_disp_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask,
0x0);
clk_disable(mdp->clk_mm); rate = clk_get_rate(mdp->clk_main);
clk_disable(mdp->clk_main); con0 = readl(mdp->base + mdp->data->con0);
con1 = readl(mdp->base + mdp->data->con1);
state->enabled = !!(con0 & BIT(0));
clk_div = FIELD_GET(PWM_CLKDIV_MASK, con0);
period = FIELD_GET(PWM_PERIOD_MASK, con1);
/*
* period has 12 bits, clk_div 11 and NSEC_PER_SEC has 30,
* so period * (clk_div + 1) * NSEC_PER_SEC doesn't overflow.
*/
state->period = DIV64_U64_ROUND_UP(period * (clk_div + 1) * NSEC_PER_SEC, rate);
high_width = FIELD_GET(PWM_HIGH_WIDTH_MASK, con1);
state->duty_cycle = DIV64_U64_ROUND_UP(high_width * (clk_div + 1) * NSEC_PER_SEC,
rate);
state->polarity = PWM_POLARITY_NORMAL;
clk_disable_unprepare(mdp->clk_mm);
clk_disable_unprepare(mdp->clk_main);
} }
static const struct pwm_ops mtk_disp_pwm_ops = { static const struct pwm_ops mtk_disp_pwm_ops = {
.config = mtk_disp_pwm_config, .apply = mtk_disp_pwm_apply,
.enable = mtk_disp_pwm_enable, .get_state = mtk_disp_pwm_get_state,
.disable = mtk_disp_pwm_disable,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
...@@ -192,58 +242,28 @@ static int mtk_disp_pwm_probe(struct platform_device *pdev) ...@@ -192,58 +242,28 @@ static int mtk_disp_pwm_probe(struct platform_device *pdev)
if (IS_ERR(mdp->clk_mm)) if (IS_ERR(mdp->clk_mm))
return PTR_ERR(mdp->clk_mm); return PTR_ERR(mdp->clk_mm);
ret = clk_prepare(mdp->clk_main);
if (ret < 0)
return ret;
ret = clk_prepare(mdp->clk_mm);
if (ret < 0)
goto disable_clk_main;
mdp->chip.dev = &pdev->dev; mdp->chip.dev = &pdev->dev;
mdp->chip.ops = &mtk_disp_pwm_ops; mdp->chip.ops = &mtk_disp_pwm_ops;
mdp->chip.npwm = 1; mdp->chip.npwm = 1;
ret = pwmchip_add(&mdp->chip); ret = pwmchip_add(&mdp->chip);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); dev_err(&pdev->dev, "pwmchip_add() failed: %pe\n", ERR_PTR(ret));
goto disable_clk_mm; return ret;
} }
platform_set_drvdata(pdev, mdp); platform_set_drvdata(pdev, mdp);
/*
* For MT2701, disable double buffer before writing register
* and select manual mode and use PWM_PERIOD/PWM_HIGH_WIDTH.
*/
if (!mdp->data->has_commit) {
mtk_disp_pwm_update_bits(mdp, mdp->data->bls_debug,
mdp->data->bls_debug_mask,
mdp->data->bls_debug_mask);
mtk_disp_pwm_update_bits(mdp, mdp->data->con0,
mdp->data->con0_sel,
mdp->data->con0_sel);
}
return 0; return 0;
disable_clk_mm:
clk_unprepare(mdp->clk_mm);
disable_clk_main:
clk_unprepare(mdp->clk_main);
return ret;
} }
static int mtk_disp_pwm_remove(struct platform_device *pdev) static int mtk_disp_pwm_remove(struct platform_device *pdev)
{ {
struct mtk_disp_pwm *mdp = platform_get_drvdata(pdev); struct mtk_disp_pwm *mdp = platform_get_drvdata(pdev);
int ret;
ret = pwmchip_remove(&mdp->chip); pwmchip_remove(&mdp->chip);
clk_unprepare(mdp->clk_mm);
clk_unprepare(mdp->clk_main);
return ret; return 0;
} }
static const struct mtk_pwm_data mt2701_pwm_data = { static const struct mtk_pwm_data mt2701_pwm_data = {
......
...@@ -145,30 +145,18 @@ static int mxs_pwm_probe(struct platform_device *pdev) ...@@ -145,30 +145,18 @@ static int mxs_pwm_probe(struct platform_device *pdev)
return ret; return ret;
} }
ret = pwmchip_add(&mxs->chip); /* FIXME: Only do this if the PWM isn't already running */
ret = stmp_reset_block(mxs->base);
if (ret)
return dev_err_probe(&pdev->dev, ret, "failed to reset PWM\n");
ret = devm_pwmchip_add(&pdev->dev, &mxs->chip);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "failed to add pwm chip %d\n", ret); dev_err(&pdev->dev, "failed to add pwm chip %d\n", ret);
return ret; return ret;
} }
platform_set_drvdata(pdev, mxs);
ret = stmp_reset_block(mxs->base);
if (ret)
goto pwm_remove;
return 0; return 0;
pwm_remove:
pwmchip_remove(&mxs->chip);
return ret;
}
static int mxs_pwm_remove(struct platform_device *pdev)
{
struct mxs_pwm_chip *mxs = platform_get_drvdata(pdev);
return pwmchip_remove(&mxs->chip);
} }
static const struct of_device_id mxs_pwm_dt_ids[] = { static const struct of_device_id mxs_pwm_dt_ids[] = {
...@@ -183,7 +171,6 @@ static struct platform_driver mxs_pwm_driver = { ...@@ -183,7 +171,6 @@ static struct platform_driver mxs_pwm_driver = {
.of_match_table = mxs_pwm_dt_ids, .of_match_table = mxs_pwm_dt_ids,
}, },
.probe = mxs_pwm_probe, .probe = mxs_pwm_probe,
.remove = mxs_pwm_remove,
}; };
module_platform_driver(mxs_pwm_driver); module_platform_driver(mxs_pwm_driver);
......
...@@ -150,23 +150,12 @@ static int ntxec_pwm_probe(struct platform_device *pdev) ...@@ -150,23 +150,12 @@ static int ntxec_pwm_probe(struct platform_device *pdev)
priv->ec = ec; priv->ec = ec;
priv->dev = &pdev->dev; priv->dev = &pdev->dev;
platform_set_drvdata(pdev, priv);
chip = &priv->chip; chip = &priv->chip;
chip->dev = &pdev->dev; chip->dev = &pdev->dev;
chip->ops = &ntxec_pwm_ops; chip->ops = &ntxec_pwm_ops;
chip->base = -1;
chip->npwm = 1; chip->npwm = 1;
return pwmchip_add(chip); return devm_pwmchip_add(&pdev->dev, chip);
}
static int ntxec_pwm_remove(struct platform_device *pdev)
{
struct ntxec_pwm *priv = platform_get_drvdata(pdev);
struct pwm_chip *chip = &priv->chip;
return pwmchip_remove(chip);
} }
static struct platform_driver ntxec_pwm_driver = { static struct platform_driver ntxec_pwm_driver = {
...@@ -174,7 +163,6 @@ static struct platform_driver ntxec_pwm_driver = { ...@@ -174,7 +163,6 @@ static struct platform_driver ntxec_pwm_driver = {
.name = "ntxec-pwm", .name = "ntxec-pwm",
}, },
.probe = ntxec_pwm_probe, .probe = ntxec_pwm_probe,
.remove = ntxec_pwm_remove,
}; };
module_platform_driver(ntxec_pwm_driver); module_platform_driver(ntxec_pwm_driver);
......
...@@ -444,11 +444,8 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev) ...@@ -444,11 +444,8 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
static int pwm_omap_dmtimer_remove(struct platform_device *pdev) static int pwm_omap_dmtimer_remove(struct platform_device *pdev)
{ {
struct pwm_omap_dmtimer_chip *omap = platform_get_drvdata(pdev); struct pwm_omap_dmtimer_chip *omap = platform_get_drvdata(pdev);
int ret;
ret = pwmchip_remove(&omap->chip); pwmchip_remove(&omap->chip);
if (ret)
return ret;
if (pm_runtime_active(&omap->dm_timer_pdev->dev)) if (pm_runtime_active(&omap->dm_timer_pdev->dev))
omap->pdata->stop(omap->dm_timer); omap->pdata->stop(omap->dm_timer);
......
...@@ -601,11 +601,8 @@ static int pca9685_pwm_probe(struct i2c_client *client, ...@@ -601,11 +601,8 @@ static int pca9685_pwm_probe(struct i2c_client *client,
static int pca9685_pwm_remove(struct i2c_client *client) static int pca9685_pwm_remove(struct i2c_client *client)
{ {
struct pca9685 *pca = i2c_get_clientdata(client); struct pca9685 *pca = i2c_get_clientdata(client);
int ret;
ret = pwmchip_remove(&pca->chip); pwmchip_remove(&pca->chip);
if (ret)
return ret;
if (!pm_runtime_enabled(&client->dev)) { if (!pm_runtime_enabled(&client->dev)) {
/* Put chip in sleep state if runtime PM is disabled */ /* Put chip in sleep state if runtime PM is disabled */
......
...@@ -195,32 +195,21 @@ static int pwm_probe(struct platform_device *pdev) ...@@ -195,32 +195,21 @@ static int pwm_probe(struct platform_device *pdev)
if (IS_ERR(pc->mmio_base)) if (IS_ERR(pc->mmio_base))
return PTR_ERR(pc->mmio_base); return PTR_ERR(pc->mmio_base);
ret = pwmchip_add(&pc->chip); ret = devm_pwmchip_add(&pdev->dev, &pc->chip);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
return ret; return ret;
} }
platform_set_drvdata(pdev, pc);
return 0; return 0;
} }
static int pwm_remove(struct platform_device *pdev)
{
struct pxa_pwm_chip *pc;
pc = platform_get_drvdata(pdev);
return pwmchip_remove(&pc->chip);
}
static struct platform_driver pwm_driver = { static struct platform_driver pwm_driver = {
.driver = { .driver = {
.name = "pxa25x-pwm", .name = "pxa25x-pwm",
.of_match_table = pwm_of_match, .of_match_table = pwm_of_match,
}, },
.probe = pwm_probe, .probe = pwm_probe,
.remove = pwm_remove,
.id_table = pwm_id_table, .id_table = pwm_id_table,
}; };
......
...@@ -166,8 +166,6 @@ static int raspberrypi_pwm_probe(struct platform_device *pdev) ...@@ -166,8 +166,6 @@ static int raspberrypi_pwm_probe(struct platform_device *pdev)
rpipwm->chip.base = -1; rpipwm->chip.base = -1;
rpipwm->chip.npwm = RASPBERRYPI_FIRMWARE_PWM_NUM; rpipwm->chip.npwm = RASPBERRYPI_FIRMWARE_PWM_NUM;
platform_set_drvdata(pdev, rpipwm);
ret = raspberrypi_pwm_get_property(rpipwm->firmware, RPI_PWM_CUR_DUTY_REG, ret = raspberrypi_pwm_get_property(rpipwm->firmware, RPI_PWM_CUR_DUTY_REG,
&rpipwm->duty_cycle); &rpipwm->duty_cycle);
if (ret) { if (ret) {
...@@ -175,14 +173,7 @@ static int raspberrypi_pwm_probe(struct platform_device *pdev) ...@@ -175,14 +173,7 @@ static int raspberrypi_pwm_probe(struct platform_device *pdev)
return ret; return ret;
} }
return pwmchip_add(&rpipwm->chip); return devm_pwmchip_add(dev, &rpipwm->chip);
}
static int raspberrypi_pwm_remove(struct platform_device *pdev)
{
struct raspberrypi_pwm *rpipwm = platform_get_drvdata(pdev);
return pwmchip_remove(&rpipwm->chip);
} }
static const struct of_device_id raspberrypi_pwm_of_match[] = { static const struct of_device_id raspberrypi_pwm_of_match[] = {
...@@ -197,7 +188,6 @@ static struct platform_driver raspberrypi_pwm_driver = { ...@@ -197,7 +188,6 @@ static struct platform_driver raspberrypi_pwm_driver = {
.of_match_table = raspberrypi_pwm_of_match, .of_match_table = raspberrypi_pwm_of_match,
}, },
.probe = raspberrypi_pwm_probe, .probe = raspberrypi_pwm_probe,
.remove = raspberrypi_pwm_remove,
}; };
module_platform_driver(raspberrypi_pwm_driver); module_platform_driver(raspberrypi_pwm_driver);
......
...@@ -241,13 +241,12 @@ static int rcar_pwm_probe(struct platform_device *pdev) ...@@ -241,13 +241,12 @@ static int rcar_pwm_probe(struct platform_device *pdev)
static int rcar_pwm_remove(struct platform_device *pdev) static int rcar_pwm_remove(struct platform_device *pdev)
{ {
struct rcar_pwm_chip *rcar_pwm = platform_get_drvdata(pdev); struct rcar_pwm_chip *rcar_pwm = platform_get_drvdata(pdev);
int ret;
ret = pwmchip_remove(&rcar_pwm->chip); pwmchip_remove(&rcar_pwm->chip);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
return ret; return 0;
} }
static const struct of_device_id rcar_pwm_of_table[] = { static const struct of_device_id rcar_pwm_of_table[] = {
......
...@@ -425,13 +425,12 @@ static int tpu_probe(struct platform_device *pdev) ...@@ -425,13 +425,12 @@ static int tpu_probe(struct platform_device *pdev)
static int tpu_remove(struct platform_device *pdev) static int tpu_remove(struct platform_device *pdev)
{ {
struct tpu_device *tpu = platform_get_drvdata(pdev); struct tpu_device *tpu = platform_get_drvdata(pdev);
int ret;
ret = pwmchip_remove(&tpu->chip); pwmchip_remove(&tpu->chip);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
return ret; return 0;
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
......
...@@ -384,24 +384,12 @@ static int rockchip_pwm_remove(struct platform_device *pdev) ...@@ -384,24 +384,12 @@ static int rockchip_pwm_remove(struct platform_device *pdev)
{ {
struct rockchip_pwm_chip *pc = platform_get_drvdata(pdev); struct rockchip_pwm_chip *pc = platform_get_drvdata(pdev);
/* pwmchip_remove(&pc->chip);
* Disable the PWM clk before unpreparing it if the PWM device is still
* running. This should only happen when the last PWM user left it
* enabled, or when nobody requested a PWM that was previously enabled
* by the bootloader.
*
* FIXME: Maybe the core should disable all PWM devices in
* pwmchip_remove(). In this case we'd only have to call
* clk_unprepare() after pwmchip_remove().
*
*/
if (pwm_is_enabled(pc->chip.pwms))
clk_disable(pc->clk);
clk_unprepare(pc->pclk); clk_unprepare(pc->pclk);
clk_unprepare(pc->clk); clk_unprepare(pc->clk);
return pwmchip_remove(&pc->chip); return 0;
} }
static struct platform_driver rockchip_pwm_driver = { static struct platform_driver rockchip_pwm_driver = {
......
...@@ -580,11 +580,8 @@ static int pwm_samsung_probe(struct platform_device *pdev) ...@@ -580,11 +580,8 @@ static int pwm_samsung_probe(struct platform_device *pdev)
static int pwm_samsung_remove(struct platform_device *pdev) static int pwm_samsung_remove(struct platform_device *pdev)
{ {
struct samsung_pwm_chip *chip = platform_get_drvdata(pdev); struct samsung_pwm_chip *chip = platform_get_drvdata(pdev);
int ret;
ret = pwmchip_remove(&chip->chip); pwmchip_remove(&chip->chip);
if (ret < 0)
return ret;
clk_disable_unprepare(chip->base_clk); clk_disable_unprepare(chip->base_clk);
......
...@@ -291,7 +291,7 @@ static int pwm_sifive_remove(struct platform_device *dev) ...@@ -291,7 +291,7 @@ static int pwm_sifive_remove(struct platform_device *dev)
struct pwm_sifive_ddata *ddata = platform_get_drvdata(dev); struct pwm_sifive_ddata *ddata = platform_get_drvdata(dev);
bool is_enabled = false; bool is_enabled = false;
struct pwm_device *pwm; struct pwm_device *pwm;
int ret, ch; int ch;
for (ch = 0; ch < ddata->chip.npwm; ch++) { for (ch = 0; ch < ddata->chip.npwm; ch++) {
pwm = &ddata->chip.pwms[ch]; pwm = &ddata->chip.pwms[ch];
...@@ -304,10 +304,10 @@ static int pwm_sifive_remove(struct platform_device *dev) ...@@ -304,10 +304,10 @@ static int pwm_sifive_remove(struct platform_device *dev)
clk_disable(ddata->clk); clk_disable(ddata->clk);
clk_disable_unprepare(ddata->clk); clk_disable_unprepare(ddata->clk);
ret = pwmchip_remove(&ddata->chip); pwmchip_remove(&ddata->chip);
clk_notifier_unregister(ddata->clk, &ddata->notifier); clk_notifier_unregister(ddata->clk, &ddata->notifier);
return ret; return 0;
} }
static const struct of_device_id pwm_sifive_of_match[] = { static const struct of_device_id pwm_sifive_of_match[] = {
......
...@@ -231,9 +231,7 @@ static int sl28cpld_pwm_probe(struct platform_device *pdev) ...@@ -231,9 +231,7 @@ static int sl28cpld_pwm_probe(struct platform_device *pdev)
chip->ops = &sl28cpld_pwm_ops; chip->ops = &sl28cpld_pwm_ops;
chip->npwm = 1; chip->npwm = 1;
platform_set_drvdata(pdev, priv); ret = devm_pwmchip_add(&pdev->dev, &priv->pwm_chip);
ret = pwmchip_add(&priv->pwm_chip);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to add PWM chip (%pe)", dev_err(&pdev->dev, "failed to add PWM chip (%pe)",
ERR_PTR(ret)); ERR_PTR(ret));
...@@ -243,13 +241,6 @@ static int sl28cpld_pwm_probe(struct platform_device *pdev) ...@@ -243,13 +241,6 @@ static int sl28cpld_pwm_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int sl28cpld_pwm_remove(struct platform_device *pdev)
{
struct sl28cpld_pwm *priv = platform_get_drvdata(pdev);
return pwmchip_remove(&priv->pwm_chip);
}
static const struct of_device_id sl28cpld_pwm_of_match[] = { static const struct of_device_id sl28cpld_pwm_of_match[] = {
{ .compatible = "kontron,sl28cpld-pwm" }, { .compatible = "kontron,sl28cpld-pwm" },
{} {}
...@@ -258,7 +249,6 @@ MODULE_DEVICE_TABLE(of, sl28cpld_pwm_of_match); ...@@ -258,7 +249,6 @@ MODULE_DEVICE_TABLE(of, sl28cpld_pwm_of_match);
static struct platform_driver sl28cpld_pwm_driver = { static struct platform_driver sl28cpld_pwm_driver = {
.probe = sl28cpld_pwm_probe, .probe = sl28cpld_pwm_probe,
.remove = sl28cpld_pwm_remove,
.driver = { .driver = {
.name = "sl28cpld-pwm", .name = "sl28cpld-pwm",
.of_match_table = sl28cpld_pwm_of_match, .of_match_table = sl28cpld_pwm_of_match,
......
...@@ -209,7 +209,7 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev) ...@@ -209,7 +209,7 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev)
priv->chip.ops = &stm32_pwm_lp_ops; priv->chip.ops = &stm32_pwm_lp_ops;
priv->chip.npwm = 1; priv->chip.npwm = 1;
ret = pwmchip_add(&priv->chip); ret = devm_pwmchip_add(&pdev->dev, &priv->chip);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -218,15 +218,6 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev) ...@@ -218,15 +218,6 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int stm32_pwm_lp_remove(struct platform_device *pdev)
{
struct stm32_pwm_lp *priv = platform_get_drvdata(pdev);
pwm_disable(&priv->chip.pwms[0]);
return pwmchip_remove(&priv->chip);
}
static int __maybe_unused stm32_pwm_lp_suspend(struct device *dev) static int __maybe_unused stm32_pwm_lp_suspend(struct device *dev)
{ {
struct stm32_pwm_lp *priv = dev_get_drvdata(dev); struct stm32_pwm_lp *priv = dev_get_drvdata(dev);
...@@ -258,7 +249,6 @@ MODULE_DEVICE_TABLE(of, stm32_pwm_lp_of_match); ...@@ -258,7 +249,6 @@ MODULE_DEVICE_TABLE(of, stm32_pwm_lp_of_match);
static struct platform_driver stm32_pwm_lp_driver = { static struct platform_driver stm32_pwm_lp_driver = {
.probe = stm32_pwm_lp_probe, .probe = stm32_pwm_lp_probe,
.remove = stm32_pwm_lp_remove,
.driver = { .driver = {
.name = "stm32-pwm-lp", .name = "stm32-pwm-lp",
.of_match_table = of_match_ptr(stm32_pwm_lp_of_match), .of_match_table = of_match_ptr(stm32_pwm_lp_of_match),
......
...@@ -484,11 +484,8 @@ static int sun4i_pwm_probe(struct platform_device *pdev) ...@@ -484,11 +484,8 @@ static int sun4i_pwm_probe(struct platform_device *pdev)
static int sun4i_pwm_remove(struct platform_device *pdev) static int sun4i_pwm_remove(struct platform_device *pdev)
{ {
struct sun4i_pwm_chip *pwm = platform_get_drvdata(pdev); struct sun4i_pwm_chip *pwm = platform_get_drvdata(pdev);
int ret;
ret = pwmchip_remove(&pwm->chip); pwmchip_remove(&pwm->chip);
if (ret)
return ret;
clk_disable_unprepare(pwm->bus_clk); clk_disable_unprepare(pwm->bus_clk);
reset_control_assert(pwm->rst); reset_control_assert(pwm->rst);
......
...@@ -253,7 +253,7 @@ static int ecap_pwm_probe(struct platform_device *pdev) ...@@ -253,7 +253,7 @@ static int ecap_pwm_probe(struct platform_device *pdev)
if (IS_ERR(pc->mmio_base)) if (IS_ERR(pc->mmio_base))
return PTR_ERR(pc->mmio_base); return PTR_ERR(pc->mmio_base);
ret = pwmchip_add(&pc->chip); ret = devm_pwmchip_add(&pdev->dev, &pc->chip);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
return ret; return ret;
...@@ -267,11 +267,9 @@ static int ecap_pwm_probe(struct platform_device *pdev) ...@@ -267,11 +267,9 @@ static int ecap_pwm_probe(struct platform_device *pdev)
static int ecap_pwm_remove(struct platform_device *pdev) static int ecap_pwm_remove(struct platform_device *pdev)
{ {
struct ecap_pwm_chip *pc = platform_get_drvdata(pdev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
return pwmchip_remove(&pc->chip); return 0;
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
......
...@@ -485,11 +485,13 @@ static int ehrpwm_pwm_remove(struct platform_device *pdev) ...@@ -485,11 +485,13 @@ static int ehrpwm_pwm_remove(struct platform_device *pdev)
{ {
struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev); struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev);
pwmchip_remove(&pc->chip);
clk_unprepare(pc->tbclk); clk_unprepare(pc->tbclk);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
return pwmchip_remove(&pc->chip); return 0;
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
......
...@@ -276,7 +276,6 @@ static const struct pwm_ops twl6030_pwmled_ops = { ...@@ -276,7 +276,6 @@ static const struct pwm_ops twl6030_pwmled_ops = {
static int twl_pwmled_probe(struct platform_device *pdev) static int twl_pwmled_probe(struct platform_device *pdev)
{ {
struct twl_pwmled_chip *twl; struct twl_pwmled_chip *twl;
int ret;
twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL); twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL);
if (!twl) if (!twl)
...@@ -294,20 +293,7 @@ static int twl_pwmled_probe(struct platform_device *pdev) ...@@ -294,20 +293,7 @@ static int twl_pwmled_probe(struct platform_device *pdev)
mutex_init(&twl->mutex); mutex_init(&twl->mutex);
ret = pwmchip_add(&twl->chip); return devm_pwmchip_add(&pdev->dev, &twl->chip);
if (ret < 0)
return ret;
platform_set_drvdata(pdev, twl);
return 0;
}
static int twl_pwmled_remove(struct platform_device *pdev)
{
struct twl_pwmled_chip *twl = platform_get_drvdata(pdev);
return pwmchip_remove(&twl->chip);
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
...@@ -325,7 +311,6 @@ static struct platform_driver twl_pwmled_driver = { ...@@ -325,7 +311,6 @@ static struct platform_driver twl_pwmled_driver = {
.of_match_table = of_match_ptr(twl_pwmled_of_match), .of_match_table = of_match_ptr(twl_pwmled_of_match),
}, },
.probe = twl_pwmled_probe, .probe = twl_pwmled_probe,
.remove = twl_pwmled_remove,
}; };
module_platform_driver(twl_pwmled_driver); module_platform_driver(twl_pwmled_driver);
......
...@@ -298,7 +298,6 @@ static const struct pwm_ops twl6030_pwm_ops = { ...@@ -298,7 +298,6 @@ static const struct pwm_ops twl6030_pwm_ops = {
static int twl_pwm_probe(struct platform_device *pdev) static int twl_pwm_probe(struct platform_device *pdev)
{ {
struct twl_pwm_chip *twl; struct twl_pwm_chip *twl;
int ret;
twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL); twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL);
if (!twl) if (!twl)
...@@ -314,20 +313,7 @@ static int twl_pwm_probe(struct platform_device *pdev) ...@@ -314,20 +313,7 @@ static int twl_pwm_probe(struct platform_device *pdev)
mutex_init(&twl->mutex); mutex_init(&twl->mutex);
ret = pwmchip_add(&twl->chip); return devm_pwmchip_add(&pdev->dev, &twl->chip);
if (ret < 0)
return ret;
platform_set_drvdata(pdev, twl);
return 0;
}
static int twl_pwm_remove(struct platform_device *pdev)
{
struct twl_pwm_chip *twl = platform_get_drvdata(pdev);
return pwmchip_remove(&twl->chip);
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
...@@ -345,7 +331,6 @@ static struct platform_driver twl_pwm_driver = { ...@@ -345,7 +331,6 @@ static struct platform_driver twl_pwm_driver = {
.of_match_table = of_match_ptr(twl_pwm_of_match), .of_match_table = of_match_ptr(twl_pwm_of_match),
}, },
.probe = twl_pwm_probe, .probe = twl_pwm_probe,
.remove = twl_pwm_remove,
}; };
module_platform_driver(twl_pwm_driver); module_platform_driver(twl_pwm_driver);
......
...@@ -404,7 +404,7 @@ int pwm_set_chip_data(struct pwm_device *pwm, void *data); ...@@ -404,7 +404,7 @@ int pwm_set_chip_data(struct pwm_device *pwm, void *data);
void *pwm_get_chip_data(struct pwm_device *pwm); void *pwm_get_chip_data(struct pwm_device *pwm);
int pwmchip_add(struct pwm_chip *chip); int pwmchip_add(struct pwm_chip *chip);
int pwmchip_remove(struct pwm_chip *chip); void pwmchip_remove(struct pwm_chip *chip);
int devm_pwmchip_add(struct device *dev, struct pwm_chip *chip); int devm_pwmchip_add(struct device *dev, struct pwm_chip *chip);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment