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