From 8744dcd4fc7800de2eb9369410470bb2930d4c14 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Mon, 24 Feb 2025 18:06:57 +0100 Subject: counter: stm32-lptimer-cnt: fix error handling when enabling In case the stm32_lptim_set_enable_state() fails to update CMP and ARR, a timeout error is raised, by regmap_read_poll_timeout. It may happen, when the lptimer runs on a slow clock, and the clock is gated only few times during the polling. Badly, when this happen, STM32_LPTIM_ENABLE in CR register has been set. So the 'enable' state in sysfs wrongly lies on the counter being correctly enabled, due to CR is read as one in stm32_lptim_is_enabled(). To fix both issues: - enable the clock before writing CMP, ARR and polling ISR bits. It will avoid the possible timeout error. - clear the ENABLE bit in CR and disable the clock in the error path. Fixes: d8958824cf07 ("iio: counter: Add support for STM32 LPTimer") Signed-off-by: Fabrice Gasnier Link: https://lore.kernel.org/r/20250224170657.3368236-1-fabrice.gasnier@foss.st.com Signed-off-by: William Breathitt Gray --- drivers/counter/stm32-lptimer-cnt.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/counter/stm32-lptimer-cnt.c b/drivers/counter/stm32-lptimer-cnt.c index cf73f65baf60..b249c8647639 100644 --- a/drivers/counter/stm32-lptimer-cnt.c +++ b/drivers/counter/stm32-lptimer-cnt.c @@ -58,37 +58,43 @@ static int stm32_lptim_set_enable_state(struct stm32_lptim_cnt *priv, return 0; } + ret = clk_enable(priv->clk); + if (ret) + goto disable_cnt; + /* LP timer must be enabled before writing CMP & ARR */ ret = regmap_write(priv->regmap, STM32_LPTIM_ARR, priv->ceiling); if (ret) - return ret; + goto disable_clk; ret = regmap_write(priv->regmap, STM32_LPTIM_CMP, 0); if (ret) - return ret; + goto disable_clk; /* ensure CMP & ARR registers are properly written */ ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val, (val & STM32_LPTIM_CMPOK_ARROK) == STM32_LPTIM_CMPOK_ARROK, 100, 1000); if (ret) - return ret; + goto disable_clk; ret = regmap_write(priv->regmap, STM32_LPTIM_ICR, STM32_LPTIM_CMPOKCF_ARROKCF); if (ret) - return ret; + goto disable_clk; - ret = clk_enable(priv->clk); - if (ret) { - regmap_write(priv->regmap, STM32_LPTIM_CR, 0); - return ret; - } priv->enabled = true; /* Start LP timer in continuous mode */ return regmap_update_bits(priv->regmap, STM32_LPTIM_CR, STM32_LPTIM_CNTSTRT, STM32_LPTIM_CNTSTRT); + +disable_clk: + clk_disable(priv->clk); +disable_cnt: + regmap_write(priv->regmap, STM32_LPTIM_CR, 0); + + return ret; } static int stm32_lptim_setup(struct stm32_lptim_cnt *priv, int enable) -- cgit v1.2.3 From c0c9c73434666dc99ee156b25e7e722150bee001 Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 5 Mar 2025 19:01:19 +0900 Subject: counter: microchip-tcb-capture: Fix undefined counter channel state on probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hardware initialize of the timer counter channel does not occur on probe thus leaving the Count in an undefined state until the first function_write() callback is executed. Fix this by performing the proper hardware initialization during probe. Fixes: 106b104137fd ("counter: Add microchip TCB capture counter") Reported-by: Csókás Bence Closes: https://lore.kernel.org/all/bfa70e78-3cc3-4295-820b-3925c26135cb@prolan.hu/ Link: https://lore.kernel.org/r/20250305-preset-capture-mode-microchip-tcb-capture-v1-1-632c95c6421e@kernel.org Signed-off-by: William Breathitt Gray --- drivers/counter/microchip-tcb-capture.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c index 2f096a5b973d..c391ac38b990 100644 --- a/drivers/counter/microchip-tcb-capture.c +++ b/drivers/counter/microchip-tcb-capture.c @@ -368,6 +368,25 @@ static int mchp_tc_probe(struct platform_device *pdev) channel); } + /* Disable Quadrature Decoder and position measure */ + ret = regmap_update_bits(regmap, ATMEL_TC_BMR, ATMEL_TC_QDEN | ATMEL_TC_POSEN, 0); + if (ret) + return ret; + + /* Setup the period capture mode */ + ret = regmap_update_bits(regmap, ATMEL_TC_REG(priv->channel[0], CMR), + ATMEL_TC_WAVE | ATMEL_TC_ABETRG | ATMEL_TC_CMR_MASK | + ATMEL_TC_TCCLKS, + ATMEL_TC_CMR_MASK); + if (ret) + return ret; + + /* Enable clock and trigger counter */ + ret = regmap_write(regmap, ATMEL_TC_REG(priv->channel[0], CCR), + ATMEL_TC_CLKEN | ATMEL_TC_SWTRG); + if (ret) + return ret; + priv->tc_cfg = tcb_config; priv->regmap = regmap; counter->name = dev_name(&pdev->dev); -- cgit v1.2.3