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