From patchwork Mon Jul 14 14:33:30 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lee Jones X-Patchwork-Id: 33602 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-qg0-f69.google.com (mail-qg0-f69.google.com [209.85.192.69]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id AC9ED20CAD for ; Mon, 14 Jul 2014 14:35:46 +0000 (UTC) Received: by mail-qg0-f69.google.com with SMTP id j107sf11746251qga.0 for ; Mon, 14 Jul 2014 07:35:46 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=xVPb4tw5iI+ooskL1cMeq80BlvO4uYtcDeukv+89yAs=; b=XLRT64+t5ZT28w30cv6i/l1P0eO2mw9fg/ezBHnf/s3lWzy/7Zh6I+Gvz+oOEDyOr3 jxlf5J/M7nGhipuGH3ccUq3znvyd4fhmv1aa+jzD6DBkuf4V7Aa8akC//kjpFIj1Z9Rs l/Fp/6CckYFswqcfE2vn7II1ZjRhbe/yCk9tg3lZqBZsAtdosMzHJtVy3RhPgPM/AvIX 58ja6E7pWsQYuTlM0edFcX2DUF4XzmwnAeaSRFh8Ebc4RNcEmeedrnQLqUrLD2yEDAwK 9UAOK3lNP4HoittZqwuBjhv9Bv6xNvDqBc9+Hs9J+ThSQ1Q54Shz2N3ozUsP1XCT66om X+gA== X-Gm-Message-State: ALoCoQl8IGmn/EK24ttYXBv11HKJCDJ+9+yMdW/wSZ9lM2JhOfiTo6rmBc6dIzUZEeRaaIXqgNpb X-Received: by 10.236.1.198 with SMTP id 46mr6888131yhd.16.1405348546550; Mon, 14 Jul 2014 07:35:46 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.47.174 with SMTP id m43ls982986qga.84.gmail; Mon, 14 Jul 2014 07:35:46 -0700 (PDT) X-Received: by 10.52.53.135 with SMTP id b7mr527502vdp.67.1405348546415; Mon, 14 Jul 2014 07:35:46 -0700 (PDT) Received: from mail-vc0-f174.google.com (mail-vc0-f174.google.com [209.85.220.174]) by mx.google.com with ESMTPS id qr19si5396556vdb.86.2014.07.14.07.35.46 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 14 Jul 2014 07:35:46 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.174 as permitted sender) client-ip=209.85.220.174; Received: by mail-vc0-f174.google.com with SMTP id la4so2222127vcb.5 for ; Mon, 14 Jul 2014 07:35:46 -0700 (PDT) X-Received: by 10.52.244.81 with SMTP id xe17mr13901581vdc.24.1405348546321; Mon, 14 Jul 2014 07:35:46 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.37.5 with SMTP id tc5csp139680vcb; Mon, 14 Jul 2014 07:35:45 -0700 (PDT) X-Received: by 10.68.226.105 with SMTP id rr9mr376005pbc.161.1405348545578; Mon, 14 Jul 2014 07:35:45 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id lp7si9301503pab.189.2014.07.14.07.35.44; Mon, 14 Jul 2014 07:35:45 -0700 (PDT) Received-SPF: none (google.com: linux-kernel-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755958AbaGNOfH (ORCPT + 28 others); Mon, 14 Jul 2014 10:35:07 -0400 Received: from mail-ig0-f180.google.com ([209.85.213.180]:62949 "EHLO mail-ig0-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755412AbaGNOeI (ORCPT ); Mon, 14 Jul 2014 10:34:08 -0400 Received: by mail-ig0-f180.google.com with SMTP id l13so1784838iga.13 for ; Mon, 14 Jul 2014 07:34:07 -0700 (PDT) X-Received: by 10.50.137.73 with SMTP id qg9mr25786181igb.19.1405348447052; Mon, 14 Jul 2014 07:34:07 -0700 (PDT) Received: from localhost.localdomain (host109-148-237-85.range109-148.btcentralplus.com. [109.148.237.85]) by mx.google.com with ESMTPSA id q11sm25317390igr.7.2014.07.14.07.34.04 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 14 Jul 2014 07:34:06 -0700 (PDT) From: Lee Jones To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: lee.jones@linaro.org, kernel@stlinux.com, thierry.reding@gmail.com, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, ajitpal.singh@st.com Subject: [PATCH v2 09/11] pwm: sti: Ensure same period values for all channels Date: Mon, 14 Jul 2014 15:33:30 +0100 Message-Id: <1405348412-7352-10-git-send-email-lee.jones@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1405348412-7352-1-git-send-email-lee.jones@linaro.org> References: <1405348412-7352-1-git-send-email-lee.jones@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: lee.jones@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.174 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: Ajit Pal Singh ST PWM IP shares the same clock prescaler across all the PWM channels. Hence configuration requests which change the period will affect all the channels. Do not allow period changes which will stomp period settings of the already configured channels. Signed-off-by: Ajit Pal Singh Signed-off-by: Lee Jones --- drivers/pwm/pwm-sti.c | 140 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 96 insertions(+), 44 deletions(-) diff --git a/drivers/pwm/pwm-sti.c b/drivers/pwm/pwm-sti.c index 21d97bc2..0fdf4b4 100644 --- a/drivers/pwm/pwm-sti.c +++ b/drivers/pwm/pwm-sti.c @@ -58,6 +58,7 @@ struct sti_pwm_chip { struct regmap_field *pwm_int_en; unsigned long *pwm_periods; struct pwm_chip chip; + struct pwm_device *cur; void __iomem *mmio; }; @@ -99,6 +100,24 @@ static void sti_pwm_calc_periods(struct sti_pwm_chip *pc) } } +/* Calculate the number of PWM devices configured with a period. */ +unsigned int sti_pwm_count_configured(struct pwm_chip *chip) +{ + struct pwm_device *pwm; + unsigned int ncfg = 0; + unsigned int i; + + for (i = 0; i < chip->npwm; i++) { + pwm = &chip->pwms[i]; + if (test_bit(PWMF_REQUESTED, &pwm->flags)) { + if (pwm_get_period(pwm)) + ncfg++; + } + } + + return ncfg; +} + static int sti_pwm_cmp_periods(const void *key, const void *elt) { unsigned long i = *(unsigned long *)key; @@ -124,57 +143,90 @@ static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, { struct sti_pwm_chip *pc = to_sti_pwmchip(chip); struct sti_pwm_compat_data *cdata = pc->cdata; + struct pwm_device *cur = pc->cur; struct device *dev = pc->dev; - unsigned int prescale, pwmvalx; + unsigned int prescale = 0, pwmvalx; unsigned long *found; int ret; - - /* - * Search for matching period value. The corresponding index is our - * prescale value + unsigned int ncfg; + bool period_same = false; + + ncfg = sti_pwm_count_configured(chip); + if (ncfg) + period_same = (period_ns == pwm_get_period(cur)); + + /* Allow configuration changes if one of the + * following conditions satisfy. + * 1. No channels have been configured. + * 2. Only one channel has been configured and the new request + * is for the same channel. + * 3. Only one channel has been configured and the new request is + * for a new channel and period of the new channel is same as + * the current configured period. + * 4. More than one channels are configured and period of the new + * requestis the same as the current period. */ - found = bsearch(&period_ns, &pc->pwm_periods[0], - cdata->max_prescale + 1, sizeof(unsigned long), - sti_pwm_cmp_periods); - if (!found) { - dev_err(dev, "failed to find matching period\n"); + if (!ncfg || + ((ncfg == 1) && (pwm->hwpwm == cur->hwpwm)) || + ((ncfg == 1) && (pwm->hwpwm != cur->hwpwm) && period_same) || + ((ncfg > 1) && period_same)) { + /* Enable clock before writing to PWM registers. */ + ret = clk_enable(pc->clk); + if (ret) + return ret; + + if (!period_same) { + /* + * Search for matching period value. + * The corresponding index is our prescale value. + */ + found = bsearch(&period_ns, &pc->pwm_periods[0], + cdata->max_prescale + 1, + sizeof(unsigned long), + sti_pwm_cmp_periods); + if (!found) { + dev_err(dev, + "failed to find matching period\n"); + ret = -EINVAL; + goto clk_dis; + } + prescale = found - &pc->pwm_periods[0]; + + ret = + regmap_field_write(pc->prescale_low, + prescale & PWM_PRESCALE_LOW_MASK); + if (ret) + goto clk_dis; + + ret = + regmap_field_write(pc->prescale_high, + (prescale & PWM_PRESCALE_HIGH_MASK) >> 4); + if (ret) + goto clk_dis; + } + + /* + * When PWMVal == 0, PWM pulse = 1 local clock cycle. + * When PWMVal == max_pwm_count, + * PWM pulse = (max_pwm_count + 1) local cycles, + * that is continuous pulse: signal never goes low. + */ + pwmvalx = cdata->max_pwm_cnt * duty_ns / period_ns; + + ret = regmap_write(pc->regmap, STI_DS_REG(pwm->hwpwm), pwmvalx); + if (ret) + goto clk_dis; + + ret = regmap_field_write(pc->pwm_int_en, 0); + + pc->cur = pwm; + + dev_dbg(dev, "prescale:%u, period:%lu, duty:%i, pwmvalx:%u\n", + prescale, period_ns, duty_ns, pwmvalx); + } else { return -EINVAL; } - prescale = found - &pc->pwm_periods[0]; - - /* - * When PWMVal == 0, PWM pulse = 1 local clock cycle. - * When PWMVal == max_pwm_count, - * PWM pulse = (max_pwm_count + 1) local cycles, - * that is continuous pulse: signal never goes low. - */ - pwmvalx = cdata->max_pwm_cnt * duty_ns / period_ns; - - dev_dbg(dev, "prescale:%u, period:%i, duty:%i, pwmvalx:%u\n", - prescale, period_ns, duty_ns, pwmvalx); - - /* Enable clock before writing to PWM registers */ - ret = clk_enable(pc->clk); - if (ret) - return ret; - - ret = regmap_field_write(pc->prescale_low, - prescale & PWM_PRESCALE_LOW_MASK); - if (ret) - goto clk_dis; - - ret = regmap_field_write(pc->prescale_high, - (prescale & PWM_PRESCALE_HIGH_MASK) >> 4); - if (ret) - goto clk_dis; - - ret = regmap_write(pc->regmap, STI_PWMVAL(pwm->hwpwm), pwmvalx); - if (ret) - goto clk_dis; - - ret = regmap_field_write(pc->pwm_int_en, 0); - clk_dis: clk_disable(pc->clk); return ret;