162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) STMicroelectronics 2016 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Author: Benjamin Gaignard <benjamin.gaignard@st.com> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/iio/iio.h> 1062306a36Sopenharmony_ci#include <linux/iio/sysfs.h> 1162306a36Sopenharmony_ci#include <linux/iio/timer/stm32-timer-trigger.h> 1262306a36Sopenharmony_ci#include <linux/iio/trigger.h> 1362306a36Sopenharmony_ci#include <linux/mfd/stm32-timers.h> 1462306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 1562306a36Sopenharmony_ci#include <linux/module.h> 1662306a36Sopenharmony_ci#include <linux/platform_device.h> 1762306a36Sopenharmony_ci#include <linux/property.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define MAX_TRIGGERS 7 2062306a36Sopenharmony_ci#define MAX_VALIDS 5 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* List the triggers created by each timer */ 2362306a36Sopenharmony_cistatic const void *triggers_table[][MAX_TRIGGERS] = { 2462306a36Sopenharmony_ci { TIM1_TRGO, TIM1_TRGO2, TIM1_CH1, TIM1_CH2, TIM1_CH3, TIM1_CH4,}, 2562306a36Sopenharmony_ci { TIM2_TRGO, TIM2_CH1, TIM2_CH2, TIM2_CH3, TIM2_CH4,}, 2662306a36Sopenharmony_ci { TIM3_TRGO, TIM3_CH1, TIM3_CH2, TIM3_CH3, TIM3_CH4,}, 2762306a36Sopenharmony_ci { TIM4_TRGO, TIM4_CH1, TIM4_CH2, TIM4_CH3, TIM4_CH4,}, 2862306a36Sopenharmony_ci { TIM5_TRGO, TIM5_CH1, TIM5_CH2, TIM5_CH3, TIM5_CH4,}, 2962306a36Sopenharmony_ci { TIM6_TRGO,}, 3062306a36Sopenharmony_ci { TIM7_TRGO,}, 3162306a36Sopenharmony_ci { TIM8_TRGO, TIM8_TRGO2, TIM8_CH1, TIM8_CH2, TIM8_CH3, TIM8_CH4,}, 3262306a36Sopenharmony_ci { TIM9_TRGO, TIM9_CH1, TIM9_CH2,}, 3362306a36Sopenharmony_ci { TIM10_OC1,}, 3462306a36Sopenharmony_ci { TIM11_OC1,}, 3562306a36Sopenharmony_ci { TIM12_TRGO, TIM12_CH1, TIM12_CH2,}, 3662306a36Sopenharmony_ci { TIM13_OC1,}, 3762306a36Sopenharmony_ci { TIM14_OC1,}, 3862306a36Sopenharmony_ci { TIM15_TRGO,}, 3962306a36Sopenharmony_ci { TIM16_OC1,}, 4062306a36Sopenharmony_ci { TIM17_OC1,}, 4162306a36Sopenharmony_ci}; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* List the triggers accepted by each timer */ 4462306a36Sopenharmony_cistatic const void *valids_table[][MAX_VALIDS] = { 4562306a36Sopenharmony_ci { TIM5_TRGO, TIM2_TRGO, TIM3_TRGO, TIM4_TRGO,}, 4662306a36Sopenharmony_ci { TIM1_TRGO, TIM8_TRGO, TIM3_TRGO, TIM4_TRGO,}, 4762306a36Sopenharmony_ci { TIM1_TRGO, TIM2_TRGO, TIM5_TRGO, TIM4_TRGO,}, 4862306a36Sopenharmony_ci { TIM1_TRGO, TIM2_TRGO, TIM3_TRGO, TIM8_TRGO,}, 4962306a36Sopenharmony_ci { TIM2_TRGO, TIM3_TRGO, TIM4_TRGO, TIM8_TRGO,}, 5062306a36Sopenharmony_ci { }, /* timer 6 */ 5162306a36Sopenharmony_ci { }, /* timer 7 */ 5262306a36Sopenharmony_ci { TIM1_TRGO, TIM2_TRGO, TIM4_TRGO, TIM5_TRGO,}, 5362306a36Sopenharmony_ci { TIM2_TRGO, TIM3_TRGO, TIM10_OC1, TIM11_OC1,}, 5462306a36Sopenharmony_ci { }, /* timer 10 */ 5562306a36Sopenharmony_ci { }, /* timer 11 */ 5662306a36Sopenharmony_ci { TIM4_TRGO, TIM5_TRGO, TIM13_OC1, TIM14_OC1,}, 5762306a36Sopenharmony_ci}; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistatic const void *stm32h7_valids_table[][MAX_VALIDS] = { 6062306a36Sopenharmony_ci { TIM15_TRGO, TIM2_TRGO, TIM3_TRGO, TIM4_TRGO,}, 6162306a36Sopenharmony_ci { TIM1_TRGO, TIM8_TRGO, TIM3_TRGO, TIM4_TRGO,}, 6262306a36Sopenharmony_ci { TIM1_TRGO, TIM2_TRGO, TIM15_TRGO, TIM4_TRGO,}, 6362306a36Sopenharmony_ci { TIM1_TRGO, TIM2_TRGO, TIM3_TRGO, TIM8_TRGO,}, 6462306a36Sopenharmony_ci { TIM1_TRGO, TIM8_TRGO, TIM3_TRGO, TIM4_TRGO,}, 6562306a36Sopenharmony_ci { }, /* timer 6 */ 6662306a36Sopenharmony_ci { }, /* timer 7 */ 6762306a36Sopenharmony_ci { TIM1_TRGO, TIM2_TRGO, TIM4_TRGO, TIM5_TRGO,}, 6862306a36Sopenharmony_ci { }, /* timer 9 */ 6962306a36Sopenharmony_ci { }, /* timer 10 */ 7062306a36Sopenharmony_ci { }, /* timer 11 */ 7162306a36Sopenharmony_ci { TIM4_TRGO, TIM5_TRGO, TIM13_OC1, TIM14_OC1,}, 7262306a36Sopenharmony_ci { }, /* timer 13 */ 7362306a36Sopenharmony_ci { }, /* timer 14 */ 7462306a36Sopenharmony_ci { TIM1_TRGO, TIM3_TRGO, TIM16_OC1, TIM17_OC1,}, 7562306a36Sopenharmony_ci { }, /* timer 16 */ 7662306a36Sopenharmony_ci { }, /* timer 17 */ 7762306a36Sopenharmony_ci}; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistruct stm32_timer_trigger_regs { 8062306a36Sopenharmony_ci u32 cr1; 8162306a36Sopenharmony_ci u32 cr2; 8262306a36Sopenharmony_ci u32 psc; 8362306a36Sopenharmony_ci u32 arr; 8462306a36Sopenharmony_ci u32 cnt; 8562306a36Sopenharmony_ci u32 smcr; 8662306a36Sopenharmony_ci}; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistruct stm32_timer_trigger { 8962306a36Sopenharmony_ci struct device *dev; 9062306a36Sopenharmony_ci struct regmap *regmap; 9162306a36Sopenharmony_ci struct clk *clk; 9262306a36Sopenharmony_ci bool enabled; 9362306a36Sopenharmony_ci u32 max_arr; 9462306a36Sopenharmony_ci const void *triggers; 9562306a36Sopenharmony_ci const void *valids; 9662306a36Sopenharmony_ci bool has_trgo2; 9762306a36Sopenharmony_ci struct mutex lock; /* concurrent sysfs configuration */ 9862306a36Sopenharmony_ci struct list_head tr_list; 9962306a36Sopenharmony_ci struct stm32_timer_trigger_regs bak; 10062306a36Sopenharmony_ci}; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistruct stm32_timer_trigger_cfg { 10362306a36Sopenharmony_ci const void *(*valids_table)[MAX_VALIDS]; 10462306a36Sopenharmony_ci const unsigned int num_valids_table; 10562306a36Sopenharmony_ci}; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic bool stm32_timer_is_trgo2_name(const char *name) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci return !!strstr(name, "trgo2"); 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic bool stm32_timer_is_trgo_name(const char *name) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci return (!!strstr(name, "trgo") && !strstr(name, "trgo2")); 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistatic int stm32_timer_start(struct stm32_timer_trigger *priv, 11862306a36Sopenharmony_ci struct iio_trigger *trig, 11962306a36Sopenharmony_ci unsigned int frequency) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci unsigned long long prd, div; 12262306a36Sopenharmony_ci int prescaler = 0; 12362306a36Sopenharmony_ci u32 ccer; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci /* Period and prescaler values depends of clock rate */ 12662306a36Sopenharmony_ci div = (unsigned long long)clk_get_rate(priv->clk); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci do_div(div, frequency); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci prd = div; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci /* 13362306a36Sopenharmony_ci * Increase prescaler value until we get a result that fit 13462306a36Sopenharmony_ci * with auto reload register maximum value. 13562306a36Sopenharmony_ci */ 13662306a36Sopenharmony_ci while (div > priv->max_arr) { 13762306a36Sopenharmony_ci prescaler++; 13862306a36Sopenharmony_ci div = prd; 13962306a36Sopenharmony_ci do_div(div, (prescaler + 1)); 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci prd = div; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci if (prescaler > MAX_TIM_PSC) { 14462306a36Sopenharmony_ci dev_err(priv->dev, "prescaler exceeds the maximum value\n"); 14562306a36Sopenharmony_ci return -EINVAL; 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci /* Check if nobody else use the timer */ 14962306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_CCER, &ccer); 15062306a36Sopenharmony_ci if (ccer & TIM_CCER_CCXE) 15162306a36Sopenharmony_ci return -EBUSY; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci mutex_lock(&priv->lock); 15462306a36Sopenharmony_ci if (!priv->enabled) { 15562306a36Sopenharmony_ci priv->enabled = true; 15662306a36Sopenharmony_ci clk_enable(priv->clk); 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci regmap_write(priv->regmap, TIM_PSC, prescaler); 16062306a36Sopenharmony_ci regmap_write(priv->regmap, TIM_ARR, prd - 1); 16162306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, TIM_CR1_ARPE); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci /* Force master mode to update mode */ 16462306a36Sopenharmony_ci if (stm32_timer_is_trgo2_name(trig->name)) 16562306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, 16662306a36Sopenharmony_ci 0x2 << TIM_CR2_MMS2_SHIFT); 16762306a36Sopenharmony_ci else 16862306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS, 16962306a36Sopenharmony_ci 0x2 << TIM_CR2_MMS_SHIFT); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci /* Make sure that registers are updated */ 17262306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci /* Enable controller */ 17562306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, TIM_CR1_CEN); 17662306a36Sopenharmony_ci mutex_unlock(&priv->lock); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci return 0; 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic void stm32_timer_stop(struct stm32_timer_trigger *priv, 18262306a36Sopenharmony_ci struct iio_trigger *trig) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci u32 ccer; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_CCER, &ccer); 18762306a36Sopenharmony_ci if (ccer & TIM_CCER_CCXE) 18862306a36Sopenharmony_ci return; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci mutex_lock(&priv->lock); 19162306a36Sopenharmony_ci /* Stop timer */ 19262306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0); 19362306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0); 19462306a36Sopenharmony_ci regmap_write(priv->regmap, TIM_PSC, 0); 19562306a36Sopenharmony_ci regmap_write(priv->regmap, TIM_ARR, 0); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci /* Force disable master mode */ 19862306a36Sopenharmony_ci if (stm32_timer_is_trgo2_name(trig->name)) 19962306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, 0); 20062306a36Sopenharmony_ci else 20162306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS, 0); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* Make sure that registers are updated */ 20462306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci if (priv->enabled) { 20762306a36Sopenharmony_ci priv->enabled = false; 20862306a36Sopenharmony_ci clk_disable(priv->clk); 20962306a36Sopenharmony_ci } 21062306a36Sopenharmony_ci mutex_unlock(&priv->lock); 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_cistatic ssize_t stm32_tt_store_frequency(struct device *dev, 21462306a36Sopenharmony_ci struct device_attribute *attr, 21562306a36Sopenharmony_ci const char *buf, size_t len) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci struct iio_trigger *trig = to_iio_trigger(dev); 21862306a36Sopenharmony_ci struct stm32_timer_trigger *priv = iio_trigger_get_drvdata(trig); 21962306a36Sopenharmony_ci unsigned int freq; 22062306a36Sopenharmony_ci int ret; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci ret = kstrtouint(buf, 10, &freq); 22362306a36Sopenharmony_ci if (ret) 22462306a36Sopenharmony_ci return ret; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci if (freq == 0) { 22762306a36Sopenharmony_ci stm32_timer_stop(priv, trig); 22862306a36Sopenharmony_ci } else { 22962306a36Sopenharmony_ci ret = stm32_timer_start(priv, trig, freq); 23062306a36Sopenharmony_ci if (ret) 23162306a36Sopenharmony_ci return ret; 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci return len; 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic ssize_t stm32_tt_read_frequency(struct device *dev, 23862306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci struct iio_trigger *trig = to_iio_trigger(dev); 24162306a36Sopenharmony_ci struct stm32_timer_trigger *priv = iio_trigger_get_drvdata(trig); 24262306a36Sopenharmony_ci u32 psc, arr, cr1; 24362306a36Sopenharmony_ci unsigned long long freq = 0; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_CR1, &cr1); 24662306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_PSC, &psc); 24762306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_ARR, &arr); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci if (cr1 & TIM_CR1_CEN) { 25062306a36Sopenharmony_ci freq = (unsigned long long)clk_get_rate(priv->clk); 25162306a36Sopenharmony_ci do_div(freq, psc + 1); 25262306a36Sopenharmony_ci do_div(freq, arr + 1); 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci return sprintf(buf, "%d\n", (unsigned int)freq); 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic IIO_DEV_ATTR_SAMP_FREQ(0660, 25962306a36Sopenharmony_ci stm32_tt_read_frequency, 26062306a36Sopenharmony_ci stm32_tt_store_frequency); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci#define MASTER_MODE_MAX 7 26362306a36Sopenharmony_ci#define MASTER_MODE2_MAX 15 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_cistatic char *master_mode_table[] = { 26662306a36Sopenharmony_ci "reset", 26762306a36Sopenharmony_ci "enable", 26862306a36Sopenharmony_ci "update", 26962306a36Sopenharmony_ci "compare_pulse", 27062306a36Sopenharmony_ci "OC1REF", 27162306a36Sopenharmony_ci "OC2REF", 27262306a36Sopenharmony_ci "OC3REF", 27362306a36Sopenharmony_ci "OC4REF", 27462306a36Sopenharmony_ci /* Master mode selection 2 only */ 27562306a36Sopenharmony_ci "OC5REF", 27662306a36Sopenharmony_ci "OC6REF", 27762306a36Sopenharmony_ci "compare_pulse_OC4REF", 27862306a36Sopenharmony_ci "compare_pulse_OC6REF", 27962306a36Sopenharmony_ci "compare_pulse_OC4REF_r_or_OC6REF_r", 28062306a36Sopenharmony_ci "compare_pulse_OC4REF_r_or_OC6REF_f", 28162306a36Sopenharmony_ci "compare_pulse_OC5REF_r_or_OC6REF_r", 28262306a36Sopenharmony_ci "compare_pulse_OC5REF_r_or_OC6REF_f", 28362306a36Sopenharmony_ci}; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_cistatic ssize_t stm32_tt_show_master_mode(struct device *dev, 28662306a36Sopenharmony_ci struct device_attribute *attr, 28762306a36Sopenharmony_ci char *buf) 28862306a36Sopenharmony_ci{ 28962306a36Sopenharmony_ci struct stm32_timer_trigger *priv = dev_get_drvdata(dev); 29062306a36Sopenharmony_ci struct iio_trigger *trig = to_iio_trigger(dev); 29162306a36Sopenharmony_ci u32 cr2; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_CR2, &cr2); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci if (stm32_timer_is_trgo2_name(trig->name)) 29662306a36Sopenharmony_ci cr2 = (cr2 & TIM_CR2_MMS2) >> TIM_CR2_MMS2_SHIFT; 29762306a36Sopenharmony_ci else 29862306a36Sopenharmony_ci cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci return sysfs_emit(buf, "%s\n", master_mode_table[cr2]); 30162306a36Sopenharmony_ci} 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_cistatic ssize_t stm32_tt_store_master_mode(struct device *dev, 30462306a36Sopenharmony_ci struct device_attribute *attr, 30562306a36Sopenharmony_ci const char *buf, size_t len) 30662306a36Sopenharmony_ci{ 30762306a36Sopenharmony_ci struct stm32_timer_trigger *priv = dev_get_drvdata(dev); 30862306a36Sopenharmony_ci struct iio_trigger *trig = to_iio_trigger(dev); 30962306a36Sopenharmony_ci u32 mask, shift, master_mode_max; 31062306a36Sopenharmony_ci int i; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci if (stm32_timer_is_trgo2_name(trig->name)) { 31362306a36Sopenharmony_ci mask = TIM_CR2_MMS2; 31462306a36Sopenharmony_ci shift = TIM_CR2_MMS2_SHIFT; 31562306a36Sopenharmony_ci master_mode_max = MASTER_MODE2_MAX; 31662306a36Sopenharmony_ci } else { 31762306a36Sopenharmony_ci mask = TIM_CR2_MMS; 31862306a36Sopenharmony_ci shift = TIM_CR2_MMS_SHIFT; 31962306a36Sopenharmony_ci master_mode_max = MASTER_MODE_MAX; 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci for (i = 0; i <= master_mode_max; i++) { 32362306a36Sopenharmony_ci if (!strncmp(master_mode_table[i], buf, 32462306a36Sopenharmony_ci strlen(master_mode_table[i]))) { 32562306a36Sopenharmony_ci mutex_lock(&priv->lock); 32662306a36Sopenharmony_ci if (!priv->enabled) { 32762306a36Sopenharmony_ci /* Clock should be enabled first */ 32862306a36Sopenharmony_ci priv->enabled = true; 32962306a36Sopenharmony_ci clk_enable(priv->clk); 33062306a36Sopenharmony_ci } 33162306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_CR2, mask, 33262306a36Sopenharmony_ci i << shift); 33362306a36Sopenharmony_ci mutex_unlock(&priv->lock); 33462306a36Sopenharmony_ci return len; 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci } 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci return -EINVAL; 33962306a36Sopenharmony_ci} 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_cistatic ssize_t stm32_tt_show_master_mode_avail(struct device *dev, 34262306a36Sopenharmony_ci struct device_attribute *attr, 34362306a36Sopenharmony_ci char *buf) 34462306a36Sopenharmony_ci{ 34562306a36Sopenharmony_ci struct iio_trigger *trig = to_iio_trigger(dev); 34662306a36Sopenharmony_ci unsigned int i, master_mode_max; 34762306a36Sopenharmony_ci size_t len = 0; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci if (stm32_timer_is_trgo2_name(trig->name)) 35062306a36Sopenharmony_ci master_mode_max = MASTER_MODE2_MAX; 35162306a36Sopenharmony_ci else 35262306a36Sopenharmony_ci master_mode_max = MASTER_MODE_MAX; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci for (i = 0; i <= master_mode_max; i++) 35562306a36Sopenharmony_ci len += scnprintf(buf + len, PAGE_SIZE - len, 35662306a36Sopenharmony_ci "%s ", master_mode_table[i]); 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci /* replace trailing space by newline */ 35962306a36Sopenharmony_ci buf[len - 1] = '\n'; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci return len; 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_cistatic IIO_DEVICE_ATTR(master_mode_available, 0444, 36562306a36Sopenharmony_ci stm32_tt_show_master_mode_avail, NULL, 0); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistatic IIO_DEVICE_ATTR(master_mode, 0660, 36862306a36Sopenharmony_ci stm32_tt_show_master_mode, 36962306a36Sopenharmony_ci stm32_tt_store_master_mode, 37062306a36Sopenharmony_ci 0); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_cistatic struct attribute *stm32_trigger_attrs[] = { 37362306a36Sopenharmony_ci &iio_dev_attr_sampling_frequency.dev_attr.attr, 37462306a36Sopenharmony_ci &iio_dev_attr_master_mode.dev_attr.attr, 37562306a36Sopenharmony_ci &iio_dev_attr_master_mode_available.dev_attr.attr, 37662306a36Sopenharmony_ci NULL, 37762306a36Sopenharmony_ci}; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_cistatic const struct attribute_group stm32_trigger_attr_group = { 38062306a36Sopenharmony_ci .attrs = stm32_trigger_attrs, 38162306a36Sopenharmony_ci}; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cistatic const struct attribute_group *stm32_trigger_attr_groups[] = { 38462306a36Sopenharmony_ci &stm32_trigger_attr_group, 38562306a36Sopenharmony_ci NULL, 38662306a36Sopenharmony_ci}; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_cistatic const struct iio_trigger_ops timer_trigger_ops = { 38962306a36Sopenharmony_ci}; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_cistatic void stm32_unregister_iio_triggers(struct stm32_timer_trigger *priv) 39262306a36Sopenharmony_ci{ 39362306a36Sopenharmony_ci struct iio_trigger *tr; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci list_for_each_entry(tr, &priv->tr_list, alloc_list) 39662306a36Sopenharmony_ci iio_trigger_unregister(tr); 39762306a36Sopenharmony_ci} 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_cistatic int stm32_register_iio_triggers(struct stm32_timer_trigger *priv) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci int ret; 40262306a36Sopenharmony_ci const char * const *cur = priv->triggers; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci INIT_LIST_HEAD(&priv->tr_list); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci while (cur && *cur) { 40762306a36Sopenharmony_ci struct iio_trigger *trig; 40862306a36Sopenharmony_ci bool cur_is_trgo = stm32_timer_is_trgo_name(*cur); 40962306a36Sopenharmony_ci bool cur_is_trgo2 = stm32_timer_is_trgo2_name(*cur); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci if (cur_is_trgo2 && !priv->has_trgo2) { 41262306a36Sopenharmony_ci cur++; 41362306a36Sopenharmony_ci continue; 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci trig = devm_iio_trigger_alloc(priv->dev, "%s", *cur); 41762306a36Sopenharmony_ci if (!trig) 41862306a36Sopenharmony_ci return -ENOMEM; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci trig->dev.parent = priv->dev->parent; 42162306a36Sopenharmony_ci trig->ops = &timer_trigger_ops; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci /* 42462306a36Sopenharmony_ci * sampling frequency and master mode attributes 42562306a36Sopenharmony_ci * should only be available on trgo/trgo2 triggers 42662306a36Sopenharmony_ci */ 42762306a36Sopenharmony_ci if (cur_is_trgo || cur_is_trgo2) 42862306a36Sopenharmony_ci trig->dev.groups = stm32_trigger_attr_groups; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci iio_trigger_set_drvdata(trig, priv); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci ret = iio_trigger_register(trig); 43362306a36Sopenharmony_ci if (ret) { 43462306a36Sopenharmony_ci stm32_unregister_iio_triggers(priv); 43562306a36Sopenharmony_ci return ret; 43662306a36Sopenharmony_ci } 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci list_add_tail(&trig->alloc_list, &priv->tr_list); 43962306a36Sopenharmony_ci cur++; 44062306a36Sopenharmony_ci } 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci return 0; 44362306a36Sopenharmony_ci} 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_cistatic int stm32_counter_read_raw(struct iio_dev *indio_dev, 44662306a36Sopenharmony_ci struct iio_chan_spec const *chan, 44762306a36Sopenharmony_ci int *val, int *val2, long mask) 44862306a36Sopenharmony_ci{ 44962306a36Sopenharmony_ci struct stm32_timer_trigger *priv = iio_priv(indio_dev); 45062306a36Sopenharmony_ci u32 dat; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci switch (mask) { 45362306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 45462306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_CNT, &dat); 45562306a36Sopenharmony_ci *val = dat; 45662306a36Sopenharmony_ci return IIO_VAL_INT; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci case IIO_CHAN_INFO_ENABLE: 45962306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_CR1, &dat); 46062306a36Sopenharmony_ci *val = (dat & TIM_CR1_CEN) ? 1 : 0; 46162306a36Sopenharmony_ci return IIO_VAL_INT; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 46462306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_SMCR, &dat); 46562306a36Sopenharmony_ci dat &= TIM_SMCR_SMS; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci *val = 1; 46862306a36Sopenharmony_ci *val2 = 0; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci /* in quadrature case scale = 0.25 */ 47162306a36Sopenharmony_ci if (dat == 3) 47262306a36Sopenharmony_ci *val2 = 2; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL_LOG2; 47562306a36Sopenharmony_ci } 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci return -EINVAL; 47862306a36Sopenharmony_ci} 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_cistatic int stm32_counter_write_raw(struct iio_dev *indio_dev, 48162306a36Sopenharmony_ci struct iio_chan_spec const *chan, 48262306a36Sopenharmony_ci int val, int val2, long mask) 48362306a36Sopenharmony_ci{ 48462306a36Sopenharmony_ci struct stm32_timer_trigger *priv = iio_priv(indio_dev); 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci switch (mask) { 48762306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 48862306a36Sopenharmony_ci return regmap_write(priv->regmap, TIM_CNT, val); 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 49162306a36Sopenharmony_ci /* fixed scale */ 49262306a36Sopenharmony_ci return -EINVAL; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci case IIO_CHAN_INFO_ENABLE: 49562306a36Sopenharmony_ci mutex_lock(&priv->lock); 49662306a36Sopenharmony_ci if (val) { 49762306a36Sopenharmony_ci if (!priv->enabled) { 49862306a36Sopenharmony_ci priv->enabled = true; 49962306a36Sopenharmony_ci clk_enable(priv->clk); 50062306a36Sopenharmony_ci } 50162306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 50262306a36Sopenharmony_ci TIM_CR1_CEN); 50362306a36Sopenharmony_ci } else { 50462306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 50562306a36Sopenharmony_ci 0); 50662306a36Sopenharmony_ci if (priv->enabled) { 50762306a36Sopenharmony_ci priv->enabled = false; 50862306a36Sopenharmony_ci clk_disable(priv->clk); 50962306a36Sopenharmony_ci } 51062306a36Sopenharmony_ci } 51162306a36Sopenharmony_ci mutex_unlock(&priv->lock); 51262306a36Sopenharmony_ci return 0; 51362306a36Sopenharmony_ci } 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci return -EINVAL; 51662306a36Sopenharmony_ci} 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_cistatic int stm32_counter_validate_trigger(struct iio_dev *indio_dev, 51962306a36Sopenharmony_ci struct iio_trigger *trig) 52062306a36Sopenharmony_ci{ 52162306a36Sopenharmony_ci struct stm32_timer_trigger *priv = iio_priv(indio_dev); 52262306a36Sopenharmony_ci const char * const *cur = priv->valids; 52362306a36Sopenharmony_ci unsigned int i = 0; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci if (!is_stm32_timer_trigger(trig)) 52662306a36Sopenharmony_ci return -EINVAL; 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci while (cur && *cur) { 52962306a36Sopenharmony_ci if (!strncmp(trig->name, *cur, strlen(trig->name))) { 53062306a36Sopenharmony_ci regmap_update_bits(priv->regmap, 53162306a36Sopenharmony_ci TIM_SMCR, TIM_SMCR_TS, 53262306a36Sopenharmony_ci i << TIM_SMCR_TS_SHIFT); 53362306a36Sopenharmony_ci return 0; 53462306a36Sopenharmony_ci } 53562306a36Sopenharmony_ci cur++; 53662306a36Sopenharmony_ci i++; 53762306a36Sopenharmony_ci } 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci return -EINVAL; 54062306a36Sopenharmony_ci} 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_cistatic const struct iio_info stm32_trigger_info = { 54362306a36Sopenharmony_ci .validate_trigger = stm32_counter_validate_trigger, 54462306a36Sopenharmony_ci .read_raw = stm32_counter_read_raw, 54562306a36Sopenharmony_ci .write_raw = stm32_counter_write_raw 54662306a36Sopenharmony_ci}; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_cistatic const char *const stm32_trigger_modes[] = { 54962306a36Sopenharmony_ci "trigger", 55062306a36Sopenharmony_ci}; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_cistatic int stm32_set_trigger_mode(struct iio_dev *indio_dev, 55362306a36Sopenharmony_ci const struct iio_chan_spec *chan, 55462306a36Sopenharmony_ci unsigned int mode) 55562306a36Sopenharmony_ci{ 55662306a36Sopenharmony_ci struct stm32_timer_trigger *priv = iio_priv(indio_dev); 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, TIM_SMCR_SMS); 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci return 0; 56162306a36Sopenharmony_ci} 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_cistatic int stm32_get_trigger_mode(struct iio_dev *indio_dev, 56462306a36Sopenharmony_ci const struct iio_chan_spec *chan) 56562306a36Sopenharmony_ci{ 56662306a36Sopenharmony_ci struct stm32_timer_trigger *priv = iio_priv(indio_dev); 56762306a36Sopenharmony_ci u32 smcr; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_SMCR, &smcr); 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci return (smcr & TIM_SMCR_SMS) == TIM_SMCR_SMS ? 0 : -EINVAL; 57262306a36Sopenharmony_ci} 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_cistatic const struct iio_enum stm32_trigger_mode_enum = { 57562306a36Sopenharmony_ci .items = stm32_trigger_modes, 57662306a36Sopenharmony_ci .num_items = ARRAY_SIZE(stm32_trigger_modes), 57762306a36Sopenharmony_ci .set = stm32_set_trigger_mode, 57862306a36Sopenharmony_ci .get = stm32_get_trigger_mode 57962306a36Sopenharmony_ci}; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_cistatic const char *const stm32_enable_modes[] = { 58262306a36Sopenharmony_ci "always", 58362306a36Sopenharmony_ci "gated", 58462306a36Sopenharmony_ci "triggered", 58562306a36Sopenharmony_ci}; 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_cistatic int stm32_enable_mode2sms(int mode) 58862306a36Sopenharmony_ci{ 58962306a36Sopenharmony_ci switch (mode) { 59062306a36Sopenharmony_ci case 0: 59162306a36Sopenharmony_ci return 0; 59262306a36Sopenharmony_ci case 1: 59362306a36Sopenharmony_ci return 5; 59462306a36Sopenharmony_ci case 2: 59562306a36Sopenharmony_ci return 6; 59662306a36Sopenharmony_ci } 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci return -EINVAL; 59962306a36Sopenharmony_ci} 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_cistatic int stm32_set_enable_mode(struct iio_dev *indio_dev, 60262306a36Sopenharmony_ci const struct iio_chan_spec *chan, 60362306a36Sopenharmony_ci unsigned int mode) 60462306a36Sopenharmony_ci{ 60562306a36Sopenharmony_ci struct stm32_timer_trigger *priv = iio_priv(indio_dev); 60662306a36Sopenharmony_ci int sms = stm32_enable_mode2sms(mode); 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci if (sms < 0) 60962306a36Sopenharmony_ci return sms; 61062306a36Sopenharmony_ci /* 61162306a36Sopenharmony_ci * Triggered mode sets CEN bit automatically by hardware. So, first 61262306a36Sopenharmony_ci * enable counter clock, so it can use it. Keeps it in sync with CEN. 61362306a36Sopenharmony_ci */ 61462306a36Sopenharmony_ci mutex_lock(&priv->lock); 61562306a36Sopenharmony_ci if (sms == 6 && !priv->enabled) { 61662306a36Sopenharmony_ci clk_enable(priv->clk); 61762306a36Sopenharmony_ci priv->enabled = true; 61862306a36Sopenharmony_ci } 61962306a36Sopenharmony_ci mutex_unlock(&priv->lock); 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, sms); 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci return 0; 62462306a36Sopenharmony_ci} 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_cistatic int stm32_sms2enable_mode(int mode) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci switch (mode) { 62962306a36Sopenharmony_ci case 0: 63062306a36Sopenharmony_ci return 0; 63162306a36Sopenharmony_ci case 5: 63262306a36Sopenharmony_ci return 1; 63362306a36Sopenharmony_ci case 6: 63462306a36Sopenharmony_ci return 2; 63562306a36Sopenharmony_ci } 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci return -EINVAL; 63862306a36Sopenharmony_ci} 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_cistatic int stm32_get_enable_mode(struct iio_dev *indio_dev, 64162306a36Sopenharmony_ci const struct iio_chan_spec *chan) 64262306a36Sopenharmony_ci{ 64362306a36Sopenharmony_ci struct stm32_timer_trigger *priv = iio_priv(indio_dev); 64462306a36Sopenharmony_ci u32 smcr; 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_SMCR, &smcr); 64762306a36Sopenharmony_ci smcr &= TIM_SMCR_SMS; 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci return stm32_sms2enable_mode(smcr); 65062306a36Sopenharmony_ci} 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_cistatic const struct iio_enum stm32_enable_mode_enum = { 65362306a36Sopenharmony_ci .items = stm32_enable_modes, 65462306a36Sopenharmony_ci .num_items = ARRAY_SIZE(stm32_enable_modes), 65562306a36Sopenharmony_ci .set = stm32_set_enable_mode, 65662306a36Sopenharmony_ci .get = stm32_get_enable_mode 65762306a36Sopenharmony_ci}; 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_cistatic ssize_t stm32_count_get_preset(struct iio_dev *indio_dev, 66062306a36Sopenharmony_ci uintptr_t private, 66162306a36Sopenharmony_ci const struct iio_chan_spec *chan, 66262306a36Sopenharmony_ci char *buf) 66362306a36Sopenharmony_ci{ 66462306a36Sopenharmony_ci struct stm32_timer_trigger *priv = iio_priv(indio_dev); 66562306a36Sopenharmony_ci u32 arr; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_ARR, &arr); 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci return snprintf(buf, PAGE_SIZE, "%u\n", arr); 67062306a36Sopenharmony_ci} 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_cistatic ssize_t stm32_count_set_preset(struct iio_dev *indio_dev, 67362306a36Sopenharmony_ci uintptr_t private, 67462306a36Sopenharmony_ci const struct iio_chan_spec *chan, 67562306a36Sopenharmony_ci const char *buf, size_t len) 67662306a36Sopenharmony_ci{ 67762306a36Sopenharmony_ci struct stm32_timer_trigger *priv = iio_priv(indio_dev); 67862306a36Sopenharmony_ci unsigned int preset; 67962306a36Sopenharmony_ci int ret; 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci ret = kstrtouint(buf, 0, &preset); 68262306a36Sopenharmony_ci if (ret) 68362306a36Sopenharmony_ci return ret; 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci /* TIMx_ARR register shouldn't be buffered (ARPE=0) */ 68662306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0); 68762306a36Sopenharmony_ci regmap_write(priv->regmap, TIM_ARR, preset); 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci return len; 69062306a36Sopenharmony_ci} 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_cistatic const struct iio_chan_spec_ext_info stm32_trigger_count_info[] = { 69362306a36Sopenharmony_ci { 69462306a36Sopenharmony_ci .name = "preset", 69562306a36Sopenharmony_ci .shared = IIO_SEPARATE, 69662306a36Sopenharmony_ci .read = stm32_count_get_preset, 69762306a36Sopenharmony_ci .write = stm32_count_set_preset 69862306a36Sopenharmony_ci }, 69962306a36Sopenharmony_ci IIO_ENUM("enable_mode", IIO_SEPARATE, &stm32_enable_mode_enum), 70062306a36Sopenharmony_ci IIO_ENUM_AVAILABLE("enable_mode", IIO_SHARED_BY_TYPE, &stm32_enable_mode_enum), 70162306a36Sopenharmony_ci IIO_ENUM("trigger_mode", IIO_SEPARATE, &stm32_trigger_mode_enum), 70262306a36Sopenharmony_ci IIO_ENUM_AVAILABLE("trigger_mode", IIO_SHARED_BY_TYPE, &stm32_trigger_mode_enum), 70362306a36Sopenharmony_ci {} 70462306a36Sopenharmony_ci}; 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_cistatic const struct iio_chan_spec stm32_trigger_channel = { 70762306a36Sopenharmony_ci .type = IIO_COUNT, 70862306a36Sopenharmony_ci .channel = 0, 70962306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 71062306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_ENABLE) | 71162306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), 71262306a36Sopenharmony_ci .ext_info = stm32_trigger_count_info, 71362306a36Sopenharmony_ci .indexed = 1 71462306a36Sopenharmony_ci}; 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_cistatic struct stm32_timer_trigger *stm32_setup_counter_device(struct device *dev) 71762306a36Sopenharmony_ci{ 71862306a36Sopenharmony_ci struct iio_dev *indio_dev; 71962306a36Sopenharmony_ci int ret; 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci indio_dev = devm_iio_device_alloc(dev, 72262306a36Sopenharmony_ci sizeof(struct stm32_timer_trigger)); 72362306a36Sopenharmony_ci if (!indio_dev) 72462306a36Sopenharmony_ci return NULL; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci indio_dev->name = dev_name(dev); 72762306a36Sopenharmony_ci indio_dev->info = &stm32_trigger_info; 72862306a36Sopenharmony_ci indio_dev->modes = INDIO_HARDWARE_TRIGGERED; 72962306a36Sopenharmony_ci indio_dev->num_channels = 1; 73062306a36Sopenharmony_ci indio_dev->channels = &stm32_trigger_channel; 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci ret = devm_iio_device_register(dev, indio_dev); 73362306a36Sopenharmony_ci if (ret) 73462306a36Sopenharmony_ci return NULL; 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci return iio_priv(indio_dev); 73762306a36Sopenharmony_ci} 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci/** 74062306a36Sopenharmony_ci * is_stm32_timer_trigger 74162306a36Sopenharmony_ci * @trig: trigger to be checked 74262306a36Sopenharmony_ci * 74362306a36Sopenharmony_ci * return true if the trigger is a valid stm32 iio timer trigger 74462306a36Sopenharmony_ci * either return false 74562306a36Sopenharmony_ci */ 74662306a36Sopenharmony_cibool is_stm32_timer_trigger(struct iio_trigger *trig) 74762306a36Sopenharmony_ci{ 74862306a36Sopenharmony_ci return (trig->ops == &timer_trigger_ops); 74962306a36Sopenharmony_ci} 75062306a36Sopenharmony_ciEXPORT_SYMBOL(is_stm32_timer_trigger); 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_cistatic void stm32_timer_detect_trgo2(struct stm32_timer_trigger *priv) 75362306a36Sopenharmony_ci{ 75462306a36Sopenharmony_ci u32 val; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci /* 75762306a36Sopenharmony_ci * Master mode selection 2 bits can only be written and read back when 75862306a36Sopenharmony_ci * timer supports it. 75962306a36Sopenharmony_ci */ 76062306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, TIM_CR2_MMS2); 76162306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_CR2, &val); 76262306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, 0); 76362306a36Sopenharmony_ci priv->has_trgo2 = !!val; 76462306a36Sopenharmony_ci} 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_cistatic int stm32_timer_trigger_probe(struct platform_device *pdev) 76762306a36Sopenharmony_ci{ 76862306a36Sopenharmony_ci struct device *dev = &pdev->dev; 76962306a36Sopenharmony_ci struct stm32_timer_trigger *priv; 77062306a36Sopenharmony_ci struct stm32_timers *ddata = dev_get_drvdata(pdev->dev.parent); 77162306a36Sopenharmony_ci const struct stm32_timer_trigger_cfg *cfg; 77262306a36Sopenharmony_ci unsigned int index; 77362306a36Sopenharmony_ci int ret; 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci ret = device_property_read_u32(dev, "reg", &index); 77662306a36Sopenharmony_ci if (ret) 77762306a36Sopenharmony_ci return ret; 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci cfg = device_get_match_data(dev); 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci if (index >= ARRAY_SIZE(triggers_table) || 78262306a36Sopenharmony_ci index >= cfg->num_valids_table) 78362306a36Sopenharmony_ci return -EINVAL; 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci /* Create an IIO device only if we have triggers to be validated */ 78662306a36Sopenharmony_ci if (*cfg->valids_table[index]) 78762306a36Sopenharmony_ci priv = stm32_setup_counter_device(dev); 78862306a36Sopenharmony_ci else 78962306a36Sopenharmony_ci priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci if (!priv) 79262306a36Sopenharmony_ci return -ENOMEM; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci priv->dev = dev; 79562306a36Sopenharmony_ci priv->regmap = ddata->regmap; 79662306a36Sopenharmony_ci priv->clk = ddata->clk; 79762306a36Sopenharmony_ci priv->max_arr = ddata->max_arr; 79862306a36Sopenharmony_ci priv->triggers = triggers_table[index]; 79962306a36Sopenharmony_ci priv->valids = cfg->valids_table[index]; 80062306a36Sopenharmony_ci stm32_timer_detect_trgo2(priv); 80162306a36Sopenharmony_ci mutex_init(&priv->lock); 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci ret = stm32_register_iio_triggers(priv); 80462306a36Sopenharmony_ci if (ret) 80562306a36Sopenharmony_ci return ret; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci platform_set_drvdata(pdev, priv); 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci return 0; 81062306a36Sopenharmony_ci} 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_cistatic int stm32_timer_trigger_remove(struct platform_device *pdev) 81362306a36Sopenharmony_ci{ 81462306a36Sopenharmony_ci struct stm32_timer_trigger *priv = platform_get_drvdata(pdev); 81562306a36Sopenharmony_ci u32 val; 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci /* Unregister triggers before everything can be safely turned off */ 81862306a36Sopenharmony_ci stm32_unregister_iio_triggers(priv); 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci /* Check if nobody else use the timer, then disable it */ 82162306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_CCER, &val); 82262306a36Sopenharmony_ci if (!(val & TIM_CCER_CCXE)) 82362306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0); 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci if (priv->enabled) 82662306a36Sopenharmony_ci clk_disable(priv->clk); 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci return 0; 82962306a36Sopenharmony_ci} 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_cistatic int stm32_timer_trigger_suspend(struct device *dev) 83262306a36Sopenharmony_ci{ 83362306a36Sopenharmony_ci struct stm32_timer_trigger *priv = dev_get_drvdata(dev); 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci /* Only take care of enabled timer: don't disturb other MFD child */ 83662306a36Sopenharmony_ci if (priv->enabled) { 83762306a36Sopenharmony_ci /* Backup registers that may get lost in low power mode */ 83862306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_CR1, &priv->bak.cr1); 83962306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_CR2, &priv->bak.cr2); 84062306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_PSC, &priv->bak.psc); 84162306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_ARR, &priv->bak.arr); 84262306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_CNT, &priv->bak.cnt); 84362306a36Sopenharmony_ci regmap_read(priv->regmap, TIM_SMCR, &priv->bak.smcr); 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci /* Disable the timer */ 84662306a36Sopenharmony_ci regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0); 84762306a36Sopenharmony_ci clk_disable(priv->clk); 84862306a36Sopenharmony_ci } 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci return 0; 85162306a36Sopenharmony_ci} 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_cistatic int stm32_timer_trigger_resume(struct device *dev) 85462306a36Sopenharmony_ci{ 85562306a36Sopenharmony_ci struct stm32_timer_trigger *priv = dev_get_drvdata(dev); 85662306a36Sopenharmony_ci int ret; 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci if (priv->enabled) { 85962306a36Sopenharmony_ci ret = clk_enable(priv->clk); 86062306a36Sopenharmony_ci if (ret) 86162306a36Sopenharmony_ci return ret; 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci /* restore master/slave modes */ 86462306a36Sopenharmony_ci regmap_write(priv->regmap, TIM_SMCR, priv->bak.smcr); 86562306a36Sopenharmony_ci regmap_write(priv->regmap, TIM_CR2, priv->bak.cr2); 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci /* restore sampling_frequency (trgo / trgo2 triggers) */ 86862306a36Sopenharmony_ci regmap_write(priv->regmap, TIM_PSC, priv->bak.psc); 86962306a36Sopenharmony_ci regmap_write(priv->regmap, TIM_ARR, priv->bak.arr); 87062306a36Sopenharmony_ci regmap_write(priv->regmap, TIM_CNT, priv->bak.cnt); 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci /* Also re-enables the timer */ 87362306a36Sopenharmony_ci regmap_write(priv->regmap, TIM_CR1, priv->bak.cr1); 87462306a36Sopenharmony_ci } 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci return 0; 87762306a36Sopenharmony_ci} 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_cistatic DEFINE_SIMPLE_DEV_PM_OPS(stm32_timer_trigger_pm_ops, 88062306a36Sopenharmony_ci stm32_timer_trigger_suspend, 88162306a36Sopenharmony_ci stm32_timer_trigger_resume); 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_cistatic const struct stm32_timer_trigger_cfg stm32_timer_trg_cfg = { 88462306a36Sopenharmony_ci .valids_table = valids_table, 88562306a36Sopenharmony_ci .num_valids_table = ARRAY_SIZE(valids_table), 88662306a36Sopenharmony_ci}; 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_cistatic const struct stm32_timer_trigger_cfg stm32h7_timer_trg_cfg = { 88962306a36Sopenharmony_ci .valids_table = stm32h7_valids_table, 89062306a36Sopenharmony_ci .num_valids_table = ARRAY_SIZE(stm32h7_valids_table), 89162306a36Sopenharmony_ci}; 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_cistatic const struct of_device_id stm32_trig_of_match[] = { 89462306a36Sopenharmony_ci { 89562306a36Sopenharmony_ci .compatible = "st,stm32-timer-trigger", 89662306a36Sopenharmony_ci .data = (void *)&stm32_timer_trg_cfg, 89762306a36Sopenharmony_ci }, { 89862306a36Sopenharmony_ci .compatible = "st,stm32h7-timer-trigger", 89962306a36Sopenharmony_ci .data = (void *)&stm32h7_timer_trg_cfg, 90062306a36Sopenharmony_ci }, 90162306a36Sopenharmony_ci { /* end node */ }, 90262306a36Sopenharmony_ci}; 90362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, stm32_trig_of_match); 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_cistatic struct platform_driver stm32_timer_trigger_driver = { 90662306a36Sopenharmony_ci .probe = stm32_timer_trigger_probe, 90762306a36Sopenharmony_ci .remove = stm32_timer_trigger_remove, 90862306a36Sopenharmony_ci .driver = { 90962306a36Sopenharmony_ci .name = "stm32-timer-trigger", 91062306a36Sopenharmony_ci .of_match_table = stm32_trig_of_match, 91162306a36Sopenharmony_ci .pm = pm_sleep_ptr(&stm32_timer_trigger_pm_ops), 91262306a36Sopenharmony_ci }, 91362306a36Sopenharmony_ci}; 91462306a36Sopenharmony_cimodule_platform_driver(stm32_timer_trigger_driver); 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ciMODULE_ALIAS("platform:stm32-timer-trigger"); 91762306a36Sopenharmony_ciMODULE_DESCRIPTION("STMicroelectronics STM32 Timer Trigger driver"); 91862306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 919