diff options
author | Fabrice Gasnier <fabrice.gasnier@st.com> | 2017-05-02 15:33:45 +0300 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2017-05-07 18:08:10 +0300 |
commit | 6fb34812c2a2a4cdcdad4452b9634892812fa97b (patch) | |
tree | 84579f1e9633faceb5db8b5404ac55e97f9a101c /drivers/iio/trigger | |
parent | f80ac400ee762bba3a420a4a537ce6ae7854b657 (diff) | |
download | linux-6fb34812c2a2a4cdcdad4452b9634892812fa97b.tar.xz |
iio: stm32 trigger: Add support for TRGO2 triggers
Add support for TRGO2 trigger that can be found on STM32F7.
Add additional master modes supported by TRGO2.
Register additional "tim[1/8]_trgo2" triggers for timer1 & timer8.
Detect TRGO2 timer capability (master mode selection 2).
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio/trigger')
-rw-r--r-- | drivers/iio/trigger/stm32-timer-trigger.c | 113 |
1 files changed, 99 insertions, 14 deletions
diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c index 25248d644e7c..0797f2fe584f 100644 --- a/drivers/iio/trigger/stm32-timer-trigger.c +++ b/drivers/iio/trigger/stm32-timer-trigger.c @@ -14,19 +14,19 @@ #include <linux/module.h> #include <linux/platform_device.h> -#define MAX_TRIGGERS 6 +#define MAX_TRIGGERS 7 #define MAX_VALIDS 5 /* List the triggers created by each timer */ static const void *triggers_table[][MAX_TRIGGERS] = { - { TIM1_TRGO, TIM1_CH1, TIM1_CH2, TIM1_CH3, TIM1_CH4,}, + { TIM1_TRGO, TIM1_TRGO2, TIM1_CH1, TIM1_CH2, TIM1_CH3, TIM1_CH4,}, { TIM2_TRGO, TIM2_CH1, TIM2_CH2, TIM2_CH3, TIM2_CH4,}, { TIM3_TRGO, TIM3_CH1, TIM3_CH2, TIM3_CH3, TIM3_CH4,}, { TIM4_TRGO, TIM4_CH1, TIM4_CH2, TIM4_CH3, TIM4_CH4,}, { TIM5_TRGO, TIM5_CH1, TIM5_CH2, TIM5_CH3, TIM5_CH4,}, { TIM6_TRGO,}, { TIM7_TRGO,}, - { TIM8_TRGO, TIM8_CH1, TIM8_CH2, TIM8_CH3, TIM8_CH4,}, + { TIM8_TRGO, TIM8_TRGO2, TIM8_CH1, TIM8_CH2, TIM8_CH3, TIM8_CH4,}, { TIM9_TRGO, TIM9_CH1, TIM9_CH2,}, { }, /* timer 10 */ { }, /* timer 11 */ @@ -56,9 +56,16 @@ struct stm32_timer_trigger { u32 max_arr; const void *triggers; const void *valids; + bool has_trgo2; }; +static bool stm32_timer_is_trgo2_name(const char *name) +{ + return !!strstr(name, "trgo2"); +} + static int stm32_timer_start(struct stm32_timer_trigger *priv, + struct iio_trigger *trig, unsigned int frequency) { unsigned long long prd, div; @@ -102,7 +109,12 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv, regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, TIM_CR1_ARPE); /* Force master mode to update mode */ - regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS, 0x20); + if (stm32_timer_is_trgo2_name(trig->name)) + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, + 0x2 << TIM_CR2_MMS2_SHIFT); + else + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS, + 0x2 << TIM_CR2_MMS_SHIFT); /* Make sure that registers are updated */ regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); @@ -150,7 +162,7 @@ static ssize_t stm32_tt_store_frequency(struct device *dev, if (freq == 0) { stm32_timer_stop(priv); } else { - ret = stm32_timer_start(priv, freq); + ret = stm32_timer_start(priv, trig, freq); if (ret) return ret; } @@ -183,6 +195,9 @@ static IIO_DEV_ATTR_SAMP_FREQ(0660, stm32_tt_read_frequency, stm32_tt_store_frequency); +#define MASTER_MODE_MAX 7 +#define MASTER_MODE2_MAX 15 + static char *master_mode_table[] = { "reset", "enable", @@ -191,7 +206,16 @@ static char *master_mode_table[] = { "OC1REF", "OC2REF", "OC3REF", - "OC4REF" + "OC4REF", + /* Master mode selection 2 only */ + "OC5REF", + "OC6REF", + "compare_pulse_OC4REF", + "compare_pulse_OC6REF", + "compare_pulse_OC4REF_r_or_OC6REF_r", + "compare_pulse_OC4REF_r_or_OC6REF_f", + "compare_pulse_OC5REF_r_or_OC6REF_r", + "compare_pulse_OC5REF_r_or_OC6REF_f", }; static ssize_t stm32_tt_show_master_mode(struct device *dev, @@ -199,10 +223,15 @@ static ssize_t stm32_tt_show_master_mode(struct device *dev, char *buf) { struct stm32_timer_trigger *priv = dev_get_drvdata(dev); + struct iio_trigger *trig = to_iio_trigger(dev); u32 cr2; regmap_read(priv->regmap, TIM_CR2, &cr2); - cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT; + + if (stm32_timer_is_trgo2_name(trig->name)) + cr2 = (cr2 & TIM_CR2_MMS2) >> TIM_CR2_MMS2_SHIFT; + else + cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT; return snprintf(buf, PAGE_SIZE, "%s\n", master_mode_table[cr2]); } @@ -212,13 +241,25 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev, const char *buf, size_t len) { 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; - for (i = 0; i < ARRAY_SIZE(master_mode_table); i++) { + if (stm32_timer_is_trgo2_name(trig->name)) { + mask = TIM_CR2_MMS2; + shift = TIM_CR2_MMS2_SHIFT; + master_mode_max = MASTER_MODE2_MAX; + } else { + mask = TIM_CR2_MMS; + shift = TIM_CR2_MMS_SHIFT; + master_mode_max = MASTER_MODE_MAX; + } + + for (i = 0; i <= master_mode_max; i++) { if (!strncmp(master_mode_table[i], buf, strlen(master_mode_table[i]))) { - regmap_update_bits(priv->regmap, TIM_CR2, - TIM_CR2_MMS, i << TIM_CR2_MMS_SHIFT); + regmap_update_bits(priv->regmap, TIM_CR2, mask, + i << shift); /* Make sure that registers are updated */ regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); @@ -229,8 +270,31 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev, return -EINVAL; } -static IIO_CONST_ATTR(master_mode_available, - "reset enable update compare_pulse OC1REF OC2REF OC3REF OC4REF"); +static ssize_t stm32_tt_show_master_mode_avail(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_trigger *trig = to_iio_trigger(dev); + unsigned int i, master_mode_max; + size_t len = 0; + + if (stm32_timer_is_trgo2_name(trig->name)) + master_mode_max = MASTER_MODE2_MAX; + else + master_mode_max = MASTER_MODE_MAX; + + for (i = 0; i <= master_mode_max; i++) + len += scnprintf(buf + len, PAGE_SIZE - len, + "%s ", master_mode_table[i]); + + /* replace trailing space by newline */ + buf[len - 1] = '\n'; + + return len; +} + +static IIO_DEVICE_ATTR(master_mode_available, 0444, + stm32_tt_show_master_mode_avail, NULL, 0); static IIO_DEVICE_ATTR(master_mode, 0660, stm32_tt_show_master_mode, @@ -240,7 +304,7 @@ static IIO_DEVICE_ATTR(master_mode, 0660, static struct attribute *stm32_trigger_attrs[] = { &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_dev_attr_master_mode.dev_attr.attr, - &iio_const_attr_master_mode_available.dev_attr.attr, + &iio_dev_attr_master_mode_available.dev_attr.attr, NULL, }; @@ -264,6 +328,12 @@ static int stm32_setup_iio_triggers(struct stm32_timer_trigger *priv) while (cur && *cur) { struct iio_trigger *trig; + bool cur_is_trgo2 = stm32_timer_is_trgo2_name(*cur); + + if (cur_is_trgo2 && !priv->has_trgo2) { + cur++; + continue; + } trig = devm_iio_trigger_alloc(priv->dev, "%s", *cur); if (!trig) @@ -277,7 +347,7 @@ static int stm32_setup_iio_triggers(struct stm32_timer_trigger *priv) * should only be available on trgo trigger which * is always the first in the list. */ - if (cur == priv->triggers) + if (cur == priv->triggers || cur_is_trgo2) trig->dev.groups = stm32_trigger_attr_groups; iio_trigger_set_drvdata(trig, priv); @@ -584,6 +654,20 @@ bool is_stm32_timer_trigger(struct iio_trigger *trig) } EXPORT_SYMBOL(is_stm32_timer_trigger); +static void stm32_timer_detect_trgo2(struct stm32_timer_trigger *priv) +{ + u32 val; + + /* + * Master mode selection 2 bits can only be written and read back when + * timer supports it. + */ + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, TIM_CR2_MMS2); + regmap_read(priv->regmap, TIM_CR2, &val); + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, 0); + priv->has_trgo2 = !!val; +} + static int stm32_timer_trigger_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -614,6 +698,7 @@ static int stm32_timer_trigger_probe(struct platform_device *pdev) priv->max_arr = ddata->max_arr; priv->triggers = triggers_table[index]; priv->valids = valids_table[index]; + stm32_timer_detect_trgo2(priv); ret = stm32_setup_iio_triggers(priv); if (ret) |