1e9034789SMichal Meloun /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3e9034789SMichal Meloun  *
4e9034789SMichal Meloun  * Copyright 2020 Michal Meloun <mmel@FreeBSD.org>
5e9034789SMichal Meloun  *
6e9034789SMichal Meloun  * Redistribution and use in source and binary forms, with or without
7e9034789SMichal Meloun  * modification, are permitted provided that the following conditions
8e9034789SMichal Meloun  * are met:
9e9034789SMichal Meloun  * 1. Redistributions of source code must retain the above copyright
10e9034789SMichal Meloun  *    notice, this list of conditions and the following disclaimer.
11e9034789SMichal Meloun  * 2. Redistributions in binary form must reproduce the above copyright
12e9034789SMichal Meloun  *    notice, this list of conditions and the following disclaimer in the
13e9034789SMichal Meloun  *    documentation and/or other materials provided with the distribution.
14e9034789SMichal Meloun  *
15e9034789SMichal Meloun  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16e9034789SMichal Meloun  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17e9034789SMichal Meloun  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18e9034789SMichal Meloun  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19e9034789SMichal Meloun  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20e9034789SMichal Meloun  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21e9034789SMichal Meloun  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22e9034789SMichal Meloun  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23e9034789SMichal Meloun  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24e9034789SMichal Meloun  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25e9034789SMichal Meloun  * SUCH DAMAGE.
26e9034789SMichal Meloun  */
27e9034789SMichal Meloun 
28e9034789SMichal Meloun #include <sys/param.h>
29e9034789SMichal Meloun #include <sys/systm.h>
30e9034789SMichal Meloun #include <sys/bus.h>
31e9034789SMichal Meloun #include <sys/gpio.h>
32e9034789SMichal Meloun #include <sys/kernel.h>
33e9034789SMichal Meloun #include <sys/malloc.h>
34e9034789SMichal Meloun #include <sys/sx.h>
35e9034789SMichal Meloun 
36e9034789SMichal Meloun #include <machine/bus.h>
37e9034789SMichal Meloun 
38e9034789SMichal Meloun #include <dev/fdt/fdt_common.h>
39e9034789SMichal Meloun #include <dev/gpio/gpiobusvar.h>
40e9034789SMichal Meloun 
41e9034789SMichal Meloun #include "max77620.h"
42e9034789SMichal Meloun 
43e9034789SMichal Meloun MALLOC_DEFINE(M_MAX77620_GPIO, "MAX77620 gpio", "MAX77620 GPIO");
44e9034789SMichal Meloun 
45e9034789SMichal Meloun #define	NGPIO		8
46e9034789SMichal Meloun 
47e9034789SMichal Meloun #define	GPIO_LOCK(_sc)	sx_slock(&(_sc)->gpio_lock)
48e9034789SMichal Meloun #define	GPIO_UNLOCK(_sc)	sx_unlock(&(_sc)->gpio_lock)
49e9034789SMichal Meloun #define	GPIO_ASSERT(_sc)	sx_assert(&(_sc)->gpio_lock, SA_LOCKED)
50e9034789SMichal Meloun 
51e9034789SMichal Meloun enum prop_id {
52e9034789SMichal Meloun 	CFG_BIAS_PULL_UP,
53e9034789SMichal Meloun 	CFG_BIAS_PULL_DOWN,
54e9034789SMichal Meloun 	CFG_OPEN_DRAIN,
55e9034789SMichal Meloun 	CFG_PUSH_PULL,
56e9034789SMichal Meloun 
57e9034789SMichal Meloun 	CFG_ACTIVE_FPS_SRC,
58e9034789SMichal Meloun 	CFG_ACTIVE_PWRUP_SLOT,
59e9034789SMichal Meloun 	CFG_ACTIVE_PWRDOWN_SLOT,
60e9034789SMichal Meloun 	CFG_SUSPEND_FPS_SRC,
61e9034789SMichal Meloun 	CFG_SUSPEND_PWRUP_SLOT,
62e9034789SMichal Meloun 	CFG_SUSPEND_PWRDOWN_SLOT,
63e9034789SMichal Meloun 
64e9034789SMichal Meloun 	PROP_ID_MAX_ID
65e9034789SMichal Meloun };
66e9034789SMichal Meloun 
67e9034789SMichal Meloun static const struct {
68e9034789SMichal Meloun 	const char	*name;
69e9034789SMichal Meloun 	enum prop_id  	id;
70e9034789SMichal Meloun } max77620_prop_names[] = {
71e9034789SMichal Meloun 	{"bias-pull-up",			CFG_BIAS_PULL_UP},
72e9034789SMichal Meloun 	{"bias-pull-down",			CFG_BIAS_PULL_DOWN},
73e9034789SMichal Meloun 	{"drive-open-drain",			CFG_OPEN_DRAIN},
74e9034789SMichal Meloun 	{"drive-push-pull",			CFG_PUSH_PULL},
75e9034789SMichal Meloun 	{"maxim,active-fps-source",		CFG_ACTIVE_FPS_SRC},
76e9034789SMichal Meloun 	{"maxim,active-fps-power-up-slot",	CFG_ACTIVE_PWRUP_SLOT},
77e9034789SMichal Meloun 	{"maxim,active-fps-power-down-slot",	CFG_ACTIVE_PWRDOWN_SLOT},
78e9034789SMichal Meloun 	{"maxim,suspend-fps-source",		CFG_SUSPEND_FPS_SRC},
79e9034789SMichal Meloun 	{"maxim,suspend-fps-power-up-slot",	CFG_SUSPEND_PWRUP_SLOT},
80e9034789SMichal Meloun 	{"maxim,suspend-fps-power-down-slot",	CFG_SUSPEND_PWRDOWN_SLOT},
81e9034789SMichal Meloun };
82e9034789SMichal Meloun 
83e9034789SMichal Meloun /* Configuration for one pin group. */
84e9034789SMichal Meloun struct max77620_pincfg {
85e9034789SMichal Meloun 	bool	alt_func;
86e9034789SMichal Meloun 	int	params[PROP_ID_MAX_ID];
87e9034789SMichal Meloun };
88e9034789SMichal Meloun 
89e9034789SMichal Meloun static char *altfnc_table[] = {
90e9034789SMichal Meloun 	"lpm-control-in",
91e9034789SMichal Meloun 	"fps-out",
92e9034789SMichal Meloun 	"32k-out1",
93e9034789SMichal Meloun 	"sd0-dvs-in",
94e9034789SMichal Meloun 	"sd1-dvs-in",
95e9034789SMichal Meloun 	"reference-out",
96e9034789SMichal Meloun };
97e9034789SMichal Meloun 
98e9034789SMichal Meloun struct max77620_gpio_pin {
99e9034789SMichal Meloun 	int		pin_caps;
100e9034789SMichal Meloun 	char		pin_name[GPIOMAXNAME];
101e9034789SMichal Meloun 	uint8_t		reg;
102e9034789SMichal Meloun 
103e9034789SMichal Meloun 	/* Runtime data  */
104e9034789SMichal Meloun 	bool		alt_func;	/* GPIO or alternate function */
105e9034789SMichal Meloun };
106e9034789SMichal Meloun 
107e9034789SMichal Meloun /* --------------------------------------------------------------------------
108e9034789SMichal Meloun  *
109e9034789SMichal Meloun  *  Pinmux functions.
110e9034789SMichal Meloun  */
111e9034789SMichal Meloun static int
max77620_pinmux_get_function(struct max77620_softc * sc,char * name,struct max77620_pincfg * cfg)112e9034789SMichal Meloun max77620_pinmux_get_function(struct max77620_softc *sc, char *name,
113e9034789SMichal Meloun     struct max77620_pincfg *cfg)
114e9034789SMichal Meloun {
115e9034789SMichal Meloun 	int i;
116e9034789SMichal Meloun 
117e9034789SMichal Meloun 	if (strcmp("gpio", name) == 0) {
118e9034789SMichal Meloun 		cfg->alt_func = false;
119e9034789SMichal Meloun 		return (0);
120e9034789SMichal Meloun 	}
121e9034789SMichal Meloun 	for (i = 0; i < nitems(altfnc_table); i++) {
122e9034789SMichal Meloun 		if (strcmp(altfnc_table[i], name) == 0) {
123e9034789SMichal Meloun 			cfg->alt_func = true;
124e9034789SMichal Meloun 			return (0);
125e9034789SMichal Meloun 		}
126e9034789SMichal Meloun 	}
127e9034789SMichal Meloun 	return (-1);
128e9034789SMichal Meloun }
129e9034789SMichal Meloun 
130e9034789SMichal Meloun static int
max77620_pinmux_set_fps(struct max77620_softc * sc,int pin_num,struct max77620_gpio_pin * pin)131e9034789SMichal Meloun max77620_pinmux_set_fps(struct max77620_softc *sc, int pin_num,
132e9034789SMichal Meloun     struct max77620_gpio_pin *pin)
133e9034789SMichal Meloun {
134e9034789SMichal Meloun #if 0
135e9034789SMichal Meloun 	struct max77620_fps_config *fps_config = &mpci->fps_config[pin];
136e9034789SMichal Meloun 	int addr, ret;
137e9034789SMichal Meloun 	int param_val;
138e9034789SMichal Meloun 	int mask, shift;
139e9034789SMichal Meloun 
140e9034789SMichal Meloun 	if ((pin < 1) || (pin > 3))
141e9034789SMichal Meloun 		return (0);
142e9034789SMichal Meloun 
143e9034789SMichal Meloun 	switch (param) {
144e9034789SMichal Meloun 	case MAX77620_ACTIVE_FPS_SOURCE:
145e9034789SMichal Meloun 	case MAX77620_SUSPEND_FPS_SOURCE:
146e9034789SMichal Meloun 		mask = MAX77620_FPS_SRC_MASK;
147e9034789SMichal Meloun 		shift = MAX77620_FPS_SRC_SHIFT;
148e9034789SMichal Meloun 		param_val = fps_config->active_fps_src;
149e9034789SMichal Meloun 		if (param == MAX77620_SUSPEND_FPS_SOURCE)
150e9034789SMichal Meloun 			param_val = fps_config->suspend_fps_src;
151e9034789SMichal Meloun 		break;
152e9034789SMichal Meloun 
153e9034789SMichal Meloun 	case MAX77620_ACTIVE_FPS_POWER_ON_SLOTS:
154e9034789SMichal Meloun 	case MAX77620_SUSPEND_FPS_POWER_ON_SLOTS:
155e9034789SMichal Meloun 		mask = MAX77620_FPS_PU_PERIOD_MASK;
156e9034789SMichal Meloun 		shift = MAX77620_FPS_PU_PERIOD_SHIFT;
157e9034789SMichal Meloun 		param_val = fps_config->active_power_up_slots;
158e9034789SMichal Meloun 		if (param == MAX77620_SUSPEND_FPS_POWER_ON_SLOTS)
159e9034789SMichal Meloun 			param_val = fps_config->suspend_power_up_slots;
160e9034789SMichal Meloun 		break;
161e9034789SMichal Meloun 
162e9034789SMichal Meloun 	case MAX77620_ACTIVE_FPS_POWER_DOWN_SLOTS:
163e9034789SMichal Meloun 	case MAX77620_SUSPEND_FPS_POWER_DOWN_SLOTS:
164e9034789SMichal Meloun 		mask = MAX77620_FPS_PD_PERIOD_MASK;
165e9034789SMichal Meloun 		shift = MAX77620_FPS_PD_PERIOD_SHIFT;
166e9034789SMichal Meloun 		param_val = fps_config->active_power_down_slots;
167e9034789SMichal Meloun 		if (param == MAX77620_SUSPEND_FPS_POWER_DOWN_SLOTS)
168e9034789SMichal Meloun 			param_val = fps_config->suspend_power_down_slots;
169e9034789SMichal Meloun 		break;
170e9034789SMichal Meloun 
171e9034789SMichal Meloun 	default:
172e9034789SMichal Meloun 		dev_err(mpci->dev, "Invalid parameter %d for pin %d\n",
173e9034789SMichal Meloun 			param, pin);
174e9034789SMichal Meloun 		return -EINVAL;
175e9034789SMichal Meloun 	}
176e9034789SMichal Meloun 
177e9034789SMichal Meloun 	if (param_val < 0)
178e9034789SMichal Meloun 		return 0;
179e9034789SMichal Meloun 
180e9034789SMichal Meloun 	ret = regmap_update_bits(mpci->rmap, addr, mask, param_val << shift);
181e9034789SMichal Meloun 	if (ret < 0)
182e9034789SMichal Meloun 		dev_err(mpci->dev, "Reg 0x%02x update failed %d\n", addr, ret);
183e9034789SMichal Meloun 
184e9034789SMichal Meloun 	return ret;
185e9034789SMichal Meloun #endif
186e9034789SMichal Meloun 	return (0);
187e9034789SMichal Meloun }
188e9034789SMichal Meloun 
189e9034789SMichal Meloun static int
max77620_pinmux_config_node(struct max77620_softc * sc,char * pin_name,struct max77620_pincfg * cfg)190e9034789SMichal Meloun max77620_pinmux_config_node(struct max77620_softc *sc, char *pin_name,
191e9034789SMichal Meloun     struct max77620_pincfg *cfg)
192e9034789SMichal Meloun {
193e9034789SMichal Meloun 	struct max77620_gpio_pin *pin;
194e9034789SMichal Meloun 	uint8_t reg;
195e9034789SMichal Meloun 	int pin_num, rv;
196e9034789SMichal Meloun 
197e9034789SMichal Meloun 	for (pin_num = 0; pin_num < sc->gpio_npins; pin_num++) {
198e9034789SMichal Meloun 		if (strcmp(sc->gpio_pins[pin_num]->pin_name, pin_name) == 0)
199e9034789SMichal Meloun 			 break;
200e9034789SMichal Meloun 	}
201e9034789SMichal Meloun 	if (pin_num >= sc->gpio_npins) {
202e9034789SMichal Meloun 		device_printf(sc->dev, "Unknown pin: %s\n", pin_name);
203e9034789SMichal Meloun 		return (ENXIO);
204e9034789SMichal Meloun 	}
205e9034789SMichal Meloun 	pin = sc->gpio_pins[pin_num];
206e9034789SMichal Meloun 
207e9034789SMichal Meloun 	rv = max77620_pinmux_set_fps(sc, pin_num, pin);
208e9034789SMichal Meloun 	if (rv != 0)
209e9034789SMichal Meloun 		return (rv);
210e9034789SMichal Meloun 
211e9034789SMichal Meloun 	rv = RD1(sc, pin->reg, &reg);
212e9034789SMichal Meloun 	if (rv != 0) {
213e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot read GIPO_CFG register\n");
214e9034789SMichal Meloun 		return (ENXIO);
215e9034789SMichal Meloun 	}
216e9034789SMichal Meloun 
217e9034789SMichal Meloun 	if (cfg->alt_func) {
218e9034789SMichal Meloun 		pin->alt_func = true;
219e9034789SMichal Meloun 		sc->gpio_reg_ame |=  1 << pin_num;
220e9034789SMichal Meloun 	} else {
221e9034789SMichal Meloun 		pin->alt_func = false;
222e9034789SMichal Meloun 		sc->gpio_reg_ame &=  ~(1 << pin_num);
223e9034789SMichal Meloun 	}
224e9034789SMichal Meloun 
225e9034789SMichal Meloun 	/* Pull up/down. */
226e9034789SMichal Meloun 	switch (cfg->params[CFG_BIAS_PULL_UP]) {
227e9034789SMichal Meloun 	case 1:
228e9034789SMichal Meloun 		sc->gpio_reg_pue |= 1 << pin_num;
229e9034789SMichal Meloun 		break;
230e9034789SMichal Meloun 	case 0:
231e9034789SMichal Meloun 		sc->gpio_reg_pue &= ~(1 << pin_num);
232e9034789SMichal Meloun 		break;
233e9034789SMichal Meloun 	default:
234e9034789SMichal Meloun 		break;
235e9034789SMichal Meloun 	}
236e9034789SMichal Meloun 
237e9034789SMichal Meloun 	switch (cfg->params[CFG_BIAS_PULL_DOWN]) {
238e9034789SMichal Meloun 	case 1:
239e9034789SMichal Meloun 		sc->gpio_reg_pde |= 1 << pin_num;
240e9034789SMichal Meloun 		break;
241e9034789SMichal Meloun 	case 0:
242e9034789SMichal Meloun 		sc->gpio_reg_pde &= ~(1 << pin_num);
243e9034789SMichal Meloun 		break;
244e9034789SMichal Meloun 	default:
245e9034789SMichal Meloun 		break;
246e9034789SMichal Meloun 	}
247e9034789SMichal Meloun 
248e9034789SMichal Meloun 	/* Open drain/push-pull modes. */
249e9034789SMichal Meloun 	if (cfg->params[CFG_OPEN_DRAIN] == 1) {
250e9034789SMichal Meloun 		reg &= ~MAX77620_REG_GPIO_DRV(~0);
251e9034789SMichal Meloun 		reg |= MAX77620_REG_GPIO_DRV(MAX77620_REG_GPIO_DRV_OPENDRAIN);
252e9034789SMichal Meloun 	}
253e9034789SMichal Meloun 
254e9034789SMichal Meloun 	if (cfg->params[CFG_PUSH_PULL] == 1) {
255e9034789SMichal Meloun 		reg &= ~MAX77620_REG_GPIO_DRV(~0);
256e9034789SMichal Meloun 		reg |= MAX77620_REG_GPIO_DRV(MAX77620_REG_GPIO_DRV_PUSHPULL);
257e9034789SMichal Meloun 	}
258e9034789SMichal Meloun 
259e9034789SMichal Meloun 	rv = WR1(sc, pin->reg, reg);
260e9034789SMichal Meloun 	if (rv != 0) {
261e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot read GIPO_CFG register\n");
262e9034789SMichal Meloun 		return (ENXIO);
263e9034789SMichal Meloun 	}
264e9034789SMichal Meloun 
265e9034789SMichal Meloun 	return (0);
266e9034789SMichal Meloun }
267e9034789SMichal Meloun 
268e9034789SMichal Meloun static int
max77620_pinmux_read_node(struct max77620_softc * sc,phandle_t node,struct max77620_pincfg * cfg,char ** pins,int * lpins)269e9034789SMichal Meloun max77620_pinmux_read_node(struct max77620_softc *sc, phandle_t node,
270e9034789SMichal Meloun      struct max77620_pincfg *cfg, char **pins, int *lpins)
271e9034789SMichal Meloun {
272e9034789SMichal Meloun 	char *function;
273e9034789SMichal Meloun 	int rv, i;
274e9034789SMichal Meloun 
275e9034789SMichal Meloun 	*lpins = OF_getprop_alloc(node, "pins", (void **)pins);
276e9034789SMichal Meloun 	if (*lpins <= 0)
277e9034789SMichal Meloun 		return (ENOENT);
278e9034789SMichal Meloun 
279e9034789SMichal Meloun 	/* Read function (mux) settings. */
280e9034789SMichal Meloun 	rv = OF_getprop_alloc(node, "function", (void **)&function);
281e9034789SMichal Meloun 	if (rv >  0) {
282e9034789SMichal Meloun 		rv = max77620_pinmux_get_function(sc, function, cfg);
283e9034789SMichal Meloun 		if (rv == -1) {
284e9034789SMichal Meloun 			device_printf(sc->dev,
285e9034789SMichal Meloun 			    "Unknown function %s\n", function);
286e9034789SMichal Meloun 			OF_prop_free(function);
287e9034789SMichal Meloun 			return (ENXIO);
288e9034789SMichal Meloun 		}
289e9034789SMichal Meloun 	}
290e9034789SMichal Meloun 
291e9034789SMichal Meloun 	/* Read numeric properties. */
292e9034789SMichal Meloun 	for (i = 0; i < PROP_ID_MAX_ID; i++) {
293e9034789SMichal Meloun 		rv = OF_getencprop(node, max77620_prop_names[i].name,
294e9034789SMichal Meloun 		    &cfg->params[i], sizeof(cfg->params[i]));
295e9034789SMichal Meloun 		if (rv <= 0)
296e9034789SMichal Meloun 			cfg->params[i] = -1;
297e9034789SMichal Meloun 	}
298e9034789SMichal Meloun 
299e9034789SMichal Meloun 	OF_prop_free(function);
300e9034789SMichal Meloun 	return (0);
301e9034789SMichal Meloun }
302e9034789SMichal Meloun 
303e9034789SMichal Meloun static int
max77620_pinmux_process_node(struct max77620_softc * sc,phandle_t node)304e9034789SMichal Meloun max77620_pinmux_process_node(struct max77620_softc *sc, phandle_t node)
305e9034789SMichal Meloun {
306e9034789SMichal Meloun 	struct max77620_pincfg cfg;
307e9034789SMichal Meloun 	char *pins, *pname;
308e9034789SMichal Meloun 	int i, len, lpins, rv;
309e9034789SMichal Meloun 
310e9034789SMichal Meloun 	rv = max77620_pinmux_read_node(sc, node, &cfg, &pins, &lpins);
311e9034789SMichal Meloun 	if (rv != 0)
312e9034789SMichal Meloun 		return (rv);
313e9034789SMichal Meloun 
314e9034789SMichal Meloun 	len = 0;
315e9034789SMichal Meloun 	pname = pins;
316e9034789SMichal Meloun 	do {
317e9034789SMichal Meloun 		i = strlen(pname) + 1;
318e9034789SMichal Meloun 		rv = max77620_pinmux_config_node(sc, pname, &cfg);
319e9034789SMichal Meloun 		if (rv != 0) {
320e9034789SMichal Meloun 			device_printf(sc->dev,
321e9034789SMichal Meloun 			    "Cannot configure pin: %s: %d\n", pname, rv);
322e9034789SMichal Meloun 		}
323e9034789SMichal Meloun 		len += i;
324e9034789SMichal Meloun 		pname += i;
325e9034789SMichal Meloun 	} while (len < lpins);
326e9034789SMichal Meloun 
327e9034789SMichal Meloun 	if (pins != NULL)
328e9034789SMichal Meloun 		OF_prop_free(pins);
329e9034789SMichal Meloun 
330e9034789SMichal Meloun 	return (rv);
331e9034789SMichal Meloun }
332e9034789SMichal Meloun 
max77620_pinmux_configure(device_t dev,phandle_t cfgxref)333e9034789SMichal Meloun int max77620_pinmux_configure(device_t dev, phandle_t cfgxref)
334e9034789SMichal Meloun {
335e9034789SMichal Meloun 	struct max77620_softc *sc;
336e9034789SMichal Meloun 	phandle_t node, cfgnode;
337e9034789SMichal Meloun 	uint8_t	old_reg_pue, old_reg_pde, old_reg_ame;
338e9034789SMichal Meloun 	int rv;
339e9034789SMichal Meloun 
340e9034789SMichal Meloun 	sc = device_get_softc(dev);
341e9034789SMichal Meloun 	cfgnode = OF_node_from_xref(cfgxref);
342e9034789SMichal Meloun 
343e9034789SMichal Meloun 	old_reg_pue =  sc->gpio_reg_pue;
344e9034789SMichal Meloun 	old_reg_pde = sc->gpio_reg_pde;
345e9034789SMichal Meloun 	old_reg_ame = sc->gpio_reg_ame;
346e9034789SMichal Meloun 
347e9034789SMichal Meloun 	for (node = OF_child(cfgnode); node != 0; node = OF_peer(node)) {
348e9034789SMichal Meloun 		if (!ofw_bus_node_status_okay(node))
349e9034789SMichal Meloun 			continue;
350e9034789SMichal Meloun 		rv = max77620_pinmux_process_node(sc, node);
351e9034789SMichal Meloun 		if (rv != 0)
352e9034789SMichal Meloun 			device_printf(dev, "Failed to process pinmux");
353e9034789SMichal Meloun 
354e9034789SMichal Meloun 	}
355e9034789SMichal Meloun 
356e9034789SMichal Meloun 	if (old_reg_pue != sc->gpio_reg_pue) {
357e9034789SMichal Meloun 		rv = WR1(sc, MAX77620_REG_PUE_GPIO, sc->gpio_reg_pue);
358e9034789SMichal Meloun 		if (rv != 0) {
359e9034789SMichal Meloun 			device_printf(sc->dev,
360e9034789SMichal Meloun 			    "Cannot update PUE_GPIO register\n");
361e9034789SMichal Meloun 			return (ENXIO);
362e9034789SMichal Meloun 		}
363e9034789SMichal Meloun 	}
364e9034789SMichal Meloun 
365e9034789SMichal Meloun 	if (old_reg_pde != sc->gpio_reg_pde) {
366e9034789SMichal Meloun 		rv = WR1(sc, MAX77620_REG_PDE_GPIO, sc->gpio_reg_pde);
367e9034789SMichal Meloun 		if (rv != 0) {
368e9034789SMichal Meloun 			device_printf(sc->dev,
369e9034789SMichal Meloun 			    "Cannot update PDE_GPIO register\n");
370e9034789SMichal Meloun 			return (ENXIO);
371e9034789SMichal Meloun 		}
372e9034789SMichal Meloun 	}
373e9034789SMichal Meloun 
374e9034789SMichal Meloun 	if (old_reg_ame != sc->gpio_reg_ame) {
375e9034789SMichal Meloun 		rv = WR1(sc, MAX77620_REG_AME_GPIO, sc->gpio_reg_ame);
376e9034789SMichal Meloun 		if (rv != 0) {
377e9034789SMichal Meloun 			device_printf(sc->dev,
378e9034789SMichal Meloun 			    "Cannot update PDE_GPIO register\n");
379e9034789SMichal Meloun 			return (ENXIO);
380e9034789SMichal Meloun 		}
381e9034789SMichal Meloun 	}
382e9034789SMichal Meloun 
383e9034789SMichal Meloun 	return (0);
384e9034789SMichal Meloun }
385e9034789SMichal Meloun 
386e9034789SMichal Meloun /* --------------------------------------------------------------------------
387e9034789SMichal Meloun  *
388e9034789SMichal Meloun  *  GPIO
389e9034789SMichal Meloun  */
390e9034789SMichal Meloun device_t
max77620_gpio_get_bus(device_t dev)391e9034789SMichal Meloun max77620_gpio_get_bus(device_t dev)
392e9034789SMichal Meloun {
393e9034789SMichal Meloun 	struct max77620_softc *sc;
394e9034789SMichal Meloun 
395e9034789SMichal Meloun 	sc = device_get_softc(dev);
396e9034789SMichal Meloun 	return (sc->gpio_busdev);
397e9034789SMichal Meloun }
398e9034789SMichal Meloun 
399e9034789SMichal Meloun int
max77620_gpio_pin_max(device_t dev,int * maxpin)400e9034789SMichal Meloun max77620_gpio_pin_max(device_t dev, int *maxpin)
401e9034789SMichal Meloun {
402e9034789SMichal Meloun 
403e9034789SMichal Meloun 	*maxpin = NGPIO - 1;
404e9034789SMichal Meloun 	return (0);
405e9034789SMichal Meloun }
406e9034789SMichal Meloun 
407e9034789SMichal Meloun int
max77620_gpio_pin_getcaps(device_t dev,uint32_t pin,uint32_t * caps)408e9034789SMichal Meloun max77620_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
409e9034789SMichal Meloun {
410e9034789SMichal Meloun 	struct max77620_softc *sc;
411e9034789SMichal Meloun 
412e9034789SMichal Meloun 	sc = device_get_softc(dev);
413e9034789SMichal Meloun 	if (pin >= sc->gpio_npins)
414e9034789SMichal Meloun 		return (EINVAL);
415e9034789SMichal Meloun 	GPIO_LOCK(sc);
416e9034789SMichal Meloun 	*caps = sc->gpio_pins[pin]->pin_caps;
417e9034789SMichal Meloun 	GPIO_UNLOCK(sc);
418e9034789SMichal Meloun 	return (0);
419e9034789SMichal Meloun }
420e9034789SMichal Meloun 
421e9034789SMichal Meloun int
max77620_gpio_pin_getname(device_t dev,uint32_t pin,char * name)422e9034789SMichal Meloun max77620_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
423e9034789SMichal Meloun {
424e9034789SMichal Meloun 	struct max77620_softc *sc;
425e9034789SMichal Meloun 
426e9034789SMichal Meloun 	sc = device_get_softc(dev);
427e9034789SMichal Meloun 	if (pin >= sc->gpio_npins)
428e9034789SMichal Meloun 		return (EINVAL);
429e9034789SMichal Meloun 	GPIO_LOCK(sc);
430e9034789SMichal Meloun 	memcpy(name, sc->gpio_pins[pin]->pin_name, GPIOMAXNAME);
431e9034789SMichal Meloun 	GPIO_UNLOCK(sc);
432e9034789SMichal Meloun 	return (0);
433e9034789SMichal Meloun }
434e9034789SMichal Meloun 
435e9034789SMichal Meloun static int
max77620_gpio_get_mode(struct max77620_softc * sc,uint32_t pin_num,uint32_t * out_flags)436e9034789SMichal Meloun max77620_gpio_get_mode(struct max77620_softc *sc, uint32_t pin_num,
437e9034789SMichal Meloun  uint32_t *out_flags)
438e9034789SMichal Meloun {
439e9034789SMichal Meloun 	struct max77620_gpio_pin *pin;
440e9034789SMichal Meloun 	uint8_t reg;
441e9034789SMichal Meloun 	int rv;
442e9034789SMichal Meloun 
443e9034789SMichal Meloun 	pin = sc->gpio_pins[pin_num];
444e9034789SMichal Meloun 	*out_flags = 0;
445e9034789SMichal Meloun 
446e9034789SMichal Meloun 	rv = RD1(sc, pin->reg, &reg);
447e9034789SMichal Meloun 	if (rv != 0) {
448e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot read GIPO_CFG register\n");
449e9034789SMichal Meloun 		return (ENXIO);
450e9034789SMichal Meloun 	}
451e9034789SMichal Meloun 
452e9034789SMichal Meloun 	/* Pin function */
453e9034789SMichal Meloun 	pin->alt_func = sc->gpio_reg_ame & (1 << pin_num);
454e9034789SMichal Meloun 
455e9034789SMichal Meloun 	/* Pull up/down. */
456e9034789SMichal Meloun 	if (sc->gpio_reg_pue & (1 << pin_num))
457e9034789SMichal Meloun 	    *out_flags |=  GPIO_PIN_PULLUP;
458e9034789SMichal Meloun 	if (sc->gpio_reg_pde & (1 << pin_num))
459e9034789SMichal Meloun 	    *out_flags |=  GPIO_PIN_PULLDOWN;
460e9034789SMichal Meloun 
461e9034789SMichal Meloun 	/* Open drain/push-pull modes. */
462e9034789SMichal Meloun 	if (MAX77620_REG_GPIO_DRV_GET(reg) == MAX77620_REG_GPIO_DRV_PUSHPULL)
463e9034789SMichal Meloun 		*out_flags |= GPIO_PIN_PUSHPULL;
464e9034789SMichal Meloun 	else
465e9034789SMichal Meloun 		*out_flags |= GPIO_PIN_OPENDRAIN;
466e9034789SMichal Meloun 
467e9034789SMichal Meloun 	/* Input/output modes. */
468e9034789SMichal Meloun 	if (MAX77620_REG_GPIO_DRV_GET(reg) == MAX77620_REG_GPIO_DRV_PUSHPULL)
469e9034789SMichal Meloun 		*out_flags |= GPIO_PIN_OUTPUT;
470e9034789SMichal Meloun 	else
471e9034789SMichal Meloun 		*out_flags |= GPIO_PIN_OUTPUT | GPIO_PIN_INPUT;
472e9034789SMichal Meloun 	return (0);
473e9034789SMichal Meloun }
474e9034789SMichal Meloun 
475e9034789SMichal Meloun int
max77620_gpio_pin_getflags(device_t dev,uint32_t pin,uint32_t * out_flags)476e9034789SMichal Meloun max77620_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *out_flags)
477e9034789SMichal Meloun {
478e9034789SMichal Meloun 	struct max77620_softc *sc;
479e9034789SMichal Meloun 	int rv;
480e9034789SMichal Meloun 
481e9034789SMichal Meloun 	sc = device_get_softc(dev);
482e9034789SMichal Meloun 	if (pin >= sc->gpio_npins)
483e9034789SMichal Meloun 		return (EINVAL);
484e9034789SMichal Meloun 
485e9034789SMichal Meloun 	GPIO_LOCK(sc);
486e9034789SMichal Meloun #if 0 /* It colide with GPIO regulators */
487e9034789SMichal Meloun 	/* Is pin in GPIO mode ? */
488e9034789SMichal Meloun 	if (sc->gpio_pins[pin]->alt_func) {
489e9034789SMichal Meloun 		GPIO_UNLOCK(sc);
490e9034789SMichal Meloun 		return (ENXIO);
491e9034789SMichal Meloun 	}
492e9034789SMichal Meloun #endif
493e9034789SMichal Meloun 	rv = max77620_gpio_get_mode(sc, pin, out_flags);
494e9034789SMichal Meloun 	GPIO_UNLOCK(sc);
495e9034789SMichal Meloun 
496e9034789SMichal Meloun 	return (rv);
497e9034789SMichal Meloun }
498e9034789SMichal Meloun 
499e9034789SMichal Meloun int
max77620_gpio_pin_setflags(device_t dev,uint32_t pin_num,uint32_t flags)500e9034789SMichal Meloun max77620_gpio_pin_setflags(device_t dev, uint32_t pin_num, uint32_t flags)
501e9034789SMichal Meloun {
502e9034789SMichal Meloun 	struct max77620_softc *sc;
503e9034789SMichal Meloun 	struct max77620_gpio_pin *pin;
504e9034789SMichal Meloun 	uint8_t reg;
505e9034789SMichal Meloun 	uint8_t	old_reg_pue, old_reg_pde;
506e9034789SMichal Meloun 	int rv;
507e9034789SMichal Meloun 
508e9034789SMichal Meloun 	sc = device_get_softc(dev);
509e9034789SMichal Meloun 	if (pin_num >= sc->gpio_npins)
510e9034789SMichal Meloun 		return (EINVAL);
511e9034789SMichal Meloun 
512e9034789SMichal Meloun 	pin = sc->gpio_pins[pin_num];
513e9034789SMichal Meloun 
514e9034789SMichal Meloun 	GPIO_LOCK(sc);
515e9034789SMichal Meloun 
516e9034789SMichal Meloun #if 0 /* It colide with GPIO regulators */
517e9034789SMichal Meloun 	/* Is pin in GPIO mode ? */
518e9034789SMichal Meloun 	if (pin->alt_func) {
519e9034789SMichal Meloun 		GPIO_UNLOCK(sc);
520e9034789SMichal Meloun 		return (ENXIO);
521e9034789SMichal Meloun 	}
522e9034789SMichal Meloun #endif
523e9034789SMichal Meloun 
524e9034789SMichal Meloun 	old_reg_pue =  sc->gpio_reg_pue;
525e9034789SMichal Meloun 	old_reg_pde = sc->gpio_reg_pde;
526e9034789SMichal Meloun 
527e9034789SMichal Meloun 	rv = RD1(sc, pin->reg, &reg);
528e9034789SMichal Meloun 	if (rv != 0) {
529e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot read GIPO_CFG register\n");
530e9034789SMichal Meloun 		GPIO_UNLOCK(sc);
531e9034789SMichal Meloun 		return (ENXIO);
532e9034789SMichal Meloun 	}
533e9034789SMichal Meloun 
534e9034789SMichal Meloun 	if (flags & GPIO_PIN_PULLUP)
535e9034789SMichal Meloun 		sc->gpio_reg_pue |= 1 << pin_num;
536e9034789SMichal Meloun 	else
537e9034789SMichal Meloun 		sc->gpio_reg_pue &= ~(1 << pin_num);
538e9034789SMichal Meloun 
539e9034789SMichal Meloun 	if (flags & GPIO_PIN_PULLDOWN)
540e9034789SMichal Meloun 		sc->gpio_reg_pde |= 1 << pin_num;
541e9034789SMichal Meloun 	else
542e9034789SMichal Meloun 		sc->gpio_reg_pde &= ~(1 << pin_num);
543e9034789SMichal Meloun 
544e9034789SMichal Meloun 	if (flags & GPIO_PIN_INPUT) {
545e9034789SMichal Meloun 		reg &= ~MAX77620_REG_GPIO_DRV(~0);
546e9034789SMichal Meloun 		reg |= MAX77620_REG_GPIO_DRV(MAX77620_REG_GPIO_DRV_OPENDRAIN);
547e9034789SMichal Meloun 		reg &= ~MAX77620_REG_GPIO_OUTPUT_VAL(~0);
548e9034789SMichal Meloun 		reg |= MAX77620_REG_GPIO_OUTPUT_VAL(1);
549e9034789SMichal Meloun 
550e9034789SMichal Meloun 	} else if (((flags & GPIO_PIN_OUTPUT) &&
551e9034789SMichal Meloun 	    (flags & GPIO_PIN_OPENDRAIN) == 0) ||
552e9034789SMichal Meloun 	    (flags & GPIO_PIN_PUSHPULL)) {
553e9034789SMichal Meloun 		reg &= ~MAX77620_REG_GPIO_DRV(~0);
554e9034789SMichal Meloun 		reg |= MAX77620_REG_GPIO_DRV(MAX77620_REG_GPIO_DRV_PUSHPULL);
555e9034789SMichal Meloun 	} else {
556e9034789SMichal Meloun 		reg &= ~MAX77620_REG_GPIO_DRV(~0);
557e9034789SMichal Meloun 		reg |= MAX77620_REG_GPIO_DRV(MAX77620_REG_GPIO_DRV_OPENDRAIN);
558e9034789SMichal Meloun 	}
559e9034789SMichal Meloun 
560e9034789SMichal Meloun 	rv = WR1(sc, pin->reg, reg);
561e9034789SMichal Meloun 	if (rv != 0) {
562e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot read GIPO_CFG register\n");
563e9034789SMichal Meloun 		return (ENXIO);
564e9034789SMichal Meloun 	}
565e9034789SMichal Meloun 	if (old_reg_pue != sc->gpio_reg_pue) {
566e9034789SMichal Meloun 		rv = WR1(sc, MAX77620_REG_PUE_GPIO, sc->gpio_reg_pue);
567e9034789SMichal Meloun 		if (rv != 0) {
568e9034789SMichal Meloun 			device_printf(sc->dev,
569e9034789SMichal Meloun 			    "Cannot update PUE_GPIO register\n");
570e9034789SMichal Meloun 			GPIO_UNLOCK(sc);
571e9034789SMichal Meloun 			return (ENXIO);
572e9034789SMichal Meloun 		}
573e9034789SMichal Meloun 	}
574e9034789SMichal Meloun 
575e9034789SMichal Meloun 	if (old_reg_pde != sc->gpio_reg_pde) {
576e9034789SMichal Meloun 		rv = WR1(sc, MAX77620_REG_PDE_GPIO, sc->gpio_reg_pde);
577e9034789SMichal Meloun 		if (rv != 0) {
578e9034789SMichal Meloun 			device_printf(sc->dev,
579e9034789SMichal Meloun 			    "Cannot update PDE_GPIO register\n");
580e9034789SMichal Meloun 			GPIO_UNLOCK(sc);
581e9034789SMichal Meloun 			return (ENXIO);
582e9034789SMichal Meloun 		}
583e9034789SMichal Meloun 	}
584e9034789SMichal Meloun 
585e9034789SMichal Meloun 	GPIO_UNLOCK(sc);
586e9034789SMichal Meloun 	return (0);
587e9034789SMichal Meloun }
588e9034789SMichal Meloun 
589e9034789SMichal Meloun int
max77620_gpio_pin_set(device_t dev,uint32_t pin,uint32_t val)590e9034789SMichal Meloun max77620_gpio_pin_set(device_t dev, uint32_t pin, uint32_t val)
591e9034789SMichal Meloun {
592e9034789SMichal Meloun 	struct max77620_softc *sc;
593e9034789SMichal Meloun 	int rv;
594e9034789SMichal Meloun 
595e9034789SMichal Meloun 	sc = device_get_softc(dev);
596e9034789SMichal Meloun 	if (pin >= sc->gpio_npins)
597e9034789SMichal Meloun 		return (EINVAL);
598e9034789SMichal Meloun 
599e9034789SMichal Meloun 	GPIO_LOCK(sc);
600e9034789SMichal Meloun 	rv = RM1(sc, sc->gpio_pins[pin]->reg, MAX77620_REG_GPIO_OUTPUT_VAL(~0),
601e9034789SMichal Meloun 	     MAX77620_REG_GPIO_OUTPUT_VAL(val));
602e9034789SMichal Meloun 	GPIO_UNLOCK(sc);
603e9034789SMichal Meloun 	return (rv);
604e9034789SMichal Meloun }
605e9034789SMichal Meloun 
606e9034789SMichal Meloun int
max77620_gpio_pin_get(device_t dev,uint32_t pin,uint32_t * val)607e9034789SMichal Meloun max77620_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *val)
608e9034789SMichal Meloun {
609e9034789SMichal Meloun 	struct max77620_softc *sc;
610e9034789SMichal Meloun 	uint8_t tmp;
611e9034789SMichal Meloun 	int rv;
612e9034789SMichal Meloun 
613e9034789SMichal Meloun 	sc = device_get_softc(dev);
614e9034789SMichal Meloun 	if (pin >= sc->gpio_npins)
615e9034789SMichal Meloun 		return (EINVAL);
616e9034789SMichal Meloun 
617e9034789SMichal Meloun 	GPIO_LOCK(sc);
618e9034789SMichal Meloun 	rv = RD1(sc, sc->gpio_pins[pin]->reg, &tmp);
619e9034789SMichal Meloun 
620e9034789SMichal Meloun 	if (MAX77620_REG_GPIO_DRV_GET(tmp) == MAX77620_REG_GPIO_DRV_PUSHPULL)
621e9034789SMichal Meloun 		*val = MAX77620_REG_GPIO_OUTPUT_VAL_GET(tmp);
622e9034789SMichal Meloun 	else
623e9034789SMichal Meloun 		*val = MAX77620_REG_GPIO_INPUT_VAL_GET(tmp);
624e9034789SMichal Meloun 	GPIO_UNLOCK(sc);
625e9034789SMichal Meloun 	if (rv != 0)
626e9034789SMichal Meloun 		return (rv);
627e9034789SMichal Meloun 
628e9034789SMichal Meloun 	return (0);
629e9034789SMichal Meloun }
630e9034789SMichal Meloun 
631e9034789SMichal Meloun int
max77620_gpio_pin_toggle(device_t dev,uint32_t pin)632e9034789SMichal Meloun max77620_gpio_pin_toggle(device_t dev, uint32_t pin)
633e9034789SMichal Meloun {
634e9034789SMichal Meloun 	struct max77620_softc *sc;
635e9034789SMichal Meloun 	uint8_t tmp;
636e9034789SMichal Meloun 	int rv;
637e9034789SMichal Meloun 
638e9034789SMichal Meloun 	sc = device_get_softc(dev);
639e9034789SMichal Meloun 	if (pin >= sc->gpio_npins)
640e9034789SMichal Meloun 		return (EINVAL);
641e9034789SMichal Meloun 
642e9034789SMichal Meloun 	GPIO_LOCK(sc);
643e9034789SMichal Meloun 	rv = RD1(sc, sc->gpio_pins[pin]->reg, &tmp);
644e9034789SMichal Meloun 	if (rv != 0) {
645e9034789SMichal Meloun 		GPIO_UNLOCK(sc);
646e9034789SMichal Meloun 		return (rv);
647e9034789SMichal Meloun 	}
648e9034789SMichal Meloun 	tmp ^= MAX77620_REG_GPIO_OUTPUT_VAL(~0);
649e9034789SMichal Meloun 	rv = RM1(sc, sc->gpio_pins[pin]->reg, MAX77620_REG_GPIO_OUTPUT_VAL(~0),
650e9034789SMichal Meloun 	   tmp);
651e9034789SMichal Meloun 	GPIO_UNLOCK(sc);
652e9034789SMichal Meloun 	return (0);
653e9034789SMichal Meloun }
654e9034789SMichal Meloun 
655e9034789SMichal Meloun int
max77620_gpio_map_gpios(device_t dev,phandle_t pdev,phandle_t gparent,int gcells,pcell_t * gpios,uint32_t * pin,uint32_t * flags)656e9034789SMichal Meloun max77620_gpio_map_gpios(device_t dev, phandle_t pdev, phandle_t gparent,
657e9034789SMichal Meloun     int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
658e9034789SMichal Meloun {
659e9034789SMichal Meloun 
660e9034789SMichal Meloun 	if (gcells != 2)
661e9034789SMichal Meloun 		return (ERANGE);
662e9034789SMichal Meloun 	*pin = gpios[0];
663e9034789SMichal Meloun 	*flags= gpios[1];
664e9034789SMichal Meloun 	return (0);
665e9034789SMichal Meloun }
666e9034789SMichal Meloun 
667e9034789SMichal Meloun int
max77620_gpio_attach(struct max77620_softc * sc,phandle_t node)668e9034789SMichal Meloun max77620_gpio_attach(struct max77620_softc *sc, phandle_t node)
669e9034789SMichal Meloun {
670e9034789SMichal Meloun 	struct max77620_gpio_pin *pin;
671e9034789SMichal Meloun 	int i, rv;
672e9034789SMichal Meloun 
673e9034789SMichal Meloun 	sx_init(&sc->gpio_lock, "MAX77620 GPIO lock");
674e9034789SMichal Meloun 
675e9034789SMichal Meloun 	sc->gpio_busdev = gpiobus_attach_bus(sc->dev);
676e9034789SMichal Meloun 	if (sc->gpio_busdev == NULL)
677e9034789SMichal Meloun 		return (ENXIO);
678e9034789SMichal Meloun 
679e9034789SMichal Meloun 	rv = RD1(sc, MAX77620_REG_PUE_GPIO, &sc->gpio_reg_pue);
680e9034789SMichal Meloun 	if (rv != 0) {
681e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot read PUE_GPIO register\n");
682e9034789SMichal Meloun 		return (ENXIO);
683e9034789SMichal Meloun 	}
684e9034789SMichal Meloun 
685e9034789SMichal Meloun 	rv = RD1(sc, MAX77620_REG_PDE_GPIO, &sc->gpio_reg_pde);
686e9034789SMichal Meloun 	if (rv != 0) {
687e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot read PDE_GPIO register\n");
688e9034789SMichal Meloun 		return (ENXIO);
689e9034789SMichal Meloun 	}
690e9034789SMichal Meloun 
691e9034789SMichal Meloun 	rv = RD1(sc, MAX77620_REG_AME_GPIO, &sc->gpio_reg_ame);
692e9034789SMichal Meloun 	if (rv != 0) {
693e9034789SMichal Meloun 		device_printf(sc->dev, "Cannot read AME_GPIO register\n");
694e9034789SMichal Meloun 		return (ENXIO);
695e9034789SMichal Meloun 	}
696e9034789SMichal Meloun 
697e9034789SMichal Meloun 	sc->gpio_npins = NGPIO;
698e9034789SMichal Meloun 	sc->gpio_pins = malloc(sizeof(struct max77620_gpio_pin *) *
699e9034789SMichal Meloun 	    sc->gpio_npins, M_MAX77620_GPIO, M_WAITOK | M_ZERO);
700e9034789SMichal Meloun 	for (i = 0; i < sc->gpio_npins; i++) {
701e9034789SMichal Meloun 		sc->gpio_pins[i] = malloc(sizeof(struct max77620_gpio_pin),
702e9034789SMichal Meloun 		    M_MAX77620_GPIO, M_WAITOK | M_ZERO);
703e9034789SMichal Meloun 		pin = sc->gpio_pins[i];
704e9034789SMichal Meloun 		sprintf(pin->pin_name, "gpio%d", i);
705e9034789SMichal Meloun 		pin->pin_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT  |
706e9034789SMichal Meloun 		    GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL |
707e9034789SMichal Meloun 		    GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN;
708e9034789SMichal Meloun 		pin->reg = MAX77620_REG_GPIO0 + i;
709e9034789SMichal Meloun 	}
710e9034789SMichal Meloun 
711e9034789SMichal Meloun 	return (0);
712e9034789SMichal Meloun }
713