]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/nvidia/as3722_gpio.c
Merge ACPICA 20191018.
[FreeBSD/FreeBSD.git] / sys / arm / nvidia / as3722_gpio.c
1 /*-
2  * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/bus.h>
33 #include <sys/gpio.h>
34 #include <sys/kernel.h>
35 #include <sys/malloc.h>
36 #include <sys/sx.h>
37
38 #include <machine/bus.h>
39
40 #include <dev/fdt/fdt_common.h>
41 #include <dev/gpio/gpiobusvar.h>
42
43 #include "as3722.h"
44
45 MALLOC_DEFINE(M_AS3722_GPIO, "AS3722 gpio", "AS3722 GPIO");
46
47 /* AS3722_GPIOx_CONTROL  MODE and IOSF definition. */
48 #define AS3722_IOSF_GPIO                                0x00
49 #define AS3722_IOSF_INTERRUPT_OUT                       0x01
50 #define AS3722_IOSF_VSUP_VBAT_LOW_UNDEBOUNCE_OUT        0x02
51 #define AS3722_IOSF_GPIO_IN_INTERRUPT                   0x03
52 #define AS3722_IOSF_PWM_IN                              0x04
53 #define AS3722_IOSF_VOLTAGE_IN_STANDBY                  0x05
54 #define AS3722_IOSF_OC_PG_SD0                           0x06
55 #define AS3722_IOSF_POWERGOOD_OUT                       0x07
56 #define AS3722_IOSF_CLK32K_OUT                          0x08
57 #define AS3722_IOSF_WATCHDOG_IN                         0x09
58 #define AS3722_IOSF_SOFT_RESET_IN                       0x0b
59 #define AS3722_IOSF_PWM_OUT                             0x0c
60 #define AS3722_IOSF_VSUP_VBAT_LOW_DEBOUNCE_OUT          0x0d
61 #define AS3722_IOSF_OC_PG_SD6                           0x0e
62
63 #define AS3722_MODE_INPUT                               0
64 #define AS3722_MODE_PUSH_PULL                           1
65 #define AS3722_MODE_OPEN_DRAIN                          2
66 #define AS3722_MODE_TRISTATE                            3
67 #define AS3722_MODE_INPUT_PULL_UP_LV                    4
68 #define AS3722_MODE_INPUT_PULL_DOWN                     5
69 #define AS3722_MODE_OPEN_DRAIN_LV                       6
70 #define AS3722_MODE_PUSH_PULL_LV                        7
71
72 #define NGPIO           8
73
74 #define GPIO_LOCK(_sc)  sx_slock(&(_sc)->gpio_lock)
75 #define GPIO_UNLOCK(_sc)        sx_unlock(&(_sc)->gpio_lock)
76 #define GPIO_ASSERT(_sc)        sx_assert(&(_sc)->gpio_lock, SA_LOCKED)
77
78 #define AS3722_CFG_BIAS_DISABLE         0x0001
79 #define AS3722_CFG_BIAS_PULL_UP         0x0002
80 #define AS3722_CFG_BIAS_PULL_DOWN       0x0004
81 #define AS3722_CFG_BIAS_HIGH_IMPEDANCE  0x0008
82 #define AS3722_CFG_OPEN_DRAIN           0x0010
83
84 static const struct {
85         const char      *name;
86         int             config;         /* AS3722_CFG_  */
87 } as3722_cfg_names[] = {
88         {"bias-disable",        AS3722_CFG_BIAS_DISABLE},
89         {"bias-pull-up",        AS3722_CFG_BIAS_PULL_UP},
90         {"bias-pull-down",      AS3722_CFG_BIAS_PULL_DOWN},
91         {"bias-high-impedance", AS3722_CFG_BIAS_HIGH_IMPEDANCE},
92         {"drive-open-drain",    AS3722_CFG_OPEN_DRAIN},
93 };
94
95 static struct {
96         const char *name;
97         int fnc_val;
98 } as3722_fnc_table[] = {
99         {"gpio",                        AS3722_IOSF_GPIO},
100         {"interrupt-out",               AS3722_IOSF_INTERRUPT_OUT},
101         {"vsup-vbat-low-undebounce-out", AS3722_IOSF_VSUP_VBAT_LOW_UNDEBOUNCE_OUT},
102         {"gpio-in-interrupt",           AS3722_IOSF_GPIO_IN_INTERRUPT},
103         {"pwm-in",                      AS3722_IOSF_PWM_IN},
104         {"voltage-in-standby",          AS3722_IOSF_VOLTAGE_IN_STANDBY},
105         {"oc-pg-sd0",                   AS3722_IOSF_OC_PG_SD0},
106         {"powergood-out",               AS3722_IOSF_POWERGOOD_OUT},
107         {"clk32k-out",                  AS3722_IOSF_CLK32K_OUT},
108         {"watchdog-in",                 AS3722_IOSF_WATCHDOG_IN},
109         {"soft-reset-in",               AS3722_IOSF_SOFT_RESET_IN},
110         {"pwm-out",                     AS3722_IOSF_PWM_OUT},
111         {"vsup-vbat-low-debounce-out",  AS3722_IOSF_VSUP_VBAT_LOW_DEBOUNCE_OUT},
112         {"oc-pg-sd6",                   AS3722_IOSF_OC_PG_SD6},
113 };
114
115 struct as3722_pincfg {
116         char    *function;
117         int     flags;
118 };
119
120 struct as3722_gpio_pin {
121         int     pin_caps;
122         uint8_t pin_ctrl_reg;
123         char    pin_name[GPIOMAXNAME];
124         int     pin_cfg_flags;
125 };
126
127
128 /* --------------------------------------------------------------------------
129  *
130  *  Pinmux functions.
131  */
132 static int
133 as3722_pinmux_get_function(struct as3722_softc *sc, char *name)
134 {
135         int i;
136
137         for (i = 0; i < nitems(as3722_fnc_table); i++) {
138                 if (strcmp(as3722_fnc_table[i].name, name) == 0)
139                          return (as3722_fnc_table[i].fnc_val);
140         }
141         return (-1);
142 }
143
144
145
146 static int
147 as3722_pinmux_config_node(struct as3722_softc *sc, char *pin_name,
148     struct as3722_pincfg *cfg)
149 {
150         uint8_t ctrl;
151         int rv, fnc, pin;
152
153         for (pin = 0; pin < sc->gpio_npins; pin++) {
154                 if (strcmp(sc->gpio_pins[pin]->pin_name, pin_name) == 0)
155                          break;
156         }
157         if (pin >= sc->gpio_npins) {
158                 device_printf(sc->dev, "Unknown pin: %s\n", pin_name);
159                 return (ENXIO);
160         }
161
162         ctrl = sc->gpio_pins[pin]->pin_ctrl_reg;
163         sc->gpio_pins[pin]->pin_cfg_flags = cfg->flags;
164         if (cfg->function != NULL) {
165                 fnc = as3722_pinmux_get_function(sc, cfg->function);
166                 if (fnc == -1) {
167                         device_printf(sc->dev,
168                             "Unknown function %s for pin %s\n", cfg->function,
169                             sc->gpio_pins[pin]->pin_name);
170                         return (ENXIO);
171                 }
172                 switch (fnc) {
173                 case AS3722_IOSF_INTERRUPT_OUT:
174                 case AS3722_IOSF_VSUP_VBAT_LOW_UNDEBOUNCE_OUT:
175                 case AS3722_IOSF_OC_PG_SD0:
176                 case AS3722_IOSF_POWERGOOD_OUT:
177                 case AS3722_IOSF_CLK32K_OUT:
178                 case AS3722_IOSF_PWM_OUT:
179                 case AS3722_IOSF_OC_PG_SD6:
180                         ctrl &= ~(AS3722_GPIO_MODE_MASK <<
181                             AS3722_GPIO_MODE_SHIFT);
182                         ctrl |= AS3722_MODE_PUSH_PULL << AS3722_GPIO_MODE_SHIFT;
183                         /* XXX Handle flags (OC + pullup) */
184                         break;
185                 case AS3722_IOSF_GPIO_IN_INTERRUPT:
186                 case AS3722_IOSF_PWM_IN:
187                 case AS3722_IOSF_VOLTAGE_IN_STANDBY:
188                 case AS3722_IOSF_WATCHDOG_IN:
189                 case AS3722_IOSF_SOFT_RESET_IN:
190                         ctrl &= ~(AS3722_GPIO_MODE_MASK <<
191                             AS3722_GPIO_MODE_SHIFT);
192                         ctrl |= AS3722_MODE_INPUT << AS3722_GPIO_MODE_SHIFT;
193                         /* XXX Handle flags (pulldown + pullup) */
194
195                 default:
196                         break;
197                 }
198                 ctrl &= ~(AS3722_GPIO_IOSF_MASK << AS3722_GPIO_IOSF_SHIFT);
199                 ctrl |= fnc << AS3722_GPIO_IOSF_SHIFT;
200         }
201         rv = 0;
202         if (ctrl != sc->gpio_pins[pin]->pin_ctrl_reg) {
203                 rv = WR1(sc, AS3722_GPIO0_CONTROL + pin, ctrl);
204                 sc->gpio_pins[pin]->pin_ctrl_reg = ctrl;
205         }
206         return (rv);
207 }
208
209 static int
210 as3722_pinmux_read_node(struct as3722_softc *sc, phandle_t node,
211      struct as3722_pincfg *cfg, char **pins, int *lpins)
212 {
213         int rv, i;
214
215         *lpins = OF_getprop_alloc(node, "pins", (void **)pins);
216         if (*lpins <= 0)
217                 return (ENOENT);
218
219         /* Read function (mux) settings. */
220         rv = OF_getprop_alloc(node, "function", (void **)&cfg->function);
221         if (rv <= 0)
222                 cfg->function = NULL;
223
224         /* Read boolean properties. */
225         for (i = 0; i < nitems(as3722_cfg_names); i++) {
226                 if (OF_hasprop(node, as3722_cfg_names[i].name))
227                         cfg->flags |= as3722_cfg_names[i].config;
228         }
229         return (0);
230 }
231
232 static int
233 as3722_pinmux_process_node(struct as3722_softc *sc, phandle_t node)
234 {
235         struct as3722_pincfg cfg;
236         char *pins, *pname;
237         int i, len, lpins, rv;
238
239         rv = as3722_pinmux_read_node(sc, node, &cfg, &pins, &lpins);
240         if (rv != 0)
241                 return (rv);
242
243         len = 0;
244         pname = pins;
245         do {
246                 i = strlen(pname) + 1;
247                 rv = as3722_pinmux_config_node(sc, pname, &cfg);
248                 if (rv != 0) {
249                         device_printf(sc->dev,
250                             "Cannot configure pin: %s: %d\n", pname, rv);
251                 }
252                 len += i;
253                 pname += i;
254         } while (len < lpins);
255
256         if (pins != NULL)
257                 OF_prop_free(pins);
258         if (cfg.function != NULL)
259                 OF_prop_free(cfg.function);
260
261         return (rv);
262 }
263
264 int as3722_pinmux_configure(device_t dev, phandle_t cfgxref)
265 {
266         struct as3722_softc *sc;
267         phandle_t node, cfgnode;
268         int rv;
269
270         sc = device_get_softc(dev);
271         cfgnode = OF_node_from_xref(cfgxref);
272
273         for (node = OF_child(cfgnode); node != 0; node = OF_peer(node)) {
274                 if (!ofw_bus_node_status_okay(node))
275                         continue;
276                 rv = as3722_pinmux_process_node(sc, node);
277                 if (rv != 0)
278                         device_printf(dev, "Failed to process pinmux");
279
280         }
281         return (0);
282 }
283
284 /* --------------------------------------------------------------------------
285  *
286  *  GPIO
287  */
288 device_t
289 as3722_gpio_get_bus(device_t dev)
290 {
291         struct as3722_softc *sc;
292
293         sc = device_get_softc(dev);
294         return (sc->gpio_busdev);
295 }
296
297 int
298 as3722_gpio_pin_max(device_t dev, int *maxpin)
299 {
300
301         *maxpin = NGPIO - 1;
302         return (0);
303 }
304
305 int
306 as3722_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
307 {
308         struct as3722_softc *sc;
309
310         sc = device_get_softc(dev);
311         if (pin >= sc->gpio_npins)
312                 return (EINVAL);
313         GPIO_LOCK(sc);
314         *caps = sc->gpio_pins[pin]->pin_caps;
315         GPIO_UNLOCK(sc);
316         return (0);
317 }
318
319 int
320 as3722_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
321 {
322         struct as3722_softc *sc;
323
324         sc = device_get_softc(dev);
325         if (pin >= sc->gpio_npins)
326                 return (EINVAL);
327         GPIO_LOCK(sc);
328         memcpy(name, sc->gpio_pins[pin]->pin_name, GPIOMAXNAME);
329         GPIO_UNLOCK(sc);
330         return (0);
331 }
332
333 int
334 as3722_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *out_flags)
335 {
336         struct as3722_softc *sc;
337         uint8_t tmp, mode, iosf;
338         uint32_t flags;
339         bool inverted;
340
341         sc = device_get_softc(dev);
342         if (pin >= sc->gpio_npins)
343                 return (EINVAL);
344
345         GPIO_LOCK(sc);
346         tmp = sc->gpio_pins[pin]->pin_ctrl_reg;
347         GPIO_UNLOCK(sc);
348         iosf = (tmp >> AS3722_GPIO_IOSF_SHIFT) & AS3722_GPIO_IOSF_MASK;
349         mode = (tmp >> AS3722_GPIO_MODE_SHIFT) & AS3722_GPIO_MODE_MASK;
350         inverted = (tmp & AS3722_GPIO_INVERT) != 0;
351         /* Is pin in GPIO mode ? */
352         if (iosf != AS3722_IOSF_GPIO)
353                 return (ENXIO);
354
355         flags = 0;
356         switch (mode) {
357         case AS3722_MODE_INPUT:
358                 flags = GPIO_PIN_INPUT;
359                 break;
360         case AS3722_MODE_PUSH_PULL:
361         case AS3722_MODE_PUSH_PULL_LV:
362                 flags = GPIO_PIN_OUTPUT;
363                 break;
364         case AS3722_MODE_OPEN_DRAIN:
365         case AS3722_MODE_OPEN_DRAIN_LV:
366                 flags = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN;
367                 break;
368         case AS3722_MODE_TRISTATE:
369                 flags = GPIO_PIN_TRISTATE;
370                 break;
371         case AS3722_MODE_INPUT_PULL_UP_LV:
372                 flags = GPIO_PIN_INPUT | GPIO_PIN_PULLUP;
373                 break;
374
375         case AS3722_MODE_INPUT_PULL_DOWN:
376                 flags = GPIO_PIN_OUTPUT | GPIO_PIN_PULLDOWN;
377                 break;
378         }
379         if (inverted)
380                 flags |= GPIO_PIN_INVIN | GPIO_PIN_INVOUT;
381         *out_flags = flags;
382         return (0);
383 }
384
385 static int
386 as3722_gpio_get_mode(struct as3722_softc *sc, uint32_t pin, uint32_t gpio_flags)
387 {
388         uint8_t ctrl;
389         int flags;
390
391         ctrl = sc->gpio_pins[pin]->pin_ctrl_reg;
392         flags =  sc->gpio_pins[pin]->pin_cfg_flags;
393
394         /* Tristate mode. */
395         if (flags & AS3722_CFG_BIAS_HIGH_IMPEDANCE ||
396             gpio_flags & GPIO_PIN_TRISTATE)
397                 return (AS3722_MODE_TRISTATE);
398
399         /* Open drain modes. */
400         if (flags & AS3722_CFG_OPEN_DRAIN || gpio_flags & GPIO_PIN_OPENDRAIN) {
401                 /* Only pull up have effect */
402                 if (flags & AS3722_CFG_BIAS_PULL_UP ||
403                     gpio_flags & GPIO_PIN_PULLUP)
404                         return (AS3722_MODE_OPEN_DRAIN_LV);
405                 return (AS3722_MODE_OPEN_DRAIN);
406         }
407         /* Input modes. */
408         if (gpio_flags & GPIO_PIN_INPUT) {
409                 /* Accept pull up or pull down. */
410                 if (flags & AS3722_CFG_BIAS_PULL_UP ||
411                     gpio_flags & GPIO_PIN_PULLUP)
412                         return (AS3722_MODE_INPUT_PULL_UP_LV);
413
414                 if (flags & AS3722_CFG_BIAS_PULL_DOWN ||
415                     gpio_flags & GPIO_PIN_PULLDOWN)
416                         return (AS3722_MODE_INPUT_PULL_DOWN);
417                 return (AS3722_MODE_INPUT);
418         }
419         /*
420          * Output modes.
421          * Pull down is used as indicator of low voltage output.
422          */
423         if (flags & AS3722_CFG_BIAS_PULL_DOWN ||
424                     gpio_flags & GPIO_PIN_PULLDOWN)
425                 return (AS3722_MODE_PUSH_PULL_LV);
426         return (AS3722_MODE_PUSH_PULL);
427 }
428
429 int
430 as3722_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
431 {
432         struct as3722_softc *sc;
433         uint8_t ctrl, mode, iosf;
434         int rv;
435
436         sc = device_get_softc(dev);
437         if (pin >= sc->gpio_npins)
438                 return (EINVAL);
439
440         GPIO_LOCK(sc);
441         ctrl = sc->gpio_pins[pin]->pin_ctrl_reg;
442         iosf = (ctrl >> AS3722_GPIO_IOSF_SHIFT) & AS3722_GPIO_IOSF_MASK;
443         /* Is pin in GPIO mode ? */
444         if (iosf != AS3722_IOSF_GPIO) {
445                 GPIO_UNLOCK(sc);
446                 return (ENXIO);
447         }
448         mode = as3722_gpio_get_mode(sc, pin, flags);
449         ctrl &= ~(AS3722_GPIO_MODE_MASK << AS3722_GPIO_MODE_SHIFT);
450         ctrl |= AS3722_MODE_PUSH_PULL << AS3722_GPIO_MODE_SHIFT;
451         rv = 0;
452         if (ctrl != sc->gpio_pins[pin]->pin_ctrl_reg) {
453                 rv = WR1(sc, AS3722_GPIO0_CONTROL + pin, ctrl);
454                 sc->gpio_pins[pin]->pin_ctrl_reg = ctrl;
455         }
456         GPIO_UNLOCK(sc);
457         return (rv);
458 }
459
460 int
461 as3722_gpio_pin_set(device_t dev, uint32_t pin, uint32_t val)
462 {
463         struct as3722_softc *sc;
464         uint8_t tmp;
465         int rv;
466
467         sc = device_get_softc(dev);
468         if (pin >= sc->gpio_npins)
469                 return (EINVAL);
470
471         tmp =  (val != 0) ? 1 : 0;
472         if (sc->gpio_pins[pin]->pin_ctrl_reg & AS3722_GPIO_INVERT)
473                 tmp ^= 1;
474
475         GPIO_LOCK(sc);
476         rv = RM1(sc, AS3722_GPIO_SIGNAL_OUT, (1 << pin), (tmp << pin));
477         GPIO_UNLOCK(sc);
478         return (rv);
479 }
480
481 int
482 as3722_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *val)
483 {
484         struct as3722_softc *sc;
485         uint8_t tmp, mode, ctrl;
486         int rv;
487
488         sc = device_get_softc(dev);
489         if (pin >= sc->gpio_npins)
490                 return (EINVAL);
491
492         GPIO_LOCK(sc);
493         ctrl = sc->gpio_pins[pin]->pin_ctrl_reg;
494         mode = (ctrl >> AS3722_GPIO_MODE_SHIFT) & AS3722_GPIO_MODE_MASK;
495         if ((mode == AS3722_MODE_PUSH_PULL) ||
496             (mode == AS3722_MODE_PUSH_PULL_LV))
497                 rv = RD1(sc, AS3722_GPIO_SIGNAL_OUT, &tmp);
498         else
499                 rv = RD1(sc, AS3722_GPIO_SIGNAL_IN, &tmp);
500         GPIO_UNLOCK(sc);
501         if (rv != 0)
502                 return (rv);
503
504         *val = tmp & (1 << pin) ? 1 : 0;
505         if (ctrl & AS3722_GPIO_INVERT)
506                 *val ^= 1;
507         return (0);
508 }
509
510 int
511 as3722_gpio_pin_toggle(device_t dev, uint32_t pin)
512 {
513         struct as3722_softc *sc;
514         uint8_t tmp;
515         int rv;
516
517         sc = device_get_softc(dev);
518         if (pin >= sc->gpio_npins)
519                 return (EINVAL);
520
521         GPIO_LOCK(sc);
522         rv = RD1(sc, AS3722_GPIO_SIGNAL_OUT, &tmp);
523         if (rv != 0) {
524                 GPIO_UNLOCK(sc);
525                 return (rv);
526         }
527         tmp ^= (1 <<pin);
528         rv = RM1(sc, AS3722_GPIO_SIGNAL_OUT, (1 << pin), tmp);
529         GPIO_UNLOCK(sc);
530         return (0);
531 }
532
533 int
534 as3722_gpio_map_gpios(device_t dev, phandle_t pdev, phandle_t gparent,
535     int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
536 {
537
538         if (gcells != 2)
539                 return (ERANGE);
540         *pin = gpios[0];
541         *flags= gpios[1];
542         return (0);
543 }
544
545 int
546 as3722_gpio_attach(struct as3722_softc *sc, phandle_t node)
547 {
548         struct as3722_gpio_pin *pin;
549         int i, rv;
550
551         sx_init(&sc->gpio_lock, "AS3722 GPIO lock");
552         sc->gpio_npins = NGPIO;
553         sc->gpio_pins = malloc(sizeof(struct as3722_gpio_pin *) *
554             sc->gpio_npins, M_AS3722_GPIO, M_WAITOK | M_ZERO);
555
556
557         sc->gpio_busdev = gpiobus_attach_bus(sc->dev);
558         if (sc->gpio_busdev == NULL)
559                 return (ENXIO);
560         for (i = 0; i < sc->gpio_npins; i++) {
561                 sc->gpio_pins[i] = malloc(sizeof(struct as3722_gpio_pin),
562                     M_AS3722_GPIO, M_WAITOK | M_ZERO);
563                 pin = sc->gpio_pins[i];
564                 sprintf(pin->pin_name, "gpio%d", i);
565                 pin->pin_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT  |
566                     GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL | GPIO_PIN_TRISTATE |
567                     GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN | GPIO_PIN_INVIN |
568                     GPIO_PIN_INVOUT;
569                 rv = RD1(sc, AS3722_GPIO0_CONTROL + i, &pin->pin_ctrl_reg);
570                 if (rv != 0) {
571                         device_printf(sc->dev,
572                             "Cannot read configuration for pin %s\n",
573                             sc->gpio_pins[i]->pin_name);
574                 }
575         }
576         return (0);
577 }