1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * STM32 Low-Power Timer Trigger driver |
4 | * |
5 | * Copyright (C) STMicroelectronics 2017 |
6 | * |
7 | * Author: Fabrice Gasnier <fabrice.gasnier@st.com>. |
8 | * |
9 | * Inspired by Benjamin Gaignard's stm32-timer-trigger driver |
10 | */ |
11 | |
12 | #include <linux/iio/timer/stm32-lptim-trigger.h> |
13 | #include <linux/mfd/stm32-lptimer.h> |
14 | #include <linux/mod_devicetable.h> |
15 | #include <linux/module.h> |
16 | #include <linux/platform_device.h> |
17 | #include <linux/property.h> |
18 | |
19 | /* List Low-Power Timer triggers */ |
20 | static const char * const stm32_lptim_triggers[] = { |
21 | LPTIM1_OUT, |
22 | LPTIM2_OUT, |
23 | LPTIM3_OUT, |
24 | }; |
25 | |
26 | struct stm32_lptim_trigger { |
27 | struct device *dev; |
28 | const char *trg; |
29 | }; |
30 | |
31 | static int stm32_lptim_validate_device(struct iio_trigger *trig, |
32 | struct iio_dev *indio_dev) |
33 | { |
34 | if (indio_dev->modes & INDIO_HARDWARE_TRIGGERED) |
35 | return 0; |
36 | |
37 | return -EINVAL; |
38 | } |
39 | |
40 | static const struct iio_trigger_ops stm32_lptim_trigger_ops = { |
41 | .validate_device = stm32_lptim_validate_device, |
42 | }; |
43 | |
44 | /** |
45 | * is_stm32_lptim_trigger |
46 | * @trig: trigger to be checked |
47 | * |
48 | * return true if the trigger is a valid STM32 IIO Low-Power Timer Trigger |
49 | * either return false |
50 | */ |
51 | bool is_stm32_lptim_trigger(struct iio_trigger *trig) |
52 | { |
53 | return (trig->ops == &stm32_lptim_trigger_ops); |
54 | } |
55 | EXPORT_SYMBOL(is_stm32_lptim_trigger); |
56 | |
57 | static int stm32_lptim_setup_trig(struct stm32_lptim_trigger *priv) |
58 | { |
59 | struct iio_trigger *trig; |
60 | |
61 | trig = devm_iio_trigger_alloc(priv->dev, "%s" , priv->trg); |
62 | if (!trig) |
63 | return -ENOMEM; |
64 | |
65 | trig->dev.parent = priv->dev->parent; |
66 | trig->ops = &stm32_lptim_trigger_ops; |
67 | iio_trigger_set_drvdata(trig, data: priv); |
68 | |
69 | return devm_iio_trigger_register(dev: priv->dev, trig_info: trig); |
70 | } |
71 | |
72 | static int stm32_lptim_trigger_probe(struct platform_device *pdev) |
73 | { |
74 | struct stm32_lptim_trigger *priv; |
75 | u32 index; |
76 | |
77 | priv = devm_kzalloc(dev: &pdev->dev, size: sizeof(*priv), GFP_KERNEL); |
78 | if (!priv) |
79 | return -ENOMEM; |
80 | |
81 | if (device_property_read_u32(dev: &pdev->dev, propname: "reg" , val: &index)) |
82 | return -EINVAL; |
83 | |
84 | if (index >= ARRAY_SIZE(stm32_lptim_triggers)) |
85 | return -EINVAL; |
86 | |
87 | priv->dev = &pdev->dev; |
88 | priv->trg = stm32_lptim_triggers[index]; |
89 | |
90 | return stm32_lptim_setup_trig(priv); |
91 | } |
92 | |
93 | static const struct of_device_id stm32_lptim_trig_of_match[] = { |
94 | { .compatible = "st,stm32-lptimer-trigger" , }, |
95 | {}, |
96 | }; |
97 | MODULE_DEVICE_TABLE(of, stm32_lptim_trig_of_match); |
98 | |
99 | static struct platform_driver stm32_lptim_trigger_driver = { |
100 | .probe = stm32_lptim_trigger_probe, |
101 | .driver = { |
102 | .name = "stm32-lptimer-trigger" , |
103 | .of_match_table = stm32_lptim_trig_of_match, |
104 | }, |
105 | }; |
106 | module_platform_driver(stm32_lptim_trigger_driver); |
107 | |
108 | MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>" ); |
109 | MODULE_ALIAS("platform:stm32-lptimer-trigger" ); |
110 | MODULE_DESCRIPTION("STMicroelectronics STM32 LPTIM trigger driver" ); |
111 | MODULE_LICENSE("GPL v2" ); |
112 | |