xref: /netbsd-src/sys/dev/gpio/gpiopps.c (revision d1b93bab8c7801129a73a508d678c429e8f0fa6a)
1 /* $NetBSD: gpiopps.c,v 1.5 2023/06/24 05:34:59 msaitoh Exp $ */
2 
3 /*
4  * Copyright (c) 2016 Brad Spencer <brad@anduin.eldar.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions, and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: gpiopps.c,v 1.5 2023/06/24 05:34:59 msaitoh Exp $");
30 
31 /*
32  * GPIO interface to the pps subsystem for ntp support.
33  */
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/bitops.h>
38 #include <sys/device.h>
39 #include <sys/module.h>
40 #include <sys/conf.h>
41 #include <sys/proc.h>
42 #include <sys/ioctl.h>
43 #include <sys/timepps.h>
44 
45 #include <sys/gpio.h>
46 #include <dev/gpio/gpiovar.h>
47 
48 #define	GPIOPPS_NPINS		2
49 
50 struct gpiopps_softc {
51 	device_t		sc_dev;
52 	void *			sc_gpio;
53 	struct gpio_pinmap	sc_map;
54 	int			_map[GPIOPPS_NPINS];
55 	struct {
56 		char		sc_intrstr[128];
57 		void *		sc_ih;
58 		int		sc_irqmode;
59 	} sc_intrs[GPIOPPS_NPINS];
60 	int			sc_assert_val;
61 	int			sc_npins;
62 	struct pps_state	sc_pps_state;
63 	bool			sc_functional;
64 	bool			sc_busy;
65 };
66 
67 #define	GPIOPPS_FLAGS_ASSERT_NEG_EDGE	0x01
68 #define	GPIOPPS_FLAGS_NO_DOUBLE_EDGE	0x02
69 
70 static int	gpiopps_match(device_t, cfdata_t, void *);
71 static void	gpiopps_attach(device_t, device_t, void *);
72 static int	gpiopps_detach(device_t, int);
73 
74 CFATTACH_DECL_NEW(gpiopps, sizeof(struct gpiopps_softc),
75 		  gpiopps_match, gpiopps_attach,
76 		  gpiopps_detach, NULL /*activate*/);
77 
78 extern struct cfdriver gpiopps_cd;
79 
80 static dev_type_open(gpioppsopen);
81 static dev_type_close(gpioppsclose);
82 static dev_type_ioctl(gpioppsioctl);
83 const struct cdevsw gpiopps_cdevsw = {
84 	.d_open = gpioppsopen,
85 	.d_close = gpioppsclose,
86 	.d_read = noread,
87 	.d_write = nowrite,
88 	.d_ioctl = gpioppsioctl,
89 	.d_stop = nostop,
90 	.d_tty = notty,
91 	.d_poll = nopoll,
92 	.d_mmap = nommap,
93 	.d_kqfilter = nokqfilter,
94 	.d_discard = nodiscard,
95 	.d_flag = D_OTHER
96 };
97 
98 static int
gpiopps_match(device_t parent,cfdata_t cf,void * aux)99 gpiopps_match(device_t parent, cfdata_t cf, void *aux)
100 {
101 	struct gpio_attach_args *ga = aux;
102 	int bits;
103 
104 	if (strcmp(ga->ga_dvname, cf->cf_name))
105 		return (0);
106 
107 	if (ga->ga_offset == -1)
108 		return (0);
109 
110 	/* One or 2 pins (unspecified, assume 1) */
111 	bits = gpio_npins(ga->ga_mask);
112 	if (bits > 2)
113 		return (0);
114 
115 	return (1);
116 }
117 
118 static void
gpiopps_attach(device_t parent,device_t self,void * aux)119 gpiopps_attach(device_t parent, device_t self, void *aux)
120 {
121 	struct gpiopps_softc *sc = device_private(self);
122 	struct gpio_attach_args *ga = aux;
123 	int flags, intrcaps, npins;
124 	int assert_edge = GPIO_INTR_POS_EDGE;
125 	int clear_edge  = GPIO_INTR_NEG_EDGE;
126 	int mask = ga->ga_mask;
127 
128 	sc->sc_dev = self;
129 	sc->sc_assert_val = GPIO_PIN_HIGH;
130 
131 	/* Map pins */
132 	sc->sc_gpio = ga->ga_gpio;
133 	sc->sc_map.pm_map = sc->_map;
134 
135 	/* Determine our pin configuration. */
136 	npins = gpio_npins(mask);
137 	if (npins == 0) {
138 		npins = 1;
139 		mask = 0x1;
140 	}
141 
142 	/*
143 	 * Here's the different pin configurations we handle:
144 	 *
145 	 * 1 pin, single-edge capable pin -- interrupt on single-edge,
146 	 * only trigger ASSERT signal.
147 	 *
148 	 * 1 pin, double-edge capable pin -- interrupt on double-edge,
149 	 * trigger ASSERT and CLEAR signals, unless 0x2 is set in ga_flags,
150 	 * in which case we degrade to ASSERT only.
151 	 *
152 	 * 2 pins -- pin #0 is ASSERT signal, pin #1 is CLEAR signal.
153 	 *
154 	 * If 0x1 is set in ga_flags, ASSERT is negative edge, otherwise
155 	 * assert is positive edge.
156 	 */
157 	if (npins < 1 || npins > 2) {
158 		aprint_error(": invalid pin configuration\n");
159 		return;
160 	}
161 	if (ga->ga_flags & GPIOPPS_FLAGS_ASSERT_NEG_EDGE) {
162 		assert_edge = GPIO_INTR_NEG_EDGE;
163 		clear_edge  = GPIO_INTR_POS_EDGE;
164 		sc->sc_assert_val = GPIO_PIN_LOW;
165 	}
166 
167 	if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, mask,
168 			 &sc->sc_map)) {
169 		aprint_error(": can't map pins\n");
170 		return;
171 	}
172 	sc->sc_npins = npins;
173 
174 	aprint_normal("\n");
175 
176 	if (sc->sc_npins == 2) {
177 		intrcaps = gpio_pin_intrcaps(sc->sc_gpio, &sc->sc_map, 0);
178 		if ((intrcaps & assert_edge) == 0) {
179 			aprint_error_dev(sc->sc_dev,
180 			    "%s edge interrupt not supported for ASSERT\n",
181 			    assert_edge == GPIO_INTR_POS_EDGE ? "positive"
182 			    				      : "negative");
183 			gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
184 			return;
185 		}
186 		sc->sc_intrs[0].sc_irqmode = assert_edge;
187 		if (!gpio_intr_str(sc->sc_gpio, &sc->sc_map, 0,
188 				   sc->sc_intrs[0].sc_irqmode,
189 				   sc->sc_intrs[0].sc_intrstr,
190 				   sizeof(sc->sc_intrs[0].sc_intrstr))) {
191 			aprint_error_dev(self,
192 			    "failed to decode ASSERT interrupt\n");
193 			gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
194 			return;
195 		}
196 		flags = gpio_pin_get_conf(sc->sc_gpio, &sc->sc_map, 0);
197 		flags = (flags & ~(GPIO_PIN_OUTPUT|GPIO_PIN_INOUT)) |
198 		    GPIO_PIN_INPUT;
199 		if (!gpio_pin_set_conf(sc->sc_gpio, &sc->sc_map, 0, flags)) {
200 			aprint_error_dev(sc->sc_dev,
201 			    "ASSERT pin not capable of input\n");
202 			gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
203 			return;
204 		}
205 
206 		intrcaps = gpio_pin_intrcaps(sc->sc_gpio, &sc->sc_map, 1);
207 		if ((intrcaps & clear_edge) == 0) {
208 			aprint_error_dev(sc->sc_dev,
209 			    "%s edge interrupt not supported for CLEAR\n",
210 			    clear_edge == GPIO_INTR_POS_EDGE ? "positive"
211 			    				     : "negative");
212 			gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
213 			return;
214 		}
215 		sc->sc_intrs[1].sc_irqmode = clear_edge;
216 		if (!gpio_intr_str(sc->sc_gpio, &sc->sc_map, 1,
217 				   sc->sc_intrs[1].sc_irqmode,
218 				   sc->sc_intrs[1].sc_intrstr,
219 				   sizeof(sc->sc_intrs[1].sc_intrstr))) {
220 			aprint_error_dev(self,
221 			    "failed to decode CLEAR interrupt\n");
222 			gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
223 			return;
224 		}
225 		flags = gpio_pin_get_conf(sc->sc_gpio, &sc->sc_map, 1);
226 		flags = (flags & ~(GPIO_PIN_OUTPUT|GPIO_PIN_INOUT)) |
227 		    GPIO_PIN_INPUT;
228 		if (!gpio_pin_set_conf(sc->sc_gpio, &sc->sc_map, 1, flags)) {
229 			aprint_error_dev(sc->sc_dev,
230 			    "CLEAR pin not capable of input\n");
231 			gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
232 			return;
233 		}
234 
235 		aprint_normal_dev(self, "ASSERT interrupting on %s\n",
236 				  sc->sc_intrs[0].sc_intrstr);
237 		aprint_normal_dev(self, "CLEAR interrupting on %s\n",
238 				  sc->sc_intrs[1].sc_intrstr);
239 	} else {
240 		intrcaps = gpio_pin_intrcaps(sc->sc_gpio, &sc->sc_map, 0);
241 		bool double_edge = false;
242 		if ((intrcaps & GPIO_INTR_DOUBLE_EDGE) &&
243 		    (ga->ga_flags & GPIOPPS_FLAGS_NO_DOUBLE_EDGE) == 0) {
244 			sc->sc_intrs[0].sc_irqmode = GPIO_INTR_DOUBLE_EDGE;
245 			double_edge = true;
246 		} else if (intrcaps & assert_edge) {
247 			sc->sc_intrs[0].sc_irqmode = assert_edge;
248 		} else {
249 			aprint_error_dev(sc->sc_dev,
250 			    "%s edge interrupt not supported for ASSERT\n",
251 			    assert_edge == GPIO_INTR_POS_EDGE ? "positive"
252 			    				      : "negative");
253 			gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
254 			return;
255 		}
256 		if (!gpio_intr_str(sc->sc_gpio, &sc->sc_map, 0,
257 				   sc->sc_intrs[0].sc_irqmode,
258 				   sc->sc_intrs[0].sc_intrstr,
259 				   sizeof(sc->sc_intrs[0].sc_intrstr))) {
260 			aprint_error_dev(self,
261 			    "failed to decode interrupt\n");
262 			gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
263 			return;
264 		}
265 		flags = gpio_pin_get_conf(sc->sc_gpio, &sc->sc_map, 0);
266 		flags = (flags & ~(GPIO_PIN_OUTPUT|GPIO_PIN_INOUT)) |
267 		    GPIO_PIN_INPUT;
268 		if (!gpio_pin_set_conf(sc->sc_gpio, &sc->sc_map, 0, flags)) {
269 			aprint_error_dev(sc->sc_dev,
270 			    "ASSERT%s pin not capable of input\n",
271 			    double_edge ? "+CLEAR" : "");
272 			gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
273 			return;
274 		}
275 
276 		aprint_normal_dev(self, "ASSERT%s interrupting on %s\n",
277 				  double_edge ? "+CLEAR" : "",
278 				  sc->sc_intrs[0].sc_intrstr);
279 	}
280 
281 	/* Interrupt will be registered when device is opened for use. */
282 
283 	sc->sc_functional = true;
284 }
285 
286 static int
gpiopps_assert_intr(void * arg)287 gpiopps_assert_intr(void *arg)
288 {
289 	struct gpiopps_softc *sc = arg;
290 
291 	mutex_spin_enter(&timecounter_lock);
292 	pps_capture(&sc->sc_pps_state);
293 	pps_event(&sc->sc_pps_state, PPS_CAPTUREASSERT);
294 	mutex_spin_exit(&timecounter_lock);
295 
296 	return (1);
297 }
298 
299 static int
gpiopps_clear_intr(void * arg)300 gpiopps_clear_intr(void *arg)
301 {
302 	struct gpiopps_softc *sc = arg;
303 
304 	mutex_spin_enter(&timecounter_lock);
305 	pps_capture(&sc->sc_pps_state);
306 	pps_event(&sc->sc_pps_state, PPS_CAPTURECLEAR);
307 	mutex_spin_exit(&timecounter_lock);
308 
309 	return (1);
310 }
311 
312 static int
gpiopps_double_intr(void * arg)313 gpiopps_double_intr(void *arg)
314 {
315 	struct gpiopps_softc *sc = arg;
316 	int val = gpio_pin_read(sc->sc_gpio, &sc->sc_map, 0);
317 
318 	if (val == sc->sc_assert_val)
319 		return (gpiopps_assert_intr(arg));
320 	return (gpiopps_clear_intr(arg));
321 }
322 
323 static void
gpiopps_disable_interrupts(struct gpiopps_softc * sc)324 gpiopps_disable_interrupts(struct gpiopps_softc *sc)
325 {
326 	int i;
327 
328 	for (i = 0; i < GPIOPPS_NPINS; i++) {
329 		if (sc->sc_intrs[i].sc_ih != NULL) {
330 			gpio_intr_disestablish(sc->sc_gpio,
331 					       sc->sc_intrs[i].sc_ih);
332 			sc->sc_intrs[i].sc_ih = NULL;
333 		}
334 	}
335 }
336 
337 static void
gpiopps_reset(struct gpiopps_softc * sc)338 gpiopps_reset(struct gpiopps_softc *sc)
339 {
340 	mutex_spin_enter(&timecounter_lock);
341 	sc->sc_pps_state.ppsparam.mode = 0;
342 	sc->sc_busy = false;
343 	mutex_spin_exit(&timecounter_lock);
344 }
345 
346 static int
gpiopps_detach(device_t self,int flags)347 gpiopps_detach(device_t self, int flags)
348 {
349 	struct gpiopps_softc *sc = device_private(self);
350 
351 	if (!sc->sc_functional) {
352 		/* Attach failed, no work to do; resources already released. */
353 		return (0);
354 	}
355 
356 	if (sc->sc_busy)
357 		return (EBUSY);
358 
359 	/*
360 	 * Clear the handler and disable the interrupt.
361 	 * NOTE: This should never be true, because we
362 	 * register the interrupt handler at open, and
363 	 * remove it at close.  We keep this as a backstop.
364 	 */
365 	gpiopps_disable_interrupts(sc);
366 
367 	/* Release the pin. */
368 	gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
369 
370 	return (0);
371 }
372 
373 static int
gpioppsopen(dev_t dev,int flags,int fmt,struct lwp * l)374 gpioppsopen(dev_t dev, int flags, int fmt, struct lwp *l)
375 {
376 	struct gpiopps_softc *sc;
377 	int error = EIO;
378 
379 	sc = device_lookup_private(&gpiopps_cd, minor(dev));
380 	if (sc == NULL)
381 		return (ENXIO);
382 
383 	if (!sc->sc_functional)
384 		return (EIO);
385 
386 	mutex_spin_enter(&timecounter_lock);
387 
388 	if (sc->sc_busy) {
389 		mutex_spin_exit(&timecounter_lock);
390 		return (0);
391 	}
392 
393 	memset(&sc->sc_pps_state, 0, sizeof(sc->sc_pps_state));
394 	sc->sc_pps_state.ppscap = PPS_CAPTUREASSERT;
395 	if (sc->sc_npins == 2 ||
396 	    sc->sc_intrs[0].sc_irqmode == GPIO_INTR_DOUBLE_EDGE)
397 	    	sc->sc_pps_state.ppscap |= PPS_CAPTURECLEAR;
398 	pps_init(&sc->sc_pps_state);
399 	sc->sc_busy = true;
400 
401 	mutex_spin_exit(&timecounter_lock);
402 
403 	if (sc->sc_npins == 2) {
404 		sc->sc_intrs[0].sc_ih = gpio_intr_establish(sc->sc_gpio,
405 		    &sc->sc_map, 0, IPL_VM,
406 		    sc->sc_intrs[0].sc_irqmode | GPIO_INTR_MPSAFE,
407 		    gpiopps_assert_intr, sc);
408 		if (sc->sc_intrs[0].sc_ih == NULL) {
409 			aprint_error_dev(sc->sc_dev,
410 			    "unable to establish ASSERT interrupt on %s\n",
411 			    sc->sc_intrs[0].sc_intrstr);
412 			goto out;
413 		}
414 
415 		sc->sc_intrs[1].sc_ih = gpio_intr_establish(sc->sc_gpio,
416 		    &sc->sc_map, 1, IPL_VM,
417 		    sc->sc_intrs[1].sc_irqmode | GPIO_INTR_MPSAFE,
418 		    gpiopps_clear_intr, sc);
419 		if (sc->sc_intrs[1].sc_ih == NULL) {
420 			aprint_error_dev(sc->sc_dev,
421 			    "unable to establish CLEAR interrupt on %s\n",
422 			    sc->sc_intrs[0].sc_intrstr);
423 			gpio_intr_disestablish(sc->sc_gpio,
424 					       sc->sc_intrs[0].sc_ih);
425 			goto out;
426 		}
427 	} else {
428 		bool double_edge =
429 		    sc->sc_intrs[0].sc_irqmode == GPIO_INTR_DOUBLE_EDGE;
430 		sc->sc_intrs[0].sc_ih = gpio_intr_establish(sc->sc_gpio,
431 		    &sc->sc_map, 0, IPL_VM,
432 		    sc->sc_intrs[0].sc_irqmode | GPIO_INTR_MPSAFE,
433 		    double_edge ? gpiopps_double_intr
434 				: gpiopps_assert_intr, sc);
435 		if (sc->sc_intrs[0].sc_ih == NULL) {
436 			aprint_error_dev(sc->sc_dev,
437 			    "unable to establish ASSERT%s interrupt on %s\n",
438 			    double_edge ? "+CLEAR" : "",
439 			    sc->sc_intrs[0].sc_intrstr);
440 			goto out;
441 		}
442 	}
443 
444 	error = 0;
445 
446  out:
447 	if (error) {
448 		gpiopps_disable_interrupts(sc);
449 		gpiopps_reset(sc);
450 	}
451 	return (error);
452 }
453 
454 static int
gpioppsclose(dev_t dev,int flags,int fmt,struct lwp * l)455 gpioppsclose(dev_t dev, int flags, int fmt, struct lwp *l)
456 {
457 	struct gpiopps_softc *sc;
458 
459 	sc = device_lookup_private(&gpiopps_cd, minor(dev));
460 
461 	gpiopps_disable_interrupts(sc);
462 	gpiopps_reset(sc);
463 
464 	return (0);
465 }
466 
467 static int
gpioppsioctl(dev_t dev,u_long cmd,void * data,int flags,struct lwp * l)468 gpioppsioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
469 {
470 	struct gpiopps_softc *sc;
471 	int error = 0;
472 
473 	sc = device_lookup_private(&gpiopps_cd, minor(dev));
474 
475 	switch (cmd) {
476 	case PPS_IOC_CREATE:
477 	case PPS_IOC_DESTROY:
478 	case PPS_IOC_GETPARAMS:
479 	case PPS_IOC_SETPARAMS:
480 	case PPS_IOC_GETCAP:
481 	case PPS_IOC_FETCH:
482 	case PPS_IOC_KCBIND:
483 		mutex_spin_enter(&timecounter_lock);
484 		error = pps_ioctl(cmd, data, &sc->sc_pps_state);
485 		mutex_spin_exit(&timecounter_lock);
486 		break;
487 
488 	default:
489 		error = EPASSTHROUGH;
490 	}
491 
492 	return (error);
493 }
494 
495 MODULE(MODULE_CLASS_DRIVER, gpiopps, "gpio");
496 
497 #ifdef _MODULE
498 #include "ioconf.c"
499 #endif
500 
501 static int
gpiopps_modcmd(modcmd_t cmd,void * opaque)502 gpiopps_modcmd(modcmd_t cmd, void *opaque)
503 {
504 	int error = 0;
505 #ifdef _MODULE
506 	int bmaj = -1, cmaj = -1;
507 #endif
508 
509 	switch (cmd) {
510 	case MODULE_CMD_INIT:
511 #ifdef _MODULE
512 		error = devsw_attach("gpiopps", NULL, &bmaj,
513 		    &gpiopps_cdevsw, &cmaj);
514 		if (error) {
515 			aprint_error("%s: unable to attach devsw\n",
516 			    gpiopps_cd.cd_name);
517 			return error;
518 		}
519 		error = config_init_component(cfdriver_ioconf_gpiopps,
520 		    cfattach_ioconf_gpiopps, cfdata_ioconf_gpiopps);
521 		if (error) {
522 			aprint_error("%s: unable to init component\n",
523 			    gpiopps_cd.cd_name);
524 			devsw_detach(NULL, &gpiopps_cdevsw);
525 			return (error);
526 		}
527 #endif
528 		return (error);
529 	case MODULE_CMD_FINI:
530 #ifdef _MODULE
531 		config_fini_component(cfdriver_ioconf_gpiopps,
532 		    cfattach_ioconf_gpiopps, cfdata_ioconf_gpiopps);
533 		devsw_detach(NULL, &gpiopps_cdevsw);
534 #endif
535 		return (0);
536 	default:
537 		return (ENOTTY);
538 	}
539 }
540