From patchwork Mon Oct 21 10:57:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 1180471 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=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="fYxmYpF1"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46xYWX63vSz9sNw for ; Mon, 21 Oct 2019 21:57:44 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727032AbfJUK5o (ORCPT ); Mon, 21 Oct 2019 06:57:44 -0400 Received: from mail-wm1-f67.google.com ([209.85.128.67]:37205 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727058AbfJUK5n (ORCPT ); Mon, 21 Oct 2019 06:57:43 -0400 Received: by mail-wm1-f67.google.com with SMTP id f22so12290399wmc.2 for ; Mon, 21 Oct 2019 03:57:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=wrFxWZMLBUPw4bBJ17t4yXM8+YLr11qHLb+Gez/eLcQ=; b=fYxmYpF1T5qqcN4Fi0/A7Cp+3Pp1orYg8hUH+xNohtLoKGarPjYGgaBwnweiziuEEE 5C4k2AY8l3DAZDbcJs4sA79W5bkLXWXOhM3g4ofPUwLM/1Dm09FvwsJYZC4kVG6hWhD1 mQbTMaTEoZZi+Zho8gQlmgwiTpm9Q0AzdK1D7k1mdu3mrBW+/rx2Ejih0EGRIE78nO5Y UugsNntG9yiM3ym0aBRKaXglW8ettbPeuVvIBYmUlOx2NNUEdccCFgSWx5VskUzjV4Jh VMejOR9aksef9ZRU+98hdcS1j0Gs0UiFb1gBPmmK6jtTBvQXURXAcMrTX5bhEMOjnvEI 0AHg== 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:mime-version :content-transfer-encoding; bh=wrFxWZMLBUPw4bBJ17t4yXM8+YLr11qHLb+Gez/eLcQ=; b=dK2VC13sBq8Kw0/n+nqXeEXxYZBk3Om8FhWK/s7d7cnzP0pJcTxiWm0zAvFS1jvzdz j1J5chTXL0v+xuhZlEMvDEtQJ+21TpcOjC8P9HfeCjBIZQBMuC0gRMlvh/+LT31cvGB0 QYyzQfI0XTK9o7f59DXa9VyRErzgulISUGaBwgIb0PZ+1UcpM7qKiYhtQflg5HXBisV8 iwOXwZ6uKLVtNKwR7ZrAz/EpzEn45JK116saYhbHw2t9bZ0YSjGhaaTwB62X9RXNaxy+ hHdZg1QjAo5aSQUfJ/g/l5mMfgrITqMqtUusiHD5/1iglYWXDM5EBtmbNCZxjvv0j/Re sL4g== X-Gm-Message-State: APjAAAWMEsfzeK4/ovK/yVYcZ8dxN6vUzE39iWmeyLiWUYN4X9qoAE2l d/qXYmves+GljISHdRA5AsoeaCkw X-Google-Smtp-Source: APXvYqwwwOemQ59F8GRQW6hxDezhpbYL/p3oz82AvUyTM01/gjdSdN3rqr+axQruH+oOL7Ywq4LsnQ== X-Received: by 2002:a7b:c8d9:: with SMTP id f25mr19370051wml.153.1571655461663; Mon, 21 Oct 2019 03:57:41 -0700 (PDT) Received: from localhost (p2E5BE2CE.dip0.t-ipconnect.de. [46.91.226.206]) by smtp.gmail.com with ESMTPSA id 36sm17208081wrp.30.2019.10.21.03.57.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Oct 2019 03:57:40 -0700 (PDT) From: Thierry Reding To: Thierry Reding Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Enric Balletbo i Serra , linux-pwm@vger.kernel.org Subject: [PATCH 1/4] pwm: Read initial hardware state at request time Date: Mon, 21 Oct 2019 12:57:36 +0200 Message-Id: <20191021105739.1357629-1-thierry.reding@gmail.com> X-Mailer: git-send-email 2.23.0 MIME-Version: 1.0 Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org The PWM core doesn't need to know about the hardware state of a PWM unless there is a user for it. Defer initial hardware readout until a PWM is requested. As a side-effect, this allows the ->get_state() callback to rely on per-PWM data. Signed-off-by: Thierry Reding Tested-by: Michal Vokáč Tested-by: Enric Balletbo i Serra --- drivers/pwm/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index f877e77d9184..e067873c6cc5 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -114,6 +114,9 @@ static int pwm_device_request(struct pwm_device *pwm, const char *label) } } + if (pwm->chip->ops->get_state) + pwm->chip->ops->get_state(pwm->chip, pwm, &pwm->state); + set_bit(PWMF_REQUESTED, &pwm->flags); pwm->label = label; @@ -283,9 +286,6 @@ int pwmchip_add_with_polarity(struct pwm_chip *chip, pwm->hwpwm = i; pwm->state.polarity = polarity; - if (chip->ops->get_state) - chip->ops->get_state(chip, pwm, &pwm->state); - radix_tree_insert(&pwm_tree, pwm->pwm, pwm); } From patchwork Mon Oct 21 10:57:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 1180472 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=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Po1yI6dC"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46xYWb3P92z9sNw for ; Mon, 21 Oct 2019 21:57:47 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727433AbfJUK5q (ORCPT ); Mon, 21 Oct 2019 06:57:46 -0400 Received: from mail-wr1-f66.google.com ([209.85.221.66]:45132 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727058AbfJUK5q (ORCPT ); Mon, 21 Oct 2019 06:57:46 -0400 Received: by mail-wr1-f66.google.com with SMTP id q13so8436523wrs.12 for ; Mon, 21 Oct 2019 03:57:44 -0700 (PDT) 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 :mime-version:content-transfer-encoding; bh=LGKZY/IUiUO+2uYTzAHQ0rrYcK00zgUZpnSA7MuBH8Y=; b=Po1yI6dCYha299HufnChjcwwTMIf04UtPqwYjI3+aENtiYRn28jjr1Hy6bjLURWwEg 9jKkvJJYjLQN74TmmoPlO4KjpUuZ6TCfIhzQEYiJ92YW6yjx2SlGwlPmyUTDbYxA7wg+ aFKOBExSvs5ZQ5dz0iz219iG7iGaUukH988WF8nWVFBzDizw7HeXwDH92JjF47KN17q8 pTEzuaLYYqEwif/o/84YA+DZjcSocEVqUuC4DDl8rP9DM2blkkRV/c0e26DO/tiJICC/ N9Z5SMjTJp+vUx0Zb9WUTMVV8cPHX0VuEH+1bV7kCYwTSw84fhBxJkWa6E94Xoxn72AN shRw== 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:mime-version:content-transfer-encoding; bh=LGKZY/IUiUO+2uYTzAHQ0rrYcK00zgUZpnSA7MuBH8Y=; b=sldFaKIq8P/4bV0nUM4hxQu84+Bw5KqcA5KLDaFX7CNXV+C9k4DIFni4eIxPMlpHKL nrHZ9CObfP9NcdIcMdeItNDtEuoxHGNZJVZ7m1SmIJZeA6dd5TPcehEhxkq0PQ8PzDxh jtgbV4FbC6s3zQ5XpKTS8zFhkUtM7piUrJgQO2Pckdg86OpbZ58j9dM22uuzYNANt3Gm 1SAJYMb/VYFaXw7/ZxZbrZyvbeCrjg4YDZhiB6ppR17bEZzKOoTAgEN/z1uqiqrl56ce CzaThGWvwD9q4Aph8aOTs3G70xU6hkZYm4xmPO9L/BNd4y9Xy+S7yo+4mxCokVc5Sa47 Wcng== X-Gm-Message-State: APjAAAUzn+LEkMJh2xfI/fe6b+LOuBP6Rrehgd6zaxfufvrwVhY0mmfV FQr1Zza5c3bbEUgUBoK3k5s= X-Google-Smtp-Source: APXvYqwyPBXXMSaujR7KAfnqVvM02q0ZOiR5Zdn09CvdZ5DS1l+2T2h5aNHdr3Gms59w+uPJ1wfrzQ== X-Received: by 2002:adf:eb8c:: with SMTP id t12mr14374076wrn.34.1571655463884; Mon, 21 Oct 2019 03:57:43 -0700 (PDT) Received: from localhost (p2E5BE2CE.dip0.t-ipconnect.de. [46.91.226.206]) by smtp.gmail.com with ESMTPSA id q11sm4149887wmq.21.2019.10.21.03.57.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Oct 2019 03:57:42 -0700 (PDT) From: Thierry Reding To: Thierry Reding Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Enric Balletbo i Serra , linux-pwm@vger.kernel.org Subject: [PATCH 2/4] pwm: cros-ec: Cache duty cycle value Date: Mon, 21 Oct 2019 12:57:37 +0200 Message-Id: <20191021105739.1357629-2-thierry.reding@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191021105739.1357629-1-thierry.reding@gmail.com> References: <20191021105739.1357629-1-thierry.reding@gmail.com> MIME-Version: 1.0 Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org The ChromeOS embedded controller doesn't differentiate between disabled and duty cycle being 0. In order not to potentially confuse consumers, cache the duty cycle and return the cached value instead of the real value when the PWM is disabled. Signed-off-by: Thierry Reding Tested-by: Enric Balletbo i Serra --- drivers/pwm/pwm-cros-ec.c | 58 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/drivers/pwm/pwm-cros-ec.c b/drivers/pwm/pwm-cros-ec.c index 89497448d217..09c08dee099e 100644 --- a/drivers/pwm/pwm-cros-ec.c +++ b/drivers/pwm/pwm-cros-ec.c @@ -25,11 +25,39 @@ struct cros_ec_pwm_device { struct pwm_chip chip; }; +/** + * struct cros_ec_pwm - per-PWM driver data + * @duty_cycle: cached duty cycle + */ +struct cros_ec_pwm { + u16 duty_cycle; +}; + static inline struct cros_ec_pwm_device *pwm_to_cros_ec_pwm(struct pwm_chip *c) { return container_of(c, struct cros_ec_pwm_device, chip); } +static int cros_ec_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct cros_ec_pwm *channel; + + channel = kzalloc(sizeof(*channel), GFP_KERNEL); + if (!channel) + return -ENOMEM; + + pwm_set_chip_data(pwm, channel); + + return 0; +} + +static void cros_ec_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct cros_ec_pwm *channel = pwm_get_chip_data(pwm); + + kfree(channel); +} + static int cros_ec_pwm_set_duty(struct cros_ec_device *ec, u8 index, u16 duty) { struct { @@ -96,7 +124,9 @@ static int cros_ec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, const struct pwm_state *state) { struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip); - int duty_cycle; + struct cros_ec_pwm *channel = pwm_get_chip_data(pwm); + u16 duty_cycle; + int ret; /* The EC won't let us change the period */ if (state->period != EC_PWM_MAX_DUTY) @@ -108,13 +138,20 @@ static int cros_ec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, */ duty_cycle = state->enabled ? state->duty_cycle : 0; - return cros_ec_pwm_set_duty(ec_pwm->ec, pwm->hwpwm, duty_cycle); + ret = cros_ec_pwm_set_duty(ec_pwm->ec, pwm->hwpwm, duty_cycle); + if (ret < 0) + return ret; + + channel->duty_cycle = state->duty_cycle; + + return 0; } static void cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state) { struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip); + struct cros_ec_pwm *channel = pwm_get_chip_data(pwm); int ret; ret = cros_ec_pwm_get_duty(ec_pwm->ec, pwm->hwpwm); @@ -126,8 +163,19 @@ static void cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, state->enabled = (ret > 0); state->period = EC_PWM_MAX_DUTY; - /* Note that "disabled" and "duty cycle == 0" are treated the same */ - state->duty_cycle = ret; + /* + * Note that "disabled" and "duty cycle == 0" are treated the same. If + * the cached duty cycle is not zero, used the cached duty cycle. This + * ensures that the configured duty cycle is kept across a disable and + * enable operation and avoids potentially confusing consumers. + * + * For the case of the initial hardware readout, channel->duty_cycle + * will be 0 and the actual duty cycle read from the EC is used. + */ + if (ret == 0 && channel->duty_cycle > 0) + state->duty_cycle = channel->duty_cycle; + else + state->duty_cycle = ret; } static struct pwm_device * @@ -149,6 +197,8 @@ cros_ec_pwm_xlate(struct pwm_chip *pc, const struct of_phandle_args *args) } static const struct pwm_ops cros_ec_pwm_ops = { + .request = cros_ec_pwm_request, + .free = cros_ec_pwm_free, .get_state = cros_ec_pwm_get_state, .apply = cros_ec_pwm_apply, .owner = THIS_MODULE, From patchwork Mon Oct 21 10:57:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 1180473 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=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="koSVawHw"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46xYWc64yQz9sNw for ; Mon, 21 Oct 2019 21:57:48 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727620AbfJUK5s (ORCPT ); Mon, 21 Oct 2019 06:57:48 -0400 Received: from mail-wm1-f67.google.com ([209.85.128.67]:40311 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727058AbfJUK5s (ORCPT ); Mon, 21 Oct 2019 06:57:48 -0400 Received: by mail-wm1-f67.google.com with SMTP id b24so12278731wmj.5 for ; Mon, 21 Oct 2019 03:57:46 -0700 (PDT) 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 :mime-version:content-transfer-encoding; bh=Vg8liwwdmOnv6h7m3dVBoJHFOX5I8jWU6N1kTGf/T3w=; b=koSVawHwtnfGqdUUa7CYC2BjChIStgAJ3UDsHIfdl85ly4KdMSriB2UWZG4cffCMtd b2AWNZ/vxvOlSD3jcX8XgXjpL4bRgUWZuC6EA+84PNw8bDWVEy57NXo9vfPYzNpmxoe1 Pa08A7Xr/hOKlnqJydsgPqdkZHi8E09QVprLvSxWL52JDRe8Vajh/+Hw3UCRqmRKY91A RRkyrHybusujmDE77AhMv93n1zPjvRXLqhjOseUVA19e1glfyRN+WyYh+b8giy6LzHso Sd3QX3AMtvz9sTpOAelUdR6n7wd2qxGJtKejYxb9VQkA1oTSGaoznbDnZTQHoB1HLQJ4 kUAA== 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:mime-version:content-transfer-encoding; bh=Vg8liwwdmOnv6h7m3dVBoJHFOX5I8jWU6N1kTGf/T3w=; b=ESeIoJ7/j2VRa+NhVQkloRD+15hg4y+WlsjIEkMDCkTeRe2IT5LIFBhu7lPuutiFcx ub4LEP55kfHlt3mkgaWa/iaD/rGjrsFfQzxl32LTNmnSvc80UkziWdorH027gPqnyKxW Bt55VGeuA/96KswCfunjyC2XuKD6XIqZniOOQdm8I6p7vvkMC6xYP82f6Hehl72cEsI3 zZqjeRRC/+JsQOtnPDpzJTnKXjKdEG2G7LmjnfeNJGdA9QeTKYe2sYcFGPNODSq5bbZH wYMAmxRy5UqY7YkKY1y+xrS2IJlQMf/KdQxJ4jFGLopOfm6sc5QRz8r8J8HShUIMpdSQ sjAA== X-Gm-Message-State: APjAAAWXNk13dceQuW041a3QTxtrTxNmI2DtRI7djB6lFBDhGVDUZbXq LfVLDl7D+zUL8QK59l7MvZo= X-Google-Smtp-Source: APXvYqyNwU+JLjYO3ev+IKbJY38YR4DXFOhy18JPEm5FFp0c1jrAR1uzYffzojIm3MTsYVx4p1LG7A== X-Received: by 2002:a1c:6a07:: with SMTP id f7mr6082484wmc.124.1571655465952; Mon, 21 Oct 2019 03:57:45 -0700 (PDT) Received: from localhost (p2E5BE2CE.dip0.t-ipconnect.de. [46.91.226.206]) by smtp.gmail.com with ESMTPSA id u10sm3168062wmj.0.2019.10.21.03.57.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Oct 2019 03:57:44 -0700 (PDT) From: Thierry Reding To: Thierry Reding Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Enric Balletbo i Serra , linux-pwm@vger.kernel.org Subject: [PATCH 3/4] pwm: imx27: Cache duty cycle register value Date: Mon, 21 Oct 2019 12:57:38 +0200 Message-Id: <20191021105739.1357629-3-thierry.reding@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191021105739.1357629-1-thierry.reding@gmail.com> References: <20191021105739.1357629-1-thierry.reding@gmail.com> MIME-Version: 1.0 Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org The hardware register containing the duty cycle value cannot be accessed when the PWM is disabled. This causes the ->get_state() callback to read back a duty cycle value of 0, which can confuse consumer drivers. Signed-off-by: Thierry Reding Tested-by: Michal Vokáč Tested-by: Adam Ford --- drivers/pwm/pwm-imx27.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c index ae11d8577f18..4113d5cd4c62 100644 --- a/drivers/pwm/pwm-imx27.c +++ b/drivers/pwm/pwm-imx27.c @@ -85,6 +85,13 @@ struct pwm_imx27_chip { struct clk *clk_per; void __iomem *mmio_base; struct pwm_chip chip; + + /* + * The driver cannot read the current duty cycle from the hardware if + * the hardware is disabled. Cache the last programmed duty cycle + * value to return in that case. + */ + unsigned int duty_cycle; }; #define to_pwm_imx27_chip(chip) container_of(chip, struct pwm_imx27_chip, chip) @@ -155,14 +162,17 @@ static void pwm_imx27_get_state(struct pwm_chip *chip, tmp = NSEC_PER_SEC * (u64)(period + 2); state->period = DIV_ROUND_CLOSEST_ULL(tmp, pwm_clk); - /* PWMSAR can be read only if PWM is enabled */ - if (state->enabled) { + /* + * PWMSAR can be read only if PWM is enabled. If the PWM is disabled, + * use the cached value. + */ + if (state->enabled) val = readl(imx->mmio_base + MX3_PWMSAR); - tmp = NSEC_PER_SEC * (u64)(val); - state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, pwm_clk); - } else { - state->duty_cycle = 0; - } + else + val = imx->duty_cycle; + + tmp = NSEC_PER_SEC * (u64)(val); + state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, pwm_clk); if (!state->enabled) pwm_imx27_clk_disable_unprepare(chip); @@ -261,6 +271,13 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, writel(duty_cycles, imx->mmio_base + MX3_PWMSAR); writel(period_cycles, imx->mmio_base + MX3_PWMPR); + /* + * Store the duty cycle for future reference in cases where + * the MX3_PWMSAR register can't be read (i.e. when the PWM + * is disabled). + */ + 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) | From patchwork Mon Oct 21 10:57:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 1180474 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=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="G6FjY87E"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 46xYWj11rdz9sNw for ; Mon, 21 Oct 2019 21:57:52 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727649AbfJUK5w (ORCPT ); Mon, 21 Oct 2019 06:57:52 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:33500 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727058AbfJUK5w (ORCPT ); Mon, 21 Oct 2019 06:57:52 -0400 Received: by mail-wr1-f65.google.com with SMTP id s1so4655732wro.0 for ; Mon, 21 Oct 2019 03:57:48 -0700 (PDT) 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 :mime-version:content-transfer-encoding; bh=sfBsCyYhcxQv6g80SbodsZVoivSPnkYbuxxCNV6WrOg=; b=G6FjY87EMDcHJYaT+cftTzu8xRf6/ceFp+MxjvuNIrzkXHPf2xWlQph5TSO1d5K2es 1Jr4kgaPeCKwBowXPcmpzrUxN2t2Y37OjRQwj31ORnHAHi5iAO4Xr0uG1YwqhWEeyeNB xeGmnFb4sPrh7aTWzsfa5M5bsHlh28xIlGuahaTRJf6nQxNYlSqukBo5Wnr+BGF0Q/ST eb9SdB33Z1n9wSTdA7W6S51ZD3NUbJVsLYV/VPmhaDy4QnqYKqwQR19oqRlPyL2AgnIB NBI/sag1rCCGQfI2ZyTFwf5AQoYHSpOWUqFpPUh+hoPNbN7BdeVa+DedFI7jA3npnIwD FEKw== 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:mime-version:content-transfer-encoding; bh=sfBsCyYhcxQv6g80SbodsZVoivSPnkYbuxxCNV6WrOg=; b=HwUWwKVIrLo1wfpDEsafpvdglxBzAfIpncUOfOvkUTOqyxpAZuKthVJeuOgbWZLfRm WBmFgJK7+JJj+nYOrw+B+DwpVrljgaGrMsDEjgBOtWbxZPvK3pu9y3uz0qhVZi2BKUdd mZeb1lHcwT4scJ6HR5yEZGPMdhfFJRU4h0ipKWo4ln3KEX35cmv7HVyvbOFqEdH3XQNz Tal2rGnJccWgxylKjpXFWolbsKeS58hPM0oOWsfrLcyCuxw79IcWp0lCKPwU4qBlLsih hnHeiEr+5ZBbJnEJxd/opQUbiFaUN/RWC2U0fGeOXmcJdJXxf1qQEEpLnB2C4534nLyD iqiA== X-Gm-Message-State: APjAAAWOhZtWqguIAtY6KpdholuKbTSpMhhb2OWokCjRJQOmwvs8WVtL GxdI9Cy6tQ06J0Msr1e3B7A= X-Google-Smtp-Source: APXvYqyecFRNIBJhTWhE0KTzKNVAcDWA3trlRhbM0CWPP0AYBTgTYfZgX/JBqApPb+EmIZTzAwukUQ== X-Received: by 2002:a05:6000:12cd:: with SMTP id l13mr19247292wrx.181.1571655467978; Mon, 21 Oct 2019 03:57:47 -0700 (PDT) Received: from localhost (p2E5BE2CE.dip0.t-ipconnect.de. [46.91.226.206]) by smtp.gmail.com with ESMTPSA id p12sm938044wrt.7.2019.10.21.03.57.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Oct 2019 03:57:47 -0700 (PDT) From: Thierry Reding To: Thierry Reding Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Enric Balletbo i Serra , linux-pwm@vger.kernel.org Subject: [PATCH 4/4] pwm: imx27: Unconditionally write state to hardware Date: Mon, 21 Oct 2019 12:57:39 +0200 Message-Id: <20191021105739.1357629-4-thierry.reding@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191021105739.1357629-1-thierry.reding@gmail.com> References: <20191021105739.1357629-1-thierry.reding@gmail.com> MIME-Version: 1.0 Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org The i.MX driver currently uses a shortcut and doesn't write all of the state through to the hardware when the PWM is disabled. This causes an inconsistent state to be read back by consumers with the result of them malfunctioning. Fix this by always writing the full state through to the hardware registers so that the correct state can always be read back. Signed-off-by: Thierry Reding Tested-by: Michal Vokáč Tested-by: Adam Ford --- drivers/pwm/pwm-imx27.c | 120 ++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 61 deletions(-) diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c index 4113d5cd4c62..59d8b1289808 100644 --- a/drivers/pwm/pwm-imx27.c +++ b/drivers/pwm/pwm-imx27.c @@ -230,70 +230,68 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, pwm_get_state(pwm, &cstate); - if (state->enabled) { - c = clk_get_rate(imx->clk_per); - c *= state->period; - - do_div(c, 1000000000); - period_cycles = c; - - prescale = period_cycles / 0x10000 + 1; - - period_cycles /= prescale; - c = (unsigned long long)period_cycles * state->duty_cycle; - do_div(c, state->period); - duty_cycles = c; - - /* - * according to imx pwm RM, the real period value should be - * PERIOD value in PWMPR plus 2. - */ - if (period_cycles > 2) - period_cycles -= 2; - else - period_cycles = 0; - - /* - * 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. - */ - if (cstate.enabled) { - pwm_imx27_wait_fifo_slot(chip, pwm); - } else { - ret = pwm_imx27_clk_prepare_enable(chip); - if (ret) - return ret; - - pwm_imx27_sw_reset(chip); - } - - writel(duty_cycles, imx->mmio_base + MX3_PWMSAR); - writel(period_cycles, imx->mmio_base + MX3_PWMPR); - - /* - * Store the duty cycle for future reference in cases where - * the MX3_PWMSAR register can't be read (i.e. when the PWM - * is disabled). - */ - 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 | MX3_PWMCR_EN; - - if (state->polarity == PWM_POLARITY_INVERSED) - cr |= FIELD_PREP(MX3_PWMCR_POUTC, - MX3_PWMCR_POUTC_INVERTED); - - writel(cr, imx->mmio_base + MX3_PWMCR); - } else if (cstate.enabled) { - writel(0, imx->mmio_base + MX3_PWMCR); + c = clk_get_rate(imx->clk_per); + c *= state->period; - pwm_imx27_clk_disable_unprepare(chip); + do_div(c, 1000000000); + period_cycles = c; + + prescale = period_cycles / 0x10000 + 1; + + period_cycles /= prescale; + c = (unsigned long long)period_cycles * state->duty_cycle; + do_div(c, state->period); + duty_cycles = c; + + /* + * according to imx pwm RM, the real period value should be PERIOD + * value in PWMPR plus 2. + */ + if (period_cycles > 2) + period_cycles -= 2; + else + period_cycles = 0; + + /* + * 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. + */ + if (cstate.enabled) { + pwm_imx27_wait_fifo_slot(chip, pwm); + } else { + ret = pwm_imx27_clk_prepare_enable(chip); + if (ret) + return ret; + + pwm_imx27_sw_reset(chip); } + writel(duty_cycles, imx->mmio_base + MX3_PWMSAR); + writel(period_cycles, imx->mmio_base + MX3_PWMPR); + + /* + * Store the duty cycle for future reference in cases where the + * MX3_PWMSAR register can't be read (i.e. when the PWM is disabled). + */ + 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; + + if (state->polarity == PWM_POLARITY_INVERSED) + cr |= FIELD_PREP(MX3_PWMCR_POUTC, + MX3_PWMCR_POUTC_INVERTED); + + if (state->enabled) + cr |= MX3_PWMCR_EN; + + writel(cr, imx->mmio_base + MX3_PWMCR); + + if (!state->enabled && cstate.enabled) + pwm_imx27_clk_disable_unprepare(chip); + return 0; }