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