From patchwork Wed Sep 15 15:58:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miquel Raynal X-Patchwork-Id: 512620 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 425D1C43217 for ; Wed, 15 Sep 2021 16:00:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 276BB61371 for ; Wed, 15 Sep 2021 16:00:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238465AbhIOQCC (ORCPT ); Wed, 15 Sep 2021 12:02:02 -0400 Received: from relay8-d.mail.gandi.net ([217.70.183.201]:52801 "EHLO relay8-d.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238519AbhIOQBq (ORCPT ); Wed, 15 Sep 2021 12:01:46 -0400 Received: (Authenticated sender: miquel.raynal@bootlin.com) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id BB1C91BF204; Wed, 15 Sep 2021 16:00:24 +0000 (UTC) From: Miquel Raynal To: Jonathan Cameron , Lars-Peter Clausen , Peter Meerwald-Stadler , Rob Herring , Dmitry Torokhov , Lee Jones , bcousson@baylibre.com, Tony Lindgren Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-omap@vger.kernel.org, Thomas Petazzoni , Vignesh Raghavendra , Lokesh Vutla , Tero Kristo , Ryan Barnett , Grygorii Strashko , Jason Reeder , Miquel Raynal , Jonathan Cameron Subject: [PATCH v3 37/47] iio: adc: ti_am335x_adc: Wait the idle state to avoid stalls Date: Wed, 15 Sep 2021 17:58:58 +0200 Message-Id: <20210915155908.476767-38-miquel.raynal@bootlin.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210915155908.476767-1-miquel.raynal@bootlin.com> References: <20210915155908.476767-1-miquel.raynal@bootlin.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org At least on a am4372, a simple: $ cat /sys/bus/iio/devices/iio\:deviceX/in_voltage*_raw can stall forever. It seems that it comes from the fact that the internal state machine does not have enough time to return to its idle state in this situation before receiving another request, leading to an internal stall. Add a tiadc_wait_idle() helper to ensure no new conversion is requested while the FSM is still busy. Signed-off-by: Miquel Raynal Acked-by: Jonathan Cameron --- drivers/iio/adc/ti_am335x_adc.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 1cc2efbb2875..0a4d66a541ed 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -102,6 +103,15 @@ static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan) return 1 << adc_dev->channel_step[chan]; } +static int tiadc_wait_idle(struct tiadc_device *adc_dev) +{ + u32 val; + + return readl_poll_timeout(adc_dev->mfd_tscadc->tscadc_base + REG_ADCFSM, + val, !(val & SEQ_STATUS), 10, + IDLE_TIMEOUT * 1000 * adc_dev->channels); +} + static void tiadc_step_config(struct iio_dev *indio_dev) { struct tiadc_device *adc_dev = iio_priv(indio_dev); @@ -295,6 +305,11 @@ static int tiadc_buffer_preenable(struct iio_dev *indio_dev) { struct tiadc_device *adc_dev = iio_priv(indio_dev); int i, fifo1count; + int ret; + + ret = tiadc_wait_idle(adc_dev); + if (ret) + return ret; tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES | IRQENB_FIFO1OVRRUN | @@ -446,12 +461,12 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct tiadc_device *adc_dev = iio_priv(indio_dev); - int ret = IIO_VAL_INT; int i, map_val; unsigned int fifo1count, read, stepid; bool found = false; u32 step_en; unsigned long timeout; + int ret; if (iio_buffer_enabled(indio_dev)) return -EBUSY; @@ -461,6 +476,11 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, return -EINVAL; mutex_lock(&adc_dev->fifo1_lock); + + ret = tiadc_wait_idle(adc_dev); + if (ret) + goto err_unlock; + fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); while (fifo1count--) tiadc_readl(adc_dev, REG_FIFO1); @@ -508,7 +528,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, err_unlock: mutex_unlock(&adc_dev->fifo1_lock); - return ret; + return ret ? ret : IIO_VAL_INT; } static const struct iio_info tiadc_info = {