gpio: serial: max310x: Support open-drain configuration for GPIOs

The push-pull vs. open-drain are the only supported output modes. The
inputs are always unconditionally equipped with weak pull-downs. That's
the only mode, so there's probably no point in exporting that. I wonder
if it's worthwhile to provide a custom dbg_show method to indicate the
current status of the outputs, though.

This patch and [1] for i2c-gpio together make it possible to bit-bang an
I2C bus over GPIOs of an UART which is connected via SPI :). Yes, this
is crazy, but it's fast enough (while on a 26Mhz SPI HW bus with a
dual-core 1.6GHz CPU) to drive an I2C bus at 200kHz, according to my
scope.

[1] https://patchwork.ozlabs.org/patch/852591/

Signed-off-by: Jan Kundrát <jan.kundrat@cesnet.cz>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Jan Kundrát 2017-12-22 21:29:44 +01:00 committed by Greg Kroah-Hartman
parent 7d09995dcb
commit e397824bf0
1 changed files with 22 additions and 0 deletions

View File

@ -1159,6 +1159,27 @@ static int max310x_gpio_direction_output(struct gpio_chip *chip,
return 0;
}
static int max310x_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long config)
{
struct max310x_port *s = gpiochip_get_data(chip);
struct uart_port *port = &s->p[offset / 4].port;
switch (pinconf_to_config_param(config)) {
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
max310x_port_update(port, MAX310X_GPIOCFG_REG,
1 << ((offset % 4) + 4),
1 << ((offset % 4) + 4));
return 0;
case PIN_CONFIG_DRIVE_PUSH_PULL:
max310x_port_update(port, MAX310X_GPIOCFG_REG,
1 << ((offset % 4) + 4), 0);
return 0;
default:
return -ENOTSUPP;
}
}
#endif
static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
@ -1302,6 +1323,7 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
s->gpio.get = max310x_gpio_get;
s->gpio.direction_output= max310x_gpio_direction_output;
s->gpio.set = max310x_gpio_set;
s->gpio.set_config = max310x_gpio_set_config;
s->gpio.base = -1;
s->gpio.ngpio = devtype->nr * 4;
s->gpio.can_sleep = 1;