summaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-aspeed.c187
-rw-r--r--drivers/gpio/gpio-bcm-kona.c14
-rw-r--r--drivers/gpio/gpio-dln2.c12
-rw-r--r--drivers/gpio/gpio-dwapb.c14
-rw-r--r--drivers/gpio/gpio-ep93xx.c11
-rw-r--r--drivers/gpio/gpio-f7188x.c19
-rw-r--r--drivers/gpio/gpio-lp873x.c14
-rw-r--r--drivers/gpio/gpio-max77620.c20
-rw-r--r--drivers/gpio/gpio-menz127.c34
-rw-r--r--drivers/gpio/gpio-merrifield.c14
-rw-r--r--drivers/gpio/gpio-omap.c14
-rw-r--r--drivers/gpio/gpio-tc3589x.c15
-rw-r--r--drivers/gpio/gpio-tegra.c14
-rw-r--r--drivers/gpio/gpio-tps65218.c14
-rw-r--r--drivers/gpio/gpio-vx855.c13
-rw-r--r--drivers/gpio/gpio-wcove.c13
-rw-r--r--drivers/gpio/gpio-wm831x.c21
-rw-r--r--drivers/gpio/gpio-wm8994.c13
-rw-r--r--drivers/gpio/gpiolib.c56
19 files changed, 377 insertions, 135 deletions
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index 03a5925a423c..fb16cc771c0d 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -18,55 +18,72 @@
#include <linux/gpio/driver.h>
#include <linux/pinctrl/consumer.h>
+struct aspeed_bank_props {
+ unsigned int bank;
+ u32 input;
+ u32 output;
+};
+
+struct aspeed_gpio_config {
+ unsigned int nr_gpios;
+ const struct aspeed_bank_props *props;
+};
+
struct aspeed_gpio {
struct gpio_chip chip;
spinlock_t lock;
void __iomem *base;
int irq;
+ const struct aspeed_gpio_config *config;
};
struct aspeed_gpio_bank {
uint16_t val_regs;
uint16_t irq_regs;
- const char names[4];
+ const char names[4][3];
};
static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
{
.val_regs = 0x0000,
.irq_regs = 0x0008,
- .names = { 'A', 'B', 'C', 'D' },
+ .names = { "A", "B", "C", "D" },
},
{
.val_regs = 0x0020,
.irq_regs = 0x0028,
- .names = { 'E', 'F', 'G', 'H' },
+ .names = { "E", "F", "G", "H" },
},
{
.val_regs = 0x0070,
.irq_regs = 0x0098,
- .names = { 'I', 'J', 'K', 'L' },
+ .names = { "I", "J", "K", "L" },
},
{
.val_regs = 0x0078,
.irq_regs = 0x00e8,
- .names = { 'M', 'N', 'O', 'P' },
+ .names = { "M", "N", "O", "P" },
},
{
.val_regs = 0x0080,
.irq_regs = 0x0118,
- .names = { 'Q', 'R', 'S', 'T' },
+ .names = { "Q", "R", "S", "T" },
},
{
.val_regs = 0x0088,
.irq_regs = 0x0148,
- .names = { 'U', 'V', 'W', 'X' },
+ .names = { "U", "V", "W", "X" },
+ },
+ {
+ .val_regs = 0x01E0,
+ .irq_regs = 0x0178,
+ .names = { "Y", "Z", "AA", "AB" },
+ },
+ {
+ .val_regs = 0x01E8,
+ .irq_regs = 0x01A8,
+ .names = { "AC", "", "", "" },
},
- /*
- * A bank exists for { 'Y', 'Z', "AA", "AB" }, but is not implemented.
- * Only half of GPIOs Y support interrupt configuration, and none of Z,
- * AA or AB do as they are output only.
- */
};
#define GPIO_BANK(x) ((x) >> 5)
@@ -90,6 +107,51 @@ static const struct aspeed_gpio_bank *to_bank(unsigned int offset)
return &aspeed_gpio_banks[bank];
}
+static inline bool is_bank_props_sentinel(const struct aspeed_bank_props *props)
+{
+ return !(props->input || props->output);
+}
+
+static inline const struct aspeed_bank_props *find_bank_props(
+ struct aspeed_gpio *gpio, unsigned int offset)
+{
+ const struct aspeed_bank_props *props = gpio->config->props;
+
+ while (!is_bank_props_sentinel(props)) {
+ if (props->bank == GPIO_BANK(offset))
+ return props;
+ props++;
+ }
+
+ return NULL;
+}
+
+static inline bool have_gpio(struct aspeed_gpio *gpio, unsigned int offset)
+{
+ const struct aspeed_bank_props *props = find_bank_props(gpio, offset);
+ const struct aspeed_gpio_bank *bank = to_bank(offset);
+ unsigned int group = GPIO_OFFSET(offset) / 8;
+
+ return bank->names[group][0] != '\0' &&
+ (!props || ((props->input | props->output) & GPIO_BIT(offset)));
+}
+
+static inline bool have_input(struct aspeed_gpio *gpio, unsigned int offset)
+{
+ const struct aspeed_bank_props *props = find_bank_props(gpio, offset);
+
+ return !props || (props->input & GPIO_BIT(offset));
+}
+
+#define have_irq(g, o) have_input((g), (o))
+
+static inline bool have_output(struct aspeed_gpio *gpio, unsigned int offset)
+{
+ const struct aspeed_bank_props *props = find_bank_props(gpio, offset);
+
+ return !props || (props->output & GPIO_BIT(offset));
+}
+
static void __iomem *bank_val_reg(struct aspeed_gpio *gpio,
const struct aspeed_gpio_bank *bank,
unsigned int reg)
@@ -152,6 +214,9 @@ static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)
unsigned long flags;
u32 reg;
+ if (!have_input(gpio, offset))
+ return -ENOTSUPP;
+
spin_lock_irqsave(&gpio->lock, flags);
reg = ioread32(bank_val_reg(gpio, bank, GPIO_DIR));
@@ -170,6 +235,9 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,
unsigned long flags;
u32 reg;
+ if (!have_output(gpio, offset))
+ return -ENOTSUPP;
+
spin_lock_irqsave(&gpio->lock, flags);
reg = ioread32(bank_val_reg(gpio, bank, GPIO_DIR));
@@ -189,6 +257,12 @@ static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
unsigned long flags;
u32 val;
+ if (!have_input(gpio, offset))
+ return 0;
+
+ if (!have_output(gpio, offset))
+ return 1;
+
spin_lock_irqsave(&gpio->lock, flags);
val = ioread32(bank_val_reg(gpio, bank, GPIO_DIR)) & GPIO_BIT(offset);
@@ -205,10 +279,17 @@ static inline int irqd_to_aspeed_gpio_data(struct irq_data *d,
u32 *bit)
{
int offset;
+ struct aspeed_gpio *internal;
offset = irqd_to_hwirq(d);
- *gpio = irq_data_get_irq_chip_data(d);
+ internal = irq_data_get_irq_chip_data(d);
+
+ /* This might be a bit of a questionable place to check */
+ if (!have_irq(internal, offset))
+ return -ENOTSUPP;
+
+ *gpio = internal;
*bank = to_bank(offset);
*bit = GPIO_BIT(offset);
@@ -364,6 +445,28 @@ static struct irq_chip aspeed_gpio_irqchip = {
.irq_set_type = aspeed_gpio_set_type,
};
+static void set_irq_valid_mask(struct aspeed_gpio *gpio)
+{
+ const struct aspeed_bank_props *props = gpio->config->props;
+
+ while (!is_bank_props_sentinel(props)) {
+ unsigned int offset;
+ const unsigned long int input = props->input;
+
+ /* Pretty crummy approach, but similar to GPIO core */
+ for_each_clear_bit(offset, &input, 32) {
+ unsigned int i = props->bank * 32 + offset;
+
+ if (i >= gpio->config->nr_gpios)
+ break;
+
+ clear_bit(i, gpio->chip.irq_valid_mask);
+ }
+
+ props++;
+ }
+}
+
static int aspeed_gpio_setup_irqs(struct aspeed_gpio *gpio,
struct platform_device *pdev)
{
@@ -375,6 +478,8 @@ static int aspeed_gpio_setup_irqs(struct aspeed_gpio *gpio,
gpio->irq = rc;
+ set_irq_valid_mask(gpio);
+
rc = gpiochip_irqchip_add(&gpio->chip, &aspeed_gpio_irqchip,
0, handle_bad_irq, IRQ_TYPE_NONE);
if (rc) {
@@ -390,6 +495,9 @@ static int aspeed_gpio_setup_irqs(struct aspeed_gpio *gpio,
static int aspeed_gpio_request(struct gpio_chip *chip, unsigned int offset)
{
+ if (!have_gpio(gpiochip_get_data(chip), offset))
+ return -ENODEV;
+
return pinctrl_request_gpio(chip->base + offset);
}
@@ -398,8 +506,46 @@ static void aspeed_gpio_free(struct gpio_chip *chip, unsigned int offset)
pinctrl_free_gpio(chip->base + offset);
}
+/*
+ * Any banks not specified in a struct aspeed_bank_props array are assumed to
+ * have the properties:
+ *
+ * { .input = 0xffffffff, .output = 0xffffffff }
+ */
+
+static const struct aspeed_bank_props ast2400_bank_props[] = {
+ /* input output */
+ { 5, 0xffffffff, 0x0000ffff }, /* U/V/W/X */
+ { 6, 0x0000000f, 0x0fffff0f }, /* Y/Z/AA/AB, two 4-GPIO holes */
+ { },
+};
+
+static const struct aspeed_gpio_config ast2400_config =
+ /* 220 for simplicity, really 216 with two 4-GPIO holes, four at end */
+ { .nr_gpios = 220, .props = ast2400_bank_props, };
+
+static const struct aspeed_bank_props ast2500_bank_props[] = {
+ /* input output */
+ { 5, 0xffffffff, 0x0000ffff }, /* U/V/W/X */
+ { 6, 0x0fffffff, 0x0fffffff }, /* Y/Z/AA/AB, 4-GPIO hole */
+ { 7, 0x000000ff, 0x000000ff }, /* AC */
+ { },
+};
+
+static const struct aspeed_gpio_config ast2500_config =
+ /* 232 for simplicity, actual number is 228 (4-GPIO hole in GPIOAB) */
+ { .nr_gpios = 232, .props = ast2500_bank_props, };
+
+static const struct of_device_id aspeed_gpio_of_table[] = {
+ { .compatible = "aspeed,ast2400-gpio", .data = &ast2400_config, },
+ { .compatible = "aspeed,ast2500-gpio", .data = &ast2500_config, },
+ {}
+};
+MODULE_DEVICE_TABLE(of, aspeed_gpio_of_table);
+
static int __init aspeed_gpio_probe(struct platform_device *pdev)
{
+ const struct of_device_id *gpio_id;
struct aspeed_gpio *gpio;
struct resource *res;
int rc;
@@ -415,8 +561,13 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
spin_lock_init(&gpio->lock);
- gpio->chip.ngpio = ARRAY_SIZE(aspeed_gpio_banks) * 32;
+ gpio_id = of_match_node(aspeed_gpio_of_table, pdev->dev.of_node);
+ if (!gpio_id)
+ return -EINVAL;
+
+ gpio->config = gpio_id->data;
+ gpio->chip.ngpio = gpio->config->nr_gpios;
gpio->chip.parent = &pdev->dev;
gpio->chip.direction_input = aspeed_gpio_dir_in;
gpio->chip.direction_output = aspeed_gpio_dir_out;
@@ -427,6 +578,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
gpio->chip.set = aspeed_gpio_set;
gpio->chip.label = dev_name(&pdev->dev);
gpio->chip.base = -1;
+ gpio->chip.irq_need_valid_mask = true;
rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
if (rc < 0)
@@ -435,13 +587,6 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
return aspeed_gpio_setup_irqs(gpio, pdev);
}
-static const struct of_device_id aspeed_gpio_of_table[] = {
- { .compatible = "aspeed,ast2400-gpio" },
- { .compatible = "aspeed,ast2500-gpio" },
- {}
-};
-MODULE_DEVICE_TABLE(of, aspeed_gpio_of_table);
-
static struct platform_driver aspeed_gpio_driver = {
.driver = {
.name = KBUILD_MODNAME,
diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c
index 3d1cf018e8e7..41d0ac142580 100644
--- a/drivers/gpio/gpio-bcm-kona.c
+++ b/drivers/gpio/gpio-bcm-kona.c
@@ -308,6 +308,18 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
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 = {
.label = "bcm-kona-gpio",
.owner = THIS_MODULE,
@@ -318,7 +330,7 @@ static const struct gpio_chip template_chip = {
.get = bcm_kona_gpio_get,
.direction_output = bcm_kona_gpio_direction_output,
.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,
.base = 0,
};
diff --git a/drivers/gpio/gpio-dln2.c b/drivers/gpio/gpio-dln2.c
index 5d38b08d1ee2..aecb847166f5 100644
--- a/drivers/gpio/gpio-dln2.c
+++ b/drivers/gpio/gpio-dln2.c
@@ -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);
}
-static int dln2_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
- unsigned debounce)
+static int dln2_gpio_set_config(struct gpio_chip *chip, unsigned offset,
+ unsigned long config)
{
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,
&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.direction_input = dln2_gpio_direction_input;
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);
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 6193f62c0df4..9c15ee4ef4e9 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -279,6 +279,18 @@ static int dwapb_gpio_set_debounce(struct gpio_chip *gc,
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)
{
u32 worked;
@@ -426,7 +438,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
/* Only port A support debounce */
if (pp->idx == 0)
- port->gc.set_debounce = dwapb_gpio_set_debounce;
+ port->gc.set_config = dwapb_gpio_set_config;
if (pp->irq)
dwapb_configure_irqs(gpio, port, pp);
diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c
index d054219e18b9..45d384039e9b 100644
--- a/drivers/gpio/gpio-ep93xx.c
+++ b/drivers/gpio/gpio-ep93xx.c
@@ -291,15 +291,20 @@ static struct ep93xx_gpio_bank ep93xx_gpio_banks[] = {
EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false),
};
-static int ep93xx_gpio_set_debounce(struct gpio_chip *chip,
- unsigned offset, unsigned debounce)
+static int ep93xx_gpio_set_config(struct gpio_chip *chip, unsigned offset,
+ unsigned long config)
{
int gpio = chip->base + offset;
int irq = gpio_to_irq(gpio);
+ u32 debounce;
+
+ if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
+ return -ENOTSUPP;
if (irq < 0)
return -EINVAL;
+ debounce = pinconf_to_config_argument(config);
ep93xx_gpio_int_debounce(irq, debounce ? true : false);
return 0;
@@ -335,7 +340,7 @@ static int ep93xx_gpio_add_bank(struct gpio_chip *gc, struct device *dev,
gc->base = bank->base;
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;
}
diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c
index e8accde62aa7..56bd76c33767 100644
--- a/drivers/gpio/gpio-f7188x.c
+++ b/drivers/gpio/gpio-f7188x.c
@@ -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,
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,
- unsigned offset,
- enum single_ended_mode mode);
+static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
+ unsigned long config);
#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, \
.direction_output = f7188x_gpio_direction_out, \
.set = f7188x_gpio_set, \
- .set_single_ended = f7188x_gpio_set_single_ended, \
+ .set_config = f7188x_gpio_set_config, \
.base = _base, \
.ngpio = _ngpio, \
.can_sleep = true, \
@@ -326,17 +325,17 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
superio_exit(sio->addr);
}
-static int f7188x_gpio_set_single_ended(struct gpio_chip *chip,
- unsigned offset,
- enum single_ended_mode mode)
+static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
+ unsigned long config)
{
int err;
+ enum pin_config_param param = pinconf_to_config_param(config);
struct f7188x_gpio_bank *bank = gpiochip_get_data(chip);
struct f7188x_sio *sio = bank->data->sio;
u8 data;
- if (mode != LINE_MODE_OPEN_DRAIN &&
- mode != LINE_MODE_PUSH_PULL)
+ if (param != PIN_CONFIG_DRIVE_OPEN_DRAIN &&
+ param != PIN_CONFIG_DRIVE_PUSH_PULL)
return -ENOTSUPP;
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);
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);
else
data |= BIT(offset);
diff --git a/drivers/gpio/gpio-lp873x.c b/drivers/gpio/gpio-lp873x.c
index 218c706359aa..df0ad2cef0d2 100644
--- a/drivers/gpio/gpio-lp873x.c
+++ b/drivers/gpio/gpio-lp873x.c
@@ -100,21 +100,21 @@ static int lp873x_gpio_request(struct gpio_chip *gc, unsigned int offset)
return 0;
}
-static int lp873x_gpio_set_single_ended(struct gpio_chip *gc,
- unsigned int offset,
- enum single_ended_mode mode)
+static int lp873x_gpio_set_config(struct gpio_chip *gc, unsigned offset,
+ unsigned long config)
{
struct lp873x_gpio *gpio = gpiochip_get_data(gc);
- switch (mode) {
- case LINE_MODE_OPEN_DRAIN:
+ switch (pinconf_to_config_param(config)) {
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
return regmap_update_bits(gpio->lp873->regmap,
LP873X_REG_GPO_CTRL,
BIT(offset * BITS_PER_GPO +
LP873X_GPO_CTRL_OD),
BIT(offset * BITS_PER_GPO +
LP873X_GPO_CTRL_OD));
- case LINE_MODE_PUSH_PULL:
+
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
return regmap_update_bits(gpio->lp873->regmap,
LP873X_REG_GPO_CTRL,
BIT(offset * BITS_PER_GPO +
@@ -133,7 +133,7 @@ static const struct gpio_chip template_chip = {
.direction_output = lp873x_gpio_direction_output,
.get = lp873x_gpio_get,
.set = lp873x_gpio_set,
- .set_single_ended = lp873x_gpio_set_single_ended,
+ .set_config = lp873x_gpio_set_config,
.base = -1,
.ngpio = 2,
.can_sleep = true,
diff --git a/drivers/gpio/gpio-max77620.c b/drivers/gpio/gpio-max77620.c
index ec8de4190db9..743459d9477d 100644
--- a/drivers/gpio/gpio-max77620.c
+++ b/drivers/gpio/gpio-max77620.c
@@ -152,11 +152,10 @@ static int max77620_gpio_dir_output(struct gpio_chip *gc, unsigned int offset,
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 debounce)
{
- struct max77620_gpio *mgpio = gpiochip_get_data(gc);
u8 val;
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);
}
-static int max77620_gpio_set_single_ended(struct gpio_chip *gc,
- unsigned int offset,
- enum single_ended_mode mode)
+static int max77620_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
+ unsigned long config)
{
struct max77620_gpio *mgpio = gpiochip_get_data(gc);
- switch (mode) {
- case LINE_MODE_OPEN_DRAIN:
+ switch (pinconf_to_config_param(config)) {
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
return regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
MAX77620_CNFG_GPIO_DRV_MASK,
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),
MAX77620_CNFG_GPIO_DRV_MASK,
MAX77620_CNFG_GPIO_DRV_PUSHPULL);
+ case PIN_CONFIG_INPUT_DEBOUNCE:
+ return max77620_gpio_set_debounce(mgpio, offset,
+ pinconf_to_config_argument(config));
default:
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.get = max77620_gpio_get;
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_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.ngpio = MAX77620_GPIO_NR;
mgpio->gpio_chip.can_sleep = 1;
diff --git a/drivers/gpio/gpio-menz127.c b/drivers/gpio/gpio-menz127.c
index a1210e330571..e1037582e34d 100644
--- a/drivers/gpio/gpio-menz127.c
+++ b/drivers/gpio/gpio-menz127.c
@@ -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,
unsigned offset,
- enum single_ended_mode mode)
+ enum pin_config_param param)
{
struct men_z127_gpio *priv = gpiochip_get_data(gc);
u32 od_en;
- if (mode != LINE_MODE_OPEN_DRAIN &&
- mode != LINE_MODE_PUSH_PULL)
- return -ENOTSUPP;
-
spin_lock(&gc->bgpio_lock);
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);
else
- /* Implicitly LINE_MODE_PUSH_PULL */
+ /* Implicitly PIN_CONFIG_DRIVE_PUSH_PULL */
od_en &= ~BIT(offset);
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;
}
+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,
const struct mcb_device_id *id)
{
@@ -149,8 +166,7 @@ static int men_z127_probe(struct mcb_device *mdev,
if (ret)
goto err_unmap;
- men_z127_gpio->gc.set_debounce = men_z127_debounce;
- men_z127_gpio->gc.set_single_ended = men_z127_set_single_ended;
+ men_z127_gpio->gc.set_config = men_z127_set_config;
ret = gpiochip_add_data(&men_z127_gpio->gc, men_z127_gpio);
if (ret) {
diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c
index 69e0f4ace465..f40088d268c1 100644
--- a/drivers/gpio/gpio-merrifield.c
+++ b/drivers/gpio/gpio-merrifield.c
@@ -190,6 +190,18 @@ static int mrfld_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
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)
{
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.set = mrfld_gpio_set;
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.ngpio = MRFLD_NGPIO;
priv->chip.can_sleep = false;
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index b98ede78c9d8..efc85a279d54 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -974,6 +974,18 @@ static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
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)
{
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.get = omap_gpio_get;
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;
if (bank->is_mpuio) {
bank->chip.label = "mpuio";
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
index be97101c2c9a..433b45ef332e 100644
--- a/drivers/gpio/gpio-tc3589x.c
+++ b/drivers/gpio/gpio-tc3589x.c
@@ -100,9 +100,8 @@ static int tc3589x_gpio_get_direction(struct gpio_chip *chip,
return !(ret & BIT(pos));
}
-static int tc3589x_gpio_set_single_ended(struct gpio_chip *chip,
- unsigned int offset,
- enum single_ended_mode mode)
+static int tc3589x_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
+ unsigned long config)
{
struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip);
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;
int ret;
- switch(mode) {
- case LINE_MODE_OPEN_DRAIN:
+ switch (pinconf_to_config_param(config)) {
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
/* Set open drain mode */
ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), 0);
if (ret)
return ret;
/* Enable open drain/source mode */
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 */
ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), BIT(pos));
if (ret)
return ret;
/* Enable open drain/source mode */
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 */
return tc3589x_set_bits(tc3589x, odereg, BIT(pos), 0);
default:
@@ -148,7 +147,7 @@ static const struct gpio_chip template_chip = {
.direction_output = tc3589x_gpio_direction_output,
.direction_input = tc3589x_gpio_direction_input,
.get_direction = tc3589x_gpio_get_direction,
- .set_single_ended = tc3589x_gpio_set_single_ended,
+ .set_config = tc3589x_gpio_set_config,
.can_sleep = true,
};
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 661b0e34e067..88529d3c06c9 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -238,6 +238,18 @@ static int tegra_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
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)
{
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);
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 *
sizeof(*tgi->bank_info), GFP_KERNEL);
diff --git a/drivers/gpio/gpio-tps65218.c b/drivers/gpio/gpio-tps65218.c
index 46e6dcc089cb..a379bba57d31 100644
--- a/drivers/gpio/gpio-tps65218.c
+++ b/drivers/gpio/gpio-tps65218.c
@@ -139,28 +139,28 @@ static int tps65218_gpio_request(struct gpio_chip *gc, unsigned offset)
return 0;
}
-static int tps65218_gpio_set_single_ended(struct gpio_chip *gc,
- unsigned offset,
- enum single_ended_mode mode)
+static int tps65218_gpio_set_config(struct gpio_chip *gc, unsigned offset,
+ unsigned long config)
{
struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc);
struct tps65218 *tps65218 = tps65218_gpio->tps65218;
+ enum pin_config_param param = pinconf_to_config_param(config);
switch (offset) {
case 0:
case 2:
/* GPO1 is hardwired to be open drain */
- if (mode == LINE_MODE_OPEN_DRAIN)
+ if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
return 0;
return -ENOTSUPP;
case 1:
/* 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,
TPS65218_REG_CONFIG1,
TPS65218_CONFIG1_GPO2_BUF,
TPS65218_PROTECT_L1);
- if (mode == LINE_MODE_PUSH_PULL)
+ if (param == PIN_CONFIG_DRIVE_PUSH_PULL)
return tps65218_set_bits(tps65218,
TPS65218_REG_CONFIG1,
TPS65218_CONFIG1_GPO2_BUF,
@@ -181,7 +181,7 @@ static const struct gpio_chip template_chip = {
.direction_input = tps65218_gpio_input,
.get = tps65218_gpio_get,
.set = tps65218_gpio_set,
- .set_single_ended = tps65218_gpio_set_single_ended,
+ .set_config = tps65218_gpio_set_config,
.can_sleep = true,
.ngpio = 3,
.base = -1,
diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c
index 4e450121129b..98a6f1fcc561 100644
--- a/drivers/gpio/gpio-vx855.c
+++ b/drivers/gpio/gpio-vx855.c
@@ -186,23 +186,24 @@ static int vx855gpio_direction_output(struct gpio_chip *gpio,
return 0;
}
-static int vx855gpio_set_single_ended(struct gpio_chip *gpio,
- unsigned int nr,
- enum single_ended_mode mode)
+static int vx855gpio_set_config(struct gpio_chip *gpio, unsigned int nr,
+ unsigned long config)
{
+ enum pin_config_param param = pinconf_to_config_param(config);
+
/* The GPI cannot be single-ended */
if (nr < NR_VX855_GPI)
return -EINVAL;
/* The GPO's are push-pull */
if (nr < NR_VX855_GPInO) {
- if (mode != LINE_MODE_PUSH_PULL)
+ if (param != PIN_CONFIG_DRIVE_PUSH_PULL)
return -ENOTSUPP;
return 0;
}
/* The GPIO's are open drain */
- if (mode != LINE_MODE_OPEN_DRAIN)
+ if (param != PIN_CONFIG_DRIVE_OPEN_DRAIN)
return -ENOTSUPP;
return 0;
@@ -231,7 +232,7 @@ static void vx855gpio_gpio_setup(struct vx855_gpio *vg)
c->direction_output = vx855gpio_direction_output;
c->get = vx855gpio_get;
c->set = vx855gpio_set;
- c->set_single_ended = vx855gpio_set_single_ended;
+ c->set_config = vx855gpio_set_config,
c->dbg_show = NULL;
c->base = 0;
c->ngpio = NR_VX855_GP;
diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c
index 34baee5b1dd6..97613de5304e 100644
--- a/drivers/gpio/gpio-wcove.c
+++ b/drivers/gpio/gpio-wcove.c
@@ -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);
}
-static int wcove_gpio_set_single_ended(struct gpio_chip *chip,
- unsigned int gpio,
- enum single_ended_mode mode)
+static int wcove_gpio_set_config(struct gpio_chip *chip, unsigned int gpio,
+ unsigned long config)
{
struct wcove_gpio *wg = gpiochip_get_data(chip);
- switch (mode) {
- case LINE_MODE_OPEN_DRAIN:
+ switch (pinconf_to_config_param(config)) {
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
return regmap_update_bits(wg->regmap, to_reg(gpio, CTRL_OUT),
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),
CTLO_DRV_MASK, CTLO_DRV_CMOS);
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 = wcove_gpio_get;
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.ngpio = WCOVE_VGPIO_NUM;
wg->chip.can_sleep = true;
diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c
index 533707f943f4..00e3839b3f96 100644
--- a/drivers/gpio/gpio-wm831x.c
+++ b/drivers/gpio/gpio-wm831x.c
@@ -101,11 +101,9 @@ static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned 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)
{
- struct wm831x_gpio *wm831x_gpio = gpiochip_get_data(chip);
- struct wm831x *wm831x = wm831x_gpio->wm831x;
int reg = WM831X_GPIO1_CONTROL + offset;
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);
}
-static int wm831x_set_single_ended(struct gpio_chip *chip,
- unsigned int offset,
- enum single_ended_mode mode)
+static int wm831x_set_config(struct gpio_chip *chip, unsigned int offset,
+ unsigned long config)
{
struct wm831x_gpio *wm831x_gpio = gpiochip_get_data(chip);
struct wm831x *wm831x = wm831x_gpio->wm831x;
int reg = WM831X_GPIO1_CONTROL + offset;
- switch (mode) {
- case LINE_MODE_OPEN_DRAIN:
+ switch (pinconf_to_config_param(config)) {
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
return wm831x_set_bits(wm831x, reg,
WM831X_GPN_OD_MASK, WM831X_GPN_OD);
- case LINE_MODE_PUSH_PULL:
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
return wm831x_set_bits(wm831x, reg,
WM831X_GPN_OD_MASK, 0);
+ case PIN_CONFIG_INPUT_DEBOUNCE:
+ return wm831x_gpio_set_debounce(wm831x, offset,
+ pinconf_to_config_argument(config));
default:
break;
}
@@ -255,8 +255,7 @@ static const struct gpio_chip template_chip = {
.direction_output = wm831x_gpio_direction_out,
.set = wm831x_gpio_set,
.to_irq = wm831x_gpio_to_irq,
- .set_debounce = wm831x_gpio_set_debounce,
- .set_single_ended = wm831x_set_single_ended,
+ .set_config = wm831x_set_config,
.dbg_show = wm831x_gpio_dbg_show,
.can_sleep = true,
};
diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c
index 68410fda6138..1e35756ac55b 100644
--- a/drivers/gpio/gpio-wm8994.c
+++ b/drivers/gpio/gpio-wm8994.c
@@ -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);
}
-static int wm8994_gpio_set_single_ended(struct gpio_chip *chip,
- unsigned int offset,
- enum single_ended_mode mode)
+static int wm8994_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
+ unsigned long config)
{
struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip);
struct wm8994 *wm8994 = wm8994_gpio->wm8994;
- switch (mode) {
- case LINE_MODE_OPEN_DRAIN:
+ switch (pinconf_to_config_param(config)) {
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
WM8994_GPN_OP_CFG_MASK,
WM8994_GPN_OP_CFG);
- case LINE_MODE_PUSH_PULL:
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
WM8994_GPN_OP_CFG_MASK, 0);
default:
@@ -257,7 +256,7 @@ static const struct gpio_chip template_chip = {
.get = wm8994_gpio_get,
.direction_output = wm8994_gpio_direction_out,
.set = wm8994_gpio_set,
- .set_single_ended = wm8994_gpio_set_single_ended,
+ .set_config = wm8994_gpio_set_config,
.to_irq = wm8994_gpio_to_irq,
.dbg_show = wm8994_gpio_dbg_show,
.can_sleep = true,
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index a07ae9e37930..d0478f1853db 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1876,6 +1876,19 @@ void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset)
}
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
/**
@@ -2264,6 +2277,14 @@ int gpiod_direction_input(struct gpio_desc *desc)
}
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)
{
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)) {
/* First see if we can enable open drain in hardware */
- if (gc->set_single_ended) {
- ret = gc->set_single_ended(gc, gpio_chip_hwgpio(desc),
- LINE_MODE_OPEN_DRAIN);
- if (!ret)
- goto set_output_value;
- }
+ ret = gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc),
+ PIN_CONFIG_DRIVE_OPEN_DRAIN);
+ if (!ret)
+ goto set_output_value;
/* Emulate open drain by not actively driving the line high */
if (val)
return gpiod_direction_input(desc);
}
else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) {
- if (gc->set_single_ended) {
- ret = gc->set_single_ended(gc, gpio_chip_hwgpio(desc),
- LINE_MODE_OPEN_SOURCE);
- if (!ret)
- goto set_output_value;
- }
+ ret = gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc),
+ PIN_CONFIG_DRIVE_OPEN_SOURCE);
+ if (!ret)
+ goto set_output_value;
/* Emulate open source by not actively driving the line low */
if (!val)
return gpiod_direction_input(desc);
} else {
- /* Make sure to disable open drain/source hardware, if any */
- if (gc->set_single_ended)
- gc->set_single_ended(gc,
- gpio_chip_hwgpio(desc),
- LINE_MODE_PUSH_PULL);
+ gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc),
+ PIN_CONFIG_DRIVE_PUSH_PULL);
}
set_output_value:
@@ -2376,17 +2390,19 @@ EXPORT_SYMBOL_GPL(gpiod_direction_output);
int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
{
struct gpio_chip *chip;
+ unsigned long config;
VALIDATE_DESC(desc);
chip = desc->gdev->chip;
- if (!chip->set || !chip->set_debounce) {
+ if (!chip->set || !chip->set_config) {
gpiod_dbg(desc,
- "%s: missing set() or set_debounce() operations\n",
+ "%s: missing set() or set_config() operations\n",
__func__);
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);