From patchwork Wed Sep 9 13:07:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Felsch X-Patchwork-Id: 11765429 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 84A40138E for ; Wed, 9 Sep 2020 13:08:15 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9A05621D81 for ; Wed, 9 Sep 2020 13:08:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="aSI8/gBg" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9A05621D81 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=trLAOk5EASfXqMwxD23ULyGXyq9pjGlqIjZ22I1d8gE=; b=aSI8/gBg4gBC9nCEl2wWW52EY c3DFJvJ1ASPdOTK3H5IdIyaMZaJZSo4c1iTics6KwSmL9PF7eH4U+sDakdPqczStHzUGGaXxQjAkx pOQ+phf4f20cf4YLCFFzCSaEowIXqDgEtlpcZdEPUjsr34UQ1bl/mMvrNK8ZSrgqM0WNXSygvuKaf zjTEHauuPIl47Q90QedGkHUs8EDt+rqU71qnLafZswC0w3TZLyPT8v6IkGjnoI3CZ6bdrz2iQbW2u rC3pR9e67EJ7wm6fyfCDHU6yox9hHZGhTcmUqHTIS/oUwFbRTJ0TL5/dNflCHrYUg2eIOuW0qFpr7 EKAPpVEeA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kFzpO-0008JB-GV; Wed, 09 Sep 2020 13:07:58 +0000 Received: from metis.ext.pengutronix.de ([2001:67c:670:201:290:27ff:fe1d:cc33]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kFzpK-0008Hu-SU for linux-arm-kernel@lists.infradead.org; Wed, 09 Sep 2020 13:07:55 +0000 Received: from dude02.hi.pengutronix.de ([2001:67c:670:100:1d::28]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kFzpB-0002t3-5r; Wed, 09 Sep 2020 15:07:45 +0200 Received: from mfe by dude02.hi.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1kFzp9-0004Uy-Ib; Wed, 09 Sep 2020 15:07:43 +0200 From: Marco Felsch To: thierry.reding@gmail.com, u.kleine-koenig@pengutronix.de, lee.jones@linaro.org, shawnguo@kernel.org, s.hauer@pengutronix.de, festevam@gmail.com, linux-imx@nxp.com, Anson.Huang@nxp.com, michal.vokac@ysoft.com, l.majewski@majess.pl Subject: [PATCH 1/3] pwm: imx27: track clock enable/disable to simplify code Date: Wed, 9 Sep 2020 15:07:37 +0200 Message-Id: <20200909130739.26717-2-m.felsch@pengutronix.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200909130739.26717-1-m.felsch@pengutronix.de> References: <20200909130739.26717-1-m.felsch@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::28 X-SA-Exim-Mail-From: mfe@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-arm-kernel@lists.infradead.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200909_090754_958383_6215B92C X-CRM114-Status: GOOD ( 15.77 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pwm@vger.kernel.org, kernel@pengutronix.de, linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Introduce a simple clock state so we can enable/disable the clock without the need to check if we are running or not. Signed-off-by: Marco Felsch --- drivers/pwm/pwm-imx27.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c index c50d453552bd..3cf9f1774244 100644 --- a/drivers/pwm/pwm-imx27.c +++ b/drivers/pwm/pwm-imx27.c @@ -91,6 +91,7 @@ struct pwm_imx27_chip { * value to return in that case. */ unsigned int duty_cycle; + bool clk_on; }; #define to_pwm_imx27_chip(chip) container_of(chip, struct pwm_imx27_chip, chip) @@ -99,6 +100,9 @@ static int pwm_imx27_clk_prepare_enable(struct pwm_imx27_chip *imx) { int ret; + if (imx->clk_on) + return 0; + ret = clk_prepare_enable(imx->clk_ipg); if (ret) return ret; @@ -109,13 +113,20 @@ static int pwm_imx27_clk_prepare_enable(struct pwm_imx27_chip *imx) return ret; } + imx->clk_on = true; + return 0; } static void pwm_imx27_clk_disable_unprepare(struct pwm_imx27_chip *imx) { + if (!imx->clk_on) + return; + clk_disable_unprepare(imx->clk_per); clk_disable_unprepare(imx->clk_ipg); + + imx->clk_on = false; } static void pwm_imx27_get_state(struct pwm_chip *chip, @@ -223,6 +234,10 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, int ret; u32 cr; + ret = pwm_imx27_clk_prepare_enable(imx); + if (ret) + return ret; + pwm_get_state(pwm, &cstate); clkrate = clk_get_rate(imx->clk_per); @@ -254,10 +269,6 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (cstate.enabled) { pwm_imx27_wait_fifo_slot(chip, pwm); } else { - ret = pwm_imx27_clk_prepare_enable(imx); - if (ret) - return ret; - pwm_imx27_sw_reset(chip); } From patchwork Wed Sep 9 13:07:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Felsch X-Patchwork-Id: 11765435 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 27FE4138E for ; Wed, 9 Sep 2020 13:09:36 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E057E21D7F for ; Wed, 9 Sep 2020 13:09:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="deZy15gZ" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E057E21D7F Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=eat9+lZI3UToiGQYB7sCJQqjPjFpzy08ozD+bweY5iw=; b=deZy15gZNVSAMJ5RaTq0baboL /4wval9/LFo4Ukdas5cBw/GiEalVwl32FCZCuW1IObPeJXVjbX5pZuey/rTpRKmgSp2lRevsAJfTh fXlCixZ3CMsVWt7keYBQvYbnY/w/R5Ulrx7pzOtUVhUIFjYsEq4PVnb2ZYPIpaXZAk8gT/yOB83uP l/nnDXexRc95DnOZrmwOQJucaiOGcmURZiUj90DKgyYITjJrYR3OVafOkzbTlmJJaHE3QKB9/uh1l oIAq4pxzQ1dPQ6OhxgSym+j9Pi8O3uoYETsyhpL8xoZ1/d1R5kN5BM8Dv1TWiQl8CVT/xwJBlxhfe taJ4Yv42Q==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kFzpM-0008Iu-Q8; Wed, 09 Sep 2020 13:07:56 +0000 Received: from metis.ext.pengutronix.de ([2001:67c:670:201:290:27ff:fe1d:cc33]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kFzpK-0008Hq-Of for linux-arm-kernel@lists.infradead.org; Wed, 09 Sep 2020 13:07:55 +0000 Received: from dude02.hi.pengutronix.de ([2001:67c:670:100:1d::28]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kFzpB-0002t4-5p; Wed, 09 Sep 2020 15:07:45 +0200 Received: from mfe by dude02.hi.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1kFzp9-0004Vk-K3; Wed, 09 Sep 2020 15:07:43 +0200 From: Marco Felsch To: thierry.reding@gmail.com, u.kleine-koenig@pengutronix.de, lee.jones@linaro.org, shawnguo@kernel.org, s.hauer@pengutronix.de, festevam@gmail.com, linux-imx@nxp.com, Anson.Huang@nxp.com, michal.vokac@ysoft.com, l.majewski@majess.pl Subject: [PATCH 2/3] pwm: imx27: move static pwmcr values into probe() function Date: Wed, 9 Sep 2020 15:07:38 +0200 Message-Id: <20200909130739.26717-3-m.felsch@pengutronix.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200909130739.26717-1-m.felsch@pengutronix.de> References: <20200909130739.26717-1-m.felsch@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::28 X-SA-Exim-Mail-From: mfe@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-arm-kernel@lists.infradead.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200909_090754_821397_BFA2B25D X-CRM114-Status: GOOD ( 20.39 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pwm@vger.kernel.org, kernel@pengutronix.de, linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org The STOPEN, DOZEN, WAITEN, DBGEN and the CLKSRC bit values never change. So it should be save to move this bit settings into probe() and change only the necessary bits during apply(). Therefore I added the pwm_imx27_update_bits() helper. Furthermore the patch adds the support to reset the pwm device during probe() if the pwm device is disabled. Both steps are required in preparation of the further patch which fixes the "pwm-disabled" state for inverted pwms. Signed-off-by: Marco Felsch --- drivers/pwm/pwm-imx27.c | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c index 3cf9f1774244..30388a9ece04 100644 --- a/drivers/pwm/pwm-imx27.c +++ b/drivers/pwm/pwm-imx27.c @@ -96,6 +96,16 @@ struct pwm_imx27_chip { #define to_pwm_imx27_chip(chip) container_of(chip, struct pwm_imx27_chip, chip) +static void pwm_imx27_update_bits(void __iomem *reg, u32 mask, u32 val) +{ + u32 tmp; + + tmp = readl(reg); + tmp &= ~mask; + tmp |= val & mask; + return writel(tmp, reg); +} + static int pwm_imx27_clk_prepare_enable(struct pwm_imx27_chip *imx) { int ret; @@ -183,10 +193,8 @@ static void pwm_imx27_get_state(struct pwm_chip *chip, pwm_imx27_clk_disable_unprepare(imx); } -static void pwm_imx27_sw_reset(struct pwm_chip *chip) +static void pwm_imx27_sw_reset(struct pwm_imx27_chip *imx, struct device *dev) { - struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip); - struct device *dev = chip->dev; int wait_count = 0; u32 cr; @@ -232,7 +240,7 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, unsigned long long c; unsigned long long clkrate; int ret; - u32 cr; + u32 cr, mask; ret = pwm_imx27_clk_prepare_enable(imx); if (ret) @@ -269,7 +277,7 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (cstate.enabled) { pwm_imx27_wait_fifo_slot(chip, pwm); } else { - pwm_imx27_sw_reset(chip); + pwm_imx27_sw_reset(imx, chip->dev); } writel(duty_cycles, imx->mmio_base + MX3_PWMSAR); @@ -281,10 +289,7 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, */ imx->duty_cycle = duty_cycles; - cr = MX3_PWMCR_PRESCALER_SET(prescale) | - MX3_PWMCR_STOPEN | MX3_PWMCR_DOZEN | MX3_PWMCR_WAITEN | - FIELD_PREP(MX3_PWMCR_CLKSRC, MX3_PWMCR_CLKSRC_IPG_HIGH) | - MX3_PWMCR_DBGEN; + cr = MX3_PWMCR_PRESCALER_SET(prescale); if (state->polarity == PWM_POLARITY_INVERSED) cr |= FIELD_PREP(MX3_PWMCR_POUTC, @@ -293,7 +298,9 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (state->enabled) cr |= MX3_PWMCR_EN; - writel(cr, imx->mmio_base + MX3_PWMCR); + mask = MX3_PWMCR_PRESCALER | MX3_PWMCR_POUTC | MX3_PWMCR_EN; + + pwm_imx27_update_bits(imx->mmio_base + MX3_PWMCR, mask, cr); if (!state->enabled) pwm_imx27_clk_disable_unprepare(imx); @@ -364,10 +371,20 @@ static int pwm_imx27_probe(struct platform_device *pdev) if (ret) return ret; - /* keep clks on if pwm is running */ + /* Keep clks on and pwm settings unchanged if the PWM is already running */ pwmcr = readl(imx->mmio_base + MX3_PWMCR); - if (!(pwmcr & MX3_PWMCR_EN)) + if (!(pwmcr & MX3_PWMCR_EN)) { + u32 mask; + + pwm_imx27_sw_reset(imx, &pdev->dev); + mask = MX3_PWMCR_STOPEN | MX3_PWMCR_DOZEN | MX3_PWMCR_WAITEN | + MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC; + pwmcr = MX3_PWMCR_STOPEN | MX3_PWMCR_DOZEN | MX3_PWMCR_WAITEN | + MX3_PWMCR_DBGEN | + FIELD_PREP(MX3_PWMCR_CLKSRC, MX3_PWMCR_CLKSRC_IPG_HIGH); + pwm_imx27_update_bits(imx->mmio_base + MX3_PWMCR, mask, pwmcr); pwm_imx27_clk_disable_unprepare(imx); + } return pwmchip_add(&imx->chip); } From patchwork Wed Sep 9 13:07:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Felsch X-Patchwork-Id: 11765431 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CC4EB138E for ; Wed, 9 Sep 2020 13:08:17 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9483221D81 for ; Wed, 9 Sep 2020 13:08:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="eZB/jf2f" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9483221D81 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=0NcXyB8racyyX70Jg8yTLZKnlQr+vsFkNhe2fbzFeSg=; b=eZB/jf2fr3UkQDPBmGQgyOjj/ 3VlaF1Ws4RIIOSKvvIMqmm53sX1LXpkRF00LQANCPdlzpmxPE3GddsXH10vJWrzL19TOfbNhgpoUZ Tb81dwUcjtCYW3EMxJEFlRPuY3WayYH52S+Fl+DZIzeDe4XlyJE1HHyn2vDNTU/FtQ0omRnkHSkrN u5oYrhFTdSKQKqpiNIi8t1QSqOj/cHOUP822tVDFFlAa+waJa9puRFz6uj1ol1bPEfEuuBdQJRAto /0E9y9c2J56Ag/xXUOTnrJxl+0veC1tvBwT/JUDc+g8XdMgWG5jp3w4djdEJBchxvtHkbfXA3QyAR 6kVuNSF7A==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kFzpW-0008LD-79; Wed, 09 Sep 2020 13:08:06 +0000 Received: from metis.ext.pengutronix.de ([2001:67c:670:201:290:27ff:fe1d:cc33]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kFzpQ-0008JM-5p for linux-arm-kernel@lists.infradead.org; Wed, 09 Sep 2020 13:08:01 +0000 Received: from dude02.hi.pengutronix.de ([2001:67c:670:100:1d::28]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kFzpB-0002t5-5r; Wed, 09 Sep 2020 15:07:45 +0200 Received: from mfe by dude02.hi.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1kFzp9-0004WX-LR; Wed, 09 Sep 2020 15:07:43 +0200 From: Marco Felsch To: thierry.reding@gmail.com, u.kleine-koenig@pengutronix.de, lee.jones@linaro.org, shawnguo@kernel.org, s.hauer@pengutronix.de, festevam@gmail.com, linux-imx@nxp.com, Anson.Huang@nxp.com, michal.vokac@ysoft.com, l.majewski@majess.pl Subject: [PATCH 3/3] pwm: imx27: fix disable state for inverted PWMs Date: Wed, 9 Sep 2020 15:07:39 +0200 Message-Id: <20200909130739.26717-4-m.felsch@pengutronix.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200909130739.26717-1-m.felsch@pengutronix.de> References: <20200909130739.26717-1-m.felsch@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::28 X-SA-Exim-Mail-From: mfe@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-arm-kernel@lists.infradead.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200909_090800_280713_5061D6C8 X-CRM114-Status: GOOD ( 26.40 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pwm@vger.kernel.org, kernel@pengutronix.de, linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Up to now disabling the PWM is done using the PWMCR.EN register bit. Setting this bit to zero results in the output pin driving a low value independent of the polarity setting (PWMCR.POUTC). There is only little documentation about expectations and requirements in the PWM framework but the usual expectation seems to be that disabling a PWM or setting .duty_cycle = 0 results in the output driving the inactive level. The pwm-bl driver for example uses this setting to disable the backlight and with the pwm-imx27 driver this results in an enabled backlight if the pwm signal is inverted. Keep the PWMCR.EN bit always enabled and simulate a disabled PWM using duty_cycle = 0 to fix this. Furthermore we have to drop the sw-reset from apply() else the PWMCR.EN is cleared too. Therefore the pwm_imx27_wait_fifo_slot() is extended to guarantee a free FIFO slot. Signed-off-by: Marco Felsch --- drivers/pwm/pwm-imx27.c | 69 ++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c index 30388a9ece04..d98e8df14eb9 100644 --- a/drivers/pwm/pwm-imx27.c +++ b/drivers/pwm/pwm-imx27.c @@ -92,6 +92,7 @@ struct pwm_imx27_chip { */ unsigned int duty_cycle; bool clk_on; + bool enabled; }; #define to_pwm_imx27_chip(chip) container_of(chip, struct pwm_imx27_chip, chip) @@ -151,12 +152,9 @@ static void pwm_imx27_get_state(struct pwm_chip *chip, if (ret < 0) return; - val = readl(imx->mmio_base + MX3_PWMCR); + state->enabled = imx->enabled; - if (val & MX3_PWMCR_EN) - state->enabled = true; - else - state->enabled = false; + val = readl(imx->mmio_base + MX3_PWMCR); switch (FIELD_GET(MX3_PWMCR_POUTC, val)) { case MX3_PWMCR_POUTC_NORMAL: @@ -179,8 +177,8 @@ static void pwm_imx27_get_state(struct pwm_chip *chip, state->period = DIV_ROUND_UP_ULL(tmp, pwm_clk); /* - * PWMSAR can be read only if PWM is enabled. If the PWM is disabled, - * use the cached value. + * Use the cached value if the PWM is disabled since we are using the + * PWMSAR to disable the PWM (see the notes in pwm_imx27_apply()) */ if (state->enabled) val = readl(imx->mmio_base + MX3_PWMSAR); @@ -209,8 +207,8 @@ static void pwm_imx27_sw_reset(struct pwm_imx27_chip *imx, struct device *dev) dev_warn(dev, "software reset timeout\n"); } -static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip, - struct pwm_device *pwm) +static int pwm_imx27_wait_fifo_slot(struct pwm_chip *chip, + struct pwm_device *pwm) { struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip); struct device *dev = chip->dev; @@ -226,9 +224,13 @@ static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip, msleep(period_ms); sr = readl(imx->mmio_base + MX3_PWMSR); - if (fifoav == FIELD_GET(MX3_PWMSR_FIFOAV, sr)) + if (fifoav == FIELD_GET(MX3_PWMSR_FIFOAV, sr)) { dev_warn(dev, "there is no free FIFO slot\n"); + return -EBUSY; + } } + + return 0; } static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, @@ -270,17 +272,25 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, else period_cycles = 0; + /* Wait for a free FIFO slot */ + ret = pwm_imx27_wait_fifo_slot(chip, pwm); + if (ret) + goto out; + /* - * Wait for a free FIFO slot if the PWM is already enabled, and flush - * the FIFO if the PWM was disabled and is about to be enabled. + * We can't use the enable bit to control the en-/disable squence + * correctly because the output pin is pulled low if setting this bit + * to '0' regardless of the poutc value. Instead we have to use the + * sample register. According the RM: + * A value of zero in the sample register will result in the PWMO output + * signal always being low/high (POUTC = 00 it will be low and + * POUTC = 01 it will be high), and no output waveform will be produced. + * If the value in this register is higher than the PERIOD */ - if (cstate.enabled) { - pwm_imx27_wait_fifo_slot(chip, pwm); - } else { - pwm_imx27_sw_reset(imx, chip->dev); - } - - writel(duty_cycles, imx->mmio_base + MX3_PWMSAR); + if (state->enabled) + writel(duty_cycles, imx->mmio_base + MX3_PWMSAR); + else + writel(0, imx->mmio_base + MX3_PWMSAR); writel(period_cycles, imx->mmio_base + MX3_PWMPR); /* @@ -288,24 +298,21 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, * MX3_PWMSAR register can't be read (i.e. when the PWM is disabled). */ imx->duty_cycle = duty_cycles; + imx->enabled = state->enabled; cr = MX3_PWMCR_PRESCALER_SET(prescale); - if (state->polarity == PWM_POLARITY_INVERSED) - cr |= FIELD_PREP(MX3_PWMCR_POUTC, - MX3_PWMCR_POUTC_INVERTED); + cr |= FIELD_PREP(MX3_PWMCR_POUTC, MX3_PWMCR_POUTC_INVERTED); - if (state->enabled) - cr |= MX3_PWMCR_EN; - - mask = MX3_PWMCR_PRESCALER | MX3_PWMCR_POUTC | MX3_PWMCR_EN; + mask = MX3_PWMCR_PRESCALER | MX3_PWMCR_POUTC; pwm_imx27_update_bits(imx->mmio_base + MX3_PWMCR, mask, cr); +out: if (!state->enabled) pwm_imx27_clk_disable_unprepare(imx); - return 0; + return ret; } static const struct pwm_ops pwm_imx27_ops = { @@ -378,12 +385,16 @@ static int pwm_imx27_probe(struct platform_device *pdev) pwm_imx27_sw_reset(imx, &pdev->dev); mask = MX3_PWMCR_STOPEN | MX3_PWMCR_DOZEN | MX3_PWMCR_WAITEN | - MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC; + MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC | MX3_PWMCR_POUTC | MX3_PWMCR_EN; pwmcr = MX3_PWMCR_STOPEN | MX3_PWMCR_DOZEN | MX3_PWMCR_WAITEN | MX3_PWMCR_DBGEN | - FIELD_PREP(MX3_PWMCR_CLKSRC, MX3_PWMCR_CLKSRC_IPG_HIGH); + FIELD_PREP(MX3_PWMCR_CLKSRC, MX3_PWMCR_CLKSRC_IPG_HIGH) | + FIELD_PREP(MX3_PWMCR_POUTC, MX3_PWMCR_POUTC_OFF) | + MX3_PWMCR_EN; pwm_imx27_update_bits(imx->mmio_base + MX3_PWMCR, mask, pwmcr); pwm_imx27_clk_disable_unprepare(imx); + } else { + imx->enabled = true; } return pwmchip_add(&imx->chip);