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/mod_devicetable.h>
16 #include <linux/module.h>
17 #include <linux/platform_device.h>
18 #include <linux/slab.h>
19 #include <linux/pps_kernel.h>
20 #include <linux/gpio/consumer.h>
21 #include <linux/list.h>
22 #include <linux/property.h>
23 #include <linux/timer.h>
24 #include <linux/jiffies.h>
26 /* Info for each registered platform device */
27 struct pps_gpio_device_data
{
28 int irq
; /* IRQ used as PPS source */
29 struct pps_device
*pps
; /* PPS source device */
30 struct pps_source_info info
; /* PPS source information */
31 struct gpio_desc
*gpio_pin
; /* GPIO port descriptors */
32 struct gpio_desc
*echo_pin
;
33 struct timer_list echo_timer
; /* timer to reset echo active state */
34 bool assert_falling_edge
;
36 unsigned int echo_active_ms
; /* PPS echo active duration */
37 unsigned long echo_timeout
; /* timer timeout value in jiffies */
41 * Report the PPS event
44 static irqreturn_t
pps_gpio_irq_handler(int irq
, void *data
)
46 const struct pps_gpio_device_data
*info
;
47 struct pps_event_time ts
;
50 /* Get the time stamp first */
55 rising_edge
= gpiod_get_value(info
->gpio_pin
);
56 if ((rising_edge
&& !info
->assert_falling_edge
) ||
57 (!rising_edge
&& info
->assert_falling_edge
))
58 pps_event(info
->pps
, &ts
, PPS_CAPTUREASSERT
, data
);
59 else if (info
->capture_clear
&&
60 ((rising_edge
&& info
->assert_falling_edge
) ||
61 (!rising_edge
&& !info
->assert_falling_edge
)))
62 pps_event(info
->pps
, &ts
, PPS_CAPTURECLEAR
, data
);
67 /* This function will only be called when an ECHO GPIO is defined */
68 static void pps_gpio_echo(struct pps_device
*pps
, int event
, void *data
)
70 /* add_timer() needs to write into info->echo_timer */
71 struct pps_gpio_device_data
*info
= data
;
74 case PPS_CAPTUREASSERT
:
75 if (pps
->params
.mode
& PPS_ECHOASSERT
)
76 gpiod_set_value(info
->echo_pin
, 1);
79 case PPS_CAPTURECLEAR
:
80 if (pps
->params
.mode
& PPS_ECHOCLEAR
)
81 gpiod_set_value(info
->echo_pin
, 1);
86 if (info
->pps
->params
.mode
& (PPS_ECHOASSERT
| PPS_ECHOCLEAR
)) {
87 info
->echo_timer
.expires
= jiffies
+ info
->echo_timeout
;
88 add_timer(&info
->echo_timer
);
92 /* Timer callback to reset the echo pin to the inactive state */
93 static void pps_gpio_echo_timer_callback(struct timer_list
*t
)
95 const struct pps_gpio_device_data
*info
;
97 info
= from_timer(info
, t
, echo_timer
);
99 gpiod_set_value(info
->echo_pin
, 0);
102 static int pps_gpio_setup(struct device
*dev
)
104 struct pps_gpio_device_data
*data
= dev_get_drvdata(dev
);
108 data
->gpio_pin
= devm_gpiod_get(dev
, NULL
, GPIOD_IN
);
109 if (IS_ERR(data
->gpio_pin
))
110 return dev_err_probe(dev
, PTR_ERR(data
->gpio_pin
),
111 "failed to request PPS GPIO\n");
113 data
->assert_falling_edge
=
114 device_property_read_bool(dev
, "assert-falling-edge");
116 data
->echo_pin
= devm_gpiod_get_optional(dev
, "echo", GPIOD_OUT_LOW
);
117 if (IS_ERR(data
->echo_pin
))
118 return dev_err_probe(dev
, PTR_ERR(data
->echo_pin
),
119 "failed to request ECHO GPIO\n");
124 ret
= device_property_read_u32(dev
, "echo-active-ms", &value
);
126 dev_err(dev
, "failed to get echo-active-ms from FW\n");
130 /* sanity check on echo_active_ms */
131 if (!value
|| value
> 999) {
132 dev_err(dev
, "echo-active-ms: %u - bad value from FW\n", value
);
136 data
->echo_active_ms
= value
;
142 get_irqf_trigger_flags(const struct pps_gpio_device_data
*data
)
144 unsigned long flags
= data
->assert_falling_edge
?
145 IRQF_TRIGGER_FALLING
: IRQF_TRIGGER_RISING
;
147 if (data
->capture_clear
) {
148 flags
|= ((flags
& IRQF_TRIGGER_RISING
) ?
149 IRQF_TRIGGER_FALLING
: IRQF_TRIGGER_RISING
);
155 static int pps_gpio_probe(struct platform_device
*pdev
)
157 struct pps_gpio_device_data
*data
;
158 struct device
*dev
= &pdev
->dev
;
160 int pps_default_params
;
162 /* allocate space for device info */
163 data
= devm_kzalloc(dev
, sizeof(*data
), GFP_KERNEL
);
167 dev_set_drvdata(dev
, data
);
170 ret
= pps_gpio_setup(dev
);
175 ret
= gpiod_to_irq(data
->gpio_pin
);
177 dev_err(dev
, "failed to map GPIO to IRQ: %d\n", ret
);
182 /* initialize PPS specific parts of the bookkeeping data structure. */
183 data
->info
.mode
= PPS_CAPTUREASSERT
| PPS_OFFSETASSERT
|
184 PPS_ECHOASSERT
| PPS_CANWAIT
| PPS_TSFMT_TSPEC
;
185 if (data
->capture_clear
)
186 data
->info
.mode
|= PPS_CAPTURECLEAR
| PPS_OFFSETCLEAR
|
188 data
->info
.owner
= THIS_MODULE
;
189 snprintf(data
->info
.name
, PPS_MAX_NAME_LEN
- 1, "%s.%d",
190 pdev
->name
, pdev
->id
);
191 if (data
->echo_pin
) {
192 data
->info
.echo
= pps_gpio_echo
;
193 data
->echo_timeout
= msecs_to_jiffies(data
->echo_active_ms
);
194 timer_setup(&data
->echo_timer
, pps_gpio_echo_timer_callback
, 0);
197 /* register PPS source */
198 pps_default_params
= PPS_CAPTUREASSERT
| PPS_OFFSETASSERT
;
199 if (data
->capture_clear
)
200 pps_default_params
|= PPS_CAPTURECLEAR
| PPS_OFFSETCLEAR
;
201 data
->pps
= pps_register_source(&data
->info
, pps_default_params
);
202 if (IS_ERR(data
->pps
)) {
203 dev_err(dev
, "failed to register IRQ %d as PPS source\n",
205 return PTR_ERR(data
->pps
);
208 /* register IRQ interrupt handler */
209 ret
= devm_request_irq(dev
, data
->irq
, pps_gpio_irq_handler
,
210 get_irqf_trigger_flags(data
), data
->info
.name
, data
);
212 pps_unregister_source(data
->pps
);
213 dev_err(dev
, "failed to acquire IRQ %d\n", data
->irq
);
217 dev_info(data
->pps
->dev
, "Registered IRQ %d as PPS source\n",
223 static void pps_gpio_remove(struct platform_device
*pdev
)
225 struct pps_gpio_device_data
*data
= platform_get_drvdata(pdev
);
227 pps_unregister_source(data
->pps
);
228 del_timer_sync(&data
->echo_timer
);
229 /* reset echo pin in any case */
230 gpiod_set_value(data
->echo_pin
, 0);
231 dev_info(&pdev
->dev
, "removed IRQ %d as PPS source\n", data
->irq
);
234 static const struct of_device_id pps_gpio_dt_ids
[] = {
235 { .compatible
= "pps-gpio", },
238 MODULE_DEVICE_TABLE(of
, pps_gpio_dt_ids
);
240 static struct platform_driver pps_gpio_driver
= {
241 .probe
= pps_gpio_probe
,
242 .remove_new
= pps_gpio_remove
,
244 .name
= PPS_GPIO_NAME
,
245 .of_match_table
= pps_gpio_dt_ids
,
249 module_platform_driver(pps_gpio_driver
);
250 MODULE_AUTHOR("Ricardo Martins <rasm@fe.up.pt>");
251 MODULE_AUTHOR("James Nuss <jamesnuss@nanometrics.ca>");
252 MODULE_DESCRIPTION("Use GPIO pin as PPS source");
253 MODULE_LICENSE("GPL");
254 MODULE_VERSION("1.2.0");