From patchwork Sun Oct 1 10:40:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Young X-Patchwork-Id: 147072 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:612c:2a8e:b0:403:3b70:6f57 with SMTP id in14csp809779vqb; Sun, 1 Oct 2023 03:58:03 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEK9T5AvLRsP9XD+y0W59vF9sRHVll0ox9bjCXMJC1MK10RogA5Y71sovPE1jpWqIt7Ubc1 X-Received: by 2002:a9d:7a95:0:b0:6b9:b938:3524 with SMTP id l21-20020a9d7a95000000b006b9b9383524mr8803983otn.6.1696157883549; Sun, 01 Oct 2023 03:58:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1696157883; cv=none; d=google.com; s=arc-20160816; b=YOvDCwrbx6OA7z26moT4YnCNiGljOwNIfSGoYuFoECR/VA8TcBTvIpCvNk3q91kTxu 0+lF4Pok0S/vEvL8GOmZbjir/J1wopL34DU+D265ypLrj47cmt6ZGsWJZZEyd0DcRcVs huXmB9FopgnvH9V09RzRvC/HSF6A61xAxU3NrlAOnZVKBWgICbLLmIzCONkKUADv6yvq bbO1Rip+hNdk8axH4P0zlcL7cKMXpkAR/RNDuCeuCycP1lVIm/HQeVPK2Ku5rbpf45nx UruPiOiXUcRdvpdBS8690VMG260sfnpkaD7IyCHLwlMQ4nwJkg641Zar0APYyMud+V59 gu3A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature:dkim-signature; bh=mgkXIICZfcIb/LuWeYI+l8zQDNZrRK3TW27FswoAKTg=; fh=HSNwNvx/xF/RxkyMZEaDg2SBHtqZJrT5/jrO79m6WII=; b=WrUUsWZNiui0QG4NsbDNZETq3QSld5nAASmFd1bqp/IclwdFltqahe8jj4ejsaALFq 84k4F74tkwkTClsK7iEpm1xMB5GfHIB+/KA30T5BhroJGbEkFRJiP+jegUUoqeZ9OnYb DkJ3hONgaxqg36anuoG0eUHbGgNsHWai2PpOM9vrlkBHTCIVBQYvzBFlXgjqx6tetehB JCYBPv01cZklZPEblsHggA/syBJZPxu2xHZe1hohKYzALrbakcRkFsnliHgH6FiO6WaL Z0QZzVdj7SoLpdHxAtLautlgHJBTDnWCxPnoSKzqwwMwXwRJPKSi4Z/bDQ0NB/3Ct2AG Va/g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@mess.org header.s=2020 header.b=fSmlNLxn; dkim=pass header.i=@mess.org header.s=2020 header.b=N7DMIwLE; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=mess.org Received: from snail.vger.email (snail.vger.email. [23.128.96.37]) by mx.google.com with ESMTPS id t12-20020a65554c000000b00578b379922bsi23779657pgr.511.2023.10.01.03.58.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 01 Oct 2023 03:58:03 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) client-ip=23.128.96.37; Authentication-Results: mx.google.com; dkim=pass header.i=@mess.org header.s=2020 header.b=fSmlNLxn; dkim=pass header.i=@mess.org header.s=2020 header.b=N7DMIwLE; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=mess.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by snail.vger.email (Postfix) with ESMTP id CE31E809E718; Sun, 1 Oct 2023 03:41:40 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at snail.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234839AbjJAKlW (ORCPT + 19 others); Sun, 1 Oct 2023 06:41:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41634 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234857AbjJAKlP (ORCPT ); Sun, 1 Oct 2023 06:41:15 -0400 Received: from gofer.mess.org (gofer.mess.org [IPv6:2a02:8011:d000:212::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 77490DA for ; Sun, 1 Oct 2023 03:41:12 -0700 (PDT) Received: by gofer.mess.org (Postfix, from userid 501) id 97BBC1007F8; Sun, 1 Oct 2023 11:41:07 +0100 (BST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=mess.org; s=2020; t=1696156867; bh=QUpPxWxeUoEKvELBUi/IX9COhqNB9pdiwdqfum1gprc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fSmlNLxnPwzFmfM5x1vpKboHQoHITBFTp/Mnkwhd5M1LVaczypyL8sT1EuycLQo1g CxPl9W2ldnzxCIr7bJCPkcCyQGpQDgehwNW2nw6IuJN38mrnoj4TBtdoxyhW989wTr 8Yo9Ma7NmejmUwaWht7xqRfoSyqhjiByvkNGN/xi/qMmCVcUp2ZW9/lMU3GTN7l6Qe 8/CINHXWlpeVvk5KfNvebLWsKfi3dDA8I3GCjro8XLDoUGzo3PQPMUWQkOrR1pHY7P N4QZj6vRcL8bkPH0r6ekdxD2KsqqR5N4HZK84g75Pdjpy4+b3fdvlHVGdCjfX4cvgG qkd0Y2hlbNV9Q== X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 Received: from bigcore.mess.org (unknown [IPv6:2a02:8011:d000:212:ca7f:54ff:fe51:14d6]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by gofer.mess.org (Postfix) with ESMTPSA id 9327F100092; Sun, 1 Oct 2023 11:41:00 +0100 (BST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=mess.org; s=2020; t=1696156860; bh=QUpPxWxeUoEKvELBUi/IX9COhqNB9pdiwdqfum1gprc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=N7DMIwLEPGNJ4j3Mlm37lK0bu/RIEdqBcVsT5mlv+uBvddxIYkMuMdiYJeL5iQ1Wx TC5O07MYh01KnJ8C00ZAuEiW3TbnV86urCSxyURHUi8H9weBMiJfGVmvMxUZ3NjEOZ k0cjm6PuwbBnW3J3EUrc6qtPFOYuGCaJmSV5UYdMQO4YKZQJjDobZsKBt6SeH6LdgF U4VkZYf1Z4pOUR1ciHtzBlXtiQrHxWJfPgcDwc9J6LjA2EsTVjOcsZciG5nNk1cca6 fzPKfpm8rNoWN5z4Fj8hX6iAEH3RQX7I31wj0SOGUK8VLMpW8ncg47bmaMG+diL0RU Q4AfqATfS0ctg== From: Sean Young To: Thierry Reding , =?utf-8?q?Uwe_Kleine-K=C3=B6n?= =?utf-8?q?ig?= , Shawn Guo , Sascha Hauer , Pengutronix Kernel Team , Fabio Estevam , NXP Linux Team , Vladimir Zapolskiy , Conor Dooley , Daire McNamara , Palmer Dabbelt , Paul Walmsley , Fabrice Gasnier , Maxime Coquelin , Alexandre Torgue Cc: Sean Young , Ivaylo Dimitrov , linux-pwm@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-riscv@lists.infradead.org, linux-stm32@st-md-mailman.stormreply.com Subject: [PATCH 1/2] pwm: make it possible to apply pwm changes in atomic context Date: Sun, 1 Oct 2023 11:40:29 +0100 Message-ID: <1bd5241d584ceb4d6b731c4dc3203fb9686ee1d1.1696156485.git.sean@mess.org> X-Mailer: git-send-email 2.42.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (snail.vger.email [0.0.0.0]); Sun, 01 Oct 2023 03:41:40 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1778550449024269654 X-GMAIL-MSGID: 1778550449024269654 Some drivers require sleeping, for example if the pwm device is connected over i2c. The pwm-ir-tx requires precise timing, and sleeping causes havoc with the generated IR signal when sleeping occurs. This patch makes it possible to use pwm when the driver does not sleep, by introducing the pwm_can_sleep() function. Signed-off-by: Sean Young Cc: Ivaylo Dimitrov --- drivers/pwm/core.c | 2 +- drivers/pwm/pwm-fsl-ftm.c | 1 + drivers/pwm/pwm-imx-tpm.c | 1 + drivers/pwm/pwm-iqs620a.c | 1 + drivers/pwm/pwm-lpc18xx-sct.c | 1 + drivers/pwm/pwm-microchip-core.c | 1 + drivers/pwm/pwm-omap-dmtimer.c | 1 + drivers/pwm/pwm-pca9685.c | 1 + drivers/pwm/pwm-renesas-tpu.c | 1 - drivers/pwm/pwm-rz-mtu3.c | 1 + drivers/pwm/pwm-sifive.c | 1 + drivers/pwm/pwm-sti.c | 1 + drivers/pwm/pwm-stm32.c | 1 + drivers/pwm/pwm-twl-led.c | 1 + drivers/pwm/pwm-twl.c | 1 + include/linux/pwm.h | 27 +++++++++++++++++++++++---- 16 files changed, 37 insertions(+), 6 deletions(-) diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index dc66e3405bf5..d9679ae5b2be 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -505,7 +505,7 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state) * is a bad idea. So make it explicit that calling this function might * sleep. */ - might_sleep(); + might_sleep_if(pwm_can_sleep(pwm)); if (!pwm || !state || !state->period || state->duty_cycle > state->period) diff --git a/drivers/pwm/pwm-fsl-ftm.c b/drivers/pwm/pwm-fsl-ftm.c index b7c6045c5d08..b8b9392844e9 100644 --- a/drivers/pwm/pwm-fsl-ftm.c +++ b/drivers/pwm/pwm-fsl-ftm.c @@ -405,6 +405,7 @@ static int fsl_pwm_probe(struct platform_device *pdev) fpc->soc = of_device_get_match_data(&pdev->dev); fpc->chip.dev = &pdev->dev; + fpc->chip.can_sleep = true; base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) diff --git a/drivers/pwm/pwm-imx-tpm.c b/drivers/pwm/pwm-imx-tpm.c index 98ab65c89685..6fd579089240 100644 --- a/drivers/pwm/pwm-imx-tpm.c +++ b/drivers/pwm/pwm-imx-tpm.c @@ -365,6 +365,7 @@ static int pwm_imx_tpm_probe(struct platform_device *pdev) tpm->chip.dev = &pdev->dev; tpm->chip.ops = &imx_tpm_pwm_ops; + tpm->chip.can_sleep = true; /* get number of channels */ val = readl(tpm->base + PWM_IMX_TPM_PARAM); diff --git a/drivers/pwm/pwm-iqs620a.c b/drivers/pwm/pwm-iqs620a.c index 47b3141135f3..ebce9e06b32e 100644 --- a/drivers/pwm/pwm-iqs620a.c +++ b/drivers/pwm/pwm-iqs620a.c @@ -209,6 +209,7 @@ static int iqs620_pwm_probe(struct platform_device *pdev) iqs620_pwm->chip.dev = &pdev->dev; iqs620_pwm->chip.ops = &iqs620_pwm_ops; iqs620_pwm->chip.npwm = 1; + iqs620_pwm->chip.can_sleep = true; mutex_init(&iqs620_pwm->lock); diff --git a/drivers/pwm/pwm-lpc18xx-sct.c b/drivers/pwm/pwm-lpc18xx-sct.c index 7a19a840bca5..e26fc18b5304 100644 --- a/drivers/pwm/pwm-lpc18xx-sct.c +++ b/drivers/pwm/pwm-lpc18xx-sct.c @@ -395,6 +395,7 @@ static int lpc18xx_pwm_probe(struct platform_device *pdev) lpc18xx_pwm->chip.dev = &pdev->dev; lpc18xx_pwm->chip.ops = &lpc18xx_pwm_ops; lpc18xx_pwm->chip.npwm = LPC18XX_NUM_PWMS; + lpc18xx_pwm->chip.can_sleep = true; /* SCT counter must be in unify (32 bit) mode */ lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CONFIG, diff --git a/drivers/pwm/pwm-microchip-core.c b/drivers/pwm/pwm-microchip-core.c index e7525c98105e..503b5b427d69 100644 --- a/drivers/pwm/pwm-microchip-core.c +++ b/drivers/pwm/pwm-microchip-core.c @@ -474,6 +474,7 @@ static int mchp_core_pwm_probe(struct platform_device *pdev) mchp_core_pwm->chip.dev = &pdev->dev; mchp_core_pwm->chip.ops = &mchp_core_pwm_ops; mchp_core_pwm->chip.npwm = 16; + mchp_core_pwm->chip.can_sleep = true; mchp_core_pwm->channel_enabled = readb_relaxed(mchp_core_pwm->base + MCHPCOREPWM_EN(0)); mchp_core_pwm->channel_enabled |= diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c index 4889fbd8a431..438abbb80daf 100644 --- a/drivers/pwm/pwm-omap-dmtimer.c +++ b/drivers/pwm/pwm-omap-dmtimer.c @@ -404,6 +404,7 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev) omap->chip.dev = &pdev->dev; omap->chip.ops = &pwm_omap_dmtimer_ops; omap->chip.npwm = 1; + omap->chip.can_sleep = true; mutex_init(&omap->mutex); diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c index 3038a68412a7..a47e21977e49 100644 --- a/drivers/pwm/pwm-pca9685.c +++ b/drivers/pwm/pwm-pca9685.c @@ -571,6 +571,7 @@ static int pca9685_pwm_probe(struct i2c_client *client) pca->chip.npwm = PCA9685_MAXCHAN + 1; pca->chip.dev = &client->dev; + pca->chip.can_sleep = true; ret = pwmchip_add(&pca->chip); if (ret < 0) diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c index d7311614c846..96797a33d8c6 100644 --- a/drivers/pwm/pwm-renesas-tpu.c +++ b/drivers/pwm/pwm-renesas-tpu.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/pwm/pwm-rz-mtu3.c b/drivers/pwm/pwm-rz-mtu3.c index a56cecb0e46e..6d874a2a8785 100644 --- a/drivers/pwm/pwm-rz-mtu3.c +++ b/drivers/pwm/pwm-rz-mtu3.c @@ -516,6 +516,7 @@ static int rz_mtu3_pwm_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); rz_mtu3_pwm->chip.dev = &pdev->dev; + rz_mtu3_pwm->chip.can_sleep = true; ret = devm_add_action_or_reset(&pdev->dev, rz_mtu3_pwm_pm_disable, rz_mtu3_pwm); if (ret < 0) diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c index eabddb7c7820..5677ed6eb4d5 100644 --- a/drivers/pwm/pwm-sifive.c +++ b/drivers/pwm/pwm-sifive.c @@ -240,6 +240,7 @@ static int pwm_sifive_probe(struct platform_device *pdev) chip->dev = dev; chip->ops = &pwm_sifive_ops; chip->npwm = 4; + chip->can_sleep = true; ddata->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(ddata->regs)) diff --git a/drivers/pwm/pwm-sti.c b/drivers/pwm/pwm-sti.c index b1d1373648a3..de9fbd570104 100644 --- a/drivers/pwm/pwm-sti.c +++ b/drivers/pwm/pwm-sti.c @@ -643,6 +643,7 @@ static int sti_pwm_probe(struct platform_device *pdev) pc->chip.dev = dev; pc->chip.ops = &sti_pwm_ops; pc->chip.npwm = pc->cdata->pwm_num_devs; + pc->chip.can_sleep = true; ret = pwmchip_add(&pc->chip); if (ret < 0) { diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c index 3d6be7749e23..cd408158e55b 100644 --- a/drivers/pwm/pwm-stm32.c +++ b/drivers/pwm/pwm-stm32.c @@ -636,6 +636,7 @@ static int stm32_pwm_probe(struct platform_device *pdev) priv->chip.dev = dev; priv->chip.ops = &stm32pwm_ops; priv->chip.npwm = stm32_pwm_detect_channels(priv); + priv->chip.can_sleep = true; ret = devm_pwmchip_add(dev, &priv->chip); if (ret < 0) diff --git a/drivers/pwm/pwm-twl-led.c b/drivers/pwm/pwm-twl-led.c index 8fb84b441853..9e71429ecaed 100644 --- a/drivers/pwm/pwm-twl-led.c +++ b/drivers/pwm/pwm-twl-led.c @@ -362,6 +362,7 @@ static int twl_pwmled_probe(struct platform_device *pdev) } twl->chip.dev = &pdev->dev; + twl->chip.can_sleep = true; mutex_init(&twl->mutex); diff --git a/drivers/pwm/pwm-twl.c b/drivers/pwm/pwm-twl.c index 86567add79db..bd08014fec44 100644 --- a/drivers/pwm/pwm-twl.c +++ b/drivers/pwm/pwm-twl.c @@ -356,6 +356,7 @@ static int twl_pwm_probe(struct platform_device *pdev) twl->chip.dev = &pdev->dev; twl->chip.npwm = 2; + twl->chip.can_sleep = true; mutex_init(&twl->mutex); diff --git a/include/linux/pwm.h b/include/linux/pwm.h index d2f9f690a9c1..c94894ffa4c4 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -287,6 +287,7 @@ struct pwm_ops { * @ops: callbacks for this PWM controller * @base: number of first PWM controlled by this chip * @npwm: number of PWMs controlled by this chip + * @can_sleep: can the driver sleep in pwm_apply_state * @of_xlate: request a PWM device given a device tree PWM specifier * @of_pwm_n_cells: number of cells expected in the device tree PWM specifier * @list: list node for internal use @@ -297,6 +298,7 @@ struct pwm_chip { const struct pwm_ops *ops; int base; unsigned int npwm; + bool can_sleep; struct pwm_device * (*of_xlate)(struct pwm_chip *chip, const struct of_phandle_args *args); @@ -380,6 +382,18 @@ static inline void pwm_disable(struct pwm_device *pwm) pwm_apply_state(pwm, &state); } +/** + * pwm_can_sleep() - can a pwm driver sleep in pwm_apply_state() + * @pwm: PWM device + * + * Returns: true if the driver may sleep, false if pwm_apply_state() + * can be called from atomic context. + */ +static inline bool pwm_can_sleep(struct pwm_device *pwm) +{ + return pwm->chip->can_sleep; +} + /* PWM provider APIs */ int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result, unsigned long timeout); @@ -411,7 +425,7 @@ struct pwm_device *devm_fwnode_pwm_get(struct device *dev, static inline int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state) { - might_sleep(); + might_sleep_if(pwm_can_sleep(pwm)); return -ENOTSUPP; } @@ -423,19 +437,24 @@ static inline int pwm_adjust_config(struct pwm_device *pwm) static inline int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) { - might_sleep(); + might_sleep_if(pwm_can_sleep(pwm)); return -EINVAL; } static inline int pwm_enable(struct pwm_device *pwm) { - might_sleep(); + might_sleep_if(pwm_can_sleep(pwm)); return -EINVAL; } static inline void pwm_disable(struct pwm_device *pwm) { - might_sleep(); + might_sleep_if(pwm_can_sleep(pwm)); +} + +static inline bool pwm_can_sleep(struct pwm_device *pwm) +{ + return true; } static inline int pwm_capture(struct pwm_device *pwm, From patchwork Sun Oct 1 10:40:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Young X-Patchwork-Id: 147125 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:612c:2a8e:b0:403:3b70:6f57 with SMTP id in14csp934434vqb; Sun, 1 Oct 2023 08:42:49 -0700 (PDT) X-Google-Smtp-Source: AGHT+IH6cYaALRttYIlr92vv0DGtMxcAs9aYJDScpAtCccAw5VMAnrKqycewzQ43NX40LOKPNNxx X-Received: by 2002:a17:903:2441:b0:1bb:994c:bc43 with SMTP id l1-20020a170903244100b001bb994cbc43mr9366472pls.18.1696174968808; Sun, 01 Oct 2023 08:42:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1696174968; cv=none; d=google.com; s=arc-20160816; b=JiMku1zog5oewatTjZFsuHnQm2YG7dhaZQZEBsZqe8GZpN6fJ/gAA5p63z7itJZeub JEluTsKcZBM8oR236sOfySfmNeklZg71tQDdgYpWhDeOeVqPqQyhFcu6/0UurDTJyADg OgYMjaVc+Dw1FH+/4Z16bGCcp7lyPlFMePxzfySAxxu3zots0xxv8K5okuXBPNPJbL0B Sez+HV1sVhRtTwRc2za3TOuwIxG3mI1tZh5/crCZKAAqC2cMWRRdnvU4JliRiBuCkA6y KtEvCMWs59O0f+Hc68NmOtoyuUX1lwHJKH2D/qzU7WYwJLmeSuwBtYvuZphPqVpfojL5 yf8w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature:dkim-signature; bh=l2BRIEZS4YDtxqPPpie44qcRwvFFJQR/SridKcHnvwE=; fh=fA02y12LmITb9T3alKvL6sLyYbo8lB87lK+ZUh5dssU=; b=E8q7sUvgVhyfgZd6Y7d1pyaXMcV+QrQq8GJVkfYmZxMedCm65hPZiZJ4y9WNkm3X+1 zj0wRNMCiLSX50ScMum6FpKeHo/aNFvso8GMrYx5Yh0sMFSWzuWcz/R4I3KkUvYbFapU cGHe0ZIiwWEK2rAIGb8Rq9NbW0hlMsndzkWRqhgJKRIwiUvJ4L/keMCxjasHBffS+FG+ OBCi1vtFAVkquUUmCQmRDdCTzMwqiW7l/lf1t17W+oducUxafQO76Gd2A38C/bSSyS29 6C7ueqYRgWqNND7ZM/yndoiWkhIrc1P9/E3RESBy9EEz8fJyJCF3N1oDOIIH1FVPYQlN pw5A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@mess.org header.s=2020 header.b=c9z9EUlg; dkim=pass header.i=@mess.org header.s=2020 header.b=Burzah2r; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=mess.org Received: from snail.vger.email (snail.vger.email. [23.128.96.37]) by mx.google.com with ESMTPS id n8-20020a170902d2c800b001bf1d1d99b0si26913617plc.568.2023.10.01.08.42.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 01 Oct 2023 08:42:48 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) client-ip=23.128.96.37; Authentication-Results: mx.google.com; dkim=pass header.i=@mess.org header.s=2020 header.b=c9z9EUlg; dkim=pass header.i=@mess.org header.s=2020 header.b=Burzah2r; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=mess.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by snail.vger.email (Postfix) with ESMTP id EC2B9805BC95; Sun, 1 Oct 2023 03:41:45 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at snail.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234875AbjJAKlU (ORCPT + 19 others); Sun, 1 Oct 2023 06:41:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41596 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234817AbjJAKlM (ORCPT ); Sun, 1 Oct 2023 06:41:12 -0400 X-Greylist: delayed 152457 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Sun, 01 Oct 2023 03:41:09 PDT Received: from gofer.mess.org (gofer.mess.org [IPv6:2a02:8011:d000:212::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 26960D8; Sun, 1 Oct 2023 03:41:09 -0700 (PDT) Received: by gofer.mess.org (Postfix, from userid 501) id 8C6291007F9; Sun, 1 Oct 2023 11:41:07 +0100 (BST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=mess.org; s=2020; t=1696156867; bh=RSMxdZlA6dvGl+ue7BCTI/DiHrSS0pIbsuFSiBzaOJ4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=c9z9EUlgawEqlaCkIPyJ6mNMWC2WE3QL+yucOEtRFySKnL/fb7NL2zshpKzwoTkmv 44LYsYUlyznZDNPS6tcJCa6WODDu4ksUgG+bgTqodh7zRtgNaDL0ujp4ahdbJGeWsc /yE/wxsgFWrdmO0FLUCdm306F9vcbcM1QlNDpjAfTLqMNzy5aQZPLVL/ynm9SDdROx vB85Mj+LRA/DGUZEtXEnH59yRl47JPWWwFSzFY6+JBcAUeuB52UcBTw75XsBHouC6x BmOVl48nSleG9qMnPkVIgA/WnlNuGKn2nMQP27/B+U0qB6gGZlBl2AUKqp7LSv/VYa RNitSIyNv/rOQ== X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 Received: from bigcore.mess.org (unknown [IPv6:2a02:8011:d000:212:ca7f:54ff:fe51:14d6]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by gofer.mess.org (Postfix) with ESMTPSA id D57F41007F6; Sun, 1 Oct 2023 11:41:00 +0100 (BST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=mess.org; s=2020; t=1696156860; bh=RSMxdZlA6dvGl+ue7BCTI/DiHrSS0pIbsuFSiBzaOJ4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Burzah2rsgdUFBELWQkDEpvEVUZuZ10sJsnvNNbRfakZycGZ1mt3/98/RYa/iw6D4 KU840KaAqRazeBe/+RR/xfltc+SSlg5DrZpoy1IzcnDOIBMozmNiKKpeWLC0MOViLL 5sfS5k1nunMjHzxWo94snpO5hz6l4mI0Tv1k8SJsVyDshiWy3q6Zn7svKI06GYwL+I LrrreBQQAdNKv2Vqv8jvYwdX0rDbpj4QaEyK3nX6Z89UVnZ9qfMZqA5l/5qSAq5piT NTHl62yvdP/bq9G9zOo4q7Sxtj7cUPj3PJ5oJf/iaYkQP7pIpeFd2YPU5slpZY1FMv shX3PYzqFLeDA== From: Sean Young To: Sean Young , Mauro Carvalho Chehab , Thierry Reding , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= Cc: Ivaylo Dimitrov , linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, linux-pwm@vger.kernel.org Subject: [PATCH 2/2] media: pwm-ir-tx: trigger edges from hrtimer interrupt context Date: Sun, 1 Oct 2023 11:40:30 +0100 Message-ID: <7efe4229514001b835fa70d51973cd3306dc0b04.1696156485.git.sean@mess.org> X-Mailer: git-send-email 2.42.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (snail.vger.email [0.0.0.0]); Sun, 01 Oct 2023 03:41:46 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1778568363919899910 X-GMAIL-MSGID: 1778568363919899910 The pwm-ir-tx driver has to turn the pwm signal on and off, and suffers from delays as this is done in process context. Make this work in atomic context. This makes the driver much more precise. Signed-off-by: Sean Young Cc: Ivaylo Dimitrov --- drivers/media/rc/pwm-ir-tx.c | 79 ++++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 16 deletions(-) diff --git a/drivers/media/rc/pwm-ir-tx.c b/drivers/media/rc/pwm-ir-tx.c index c5f37c03af9c..557725a07a67 100644 --- a/drivers/media/rc/pwm-ir-tx.c +++ b/drivers/media/rc/pwm-ir-tx.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #define DRIVER_NAME "pwm-ir-tx" @@ -17,8 +19,13 @@ struct pwm_ir { struct pwm_device *pwm; - unsigned int carrier; - unsigned int duty_cycle; + struct hrtimer timer; + struct completion completion; + uint carrier; + uint duty_cycle; + uint *txbuf; + uint txbuf_len; + uint txbuf_index; }; static const struct of_device_id pwm_ir_of_match[] = { @@ -55,33 +62,65 @@ static int pwm_ir_tx(struct rc_dev *dev, unsigned int *txbuf, struct pwm_ir *pwm_ir = dev->priv; struct pwm_device *pwm = pwm_ir->pwm; struct pwm_state state; - int i; - ktime_t edge; - long delta; + + reinit_completion(&pwm_ir->completion); pwm_init_state(pwm, &state); state.period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, pwm_ir->carrier); pwm_set_relative_duty_cycle(&state, pwm_ir->duty_cycle, 100); + state.enabled = false; - edge = ktime_get(); + pwm_ir->txbuf = txbuf; + pwm_ir->txbuf_len = count; + pwm_ir->txbuf_index = 0; - for (i = 0; i < count; i++) { - state.enabled = !(i % 2); - pwm_apply_state(pwm, &state); + pwm_apply_state(pwm, &state); - edge = ktime_add_us(edge, txbuf[i]); - delta = ktime_us_delta(edge, ktime_get()); - if (delta > 0) - usleep_range(delta, delta + 10); - } + hrtimer_start(&pwm_ir->timer, 1000, HRTIMER_MODE_REL); - state.enabled = false; - pwm_apply_state(pwm, &state); + wait_for_completion(&pwm_ir->completion); return count; } +static enum hrtimer_restart pwm_ir_timer(struct hrtimer *timer) +{ + struct pwm_ir *pwm_ir = container_of(timer, struct pwm_ir, timer); + ktime_t now; + + /* + * If we happen to hit an odd latency spike, loop through the + * pulses until we catch up. + */ + do { + u64 ns; + + if (pwm_ir->txbuf_index >= pwm_ir->txbuf_len) { + /* Stop TX here */ + pwm_disable(pwm_ir->pwm); + + complete(&pwm_ir->completion); + + return HRTIMER_NORESTART; + } + + if (pwm_ir->txbuf_index % 2) + pwm_disable(pwm_ir->pwm); + else + pwm_enable(pwm_ir->pwm); + + ns = US_TO_NS(pwm_ir->txbuf[pwm_ir->txbuf_index]); + hrtimer_add_expires_ns(timer, ns); + + pwm_ir->txbuf_index++; + + now = timer->base->get_time(); + } while (hrtimer_get_expires_tv64(timer) < now); + + return HRTIMER_RESTART; +} + static int pwm_ir_probe(struct platform_device *pdev) { struct pwm_ir *pwm_ir; @@ -96,8 +135,16 @@ static int pwm_ir_probe(struct platform_device *pdev) if (IS_ERR(pwm_ir->pwm)) return PTR_ERR(pwm_ir->pwm); + if (pwm_can_sleep(pwm_ir->pwm)) { + dev_err(&pdev->dev, "unsupported pwm device: driver can sleep\n"); + return -ENODEV; + } + pwm_ir->carrier = 38000; pwm_ir->duty_cycle = 50; + init_completion(&pwm_ir->completion); + hrtimer_init(&pwm_ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + pwm_ir->timer.function = pwm_ir_timer; rcdev = devm_rc_allocate_device(&pdev->dev, RC_DRIVER_IR_RAW_TX); if (!rcdev)