From patchwork Wed Feb 1 14:35:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 722554 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3vD5KG1jTtz9sdn for ; Thu, 2 Feb 2017 01:36:02 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751170AbdBAOgB (ORCPT ); Wed, 1 Feb 2017 09:36:01 -0500 Received: from mail.free-electrons.com ([62.4.15.54]:52736 "EHLO mail.free-electrons.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750920AbdBAOgB (ORCPT ); Wed, 1 Feb 2017 09:36:01 -0500 Received: by mail.free-electrons.com (Postfix, from userid 110) id EB68A20C01; Wed, 1 Feb 2017 15:35:57 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.free-electrons.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT shortcircuit=ham autolearn=disabled version=3.4.0 Received: from bbrezillon.home (LStLambert-657-1-97-87.w90-63.abo.wanadoo.fr [90.63.216.87]) by mail.free-electrons.com (Postfix) with ESMTPSA id 4064420B8A; Wed, 1 Feb 2017 15:35:35 +0100 (CET) From: Boris Brezillon To: Thierry Reding , linux-pwm@vger.kernel.org Cc: Nicolas Ferre , Alexandre Belloni , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Boris Brezillon Subject: [PATCH] pwm: atmel-hlcdc: Convert to the atomic PWM API Date: Wed, 1 Feb 2017 15:35:34 +0100 Message-Id: <1485959734-22317-1-git-send-email-boris.brezillon@free-electrons.com> X-Mailer: git-send-email 2.7.4 Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Implement the ->apply() hook and drop the ->enable(), ->disable, ->set_polarity and ->config() ones. Signed-off-by: Boris Brezillon Acked-by: Nicolas Ferre --- drivers/pwm/pwm-atmel-hlcdc.c | 215 +++++++++++++++++------------------------- 1 file changed, 86 insertions(+), 129 deletions(-) diff --git a/drivers/pwm/pwm-atmel-hlcdc.c b/drivers/pwm/pwm-atmel-hlcdc.c index 14fc011faa32..64f1e1662b57 100644 --- a/drivers/pwm/pwm-atmel-hlcdc.c +++ b/drivers/pwm/pwm-atmel-hlcdc.c @@ -49,162 +49,119 @@ static inline struct atmel_hlcdc_pwm *to_atmel_hlcdc_pwm(struct pwm_chip *chip) return container_of(chip, struct atmel_hlcdc_pwm, chip); } -static int atmel_hlcdc_pwm_config(struct pwm_chip *c, - struct pwm_device *pwm, - int duty_ns, int period_ns) +static int atmel_hlcdc_pwm_apply(struct pwm_chip *c, struct pwm_device *pwm, + struct pwm_state *state) { struct atmel_hlcdc_pwm *chip = to_atmel_hlcdc_pwm(c); struct atmel_hlcdc *hlcdc = chip->hlcdc; - struct clk *new_clk = hlcdc->slow_clk; - u64 pwmcval = duty_ns * 256; - unsigned long clk_freq; - u64 clk_period_ns; - u32 pwmcfg; - int pres; - - if (!chip->errata || !chip->errata->slow_clk_erratum) { - clk_freq = clk_get_rate(new_clk); - if (!clk_freq) - return -EINVAL; - - clk_period_ns = (u64)NSEC_PER_SEC * 256; - do_div(clk_period_ns, clk_freq); - } - - /* Errata: cannot use slow clk on some IP revisions */ - if ((chip->errata && chip->errata->slow_clk_erratum) || - clk_period_ns > period_ns) { - new_clk = hlcdc->sys_clk; - clk_freq = clk_get_rate(new_clk); - if (!clk_freq) - return -EINVAL; - - clk_period_ns = (u64)NSEC_PER_SEC * 256; - do_div(clk_period_ns, clk_freq); - } + unsigned int status; + int ret; - for (pres = 0; pres <= ATMEL_HLCDC_PWMPS_MAX; pres++) { + if (state->enabled) { + struct clk *new_clk = hlcdc->slow_clk; + u64 pwmcval = state->duty_cycle * 256; + unsigned long clk_freq; + u64 clk_period_ns; + u32 pwmcfg; + int pres; + + if (!chip->errata || !chip->errata->slow_clk_erratum) { + clk_freq = clk_get_rate(new_clk); + if (!clk_freq) + return -EINVAL; + + clk_period_ns = (u64)NSEC_PER_SEC * 256; + do_div(clk_period_ns, clk_freq); + } + + /* Errata: cannot use slow clk on some IP revisions */ + if ((chip->errata && chip->errata->slow_clk_erratum) || + clk_period_ns > state->period) { + new_clk = hlcdc->sys_clk; + clk_freq = clk_get_rate(new_clk); + if (!clk_freq) + return -EINVAL; + + clk_period_ns = (u64)NSEC_PER_SEC * 256; + do_div(clk_period_ns, clk_freq); + } + + for (pres = 0; pres <= ATMEL_HLCDC_PWMPS_MAX; pres++) { /* Errata: cannot divide by 1 on some IP revisions */ - if (!pres && chip->errata && chip->errata->div1_clk_erratum) - continue; - - if ((clk_period_ns << pres) >= period_ns) - break; - } - - if (pres > ATMEL_HLCDC_PWMPS_MAX) - return -EINVAL; - - pwmcfg = ATMEL_HLCDC_PWMPS(pres); + if (!pres && chip->errata && + chip->errata->div1_clk_erratum) + continue; - if (new_clk != chip->cur_clk) { - u32 gencfg = 0; - int ret; + if ((clk_period_ns << pres) >= state->period) + break; + } - ret = clk_prepare_enable(new_clk); - if (ret) - return ret; + if (pres > ATMEL_HLCDC_PWMPS_MAX) + return -EINVAL; - clk_disable_unprepare(chip->cur_clk); - chip->cur_clk = new_clk; + pwmcfg = ATMEL_HLCDC_PWMPS(pres); - if (new_clk == hlcdc->sys_clk) - gencfg = ATMEL_HLCDC_CLKPWMSEL; + if (new_clk != chip->cur_clk) { + u32 gencfg = 0; + int ret; - ret = regmap_update_bits(hlcdc->regmap, ATMEL_HLCDC_CFG(0), - ATMEL_HLCDC_CLKPWMSEL, gencfg); - if (ret) - return ret; - } + ret = clk_prepare_enable(new_clk); + if (ret) + return ret; - do_div(pwmcval, period_ns); + clk_disable_unprepare(chip->cur_clk); + chip->cur_clk = new_clk; - /* - * The PWM duty cycle is configurable from 0/256 to 255/256 of the - * period cycle. Hence we can't set a duty cycle occupying the - * whole period cycle if we're asked to. - * Set it to 255 if pwmcval is greater than 256. - */ - if (pwmcval > 255) - pwmcval = 255; + if (new_clk == hlcdc->sys_clk) + gencfg = ATMEL_HLCDC_CLKPWMSEL; - pwmcfg |= ATMEL_HLCDC_PWMCVAL(pwmcval); - - return regmap_update_bits(hlcdc->regmap, ATMEL_HLCDC_CFG(6), - ATMEL_HLCDC_PWMCVAL_MASK | - ATMEL_HLCDC_PWMPS_MASK, - pwmcfg); -} - -static int atmel_hlcdc_pwm_set_polarity(struct pwm_chip *c, - struct pwm_device *pwm, - enum pwm_polarity polarity) -{ - struct atmel_hlcdc_pwm *chip = to_atmel_hlcdc_pwm(c); - struct atmel_hlcdc *hlcdc = chip->hlcdc; - u32 cfg = 0; + ret = regmap_update_bits(hlcdc->regmap, + ATMEL_HLCDC_CFG(0), + ATMEL_HLCDC_CLKPWMSEL, + gencfg); + if (ret) + return ret; + } - if (polarity == PWM_POLARITY_NORMAL) - cfg = ATMEL_HLCDC_PWMPOL; + do_div(pwmcval, state->period); - return regmap_update_bits(hlcdc->regmap, ATMEL_HLCDC_CFG(6), - ATMEL_HLCDC_PWMPOL, cfg); -} + /* + * The PWM duty cycle is configurable from 0/256 to 255/256 of + * the period cycle. Hence we can't set a duty cycle occupying + * the whole period cycle if we're asked to. + * Set it to 255 if pwmcval is greater than 256. + */ + if (pwmcval > 255) + pwmcval = 255; -static int atmel_hlcdc_pwm_enable(struct pwm_chip *c, struct pwm_device *pwm) -{ - struct atmel_hlcdc_pwm *chip = to_atmel_hlcdc_pwm(c); - struct atmel_hlcdc *hlcdc = chip->hlcdc; - u32 status; - int ret; + pwmcfg |= ATMEL_HLCDC_PWMCVAL(pwmcval); - ret = regmap_write(hlcdc->regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_PWM); - if (ret) - return ret; + if (state->polarity == PWM_POLARITY_NORMAL) + pwmcfg |= ATMEL_HLCDC_PWMPOL; - while (true) { - ret = regmap_read(hlcdc->regmap, ATMEL_HLCDC_SR, &status); + ret = regmap_update_bits(hlcdc->regmap, ATMEL_HLCDC_CFG(6), + ATMEL_HLCDC_PWMCVAL_MASK | + ATMEL_HLCDC_PWMPS_MASK | + ATMEL_HLCDC_PWMPOL, + pwmcfg); if (ret) return ret; - - if ((status & ATMEL_HLCDC_PWM) != 0) - break; - - usleep_range(1, 10); } - return 0; -} - -static void atmel_hlcdc_pwm_disable(struct pwm_chip *c, - struct pwm_device *pwm) -{ - struct atmel_hlcdc_pwm *chip = to_atmel_hlcdc_pwm(c); - struct atmel_hlcdc *hlcdc = chip->hlcdc; - u32 status; - int ret; - - ret = regmap_write(hlcdc->regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_PWM); + ret = regmap_write(hlcdc->regmap, + state->enabled ? ATMEL_HLCDC_EN : ATMEL_HLCDC_DIS, + ATMEL_HLCDC_PWM); if (ret) - return; - - while (true) { - ret = regmap_read(hlcdc->regmap, ATMEL_HLCDC_SR, &status); - if (ret) - return; - - if ((status & ATMEL_HLCDC_PWM) == 0) - break; + return ret; - usleep_range(1, 10); - } + return regmap_read_poll_timeout(hlcdc->regmap, ATMEL_HLCDC_SR, status, + (status & ATMEL_HLCDC_PWM) == + (state->enabled ? ATMEL_HLCDC_PWM : 0), + 10, 0); } static const struct pwm_ops atmel_hlcdc_pwm_ops = { - .config = atmel_hlcdc_pwm_config, - .set_polarity = atmel_hlcdc_pwm_set_polarity, - .enable = atmel_hlcdc_pwm_enable, - .disable = atmel_hlcdc_pwm_disable, + .apply = atmel_hlcdc_pwm_apply, .owner = THIS_MODULE, };