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