mirror of
https://github.com/torvalds/linux.git
synced 2025-01-01 07:42:07 +00:00
pwm: Changes for v5.15-rc1
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. -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEEiOrDCAFJzPfAjcif3SOs138+s6EFAmE6RScZHHRoaWVycnku cmVkaW5nQGdtYWlsLmNvbQAKCRDdI6zXfz6zoVR8D/9BpmjIIVQr8qZG3dFORDfF /NXyALB4FQsc2uNMyKevriCHfkdiRLH5/0ElW0K9Fp/tt05JEFxDEq1eurojject LIwx5Yf7gAyvO90F3ty9iZNhHDbxagtR0fftQj7HcC+S3otbUFoTDsjitcrc7bwR qUOxOuuWKA4mrXNQQZLNUzRoJDgxau4UQtc+TGAk+IJz6KutE4zT5TBraozdNF8X bJHD2PPn/2yvKOd0t1x7UctjZUArodO/S09QeAa3JmhHBblTwagRVYhqpg2kiAXC lpPoqGOXYsgR0XAWmzLZeQ58Lrgn3gk7FpnMmoJ0aTk9kXVbt/wjBwtUEY/pip7U GsVbizNT6PZFC/d1rDLd5bYPVUBHvR4XSUt8iWbyNiRHerkVDXzKpcQ7z0NlGT8a zuVcroM/3L6V/lWN763OmOEP0n+SuiCFCZ1wKBF+zYsfXlvLTtSdjONDA+IcwETT ACpmdot7/zesBHjXgeQDtF1xa4qM4jPWZAUI7R6o+/g64kTh6duVOpT7IOoTs2y9 X0zyry51r/zNO2XyClosgRsItWY8dgfst3b6hBDM6ZAiMgUVqJgWliJBrRzIMsSr pj9ZcletTjpS7PVyzuIq9am9QO0TDAGzJ5g+wSP9MtW3+3FAuvUVQraIXVjVckGW TF3hrWKGjDeGmj5KQ346GA== =yTrZ -----END PGP SIGNATURE----- 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() ...
This commit is contained in:
commit
6701e7e7d8
@ -29,6 +29,7 @@ properties:
|
||||
- enum:
|
||||
- rockchip,px30-pwm
|
||||
- rockchip,rk3308-pwm
|
||||
- rockchip,rk3568-pwm
|
||||
- const: rockchip,rk3328-pwm
|
||||
|
||||
reg:
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -22,14 +22,21 @@
|
||||
|
||||
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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
atmel_pwm_wait_nonpending(atmel_pwm, pwm->hwpwm);
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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[] = {
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
|
@ -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 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));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* When PWM is disable, 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);
|
||||
|
||||
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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
clk_disable(mdp->clk_mm);
|
||||
clk_disable(mdp->clk_main);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_disp_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
{
|
||||
struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
|
||||
int err;
|
||||
|
||||
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;
|
||||
} 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);
|
||||
}
|
||||
|
||||
mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask,
|
||||
mdp->data->enable_mask);
|
||||
mdp->enabled = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_disp_pwm_disable(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;
|
||||
|
||||
mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask,
|
||||
0x0);
|
||||
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;
|
||||
}
|
||||
|
||||
clk_disable(mdp->clk_mm);
|
||||
clk_disable(mdp->clk_main);
|
||||
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;
|
||||
}
|
||||
|
||||
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 = {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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[] = {
|
||||
|
@ -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
|
||||
|
@ -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 = {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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[] = {
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user