1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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
46MALLOC_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
54enum 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
70static 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. */
87struct max77620_pincfg {
88	bool	alt_func;
89	int	params[PROP_ID_MAX_ID];
90};
91
92static 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
101struct 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 */
114static int
115max77620_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
133static int
134max77620_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
192static int
193max77620_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
271static int
272max77620_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
306static int
307max77620_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
336int 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 */
393device_t
394max77620_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
402int
403max77620_gpio_pin_max(device_t dev, int *maxpin)
404{
405
406	*maxpin = NGPIO - 1;
407	return (0);
408}
409
410int
411max77620_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
424int
425max77620_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
438static int
439max77620_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
478int
479max77620_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
502int
503max77620_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
592int
593max77620_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
609int
610max77620_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
634int
635max77620_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
658int
659max77620_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
670int
671max77620_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