Merge tag 'pwm/for-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 11 Sep 2021 16:26:00 +0000 (09:26 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 11 Sep 2021 16:26:00 +0000 (09:26 -0700)
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()
  ...

43 files changed:
Documentation/devicetree/bindings/pwm/pwm-rockchip.yaml
drivers/pwm/Kconfig
drivers/pwm/core.c
drivers/pwm/pwm-ab8500.c
drivers/pwm/pwm-atmel-hlcdc.c
drivers/pwm/pwm-atmel-tcb.c
drivers/pwm/pwm-atmel.c
drivers/pwm/pwm-bcm-kona.c
drivers/pwm/pwm-brcmstb.c
drivers/pwm/pwm-cros-ec.c
drivers/pwm/pwm-ep93xx.c
drivers/pwm/pwm-fsl-ftm.c
drivers/pwm/pwm-hibvt.c
drivers/pwm/pwm-img.c
drivers/pwm/pwm-imx-tpm.c
drivers/pwm/pwm-imx27.c
drivers/pwm/pwm-intel-lgm.c
drivers/pwm/pwm-iqs620a.c
drivers/pwm/pwm-jz4740.c
drivers/pwm/pwm-keembay.c
drivers/pwm/pwm-lp3943.c
drivers/pwm/pwm-lpc32xx.c
drivers/pwm/pwm-mediatek.c
drivers/pwm/pwm-mtk-disp.c
drivers/pwm/pwm-mxs.c
drivers/pwm/pwm-ntxec.c
drivers/pwm/pwm-omap-dmtimer.c
drivers/pwm/pwm-pca9685.c
drivers/pwm/pwm-pxa.c
drivers/pwm/pwm-raspberrypi-poe.c
drivers/pwm/pwm-rcar.c
drivers/pwm/pwm-renesas-tpu.c
drivers/pwm/pwm-rockchip.c
drivers/pwm/pwm-samsung.c
drivers/pwm/pwm-sifive.c
drivers/pwm/pwm-sl28cpld.c
drivers/pwm/pwm-stm32-lp.c
drivers/pwm/pwm-sun4i.c
drivers/pwm/pwm-tiecap.c
drivers/pwm/pwm-tiehrpwm.c
drivers/pwm/pwm-twl-led.c
drivers/pwm/pwm-twl.c
include/linux/pwm.h

index 5596bee..81a54a4 100644 (file)
@@ -29,6 +29,7 @@ properties:
           - enum:
               - rockchip,px30-pwm
               - rockchip,rk3308-pwm
+              - rockchip,rk3568-pwm
           - const: rockchip,rk3328-pwm
 
   reg:
index c76aded..aa29841 100644 (file)
@@ -272,7 +272,7 @@ config PWM_IQS620A
 
 config PWM_JZ4740
        tristate "Ingenic JZ47xx PWM support"
-       depends on MIPS
+       depends on MIPS || COMPILE_TEST
        depends on COMMON_CLK
        select MFD_SYSCON
        help
@@ -284,7 +284,8 @@ config PWM_JZ4740
 
 config PWM_KEEMBAY
        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
          The platform driver for Intel Keem Bay PWM controller.
 
index 35e894f..4527f09 100644 (file)
@@ -304,7 +304,7 @@ EXPORT_SYMBOL_GPL(pwmchip_add);
  *
  * 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);
 
@@ -318,8 +318,6 @@ int pwmchip_remove(struct pwm_chip *chip)
        free_pwms(chip);
 
        mutex_unlock(&pwm_lock);
-
-       return 0;
 }
 EXPORT_SYMBOL_GPL(pwmchip_remove);
 
index e2a26d9..ad37bc4 100644 (file)
 
 struct ab8500_pwm_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,
                            const struct pwm_state *state)
 {
        int ret;
        u8 reg;
        unsigned int higher_val, lower_val;
+       struct ab8500_pwm_chip *ab8500 = ab8500_pwm_from_chip(chip);
 
        if (state->polarity != PWM_POLARITY_NORMAL)
                return -EINVAL;
@@ -37,7 +44,7 @@ static int ab8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
        if (!state->enabled) {
                ret = abx500_mask_and_set_register_interruptible(chip->dev,
                                        AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
-                                       1 << (chip->base - 1), 0);
+                                       1 << ab8500->hwid, 0);
 
                if (ret < 0)
                        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,
         */
        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,
                        reg, (u8)lower_val);
@@ -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,
                                AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
-                               1 << (chip->base - 1), 1 << (chip->base - 1));
+                               1 << ab8500->hwid, 1 << ab8500->hwid);
        if (ret < 0)
                dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n",
                                                        pwm->label, ret);
@@ -88,6 +95,9 @@ static int ab8500_pwm_probe(struct platform_device *pdev)
        struct ab8500_pwm_chip *ab8500;
        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
         * device which is required for ab8500 read and write
@@ -99,27 +109,13 @@ static int ab8500_pwm_probe(struct platform_device *pdev)
        ab8500->chip.dev = &pdev->dev;
        ab8500->chip.ops = &ab8500_pwm_ops;
        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)
                return dev_err_probe(&pdev->dev, err, "Failed to add pwm chip\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;
 }
@@ -129,7 +125,6 @@ static struct platform_driver ab8500_pwm_driver = {
                .name = "ab8500-pwm",
        },
        .probe = ab8500_pwm_probe,
-       .remove = ab8500_pwm_remove,
 };
 module_platform_driver(ab8500_pwm_driver);
 
index 4459325..a43b2ba 100644 (file)
@@ -281,11 +281,8 @@ static int atmel_hlcdc_pwm_probe(struct platform_device *pdev)
 static int atmel_hlcdc_pwm_remove(struct platform_device *pdev)
 {
        struct atmel_hlcdc_pwm *chip = platform_get_drvdata(pdev);
-       int ret;
 
-       ret = pwmchip_remove(&chip->chip);
-       if (ret)
-               return ret;
+       pwmchip_remove(&chip->chip);
 
        clk_disable_unprepare(chip->hlcdc->periph_clk);
 
index bf398f2..36f7ea3 100644 (file)
@@ -503,11 +503,8 @@ err_slow_clk:
 static int atmel_tcb_pwm_remove(struct platform_device *pdev)
 {
        struct atmel_tcb_pwm_chip *tcbpwm = platform_get_drvdata(pdev);
-       int err;
 
-       err = pwmchip_remove(&tcbpwm->chip);
-       if (err < 0)
-               return err;
+       pwmchip_remove(&tcbpwm->chip);
 
        clk_disable_unprepare(tcbpwm->slow_clk);
        clk_put(tcbpwm->slow_clk);
index a8162ba..e748604 100644 (file)
@@ -84,9 +84,19 @@ struct atmel_pwm_chip {
        void __iomem *base;
        const struct atmel_pwm_data *data;
 
-       unsigned int updated_pwms;
-       /* ISR is cleared when read, ensure only one thread does that */
-       struct mutex isr_lock;
+       /*
+        * The hardware supports a mechanism to update a channel's duty cycle at
+        * 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)
@@ -123,6 +133,64 @@ static inline void atmel_pwm_ch_writel(struct atmel_pwm_chip *chip,
        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,
                                             unsigned long clkrate,
                                             const struct pwm_state *state,
@@ -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->data->regs.duty_upd, cdty);
+       atmel_pwm_set_pending(atmel_pwm, pwm->hwpwm);
 }
 
 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,
        struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
        unsigned long timeout = jiffies + 2 * HZ;
 
-       /*
-        * 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);
-       }
+       atmel_pwm_wait_nonpending(atmel_pwm, pwm->hwpwm);
 
-       mutex_unlock(&atmel_pwm->isr_lock);
        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,
                        val |= PWM_CMR_CPOL;
                atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
                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);
        } else if (cstate.enabled) {
                atmel_pwm_disable(chip, pwm, true);
@@ -326,6 +379,9 @@ static void atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
                tmp <<= pres;
                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,
                                          atmel_pwm->data->regs.duty);
                tmp = (u64)(cprd - cdty) * NSEC_PER_SEC;
@@ -416,9 +472,10 @@ static int atmel_pwm_probe(struct platform_device *pdev)
        if (!atmel_pwm)
                return -ENOMEM;
 
-       mutex_init(&atmel_pwm->isr_lock);
        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);
        if (IS_ERR(atmel_pwm->base))
@@ -460,7 +517,6 @@ static int atmel_pwm_remove(struct platform_device *pdev)
        pwmchip_remove(&atmel_pwm->chip);
 
        clk_unprepare(atmel_pwm->clk);
-       mutex_destroy(&atmel_pwm->isr_lock);
 
        return 0;
 }
index 8c85c66..64148f5 100644 (file)
@@ -267,8 +267,6 @@ static int kona_pwmc_probe(struct platform_device *pdev)
        if (kp == NULL)
                return -ENOMEM;
 
-       platform_set_drvdata(pdev, kp);
-
        kp->chip.dev = &pdev->dev;
        kp->chip.ops = &kona_pwm_ops;
        kp->chip.npwm = 6;
@@ -298,20 +296,13 @@ static int kona_pwmc_probe(struct platform_device *pdev)
 
        clk_disable_unprepare(kp->clk);
 
-       ret = pwmchip_add(&kp->chip);
+       ret = devm_pwmchip_add(&pdev->dev, &kp->chip);
        if (ret < 0)
                dev_err(&pdev->dev, "failed to add PWM chip: %d\n", 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[] = {
        { .compatible = "brcm,kona-pwm" },
        { },
@@ -324,7 +315,6 @@ static struct platform_driver kona_pwmc_driver = {
                .of_match_table = bcm_kona_pwmc_dt,
        },
        .probe = kona_pwmc_probe,
-       .remove = kona_pwmc_remove,
 };
 module_platform_driver(kona_pwmc_driver);
 
index 8b1d1e7..3b529f8 100644 (file)
@@ -282,12 +282,11 @@ out_clk:
 static int brcmstb_pwm_remove(struct platform_device *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);
 
-       return ret;
+       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index 9fffb56..5e29d9c 100644 (file)
@@ -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 pwm_chip *chip = &ec_pwm->chip;
 
-       return pwmchip_remove(chip);
+       pwmchip_remove(chip);
+
+       return 0;
 }
 
 #ifdef CONFIG_OF
index fc3cb7d..c45a75e 100644 (file)
@@ -183,27 +183,18 @@ static int ep93xx_pwm_probe(struct platform_device *pdev)
        ep93xx_pwm->chip.ops = &ep93xx_pwm_ops;
        ep93xx_pwm->chip.npwm = 1;
 
-       ret = pwmchip_add(&ep93xx_pwm->chip);
+       ret = devm_pwmchip_add(&pdev->dev, &ep93xx_pwm->chip);
        if (ret < 0)
                return ret;
 
-       platform_set_drvdata(pdev, ep93xx_pwm);
        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 = {
        .driver = {
                .name = "ep93xx-pwm",
        },
        .probe = ep93xx_pwm_probe,
-       .remove = ep93xx_pwm_remove,
 };
 module_platform_driver(ep93xx_pwm_driver);
 
index 96ccd77..0247757 100644 (file)
@@ -453,7 +453,7 @@ static int fsl_pwm_probe(struct platform_device *pdev)
        fpc->chip.ops = &fsl_pwm_ops;
        fpc->chip.npwm = 8;
 
-       ret = pwmchip_add(&fpc->chip);
+       ret = devm_pwmchip_add(&pdev->dev, &fpc->chip);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
                return ret;
@@ -464,13 +464,6 @@ static int fsl_pwm_probe(struct platform_device *pdev)
        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
 static int fsl_pwm_suspend(struct device *dev)
 {
@@ -552,7 +545,6 @@ static struct platform_driver fsl_pwm_driver = {
                .pm = &fsl_pwm_pm_ops,
        },
        .probe = fsl_pwm_probe,
-       .remove = fsl_pwm_remove,
 };
 module_platform_driver(fsl_pwm_driver);
 
index 4a6e9ad..333f1b1 100644 (file)
@@ -248,13 +248,15 @@ static int hibvt_pwm_remove(struct platform_device *pdev)
 
        pwm_chip = platform_get_drvdata(pdev);
 
+       pwmchip_remove(&pwm_chip->chip);
+
        reset_control_assert(pwm_chip->rstc);
        msleep(30);
        reset_control_deassert(pwm_chip->rstc);
 
        clk_disable_unprepare(pwm_chip->clk);
 
-       return pwmchip_remove(&pwm_chip->chip);
+       return 0;
 }
 
 static const struct of_device_id hibvt_pwm_of_match[] = {
index 11b16ec..f97f825 100644 (file)
@@ -326,28 +326,14 @@ err_pm_disable:
 static int img_pwm_remove(struct platform_device *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);
        if (!pm_runtime_status_suspended(&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
index dbb5049..e5e7b7c 100644 (file)
@@ -382,11 +382,12 @@ static int pwm_imx_tpm_probe(struct platform_device *pdev)
 static int pwm_imx_tpm_remove(struct platform_device *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);
 
-       return ret;
+       return 0;
 }
 
 static int __maybe_unused pwm_imx_tpm_suspend(struct device *dev)
index f6588a9..ea91a2f 100644 (file)
@@ -313,8 +313,6 @@ static int pwm_imx27_probe(struct platform_device *pdev)
        if (imx == NULL)
                return -ENOMEM;
 
-       platform_set_drvdata(pdev, imx);
-
        imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
        if (IS_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)
        if (!(pwmcr & MX3_PWMCR_EN))
                pwm_imx27_clk_disable_unprepare(imx);
 
-       return pwmchip_add(&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);
+       return devm_pwmchip_add(&pdev->dev, &imx->chip);
 }
 
 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,
        },
        .probe = pwm_imx27_probe,
-       .remove = pwm_imx27_remove,
 };
 module_platform_driver(imx_pwm_driver);
 
index 015f5eb..b66c350 100644 (file)
@@ -176,8 +176,6 @@ static int lgm_pwm_probe(struct platform_device *pdev)
        if (!pc)
                return -ENOMEM;
 
-       platform_set_drvdata(pdev, pc);
-
        io_base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(io_base))
                return PTR_ERR(io_base);
@@ -210,20 +208,13 @@ static int lgm_pwm_probe(struct platform_device *pdev)
 
        lgm_pwm_init(pc);
 
-       ret = pwmchip_add(&pc->chip);
+       ret = devm_pwmchip_add(dev, &pc->chip);
        if (ret < 0)
                return dev_err_probe(dev, ret, "failed to add PWM chip\n");
 
        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[] = {
        { .compatible = "intel,lgm-pwm" },
        { }
@@ -236,7 +227,6 @@ static struct platform_driver lgm_pwm_driver = {
                .of_match_table = lgm_pwm_of_match,
        },
        .probe = lgm_pwm_probe,
-       .remove = lgm_pwm_remove,
 };
 module_platform_driver(lgm_pwm_driver);
 
index 6c6e26d..54bd95a 100644 (file)
@@ -189,7 +189,6 @@ static int iqs620_pwm_probe(struct platform_device *pdev)
        if (!iqs620_pwm)
                return -ENOMEM;
 
-       platform_set_drvdata(pdev, iqs620_pwm);
        iqs620_pwm->iqs62x = iqs62x;
 
        ret = regmap_read(iqs62x->regmap, IQS620_PWR_SETTINGS, &val);
@@ -224,31 +223,18 @@ static int iqs620_pwm_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       ret = pwmchip_add(&iqs620_pwm->chip);
+       ret = devm_pwmchip_add(&pdev->dev, &iqs620_pwm->chip);
        if (ret)
                dev_err(&pdev->dev, "Failed to add device: %d\n", 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 = {
        .driver = {
                .name = "iqs620a-pwm",
        },
        .probe = iqs620_pwm_probe,
-       .remove = iqs620_pwm_remove,
 };
 module_platform_driver(iqs620_pwm_platform_driver);
 
index 990e790..23dc1fb 100644 (file)
@@ -245,16 +245,7 @@ static int jz4740_pwm_probe(struct platform_device *pdev)
        jz4740->chip.ops = &jz4740_pwm_ops;
        jz4740->chip.npwm = info->num_pwms;
 
-       platform_set_drvdata(pdev, jz4740);
-
-       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);
+       return devm_pwmchip_add(dev, &jz4740->chip);
 }
 
 static const struct soc_info __maybe_unused jz4740_soc_info = {
@@ -280,7 +271,6 @@ static struct platform_driver jz4740_pwm_driver = {
                .of_match_table = of_match_ptr(jz4740_pwm_dt_ids),
        },
        .probe = jz4740_pwm_probe,
-       .remove = jz4740_pwm_remove,
 };
 module_platform_driver(jz4740_pwm_driver);
 
index 521a825..733811b 100644 (file)
@@ -207,22 +207,13 @@ static int keembay_pwm_probe(struct platform_device *pdev)
        priv->chip.ops = &keembay_pwm_ops;
        priv->chip.npwm = KMB_TOTAL_PWM_CHANNELS;
 
-       ret = pwmchip_add(&priv->chip);
+       ret = devm_pwmchip_add(dev, &priv->chip);
        if (ret)
                return dev_err_probe(dev, ret, "Failed to add PWM chip\n");
 
-       platform_set_drvdata(pdev, priv);
-
        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[] = {
        { .compatible = "intel,keembay-pwm" },
        { }
@@ -231,7 +222,6 @@ MODULE_DEVICE_TABLE(of, keembay_pwm_of_match);
 
 static struct platform_driver keembay_pwm_driver = {
        .probe  = keembay_pwm_probe,
-       .remove = keembay_pwm_remove,
        .driver = {
                .name = "pwm-keembay",
                .of_match_table = keembay_pwm_of_match,
index 7551253..ea17d44 100644 (file)
@@ -276,16 +276,7 @@ static int lp3943_pwm_probe(struct platform_device *pdev)
        lp3943_pwm->chip.ops = &lp3943_pwm_ops;
        lp3943_pwm->chip.npwm = LP3943_NUM_PWMS;
 
-       platform_set_drvdata(pdev, lp3943_pwm);
-
-       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);
+       return devm_pwmchip_add(&pdev->dev, &lp3943_pwm->chip);
 }
 
 #ifdef CONFIG_OF
@@ -298,7 +289,6 @@ MODULE_DEVICE_TABLE(of, lp3943_pwm_of_match);
 
 static struct platform_driver lp3943_pwm_driver = {
        .probe = lp3943_pwm_probe,
-       .remove = lp3943_pwm_remove,
        .driver = {
                .name = "lp3943-pwm",
                .of_match_table = of_match_ptr(lp3943_pwm_of_match),
index 2834a0f..ddeab56 100644 (file)
@@ -117,29 +117,20 @@ static int lpc32xx_pwm_probe(struct platform_device *pdev)
        lpc32xx->chip.ops = &lpc32xx_pwm_ops;
        lpc32xx->chip.npwm = 1;
 
-       ret = pwmchip_add(&lpc32xx->chip);
-       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 */
+       /* If PWM is disabled, configure the output to the default value */
        val = readl(lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2));
        val &= ~PWM_PIN_LEVEL;
        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;
 }
 
-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[] = {
        { .compatible = "nxp,lpc3220-pwm", },
        { /* sentinel */ }
@@ -152,7 +143,6 @@ static struct platform_driver lpc32xx_pwm_driver = {
                .of_match_table = lpc32xx_pwm_dt_ids,
        },
        .probe = lpc32xx_pwm_probe,
-       .remove = lpc32xx_pwm_remove,
 };
 module_platform_driver(lpc32xx_pwm_driver);
 
index b4a3106..0d4dd80 100644 (file)
@@ -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.ops = &pwm_mediatek_ops;
        pc->chip.npwm = pc->soc->num_pwms;
 
-       ret = pwmchip_add(&pc->chip);
+       ret = devm_pwmchip_add(&pdev->dev, &pc->chip);
        if (ret < 0) {
                dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
                return ret;
@@ -268,13 +266,6 @@ static int pwm_mediatek_probe(struct platform_device *pdev)
        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 = {
        .num_pwms = 8,
        .pwm45_fixup = false,
@@ -335,7 +326,6 @@ static struct platform_driver pwm_mediatek_driver = {
                .of_match_table = pwm_mediatek_of_match,
        },
        .probe = pwm_mediatek_probe,
-       .remove = pwm_mediatek_remove,
 };
 module_platform_driver(pwm_mediatek_driver);
 
index 9b3ba40..c605013 100644 (file)
@@ -5,6 +5,7 @@
  * Author: YH Huang <yh.huang@mediatek.com>
  */
 
+#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
@@ -47,6 +48,7 @@ struct mtk_disp_pwm {
        struct clk *clk_main;
        struct clk *clk_mm;
        void __iomem *base;
+       bool enabled;
 };
 
 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,
        writel(value, address);
 }
 
-static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
-                              int duty_ns, int period_ns)
+static int mtk_disp_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+                             const struct pwm_state *state)
 {
        struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
        u32 clk_div, period, high_width, value;
        u64 div, rate;
        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.
         * 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,
         * high_width = (PWM_CLK_RATE * duty_ns) / (10^9 * (clk_div + 1))
         */
        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;
-       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;
+       }
 
        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)
                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);
 
-       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,
                                 PWM_CLKDIV_MASK,
                                 clk_div << PWM_CLKDIV_SHIFT);
@@ -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,
                                         mdp->data->commit_mask,
                                         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);
-       clk_disable(mdp->clk_main);
+       mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask,
+                                mdp->data->enable_mask);
+       mdp->enabled = true;
 
        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);
+       u64 rate, period, high_width;
+       u32 clk_div, con0, con1;
        int err;
 
-       err = clk_enable(mdp->clk_main);
-       if (err < 0)
-               return err;
-
-       err = clk_enable(mdp->clk_mm);
+       err = clk_prepare_enable(mdp->clk_main);
        if (err < 0) {
-               clk_disable(mdp->clk_main);
-               return err;
+               dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n", ERR_PTR(err));
+               return;
        }
 
-       mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask,
-                                mdp->data->enable_mask);
-
-       return 0;
-}
-
-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);
+       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;
+       }
 
-       clk_disable(mdp->clk_mm);
-       clk_disable(mdp->clk_main);
+       rate = clk_get_rate(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 = {
-       .config = mtk_disp_pwm_config,
-       .enable = mtk_disp_pwm_enable,
-       .disable = mtk_disp_pwm_disable,
+       .apply = mtk_disp_pwm_apply,
+       .get_state = mtk_disp_pwm_get_state,
        .owner = THIS_MODULE,
 };
 
@@ -192,58 +242,28 @@ static int mtk_disp_pwm_probe(struct platform_device *pdev)
        if (IS_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.ops = &mtk_disp_pwm_ops;
        mdp->chip.npwm = 1;
 
        ret = pwmchip_add(&mdp->chip);
        if (ret < 0) {
-               dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
-               goto disable_clk_mm;
+               dev_err(&pdev->dev, "pwmchip_add() failed: %pe\n", ERR_PTR(ret));
+               return ret;
        }
 
        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;
-
-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)
 {
        struct mtk_disp_pwm *mdp = platform_get_drvdata(pdev);
-       int ret;
 
-       ret = pwmchip_remove(&mdp->chip);
-       clk_unprepare(mdp->clk_mm);
-       clk_unprepare(mdp->clk_main);
+       pwmchip_remove(&mdp->chip);
 
-       return ret;
+       return 0;
 }
 
 static const struct mtk_pwm_data mt2701_pwm_data = {
index a221808..766dbc5 100644 (file)
@@ -145,30 +145,18 @@ static int mxs_pwm_probe(struct platform_device *pdev)
                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) {
                dev_err(&pdev->dev, "failed to add pwm chip %d\n", ret);
                return ret;
        }
 
-       platform_set_drvdata(pdev, mxs);
-
-       ret = stmp_reset_block(mxs->base);
-       if (ret)
-               goto pwm_remove;
-
        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[] = {
@@ -183,7 +171,6 @@ static struct platform_driver mxs_pwm_driver = {
                .of_match_table = mxs_pwm_dt_ids,
        },
        .probe = mxs_pwm_probe,
-       .remove = mxs_pwm_remove,
 };
 module_platform_driver(mxs_pwm_driver);
 
index 50c454c..ab63b08 100644 (file)
@@ -150,23 +150,12 @@ static int ntxec_pwm_probe(struct platform_device *pdev)
        priv->ec = ec;
        priv->dev = &pdev->dev;
 
-       platform_set_drvdata(pdev, priv);
-
        chip = &priv->chip;
        chip->dev = &pdev->dev;
        chip->ops = &ntxec_pwm_ops;
-       chip->base = -1;
        chip->npwm = 1;
 
-       return pwmchip_add(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);
+       return devm_pwmchip_add(&pdev->dev, chip);
 }
 
 static struct platform_driver ntxec_pwm_driver = {
@@ -174,7 +163,6 @@ static struct platform_driver ntxec_pwm_driver = {
                .name = "ntxec-pwm",
        },
        .probe = ntxec_pwm_probe,
-       .remove = ntxec_pwm_remove,
 };
 module_platform_driver(ntxec_pwm_driver);
 
index 507a2d9..fa800fc 100644 (file)
@@ -444,11 +444,8 @@ err_find_timer_pdev:
 static int pwm_omap_dmtimer_remove(struct platform_device *pdev)
 {
        struct pwm_omap_dmtimer_chip *omap = platform_get_drvdata(pdev);
-       int ret;
 
-       ret = pwmchip_remove(&omap->chip);
-       if (ret)
-               return ret;
+       pwmchip_remove(&omap->chip);
 
        if (pm_runtime_active(&omap->dm_timer_pdev->dev))
                omap->pdata->stop(omap->dm_timer);
index 42ed770..c56001a 100644 (file)
@@ -601,11 +601,8 @@ static int pca9685_pwm_probe(struct i2c_client *client,
 static int pca9685_pwm_remove(struct i2c_client *client)
 {
        struct pca9685 *pca = i2c_get_clientdata(client);
-       int ret;
 
-       ret = pwmchip_remove(&pca->chip);
-       if (ret)
-               return ret;
+       pwmchip_remove(&pca->chip);
 
        if (!pm_runtime_enabled(&client->dev)) {
                /* Put chip in sleep state if runtime PM is disabled */
index e091a52..a9efdcf 100644 (file)
@@ -195,32 +195,21 @@ static int pwm_probe(struct platform_device *pdev)
        if (IS_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) {
                dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
                return ret;
        }
 
-       platform_set_drvdata(pdev, pc);
        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 = {
        .driver         = {
                .name   = "pxa25x-pwm",
                .of_match_table = pwm_of_match,
        },
        .probe          = pwm_probe,
-       .remove         = pwm_remove,
        .id_table       = pwm_id_table,
 };
 
index 043fc32..579a152 100644 (file)
@@ -166,8 +166,6 @@ static int raspberrypi_pwm_probe(struct platform_device *pdev)
        rpipwm->chip.base = -1;
        rpipwm->chip.npwm = RASPBERRYPI_FIRMWARE_PWM_NUM;
 
-       platform_set_drvdata(pdev, rpipwm);
-
        ret = raspberrypi_pwm_get_property(rpipwm->firmware, RPI_PWM_CUR_DUTY_REG,
                                           &rpipwm->duty_cycle);
        if (ret) {
@@ -175,14 +173,7 @@ static int raspberrypi_pwm_probe(struct platform_device *pdev)
                return ret;
        }
 
-       return pwmchip_add(&rpipwm->chip);
-}
-
-static int raspberrypi_pwm_remove(struct platform_device *pdev)
-{
-       struct raspberrypi_pwm *rpipwm = platform_get_drvdata(pdev);
-
-       return pwmchip_remove(&rpipwm->chip);
+       return devm_pwmchip_add(dev, &rpipwm->chip);
 }
 
 static const struct of_device_id raspberrypi_pwm_of_match[] = {
@@ -197,7 +188,6 @@ static struct platform_driver raspberrypi_pwm_driver = {
                .of_match_table = raspberrypi_pwm_of_match,
        },
        .probe = raspberrypi_pwm_probe,
-       .remove = raspberrypi_pwm_remove,
 };
 module_platform_driver(raspberrypi_pwm_driver);
 
index 9daca0c..b437192 100644 (file)
@@ -241,13 +241,12 @@ static int rcar_pwm_probe(struct platform_device *pdev)
 static int rcar_pwm_remove(struct platform_device *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);
 
-       return ret;
+       return 0;
 }
 
 static const struct of_device_id rcar_pwm_of_table[] = {
index b853e79..4381df9 100644 (file)
@@ -425,13 +425,12 @@ static int tpu_probe(struct platform_device *pdev)
 static int tpu_remove(struct platform_device *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);
 
-       return ret;
+       return 0;
 }
 
 #ifdef CONFIG_OF
index cbe9008..f3647b3 100644 (file)
@@ -384,24 +384,12 @@ static int rockchip_pwm_remove(struct platform_device *pdev)
 {
        struct rockchip_pwm_chip *pc = platform_get_drvdata(pdev);
 
-       /*
-        * 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);
+       pwmchip_remove(&pc->chip);
 
        clk_unprepare(pc->pclk);
        clk_unprepare(pc->clk);
 
-       return pwmchip_remove(&pc->chip);
+       return 0;
 }
 
 static struct platform_driver rockchip_pwm_driver = {
index f6c528f..dd94c43 100644 (file)
@@ -580,11 +580,8 @@ static int pwm_samsung_probe(struct platform_device *pdev)
 static int pwm_samsung_remove(struct platform_device *pdev)
 {
        struct samsung_pwm_chip *chip = platform_get_drvdata(pdev);
-       int ret;
 
-       ret = pwmchip_remove(&chip->chip);
-       if (ret < 0)
-               return ret;
+       pwmchip_remove(&chip->chip);
 
        clk_disable_unprepare(chip->base_clk);
 
index 420edc4..253c4a1 100644 (file)
@@ -291,7 +291,7 @@ static int pwm_sifive_remove(struct platform_device *dev)
        struct pwm_sifive_ddata *ddata = platform_get_drvdata(dev);
        bool is_enabled = false;
        struct pwm_device *pwm;
-       int ret, ch;
+       int ch;
 
        for (ch = 0; ch < ddata->chip.npwm; ch++) {
                pwm = &ddata->chip.pwms[ch];
@@ -304,10 +304,10 @@ static int pwm_sifive_remove(struct platform_device *dev)
                clk_disable(ddata->clk);
 
        clk_disable_unprepare(ddata->clk);
-       ret = pwmchip_remove(&ddata->chip);
+       pwmchip_remove(&ddata->chip);
        clk_notifier_unregister(ddata->clk, &ddata->notifier);
 
-       return ret;
+       return 0;
 }
 
 static const struct of_device_id pwm_sifive_of_match[] = {
index 7a69c1a..589aeaa 100644 (file)
@@ -231,9 +231,7 @@ static int sl28cpld_pwm_probe(struct platform_device *pdev)
        chip->ops = &sl28cpld_pwm_ops;
        chip->npwm = 1;
 
-       platform_set_drvdata(pdev, priv);
-
-       ret = pwmchip_add(&priv->pwm_chip);
+       ret = devm_pwmchip_add(&pdev->dev, &priv->pwm_chip);
        if (ret) {
                dev_err(&pdev->dev, "failed to add PWM chip (%pe)",
                        ERR_PTR(ret));
@@ -243,13 +241,6 @@ static int sl28cpld_pwm_probe(struct platform_device *pdev)
        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[] = {
        { .compatible = "kontron,sl28cpld-pwm" },
        {}
@@ -258,7 +249,6 @@ MODULE_DEVICE_TABLE(of, sl28cpld_pwm_of_match);
 
 static struct platform_driver sl28cpld_pwm_driver = {
        .probe = sl28cpld_pwm_probe,
-       .remove = sl28cpld_pwm_remove,
        .driver = {
                .name = "sl28cpld-pwm",
                .of_match_table = sl28cpld_pwm_of_match,
index 93dd036..3115abb 100644 (file)
@@ -209,7 +209,7 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev)
        priv->chip.ops = &stm32_pwm_lp_ops;
        priv->chip.npwm = 1;
 
-       ret = pwmchip_add(&priv->chip);
+       ret = devm_pwmchip_add(&pdev->dev, &priv->chip);
        if (ret < 0)
                return ret;
 
@@ -218,15 +218,6 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev)
        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)
 {
        struct stm32_pwm_lp *priv = dev_get_drvdata(dev);
@@ -258,7 +249,6 @@ MODULE_DEVICE_TABLE(of, stm32_pwm_lp_of_match);
 
 static struct platform_driver stm32_pwm_lp_driver = {
        .probe  = stm32_pwm_lp_probe,
-       .remove = stm32_pwm_lp_remove,
        .driver = {
                .name = "stm32-pwm-lp",
                .of_match_table = of_match_ptr(stm32_pwm_lp_of_match),
index c952604..91ca676 100644 (file)
@@ -484,11 +484,8 @@ err_bus:
 static int sun4i_pwm_remove(struct platform_device *pdev)
 {
        struct sun4i_pwm_chip *pwm = platform_get_drvdata(pdev);
-       int ret;
 
-       ret = pwmchip_remove(&pwm->chip);
-       if (ret)
-               return ret;
+       pwmchip_remove(&pwm->chip);
 
        clk_disable_unprepare(pwm->bus_clk);
        reset_control_assert(pwm->rst);
index 35eb19a..4701f0c 100644 (file)
@@ -253,7 +253,7 @@ static int ecap_pwm_probe(struct platform_device *pdev)
        if (IS_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) {
                dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
                return ret;
@@ -267,11 +267,9 @@ static int ecap_pwm_probe(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);
 
-       return pwmchip_remove(&pc->chip);
+       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index 17909fa..5b723a4 100644 (file)
@@ -485,11 +485,13 @@ static int ehrpwm_pwm_remove(struct platform_device *pdev)
 {
        struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev);
 
+       pwmchip_remove(&pc->chip);
+
        clk_unprepare(pc->tbclk);
 
        pm_runtime_disable(&pdev->dev);
 
-       return pwmchip_remove(&pc->chip);
+       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index 6c8df5f..49d9f7a 100644 (file)
@@ -276,7 +276,6 @@ static const struct pwm_ops twl6030_pwmled_ops = {
 static int twl_pwmled_probe(struct platform_device *pdev)
 {
        struct twl_pwmled_chip *twl;
-       int ret;
 
        twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL);
        if (!twl)
@@ -294,20 +293,7 @@ static int twl_pwmled_probe(struct platform_device *pdev)
 
        mutex_init(&twl->mutex);
 
-       ret = pwmchip_add(&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);
+       return devm_pwmchip_add(&pdev->dev, &twl->chip);
 }
 
 #ifdef CONFIG_OF
@@ -325,7 +311,6 @@ static struct platform_driver twl_pwmled_driver = {
                .of_match_table = of_match_ptr(twl_pwmled_of_match),
        },
        .probe = twl_pwmled_probe,
-       .remove = twl_pwmled_remove,
 };
 module_platform_driver(twl_pwmled_driver);
 
index e83a826..203194f 100644 (file)
@@ -298,7 +298,6 @@ static const struct pwm_ops twl6030_pwm_ops = {
 static int twl_pwm_probe(struct platform_device *pdev)
 {
        struct twl_pwm_chip *twl;
-       int ret;
 
        twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL);
        if (!twl)
@@ -314,20 +313,7 @@ static int twl_pwm_probe(struct platform_device *pdev)
 
        mutex_init(&twl->mutex);
 
-       ret = pwmchip_add(&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);
+       return devm_pwmchip_add(&pdev->dev, &twl->chip);
 }
 
 #ifdef CONFIG_OF
@@ -345,7 +331,6 @@ static struct platform_driver twl_pwm_driver = {
                .of_match_table = of_match_ptr(twl_pwm_of_match),
        },
        .probe = twl_pwm_probe,
-       .remove = twl_pwm_remove,
 };
 module_platform_driver(twl_pwm_driver);
 
index a0b7e43..725c9b7 100644 (file)
@@ -404,7 +404,7 @@ int pwm_set_chip_data(struct pwm_device *pwm, void *data);
 void *pwm_get_chip_data(struct pwm_device *pwm);
 
 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);