From patchwork Mon Oct 26 21:32:34 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olliver Schinagl X-Patchwork-Id: 7492161 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 3A76BBEEA4 for ; Mon, 26 Oct 2015 21:35:06 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 50C0E2072B for ; Mon, 26 Oct 2015 21:35:05 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5610D204A7 for ; Mon, 26 Oct 2015 21:35:04 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZqpOX-0001qI-Re; Mon, 26 Oct 2015 21:33:33 +0000 Received: from 7of9.schinagl.nl ([88.159.158.68]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZqpOJ-0001Ul-2W for linux-arm-kernel@lists.infradead.org; Mon, 26 Oct 2015 21:33:21 +0000 Received: from um-mba-140.are-b.org. (unknown [10.2.0.189]) by 7of9.schinagl.nl (Postfix) with ESMTPA id 5243B44663; Mon, 26 Oct 2015 22:32:53 +0100 (CET) From: Olliver Schinagl To: Olliver Schinagl , Thierry Reding , Rob Herring , Pawel Moll , Mark Rutland , Ian Campbell , Kumar Gala , Joachim Eastwood , Maxime Ripard , Alexandre Belloni Subject: [PATCH 03/10] pwm: sunxi: Yield some time to the pwm-block to become ready Date: Mon, 26 Oct 2015 22:32:34 +0100 Message-Id: <1445895161-2317-4-git-send-email-o.schinagl@ultimaker.com> X-Mailer: git-send-email 2.6.1 In-Reply-To: <1445895161-2317-1-git-send-email-o.schinagl@ultimaker.com> References: <1445895161-2317-1-git-send-email-o.schinagl@ultimaker.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20151026_143319_322426_5D8176E5 X-CRM114-Status: GOOD ( 14.71 ) X-Spam-Score: -1.2 (-) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Olliver Schinagl , linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, Olliver Schinagl , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The pwm-block of some of the sunxi chips feature a 'ready' flag to indicate the software that it is ready for new commands. Right now, when we call pwm_config and set the period, we write the values to the registers, and turn off the clock to the IP. Because of this, the hardware does not have time to configure the hardware and set the 'ready' flag. By running the clock just before making new changes and before checking if the hardware is ready, the hardware has time to reconfigure itself and set the clear the flag appropriately. Signed-off-by: Olliver Schinagl --- drivers/pwm/pwm-sun4i.c | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c index 58ff424..4d84d9d 100644 --- a/drivers/pwm/pwm-sun4i.c +++ b/drivers/pwm/pwm-sun4i.c @@ -104,6 +104,22 @@ static int sun4i_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, u64 clk_rate, div = 0; unsigned int prescaler = 0; int err; + int ret = 0; + + /* Let the PWM hardware run before making any changes. We do this to + * allow the hardware to have some time to clear the 'ready' flag. + */ + err = clk_prepare_enable(sun4i_pwm->clk); + if (err) { + dev_err(chip->dev, "failed to enable PWM clock\n"); + return err; + } + spin_lock(&sun4i_pwm->ctrl_lock); + val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG); + clk_gate = val & BIT_CH(PWM_CLK_GATING, pwm->hwpwm); + val |= BIT_CH(PWM_CLK_GATING, pwm->hwpwm); + sun4i_pwm_writel(sun4i_pwm, val, PWM_CTRL_REG); + spin_unlock(&sun4i_pwm->ctrl_lock); clk_rate = clk_get_rate(sun4i_pwm->clk); @@ -136,7 +152,9 @@ static int sun4i_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, if (div - 1 > PWM_PRD_MASK) { dev_err(chip->dev, "period exceeds the maximum value\n"); - return -EINVAL; + ret = -EINVAL; + spin_lock(&sun4i_pwm->ctrl_lock); + goto out; } } @@ -145,26 +163,14 @@ static int sun4i_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, do_div(div, period_ns); dty = div; - err = clk_prepare_enable(sun4i_pwm->clk); - if (err) { - dev_err(chip->dev, "failed to enable PWM clock\n"); - return err; - } - spin_lock(&sun4i_pwm->ctrl_lock); val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG); - 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); - sun4i_pwm_writel(sun4i_pwm, val, PWM_CTRL_REG); + ret = -EBUSY; + goto out; } + val &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm); + sun4i_pwm_writel(sun4i_pwm, val, PWM_CTRL_REG); val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG); val &= ~BIT_CH(PWM_PRESCAL_MASK, pwm->hwpwm); @@ -174,6 +180,7 @@ static int sun4i_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, val = (dty & PWM_DTY_MASK) | PWM_PRD(prd); sun4i_pwm_writel(sun4i_pwm, val, PWM_CH_PRD(pwm->hwpwm)); +out: if (clk_gate) { val = sun4i_pwm_readl(sun4i_pwm, PWM_CTRL_REG); val |= clk_gate; @@ -183,7 +190,7 @@ static int sun4i_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, spin_unlock(&sun4i_pwm->ctrl_lock); clk_disable_unprepare(sun4i_pwm->clk); - return 0; + return ret; } static int sun4i_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,