History

pps: pps-gpio PPS ECHO implementation

This patch implements the PPS ECHO functionality for pps-gpio, that sysfs claims is available already. Configuration is done via device tree bindings. No changes are made to userspace interfaces. This patch was originally written by Lukas Senger as part of a masters thesis project and modified for inclusion into the linux kernel by Tom Burkart.

Tom Burkart committed 7 years ago

Commit 4c69add1 parent 652e2212 files · +87 −3Browse files

Unified · Split

2 files
  1. drivers/pps/clients/pps-gpio.c +85 −3
  2. include/linux/pps-gpio.h +2 −0
drivers/pps/clients/pps-gpio.c+85−3
@@ -35,6 +35,8 @@ · 34 unmodified lines
3535 #include <linux/list.h>
3636 #include <linux/of_device.h>
3737 #include <linux/of_gpio.h>
38+#include <linux/timer.h>
39+#include <linux/jiffies.h>
3840
3941 /* Info for each registered platform device */
4042 struct pps_gpio_device_data {
@@ -42,8 +44,12 @@ struct pps_gpio_device_data { · 1 unmodified line
4244 struct pps_device *pps; /* PPS source device */
4345 struct pps_source_info info; /* PPS source information */
4446 struct gpio_desc *gpio_pin; /* GPIO port descriptors */
47+ struct gpio_desc *echo_pin;
48+ struct timer_list echo_timer; /* timer to reset echo active state */
4549 bool assert_falling_edge;
4650 bool capture_clear;
51+ unsigned int echo_active_ms; /* PPS echo active duration */
52+ unsigned long echo_timeout; /* timer timeout value in jiffies */
4753 };
4854
4955 /*
@@ -64,19 +70,56 @@ static irqreturn_t pps_gpio_irq_handler(int irq, void *data) · 14 unmodified lines
6470 rising_edge = gpiod_get_value(info->gpio_pin);
6571 if ((rising_edge && !info->assert_falling_edge) ||
6672 (!rising_edge && info->assert_falling_edge))
67− pps_event(info->pps, &ts, PPS_CAPTUREASSERT, NULL);
73+ pps_event(info->pps, &ts, PPS_CAPTUREASSERT, data);
6874 else if (info->capture_clear &&
6975 ((rising_edge && info->assert_falling_edge) ||
7076 (!rising_edge && !info->assert_falling_edge)))
71− pps_event(info->pps, &ts, PPS_CAPTURECLEAR, NULL);
77+ pps_event(info->pps, &ts, PPS_CAPTURECLEAR, data);
7278
7379 return IRQ_HANDLED;
7480 }
7581
82+/* This function will only be called when an ECHO GPIO is defined */
83+static void pps_gpio_echo(struct pps_device *pps, int event, void *data)
84+{
85+ /* add_timer() needs to write into info->echo_timer */
86+ struct pps_gpio_device_data *info = data;
87+
88+ switch (event) {
89+ case PPS_CAPTUREASSERT:
90+ if (pps->params.mode & PPS_ECHOASSERT)
91+ gpiod_set_value(info->echo_pin, 1);
92+ break;
93+
94+ case PPS_CAPTURECLEAR:
95+ if (pps->params.mode & PPS_ECHOCLEAR)
96+ gpiod_set_value(info->echo_pin, 1);
97+ break;
98+ }
99+
100+ /* fire the timer */
101+ if (info->pps->params.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) {
102+ info->echo_timer.expires = jiffies + info->echo_timeout;
103+ add_timer(&info->echo_timer);
104+ }
105+}
106+
107+/* Timer callback to reset the echo pin to the inactive state */
108+static void pps_gpio_echo_timer_callback(struct timer_list *t)
109+{
110+ const struct pps_gpio_device_data *info;
111+
112+ info = from_timer(info, t, echo_timer);
113+
114+ gpiod_set_value(info->echo_pin, 0);
115+}
116+
76117 static int pps_gpio_setup(struct platform_device *pdev)
77118 {
78119 struct pps_gpio_device_data *data = platform_get_drvdata(pdev);
79120 struct device_node *np = pdev->dev.of_node;
121+ int ret;
122+ u32 value;
80123
81124 data->gpio_pin = devm_gpiod_get(&pdev->dev,
82125 NULL, /* request "gpios" */
@@ -87,6 +130,33 @@ static int pps_gpio_setup(struct platform_device *pdev) · 4 unmodified lines
87130 return PTR_ERR(data->gpio_pin);
88131 }
89132
133+ data->echo_pin = devm_gpiod_get_optional(&pdev->dev,
134+ "echo",
135+ GPIOD_OUT_LOW);
136+ if (data->echo_pin) {
137+ if (IS_ERR(data->echo_pin)) {
138+ dev_err(&pdev->dev, "failed to request ECHO GPIO\n");
139+ return PTR_ERR(data->echo_pin);
140+ }
141+
142+ ret = of_property_read_u32(np,
143+ "echo-active-ms",
144+ &value);
145+ if (ret) {
146+ dev_err(&pdev->dev,
147+ "failed to get echo-active-ms from OF\n");
148+ return ret;
149+ }
150+ data->echo_active_ms = value;
151+ /* sanity check on echo_active_ms */
152+ if (!data->echo_active_ms || data->echo_active_ms > 999) {
153+ dev_err(&pdev->dev,
154+ "echo-active-ms: %u - bad value from OF\n",
155+ data->echo_active_ms);
156+ return -EINVAL;
157+ }
158+ }
159+
90160 if (of_property_read_bool(np, "assert-falling-edge"))
91161 data->assert_falling_edge = true;
92162 return 0;
@@ -122,9 +192,11 @@ static int pps_gpio_probe(struct platform_device *pdev) · 29 unmodified lines
122192 /* GPIO setup */
123193 if (pdata) {
124194 data->gpio_pin = pdata->gpio_pin;
195+ data->echo_pin = pdata->echo_pin;
125196
126197 data->assert_falling_edge = pdata->assert_falling_edge;
127198 data->capture_clear = pdata->capture_clear;
199+ data->echo_active_ms = pdata->echo_active_ms;
128200 } else {
129201 ret = pps_gpio_setup(pdev);
130202 if (ret)
@@ -148,6 +220,11 @@ static int pps_gpio_probe(struct platform_device *pdev) · 17 unmodified lines
148220 data->info.owner = THIS_MODULE;
149221 snprintf(data->info.name, PPS_MAX_NAME_LEN - 1, "%s.%d",
150222 pdev->name, pdev->id);
223+ if (data->echo_pin) {
224+ data->info.echo = pps_gpio_echo;
225+ data->echo_timeout = msecs_to_jiffies(data->echo_active_ms);
226+ timer_setup(&data->echo_timer, pps_gpio_echo_timer_callback, 0);
227+ }
151228
152229 /* register PPS source */
153230 pps_default_params = PPS_CAPTUREASSERT | PPS_OFFSETASSERT;
@@ -180,6 +257,11 @@ static int pps_gpio_remove(struct platform_device *pdev) · 26 unmodified lines
180257 struct pps_gpio_device_data *data = platform_get_drvdata(pdev);
181258
182259 pps_unregister_source(data->pps);
260+ if (data->echo_pin) {
261+ del_timer_sync(&data->echo_timer);
262+ /* reset echo pin in any case */
263+ gpiod_set_value(data->echo_pin, 0);
264+ }
183265 dev_info(&pdev->dev, "removed IRQ %d as PPS source\n", data->irq);
184266 return 0;
185267 }
@@ -204,4 +286,4 @@ MODULE_AUTHOR("Ricardo Martins <rasm@fe.up.pt>"); · 18 unmodified lines
204286 MODULE_AUTHOR("James Nuss <jamesnuss@nanometrics.ca>");
205287 MODULE_DESCRIPTION("Use GPIO pin as PPS source");
206288 MODULE_LICENSE("GPL");
207−MODULE_VERSION("1.1.0");
289+MODULE_VERSION("1.2.0");
include/linux/pps-gpio.h+2−0
@@ -24,8 +24,10 @@ · 23 unmodified lines
2424
2525 struct pps_gpio_platform_data {
2626 struct gpio_desc *gpio_pin;
27+ struct gpio_desc *echo_pin;
2728 bool assert_falling_edge;
2829 bool capture_clear;
30+ unsigned int echo_active_ms;
2931 };
3032
3133 #endif /* _PPS_GPIO_H */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t