Implement subroutines for parsing out some of the generic properties

specified in the pinctrl bindings, and adapt Meson, Rockchip, and
Allwinner pinctrl back-ends to use them.

Ok jmcneill@
This commit is contained in:
thorpej 2019-01-23 04:21:54 +00:00
parent b155c19ac3
commit dfaf6e7909
6 changed files with 275 additions and 74 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: meson_pinctrl.c,v 1.1 2019/01/19 20:56:03 jmcneill Exp $ */
/* $NetBSD: meson_pinctrl.c,v 1.2 2019/01/23 04:21:54 thorpej Exp $ */
/*-
* Copyright (c) 2019 Jared D. McNeill <jmcneill@invisible.ca>
@ -29,7 +29,7 @@
#include "opt_soc.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: meson_pinctrl.c,v 1.1 2019/01/19 20:56:03 jmcneill Exp $");
__KERNEL_RCSID(0, "$NetBSD: meson_pinctrl.c,v 1.2 2019/01/23 04:21:54 thorpej Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@ -170,10 +170,9 @@ meson_pinctrl_set_config(device_t dev, const void *data, size_t len)
if (mux == -1)
return -1;
groups_len = OF_getproplen(mux, "groups");
if (groups_len <= 0)
groups = fdtbus_pinctrl_parse_groups(mux, &groups_len);
if (groups == NULL)
return -1;
groups = fdtbus_get_string(mux, "groups");
for (; groups_len > 0;
groups_len -= strlen(groups) + 1, groups += strlen(groups) + 1) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: rk3328_iomux.c,v 1.1 2018/08/12 16:48:04 jmcneill Exp $ */
/* $NetBSD: rk3328_iomux.c,v 1.2 2019/01/23 04:21:54 thorpej Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rk3328_iomux.c,v 1.1 2018/08/12 16:48:04 jmcneill Exp $");
__KERNEL_RCSID(0, "$NetBSD: rk3328_iomux.c,v 1.2 2019/01/23 04:21:54 thorpej Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@ -190,42 +190,49 @@ rk3328_iomux_set_mux(struct rk3328_iomux_softc *sc, u_int bank, u_int idx, u_int
static int
rk3328_iomux_config(struct rk3328_iomux_softc *sc, const int phandle, u_int bank, u_int idx, u_int mux)
{
u_int drv;
if (of_hasprop(phandle, "bias-disable"))
const int bias = fdtbus_pinctrl_parse_bias(phandle, NULL);
switch (bias) {
case 0:
rk3328_iomux_set_bias(sc, bank, idx, GRF_GPIO_P_CTL_Z);
else if (of_hasprop(phandle, "bias-pull-up"))
break;
case GPIO_PIN_PULLUP:
rk3328_iomux_set_bias(sc, bank, idx, GRF_GPIO_P_CTL_PULLUP);
else if (of_hasprop(phandle, "bias-pull-down"))
break;
case GPIO_PIN_PULLDOWN:
rk3328_iomux_set_bias(sc, bank, idx, GRF_GPIO_P_CTL_PULLDOWN);
break;
}
if (of_getprop_uint32(phandle, "drive-strength", &drv) == 0) {
switch (drv) {
case 2:
rk3328_iomux_set_drive_strength(sc, bank, idx, GRF_GPIO_E_CTL_2MA);
break;
case 4:
rk3328_iomux_set_drive_strength(sc, bank, idx, GRF_GPIO_E_CTL_4MA);
break;
case 8:
rk3328_iomux_set_drive_strength(sc, bank, idx, GRF_GPIO_E_CTL_8MA);
break;
case 12:
rk3328_iomux_set_drive_strength(sc, bank, idx, GRF_GPIO_E_CTL_12MA);
break;
default:
aprint_error_dev(sc->sc_dev, "unsupported drive-strength %u\n", drv);
return EINVAL;
}
const int drv = fdtbus_pinctrl_parse_drive_strength(phandle);
switch (drv) {
case -1:
break;
case 2:
rk3328_iomux_set_drive_strength(sc, bank, idx, GRF_GPIO_E_CTL_2MA);
break;
case 4:
rk3328_iomux_set_drive_strength(sc, bank, idx, GRF_GPIO_E_CTL_4MA);
break;
case 8:
rk3328_iomux_set_drive_strength(sc, bank, idx, GRF_GPIO_E_CTL_8MA);
break;
case 12:
rk3328_iomux_set_drive_strength(sc, bank, idx, GRF_GPIO_E_CTL_12MA);
break;
default:
aprint_error_dev(sc->sc_dev, "unsupported drive-strength %u\n", drv);
return EINVAL;
}
#if notyet
if (of_hasprop(phandle, "input-enable"))
rk3328_iomux_set_direction(sc, bank, idx, GPIO_PIN_INPUT, -1);
else if (of_hasprop(phandle, "output-high"))
rk3328_iomux_set_direction(sc, bank, idx, GPIO_PIN_OUTPUT, GPIO_PIN_HIGH);
else if (of_hasprop(phandle, "output-low"))
rk3328_iomux_set_direction(sc, bank, idx, GPIO_PIN_OUTPUT, GPIO_PIN_LOW);
int output_value;
const int direction =
fdtbus_pinctrl_parse_input_output(phandle, &output_value);
if (direction != -1) {
rk3328_iomux_set_direction(sc, bank, idx, direction,
output_value);
}
#endif
rk3328_iomux_set_mux(sc, bank, idx, mux);

View File

@ -1,4 +1,4 @@
/* $NetBSD: rk3399_iomux.c,v 1.1 2018/08/12 16:48:05 jmcneill Exp $ */
/* $NetBSD: rk3399_iomux.c,v 1.2 2019/01/23 04:21:54 thorpej Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
@ -29,7 +29,7 @@
//#define RK3399_IOMUX_DEBUG
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rk3399_iomux.c,v 1.1 2018/08/12 16:48:05 jmcneill Exp $");
__KERNEL_RCSID(0, "$NetBSD: rk3399_iomux.c,v 1.2 2019/01/23 04:21:54 thorpej Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@ -348,27 +348,24 @@ rk3399_iomux_set_mux(struct rk3399_iomux_softc *sc, u_int bank, u_int idx, u_int
static int
rk3399_iomux_config(struct rk3399_iomux_softc *sc, const int phandle, u_int bank, u_int idx, u_int mux)
{
u_int drv;
if (of_hasprop(phandle, "bias-disable"))
rk3399_iomux_set_bias(sc, bank, idx, 0);
else if (of_hasprop(phandle, "bias-pull-up"))
rk3399_iomux_set_bias(sc, bank, idx, GPIO_PIN_PULLUP);
else if (of_hasprop(phandle, "bias-pull-down"))
rk3399_iomux_set_bias(sc, bank, idx, GPIO_PIN_PULLDOWN);
const int bias = fdtbus_pinctrl_parse_bias(phandle, NULL);
if (bias != -1)
rk3399_iomux_set_bias(sc, bank, idx, bias);
if (of_getprop_uint32(phandle, "drive-strength", &drv) == 0) {
if (rk3399_iomux_set_drive_strength(sc, bank, idx, drv) != 0)
return EINVAL;
}
const int drv = fdtbus_pinctrl_parse_drive_strength(phandle);
if (drv != -1 &&
rk3399_iomux_set_drive_strength(sc, bank, idx, drv) != 0)
return EINVAL;
#if notyet
if (of_hasprop(phandle, "input-enable"))
rk3399_iomux_set_direction(sc, bank, idx, GPIO_PIN_INPUT, -1);
else if (of_hasprop(phandle, "output-high"))
rk3399_iomux_set_direction(sc, bank, idx, GPIO_PIN_OUTPUT, GPIO_PIN_HIGH);
else if (of_hasprop(phandle, "output-low"))
rk3399_iomux_set_direction(sc, bank, idx, GPIO_PIN_OUTPUT, GPIO_PIN_LOW);
int output_value;
const int direction =
fdtbus_pinctrl_parse_input_output(phandle, &output_value);
if (direction != -1) {
rk3399_iomux_set_direction(sc, bank, idx, direction,
output_value);
}
#endif
rk3399_iomux_set_mux(sc, bank, idx, mux);

View File

@ -1,4 +1,4 @@
/* $NetBSD: sunxi_gpio.c,v 1.21 2018/05/31 20:52:53 jmcneill Exp $ */
/* $NetBSD: sunxi_gpio.c,v 1.22 2019/01/23 04:21:54 thorpej Exp $ */
/*-
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
@ -29,7 +29,7 @@
#include "opt_soc.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sunxi_gpio.c,v 1.21 2018/05/31 20:52:53 jmcneill Exp $");
__KERNEL_RCSID(0, "$NetBSD: sunxi_gpio.c,v 1.22 2019/01/23 04:21:54 thorpej Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@ -582,7 +582,7 @@ sunxi_pinctrl_parse_function(int phandle)
{
const char *function;
function = fdtbus_get_string(phandle, "function");
function = fdtbus_pinctrl_parse_function(phandle);
if (function != NULL)
return function;
@ -592,13 +592,12 @@ sunxi_pinctrl_parse_function(int phandle)
static const char *
sunxi_pinctrl_parse_pins(int phandle, int *pins_len)
{
const char *pins;
int len;
len = OF_getproplen(phandle, "pins");
if (len > 0) {
*pins_len = len;
return fdtbus_get_string(phandle, "pins");
}
pins = fdtbus_pinctrl_parse_pins(phandle, pins_len);
if (pins != NULL)
return pins;
len = OF_getproplen(phandle, "allwinner,pins");
if (len > 0) {
@ -613,15 +612,13 @@ static int
sunxi_pinctrl_parse_bias(int phandle)
{
u_int pull;
int bias = -1;
int bias;
if (of_hasprop(phandle, "bias-disable"))
bias = 0;
else if (of_hasprop(phandle, "bias-pull-up"))
bias = GPIO_PIN_PULLUP;
else if (of_hasprop(phandle, "bias-pull-down"))
bias = GPIO_PIN_PULLDOWN;
else if (of_getprop_uint32(phandle, "allwinner,pull", &pull) == 0) {
bias = fdtbus_pinctrl_parse_bias(phandle, NULL);
if (bias != -1)
return bias;
if (of_getprop_uint32(phandle, "allwinner,pull", &pull) == 0) {
switch (pull) {
case 0:
bias = 0;
@ -643,7 +640,8 @@ sunxi_pinctrl_parse_drive_strength(int phandle)
{
int val;
if (of_getprop_uint32(phandle, "drive-strength", &val) == 0)
val = fdtbus_pinctrl_parse_drive_strength(phandle);
if (val != -1)
return val;
if (of_getprop_uint32(phandle, "allwinner,drive", &val) == 0)

View File

@ -1,6 +1,7 @@
/* $NetBSD: fdt_pinctrl.c,v 1.6 2019/01/14 12:23:53 mlelstv Exp $ */
/* $NetBSD: fdt_pinctrl.c,v 1.7 2019/01/23 04:23:01 thorpej Exp $ */
/*-
* Copyright (c) 2019 Jason R. Thorpe
* Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
* Copyright (c) 2015 Martin Fouts
* All rights reserved.
@ -28,10 +29,11 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: fdt_pinctrl.c,v 1.6 2019/01/14 12:23:53 mlelstv Exp $");
__KERNEL_RCSID(0, "$NetBSD: fdt_pinctrl.c,v 1.7 2019/01/23 04:23:01 thorpej Exp $");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/gpio.h>
#include <sys/kmem.h>
#include <sys/queue.h>
@ -166,3 +168,192 @@ fdtbus_pinctrl_configure(void)
{
fdtbus_pinctrl_configure_node(OF_finddevice("/"));
}
/*
* Helper routines for parsing put properties related to pinctrl bindings.
*/
/*
* Pin mux settings apply to sets of pins specified by one of 3
* sets of properties:
*
* - "pins" + "function"
* - "groups" + "function"
* - "pinmux"
*
* Eactly one of those 3 combinations must be specified.
*/
const char *
fdtbus_pinctrl_parse_function(int phandle)
{
return fdtbus_get_string(phandle, "function");
}
const void *
fdtbus_pinctrl_parse_pins(int phandle, int *pins_len)
{
int len;
/*
* The pinctrl bindings specify that entries in "pins"
* may be integers or strings; this is determined by
* the hardware-specific binding.
*/
len = OF_getproplen(phandle, "pins");
if (len > 0) {
return fdtbus_get_prop(phandle, "pins", pins_len);
}
return NULL;
}
const char *
fdtbus_pinctrl_parse_groups(int phandle, int *groups_len)
{
int len;
len = OF_getproplen(phandle, "groups");
if (len > 0) {
*groups_len = len;
return fdtbus_get_string(phandle, "groups");
}
return NULL;
}
const u_int *
fdtbus_pinctrl_parse_pinmux(int phandle, int *pinmux_len)
{
int len;
len = OF_getproplen(phandle, "pinmux");
if (len > 0) {
return fdtbus_get_prop(phandle, "pinmux", pinmux_len);
}
return NULL;
}
int
fdtbus_pinctrl_parse_bias(int phandle, int *pull_strength)
{
const char *bias_prop = NULL;
int bias = -1;
/*
* bias-pull-{up,down,pin-default} properties have an optional
* argument: the pull strength in Ohms. (In practice, this is
* sometimes a hardware-specific constant.)
*
* XXXJRT How to represent bias-pull-pin-default?
*/
if (of_hasprop(phandle, "bias-disable")) {
bias = 0;
} else if (of_hasprop(phandle, "bias-pull-up")) {
bias_prop = "bias-pull-up";
bias = GPIO_PIN_PULLUP;
} else if (of_hasprop(phandle, "bias-pull-down")) {
bias_prop = "bias-pull-down";
bias = GPIO_PIN_PULLDOWN;
}
if (pull_strength) {
*pull_strength = -1;
if (bias_prop) {
uint32_t val;
if (of_getprop_uint32(phandle, bias_prop, &val) == 0) {
*pull_strength = (int)val;
}
}
}
return bias;
}
int
fdtbus_pinctrl_parse_drive(int phandle)
{
int drive = -1;
if (of_hasprop(phandle, "drive-push-pull"))
drive = GPIO_PIN_PUSHPULL;
else if (of_hasprop(phandle, "drive-open-drain"))
drive = GPIO_PIN_OPENDRAIN;
else if (of_hasprop(phandle, "drive-open-source"))
drive = 0;
return drive;
}
int
fdtbus_pinctrl_parse_drive_strength(int phandle)
{
int val;
/*
* drive-strength has as an argument the target strength
* in mA.
*/
if (of_getprop_uint32(phandle, "drive-strength", &val) == 0)
return val;
return -1;
}
int fdtbus_pinctrl_parse_input_output(int phandle, int *output_value)
{
int direction = -1;
int pinval = -1;
if (of_hasprop(phandle, "input-enable")) {
direction = GPIO_PIN_INPUT;
} else if (of_hasprop(phandle, "input-disable")) {
/*
* XXXJRT How to represent this? This is more than
* just "don't set the direction" - it's an active
* command that might involve disabling an input
* buffer on the pin.
*/
}
if (of_hasprop(phandle, "output-enable")) {
if (direction == -1)
direction = 0;
direction |= GPIO_PIN_OUTPUT;
} else if (of_hasprop(phandle, "output-disable")) {
if (direction == -1)
direction = 0;
direction |= GPIO_PIN_TRISTATE;
}
if (of_hasprop(phandle, "output-low")) {
if (direction == -1)
direction = 0;
direction |= GPIO_PIN_OUTPUT;
pinval = GPIO_PIN_LOW;
} else if (of_hasprop(phandle, "output-high")) {
if (direction == -1)
direction = 0;
direction |= GPIO_PIN_OUTPUT;
pinval = GPIO_PIN_HIGH;
}
if (output_value)
*output_value = pinval;
/*
* XXX input-schmitt-enable
* XXX input-schmitt-disable
*/
if (direction != -1
&& (direction & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT))
== (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) {
direction |= GPIO_PIN_INOUT;
}
return direction;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: fdtvar.h,v 1.45 2019/01/19 20:50:48 jmcneill Exp $ */
/* $NetBSD: fdtvar.h,v 1.46 2019/01/23 04:21:55 thorpej Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
@ -31,6 +31,7 @@
#include <sys/types.h>
#include <sys/bus.h>
#include <sys/gpio.h>
#include <sys/termios.h>
#include <dev/i2c/i2cvar.h>
@ -292,6 +293,14 @@ pwm_tag_t fdtbus_pwm_acquire_index(int, const char *, int);
void fdtbus_pinctrl_configure(void);
int fdtbus_pinctrl_set_config_index(int, u_int);
int fdtbus_pinctrl_set_config(int, const char *);
const char * fdtbus_pinctrl_parse_function(int);
const void * fdtbus_pinctrl_parse_pins(int, int *);
const char * fdtbus_pinctrl_parse_groups(int, int *);
const u_int * fdtbus_pinctrl_parse_pinmux(int, int *);
int fdtbus_pinctrl_parse_bias(int, int *);
int fdtbus_pinctrl_parse_drive(int);
int fdtbus_pinctrl_parse_drive_strength(int);
int fdtbus_pinctrl_parse_input_output(int, int *);
struct fdtbus_regulator *fdtbus_regulator_acquire(int, const char *);
void fdtbus_regulator_release(struct fdtbus_regulator *);
int fdtbus_regulator_enable(struct fdtbus_regulator *);