|
@@ -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)
|