From patchwork Fri Feb 24 05:41:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Siarhei Volkau X-Patchwork-Id: 731907 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 3vV0Mm1TyTz9s7t for ; Fri, 24 Feb 2017 16:41:24 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="TVYLzkBX"; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751121AbdBXFlY (ORCPT ); Fri, 24 Feb 2017 00:41:24 -0500 Received: from mail-lf0-f65.google.com ([209.85.215.65]:33897 "EHLO mail-lf0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751049AbdBXFlX (ORCPT ); Fri, 24 Feb 2017 00:41:23 -0500 Received: by mail-lf0-f65.google.com with SMTP id h67so749401lfg.1 for ; Thu, 23 Feb 2017 21:41:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=8vk7OjtdUbd3BJip8W5rdrVnkcn2QnPjEdFEPzbYEPw=; b=TVYLzkBXL1w+CW61QX8YNbjB7I/V942XI4EEYqLWjfTyqlVqjZt6Wx/ch7IxGsr6UN EY5zTDtuErNBtJpwf2fw3nr6FELbQyihs6Ue2oYVRudIOBYXrb6GwSoauwrCKVmsngIr BLhLAHfplsynVTZdquiWeypxG4AXbTPKg6eERQkDENVO/VeUTblmoy292/6pmZSQLk/z 9WG9L2fIlmQZAW2D9OMgi+3rVrSvnXVp3Y04tBX5g+hx5WijA9LISzI63Befwd8LSSQP iwieIxmI9B2X4iIiwMbeta+0iRoBj2XOIyJ0aWc8lepaqoKLR67MCWPrvFy+YINBhY/y oZyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=8vk7OjtdUbd3BJip8W5rdrVnkcn2QnPjEdFEPzbYEPw=; b=R8ety7hkUdbiHzADA36uWELtd394N86VKA8ht4K66AdL7nP11G750J/Ueryxto9oGQ wbFEsVhY6ZiVnGYgChP205296THCyyxc6QSPCRCQ6eaFlO8oXikZSfu5BfbfTCSYRQHX O1DmFeyErc3HuJ6IvJyF8puegRHR5KqM9Fxs2yQAmXpTrZonkPAkDkRnsOoUjzKH0ZHE 7IiLoSFN4JaSkgP54ncz+s+4aLjlgRMcnG1aQr4yATyL9wvSVSu1ouRfuZviNG9gKe3Y ry7Gzc9sJ1UoM1q1Xho2F8Nc/G6aGIGgOfDAqMmkkjaEh2J92nfBxIFqCCQfO6yZzaeO 3OdQ== X-Gm-Message-State: AMke39nP+jeIrxI/8nu0JJmnxEWTy7NCKJ/K/zoqEnZ2EoRZuddsLhIwJ9X8Lj0j+7UUlw== X-Received: by 10.46.71.207 with SMTP id u198mr218974lja.42.1487914881448; Thu, 23 Feb 2017 21:41:21 -0800 (PST) Received: from hp-envy-1014.local (mm-118-67-212-37.vitebsk.dynamic.pppoe.byfly.by. [37.212.67.118]) by smtp.gmail.com with ESMTPSA id d77sm1764975lfd.26.2017.02.23.21.41.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 23 Feb 2017 21:41:21 -0800 (PST) From: lis8215@gmail.com To: linux-sunxi@googlegroups.com Cc: thierry.reding@gmail.com, robh+dt@kernel.org, mark.rutland@arm.com, maxime.ripard@free-electrons.com, wens@csie.org, linux-pwm@vger.kernel.org, Siarhei Volkau Subject: [PATCH v4 2/9] pwm: sunxi: Use regmap fields for bit operations. Date: Fri, 24 Feb 2017 08:41:09 +0300 Message-Id: <1487914876-8594-3-git-send-email-lis8215@gmail.com> X-Mailer: git-send-email 2.4.11 In-Reply-To: <1487914876-8594-1-git-send-email-lis8215@gmail.com> References: <1487914876-8594-1-git-send-email-lis8215@gmail.com> Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org From: Siarhei Volkau This patch replaces a bunch of custom read-modify-write operations by regmap fields. Signed-off-by: Siarhei Volkau --- drivers/pwm/pwm-sun4i.c | 197 ++++++++++++++++++++++++++---------------------- 1 file changed, 108 insertions(+), 89 deletions(-) diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c index 5565f03..7af6bd8 100644 --- a/drivers/pwm/pwm-sun4i.c +++ b/drivers/pwm/pwm-sun4i.c @@ -46,6 +46,20 @@ #define BIT_CH(bit, chan) ((bit) << ((chan) * PWMCH_OFFSET)) +#define SUN4I_MAX_PWM_CHANNELS 2 + +/* regmap fields */ +enum { + /* Used bit fields in control register */ + FIELD_PRESCALER = 0, + FIELD_POLARITY, + FIELD_CLK_GATING, + FIELD_READY, + + /* Keep last */ + NUM_FIELDS, +}; + static const u32 prescaler_table[] = { 120, 180, @@ -75,6 +89,7 @@ struct sun4i_pwm_chip { struct pwm_chip chip; struct clk *clk; struct regmap *regmap; + struct regmap_field *fields[SUN4I_MAX_PWM_CHANNELS][NUM_FIELDS]; spinlock_t ctrl_lock; const struct sun4i_pwm_data *data; }; @@ -88,6 +103,7 @@ static int sun4i_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, int duty_ns, int period_ns) { struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip); + struct regmap_field **chan_fields = sun4i_pwm->fields[pwm->hwpwm]; u32 prd, dty, val, clk_gate; u64 clk_rate, div = 0; unsigned int prescaler = 0; @@ -140,38 +156,36 @@ static int sun4i_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, } spin_lock(&sun4i_pwm->ctrl_lock); - err = regmap_read(sun4i_pwm->regmap, PWM_CTRL_REG, &val); - if (err) { - dev_err(chip->dev, "failed to read from CTL register\n"); - goto err_cleanup; - } - if (sun4i_pwm->data->has_rdy && (val & PWM_RDY(pwm->hwpwm))) { - spin_unlock(&sun4i_pwm->ctrl_lock); - clk_disable_unprepare(sun4i_pwm->clk); - return -EBUSY; - } - - clk_gate = val & BIT_CH(PWM_CLK_GATING, pwm->hwpwm); - if (clk_gate) { - val &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm); - err = regmap_write(sun4i_pwm->regmap, PWM_CTRL_REG, val); + if (sun4i_pwm->data->has_rdy) { + err = regmap_field_read(chan_fields[FIELD_READY], &val); if (err) { - dev_err(chip->dev, "failed to write to CTL register\n"); + dev_err(chip->dev, "failed to read ready bit\n"); + goto err_cleanup; + } + if (val) { + err = -EBUSY; goto err_cleanup; } } - err = regmap_read(sun4i_pwm->regmap, PWM_CTRL_REG, &val); + err = regmap_field_read(chan_fields[FIELD_CLK_GATING], &clk_gate); if (err) { - dev_err(chip->dev, "failed to read from CTL register\n"); + dev_err(chip->dev, "failed to read clock_gating bit\n"); goto err_cleanup; } - val &= ~BIT_CH(PWM_PRESCAL_MASK, pwm->hwpwm); - val |= BIT_CH(prescaler, pwm->hwpwm); - err = regmap_write(sun4i_pwm->regmap, PWM_CTRL_REG, val); + if (clk_gate) { + err = regmap_field_write(chan_fields[FIELD_CLK_GATING], 0); + if (err) { + dev_err(chip->dev, + "failed to write to clock_gating bit\n"); + goto err_cleanup; + } + } + + err = regmap_field_write(chan_fields[FIELD_PRESCALER], prescaler); if (err) { - dev_err(chip->dev, "failed to write to CTL register\n"); + dev_err(chip->dev, "failed to write to prescaler field\n"); goto err_cleanup; } @@ -183,16 +197,10 @@ static int sun4i_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, } if (clk_gate) { - err = regmap_read(sun4i_pwm->regmap, PWM_CTRL_REG, &val); + err = regmap_field_write(chan_fields[FIELD_CLK_GATING], 1); if (err) { dev_err(chip->dev, - "failed to read from CTL register\n"); - goto err_cleanup; - } - val |= clk_gate; - err = regmap_write(sun4i_pwm->regmap, PWM_CTRL_REG, val); - if (err) { - dev_err(chip->dev, "failed to write to CTL register\n"); + "failed to write to clock_gating bit\n"); goto err_cleanup; } } @@ -208,7 +216,7 @@ static int sun4i_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, enum pwm_polarity polarity) { struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip); - u32 val; + struct regmap_field **chan_fields = sun4i_pwm->fields[pwm->hwpwm]; int ret; ret = clk_prepare_enable(sun4i_pwm->clk); @@ -218,27 +226,14 @@ static int sun4i_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, } spin_lock(&sun4i_pwm->ctrl_lock); - ret = regmap_read(sun4i_pwm->regmap, PWM_CTRL_REG, &val); - if (ret) { - dev_err(chip->dev, - "failed to read from CTL register\n"); - goto err_cleanup; - } - - if (polarity != PWM_POLARITY_NORMAL) - val &= ~BIT_CH(PWM_ACT_STATE, pwm->hwpwm); - else - val |= BIT_CH(PWM_ACT_STATE, pwm->hwpwm); - - ret = regmap_write(sun4i_pwm->regmap, PWM_CTRL_REG, val); - if (ret) { - dev_err(chip->dev, "failed to write to CTL register\n"); - goto err_cleanup; - } + ret = regmap_field_write(chan_fields[FIELD_POLARITY], + polarity == PWM_POLARITY_NORMAL); + if (ret) + dev_err(chip->dev, "failed to write to polarity bit\n"); -err_cleanup: spin_unlock(&sun4i_pwm->ctrl_lock); - clk_disable_unprepare(sun4i_pwm->clk); + if (ret) + clk_disable_unprepare(sun4i_pwm->clk); return ret; } @@ -246,7 +241,7 @@ static int sun4i_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, static int sun4i_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) { struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip); - u32 val; + u32 mask; int ret; ret = clk_prepare_enable(sun4i_pwm->clk); @@ -255,54 +250,33 @@ static int sun4i_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) return ret; } + mask = BIT_CH(PWM_EN, pwm->hwpwm); + mask |= BIT_CH(PWM_CLK_GATING, pwm->hwpwm); + spin_lock(&sun4i_pwm->ctrl_lock); - ret = regmap_read(sun4i_pwm->regmap, PWM_CTRL_REG, &val); - if (ret) { - dev_err(chip->dev, - "failed to read from CTL register\n"); - goto err_cleanup; - } - val |= BIT_CH(PWM_EN, pwm->hwpwm); - val |= BIT_CH(PWM_CLK_GATING, pwm->hwpwm); - ret = regmap_write(sun4i_pwm->regmap, PWM_CTRL_REG, val); - if (ret) { + ret = regmap_update_bits(sun4i_pwm->regmap, PWM_CTRL_REG, mask, mask); + if (ret) dev_err(chip->dev, "failed to write to CTL register\n"); - goto err_cleanup; - } - spin_unlock(&sun4i_pwm->ctrl_lock); - return ret; -err_cleanup: - spin_unlock(&sun4i_pwm->ctrl_lock); if (ret) clk_disable_unprepare(sun4i_pwm->clk); - return ret; } static void sun4i_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) { struct sun4i_pwm_chip *sun4i_pwm = to_sun4i_pwm_chip(chip); - u32 val; + u32 mask; int err; + mask = BIT_CH(PWM_EN, pwm->hwpwm); + mask |= BIT_CH(PWM_CLK_GATING, pwm->hwpwm); + spin_lock(&sun4i_pwm->ctrl_lock); - err = regmap_read(sun4i_pwm->regmap, PWM_CTRL_REG, &val); - if (err) { - dev_err(chip->dev, - "failed to read from CTL register\n"); - goto err_cleanup; - } - val &= ~BIT_CH(PWM_EN, pwm->hwpwm); - val &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm); - err = regmap_write(sun4i_pwm->regmap, PWM_CTRL_REG, val); - if (err) { + err = regmap_update_bits(sun4i_pwm->regmap, PWM_CTRL_REG, mask, 0); + if (err) dev_err(chip->dev, "failed to write to CTL register\n"); - goto err_cleanup; - } - -err_cleanup: spin_unlock(&sun4i_pwm->ctrl_lock); clk_disable_unprepare(sun4i_pwm->clk); @@ -316,6 +290,22 @@ static const struct pwm_ops sun4i_pwm_ops = { .owner = THIS_MODULE, }; +static const struct reg_field +sun4i_pwm_regfields[SUN4I_MAX_PWM_CHANNELS][NUM_FIELDS] = { + { + [FIELD_PRESCALER] = REG_FIELD(PWM_CTRL_REG, 0, 3), + [FIELD_POLARITY] = REG_FIELD(PWM_CTRL_REG, 5, 5), + [FIELD_CLK_GATING] = REG_FIELD(PWM_CTRL_REG, 6, 6), + [FIELD_READY] = REG_FIELD(PWM_CTRL_REG, 28, 28), + }, + { + [FIELD_PRESCALER] = REG_FIELD(PWM_CTRL_REG, 15, 18), + [FIELD_POLARITY] = REG_FIELD(PWM_CTRL_REG, 20, 20), + [FIELD_CLK_GATING] = REG_FIELD(PWM_CTRL_REG, 21, 21), + [FIELD_READY] = REG_FIELD(PWM_CTRL_REG, 29, 29), + }, +}; + static const struct sun4i_pwm_data sun4i_pwm_data_a10 = { .has_prescaler_bypass = false, .has_rdy = false, @@ -374,6 +364,28 @@ static const struct regmap_config sunxi_pwm_regmap_config = { .reg_stride = 4, }; +static int sun4i_alloc_reg_fields(struct device *dev, + struct sun4i_pwm_chip *pwm, int chan) +{ + int i, err; + + if (chan >= SUN4I_MAX_PWM_CHANNELS) + return -EINVAL; + for (i = 0; i < NUM_FIELDS; i++) { + pwm->fields[chan][i] = + devm_regmap_field_alloc(dev, pwm->regmap, + sun4i_pwm_regfields[chan][i]); + if (IS_ERR(pwm->fields[chan][i])) { + dev_err(dev, "regmap field allocation failed\n"); + err = PTR_ERR(pwm->fields[chan][i]); + pwm->fields[chan][i] = NULL; + return err; + } + } + + return 0; +} + static int sun4i_pwm_probe(struct platform_device *pdev) { struct sun4i_pwm_chip *pwm; @@ -428,15 +440,22 @@ static int sun4i_pwm_probe(struct platform_device *pdev) goto clk_error; } - ret = regmap_read(pwm->regmap, PWM_CTRL_REG, &val); - if (ret) { - dev_err(&pdev->dev, "failed to read from CTL register\n"); - goto read_error; + for (i = 0; i < pwm->chip.npwm; i++) { + ret = sun4i_alloc_reg_fields(&pdev->dev, pwm, i); + if (ret) + goto read_error; } - for (i = 0; i < pwm->chip.npwm; i++) - if (!(val & BIT_CH(PWM_ACT_STATE, i))) + + for (i = 0; i < pwm->chip.npwm; i++) { + ret = regmap_field_read(pwm->fields[i][FIELD_POLARITY], &val); + if (ret) { + dev_err(&pdev->dev, "failed to read polarity bit\n"); + goto read_error; + } + if (val) pwm_set_polarity(&pwm->chip.pwms[i], PWM_POLARITY_INVERSED); + } clk_disable_unprepare(pwm->clk); return 0;