diff options
Diffstat (limited to 'drivers/pwm/pwm-vt8500.c')
| -rw-r--r-- | drivers/pwm/pwm-vt8500.c | 93 |
1 files changed, 33 insertions, 60 deletions
diff --git a/drivers/pwm/pwm-vt8500.c b/drivers/pwm/pwm-vt8500.c index f1ff9940b37c..016c82d65527 100644 --- a/drivers/pwm/pwm-vt8500.c +++ b/drivers/pwm/pwm-vt8500.c @@ -6,6 +6,7 @@ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> */ +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/platform_device.h> @@ -18,10 +19,6 @@ #include <asm/div64.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_address.h> - /* * SoC architecture allocates register space for 4 PWMs but only * 2 are currently implemented. @@ -48,16 +45,19 @@ #define STATUS_ALL_UPDATE 0x0F struct vt8500_chip { - struct pwm_chip chip; void __iomem *base; struct clk *clk; }; -#define to_vt8500_chip(chip) container_of(chip, struct vt8500_chip, chip) +static inline struct vt8500_chip *to_vt8500_chip(struct pwm_chip *chip) +{ + return pwmchip_get_drvdata(chip); +} #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) -static inline void vt8500_pwm_busy_wait(struct vt8500_chip *vt8500, int nr, u8 bitmask) +static inline void vt8500_pwm_busy_wait(struct pwm_chip *chip, int nr, u8 bitmask) { + struct vt8500_chip *vt8500 = to_vt8500_chip(chip); int loops = msecs_to_loops(10); u32 mask = bitmask << (nr << 8); @@ -65,7 +65,7 @@ static inline void vt8500_pwm_busy_wait(struct vt8500_chip *vt8500, int nr, u8 b cpu_relax(); if (unlikely(!loops)) - dev_warn(vt8500->chip.dev, "Waiting for status bits 0x%x to clear timed out\n", + dev_warn(pwmchip_parent(chip), "Waiting for status bits 0x%x to clear timed out\n", mask); } @@ -80,7 +80,7 @@ static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, err = clk_enable(vt8500->clk); if (err < 0) { - dev_err(chip->dev, "failed to enable clock\n"); + dev_err(pwmchip_parent(chip), "failed to enable clock\n"); return err; } @@ -106,18 +106,18 @@ static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, dc = div64_u64(c, period_ns); writel(prescale, vt8500->base + REG_SCALAR(pwm->hwpwm)); - vt8500_pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_SCALAR_UPDATE); + vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_SCALAR_UPDATE); writel(pv, vt8500->base + REG_PERIOD(pwm->hwpwm)); - vt8500_pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_PERIOD_UPDATE); + vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_PERIOD_UPDATE); writel(dc, vt8500->base + REG_DUTY(pwm->hwpwm)); - vt8500_pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_DUTY_UPDATE); + vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_DUTY_UPDATE); val = readl(vt8500->base + REG_CTRL(pwm->hwpwm)); val |= CTRL_AUTOLOAD; writel(val, vt8500->base + REG_CTRL(pwm->hwpwm)); - vt8500_pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE); + vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_CTRL_UPDATE); clk_disable(vt8500->clk); return 0; @@ -131,14 +131,14 @@ static int vt8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) err = clk_enable(vt8500->clk); if (err < 0) { - dev_err(chip->dev, "failed to enable clock\n"); + dev_err(pwmchip_parent(chip), "failed to enable clock\n"); return err; } val = readl(vt8500->base + REG_CTRL(pwm->hwpwm)); val |= CTRL_ENABLE; writel(val, vt8500->base + REG_CTRL(pwm->hwpwm)); - vt8500_pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE); + vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_CTRL_UPDATE); return 0; } @@ -151,7 +151,7 @@ static void vt8500_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) val = readl(vt8500->base + REG_CTRL(pwm->hwpwm)); val &= ~CTRL_ENABLE; writel(val, vt8500->base + REG_CTRL(pwm->hwpwm)); - vt8500_pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE); + vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_CTRL_UPDATE); clk_disable(vt8500->clk); } @@ -171,7 +171,7 @@ static int vt8500_pwm_set_polarity(struct pwm_chip *chip, val &= ~CTRL_INVERT; writel(val, vt8500->base + REG_CTRL(pwm->hwpwm)); - vt8500_pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE); + vt8500_pwm_busy_wait(chip, pwm->hwpwm, STATUS_CTRL_UPDATE); return 0; } @@ -209,10 +209,10 @@ static int vt8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, * We cannot skip calling ->config even if state->period == * pwm->state.period && state->duty_cycle == pwm->state.duty_cycle * because we might have exited early in the last call to - * pwm_apply_state because of !state->enabled and so the two values in + * pwm_apply_might_sleep because of !state->enabled and so the two values in * pwm->state might not be configured in hardware. */ - err = vt8500_pwm_config(pwm->chip, pwm, state->duty_cycle, state->period); + err = vt8500_pwm_config(chip, pwm, state->duty_cycle, state->period); if (err) return err; @@ -224,7 +224,6 @@ static int vt8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, static const struct pwm_ops vt8500_pwm_ops = { .apply = vt8500_pwm_apply, - .owner = THIS_MODULE, }; static const struct of_device_id vt8500_pwm_dt_ids[] = { @@ -235,64 +234,38 @@ MODULE_DEVICE_TABLE(of, vt8500_pwm_dt_ids); static int vt8500_pwm_probe(struct platform_device *pdev) { + struct pwm_chip *chip; struct vt8500_chip *vt8500; struct device_node *np = pdev->dev.of_node; int ret; - if (!np) { - dev_err(&pdev->dev, "invalid devicetree node\n"); - return -EINVAL; - } + if (!np) + return dev_err_probe(&pdev->dev, -EINVAL, "invalid devicetree node\n"); - vt8500 = devm_kzalloc(&pdev->dev, sizeof(*vt8500), GFP_KERNEL); - if (vt8500 == NULL) - return -ENOMEM; + chip = devm_pwmchip_alloc(&pdev->dev, VT8500_NR_PWMS, sizeof(*vt8500)); + if (IS_ERR(chip)) + return PTR_ERR(chip); + vt8500 = to_vt8500_chip(chip); - vt8500->chip.dev = &pdev->dev; - vt8500->chip.ops = &vt8500_pwm_ops; - vt8500->chip.npwm = VT8500_NR_PWMS; + chip->ops = &vt8500_pwm_ops; - vt8500->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(vt8500->clk)) { - dev_err(&pdev->dev, "clock source not specified\n"); - return PTR_ERR(vt8500->clk); - } + vt8500->clk = devm_clk_get_prepared(&pdev->dev, NULL); + if (IS_ERR(vt8500->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(vt8500->clk), "clock source not specified\n"); vt8500->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(vt8500->base)) return PTR_ERR(vt8500->base); - ret = clk_prepare(vt8500->clk); - if (ret < 0) { - dev_err(&pdev->dev, "failed to prepare clock\n"); - return ret; - } - - ret = pwmchip_add(&vt8500->chip); - if (ret < 0) { - dev_err(&pdev->dev, "failed to add PWM chip\n"); - clk_unprepare(vt8500->clk); - return ret; - } - - platform_set_drvdata(pdev, vt8500); - return ret; -} - -static int vt8500_pwm_remove(struct platform_device *pdev) -{ - struct vt8500_chip *vt8500 = platform_get_drvdata(pdev); - - pwmchip_remove(&vt8500->chip); - - clk_unprepare(vt8500->clk); + ret = devm_pwmchip_add(&pdev->dev, chip); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, "failed to add PWM chip\n"); return 0; } static struct platform_driver vt8500_pwm_driver = { .probe = vt8500_pwm_probe, - .remove = vt8500_pwm_remove, .driver = { .name = "vt8500-pwm", .of_match_table = vt8500_pwm_dt_ids, |
