Merge branch 'ib-pinctrl-genprops' into devel

This commit is contained in:
Linus Walleij 2017-01-26 15:27:54 +01:00
commit 27a2873617
47 changed files with 403 additions and 268 deletions

View File

@ -146,10 +146,11 @@ a pull-up resistor is needed on the outgoing rail to complete the circuit, and
in the second case, a pull-down resistor is needed on the rail. in the second case, a pull-down resistor is needed on the rail.
Hardware that supports open drain or open source or both, can implement a Hardware that supports open drain or open source or both, can implement a
special callback in the gpio_chip: .set_single_ended() that takes an enum flag special callback in the gpio_chip: .set_config() that takes a generic
telling whether to configure the line as open drain, open source or push-pull. pinconf packed value telling whether to configure the line as open drain,
This will happen in response to the GPIO_OPEN_DRAIN or GPIO_OPEN_SOURCE flag open source or push-pull. This will happen in response to the
set in the machine file, or coming from other hardware descriptions. GPIO_OPEN_DRAIN or GPIO_OPEN_SOURCE flag set in the machine file, or coming
from other hardware descriptions.
If this state can not be configured in hardware, i.e. if the GPIO hardware does If this state can not be configured in hardware, i.e. if the GPIO hardware does
not support open drain/open source in hardware, the GPIO library will instead not support open drain/open source in hardware, the GPIO library will instead

View File

@ -308,6 +308,18 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
return 0; return 0;
} }
static int bcm_kona_gpio_set_config(struct gpio_chip *chip, unsigned gpio,
unsigned long config)
{
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
debounce = pinconf_to_config_argument(config);
return bcm_kona_gpio_set_debounce(chip, gpio, debounce);
}
static const struct gpio_chip template_chip = { static const struct gpio_chip template_chip = {
.label = "bcm-kona-gpio", .label = "bcm-kona-gpio",
.owner = THIS_MODULE, .owner = THIS_MODULE,
@ -318,7 +330,7 @@ static const struct gpio_chip template_chip = {
.get = bcm_kona_gpio_get, .get = bcm_kona_gpio_get,
.direction_output = bcm_kona_gpio_direction_output, .direction_output = bcm_kona_gpio_direction_output,
.set = bcm_kona_gpio_set, .set = bcm_kona_gpio_set,
.set_debounce = bcm_kona_gpio_set_debounce, .set_config = bcm_kona_gpio_set_config,
.to_irq = bcm_kona_gpio_to_irq, .to_irq = bcm_kona_gpio_to_irq,
.base = 0, .base = 0,
}; };

View File

@ -272,12 +272,16 @@ static int dln2_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
return dln2_gpio_set_direction(chip, offset, DLN2_GPIO_DIRECTION_OUT); return dln2_gpio_set_direction(chip, offset, DLN2_GPIO_DIRECTION_OUT);
} }
static int dln2_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, static int dln2_gpio_set_config(struct gpio_chip *chip, unsigned offset,
unsigned debounce) unsigned long config)
{ {
struct dln2_gpio *dln2 = gpiochip_get_data(chip); struct dln2_gpio *dln2 = gpiochip_get_data(chip);
__le32 duration = cpu_to_le32(debounce); __le32 duration;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
duration = cpu_to_le32(pinconf_to_config_argument(config));
return dln2_transfer_tx(dln2->pdev, DLN2_GPIO_SET_DEBOUNCE, return dln2_transfer_tx(dln2->pdev, DLN2_GPIO_SET_DEBOUNCE,
&duration, sizeof(duration)); &duration, sizeof(duration));
} }
@ -474,7 +478,7 @@ static int dln2_gpio_probe(struct platform_device *pdev)
dln2->gpio.get_direction = dln2_gpio_get_direction; dln2->gpio.get_direction = dln2_gpio_get_direction;
dln2->gpio.direction_input = dln2_gpio_direction_input; dln2->gpio.direction_input = dln2_gpio_direction_input;
dln2->gpio.direction_output = dln2_gpio_direction_output; dln2->gpio.direction_output = dln2_gpio_direction_output;
dln2->gpio.set_debounce = dln2_gpio_set_debounce; dln2->gpio.set_config = dln2_gpio_set_config;
platform_set_drvdata(pdev, dln2); platform_set_drvdata(pdev, dln2);

View File

@ -279,6 +279,18 @@ static int dwapb_gpio_set_debounce(struct gpio_chip *gc,
return 0; return 0;
} }
static int dwapb_gpio_set_config(struct gpio_chip *gc, unsigned offset,
unsigned long config)
{
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
debounce = pinconf_to_config_argument(config);
return dwapb_gpio_set_debounce(gc, offset, debounce);
}
static irqreturn_t dwapb_irq_handler_mfd(int irq, void *dev_id) static irqreturn_t dwapb_irq_handler_mfd(int irq, void *dev_id)
{ {
u32 worked; u32 worked;
@ -426,7 +438,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
/* Only port A support debounce */ /* Only port A support debounce */
if (pp->idx == 0) if (pp->idx == 0)
port->gc.set_debounce = dwapb_gpio_set_debounce; port->gc.set_config = dwapb_gpio_set_config;
if (pp->irq) if (pp->irq)
dwapb_configure_irqs(gpio, port, pp); dwapb_configure_irqs(gpio, port, pp);

View File

@ -291,15 +291,20 @@ static struct ep93xx_gpio_bank ep93xx_gpio_banks[] = {
EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false), EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false),
}; };
static int ep93xx_gpio_set_debounce(struct gpio_chip *chip, static int ep93xx_gpio_set_config(struct gpio_chip *chip, unsigned offset,
unsigned offset, unsigned debounce) unsigned long config)
{ {
int gpio = chip->base + offset; int gpio = chip->base + offset;
int irq = gpio_to_irq(gpio); int irq = gpio_to_irq(gpio);
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
if (irq < 0) if (irq < 0)
return -EINVAL; return -EINVAL;
debounce = pinconf_to_config_argument(config);
ep93xx_gpio_int_debounce(irq, debounce ? true : false); ep93xx_gpio_int_debounce(irq, debounce ? true : false);
return 0; return 0;
@ -335,7 +340,7 @@ static int ep93xx_gpio_add_bank(struct gpio_chip *gc, struct device *dev,
gc->base = bank->base; gc->base = bank->base;
if (bank->has_debounce) { if (bank->has_debounce) {
gc->set_debounce = ep93xx_gpio_set_debounce; gc->set_config = ep93xx_gpio_set_config;
gc->to_irq = ep93xx_gpio_to_irq; gc->to_irq = ep93xx_gpio_to_irq;
} }

View File

@ -131,9 +131,8 @@ static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset);
static int f7188x_gpio_direction_out(struct gpio_chip *chip, static int f7188x_gpio_direction_out(struct gpio_chip *chip,
unsigned offset, int value); unsigned offset, int value);
static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value); static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value);
static int f7188x_gpio_set_single_ended(struct gpio_chip *gc, static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
unsigned offset, unsigned long config);
enum single_ended_mode mode);
#define F7188X_GPIO_BANK(_base, _ngpio, _regbase) \ #define F7188X_GPIO_BANK(_base, _ngpio, _regbase) \
{ \ { \
@ -145,7 +144,7 @@ static int f7188x_gpio_set_single_ended(struct gpio_chip *gc,
.get = f7188x_gpio_get, \ .get = f7188x_gpio_get, \
.direction_output = f7188x_gpio_direction_out, \ .direction_output = f7188x_gpio_direction_out, \
.set = f7188x_gpio_set, \ .set = f7188x_gpio_set, \
.set_single_ended = f7188x_gpio_set_single_ended, \ .set_config = f7188x_gpio_set_config, \
.base = _base, \ .base = _base, \
.ngpio = _ngpio, \ .ngpio = _ngpio, \
.can_sleep = true, \ .can_sleep = true, \
@ -326,17 +325,17 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
superio_exit(sio->addr); superio_exit(sio->addr);
} }
static int f7188x_gpio_set_single_ended(struct gpio_chip *chip, static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
unsigned offset, unsigned long config)
enum single_ended_mode mode)
{ {
int err; int err;
enum pin_config_param param = pinconf_to_config_param(config);
struct f7188x_gpio_bank *bank = gpiochip_get_data(chip); struct f7188x_gpio_bank *bank = gpiochip_get_data(chip);
struct f7188x_sio *sio = bank->data->sio; struct f7188x_sio *sio = bank->data->sio;
u8 data; u8 data;
if (mode != LINE_MODE_OPEN_DRAIN && if (param != PIN_CONFIG_DRIVE_OPEN_DRAIN &&
mode != LINE_MODE_PUSH_PULL) param != PIN_CONFIG_DRIVE_PUSH_PULL)
return -ENOTSUPP; return -ENOTSUPP;
err = superio_enter(sio->addr); err = superio_enter(sio->addr);
@ -345,7 +344,7 @@ static int f7188x_gpio_set_single_ended(struct gpio_chip *chip,
superio_select(sio->addr, SIO_LD_GPIO); superio_select(sio->addr, SIO_LD_GPIO);
data = superio_inb(sio->addr, gpio_out_mode(bank->regbase)); data = superio_inb(sio->addr, gpio_out_mode(bank->regbase));
if (mode == LINE_MODE_OPEN_DRAIN) if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
data &= ~BIT(offset); data &= ~BIT(offset);
else else
data |= BIT(offset); data |= BIT(offset);

View File

@ -100,21 +100,21 @@ static int lp873x_gpio_request(struct gpio_chip *gc, unsigned int offset)
return 0; return 0;
} }
static int lp873x_gpio_set_single_ended(struct gpio_chip *gc, static int lp873x_gpio_set_config(struct gpio_chip *gc, unsigned offset,
unsigned int offset, unsigned long config)
enum single_ended_mode mode)
{ {
struct lp873x_gpio *gpio = gpiochip_get_data(gc); struct lp873x_gpio *gpio = gpiochip_get_data(gc);
switch (mode) { switch (pinconf_to_config_param(config)) {
case LINE_MODE_OPEN_DRAIN: case PIN_CONFIG_DRIVE_OPEN_DRAIN:
return regmap_update_bits(gpio->lp873->regmap, return regmap_update_bits(gpio->lp873->regmap,
LP873X_REG_GPO_CTRL, LP873X_REG_GPO_CTRL,
BIT(offset * BITS_PER_GPO + BIT(offset * BITS_PER_GPO +
LP873X_GPO_CTRL_OD), LP873X_GPO_CTRL_OD),
BIT(offset * BITS_PER_GPO + BIT(offset * BITS_PER_GPO +
LP873X_GPO_CTRL_OD)); LP873X_GPO_CTRL_OD));
case LINE_MODE_PUSH_PULL:
case PIN_CONFIG_DRIVE_PUSH_PULL:
return regmap_update_bits(gpio->lp873->regmap, return regmap_update_bits(gpio->lp873->regmap,
LP873X_REG_GPO_CTRL, LP873X_REG_GPO_CTRL,
BIT(offset * BITS_PER_GPO + BIT(offset * BITS_PER_GPO +
@ -133,7 +133,7 @@ static const struct gpio_chip template_chip = {
.direction_output = lp873x_gpio_direction_output, .direction_output = lp873x_gpio_direction_output,
.get = lp873x_gpio_get, .get = lp873x_gpio_get,
.set = lp873x_gpio_set, .set = lp873x_gpio_set,
.set_single_ended = lp873x_gpio_set_single_ended, .set_config = lp873x_gpio_set_config,
.base = -1, .base = -1,
.ngpio = 2, .ngpio = 2,
.can_sleep = true, .can_sleep = true,

View File

@ -152,11 +152,10 @@ static int max77620_gpio_dir_output(struct gpio_chip *gc, unsigned int offset,
return ret; return ret;
} }
static int max77620_gpio_set_debounce(struct gpio_chip *gc, static int max77620_gpio_set_debounce(struct max77620_gpio *mgpio,
unsigned int offset, unsigned int offset,
unsigned int debounce) unsigned int debounce)
{ {
struct max77620_gpio *mgpio = gpiochip_get_data(gc);
u8 val; u8 val;
int ret; int ret;
@ -202,21 +201,23 @@ static void max77620_gpio_set(struct gpio_chip *gc, unsigned int offset,
dev_err(mgpio->dev, "CNFG_GPIO_OUT update failed: %d\n", ret); dev_err(mgpio->dev, "CNFG_GPIO_OUT update failed: %d\n", ret);
} }
static int max77620_gpio_set_single_ended(struct gpio_chip *gc, static int max77620_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
unsigned int offset, unsigned long config)
enum single_ended_mode mode)
{ {
struct max77620_gpio *mgpio = gpiochip_get_data(gc); struct max77620_gpio *mgpio = gpiochip_get_data(gc);
switch (mode) { switch (pinconf_to_config_param(config)) {
case LINE_MODE_OPEN_DRAIN: case PIN_CONFIG_DRIVE_OPEN_DRAIN:
return regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset), return regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
MAX77620_CNFG_GPIO_DRV_MASK, MAX77620_CNFG_GPIO_DRV_MASK,
MAX77620_CNFG_GPIO_DRV_OPENDRAIN); MAX77620_CNFG_GPIO_DRV_OPENDRAIN);
case LINE_MODE_PUSH_PULL: case PIN_CONFIG_DRIVE_PUSH_PULL:
return regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset), return regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
MAX77620_CNFG_GPIO_DRV_MASK, MAX77620_CNFG_GPIO_DRV_MASK,
MAX77620_CNFG_GPIO_DRV_PUSHPULL); MAX77620_CNFG_GPIO_DRV_PUSHPULL);
case PIN_CONFIG_INPUT_DEBOUNCE:
return max77620_gpio_set_debounce(mgpio, offset,
pinconf_to_config_argument(config));
default: default:
break; break;
} }
@ -257,9 +258,8 @@ static int max77620_gpio_probe(struct platform_device *pdev)
mgpio->gpio_chip.direction_input = max77620_gpio_dir_input; mgpio->gpio_chip.direction_input = max77620_gpio_dir_input;
mgpio->gpio_chip.get = max77620_gpio_get; mgpio->gpio_chip.get = max77620_gpio_get;
mgpio->gpio_chip.direction_output = max77620_gpio_dir_output; mgpio->gpio_chip.direction_output = max77620_gpio_dir_output;
mgpio->gpio_chip.set_debounce = max77620_gpio_set_debounce;
mgpio->gpio_chip.set = max77620_gpio_set; mgpio->gpio_chip.set = max77620_gpio_set;
mgpio->gpio_chip.set_single_ended = max77620_gpio_set_single_ended; mgpio->gpio_chip.set_config = max77620_gpio_set_config;
mgpio->gpio_chip.to_irq = max77620_gpio_to_irq; mgpio->gpio_chip.to_irq = max77620_gpio_to_irq;
mgpio->gpio_chip.ngpio = MAX77620_GPIO_NR; mgpio->gpio_chip.ngpio = MAX77620_GPIO_NR;
mgpio->gpio_chip.can_sleep = 1; mgpio->gpio_chip.can_sleep = 1;

View File

@ -89,22 +89,18 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio,
static int men_z127_set_single_ended(struct gpio_chip *gc, static int men_z127_set_single_ended(struct gpio_chip *gc,
unsigned offset, unsigned offset,
enum single_ended_mode mode) enum pin_config_param param)
{ {
struct men_z127_gpio *priv = gpiochip_get_data(gc); struct men_z127_gpio *priv = gpiochip_get_data(gc);
u32 od_en; u32 od_en;
if (mode != LINE_MODE_OPEN_DRAIN &&
mode != LINE_MODE_PUSH_PULL)
return -ENOTSUPP;
spin_lock(&gc->bgpio_lock); spin_lock(&gc->bgpio_lock);
od_en = readl(priv->reg_base + MEN_Z127_ODER); od_en = readl(priv->reg_base + MEN_Z127_ODER);
if (mode == LINE_MODE_OPEN_DRAIN) if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
od_en |= BIT(offset); od_en |= BIT(offset);
else else
/* Implicitly LINE_MODE_PUSH_PULL */ /* Implicitly PIN_CONFIG_DRIVE_PUSH_PULL */
od_en &= ~BIT(offset); od_en &= ~BIT(offset);
writel(od_en, priv->reg_base + MEN_Z127_ODER); writel(od_en, priv->reg_base + MEN_Z127_ODER);
@ -113,6 +109,27 @@ static int men_z127_set_single_ended(struct gpio_chip *gc,
return 0; return 0;
} }
static int men_z127_set_config(struct gpio_chip *gc, unsigned offset,
unsigned long config)
{
enum pin_config_param param = pinconf_to_config_param(config);
switch (param) {
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
case PIN_CONFIG_DRIVE_PUSH_PULL:
return men_z127_set_single_ended(gc, offset, param);
case PIN_CONFIG_INPUT_DEBOUNCE:
return men_z127_debounce(gc, offset,
pinconf_to_config_argument(config));
default:
break;
}
return -ENOTSUPP;
}
static int men_z127_probe(struct mcb_device *mdev, static int men_z127_probe(struct mcb_device *mdev,
const struct mcb_device_id *id) const struct mcb_device_id *id)
{ {
@ -149,8 +166,7 @@ static int men_z127_probe(struct mcb_device *mdev,
if (ret) if (ret)
goto err_unmap; goto err_unmap;
men_z127_gpio->gc.set_debounce = men_z127_debounce; men_z127_gpio->gc.set_config = men_z127_set_config;
men_z127_gpio->gc.set_single_ended = men_z127_set_single_ended;
ret = gpiochip_add_data(&men_z127_gpio->gc, men_z127_gpio); ret = gpiochip_add_data(&men_z127_gpio->gc, men_z127_gpio);
if (ret) { if (ret) {

View File

@ -190,6 +190,18 @@ static int mrfld_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
return 0; return 0;
} }
static int mrfld_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long config)
{
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
debounce = pinconf_to_config_argument(config);
return mrfld_gpio_set_debounce(chip, offset, debounce);
}
static void mrfld_irq_ack(struct irq_data *d) static void mrfld_irq_ack(struct irq_data *d)
{ {
struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d); struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d);
@ -414,7 +426,7 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
priv->chip.get = mrfld_gpio_get; priv->chip.get = mrfld_gpio_get;
priv->chip.set = mrfld_gpio_set; priv->chip.set = mrfld_gpio_set;
priv->chip.get_direction = mrfld_gpio_get_direction; priv->chip.get_direction = mrfld_gpio_get_direction;
priv->chip.set_debounce = mrfld_gpio_set_debounce; priv->chip.set_config = mrfld_gpio_set_config;
priv->chip.base = gpio_base; priv->chip.base = gpio_base;
priv->chip.ngpio = MRFLD_NGPIO; priv->chip.ngpio = MRFLD_NGPIO;
priv->chip.can_sleep = false; priv->chip.can_sleep = false;

View File

@ -974,6 +974,18 @@ static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
return 0; return 0;
} }
static int omap_gpio_set_config(struct gpio_chip *chip, unsigned offset,
unsigned long config)
{
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
debounce = pinconf_to_config_argument(config);
return omap_gpio_debounce(chip, offset, debounce);
}
static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{ {
struct gpio_bank *bank; struct gpio_bank *bank;
@ -1045,7 +1057,7 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
bank->chip.direction_input = omap_gpio_input; bank->chip.direction_input = omap_gpio_input;
bank->chip.get = omap_gpio_get; bank->chip.get = omap_gpio_get;
bank->chip.direction_output = omap_gpio_output; bank->chip.direction_output = omap_gpio_output;
bank->chip.set_debounce = omap_gpio_debounce; bank->chip.set_config = omap_gpio_set_config;
bank->chip.set = omap_gpio_set; bank->chip.set = omap_gpio_set;
if (bank->is_mpuio) { if (bank->is_mpuio) {
bank->chip.label = "mpuio"; bank->chip.label = "mpuio";

View File

@ -100,9 +100,8 @@ static int tc3589x_gpio_get_direction(struct gpio_chip *chip,
return !(ret & BIT(pos)); return !(ret & BIT(pos));
} }
static int tc3589x_gpio_set_single_ended(struct gpio_chip *chip, static int tc3589x_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned int offset, unsigned long config)
enum single_ended_mode mode)
{ {
struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip); struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip);
struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
@ -116,22 +115,22 @@ static int tc3589x_gpio_set_single_ended(struct gpio_chip *chip,
unsigned int pos = offset % 8; unsigned int pos = offset % 8;
int ret; int ret;
switch(mode) { switch (pinconf_to_config_param(config)) {
case LINE_MODE_OPEN_DRAIN: case PIN_CONFIG_DRIVE_OPEN_DRAIN:
/* Set open drain mode */ /* Set open drain mode */
ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), 0); ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), 0);
if (ret) if (ret)
return ret; return ret;
/* Enable open drain/source mode */ /* Enable open drain/source mode */
return tc3589x_set_bits(tc3589x, odereg, BIT(pos), BIT(pos)); return tc3589x_set_bits(tc3589x, odereg, BIT(pos), BIT(pos));
case LINE_MODE_OPEN_SOURCE: case PIN_CONFIG_DRIVE_OPEN_SOURCE:
/* Set open source mode */ /* Set open source mode */
ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), BIT(pos)); ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), BIT(pos));
if (ret) if (ret)
return ret; return ret;
/* Enable open drain/source mode */ /* Enable open drain/source mode */
return tc3589x_set_bits(tc3589x, odereg, BIT(pos), BIT(pos)); return tc3589x_set_bits(tc3589x, odereg, BIT(pos), BIT(pos));
case LINE_MODE_PUSH_PULL: case PIN_CONFIG_DRIVE_PUSH_PULL:
/* Disable open drain/source mode */ /* Disable open drain/source mode */
return tc3589x_set_bits(tc3589x, odereg, BIT(pos), 0); return tc3589x_set_bits(tc3589x, odereg, BIT(pos), 0);
default: default:
@ -148,7 +147,7 @@ static const struct gpio_chip template_chip = {
.direction_output = tc3589x_gpio_direction_output, .direction_output = tc3589x_gpio_direction_output,
.direction_input = tc3589x_gpio_direction_input, .direction_input = tc3589x_gpio_direction_input,
.get_direction = tc3589x_gpio_get_direction, .get_direction = tc3589x_gpio_get_direction,
.set_single_ended = tc3589x_gpio_set_single_ended, .set_config = tc3589x_gpio_set_config,
.can_sleep = true, .can_sleep = true,
}; };

View File

@ -238,6 +238,18 @@ static int tegra_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
return 0; return 0;
} }
static int tegra_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long config)
{
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
debounce = pinconf_to_config_argument(config);
return tegra_gpio_set_debounce(chip, offset, debounce);
}
static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset) static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{ {
struct tegra_gpio_info *tgi = gpiochip_get_data(chip); struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
@ -615,7 +627,7 @@ static int tegra_gpio_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, tgi); platform_set_drvdata(pdev, tgi);
if (config->debounce_supported) if (config->debounce_supported)
tgi->gc.set_debounce = tegra_gpio_set_debounce; tgi->gc.set_config = tegra_gpio_set_config;
tgi->bank_info = devm_kzalloc(&pdev->dev, tgi->bank_count * tgi->bank_info = devm_kzalloc(&pdev->dev, tgi->bank_count *
sizeof(*tgi->bank_info), GFP_KERNEL); sizeof(*tgi->bank_info), GFP_KERNEL);

View File

@ -139,28 +139,28 @@ static int tps65218_gpio_request(struct gpio_chip *gc, unsigned offset)
return 0; return 0;
} }
static int tps65218_gpio_set_single_ended(struct gpio_chip *gc, static int tps65218_gpio_set_config(struct gpio_chip *gc, unsigned offset,
unsigned offset, unsigned long config)
enum single_ended_mode mode)
{ {
struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc); struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc);
struct tps65218 *tps65218 = tps65218_gpio->tps65218; struct tps65218 *tps65218 = tps65218_gpio->tps65218;
enum pin_config_param param = pinconf_to_config_param(config);
switch (offset) { switch (offset) {
case 0: case 0:
case 2: case 2:
/* GPO1 is hardwired to be open drain */ /* GPO1 is hardwired to be open drain */
if (mode == LINE_MODE_OPEN_DRAIN) if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
return 0; return 0;
return -ENOTSUPP; return -ENOTSUPP;
case 1: case 1:
/* GPO2 is push-pull by default, can be set as open drain. */ /* GPO2 is push-pull by default, can be set as open drain. */
if (mode == LINE_MODE_OPEN_DRAIN) if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
return tps65218_clear_bits(tps65218, return tps65218_clear_bits(tps65218,
TPS65218_REG_CONFIG1, TPS65218_REG_CONFIG1,
TPS65218_CONFIG1_GPO2_BUF, TPS65218_CONFIG1_GPO2_BUF,
TPS65218_PROTECT_L1); TPS65218_PROTECT_L1);
if (mode == LINE_MODE_PUSH_PULL) if (param == PIN_CONFIG_DRIVE_PUSH_PULL)
return tps65218_set_bits(tps65218, return tps65218_set_bits(tps65218,
TPS65218_REG_CONFIG1, TPS65218_REG_CONFIG1,
TPS65218_CONFIG1_GPO2_BUF, TPS65218_CONFIG1_GPO2_BUF,
@ -181,7 +181,7 @@ static const struct gpio_chip template_chip = {
.direction_input = tps65218_gpio_input, .direction_input = tps65218_gpio_input,
.get = tps65218_gpio_get, .get = tps65218_gpio_get,
.set = tps65218_gpio_set, .set = tps65218_gpio_set,
.set_single_ended = tps65218_gpio_set_single_ended, .set_config = tps65218_gpio_set_config,
.can_sleep = true, .can_sleep = true,
.ngpio = 3, .ngpio = 3,
.base = -1, .base = -1,

View File

@ -186,23 +186,24 @@ static int vx855gpio_direction_output(struct gpio_chip *gpio,
return 0; return 0;
} }
static int vx855gpio_set_single_ended(struct gpio_chip *gpio, static int vx855gpio_set_config(struct gpio_chip *gpio, unsigned int nr,
unsigned int nr, unsigned long config)
enum single_ended_mode mode)
{ {
enum pin_config_param param = pinconf_to_config_param(config);
/* The GPI cannot be single-ended */ /* The GPI cannot be single-ended */
if (nr < NR_VX855_GPI) if (nr < NR_VX855_GPI)
return -EINVAL; return -EINVAL;
/* The GPO's are push-pull */ /* The GPO's are push-pull */
if (nr < NR_VX855_GPInO) { if (nr < NR_VX855_GPInO) {
if (mode != LINE_MODE_PUSH_PULL) if (param != PIN_CONFIG_DRIVE_PUSH_PULL)
return -ENOTSUPP; return -ENOTSUPP;
return 0; return 0;
} }
/* The GPIO's are open drain */ /* The GPIO's are open drain */
if (mode != LINE_MODE_OPEN_DRAIN) if (param != PIN_CONFIG_DRIVE_OPEN_DRAIN)
return -ENOTSUPP; return -ENOTSUPP;
return 0; return 0;
@ -231,7 +232,7 @@ static void vx855gpio_gpio_setup(struct vx855_gpio *vg)
c->direction_output = vx855gpio_direction_output; c->direction_output = vx855gpio_direction_output;
c->get = vx855gpio_get; c->get = vx855gpio_get;
c->set = vx855gpio_set; c->set = vx855gpio_set;
c->set_single_ended = vx855gpio_set_single_ended; c->set_config = vx855gpio_set_config,
c->dbg_show = NULL; c->dbg_show = NULL;
c->base = 0; c->base = 0;
c->ngpio = NR_VX855_GP; c->ngpio = NR_VX855_GP;

View File

@ -202,17 +202,16 @@ static void wcove_gpio_set(struct gpio_chip *chip,
regmap_update_bits(wg->regmap, to_reg(gpio, CTRL_OUT), 1, 0); regmap_update_bits(wg->regmap, to_reg(gpio, CTRL_OUT), 1, 0);
} }
static int wcove_gpio_set_single_ended(struct gpio_chip *chip, static int wcove_gpio_set_config(struct gpio_chip *chip, unsigned int gpio,
unsigned int gpio, unsigned long config)
enum single_ended_mode mode)
{ {
struct wcove_gpio *wg = gpiochip_get_data(chip); struct wcove_gpio *wg = gpiochip_get_data(chip);
switch (mode) { switch (pinconf_to_config_param(config)) {
case LINE_MODE_OPEN_DRAIN: case PIN_CONFIG_DRIVE_OPEN_DRAIN:
return regmap_update_bits(wg->regmap, to_reg(gpio, CTRL_OUT), return regmap_update_bits(wg->regmap, to_reg(gpio, CTRL_OUT),
CTLO_DRV_MASK, CTLO_DRV_OD); CTLO_DRV_MASK, CTLO_DRV_OD);
case LINE_MODE_PUSH_PULL: case PIN_CONFIG_DRIVE_PUSH_PULL:
return regmap_update_bits(wg->regmap, to_reg(gpio, CTRL_OUT), return regmap_update_bits(wg->regmap, to_reg(gpio, CTRL_OUT),
CTLO_DRV_MASK, CTLO_DRV_CMOS); CTLO_DRV_MASK, CTLO_DRV_CMOS);
default: default:
@ -411,7 +410,7 @@ static int wcove_gpio_probe(struct platform_device *pdev)
wg->chip.get_direction = wcove_gpio_get_direction; wg->chip.get_direction = wcove_gpio_get_direction;
wg->chip.get = wcove_gpio_get; wg->chip.get = wcove_gpio_get;
wg->chip.set = wcove_gpio_set; wg->chip.set = wcove_gpio_set;
wg->chip.set_single_ended = wcove_gpio_set_single_ended, wg->chip.set_config = wcove_gpio_set_config,
wg->chip.base = -1; wg->chip.base = -1;
wg->chip.ngpio = WCOVE_VGPIO_NUM; wg->chip.ngpio = WCOVE_VGPIO_NUM;
wg->chip.can_sleep = true; wg->chip.can_sleep = true;

View File

@ -101,11 +101,9 @@ static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
WM831X_IRQ_GPIO_1 + offset); WM831X_IRQ_GPIO_1 + offset);
} }
static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, static int wm831x_gpio_set_debounce(struct wm831x *wm831x, unsigned offset,
unsigned debounce) unsigned debounce)
{ {
struct wm831x_gpio *wm831x_gpio = gpiochip_get_data(chip);
struct wm831x *wm831x = wm831x_gpio->wm831x;
int reg = WM831X_GPIO1_CONTROL + offset; int reg = WM831X_GPIO1_CONTROL + offset;
int ret, fn; int ret, fn;
@ -132,21 +130,23 @@ static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn); return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn);
} }
static int wm831x_set_single_ended(struct gpio_chip *chip, static int wm831x_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned int offset, unsigned long config)
enum single_ended_mode mode)
{ {
struct wm831x_gpio *wm831x_gpio = gpiochip_get_data(chip); struct wm831x_gpio *wm831x_gpio = gpiochip_get_data(chip);
struct wm831x *wm831x = wm831x_gpio->wm831x; struct wm831x *wm831x = wm831x_gpio->wm831x;
int reg = WM831X_GPIO1_CONTROL + offset; int reg = WM831X_GPIO1_CONTROL + offset;
switch (mode) { switch (pinconf_to_config_param(config)) {
case LINE_MODE_OPEN_DRAIN: case PIN_CONFIG_DRIVE_OPEN_DRAIN:
return wm831x_set_bits(wm831x, reg, return wm831x_set_bits(wm831x, reg,
WM831X_GPN_OD_MASK, WM831X_GPN_OD); WM831X_GPN_OD_MASK, WM831X_GPN_OD);
case LINE_MODE_PUSH_PULL: case PIN_CONFIG_DRIVE_PUSH_PULL:
return wm831x_set_bits(wm831x, reg, return wm831x_set_bits(wm831x, reg,
WM831X_GPN_OD_MASK, 0); WM831X_GPN_OD_MASK, 0);
case PIN_CONFIG_INPUT_DEBOUNCE:
return wm831x_gpio_set_debounce(wm831x, offset,
pinconf_to_config_argument(config));
default: default:
break; break;
} }
@ -255,8 +255,7 @@ static const struct gpio_chip template_chip = {
.direction_output = wm831x_gpio_direction_out, .direction_output = wm831x_gpio_direction_out,
.set = wm831x_gpio_set, .set = wm831x_gpio_set,
.to_irq = wm831x_gpio_to_irq, .to_irq = wm831x_gpio_to_irq,
.set_debounce = wm831x_gpio_set_debounce, .set_config = wm831x_set_config,
.set_single_ended = wm831x_set_single_ended,
.dbg_show = wm831x_gpio_dbg_show, .dbg_show = wm831x_gpio_dbg_show,
.can_sleep = true, .can_sleep = true,
}; };

View File

@ -103,19 +103,18 @@ static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value); wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value);
} }
static int wm8994_gpio_set_single_ended(struct gpio_chip *chip, static int wm8994_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned int offset, unsigned long config)
enum single_ended_mode mode)
{ {
struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip); struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip);
struct wm8994 *wm8994 = wm8994_gpio->wm8994; struct wm8994 *wm8994 = wm8994_gpio->wm8994;
switch (mode) { switch (pinconf_to_config_param(config)) {
case LINE_MODE_OPEN_DRAIN: case PIN_CONFIG_DRIVE_OPEN_DRAIN:
return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
WM8994_GPN_OP_CFG_MASK, WM8994_GPN_OP_CFG_MASK,
WM8994_GPN_OP_CFG); WM8994_GPN_OP_CFG);
case LINE_MODE_PUSH_PULL: case PIN_CONFIG_DRIVE_PUSH_PULL:
return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
WM8994_GPN_OP_CFG_MASK, 0); WM8994_GPN_OP_CFG_MASK, 0);
default: default:
@ -257,7 +256,7 @@ static const struct gpio_chip template_chip = {
.get = wm8994_gpio_get, .get = wm8994_gpio_get,
.direction_output = wm8994_gpio_direction_out, .direction_output = wm8994_gpio_direction_out,
.set = wm8994_gpio_set, .set = wm8994_gpio_set,
.set_single_ended = wm8994_gpio_set_single_ended, .set_config = wm8994_gpio_set_config,
.to_irq = wm8994_gpio_to_irq, .to_irq = wm8994_gpio_to_irq,
.dbg_show = wm8994_gpio_dbg_show, .dbg_show = wm8994_gpio_dbg_show,
.can_sleep = true, .can_sleep = true,

View File

@ -1876,6 +1876,19 @@ void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset)
} }
EXPORT_SYMBOL_GPL(gpiochip_generic_free); EXPORT_SYMBOL_GPL(gpiochip_generic_free);
/**
* gpiochip_generic_config() - apply configuration for a pin
* @chip: the gpiochip owning the GPIO
* @offset: the offset of the GPIO to apply the configuration
* @config: the configuration to be applied
*/
int gpiochip_generic_config(struct gpio_chip *chip, unsigned offset,
unsigned long config)
{
return pinctrl_gpio_set_config(chip->gpiodev->base + offset, config);
}
EXPORT_SYMBOL_GPL(gpiochip_generic_config);
#ifdef CONFIG_PINCTRL #ifdef CONFIG_PINCTRL
/** /**
@ -2264,6 +2277,14 @@ int gpiod_direction_input(struct gpio_desc *desc)
} }
EXPORT_SYMBOL_GPL(gpiod_direction_input); EXPORT_SYMBOL_GPL(gpiod_direction_input);
static int gpio_set_drive_single_ended(struct gpio_chip *gc, unsigned offset,
enum pin_config_param mode)
{
unsigned long config = { PIN_CONF_PACKED(mode, 0) };
return gc->set_config ? gc->set_config(gc, offset, config) : -ENOTSUPP;
}
static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value) static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
{ {
struct gpio_chip *gc = desc->gdev->chip; struct gpio_chip *gc = desc->gdev->chip;
@ -2280,32 +2301,25 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) { if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) {
/* First see if we can enable open drain in hardware */ /* First see if we can enable open drain in hardware */
if (gc->set_single_ended) { ret = gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc),
ret = gc->set_single_ended(gc, gpio_chip_hwgpio(desc), PIN_CONFIG_DRIVE_OPEN_DRAIN);
LINE_MODE_OPEN_DRAIN); if (!ret)
if (!ret) goto set_output_value;
goto set_output_value;
}
/* Emulate open drain by not actively driving the line high */ /* Emulate open drain by not actively driving the line high */
if (val) if (val)
return gpiod_direction_input(desc); return gpiod_direction_input(desc);
} }
else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) { else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) {
if (gc->set_single_ended) { ret = gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc),
ret = gc->set_single_ended(gc, gpio_chip_hwgpio(desc), PIN_CONFIG_DRIVE_OPEN_SOURCE);
LINE_MODE_OPEN_SOURCE); if (!ret)
if (!ret) goto set_output_value;
goto set_output_value;
}
/* Emulate open source by not actively driving the line low */ /* Emulate open source by not actively driving the line low */
if (!val) if (!val)
return gpiod_direction_input(desc); return gpiod_direction_input(desc);
} else { } else {
/* Make sure to disable open drain/source hardware, if any */ gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc),
if (gc->set_single_ended) PIN_CONFIG_DRIVE_PUSH_PULL);
gc->set_single_ended(gc,
gpio_chip_hwgpio(desc),
LINE_MODE_PUSH_PULL);
} }
set_output_value: set_output_value:
@ -2376,17 +2390,19 @@ EXPORT_SYMBOL_GPL(gpiod_direction_output);
int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
{ {
struct gpio_chip *chip; struct gpio_chip *chip;
unsigned long config;
VALIDATE_DESC(desc); VALIDATE_DESC(desc);
chip = desc->gdev->chip; chip = desc->gdev->chip;
if (!chip->set || !chip->set_debounce) { if (!chip->set || !chip->set_config) {
gpiod_dbg(desc, gpiod_dbg(desc,
"%s: missing set() or set_debounce() operations\n", "%s: missing set() or set_config() operations\n",
__func__); __func__);
return -ENOTSUPP; return -ENOTSUPP;
} }
return chip->set_debounce(chip, gpio_chip_hwgpio(desc), debounce); config = pinconf_to_config_packed(PIN_CONFIG_INPUT_DEBOUNCE, debounce);
return chip->set_config(chip, gpio_chip_hwgpio(desc), config);
} }
EXPORT_SYMBOL_GPL(gpiod_set_debounce); EXPORT_SYMBOL_GPL(gpiod_set_debounce);

View File

@ -1106,7 +1106,7 @@ static int bcm281xx_std_pin_update(struct pinctrl_dev *pctldev,
struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
int i; int i;
enum pin_config_param param; enum pin_config_param param;
u16 arg; u32 arg;
for (i = 0; i < num_configs; i++) { for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]); param = pinconf_to_config_param(configs[i]);
@ -1222,7 +1222,7 @@ static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev,
struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
int i, j; int i, j;
enum pin_config_param param; enum pin_config_param param;
u16 arg; u32 arg;
for (i = 0; i < num_configs; i++) { for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]); param = pinconf_to_config_param(configs[i]);
@ -1292,7 +1292,7 @@ static int bcm281xx_hdmi_pin_update(struct pinctrl_dev *pctldev,
struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
int i; int i;
enum pin_config_param param; enum pin_config_param param;
u16 arg; u32 arg;
for (i = 0; i < num_configs; i++) { for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]); param = pinconf_to_config_param(configs[i]);

View File

@ -619,7 +619,7 @@ static int iproc_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
{ {
struct iproc_gpio *chip = pinctrl_dev_get_drvdata(pctldev); struct iproc_gpio *chip = pinctrl_dev_get_drvdata(pctldev);
enum pin_config_param param; enum pin_config_param param;
u16 arg; u32 arg;
unsigned i, gpio = iproc_pin_to_gpio(pin); unsigned i, gpio = iproc_pin_to_gpio(pin);
int ret = -ENOTSUPP; int ret = -ENOTSUPP;

View File

@ -703,7 +703,7 @@ static int ns2_pin_get_enable(struct pinctrl_dev *pctrldev, unsigned int pin)
} }
static int ns2_pin_set_slew(struct pinctrl_dev *pctrldev, unsigned int pin, static int ns2_pin_set_slew(struct pinctrl_dev *pctrldev, unsigned int pin,
u16 slew) u32 slew)
{ {
struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrldev); struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrldev);
struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data; struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data;
@ -793,7 +793,7 @@ static void ns2_pin_get_pull(struct pinctrl_dev *pctrldev,
} }
static int ns2_pin_set_strength(struct pinctrl_dev *pctrldev, unsigned int pin, static int ns2_pin_set_strength(struct pinctrl_dev *pctrldev, unsigned int pin,
u16 strength) u32 strength)
{ {
struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrldev); struct ns2_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrldev);
struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data; struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data;
@ -904,7 +904,7 @@ static int ns2_pin_config_set(struct pinctrl_dev *pctrldev, unsigned int pin,
struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data; struct ns2_pin *pin_data = pctrldev->desc->pins[pin].drv_data;
enum pin_config_param param; enum pin_config_param param;
unsigned int i; unsigned int i;
u16 arg; u32 arg;
int ret = -ENOTSUPP; int ret = -ENOTSUPP;
if (pin_data->pin_conf.base == -1) if (pin_data->pin_conf.base == -1)

View File

@ -366,7 +366,7 @@ static const struct pinctrl_ops nsp_pctrl_ops = {
.dt_free_map = pinctrl_utils_free_map, .dt_free_map = pinctrl_utils_free_map,
}; };
static int nsp_gpio_set_slew(struct nsp_gpio *chip, unsigned gpio, u16 slew) static int nsp_gpio_set_slew(struct nsp_gpio *chip, unsigned gpio, u32 slew)
{ {
if (slew) if (slew)
nsp_set_bit(chip, IO_CTRL, NSP_GPIO_SLEW_RATE_EN, gpio, true); nsp_set_bit(chip, IO_CTRL, NSP_GPIO_SLEW_RATE_EN, gpio, true);
@ -403,7 +403,7 @@ static void nsp_gpio_get_pull(struct nsp_gpio *chip, unsigned gpio,
} }
static int nsp_gpio_set_strength(struct nsp_gpio *chip, unsigned gpio, static int nsp_gpio_set_strength(struct nsp_gpio *chip, unsigned gpio,
u16 strength) u32 strength)
{ {
u32 offset, shift, i; u32 offset, shift, i;
u32 val; u32 val;
@ -522,7 +522,7 @@ static int nsp_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
{ {
struct nsp_gpio *chip = pinctrl_dev_get_drvdata(pctldev); struct nsp_gpio *chip = pinctrl_dev_get_drvdata(pctldev);
enum pin_config_param param; enum pin_config_param param;
u16 arg; u32 arg;
unsigned int i, gpio; unsigned int i, gpio;
int ret = -ENOTSUPP; int ret = -ENOTSUPP;

View File

@ -862,6 +862,35 @@ int pinctrl_gpio_direction_output(unsigned gpio)
} }
EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_output); EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_output);
/**
* pinctrl_gpio_set_config() - Apply config to given GPIO pin
* @gpio: the GPIO pin number from the GPIO subsystem number space
* @config: the configuration to apply to the GPIO
*
* This function should *ONLY* be used from gpiolib-based GPIO drivers, if
* they need to call the underlying pin controller to change GPIO config
* (for example set debounce time).
*/
int pinctrl_gpio_set_config(unsigned gpio, unsigned long config)
{
unsigned long configs[] = { config };
struct pinctrl_gpio_range *range;
struct pinctrl_dev *pctldev;
int ret, pin;
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
if (ret)
return ret;
mutex_lock(&pctldev->mutex);
pin = gpio_to_pin(range, gpio);
ret = pinconf_set_config(pctldev, pin, configs, ARRAY_SIZE(configs));
mutex_unlock(&pctldev->mutex);
return ret;
}
EXPORT_SYMBOL_GPL(pinctrl_gpio_set_config);
static struct pinctrl_state *find_state(struct pinctrl *p, static struct pinctrl_state *find_state(struct pinctrl *p,
const char *name) const char *name)
{ {

View File

@ -1059,7 +1059,7 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned pin,
} }
static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned pin, static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned pin,
enum pin_config_param param, u16 arg) enum pin_config_param param, u32 arg)
{ {
void __iomem *reg = chv_padreg(pctrl, pin, CHV_PADCTRL0); void __iomem *reg = chv_padreg(pctrl, pin, CHV_PADCTRL0);
unsigned long flags; unsigned long flags;
@ -1151,7 +1151,7 @@ static int chv_config_set(struct pinctrl_dev *pctldev, unsigned pin,
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
enum pin_config_param param; enum pin_config_param param;
int i, ret; int i, ret;
u16 arg; u32 arg;
if (chv_pad_locked(pctrl, pin)) if (chv_pad_locked(pctrl, pin))
return -EBUSY; return -EBUSY;

View File

@ -1054,6 +1054,18 @@ static int mtk_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
return 0; return 0;
} }
static int mtk_gpio_set_config(struct gpio_chip *chip, unsigned offset,
unsigned long config)
{
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
debounce = pinconf_to_config_argument(config);
return mtk_gpio_set_debounce(chip, offset, debounce);
}
static const struct gpio_chip mtk_gpio_chip = { static const struct gpio_chip mtk_gpio_chip = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.request = gpiochip_generic_request, .request = gpiochip_generic_request,
@ -1064,7 +1076,7 @@ static const struct gpio_chip mtk_gpio_chip = {
.get = mtk_gpio_get, .get = mtk_gpio_get,
.set = mtk_gpio_set, .set = mtk_gpio_set,
.to_irq = mtk_gpio_to_irq, .to_irq = mtk_gpio_to_irq,
.set_debounce = mtk_gpio_set_debounce, .set_config = mtk_gpio_set_config,
.of_gpio_n_cells = 2, .of_gpio_n_cells = 2,
}; };

View File

@ -260,7 +260,6 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
enum pin_config_param param; enum pin_config_param param;
unsigned int reg, bit; unsigned int reg, bit;
int i, ret; int i, ret;
u16 arg;
ret = meson_get_bank(pc, pin, &bank); ret = meson_get_bank(pc, pin, &bank);
if (ret) if (ret)
@ -268,7 +267,6 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
for (i = 0; i < num_configs; i++) { for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]); param = pinconf_to_config_param(configs[i]);
arg = pinconf_to_config_argument(configs[i]);
switch (param) { switch (param) {
case PIN_CONFIG_BIAS_DISABLE: case PIN_CONFIG_BIAS_DISABLE:

View File

@ -200,6 +200,18 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting)
return 0; return 0;
} }
int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long *configs, size_t nconfigs)
{
const struct pinconf_ops *ops;
ops = pctldev->desc->confops;
if (!ops)
return -ENOTSUPP;
return ops->pin_config_set(pctldev, pin, configs, nconfigs);
}
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
static void pinconf_show_config(struct seq_file *s, struct pinctrl_dev *pctldev, static void pinconf_show_config(struct seq_file *s, struct pinctrl_dev *pctldev,

View File

@ -20,6 +20,9 @@ int pinconf_map_to_setting(struct pinctrl_map const *map,
void pinconf_free_setting(struct pinctrl_setting const *setting); void pinconf_free_setting(struct pinctrl_setting const *setting);
int pinconf_apply_setting(struct pinctrl_setting const *setting); int pinconf_apply_setting(struct pinctrl_setting const *setting);
int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long *configs, size_t nconfigs);
/* /*
* You will only be interested in these if you're using PINCONF * You will only be interested in these if you're using PINCONF
* so don't supply any stubs for these. * so don't supply any stubs for these.
@ -56,6 +59,12 @@ static inline int pinconf_apply_setting(struct pinctrl_setting const *setting)
return 0; return 0;
} }
static inline int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long *configs, size_t nconfigs)
{
return -ENOTSUPP;
}
#endif #endif
#if defined(CONFIG_PINCONF) && defined(CONFIG_DEBUG_FS) #if defined(CONFIG_PINCONF) && defined(CONFIG_DEBUG_FS)

View File

@ -164,6 +164,18 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset,
return ret; return ret;
} }
static int amd_gpio_set_config(struct gpio_chip *gc, unsigned offset,
unsigned long config)
{
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
debounce = pinconf_to_config_argument(config);
return amd_gpio_set_debounce(gc, offset, debounce);
}
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc) static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
{ {
@ -768,7 +780,7 @@ static int amd_gpio_probe(struct platform_device *pdev)
gpio_dev->gc.direction_output = amd_gpio_direction_output; gpio_dev->gc.direction_output = amd_gpio_direction_output;
gpio_dev->gc.get = amd_gpio_get_value; gpio_dev->gc.get = amd_gpio_get_value;
gpio_dev->gc.set = amd_gpio_set_value; gpio_dev->gc.set = amd_gpio_set_value;
gpio_dev->gc.set_debounce = amd_gpio_set_debounce; gpio_dev->gc.set_config = amd_gpio_set_config;
gpio_dev->gc.dbg_show = amd_gpio_dbg_show; gpio_dev->gc.dbg_show = amd_gpio_dbg_show;
gpio_dev->gc.base = -1; gpio_dev->gc.base = -1;

View File

@ -113,7 +113,6 @@ static int da850_pupd_pin_config_group_set(struct pinctrl_dev *pctldev,
struct da850_pupd_data *data = pinctrl_dev_get_drvdata(pctldev); struct da850_pupd_data *data = pinctrl_dev_get_drvdata(pctldev);
u32 ena, sel; u32 ena, sel;
enum pin_config_param param; enum pin_config_param param;
u16 arg;
int i; int i;
ena = readl(data->base + DA850_PUPD_ENA); ena = readl(data->base + DA850_PUPD_ENA);
@ -121,7 +120,6 @@ static int da850_pupd_pin_config_group_set(struct pinctrl_dev *pctldev,
for (i = 0; i < num_configs; i++) { for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]); param = pinconf_to_config_param(configs[i]);
arg = pinconf_to_config_argument(configs[i]);
switch (param) { switch (param) {
case PIN_CONFIG_BIAS_DISABLE: case PIN_CONFIG_BIAS_DISABLE:

View File

@ -904,7 +904,7 @@ static int lpc18xx_pconf_get(struct pinctrl_dev *pctldev, unsigned pin,
static int lpc18xx_pconf_set_usb1(struct pinctrl_dev *pctldev, static int lpc18xx_pconf_set_usb1(struct pinctrl_dev *pctldev,
enum pin_config_param param, enum pin_config_param param,
u16 param_val, u32 *reg) u32 param_val, u32 *reg)
{ {
switch (param) { switch (param) {
case PIN_CONFIG_LOW_POWER_MODE: case PIN_CONFIG_LOW_POWER_MODE:
@ -932,7 +932,7 @@ static int lpc18xx_pconf_set_usb1(struct pinctrl_dev *pctldev,
static int lpc18xx_pconf_set_i2c0(struct pinctrl_dev *pctldev, static int lpc18xx_pconf_set_i2c0(struct pinctrl_dev *pctldev,
enum pin_config_param param, enum pin_config_param param,
u16 param_val, u32 *reg, u32 param_val, u32 *reg,
unsigned pin) unsigned pin)
{ {
u8 shift; u8 shift;
@ -982,7 +982,7 @@ static int lpc18xx_pconf_set_i2c0(struct pinctrl_dev *pctldev,
} }
static int lpc18xx_pconf_set_gpio_pin_int(struct pinctrl_dev *pctldev, static int lpc18xx_pconf_set_gpio_pin_int(struct pinctrl_dev *pctldev,
u16 param_val, unsigned pin) u32 param_val, unsigned pin)
{ {
struct lpc18xx_scu_data *scu = pinctrl_dev_get_drvdata(pctldev); struct lpc18xx_scu_data *scu = pinctrl_dev_get_drvdata(pctldev);
u32 val, reg_val, reg_offset = LPC18XX_SCU_PINTSEL0; u32 val, reg_val, reg_offset = LPC18XX_SCU_PINTSEL0;
@ -1008,7 +1008,7 @@ static int lpc18xx_pconf_set_gpio_pin_int(struct pinctrl_dev *pctldev,
} }
static int lpc18xx_pconf_set_pin(struct pinctrl_dev *pctldev, unsigned param, static int lpc18xx_pconf_set_pin(struct pinctrl_dev *pctldev, unsigned param,
u16 param_val, u32 *reg, unsigned pin, u32 param_val, u32 *reg, unsigned pin,
struct lpc18xx_pin_caps *pin_cap) struct lpc18xx_pin_caps *pin_cap)
{ {
switch (param) { switch (param) {
@ -1088,7 +1088,7 @@ static int lpc18xx_pconf_set(struct pinctrl_dev *pctldev, unsigned pin,
struct lpc18xx_scu_data *scu = pinctrl_dev_get_drvdata(pctldev); struct lpc18xx_scu_data *scu = pinctrl_dev_get_drvdata(pctldev);
struct lpc18xx_pin_caps *pin_cap; struct lpc18xx_pin_caps *pin_cap;
enum pin_config_param param; enum pin_config_param param;
u16 param_val; u32 param_val;
u32 reg; u32 reg;
int ret; int ret;
int i; int i;

View File

@ -402,7 +402,7 @@ static int max77620_pinconf_set(struct pinctrl_dev *pctldev,
struct device *dev = mpci->dev; struct device *dev = mpci->dev;
struct max77620_fps_config *fps_config; struct max77620_fps_config *fps_config;
int param; int param;
u16 param_val; u32 param_val;
unsigned int val; unsigned int val;
unsigned int pu_val; unsigned int pu_val;
unsigned int pd_val; unsigned int pd_val;

View File

@ -860,7 +860,7 @@ static int palmas_pinconf_set(struct pinctrl_dev *pctldev,
{ {
struct palmas_pctrl_chip_info *pci = pinctrl_dev_get_drvdata(pctldev); struct palmas_pctrl_chip_info *pci = pinctrl_dev_get_drvdata(pctldev);
enum pin_config_param param; enum pin_config_param param;
u16 param_val; u32 param_val;
const struct palmas_pingroup *g; const struct palmas_pingroup *g;
const struct palmas_pin_info *opt; const struct palmas_pin_info *opt;
int ret; int ret;

View File

@ -1441,7 +1441,7 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
struct rockchip_pin_bank *bank = pin_to_bank(info, pin); struct rockchip_pin_bank *bank = pin_to_bank(info, pin);
enum pin_config_param param; enum pin_config_param param;
u16 arg; u32 arg;
int i; int i;
int rc; int rc;

View File

@ -504,7 +504,7 @@ static int pcs_pinconf_set(struct pinctrl_dev *pctldev,
struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev); struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
struct pcs_function *func; struct pcs_function *func;
unsigned offset = 0, shift = 0, i, data, ret; unsigned offset = 0, shift = 0, i, data, ret;
u16 arg; u32 arg;
int j; int j;
ret = pcs_get_function(pctldev, pin, &func); ret = pcs_get_function(pctldev, pin, &func);

View File

@ -424,41 +424,6 @@ static int sx150x_gpio_get(struct gpio_chip *chip, unsigned int offset)
return !!(value & BIT(offset)); return !!(value & BIT(offset));
} }
static int sx150x_gpio_set_single_ended(struct gpio_chip *chip,
unsigned int offset,
enum single_ended_mode mode)
{
struct sx150x_pinctrl *pctl = gpiochip_get_data(chip);
int ret;
switch (mode) {
case LINE_MODE_PUSH_PULL:
if (pctl->data->model != SX150X_789 ||
sx150x_pin_is_oscio(pctl, offset))
return 0;
ret = regmap_write_bits(pctl->regmap,
pctl->data->pri.x789.reg_drain,
BIT(offset), 0);
break;
case LINE_MODE_OPEN_DRAIN:
if (pctl->data->model != SX150X_789 ||
sx150x_pin_is_oscio(pctl, offset))
return -ENOTSUPP;
ret = regmap_write_bits(pctl->regmap,
pctl->data->pri.x789.reg_drain,
BIT(offset), BIT(offset));
break;
default:
ret = -ENOTSUPP;
break;
}
return ret;
}
static int __sx150x_gpio_set(struct sx150x_pinctrl *pctl, unsigned int offset, static int __sx150x_gpio_set(struct sx150x_pinctrl *pctl, unsigned int offset,
int value) int value)
{ {
@ -811,16 +776,26 @@ static int sx150x_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
break; break;
case PIN_CONFIG_DRIVE_OPEN_DRAIN: case PIN_CONFIG_DRIVE_OPEN_DRAIN:
ret = sx150x_gpio_set_single_ended(&pctl->gpio, if (pctl->data->model != SX150X_789 ||
pin, LINE_MODE_OPEN_DRAIN); sx150x_pin_is_oscio(pctl, pin))
return -ENOTSUPP;
ret = regmap_write_bits(pctl->regmap,
pctl->data->pri.x789.reg_drain,
BIT(pin), BIT(pin));
if (ret < 0) if (ret < 0)
return ret; return ret;
break; break;
case PIN_CONFIG_DRIVE_PUSH_PULL: case PIN_CONFIG_DRIVE_PUSH_PULL:
ret = sx150x_gpio_set_single_ended(&pctl->gpio, if (pctl->data->model != SX150X_789 ||
pin, LINE_MODE_PUSH_PULL); sx150x_pin_is_oscio(pctl, pin))
return 0;
ret = regmap_write_bits(pctl->regmap,
pctl->data->pri.x789.reg_drain,
BIT(pin), 0);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -1178,7 +1153,7 @@ static int sx150x_probe(struct i2c_client *client,
pctl->gpio.direction_output = sx150x_gpio_direction_output; pctl->gpio.direction_output = sx150x_gpio_direction_output;
pctl->gpio.get = sx150x_gpio_get; pctl->gpio.get = sx150x_gpio_get;
pctl->gpio.set = sx150x_gpio_set; pctl->gpio.set = sx150x_gpio_set;
pctl->gpio.set_single_ended = sx150x_gpio_set_single_ended; pctl->gpio.set_config = gpiochip_generic_config;
pctl->gpio.parent = dev; pctl->gpio.parent = dev;
#ifdef CONFIG_OF_GPIO #ifdef CONFIG_OF_GPIO
pctl->gpio.of_node = dev->of_node; pctl->gpio.of_node = dev->of_node;

View File

@ -5322,7 +5322,8 @@ static int atlas7_pin_config_set(struct pinctrl_dev *pctldev,
unsigned pin, unsigned long *configs, unsigned pin, unsigned long *configs,
unsigned num_configs) unsigned num_configs)
{ {
u16 param, arg; u16 param;
u32 arg;
int idx, err; int idx, err;
for (idx = 0; idx < num_configs; idx++) { for (idx = 0; idx < num_configs; idx++) {

View File

@ -540,7 +540,7 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
enum pin_config_param param; enum pin_config_param param;
unsigned long flags; unsigned long flags;
u32 offset, shift, mask, reg; u32 offset, shift, mask, reg;
u16 arg, val; u32 arg, val;
int ret; int ret;
param = pinconf_to_config_param(configs[i]); param = pinconf_to_config_param(configs[i]);

View File

@ -297,7 +297,7 @@ static int uniphier_conf_pin_config_get(struct pinctrl_dev *pctldev,
static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev, static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
const struct pin_desc *desc, const struct pin_desc *desc,
enum pin_config_param param, u16 arg) enum pin_config_param param, u32 arg)
{ {
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
enum uniphier_pin_pull_dir pull_dir = enum uniphier_pin_pull_dir pull_dir =
@ -468,7 +468,7 @@ static int uniphier_conf_pin_config_set(struct pinctrl_dev *pctldev,
for (i = 0; i < num_configs; i++) { for (i = 0; i < num_configs; i++) {
enum pin_config_param param = enum pin_config_param param =
pinconf_to_config_param(configs[i]); pinconf_to_config_param(configs[i]);
u16 arg = pinconf_to_config_argument(configs[i]); u32 arg = pinconf_to_config_argument(configs[i]);
switch (param) { switch (param) {
case PIN_CONFIG_BIAS_DISABLE: case PIN_CONFIG_BIAS_DISABLE:

View File

@ -428,7 +428,7 @@ static int wmt_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
{ {
struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);
enum pin_config_param param; enum pin_config_param param;
u16 arg; u32 arg;
u32 bank = WMT_BANK_FROM_PIN(pin); u32 bank = WMT_BANK_FROM_PIN(pin);
u32 bit = WMT_BIT_FROM_PIN(pin); u32 bit = WMT_BIT_FROM_PIN(pin);
u32 reg_pull_en = data->banks[bank].reg_pull_en; u32 reg_pull_en = data->banks[bank].reg_pull_en;

View File

@ -610,7 +610,7 @@ static int rtc_pinconf_set(struct pinctrl_dev *pctldev,
struct omap_rtc *rtc = pinctrl_dev_get_drvdata(pctldev); struct omap_rtc *rtc = pinctrl_dev_get_drvdata(pctldev);
u32 val; u32 val;
unsigned int param; unsigned int param;
u16 param_val; u32 param_val;
int i; int i;
rtc->type->unlock(rtc); rtc->type->unlock(rtc);

View File

@ -474,17 +474,20 @@ static void gb_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
gb_gpio_set_value_operation(ggc, (u8)offset, !!value); gb_gpio_set_value_operation(ggc, (u8)offset, !!value);
} }
static int gb_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, static int gb_gpio_set_config(struct gpio_chip *chip, unsigned offset,
unsigned debounce) unsigned long config)
{ {
struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
u16 usec; u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
debounce = pinconf_to_config_argument(config);
if (debounce > U16_MAX) if (debounce > U16_MAX)
return -EINVAL; return -EINVAL;
usec = (u16)debounce;
return gb_gpio_set_debounce_operation(ggc, (u8)offset, usec); return gb_gpio_set_debounce_operation(ggc, (u8)offset, (u16)debounce);
} }
static int gb_gpio_controller_setup(struct gb_gpio_controller *ggc) static int gb_gpio_controller_setup(struct gb_gpio_controller *ggc)
@ -689,7 +692,7 @@ static int gb_gpio_probe(struct gbphy_device *gbphy_dev,
gpio->direction_output = gb_gpio_direction_output; gpio->direction_output = gb_gpio_direction_output;
gpio->get = gb_gpio_get; gpio->get = gb_gpio_get;
gpio->set = gb_gpio_set; gpio->set = gb_gpio_set;
gpio->set_debounce = gb_gpio_set_debounce; gpio->set_config = gb_gpio_set_config;
gpio->to_irq = gb_gpio_to_irq; gpio->to_irq = gb_gpio_to_irq;
gpio->base = -1; /* Allocate base dynamically */ gpio->base = -1; /* Allocate base dynamically */
gpio->ngpio = ggc->line_max + 1; gpio->ngpio = ggc->line_max + 1;

View File

@ -1329,17 +1329,20 @@ static int cp210x_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio,
return 0; return 0;
} }
static int cp210x_gpio_set_single_ended(struct gpio_chip *gc, unsigned int gpio, static int cp210x_gpio_set_config(struct gpio_chip *gc, unsigned int gpio,
enum single_ended_mode mode) unsigned long config)
{ {
struct usb_serial *serial = gpiochip_get_data(gc); struct usb_serial *serial = gpiochip_get_data(gc);
struct cp210x_serial_private *priv = usb_get_serial_data(serial); struct cp210x_serial_private *priv = usb_get_serial_data(serial);
enum pin_config_param param = pinconf_to_config_param(config);
/* Succeed only if in correct mode (this can't be set at runtime) */ /* Succeed only if in correct mode (this can't be set at runtime) */
if ((mode == LINE_MODE_PUSH_PULL) && (priv->gpio_mode & BIT(gpio))) if ((param == PIN_CONFIG_DRIVE_PUSH_PULL) &&
(priv->gpio_mode & BIT(gpio)))
return 0; return 0;
if ((mode == LINE_MODE_OPEN_DRAIN) && !(priv->gpio_mode & BIT(gpio))) if ((param == PIN_CONFIG_DRIVE_OPEN_DRAIN) &&
!(priv->gpio_mode & BIT(gpio)))
return 0; return 0;
return -ENOTSUPP; return -ENOTSUPP;
@ -1402,7 +1405,7 @@ static int cp2105_shared_gpio_init(struct usb_serial *serial)
priv->gc.direction_output = cp210x_gpio_direction_output; priv->gc.direction_output = cp210x_gpio_direction_output;
priv->gc.get = cp210x_gpio_get; priv->gc.get = cp210x_gpio_get;
priv->gc.set = cp210x_gpio_set; priv->gc.set = cp210x_gpio_set;
priv->gc.set_single_ended = cp210x_gpio_set_single_ended; priv->gc.set_config = cp210x_gpio_set_config;
priv->gc.owner = THIS_MODULE; priv->gc.owner = THIS_MODULE;
priv->gc.parent = &serial->interface->dev; priv->gc.parent = &serial->interface->dev;
priv->gc.base = -1; priv->gc.base = -1;

View File

@ -8,6 +8,7 @@
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
#include <linux/lockdep.h> #include <linux/lockdep.h>
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinconf-generic.h>
struct gpio_desc; struct gpio_desc;
struct of_phandle_args; struct of_phandle_args;
@ -18,18 +19,6 @@ struct module;
#ifdef CONFIG_GPIOLIB #ifdef CONFIG_GPIOLIB
/**
* enum single_ended_mode - mode for single ended operation
* @LINE_MODE_PUSH_PULL: normal mode for a GPIO line, drive actively high/low
* @LINE_MODE_OPEN_DRAIN: set line to be open drain
* @LINE_MODE_OPEN_SOURCE: set line to be open source
*/
enum single_ended_mode {
LINE_MODE_PUSH_PULL,
LINE_MODE_OPEN_DRAIN,
LINE_MODE_OPEN_SOURCE,
};
/** /**
* struct gpio_chip - abstract a GPIO controller * struct gpio_chip - abstract a GPIO controller
* @label: a functional name for the GPIO device, such as a part * @label: a functional name for the GPIO device, such as a part
@ -48,16 +37,8 @@ enum single_ended_mode {
* @get: returns value for signal "offset", 0=low, 1=high, or negative error * @get: returns value for signal "offset", 0=low, 1=high, or negative error
* @set: assigns output value for signal "offset" * @set: assigns output value for signal "offset"
* @set_multiple: assigns output values for multiple signals defined by "mask" * @set_multiple: assigns output values for multiple signals defined by "mask"
* @set_debounce: optional hook for setting debounce time for specified gpio in * @set_config: optional hook for all kinds of settings. Uses the same
* interrupt triggered gpio chips * packed config format as generic pinconf.
* @set_single_ended: optional hook for setting a line as open drain, open
* source, or non-single ended (restore from open drain/source to normal
* push-pull mode) this should be implemented if the hardware supports
* open drain or open source settings. The GPIOlib will otherwise try
* to emulate open drain/source by not actively driving lines high/low
* if a consumer request this. The driver may return -ENOTSUPP if e.g.
* it supports just open drain but not open source and is called
* with LINE_MODE_OPEN_SOURCE as mode argument.
* @to_irq: optional hook supporting non-static gpio_to_irq() mappings; * @to_irq: optional hook supporting non-static gpio_to_irq() mappings;
* implementation may not sleep * implementation may not sleep
* @dbg_show: optional routine to show contents in debugfs; default code * @dbg_show: optional routine to show contents in debugfs; default code
@ -150,13 +131,9 @@ struct gpio_chip {
void (*set_multiple)(struct gpio_chip *chip, void (*set_multiple)(struct gpio_chip *chip,
unsigned long *mask, unsigned long *mask,
unsigned long *bits); unsigned long *bits);
int (*set_debounce)(struct gpio_chip *chip, int (*set_config)(struct gpio_chip *chip,
unsigned offset, unsigned offset,
unsigned debounce); unsigned long config);
int (*set_single_ended)(struct gpio_chip *chip,
unsigned offset,
enum single_ended_mode mode);
int (*to_irq)(struct gpio_chip *chip, int (*to_irq)(struct gpio_chip *chip,
unsigned offset); unsigned offset);
@ -310,6 +287,8 @@ static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gpiochip,
int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset); int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset);
void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset); void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset);
int gpiochip_generic_config(struct gpio_chip *chip, unsigned offset,
unsigned long config);
#ifdef CONFIG_PINCTRL #ifdef CONFIG_PINCTRL

View File

@ -29,6 +29,7 @@ extern int pinctrl_request_gpio(unsigned gpio);
extern void pinctrl_free_gpio(unsigned gpio); extern void pinctrl_free_gpio(unsigned gpio);
extern int pinctrl_gpio_direction_input(unsigned gpio); extern int pinctrl_gpio_direction_input(unsigned gpio);
extern int pinctrl_gpio_direction_output(unsigned gpio); extern int pinctrl_gpio_direction_output(unsigned gpio);
extern int pinctrl_gpio_set_config(unsigned gpio, unsigned long config);
extern struct pinctrl * __must_check pinctrl_get(struct device *dev); extern struct pinctrl * __must_check pinctrl_get(struct device *dev);
extern void pinctrl_put(struct pinctrl *p); extern void pinctrl_put(struct pinctrl *p);
@ -80,6 +81,11 @@ static inline int pinctrl_gpio_direction_output(unsigned gpio)
return 0; return 0;
} }
static inline int pinctrl_gpio_set_config(unsigned gpio, unsigned long config)
{
return 0;
}
static inline struct pinctrl * __must_check pinctrl_get(struct device *dev) static inline struct pinctrl * __must_check pinctrl_get(struct device *dev)
{ {
return NULL; return NULL;

View File

@ -12,12 +12,6 @@
#ifndef __LINUX_PINCTRL_PINCONF_GENERIC_H #ifndef __LINUX_PINCTRL_PINCONF_GENERIC_H
#define __LINUX_PINCTRL_PINCONF_GENERIC_H #define __LINUX_PINCTRL_PINCONF_GENERIC_H
/*
* You shouldn't even be able to compile with these enums etc unless you're
* using generic pin config. That is why this is defined out.
*/
#ifdef CONFIG_GENERIC_PINCONF
/** /**
* enum pin_config_param - possible pin configuration parameters * enum pin_config_param - possible pin configuration parameters
* @PIN_CONFIG_BIAS_BUS_HOLD: the pin will be set to weakly latch so that it * @PIN_CONFIG_BIAS_BUS_HOLD: the pin will be set to weakly latch so that it
@ -92,6 +86,8 @@
* @PIN_CONFIG_END: this is the last enumerator for pin configurations, if * @PIN_CONFIG_END: this is the last enumerator for pin configurations, if
* you need to pass in custom configurations to the pin controller, use * you need to pass in custom configurations to the pin controller, use
* PIN_CONFIG_END+1 as the base offset. * PIN_CONFIG_END+1 as the base offset.
* @PIN_CONFIG_MAX: this is the maximum configuration value that can be
* presented using the packed format.
*/ */
enum pin_config_param { enum pin_config_param {
PIN_CONFIG_BIAS_BUS_HOLD, PIN_CONFIG_BIAS_BUS_HOLD,
@ -112,12 +108,44 @@ enum pin_config_param {
PIN_CONFIG_OUTPUT, PIN_CONFIG_OUTPUT,
PIN_CONFIG_POWER_SOURCE, PIN_CONFIG_POWER_SOURCE,
PIN_CONFIG_SLEW_RATE, PIN_CONFIG_SLEW_RATE,
PIN_CONFIG_END = 0x7FFF, PIN_CONFIG_END = 0x7F,
PIN_CONFIG_MAX = 0xFF,
}; };
/*
* Helpful configuration macro to be used in tables etc.
*/
#define PIN_CONF_PACKED(p, a) ((a << 8) | ((unsigned long) p & 0xffUL))
/*
* The following inlines stuffs a configuration parameter and data value
* into and out of an unsigned long argument, as used by the generic pin config
* system. We put the parameter in the lower 8 bits and the argument in the
* upper 24 bits.
*/
static inline enum pin_config_param pinconf_to_config_param(unsigned long config)
{
return (enum pin_config_param) (config & 0xffUL);
}
static inline u32 pinconf_to_config_argument(unsigned long config)
{
return (u32) ((config >> 8) & 0xffffffUL);
}
static inline unsigned long pinconf_to_config_packed(enum pin_config_param param,
u32 argument)
{
return PIN_CONF_PACKED(param, argument);
}
#ifdef CONFIG_GENERIC_PINCONF
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
#define PCONFDUMP(a, b, c, d) { .param = a, .display = b, .format = c, \ #define PCONFDUMP(a, b, c, d) { \
.has_arg = d } .param = a, .display = b, .format = c, .has_arg = d \
}
struct pin_config_item { struct pin_config_item {
const enum pin_config_param param; const enum pin_config_param param;
@ -127,34 +155,6 @@ struct pin_config_item {
}; };
#endif /* CONFIG_DEBUG_FS */ #endif /* CONFIG_DEBUG_FS */
/*
* Helpful configuration macro to be used in tables etc.
*/
#define PIN_CONF_PACKED(p, a) ((a << 16) | ((unsigned long) p & 0xffffUL))
/*
* The following inlines stuffs a configuration parameter and data value
* into and out of an unsigned long argument, as used by the generic pin config
* system. We put the parameter in the lower 16 bits and the argument in the
* upper 16 bits.
*/
static inline enum pin_config_param pinconf_to_config_param(unsigned long config)
{
return (enum pin_config_param) (config & 0xffffUL);
}
static inline u16 pinconf_to_config_argument(unsigned long config)
{
return (enum pin_config_param) ((config >> 16) & 0xffffUL);
}
static inline unsigned long pinconf_to_config_packed(enum pin_config_param param,
u16 argument)
{
return PIN_CONF_PACKED(param, argument);
}
#ifdef CONFIG_OF #ifdef CONFIG_OF
#include <linux/device.h> #include <linux/device.h>