/* * Copyright (C) STMicroelectronics 2016 * * Author: Benjamin Gaignard * * License terms: GNU General Public License (GPL), version 2 */ #include #include #include #include #include #include #include #define MAX_TRIGGERS 6 /* List the triggers created by each timer */ static const void *triggers_table[][MAX_TRIGGERS] = { { TIM1_TRGO, 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,}, { TIM9_TRGO, TIM9_CH1, TIM9_CH2,}, { }, /* timer 10 */ { }, /* timer 11 */ { TIM12_TRGO, TIM12_CH1, TIM12_CH2,}, }; struct stm32_timer_trigger { struct device *dev; struct regmap *regmap; struct clk *clk; u32 max_arr; const void *triggers; }; static int stm32_timer_start(struct stm32_timer_trigger *priv, unsigned int frequency) { unsigned long long prd, div; int prescaler = 0; u32 ccer, cr1; /* Period and prescaler values depends of clock rate */ div = (unsigned long long)clk_get_rate(priv->clk); do_div(div, frequency); prd = div; /* * Increase prescaler value until we get a result that fit * with auto reload register maximum value. */ while (div > priv->max_arr) { prescaler++; div = prd; do_div(div, (prescaler + 1)); } prd = div; if (prescaler > MAX_TIM_PSC) { dev_err(priv->dev, "prescaler exceeds the maximum value\n"); return -EINVAL; } /* Check if nobody else use the timer */ regmap_read(priv->regmap, TIM_CCER, &ccer); if (ccer & TIM_CCER_CCXE) return -EBUSY; regmap_read(priv->regmap, TIM_CR1, &cr1); if (!(cr1 & TIM_CR1_CEN)) clk_enable(priv->clk); regmap_write(priv->regmap, TIM_PSC, prescaler); regmap_write(priv->regmap, TIM_ARR, prd - 1); 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); /* Make sure that registers are updated */ regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); /* Enable controller */ regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, TIM_CR1_CEN); return 0; } static void stm32_timer_stop(struct stm32_timer_trigger *priv) { u32 ccer, cr1; regmap_read(priv->regmap, TIM_CCER, &ccer); if (ccer & TIM_CCER_CCXE) return; regmap_read(priv->regmap, TIM_CR1, &cr1); if (cr1 & TIM_CR1_CEN) clk_disable(priv->clk); /* Stop timer */ regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0); regmap_write(priv->regmap, TIM_PSC, 0); regmap_write(priv->regmap, TIM_ARR, 0); /* Make sure that registers are updated */ regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); } static ssize_t stm32_tt_store_frequency(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_trigger *trig = to_iio_trigger(dev); struct stm32_timer_trigger *priv = iio_trigger_get_drvdata(trig); unsigned int freq; int ret; ret = kstrtouint(buf, 10, &freq); if (ret) return ret; if (freq == 0) { stm32_timer_stop(priv); } else { ret = stm32_timer_start(priv, freq); if (ret) return ret; } return len; } static ssize_t stm32_tt_read_frequency(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_trigger *trig = to_iio_trigger(dev); struct stm32_timer_trigger *priv = iio_trigger_get_drvdata(trig); u32 psc, arr, cr1; unsigned long long freq = 0; regmap_read(priv->regmap, TIM_CR1, &cr1); regmap_read(priv->regmap, TIM_PSC, &psc); regmap_read(priv->regmap, TIM_ARR, &arr); if (cr1 & TIM_CR1_CEN) { freq = (unsigned long long)clk_get_rate(priv->clk); do_div(freq, psc + 1); do_div(freq, arr + 1); } return sprintf(buf, "%d\n", (unsigned int)freq); } static IIO_DEV_ATTR_SAMP_FREQ(0660, stm32_tt_read_frequency, stm32_tt_store_frequency); static char *master_mode_table[] = { "reset", "enable", "update", "compare_pulse", "OC1REF", "OC2REF", "OC3REF", "OC4REF" }; static ssize_t stm32_tt_show_master_mode(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct stm32_timer_trigger *priv = iio_priv(indio_dev); u32 cr2; regmap_read(priv->regmap, TIM_CR2, &cr2); cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT; return snprintf(buf, PAGE_SIZE, "%s\n", master_mode_table[cr2]); } static ssize_t stm32_tt_store_master_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct stm32_timer_trigger *priv = iio_priv(indio_dev); int i; for (i = 0; i < ARRAY_SIZE(master_mode_table); 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); /* Make sure that registers are updated */ regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); return len; } } return -EINVAL; } static IIO_CONST_ATTR(master_mode_available, "reset enable update compare_pulse OC1REF OC2REF OC3REF OC4REF"); static IIO_DEVICE_ATTR(master_mode, 0660, stm32_tt_show_master_mode, stm32_tt_store_master_mode, 0); 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, NULL, }; static const struct attribute_group stm32_trigger_attr_group = { .attrs = stm32_trigger_attrs, }; static const struct attribute_group *stm32_trigger_attr_groups[] = { &stm32_trigger_attr_group, NULL, }; static const struct iio_trigger_ops timer_trigger_ops = { .owner = THIS_MODULE, }; static int stm32_setup_iio_triggers(struct stm32_timer_trigger *priv) { int ret; const char * const *cur = priv->triggers; while (cur && *cur) { struct iio_trigger *trig; trig = devm_iio_trigger_alloc(priv->dev, "%s", *cur); if (!trig) return -ENOMEM; trig->dev.parent = priv->dev->parent; trig->ops = &timer_trigger_ops; /* * sampling frequency and master mode attributes * should only be available on trgo trigger which * is always the first in the list. */ if (cur == priv->triggers) trig->dev.groups = stm32_trigger_attr_groups; iio_trigger_set_drvdata(trig, priv); ret = devm_iio_trigger_register(priv->dev, trig); if (ret) return ret; cur++; } return 0; } /** * is_stm32_timer_trigger * @trig: trigger to be checked * * return true if the trigger is a valid stm32 iio timer trigger * either return false */ bool is_stm32_timer_trigger(struct iio_trigger *trig) { return (trig->ops == &timer_trigger_ops); } EXPORT_SYMBOL(is_stm32_timer_trigger); static int stm32_timer_trigger_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct stm32_timer_trigger *priv; struct stm32_timers *ddata = dev_get_drvdata(pdev->dev.parent); unsigned int index; int ret; if (of_property_read_u32(dev->of_node, "reg", &index)) return -EINVAL; if (index >= ARRAY_SIZE(triggers_table)) return -EINVAL; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->dev = dev; priv->regmap = ddata->regmap; priv->clk = ddata->clk; priv->max_arr = ddata->max_arr; priv->triggers = triggers_table[index]; ret = stm32_setup_iio_triggers(priv); if (ret) return ret; platform_set_drvdata(pdev, priv); return 0; } static const struct of_device_id stm32_trig_of_match[] = { { .compatible = "st,stm32-timer-trigger", }, { /* end node */ }, }; MODULE_DEVICE_TABLE(of, stm32_trig_of_match); static struct platform_driver stm32_timer_trigger_driver = { .probe = stm32_timer_trigger_probe, .driver = { .name = "stm32-timer-trigger", .of_match_table = stm32_trig_of_match, }, }; module_platform_driver(stm32_timer_trigger_driver); MODULE_ALIAS("platform: stm32-timer-trigger"); MODULE_DESCRIPTION("STMicroelectronics STM32 Timer Trigger driver"); MODULE_LICENSE("GPL v2");