xref: /OK3568_Linux_fs/kernel/drivers/pps/clients/pps-gpio.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * pps-gpio.c -- PPS client driver using GPIO
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2010 Ricardo Martins <rasm@fe.up.pt>
6*4882a593Smuzhiyun  * Copyright (C) 2011 James Nuss <jamesnuss@nanometrics.ca>
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #define PPS_GPIO_NAME "pps-gpio"
10*4882a593Smuzhiyun #define pr_fmt(fmt) PPS_GPIO_NAME ": " fmt
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include <linux/init.h>
13*4882a593Smuzhiyun #include <linux/kernel.h>
14*4882a593Smuzhiyun #include <linux/interrupt.h>
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/platform_device.h>
17*4882a593Smuzhiyun #include <linux/slab.h>
18*4882a593Smuzhiyun #include <linux/pps_kernel.h>
19*4882a593Smuzhiyun #include <linux/pps-gpio.h>
20*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
21*4882a593Smuzhiyun #include <linux/list.h>
22*4882a593Smuzhiyun #include <linux/of_device.h>
23*4882a593Smuzhiyun #include <linux/of_gpio.h>
24*4882a593Smuzhiyun #include <linux/timer.h>
25*4882a593Smuzhiyun #include <linux/jiffies.h>
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun /* Info for each registered platform device */
28*4882a593Smuzhiyun struct pps_gpio_device_data {
29*4882a593Smuzhiyun 	int irq;			/* IRQ used as PPS source */
30*4882a593Smuzhiyun 	struct pps_device *pps;		/* PPS source device */
31*4882a593Smuzhiyun 	struct pps_source_info info;	/* PPS source information */
32*4882a593Smuzhiyun 	struct gpio_desc *gpio_pin;	/* GPIO port descriptors */
33*4882a593Smuzhiyun 	struct gpio_desc *echo_pin;
34*4882a593Smuzhiyun 	struct timer_list echo_timer;	/* timer to reset echo active state */
35*4882a593Smuzhiyun 	bool assert_falling_edge;
36*4882a593Smuzhiyun 	bool capture_clear;
37*4882a593Smuzhiyun 	unsigned int echo_active_ms;	/* PPS echo active duration */
38*4882a593Smuzhiyun 	unsigned long echo_timeout;	/* timer timeout value in jiffies */
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun /*
42*4882a593Smuzhiyun  * Report the PPS event
43*4882a593Smuzhiyun  */
44*4882a593Smuzhiyun 
pps_gpio_irq_handler(int irq,void * data)45*4882a593Smuzhiyun static irqreturn_t pps_gpio_irq_handler(int irq, void *data)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun 	const struct pps_gpio_device_data *info;
48*4882a593Smuzhiyun 	struct pps_event_time ts;
49*4882a593Smuzhiyun 	int rising_edge;
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	/* Get the time stamp first */
52*4882a593Smuzhiyun 	pps_get_ts(&ts);
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	info = data;
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	rising_edge = gpiod_get_value(info->gpio_pin);
57*4882a593Smuzhiyun 	if ((rising_edge && !info->assert_falling_edge) ||
58*4882a593Smuzhiyun 			(!rising_edge && info->assert_falling_edge))
59*4882a593Smuzhiyun 		pps_event(info->pps, &ts, PPS_CAPTUREASSERT, data);
60*4882a593Smuzhiyun 	else if (info->capture_clear &&
61*4882a593Smuzhiyun 			((rising_edge && info->assert_falling_edge) ||
62*4882a593Smuzhiyun 			(!rising_edge && !info->assert_falling_edge)))
63*4882a593Smuzhiyun 		pps_event(info->pps, &ts, PPS_CAPTURECLEAR, data);
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	return IRQ_HANDLED;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun /* This function will only be called when an ECHO GPIO is defined */
pps_gpio_echo(struct pps_device * pps,int event,void * data)69*4882a593Smuzhiyun static void pps_gpio_echo(struct pps_device *pps, int event, void *data)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun 	/* add_timer() needs to write into info->echo_timer */
72*4882a593Smuzhiyun 	struct pps_gpio_device_data *info = data;
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	switch (event) {
75*4882a593Smuzhiyun 	case PPS_CAPTUREASSERT:
76*4882a593Smuzhiyun 		if (pps->params.mode & PPS_ECHOASSERT)
77*4882a593Smuzhiyun 			gpiod_set_value(info->echo_pin, 1);
78*4882a593Smuzhiyun 		break;
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	case PPS_CAPTURECLEAR:
81*4882a593Smuzhiyun 		if (pps->params.mode & PPS_ECHOCLEAR)
82*4882a593Smuzhiyun 			gpiod_set_value(info->echo_pin, 1);
83*4882a593Smuzhiyun 		break;
84*4882a593Smuzhiyun 	}
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	/* fire the timer */
87*4882a593Smuzhiyun 	if (info->pps->params.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) {
88*4882a593Smuzhiyun 		info->echo_timer.expires = jiffies + info->echo_timeout;
89*4882a593Smuzhiyun 		add_timer(&info->echo_timer);
90*4882a593Smuzhiyun 	}
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun /* Timer callback to reset the echo pin to the inactive state */
pps_gpio_echo_timer_callback(struct timer_list * t)94*4882a593Smuzhiyun static void pps_gpio_echo_timer_callback(struct timer_list *t)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	const struct pps_gpio_device_data *info;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	info = from_timer(info, t, echo_timer);
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 	gpiod_set_value(info->echo_pin, 0);
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun 
pps_gpio_setup(struct platform_device * pdev)103*4882a593Smuzhiyun static int pps_gpio_setup(struct platform_device *pdev)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun 	struct pps_gpio_device_data *data = platform_get_drvdata(pdev);
106*4882a593Smuzhiyun 	struct device_node *np = pdev->dev.of_node;
107*4882a593Smuzhiyun 	int ret;
108*4882a593Smuzhiyun 	u32 value;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	data->gpio_pin = devm_gpiod_get(&pdev->dev,
111*4882a593Smuzhiyun 		NULL,	/* request "gpios" */
112*4882a593Smuzhiyun 		GPIOD_IN);
113*4882a593Smuzhiyun 	if (IS_ERR(data->gpio_pin)) {
114*4882a593Smuzhiyun 		dev_err(&pdev->dev,
115*4882a593Smuzhiyun 			"failed to request PPS GPIO\n");
116*4882a593Smuzhiyun 		return PTR_ERR(data->gpio_pin);
117*4882a593Smuzhiyun 	}
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	data->echo_pin = devm_gpiod_get_optional(&pdev->dev,
120*4882a593Smuzhiyun 			"echo",
121*4882a593Smuzhiyun 			GPIOD_OUT_LOW);
122*4882a593Smuzhiyun 	if (data->echo_pin) {
123*4882a593Smuzhiyun 		if (IS_ERR(data->echo_pin)) {
124*4882a593Smuzhiyun 			dev_err(&pdev->dev, "failed to request ECHO GPIO\n");
125*4882a593Smuzhiyun 			return PTR_ERR(data->echo_pin);
126*4882a593Smuzhiyun 		}
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 		ret = of_property_read_u32(np,
129*4882a593Smuzhiyun 			"echo-active-ms",
130*4882a593Smuzhiyun 			&value);
131*4882a593Smuzhiyun 		if (ret) {
132*4882a593Smuzhiyun 			dev_err(&pdev->dev,
133*4882a593Smuzhiyun 				"failed to get echo-active-ms from OF\n");
134*4882a593Smuzhiyun 			return ret;
135*4882a593Smuzhiyun 		}
136*4882a593Smuzhiyun 		data->echo_active_ms = value;
137*4882a593Smuzhiyun 		/* sanity check on echo_active_ms */
138*4882a593Smuzhiyun 		if (!data->echo_active_ms || data->echo_active_ms > 999) {
139*4882a593Smuzhiyun 			dev_err(&pdev->dev,
140*4882a593Smuzhiyun 				"echo-active-ms: %u - bad value from OF\n",
141*4882a593Smuzhiyun 				data->echo_active_ms);
142*4882a593Smuzhiyun 			return -EINVAL;
143*4882a593Smuzhiyun 		}
144*4882a593Smuzhiyun 	}
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	if (of_property_read_bool(np, "assert-falling-edge"))
147*4882a593Smuzhiyun 		data->assert_falling_edge = true;
148*4882a593Smuzhiyun 	return 0;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun static unsigned long
get_irqf_trigger_flags(const struct pps_gpio_device_data * data)152*4882a593Smuzhiyun get_irqf_trigger_flags(const struct pps_gpio_device_data *data)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun 	unsigned long flags = data->assert_falling_edge ?
155*4882a593Smuzhiyun 		IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	if (data->capture_clear) {
158*4882a593Smuzhiyun 		flags |= ((flags & IRQF_TRIGGER_RISING) ?
159*4882a593Smuzhiyun 				IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING);
160*4882a593Smuzhiyun 	}
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	return flags;
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun 
pps_gpio_probe(struct platform_device * pdev)165*4882a593Smuzhiyun static int pps_gpio_probe(struct platform_device *pdev)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun 	struct pps_gpio_device_data *data;
168*4882a593Smuzhiyun 	int ret;
169*4882a593Smuzhiyun 	int pps_default_params;
170*4882a593Smuzhiyun 	const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	/* allocate space for device info */
173*4882a593Smuzhiyun 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
174*4882a593Smuzhiyun 	if (!data)
175*4882a593Smuzhiyun 		return -ENOMEM;
176*4882a593Smuzhiyun 	platform_set_drvdata(pdev, data);
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	/* GPIO setup */
179*4882a593Smuzhiyun 	if (pdata) {
180*4882a593Smuzhiyun 		data->gpio_pin = pdata->gpio_pin;
181*4882a593Smuzhiyun 		data->echo_pin = pdata->echo_pin;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 		data->assert_falling_edge = pdata->assert_falling_edge;
184*4882a593Smuzhiyun 		data->capture_clear = pdata->capture_clear;
185*4882a593Smuzhiyun 		data->echo_active_ms = pdata->echo_active_ms;
186*4882a593Smuzhiyun 	} else {
187*4882a593Smuzhiyun 		ret = pps_gpio_setup(pdev);
188*4882a593Smuzhiyun 		if (ret)
189*4882a593Smuzhiyun 			return -EINVAL;
190*4882a593Smuzhiyun 	}
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	/* IRQ setup */
193*4882a593Smuzhiyun 	ret = gpiod_to_irq(data->gpio_pin);
194*4882a593Smuzhiyun 	if (ret < 0) {
195*4882a593Smuzhiyun 		dev_err(&pdev->dev, "failed to map GPIO to IRQ: %d\n", ret);
196*4882a593Smuzhiyun 		return -EINVAL;
197*4882a593Smuzhiyun 	}
198*4882a593Smuzhiyun 	data->irq = ret;
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	/* initialize PPS specific parts of the bookkeeping data structure. */
201*4882a593Smuzhiyun 	data->info.mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT |
202*4882a593Smuzhiyun 		PPS_ECHOASSERT | PPS_CANWAIT | PPS_TSFMT_TSPEC;
203*4882a593Smuzhiyun 	if (data->capture_clear)
204*4882a593Smuzhiyun 		data->info.mode |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR |
205*4882a593Smuzhiyun 			PPS_ECHOCLEAR;
206*4882a593Smuzhiyun 	data->info.owner = THIS_MODULE;
207*4882a593Smuzhiyun 	snprintf(data->info.name, PPS_MAX_NAME_LEN - 1, "%s.%d",
208*4882a593Smuzhiyun 		 pdev->name, pdev->id);
209*4882a593Smuzhiyun 	if (data->echo_pin) {
210*4882a593Smuzhiyun 		data->info.echo = pps_gpio_echo;
211*4882a593Smuzhiyun 		data->echo_timeout = msecs_to_jiffies(data->echo_active_ms);
212*4882a593Smuzhiyun 		timer_setup(&data->echo_timer, pps_gpio_echo_timer_callback, 0);
213*4882a593Smuzhiyun 	}
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	/* register PPS source */
216*4882a593Smuzhiyun 	pps_default_params = PPS_CAPTUREASSERT | PPS_OFFSETASSERT;
217*4882a593Smuzhiyun 	if (data->capture_clear)
218*4882a593Smuzhiyun 		pps_default_params |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR;
219*4882a593Smuzhiyun 	data->pps = pps_register_source(&data->info, pps_default_params);
220*4882a593Smuzhiyun 	if (IS_ERR(data->pps)) {
221*4882a593Smuzhiyun 		dev_err(&pdev->dev, "failed to register IRQ %d as PPS source\n",
222*4882a593Smuzhiyun 			data->irq);
223*4882a593Smuzhiyun 		return PTR_ERR(data->pps);
224*4882a593Smuzhiyun 	}
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	/* register IRQ interrupt handler */
227*4882a593Smuzhiyun 	ret = devm_request_irq(&pdev->dev, data->irq, pps_gpio_irq_handler,
228*4882a593Smuzhiyun 			get_irqf_trigger_flags(data), data->info.name, data);
229*4882a593Smuzhiyun 	if (ret) {
230*4882a593Smuzhiyun 		pps_unregister_source(data->pps);
231*4882a593Smuzhiyun 		dev_err(&pdev->dev, "failed to acquire IRQ %d\n", data->irq);
232*4882a593Smuzhiyun 		return -EINVAL;
233*4882a593Smuzhiyun 	}
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	dev_info(data->pps->dev, "Registered IRQ %d as PPS source\n",
236*4882a593Smuzhiyun 		 data->irq);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	return 0;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun 
pps_gpio_remove(struct platform_device * pdev)241*4882a593Smuzhiyun static int pps_gpio_remove(struct platform_device *pdev)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	struct pps_gpio_device_data *data = platform_get_drvdata(pdev);
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	pps_unregister_source(data->pps);
246*4882a593Smuzhiyun 	if (data->echo_pin) {
247*4882a593Smuzhiyun 		del_timer_sync(&data->echo_timer);
248*4882a593Smuzhiyun 		/* reset echo pin in any case */
249*4882a593Smuzhiyun 		gpiod_set_value(data->echo_pin, 0);
250*4882a593Smuzhiyun 	}
251*4882a593Smuzhiyun 	dev_info(&pdev->dev, "removed IRQ %d as PPS source\n", data->irq);
252*4882a593Smuzhiyun 	return 0;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun static const struct of_device_id pps_gpio_dt_ids[] = {
256*4882a593Smuzhiyun 	{ .compatible = "pps-gpio", },
257*4882a593Smuzhiyun 	{ /* sentinel */ }
258*4882a593Smuzhiyun };
259*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, pps_gpio_dt_ids);
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun static struct platform_driver pps_gpio_driver = {
262*4882a593Smuzhiyun 	.probe		= pps_gpio_probe,
263*4882a593Smuzhiyun 	.remove		= pps_gpio_remove,
264*4882a593Smuzhiyun 	.driver		= {
265*4882a593Smuzhiyun 		.name	= PPS_GPIO_NAME,
266*4882a593Smuzhiyun 		.of_match_table	= pps_gpio_dt_ids,
267*4882a593Smuzhiyun 	},
268*4882a593Smuzhiyun };
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun module_platform_driver(pps_gpio_driver);
271*4882a593Smuzhiyun MODULE_AUTHOR("Ricardo Martins <rasm@fe.up.pt>");
272*4882a593Smuzhiyun MODULE_AUTHOR("James Nuss <jamesnuss@nanometrics.ca>");
273*4882a593Smuzhiyun MODULE_DESCRIPTION("Use GPIO pin as PPS source");
274*4882a593Smuzhiyun MODULE_LICENSE("GPL");
275*4882a593Smuzhiyun MODULE_VERSION("1.2.0");
276