diff options
Diffstat (limited to 'drivers/iio/trigger/stm32-timer-trigger.c')
-rw-r--r-- | drivers/iio/trigger/stm32-timer-trigger.c | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c new file mode 100644 index 000000000000..994b96d19750 --- /dev/null +++ b/drivers/iio/trigger/stm32-timer-trigger.c | |||
@@ -0,0 +1,342 @@ | |||
1 | /* | ||
2 | * Copyright (C) STMicroelectronics 2016 | ||
3 | * | ||
4 | * Author: Benjamin Gaignard <benjamin.gaignard@st.com> | ||
5 | * | ||
6 | * License terms: GNU General Public License (GPL), version 2 | ||
7 | */ | ||
8 | |||
9 | #include <linux/iio/iio.h> | ||
10 | #include <linux/iio/sysfs.h> | ||
11 | #include <linux/iio/timer/stm32-timer-trigger.h> | ||
12 | #include <linux/iio/trigger.h> | ||
13 | #include <linux/mfd/stm32-timers.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | |||
17 | #define MAX_TRIGGERS 6 | ||
18 | |||
19 | /* List the triggers created by each timer */ | ||
20 | static const void *triggers_table[][MAX_TRIGGERS] = { | ||
21 | { TIM1_TRGO, TIM1_CH1, TIM1_CH2, TIM1_CH3, TIM1_CH4,}, | ||
22 | { TIM2_TRGO, TIM2_CH1, TIM2_CH2, TIM2_CH3, TIM2_CH4,}, | ||
23 | { TIM3_TRGO, TIM3_CH1, TIM3_CH2, TIM3_CH3, TIM3_CH4,}, | ||
24 | { TIM4_TRGO, TIM4_CH1, TIM4_CH2, TIM4_CH3, TIM4_CH4,}, | ||
25 | { TIM5_TRGO, TIM5_CH1, TIM5_CH2, TIM5_CH3, TIM5_CH4,}, | ||
26 | { TIM6_TRGO,}, | ||
27 | { TIM7_TRGO,}, | ||
28 | { TIM8_TRGO, TIM8_CH1, TIM8_CH2, TIM8_CH3, TIM8_CH4,}, | ||
29 | { TIM9_TRGO, TIM9_CH1, TIM9_CH2,}, | ||
30 | { }, /* timer 10 */ | ||
31 | { }, /* timer 11 */ | ||
32 | { TIM12_TRGO, TIM12_CH1, TIM12_CH2,}, | ||
33 | }; | ||
34 | |||
35 | struct stm32_timer_trigger { | ||
36 | struct device *dev; | ||
37 | struct regmap *regmap; | ||
38 | struct clk *clk; | ||
39 | u32 max_arr; | ||
40 | const void *triggers; | ||
41 | }; | ||
42 | |||
43 | static int stm32_timer_start(struct stm32_timer_trigger *priv, | ||
44 | unsigned int frequency) | ||
45 | { | ||
46 | unsigned long long prd, div; | ||
47 | int prescaler = 0; | ||
48 | u32 ccer, cr1; | ||
49 | |||
50 | /* Period and prescaler values depends of clock rate */ | ||
51 | div = (unsigned long long)clk_get_rate(priv->clk); | ||
52 | |||
53 | do_div(div, frequency); | ||
54 | |||
55 | prd = div; | ||
56 | |||
57 | /* | ||
58 | * Increase prescaler value until we get a result that fit | ||
59 | * with auto reload register maximum value. | ||
60 | */ | ||
61 | while (div > priv->max_arr) { | ||
62 | prescaler++; | ||
63 | div = prd; | ||
64 | do_div(div, (prescaler + 1)); | ||
65 | } | ||
66 | prd = div; | ||
67 | |||
68 | if (prescaler > MAX_TIM_PSC) { | ||
69 | dev_err(priv->dev, "prescaler exceeds the maximum value\n"); | ||
70 | return -EINVAL; | ||
71 | } | ||
72 | |||
73 | /* Check if nobody else use the timer */ | ||
74 | regmap_read(priv->regmap, TIM_CCER, &ccer); | ||
75 | if (ccer & TIM_CCER_CCXE) | ||
76 | return -EBUSY; | ||
77 | |||
78 | regmap_read(priv->regmap, TIM_CR1, &cr1); | ||
79 | if (!(cr1 & TIM_CR1_CEN)) | ||
80 | clk_enable(priv->clk); | ||
81 | |||
82 | regmap_write(priv->regmap, TIM_PSC, prescaler); | ||
83 | regmap_write(priv->regmap, TIM_ARR, prd - 1); | ||
84 | regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, TIM_CR1_ARPE); | ||
85 | |||
86 | /* Force master mode to update mode */ | ||
87 | regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS, 0x20); | ||
88 | |||
89 | /* Make sure that registers are updated */ | ||
90 | regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); | ||
91 | |||
92 | /* Enable controller */ | ||
93 | regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, TIM_CR1_CEN); | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static void stm32_timer_stop(struct stm32_timer_trigger *priv) | ||
99 | { | ||
100 | u32 ccer, cr1; | ||
101 | |||
102 | regmap_read(priv->regmap, TIM_CCER, &ccer); | ||
103 | if (ccer & TIM_CCER_CCXE) | ||
104 | return; | ||
105 | |||
106 | regmap_read(priv->regmap, TIM_CR1, &cr1); | ||
107 | if (cr1 & TIM_CR1_CEN) | ||
108 | clk_disable(priv->clk); | ||
109 | |||
110 | /* Stop timer */ | ||
111 | regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0); | ||
112 | regmap_write(priv->regmap, TIM_PSC, 0); | ||
113 | regmap_write(priv->regmap, TIM_ARR, 0); | ||
114 | |||
115 | /* Make sure that registers are updated */ | ||
116 | regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); | ||
117 | } | ||
118 | |||
119 | static ssize_t stm32_tt_store_frequency(struct device *dev, | ||
120 | struct device_attribute *attr, | ||
121 | const char *buf, size_t len) | ||
122 | { | ||
123 | struct iio_trigger *trig = to_iio_trigger(dev); | ||
124 | struct stm32_timer_trigger *priv = iio_trigger_get_drvdata(trig); | ||
125 | unsigned int freq; | ||
126 | int ret; | ||
127 | |||
128 | ret = kstrtouint(buf, 10, &freq); | ||
129 | if (ret) | ||
130 | return ret; | ||
131 | |||
132 | if (freq == 0) { | ||
133 | stm32_timer_stop(priv); | ||
134 | } else { | ||
135 | ret = stm32_timer_start(priv, freq); | ||
136 | if (ret) | ||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | return len; | ||
141 | } | ||
142 | |||
143 | static ssize_t stm32_tt_read_frequency(struct device *dev, | ||
144 | struct device_attribute *attr, char *buf) | ||
145 | { | ||
146 | struct iio_trigger *trig = to_iio_trigger(dev); | ||
147 | struct stm32_timer_trigger *priv = iio_trigger_get_drvdata(trig); | ||
148 | u32 psc, arr, cr1; | ||
149 | unsigned long long freq = 0; | ||
150 | |||
151 | regmap_read(priv->regmap, TIM_CR1, &cr1); | ||
152 | regmap_read(priv->regmap, TIM_PSC, &psc); | ||
153 | regmap_read(priv->regmap, TIM_ARR, &arr); | ||
154 | |||
155 | if (psc && arr && (cr1 & TIM_CR1_CEN)) { | ||
156 | freq = (unsigned long long)clk_get_rate(priv->clk); | ||
157 | do_div(freq, psc); | ||
158 | do_div(freq, arr); | ||
159 | } | ||
160 | |||
161 | return sprintf(buf, "%d\n", (unsigned int)freq); | ||
162 | } | ||
163 | |||
164 | static IIO_DEV_ATTR_SAMP_FREQ(0660, | ||
165 | stm32_tt_read_frequency, | ||
166 | stm32_tt_store_frequency); | ||
167 | |||
168 | static char *master_mode_table[] = { | ||
169 | "reset", | ||
170 | "enable", | ||
171 | "update", | ||
172 | "compare_pulse", | ||
173 | "OC1REF", | ||
174 | "OC2REF", | ||
175 | "OC3REF", | ||
176 | "OC4REF" | ||
177 | }; | ||
178 | |||
179 | static ssize_t stm32_tt_show_master_mode(struct device *dev, | ||
180 | struct device_attribute *attr, | ||
181 | char *buf) | ||
182 | { | ||
183 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
184 | struct stm32_timer_trigger *priv = iio_priv(indio_dev); | ||
185 | u32 cr2; | ||
186 | |||
187 | regmap_read(priv->regmap, TIM_CR2, &cr2); | ||
188 | cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT; | ||
189 | |||
190 | return snprintf(buf, PAGE_SIZE, "%s\n", master_mode_table[cr2]); | ||
191 | } | ||
192 | |||
193 | static ssize_t stm32_tt_store_master_mode(struct device *dev, | ||
194 | struct device_attribute *attr, | ||
195 | const char *buf, size_t len) | ||
196 | { | ||
197 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
198 | struct stm32_timer_trigger *priv = iio_priv(indio_dev); | ||
199 | int i; | ||
200 | |||
201 | for (i = 0; i < ARRAY_SIZE(master_mode_table); i++) { | ||
202 | if (!strncmp(master_mode_table[i], buf, | ||
203 | strlen(master_mode_table[i]))) { | ||
204 | regmap_update_bits(priv->regmap, TIM_CR2, | ||
205 | TIM_CR2_MMS, i << TIM_CR2_MMS_SHIFT); | ||
206 | /* Make sure that registers are updated */ | ||
207 | regmap_update_bits(priv->regmap, TIM_EGR, | ||
208 | TIM_EGR_UG, TIM_EGR_UG); | ||
209 | return len; | ||
210 | } | ||
211 | } | ||
212 | |||
213 | return -EINVAL; | ||
214 | } | ||
215 | |||
216 | static IIO_CONST_ATTR(master_mode_available, | ||
217 | "reset enable update compare_pulse OC1REF OC2REF OC3REF OC4REF"); | ||
218 | |||
219 | static IIO_DEVICE_ATTR(master_mode, 0660, | ||
220 | stm32_tt_show_master_mode, | ||
221 | stm32_tt_store_master_mode, | ||
222 | 0); | ||
223 | |||
224 | static struct attribute *stm32_trigger_attrs[] = { | ||
225 | &iio_dev_attr_sampling_frequency.dev_attr.attr, | ||
226 | &iio_dev_attr_master_mode.dev_attr.attr, | ||
227 | &iio_const_attr_master_mode_available.dev_attr.attr, | ||
228 | NULL, | ||
229 | }; | ||
230 | |||
231 | static const struct attribute_group stm32_trigger_attr_group = { | ||
232 | .attrs = stm32_trigger_attrs, | ||
233 | }; | ||
234 | |||
235 | static const struct attribute_group *stm32_trigger_attr_groups[] = { | ||
236 | &stm32_trigger_attr_group, | ||
237 | NULL, | ||
238 | }; | ||
239 | |||
240 | static const struct iio_trigger_ops timer_trigger_ops = { | ||
241 | .owner = THIS_MODULE, | ||
242 | }; | ||
243 | |||
244 | static int stm32_setup_iio_triggers(struct stm32_timer_trigger *priv) | ||
245 | { | ||
246 | int ret; | ||
247 | const char * const *cur = priv->triggers; | ||
248 | |||
249 | while (cur && *cur) { | ||
250 | struct iio_trigger *trig; | ||
251 | |||
252 | trig = devm_iio_trigger_alloc(priv->dev, "%s", *cur); | ||
253 | if (!trig) | ||
254 | return -ENOMEM; | ||
255 | |||
256 | trig->dev.parent = priv->dev->parent; | ||
257 | trig->ops = &timer_trigger_ops; | ||
258 | |||
259 | /* | ||
260 | * sampling frequency and master mode attributes | ||
261 | * should only be available on trgo trigger which | ||
262 | * is always the first in the list. | ||
263 | */ | ||
264 | if (cur == priv->triggers) | ||
265 | trig->dev.groups = stm32_trigger_attr_groups; | ||
266 | |||
267 | iio_trigger_set_drvdata(trig, priv); | ||
268 | |||
269 | ret = devm_iio_trigger_register(priv->dev, trig); | ||
270 | if (ret) | ||
271 | return ret; | ||
272 | cur++; | ||
273 | } | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | /** | ||
279 | * is_stm32_timer_trigger | ||
280 | * @trig: trigger to be checked | ||
281 | * | ||
282 | * return true if the trigger is a valid stm32 iio timer trigger | ||
283 | * either return false | ||
284 | */ | ||
285 | bool is_stm32_timer_trigger(struct iio_trigger *trig) | ||
286 | { | ||
287 | return (trig->ops == &timer_trigger_ops); | ||
288 | } | ||
289 | EXPORT_SYMBOL(is_stm32_timer_trigger); | ||
290 | |||
291 | static int stm32_timer_trigger_probe(struct platform_device *pdev) | ||
292 | { | ||
293 | struct device *dev = &pdev->dev; | ||
294 | struct stm32_timer_trigger *priv; | ||
295 | struct stm32_timers *ddata = dev_get_drvdata(pdev->dev.parent); | ||
296 | unsigned int index; | ||
297 | int ret; | ||
298 | |||
299 | if (of_property_read_u32(dev->of_node, "reg", &index)) | ||
300 | return -EINVAL; | ||
301 | |||
302 | if (index >= ARRAY_SIZE(triggers_table)) | ||
303 | return -EINVAL; | ||
304 | |||
305 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
306 | |||
307 | if (!priv) | ||
308 | return -ENOMEM; | ||
309 | |||
310 | priv->dev = dev; | ||
311 | priv->regmap = ddata->regmap; | ||
312 | priv->clk = ddata->clk; | ||
313 | priv->max_arr = ddata->max_arr; | ||
314 | priv->triggers = triggers_table[index]; | ||
315 | |||
316 | ret = stm32_setup_iio_triggers(priv); | ||
317 | if (ret) | ||
318 | return ret; | ||
319 | |||
320 | platform_set_drvdata(pdev, priv); | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static const struct of_device_id stm32_trig_of_match[] = { | ||
326 | { .compatible = "st,stm32-timer-trigger", }, | ||
327 | { /* end node */ }, | ||
328 | }; | ||
329 | MODULE_DEVICE_TABLE(of, stm32_trig_of_match); | ||
330 | |||
331 | static struct platform_driver stm32_timer_trigger_driver = { | ||
332 | .probe = stm32_timer_trigger_probe, | ||
333 | .driver = { | ||
334 | .name = "stm32-timer-trigger", | ||
335 | .of_match_table = stm32_trig_of_match, | ||
336 | }, | ||
337 | }; | ||
338 | module_platform_driver(stm32_timer_trigger_driver); | ||
339 | |||
340 | MODULE_ALIAS("platform: stm32-timer-trigger"); | ||
341 | MODULE_DESCRIPTION("STMicroelectronics STM32 Timer Trigger driver"); | ||
342 | MODULE_LICENSE("GPL v2"); | ||