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