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, ®);
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, ®);
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, ®);
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