From c437190ceaaa68caa303e1fd8ab3654be580b1c4 Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Sat, 23 Nov 2024 22:01:49 +0000 Subject: iio: trigger: stm32-timer-trigger: Add check for clk_enable() Add check for the return value of clk_enable() in order to catch the potential exception. Reviewed-by: David Lechner Signed-off-by: Jiasheng Jiang Link: https://patch.msgid.link/20241123220149.30655-1-jiashengjiangcool@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/trigger/stm32-timer-trigger.c | 48 +++++++++++++++++++------------ 1 file changed, 29 insertions(+), 19 deletions(-) (limited to 'drivers/iio/trigger/stm32-timer-trigger.c') diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c index bb60b2d7b2ec..bd58e60f586c 100644 --- a/drivers/iio/trigger/stm32-timer-trigger.c +++ b/drivers/iio/trigger/stm32-timer-trigger.c @@ -119,7 +119,7 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv, unsigned int frequency) { unsigned long long prd, div; - int prescaler = 0; + int prescaler = 0, ret; u32 ccer; /* Period and prescaler values depends of clock rate */ @@ -150,10 +150,12 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv, if (ccer & TIM_CCER_CCXE) return -EBUSY; - mutex_lock(&priv->lock); + guard(mutex)(&priv->lock); if (!priv->enabled) { priv->enabled = true; - clk_enable(priv->clk); + ret = clk_enable(priv->clk); + if (ret) + return ret; } regmap_write(priv->regmap, TIM_PSC, prescaler); @@ -173,7 +175,6 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv, /* Enable controller */ regmap_set_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN); - mutex_unlock(&priv->lock); return 0; } @@ -307,7 +308,7 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev, struct stm32_timer_trigger *priv = dev_get_drvdata(dev); struct iio_trigger *trig = to_iio_trigger(dev); u32 mask, shift, master_mode_max; - int i; + int i, ret; if (stm32_timer_is_trgo2_name(trig->name)) { mask = TIM_CR2_MMS2; @@ -322,15 +323,16 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev, for (i = 0; i <= master_mode_max; i++) { if (!strncmp(master_mode_table[i], buf, strlen(master_mode_table[i]))) { - mutex_lock(&priv->lock); + guard(mutex)(&priv->lock); if (!priv->enabled) { /* Clock should be enabled first */ priv->enabled = true; - clk_enable(priv->clk); + ret = clk_enable(priv->clk); + if (ret) + return ret; } regmap_update_bits(priv->regmap, TIM_CR2, mask, i << shift); - mutex_unlock(&priv->lock); return len; } } @@ -482,6 +484,7 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev, int val, int val2, long mask) { struct stm32_timer_trigger *priv = iio_priv(indio_dev); + int ret; switch (mask) { case IIO_CHAN_INFO_RAW: @@ -491,12 +494,14 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev, /* fixed scale */ return -EINVAL; - case IIO_CHAN_INFO_ENABLE: - mutex_lock(&priv->lock); + case IIO_CHAN_INFO_ENABLE: { + guard(mutex)(&priv->lock); if (val) { if (!priv->enabled) { priv->enabled = true; - clk_enable(priv->clk); + ret = clk_enable(priv->clk); + if (ret) + return ret; } regmap_set_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN); } else { @@ -506,11 +511,12 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev, clk_disable(priv->clk); } } - mutex_unlock(&priv->lock); + return 0; } - - return -EINVAL; + default: + return -EINVAL; + } } static int stm32_counter_validate_trigger(struct iio_dev *indio_dev, @@ -602,6 +608,7 @@ static int stm32_set_enable_mode(struct iio_dev *indio_dev, { struct stm32_timer_trigger *priv = iio_priv(indio_dev); int sms = stm32_enable_mode2sms(mode); + int ret; if (sms < 0) return sms; @@ -609,12 +616,15 @@ static int stm32_set_enable_mode(struct iio_dev *indio_dev, * Triggered mode sets CEN bit automatically by hardware. So, first * enable counter clock, so it can use it. Keeps it in sync with CEN. */ - mutex_lock(&priv->lock); - if (sms == 6 && !priv->enabled) { - clk_enable(priv->clk); - priv->enabled = true; + scoped_guard(mutex, &priv->lock) { + if (sms == 6 && !priv->enabled) { + ret = clk_enable(priv->clk); + if (ret) + return ret; + + priv->enabled = true; + } } - mutex_unlock(&priv->lock); regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, sms); -- cgit v1.2.3 From e2f9d754fc5b5dcb53a0df627f386b63f8ba2d68 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Fri, 20 Dec 2024 10:59:21 +0100 Subject: iio: trigger: stm32-timer: add support for stm32mp25 Add support for STM32MP25 SoC. Use newly introduced compatible to handle this new HW variant. Add TIM20 trigger definitions that can be used by the stm32 analog-to-digital converter. Use compatible data to identify it. As the counter framework is now superseding the deprecated IIO counter interface (IIO_COUNT), don't support it. Only register IIO trigger devices for ADC usage. So, make the valids_table a cfg option. Signed-off-by: Fabrice Gasnier Link: https://patch.msgid.link/20241220095927.1122782-4-fabrice.gasnier@foss.st.com Signed-off-by: Jonathan Cameron --- drivers/iio/trigger/stm32-timer-trigger.c | 21 +++++++++++++++++++-- include/linux/iio/timer/stm32-timer-trigger.h | 6 ++++++ 2 files changed, 25 insertions(+), 2 deletions(-) (limited to 'drivers/iio/trigger/stm32-timer-trigger.c') diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c index bd58e60f586c..e41cb741253b 100644 --- a/drivers/iio/trigger/stm32-timer-trigger.c +++ b/drivers/iio/trigger/stm32-timer-trigger.c @@ -38,6 +38,9 @@ static const void *triggers_table[][MAX_TRIGGERS] = { { TIM15_TRGO,}, { TIM16_OC1,}, { TIM17_OC1,}, + { }, /* timer 18 */ + { }, /* timer 19 */ + { TIM20_TRGO, TIM20_TRGO2, TIM20_OC1, TIM20_OC2, TIM20_OC3, }, }; /* List the triggers accepted by each timer */ @@ -791,7 +794,7 @@ static int stm32_timer_trigger_probe(struct platform_device *pdev) return -EINVAL; /* Create an IIO device only if we have triggers to be validated */ - if (*cfg->valids_table[index]) + if (cfg->valids_table && *cfg->valids_table[index]) priv = stm32_setup_counter_device(dev); else priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -804,7 +807,8 @@ static int stm32_timer_trigger_probe(struct platform_device *pdev) priv->clk = ddata->clk; priv->max_arr = ddata->max_arr; priv->triggers = triggers_table[index]; - priv->valids = cfg->valids_table[index]; + if (cfg->valids_table && *cfg->valids_table[index]) + priv->valids = cfg->valids_table[index]; stm32_timer_detect_trgo2(priv); mutex_init(&priv->lock); @@ -896,6 +900,16 @@ static const struct stm32_timer_trigger_cfg stm32h7_timer_trg_cfg = { .num_valids_table = ARRAY_SIZE(stm32h7_valids_table), }; +static const struct stm32_timer_trigger_cfg stm32mp25_timer_trg_cfg = { + /* + * valids_table not used: counter framework is now superseding the deprecated IIO + * counter interface (IIO_COUNT), so don't support it. num_valids_table is only + * kept here to register the IIO HW triggers. valids_table should be moved at some + * point to the stm32-timer-cnt driver instead. + */ + .num_valids_table = ARRAY_SIZE(triggers_table), +}; + static const struct of_device_id stm32_trig_of_match[] = { { .compatible = "st,stm32-timer-trigger", @@ -903,6 +917,9 @@ static const struct of_device_id stm32_trig_of_match[] = { }, { .compatible = "st,stm32h7-timer-trigger", .data = (void *)&stm32h7_timer_trg_cfg, + }, { + .compatible = "st,stm32mp25-timer-trigger", + .data = (void *)&stm32mp25_timer_trg_cfg, }, { /* end node */ }, }; diff --git a/include/linux/iio/timer/stm32-timer-trigger.h b/include/linux/iio/timer/stm32-timer-trigger.h index 37572e4dc73a..1ee237b56183 100644 --- a/include/linux/iio/timer/stm32-timer-trigger.h +++ b/include/linux/iio/timer/stm32-timer-trigger.h @@ -72,6 +72,12 @@ #define TIM17_OC1 "tim17_oc1" +#define TIM20_OC1 "tim20_oc1" +#define TIM20_OC2 "tim20_oc2" +#define TIM20_OC3 "tim20_oc3" +#define TIM20_TRGO "tim20_trgo" +#define TIM20_TRGO2 "tim20_trgo2" + #if IS_REACHABLE(CONFIG_IIO_STM32_TIMER_TRIGGER) bool is_stm32_timer_trigger(struct iio_trigger *trig); #else -- cgit v1.2.3