1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * pps-gpio.c -- PPS client driver using GPIO
5 * Copyright (C) 2010 Ricardo Martins <rasm@fe.up.pt>
6 * Copyright (C) 2011 James Nuss <jamesnuss@nanometrics.ca>
9 #define PPS_GPIO_NAME "pps-gpio"
10 #define pr_fmt(fmt) PPS_GPIO_NAME ": " fmt
12 #include <linux/init.h>
13 #include <linux/kernel.h>
14 #include <linux/interrupt.h>
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/slab.h>
18 #include <linux/pps_kernel.h>
19 #include <linux/pps-gpio.h>
20 #include <linux/gpio/consumer.h>
21 #include <linux/list.h>
22 #include <linux/of_device.h>
23 #include <linux/of_gpio.h>
24 #include <linux/timer.h>
25 #include <linux/jiffies.h>
27 /* Info for each registered platform device */
28 struct pps_gpio_device_data
{
29 int irq
; /* IRQ used as PPS source */
30 struct pps_device
*pps
; /* PPS source device */
31 struct pps_source_info info
; /* PPS source information */
32 struct gpio_desc
*gpio_pin
; /* GPIO port descriptors */
33 struct gpio_desc
*echo_pin
;
34 struct timer_list echo_timer
; /* timer to reset echo active state */
35 bool assert_falling_edge
;
37 unsigned int echo_active_ms
; /* PPS echo active duration */
38 unsigned long echo_timeout
; /* timer timeout value in jiffies */
42 * Report the PPS event
45 static irqreturn_t
pps_gpio_irq_handler(int irq
, void *data
)
47 const struct pps_gpio_device_data
*info
;
48 struct pps_event_time ts
;
51 /* Get the time stamp first */
56 rising_edge
= gpiod_get_value(info
->gpio_pin
);
57 if ((rising_edge
&& !info
->assert_falling_edge
) ||
58 (!rising_edge
&& info
->assert_falling_edge
))
59 pps_event(info
->pps
, &ts
, PPS_CAPTUREASSERT
, data
);
60 else if (info
->capture_clear
&&
61 ((rising_edge
&& info
->assert_falling_edge
) ||
62 (!rising_edge
&& !info
->assert_falling_edge
)))
63 pps_event(info
->pps
, &ts
, PPS_CAPTURECLEAR
, data
);
68 /* This function will only be called when an ECHO GPIO is defined */
69 static void pps_gpio_echo(struct pps_device
*pps
, int event
, void *data
)
71 /* add_timer() needs to write into info->echo_timer */
72 struct pps_gpio_device_data
*info
= data
;
75 case PPS_CAPTUREASSERT
:
76 if (pps
->params
.mode
& PPS_ECHOASSERT
)
77 gpiod_set_value(info
->echo_pin
, 1);
80 case PPS_CAPTURECLEAR
:
81 if (pps
->params
.mode
& PPS_ECHOCLEAR
)
82 gpiod_set_value(info
->echo_pin
, 1);
87 if (info
->pps
->params
.mode
& (PPS_ECHOASSERT
| PPS_ECHOCLEAR
)) {
88 info
->echo_timer
.expires
= jiffies
+ info
->echo_timeout
;
89 add_timer(&info
->echo_timer
);
93 /* Timer callback to reset the echo pin to the inactive state */
94 static void pps_gpio_echo_timer_callback(struct timer_list
*t
)
96 const struct pps_gpio_device_data
*info
;
98 info
= from_timer(info
, t
, echo_timer
);
100 gpiod_set_value(info
->echo_pin
, 0);
103 static int pps_gpio_setup(struct platform_device
*pdev
)
105 struct pps_gpio_device_data
*data
= platform_get_drvdata(pdev
);
106 struct device_node
*np
= pdev
->dev
.of_node
;
110 data
->gpio_pin
= devm_gpiod_get(&pdev
->dev
,
111 NULL
, /* request "gpios" */
113 if (IS_ERR(data
->gpio_pin
)) {
115 "failed to request PPS GPIO\n");
116 return PTR_ERR(data
->gpio_pin
);
119 data
->echo_pin
= devm_gpiod_get_optional(&pdev
->dev
,
122 if (data
->echo_pin
) {
123 if (IS_ERR(data
->echo_pin
)) {
124 dev_err(&pdev
->dev
, "failed to request ECHO GPIO\n");
125 return PTR_ERR(data
->echo_pin
);
128 ret
= of_property_read_u32(np
,
133 "failed to get echo-active-ms from OF\n");
136 data
->echo_active_ms
= value
;
137 /* sanity check on echo_active_ms */
138 if (!data
->echo_active_ms
|| data
->echo_active_ms
> 999) {
140 "echo-active-ms: %u - bad value from OF\n",
141 data
->echo_active_ms
);
146 if (of_property_read_bool(np
, "assert-falling-edge"))
147 data
->assert_falling_edge
= true;
152 get_irqf_trigger_flags(const struct pps_gpio_device_data
*data
)
154 unsigned long flags
= data
->assert_falling_edge
?
155 IRQF_TRIGGER_FALLING
: IRQF_TRIGGER_RISING
;
157 if (data
->capture_clear
) {
158 flags
|= ((flags
& IRQF_TRIGGER_RISING
) ?
159 IRQF_TRIGGER_FALLING
: IRQF_TRIGGER_RISING
);
165 static int pps_gpio_probe(struct platform_device
*pdev
)
167 struct pps_gpio_device_data
*data
;
169 int pps_default_params
;
170 const struct pps_gpio_platform_data
*pdata
= pdev
->dev
.platform_data
;
172 /* allocate space for device info */
173 data
= devm_kzalloc(&pdev
->dev
, sizeof(*data
), GFP_KERNEL
);
176 platform_set_drvdata(pdev
, data
);
180 data
->gpio_pin
= pdata
->gpio_pin
;
181 data
->echo_pin
= pdata
->echo_pin
;
183 data
->assert_falling_edge
= pdata
->assert_falling_edge
;
184 data
->capture_clear
= pdata
->capture_clear
;
185 data
->echo_active_ms
= pdata
->echo_active_ms
;
187 ret
= pps_gpio_setup(pdev
);
193 ret
= gpiod_to_irq(data
->gpio_pin
);
195 dev_err(&pdev
->dev
, "failed to map GPIO to IRQ: %d\n", ret
);
200 /* initialize PPS specific parts of the bookkeeping data structure. */
201 data
->info
.mode
= PPS_CAPTUREASSERT
| PPS_OFFSETASSERT
|
202 PPS_ECHOASSERT
| PPS_CANWAIT
| PPS_TSFMT_TSPEC
;
203 if (data
->capture_clear
)
204 data
->info
.mode
|= PPS_CAPTURECLEAR
| PPS_OFFSETCLEAR
|
206 data
->info
.owner
= THIS_MODULE
;
207 snprintf(data
->info
.name
, PPS_MAX_NAME_LEN
- 1, "%s.%d",
208 pdev
->name
, pdev
->id
);
209 if (data
->echo_pin
) {
210 data
->info
.echo
= pps_gpio_echo
;
211 data
->echo_timeout
= msecs_to_jiffies(data
->echo_active_ms
);
212 timer_setup(&data
->echo_timer
, pps_gpio_echo_timer_callback
, 0);
215 /* register PPS source */
216 pps_default_params
= PPS_CAPTUREASSERT
| PPS_OFFSETASSERT
;
217 if (data
->capture_clear
)
218 pps_default_params
|= PPS_CAPTURECLEAR
| PPS_OFFSETCLEAR
;
219 data
->pps
= pps_register_source(&data
->info
, pps_default_params
);
220 if (IS_ERR(data
->pps
)) {
221 dev_err(&pdev
->dev
, "failed to register IRQ %d as PPS source\n",
223 return PTR_ERR(data
->pps
);
226 /* register IRQ interrupt handler */
227 ret
= devm_request_irq(&pdev
->dev
, data
->irq
, pps_gpio_irq_handler
,
228 get_irqf_trigger_flags(data
), data
->info
.name
, data
);
230 pps_unregister_source(data
->pps
);
231 dev_err(&pdev
->dev
, "failed to acquire IRQ %d\n", data
->irq
);
235 dev_info(data
->pps
->dev
, "Registered IRQ %d as PPS source\n",
241 static int pps_gpio_remove(struct platform_device
*pdev
)
243 struct pps_gpio_device_data
*data
= platform_get_drvdata(pdev
);
245 pps_unregister_source(data
->pps
);
246 if (data
->echo_pin
) {
247 del_timer_sync(&data
->echo_timer
);
248 /* reset echo pin in any case */
249 gpiod_set_value(data
->echo_pin
, 0);
251 dev_info(&pdev
->dev
, "removed IRQ %d as PPS source\n", data
->irq
);
255 static const struct of_device_id pps_gpio_dt_ids
[] = {
256 { .compatible
= "pps-gpio", },
259 MODULE_DEVICE_TABLE(of
, pps_gpio_dt_ids
);
261 static struct platform_driver pps_gpio_driver
= {
262 .probe
= pps_gpio_probe
,
263 .remove
= pps_gpio_remove
,
265 .name
= PPS_GPIO_NAME
,
266 .of_match_table
= pps_gpio_dt_ids
,
270 module_platform_driver(pps_gpio_driver
);
271 MODULE_AUTHOR("Ricardo Martins <rasm@fe.up.pt>");
272 MODULE_AUTHOR("James Nuss <jamesnuss@nanometrics.ca>");
273 MODULE_DESCRIPTION("Use GPIO pin as PPS source");
274 MODULE_LICENSE("GPL");
275 MODULE_VERSION("1.2.0");