From patchwork Mon Feb 10 21:22:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= X-Patchwork-Id: 1236001 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48Gf5M1V89z9sRX for ; Tue, 11 Feb 2020 08:23:03 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727254AbgBJVXC (ORCPT ); Mon, 10 Feb 2020 16:23:02 -0500 Received: from metis.ext.pengutronix.de ([85.220.165.71]:39637 "EHLO metis.ext.pengutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727363AbgBJVXC (ORCPT ); Mon, 10 Feb 2020 16:23:02 -0500 Received: from pty.hi.pengutronix.de ([2001:67c:670:100:1d::c5]) by metis.ext.pengutronix.de with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1j1GWC-0000yM-HV; Mon, 10 Feb 2020 22:23:00 +0100 Received: from ukl by pty.hi.pengutronix.de with local (Exim 4.89) (envelope-from ) id 1j1GWB-00042y-Bp; Mon, 10 Feb 2020 22:22:59 +0100 From: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= To: Thierry Reding Cc: linux-pwm@vger.kernel.org, Shawn Guo , NXP Linux Team , Pengutronix Kernel Team , Fabio Estevam , linux-arm-kernel@lists.infradead.org Subject: [PATCH 3/3] pwm: imx27: Ensure clocks being on iff the PWM is on Date: Mon, 10 Feb 2020 22:22:40 +0100 Message-Id: <20200210212240.25513-4-u.kleine-koenig@pengutronix.de> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200210212240.25513-1-u.kleine-koenig@pengutronix.de> References: <20200209213106.5067-1-u.kleine-koenig@pengutronix.de> <20200210212240.25513-1-u.kleine-koenig@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::c5 X-SA-Exim-Mail-From: ukl@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-pwm@vger.kernel.org Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org Up to now the .probe function didn't enable clks and relied on the core to call the .get_state() callback to have the clk running. The latter enabled the needed clocks and kept them running if the PWM is enabled. This only works correctly if the .get_state() callback is called exactly once and this single call happens before unused clocks are disabled by the clk core. The former wasn't true for a short period while commit 01ccf903edd6 ("pwm: Let pwm_get_state() return the last implemented state") applied and not not reverted yet and might become wrong in the future. The latter isn't true any more since commit cfc4c189bc70 ("pwm: Read initial hardware state at request time") which results in a running PWM being stopped at boot time if for example the consumer lives in a kernel module that is only loaded after the clk core disabled unused clocks. So ensure .probe() is left with the clocks on if the PWM is running and .get_state() disables everything it enabled. Signed-off-by: Uwe Kleine-König --- drivers/pwm/pwm-imx27.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c index fb142813d455..e83c077bb7cc 100644 --- a/drivers/pwm/pwm-imx27.c +++ b/drivers/pwm/pwm-imx27.c @@ -171,8 +171,7 @@ static void pwm_imx27_get_state(struct pwm_chip *chip, tmp = NSEC_PER_SEC * (u64)(val); state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, pwm_clk); - if (!state->enabled) - pwm_imx27_clk_disable_unprepare(imx); + pwm_imx27_clk_disable_unprepare(imx); } static void pwm_imx27_sw_reset(struct pwm_chip *chip) @@ -307,6 +306,8 @@ MODULE_DEVICE_TABLE(of, pwm_imx27_dt_ids); static int pwm_imx27_probe(struct platform_device *pdev) { struct pwm_imx27_chip *imx; + int ret; + u32 pwmcr; imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL); if (imx == NULL) @@ -349,6 +350,15 @@ static int pwm_imx27_probe(struct platform_device *pdev) if (IS_ERR(imx->mmio_base)) return PTR_ERR(imx->mmio_base); + ret = pwm_imx27_clk_prepare_enable(imx); + if (ret) + return ret; + + /* keep clks on if pwm is running */ + pwmcr = readl(imx->mmio_base + MX3_PWMCR); + if (!(pwmcr & MX3_PWMCR_EN)) + pwm_imx27_clk_disable_unprepare(imx); + return pwmchip_add(&imx->chip); }