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