]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/nvidia/as3722_gpio.c
as3722_gpio_pin_setflags: Use computed mode instead of hardcoded PUSHPULL.
[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  *  Pinmux functions.
130  */
131 static int
132 as3722_pinmux_get_function(struct as3722_softc *sc, char *name)
133 {
134         int i;
135
136         for (i = 0; i < nitems(as3722_fnc_table); i++) {
137                 if (strcmp(as3722_fnc_table[i].name, name) == 0)
138                          return (as3722_fnc_table[i].fnc_val);
139         }
140         return (-1);
141 }
142
143 static int
144 as3722_pinmux_config_node(struct as3722_softc *sc, char *pin_name,
145     struct as3722_pincfg *cfg)
146 {
147         uint8_t ctrl;
148         int rv, fnc, pin;
149
150         for (pin = 0; pin < sc->gpio_npins; pin++) {
151                 if (strcmp(sc->gpio_pins[pin]->pin_name, pin_name) == 0)
152                          break;
153         }
154         if (pin >= sc->gpio_npins) {
155                 device_printf(sc->dev, "Unknown pin: %s\n", pin_name);
156                 return (ENXIO);
157         }
158
159         ctrl = sc->gpio_pins[pin]->pin_ctrl_reg;
160         sc->gpio_pins[pin]->pin_cfg_flags = cfg->flags;
161         if (cfg->function != NULL) {
162                 fnc = as3722_pinmux_get_function(sc, cfg->function);
163                 if (fnc == -1) {
164                         device_printf(sc->dev,
165                             "Unknown function %s for pin %s\n", cfg->function,
166                             sc->gpio_pins[pin]->pin_name);
167                         return (ENXIO);
168                 }
169                 switch (fnc) {
170                 case AS3722_IOSF_INTERRUPT_OUT:
171                 case AS3722_IOSF_VSUP_VBAT_LOW_UNDEBOUNCE_OUT:
172                 case AS3722_IOSF_OC_PG_SD0:
173                 case AS3722_IOSF_POWERGOOD_OUT:
174                 case AS3722_IOSF_CLK32K_OUT:
175                 case AS3722_IOSF_PWM_OUT:
176                 case AS3722_IOSF_OC_PG_SD6:
177                         ctrl &= ~(AS3722_GPIO_MODE_MASK <<
178                             AS3722_GPIO_MODE_SHIFT);
179                         ctrl |= AS3722_MODE_PUSH_PULL << AS3722_GPIO_MODE_SHIFT;
180                         /* XXX Handle flags (OC + pullup) */
181                         break;
182                 case AS3722_IOSF_GPIO_IN_INTERRUPT:
183                 case AS3722_IOSF_PWM_IN:
184                 case AS3722_IOSF_VOLTAGE_IN_STANDBY:
185                 case AS3722_IOSF_WATCHDOG_IN:
186                 case AS3722_IOSF_SOFT_RESET_IN:
187                         ctrl &= ~(AS3722_GPIO_MODE_MASK <<
188                             AS3722_GPIO_MODE_SHIFT);
189                         ctrl |= AS3722_MODE_INPUT << AS3722_GPIO_MODE_SHIFT;
190                         /* XXX Handle flags (pulldown + pullup) */
191
192                 default:
193                         break;
194                 }
195                 ctrl &= ~(AS3722_GPIO_IOSF_MASK << AS3722_GPIO_IOSF_SHIFT);
196                 ctrl |= fnc << AS3722_GPIO_IOSF_SHIFT;
197         }
198         rv = 0;
199         if (ctrl != sc->gpio_pins[pin]->pin_ctrl_reg) {
200                 rv = WR1(sc, AS3722_GPIO0_CONTROL + pin, ctrl);
201                 sc->gpio_pins[pin]->pin_ctrl_reg = ctrl;
202         }
203         return (rv);
204 }
205
206 static int
207 as3722_pinmux_read_node(struct as3722_softc *sc, phandle_t node,
208      struct as3722_pincfg *cfg, char **pins, int *lpins)
209 {
210         int rv, i;
211
212         *lpins = OF_getprop_alloc(node, "pins", (void **)pins);
213         if (*lpins <= 0)
214                 return (ENOENT);
215
216         /* Read function (mux) settings. */
217         rv = OF_getprop_alloc(node, "function", (void **)&cfg->function);
218         if (rv <= 0)
219                 cfg->function = NULL;
220
221         /* Read boolean properties. */
222         for (i = 0; i < nitems(as3722_cfg_names); i++) {
223                 if (OF_hasprop(node, as3722_cfg_names[i].name))
224                         cfg->flags |= as3722_cfg_names[i].config;
225         }
226         return (0);
227 }
228
229 static int
230 as3722_pinmux_process_node(struct as3722_softc *sc, phandle_t node)
231 {
232         struct as3722_pincfg cfg;
233         char *pins, *pname;
234         int i, len, lpins, rv;
235
236         rv = as3722_pinmux_read_node(sc, node, &cfg, &pins, &lpins);
237         if (rv != 0)
238                 return (rv);
239
240         len = 0;
241         pname = pins;
242         do {
243                 i = strlen(pname) + 1;
244                 rv = as3722_pinmux_config_node(sc, pname, &cfg);
245                 if (rv != 0) {
246                         device_printf(sc->dev,
247                             "Cannot configure pin: %s: %d\n", pname, rv);
248                 }
249                 len += i;
250                 pname += i;
251         } while (len < lpins);
252
253         if (pins != NULL)
254                 OF_prop_free(pins);
255         if (cfg.function != NULL)
256                 OF_prop_free(cfg.function);
257
258         return (rv);
259 }
260
261 int as3722_pinmux_configure(device_t dev, phandle_t cfgxref)
262 {
263         struct as3722_softc *sc;
264         phandle_t node, cfgnode;
265         int rv;
266
267         sc = device_get_softc(dev);
268         cfgnode = OF_node_from_xref(cfgxref);
269
270         for (node = OF_child(cfgnode); node != 0; node = OF_peer(node)) {
271                 if (!ofw_bus_node_status_okay(node))
272                         continue;
273                 rv = as3722_pinmux_process_node(sc, node);
274                 if (rv != 0)
275                         device_printf(dev, "Failed to process pinmux");
276         }
277         return (0);
278 }
279
280 /* --------------------------------------------------------------------------
281  *
282  *  GPIO
283  */
284 device_t
285 as3722_gpio_get_bus(device_t dev)
286 {
287         struct as3722_softc *sc;
288
289         sc = device_get_softc(dev);
290         return (sc->gpio_busdev);
291 }
292
293 int
294 as3722_gpio_pin_max(device_t dev, int *maxpin)
295 {
296
297         *maxpin = NGPIO - 1;
298         return (0);
299 }
300
301 int
302 as3722_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
303 {
304         struct as3722_softc *sc;
305
306         sc = device_get_softc(dev);
307         if (pin >= sc->gpio_npins)
308                 return (EINVAL);
309         GPIO_LOCK(sc);
310         *caps = sc->gpio_pins[pin]->pin_caps;
311         GPIO_UNLOCK(sc);
312         return (0);
313 }
314
315 int
316 as3722_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
317 {
318         struct as3722_softc *sc;
319
320         sc = device_get_softc(dev);
321         if (pin >= sc->gpio_npins)
322                 return (EINVAL);
323         GPIO_LOCK(sc);
324         memcpy(name, sc->gpio_pins[pin]->pin_name, GPIOMAXNAME);
325         GPIO_UNLOCK(sc);
326         return (0);
327 }
328
329 int
330 as3722_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *out_flags)
331 {
332         struct as3722_softc *sc;
333         uint8_t tmp, mode, iosf;
334         uint32_t flags;
335         bool inverted;
336
337         sc = device_get_softc(dev);
338         if (pin >= sc->gpio_npins)
339                 return (EINVAL);
340
341         GPIO_LOCK(sc);
342         tmp = sc->gpio_pins[pin]->pin_ctrl_reg;
343         GPIO_UNLOCK(sc);
344         iosf = (tmp >> AS3722_GPIO_IOSF_SHIFT) & AS3722_GPIO_IOSF_MASK;
345         mode = (tmp >> AS3722_GPIO_MODE_SHIFT) & AS3722_GPIO_MODE_MASK;
346         inverted = (tmp & AS3722_GPIO_INVERT) != 0;
347         /* Is pin in GPIO mode ? */
348         if (iosf != AS3722_IOSF_GPIO)
349                 return (ENXIO);
350
351         flags = 0;
352         switch (mode) {
353         case AS3722_MODE_INPUT:
354                 flags = GPIO_PIN_INPUT;
355                 break;
356         case AS3722_MODE_PUSH_PULL:
357         case AS3722_MODE_PUSH_PULL_LV:
358                 flags = GPIO_PIN_OUTPUT;
359                 break;
360         case AS3722_MODE_OPEN_DRAIN:
361         case AS3722_MODE_OPEN_DRAIN_LV:
362                 flags = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN;
363                 break;
364         case AS3722_MODE_TRISTATE:
365                 flags = GPIO_PIN_TRISTATE;
366                 break;
367         case AS3722_MODE_INPUT_PULL_UP_LV:
368                 flags = GPIO_PIN_INPUT | GPIO_PIN_PULLUP;
369                 break;
370
371         case AS3722_MODE_INPUT_PULL_DOWN:
372                 flags = GPIO_PIN_OUTPUT | GPIO_PIN_PULLDOWN;
373                 break;
374         }
375         if (inverted)
376                 flags |= GPIO_PIN_INVIN | GPIO_PIN_INVOUT;
377         *out_flags = flags;
378         return (0);
379 }
380
381 static int
382 as3722_gpio_get_mode(struct as3722_softc *sc, uint32_t pin, uint32_t gpio_flags)
383 {
384         uint8_t ctrl;
385         int flags;
386
387         ctrl = sc->gpio_pins[pin]->pin_ctrl_reg;
388         flags =  sc->gpio_pins[pin]->pin_cfg_flags;
389
390         /* Tristate mode. */
391         if (flags & AS3722_CFG_BIAS_HIGH_IMPEDANCE ||
392             gpio_flags & GPIO_PIN_TRISTATE)
393                 return (AS3722_MODE_TRISTATE);
394
395         /* Open drain modes. */
396         if (flags & AS3722_CFG_OPEN_DRAIN || gpio_flags & GPIO_PIN_OPENDRAIN) {
397                 /* Only pull up have effect */
398                 if (flags & AS3722_CFG_BIAS_PULL_UP ||
399                     gpio_flags & GPIO_PIN_PULLUP)
400                         return (AS3722_MODE_OPEN_DRAIN_LV);
401                 return (AS3722_MODE_OPEN_DRAIN);
402         }
403         /* Input modes. */
404         if (gpio_flags & GPIO_PIN_INPUT) {
405                 /* Accept pull up or pull down. */
406                 if (flags & AS3722_CFG_BIAS_PULL_UP ||
407                     gpio_flags & GPIO_PIN_PULLUP)
408                         return (AS3722_MODE_INPUT_PULL_UP_LV);
409
410                 if (flags & AS3722_CFG_BIAS_PULL_DOWN ||
411                     gpio_flags & GPIO_PIN_PULLDOWN)
412                         return (AS3722_MODE_INPUT_PULL_DOWN);
413                 return (AS3722_MODE_INPUT);
414         }
415         /*
416          * Output modes.
417          * Pull down is used as indicator of low voltage output.
418          */
419         if (flags & AS3722_CFG_BIAS_PULL_DOWN ||
420                     gpio_flags & GPIO_PIN_PULLDOWN)
421                 return (AS3722_MODE_PUSH_PULL_LV);
422         return (AS3722_MODE_PUSH_PULL);
423 }
424
425 int
426 as3722_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
427 {
428         struct as3722_softc *sc;
429         uint8_t ctrl, mode, iosf;
430         int rv;
431
432         sc = device_get_softc(dev);
433         if (pin >= sc->gpio_npins)
434                 return (EINVAL);
435
436         GPIO_LOCK(sc);
437         ctrl = sc->gpio_pins[pin]->pin_ctrl_reg;
438         iosf = (ctrl >> AS3722_GPIO_IOSF_SHIFT) & AS3722_GPIO_IOSF_MASK;
439         /* Is pin in GPIO mode ? */
440         if (iosf != AS3722_IOSF_GPIO) {
441                 GPIO_UNLOCK(sc);
442                 return (ENXIO);
443         }
444         mode = as3722_gpio_get_mode(sc, pin, flags);
445         ctrl &= ~(AS3722_GPIO_MODE_MASK << AS3722_GPIO_MODE_SHIFT);
446         ctrl |= mode << AS3722_GPIO_MODE_SHIFT;
447         rv = 0;
448         if (ctrl != sc->gpio_pins[pin]->pin_ctrl_reg) {
449                 rv = WR1(sc, AS3722_GPIO0_CONTROL + pin, ctrl);
450                 sc->gpio_pins[pin]->pin_ctrl_reg = ctrl;
451         }
452         GPIO_UNLOCK(sc);
453         return (rv);
454 }
455
456 int
457 as3722_gpio_pin_set(device_t dev, uint32_t pin, uint32_t val)
458 {
459         struct as3722_softc *sc;
460         uint8_t tmp;
461         int rv;
462
463         sc = device_get_softc(dev);
464         if (pin >= sc->gpio_npins)
465                 return (EINVAL);
466
467         tmp =  (val != 0) ? 1 : 0;
468         if (sc->gpio_pins[pin]->pin_ctrl_reg & AS3722_GPIO_INVERT)
469                 tmp ^= 1;
470
471         GPIO_LOCK(sc);
472         rv = RM1(sc, AS3722_GPIO_SIGNAL_OUT, (1 << pin), (tmp << pin));
473         GPIO_UNLOCK(sc);
474         return (rv);
475 }
476
477 int
478 as3722_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *val)
479 {
480         struct as3722_softc *sc;
481         uint8_t tmp, mode, ctrl;
482         int rv;
483
484         sc = device_get_softc(dev);
485         if (pin >= sc->gpio_npins)
486                 return (EINVAL);
487
488         GPIO_LOCK(sc);
489         ctrl = sc->gpio_pins[pin]->pin_ctrl_reg;
490         mode = (ctrl >> AS3722_GPIO_MODE_SHIFT) & AS3722_GPIO_MODE_MASK;
491         if ((mode == AS3722_MODE_PUSH_PULL) ||
492             (mode == AS3722_MODE_PUSH_PULL_LV))
493                 rv = RD1(sc, AS3722_GPIO_SIGNAL_OUT, &tmp);
494         else
495                 rv = RD1(sc, AS3722_GPIO_SIGNAL_IN, &tmp);
496         GPIO_UNLOCK(sc);
497         if (rv != 0)
498                 return (rv);
499
500         *val = tmp & (1 << pin) ? 1 : 0;
501         if (ctrl & AS3722_GPIO_INVERT)
502                 *val ^= 1;
503         return (0);
504 }
505
506 int
507 as3722_gpio_pin_toggle(device_t dev, uint32_t pin)
508 {
509         struct as3722_softc *sc;
510         uint8_t tmp;
511         int rv;
512
513         sc = device_get_softc(dev);
514         if (pin >= sc->gpio_npins)
515                 return (EINVAL);
516
517         GPIO_LOCK(sc);
518         rv = RD1(sc, AS3722_GPIO_SIGNAL_OUT, &tmp);
519         if (rv != 0) {
520                 GPIO_UNLOCK(sc);
521                 return (rv);
522         }
523         tmp ^= (1 <<pin);
524         rv = RM1(sc, AS3722_GPIO_SIGNAL_OUT, (1 << pin), tmp);
525         GPIO_UNLOCK(sc);
526         return (0);
527 }
528
529 int
530 as3722_gpio_map_gpios(device_t dev, phandle_t pdev, phandle_t gparent,
531     int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
532 {
533
534         if (gcells != 2)
535                 return (ERANGE);
536         *pin = gpios[0];
537         *flags= gpios[1];
538         return (0);
539 }
540
541 int
542 as3722_gpio_attach(struct as3722_softc *sc, phandle_t node)
543 {
544         struct as3722_gpio_pin *pin;
545         int i, rv;
546
547         sx_init(&sc->gpio_lock, "AS3722 GPIO lock");
548         sc->gpio_npins = NGPIO;
549         sc->gpio_pins = malloc(sizeof(struct as3722_gpio_pin *) *
550             sc->gpio_npins, M_AS3722_GPIO, M_WAITOK | M_ZERO);
551
552         sc->gpio_busdev = gpiobus_attach_bus(sc->dev);
553         if (sc->gpio_busdev == NULL)
554                 return (ENXIO);
555         for (i = 0; i < sc->gpio_npins; i++) {
556                 sc->gpio_pins[i] = malloc(sizeof(struct as3722_gpio_pin),
557                     M_AS3722_GPIO, M_WAITOK | M_ZERO);
558                 pin = sc->gpio_pins[i];
559                 sprintf(pin->pin_name, "gpio%d", i);
560                 pin->pin_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT  |
561                     GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL | GPIO_PIN_TRISTATE |
562                     GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN | GPIO_PIN_INVIN |
563                     GPIO_PIN_INVOUT;
564                 rv = RD1(sc, AS3722_GPIO0_CONTROL + i, &pin->pin_ctrl_reg);
565                 if (rv != 0) {
566                         device_printf(sc->dev,
567                             "Cannot read configuration for pin %s\n",
568                             sc->gpio_pins[i]->pin_name);
569                 }
570         }
571         return (0);
572 }