diff options
Diffstat (limited to 'drivers/pwm/pwm-bcm-iproc.c')
| -rw-r--r-- | drivers/pwm/pwm-bcm-iproc.c | 77 |
1 files changed, 23 insertions, 54 deletions
diff --git a/drivers/pwm/pwm-bcm-iproc.c b/drivers/pwm/pwm-bcm-iproc.c index 0226bf697f09..f4c9f10e490e 100644 --- a/drivers/pwm/pwm-bcm-iproc.c +++ b/drivers/pwm/pwm-bcm-iproc.c @@ -1,15 +1,5 @@ -/* - * Copyright (C) 2016 Broadcom - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (C) 2016 Broadcom #include <linux/clk.h> #include <linux/delay.h> @@ -44,14 +34,13 @@ #define IPROC_PWM_PRESCALE_MAX 0x3f struct iproc_pwmc { - struct pwm_chip chip; void __iomem *base; struct clk *clk; }; static inline struct iproc_pwmc *to_iproc_pwmc(struct pwm_chip *chip) { - return container_of(chip, struct iproc_pwmc, chip); + return pwmchip_get_drvdata(chip); } static void iproc_pwmc_enable(struct iproc_pwmc *ip, unsigned int channel) @@ -78,8 +67,8 @@ static void iproc_pwmc_disable(struct iproc_pwmc *ip, unsigned int channel) ndelay(400); } -static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm, - struct pwm_state *state) +static int iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) { struct iproc_pwmc *ip = to_iproc_pwmc(chip); u64 tmp, multi, rate; @@ -101,7 +90,7 @@ static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm, if (rate == 0) { state->period = 0; state->duty_cycle = 0; - return; + return 0; } value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET); @@ -117,6 +106,8 @@ static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm, value = readl(ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(pwm->hwpwm)); tmp = (value & IPROC_PWM_PERIOD_MAX) * multi; state->duty_cycle = div64_u64(tmp, rate); + + return 0; } static int iproc_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm, @@ -191,69 +182,48 @@ static int iproc_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm, static const struct pwm_ops iproc_pwm_ops = { .apply = iproc_pwmc_apply, .get_state = iproc_pwmc_get_state, - .owner = THIS_MODULE, }; static int iproc_pwmc_probe(struct platform_device *pdev) { + struct pwm_chip *chip; struct iproc_pwmc *ip; unsigned int i; u32 value; int ret; - ip = devm_kzalloc(&pdev->dev, sizeof(*ip), GFP_KERNEL); - if (!ip) - return -ENOMEM; + chip = devm_pwmchip_alloc(&pdev->dev, 4, sizeof(*ip)); + if (IS_ERR(chip)) + return PTR_ERR(chip); + ip = to_iproc_pwmc(chip); platform_set_drvdata(pdev, ip); - ip->chip.dev = &pdev->dev; - ip->chip.ops = &iproc_pwm_ops; - ip->chip.npwm = 4; + chip->ops = &iproc_pwm_ops; ip->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(ip->base)) return PTR_ERR(ip->base); - ip->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(ip->clk)) { - dev_err(&pdev->dev, "failed to get clock: %ld\n", - PTR_ERR(ip->clk)); - return PTR_ERR(ip->clk); - } - - ret = clk_prepare_enable(ip->clk); - if (ret < 0) { - dev_err(&pdev->dev, "failed to enable clock: %d\n", ret); - return ret; - } + ip->clk = devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(ip->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(ip->clk), + "failed to get clock\n"); /* Set full drive and normal polarity for all channels */ value = readl(ip->base + IPROC_PWM_CTRL_OFFSET); - for (i = 0; i < ip->chip.npwm; i++) { + for (i = 0; i < chip->npwm; i++) { value &= ~(1 << IPROC_PWM_CTRL_TYPE_SHIFT(i)); value |= 1 << IPROC_PWM_CTRL_POLARITY_SHIFT(i); } writel(value, ip->base + IPROC_PWM_CTRL_OFFSET); - ret = pwmchip_add(&ip->chip); - if (ret < 0) { - dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret); - clk_disable_unprepare(ip->clk); - } - - return ret; -} - -static int iproc_pwmc_remove(struct platform_device *pdev) -{ - struct iproc_pwmc *ip = platform_get_drvdata(pdev); - - pwmchip_remove(&ip->chip); - - clk_disable_unprepare(ip->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; } @@ -270,7 +240,6 @@ static struct platform_driver iproc_pwmc_driver = { .of_match_table = bcm_iproc_pwmc_dt, }, .probe = iproc_pwmc_probe, - .remove = iproc_pwmc_remove, }; module_platform_driver(iproc_pwmc_driver); |
