2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright 2020 Michal Meloun <mmel@FreeBSD.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
28 #include <sys/param.h>
29 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/malloc.h>
36 #include <machine/bus.h>
38 #include <dev/fdt/fdt_common.h>
39 #include <dev/gpio/gpiobusvar.h>
43 MALLOC_DEFINE(M_MAX77620_GPIO
, "MAX77620 gpio", "MAX77620 GPIO");
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)
58 CFG_ACTIVE_PWRUP_SLOT
,
59 CFG_ACTIVE_PWRDOWN_SLOT
,
61 CFG_SUSPEND_PWRUP_SLOT
,
62 CFG_SUSPEND_PWRDOWN_SLOT
,
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
},
83 /* Configuration for one pin group. */
84 struct max77620_pincfg
{
86 int params
[PROP_ID_MAX_ID
];
89 static char *altfnc_table
[] = {
98 struct max77620_gpio_pin
{
100 char pin_name
[GPIOMAXNAME
];
104 bool alt_func
; /* GPIO or alternate function */
107 /* --------------------------------------------------------------------------
112 max77620_pinmux_get_function(struct max77620_softc
*sc
, char *name
,
113 struct max77620_pincfg
*cfg
)
117 if (strcmp("gpio", name
) == 0) {
118 cfg
->alt_func
= false;
121 for (i
= 0; i
< nitems(altfnc_table
); i
++) {
122 if (strcmp(altfnc_table
[i
], name
) == 0) {
123 cfg
->alt_func
= true;
131 max77620_pinmux_set_fps(struct max77620_softc
*sc
, int pin_num
,
132 struct max77620_gpio_pin
*pin
)
135 struct max77620_fps_config
*fps_config
= &mpci
->fps_config
[pin
];
140 if ((pin
< 1) || (pin
> 3))
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
;
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
;
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
;
172 dev_err(mpci
->dev
, "Invalid parameter %d for pin %d\n",
180 ret
= regmap_update_bits(mpci
->rmap
, addr
, mask
, param_val
<< shift
);
182 dev_err(mpci
->dev
, "Reg 0x%02x update failed %d\n", addr
, ret
);
190 max77620_pinmux_config_node(struct max77620_softc
*sc
, char *pin_name
,
191 struct max77620_pincfg
*cfg
)
193 struct max77620_gpio_pin
*pin
;
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)
201 if (pin_num
>= sc
->gpio_npins
) {
202 device_printf(sc
->dev
, "Unknown pin: %s\n", pin_name
);
205 pin
= sc
->gpio_pins
[pin_num
];
207 rv
= max77620_pinmux_set_fps(sc
, pin_num
, pin
);
211 rv
= RD1(sc
, pin
->reg
, ®
);
213 device_printf(sc
->dev
, "Cannot read GIPO_CFG register\n");
218 pin
->alt_func
= true;
219 sc
->gpio_reg_ame
|= 1 << pin_num
;
221 pin
->alt_func
= false;
222 sc
->gpio_reg_ame
&= ~(1 << pin_num
);
226 switch (cfg
->params
[CFG_BIAS_PULL_UP
]) {
228 sc
->gpio_reg_pue
|= 1 << pin_num
;
231 sc
->gpio_reg_pue
&= ~(1 << pin_num
);
237 switch (cfg
->params
[CFG_BIAS_PULL_DOWN
]) {
239 sc
->gpio_reg_pde
|= 1 << pin_num
;
242 sc
->gpio_reg_pde
&= ~(1 << pin_num
);
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
);
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
);
259 rv
= WR1(sc
, pin
->reg
, reg
);
261 device_printf(sc
->dev
, "Cannot read GIPO_CFG register\n");
269 max77620_pinmux_read_node(struct max77620_softc
*sc
, phandle_t node
,
270 struct max77620_pincfg
*cfg
, char **pins
, int *lpins
)
275 *lpins
= OF_getprop_alloc(node
, "pins", (void **)pins
);
279 /* Read function (mux) settings. */
280 rv
= OF_getprop_alloc(node
, "function", (void **)&function
);
282 rv
= max77620_pinmux_get_function(sc
, function
, cfg
);
284 device_printf(sc
->dev
,
285 "Unknown function %s\n", function
);
286 OF_prop_free(function
);
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
]));
299 OF_prop_free(function
);
304 max77620_pinmux_process_node(struct max77620_softc
*sc
, phandle_t node
)
306 struct max77620_pincfg cfg
;
308 int i
, len
, lpins
, rv
;
310 rv
= max77620_pinmux_read_node(sc
, node
, &cfg
, &pins
, &lpins
);
317 i
= strlen(pname
) + 1;
318 rv
= max77620_pinmux_config_node(sc
, pname
, &cfg
);
320 device_printf(sc
->dev
,
321 "Cannot configure pin: %s: %d\n", pname
, rv
);
325 } while (len
< lpins
);
333 int max77620_pinmux_configure(device_t dev
, phandle_t cfgxref
)
335 struct max77620_softc
*sc
;
336 phandle_t node
, cfgnode
;
337 uint8_t old_reg_pue
, old_reg_pde
, old_reg_ame
;
340 sc
= device_get_softc(dev
);
341 cfgnode
= OF_node_from_xref(cfgxref
);
343 old_reg_pue
= sc
->gpio_reg_pue
;
344 old_reg_pde
= sc
->gpio_reg_pde
;
345 old_reg_ame
= sc
->gpio_reg_ame
;
347 for (node
= OF_child(cfgnode
); node
!= 0; node
= OF_peer(node
)) {
348 if (!ofw_bus_node_status_okay(node
))
350 rv
= max77620_pinmux_process_node(sc
, node
);
352 device_printf(dev
, "Failed to process pinmux");
356 if (old_reg_pue
!= sc
->gpio_reg_pue
) {
357 rv
= WR1(sc
, MAX77620_REG_PUE_GPIO
, sc
->gpio_reg_pue
);
359 device_printf(sc
->dev
,
360 "Cannot update PUE_GPIO register\n");
365 if (old_reg_pde
!= sc
->gpio_reg_pde
) {
366 rv
= WR1(sc
, MAX77620_REG_PDE_GPIO
, sc
->gpio_reg_pde
);
368 device_printf(sc
->dev
,
369 "Cannot update PDE_GPIO register\n");
374 if (old_reg_ame
!= sc
->gpio_reg_ame
) {
375 rv
= WR1(sc
, MAX77620_REG_AME_GPIO
, sc
->gpio_reg_ame
);
377 device_printf(sc
->dev
,
378 "Cannot update PDE_GPIO register\n");
386 /* --------------------------------------------------------------------------
391 max77620_gpio_get_bus(device_t dev
)
393 struct max77620_softc
*sc
;
395 sc
= device_get_softc(dev
);
396 return (sc
->gpio_busdev
);
400 max77620_gpio_pin_max(device_t dev
, int *maxpin
)
408 max77620_gpio_pin_getcaps(device_t dev
, uint32_t pin
, uint32_t *caps
)
410 struct max77620_softc
*sc
;
412 sc
= device_get_softc(dev
);
413 if (pin
>= sc
->gpio_npins
)
416 *caps
= sc
->gpio_pins
[pin
]->pin_caps
;
422 max77620_gpio_pin_getname(device_t dev
, uint32_t pin
, char *name
)
424 struct max77620_softc
*sc
;
426 sc
= device_get_softc(dev
);
427 if (pin
>= sc
->gpio_npins
)
430 memcpy(name
, sc
->gpio_pins
[pin
]->pin_name
, GPIOMAXNAME
);
436 max77620_gpio_get_mode(struct max77620_softc
*sc
, uint32_t pin_num
,
439 struct max77620_gpio_pin
*pin
;
443 pin
= sc
->gpio_pins
[pin_num
];
446 rv
= RD1(sc
, pin
->reg
, ®
);
448 device_printf(sc
->dev
, "Cannot read GIPO_CFG register\n");
453 pin
->alt_func
= sc
->gpio_reg_ame
& (1 << pin_num
);
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
;
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
;
465 *out_flags
|= GPIO_PIN_OPENDRAIN
;
467 /* Input/output modes. */
468 if (MAX77620_REG_GPIO_DRV_GET(reg
) == MAX77620_REG_GPIO_DRV_PUSHPULL
)
469 *out_flags
|= GPIO_PIN_OUTPUT
;
471 *out_flags
|= GPIO_PIN_OUTPUT
| GPIO_PIN_INPUT
;
476 max77620_gpio_pin_getflags(device_t dev
, uint32_t pin
, uint32_t *out_flags
)
478 struct max77620_softc
*sc
;
481 sc
= device_get_softc(dev
);
482 if (pin
>= sc
->gpio_npins
)
486 #if 0 /* It colide with GPIO regulators */
487 /* Is pin in GPIO mode ? */
488 if (sc
->gpio_pins
[pin
]->alt_func
) {
493 rv
= max77620_gpio_get_mode(sc
, pin
, out_flags
);
500 max77620_gpio_pin_setflags(device_t dev
, uint32_t pin_num
, uint32_t flags
)
502 struct max77620_softc
*sc
;
503 struct max77620_gpio_pin
*pin
;
505 uint8_t old_reg_pue
, old_reg_pde
;
508 sc
= device_get_softc(dev
);
509 if (pin_num
>= sc
->gpio_npins
)
512 pin
= sc
->gpio_pins
[pin_num
];
516 #if 0 /* It colide with GPIO regulators */
517 /* Is pin in GPIO mode ? */
524 old_reg_pue
= sc
->gpio_reg_pue
;
525 old_reg_pde
= sc
->gpio_reg_pde
;
527 rv
= RD1(sc
, pin
->reg
, ®
);
529 device_printf(sc
->dev
, "Cannot read GIPO_CFG register\n");
534 if (flags
& GPIO_PIN_PULLUP
)
535 sc
->gpio_reg_pue
|= 1 << pin_num
;
537 sc
->gpio_reg_pue
&= ~(1 << pin_num
);
539 if (flags
& GPIO_PIN_PULLDOWN
)
540 sc
->gpio_reg_pde
|= 1 << pin_num
;
542 sc
->gpio_reg_pde
&= ~(1 << pin_num
);
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);
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
);
556 reg
&= ~MAX77620_REG_GPIO_DRV(~0);
557 reg
|= MAX77620_REG_GPIO_DRV(MAX77620_REG_GPIO_DRV_OPENDRAIN
);
560 rv
= WR1(sc
, pin
->reg
, reg
);
562 device_printf(sc
->dev
, "Cannot read GIPO_CFG register\n");
565 if (old_reg_pue
!= sc
->gpio_reg_pue
) {
566 rv
= WR1(sc
, MAX77620_REG_PUE_GPIO
, sc
->gpio_reg_pue
);
568 device_printf(sc
->dev
,
569 "Cannot update PUE_GPIO register\n");
575 if (old_reg_pde
!= sc
->gpio_reg_pde
) {
576 rv
= WR1(sc
, MAX77620_REG_PDE_GPIO
, sc
->gpio_reg_pde
);
578 device_printf(sc
->dev
,
579 "Cannot update PDE_GPIO register\n");
590 max77620_gpio_pin_set(device_t dev
, uint32_t pin
, uint32_t val
)
592 struct max77620_softc
*sc
;
595 sc
= device_get_softc(dev
);
596 if (pin
>= sc
->gpio_npins
)
600 rv
= RM1(sc
, sc
->gpio_pins
[pin
]->reg
, MAX77620_REG_GPIO_OUTPUT_VAL(~0),
601 MAX77620_REG_GPIO_OUTPUT_VAL(val
));
607 max77620_gpio_pin_get(device_t dev
, uint32_t pin
, uint32_t *val
)
609 struct max77620_softc
*sc
;
613 sc
= device_get_softc(dev
);
614 if (pin
>= sc
->gpio_npins
)
618 rv
= RD1(sc
, sc
->gpio_pins
[pin
]->reg
, &tmp
);
620 if (MAX77620_REG_GPIO_DRV_GET(tmp
) == MAX77620_REG_GPIO_DRV_PUSHPULL
)
621 *val
= MAX77620_REG_GPIO_OUTPUT_VAL_GET(tmp
);
623 *val
= MAX77620_REG_GPIO_INPUT_VAL_GET(tmp
);
632 max77620_gpio_pin_toggle(device_t dev
, uint32_t pin
)
634 struct max77620_softc
*sc
;
638 sc
= device_get_softc(dev
);
639 if (pin
>= sc
->gpio_npins
)
643 rv
= RD1(sc
, sc
->gpio_pins
[pin
]->reg
, &tmp
);
648 tmp
^= MAX77620_REG_GPIO_OUTPUT_VAL(~0);
649 rv
= RM1(sc
, sc
->gpio_pins
[pin
]->reg
, MAX77620_REG_GPIO_OUTPUT_VAL(~0),
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
)
668 max77620_gpio_attach(struct max77620_softc
*sc
, phandle_t node
)
670 struct max77620_gpio_pin
*pin
;
673 sx_init(&sc
->gpio_lock
, "MAX77620 GPIO lock");
675 sc
->gpio_busdev
= gpiobus_attach_bus(sc
->dev
);
676 if (sc
->gpio_busdev
== NULL
)
679 rv
= RD1(sc
, MAX77620_REG_PUE_GPIO
, &sc
->gpio_reg_pue
);
681 device_printf(sc
->dev
, "Cannot read PUE_GPIO register\n");
685 rv
= RD1(sc
, MAX77620_REG_PDE_GPIO
, &sc
->gpio_reg_pde
);
687 device_printf(sc
->dev
, "Cannot read PDE_GPIO register\n");
691 rv
= RD1(sc
, MAX77620_REG_AME_GPIO
, &sc
->gpio_reg_ame
);
693 device_printf(sc
->dev
, "Cannot read AME_GPIO register\n");
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
;