mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-20 12:54:36 +08:00
gpio: pca953x: add ->set_config implementation
This commit adds a minimal implementation of the ->set_config() hook, with support for the PIN_CONFIG_BIAS_PULL_UP and PIN_CONFIG_BIAS_PULL_DOWN configurations. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
d449991c4d
commit
15add06841
@ -178,6 +178,8 @@ static int pca953x_bank_shift(struct pca953x_chip *chip)
|
|||||||
#define PCA957x_BANK_OUTPUT BIT(5)
|
#define PCA957x_BANK_OUTPUT BIT(5)
|
||||||
|
|
||||||
#define PCAL9xxx_BANK_IN_LATCH BIT(8 + 2)
|
#define PCAL9xxx_BANK_IN_LATCH BIT(8 + 2)
|
||||||
|
#define PCAL9xxx_BANK_PULL_EN BIT(8 + 3)
|
||||||
|
#define PCAL9xxx_BANK_PULL_SEL BIT(8 + 4)
|
||||||
#define PCAL9xxx_BANK_IRQ_MASK BIT(8 + 5)
|
#define PCAL9xxx_BANK_IRQ_MASK BIT(8 + 5)
|
||||||
#define PCAL9xxx_BANK_IRQ_STAT BIT(8 + 6)
|
#define PCAL9xxx_BANK_IRQ_STAT BIT(8 + 6)
|
||||||
|
|
||||||
@ -199,6 +201,8 @@ static int pca953x_bank_shift(struct pca953x_chip *chip)
|
|||||||
* - Extended set, above 0x40, often chip specific.
|
* - Extended set, above 0x40, often chip specific.
|
||||||
* - PCAL6524/PCAL9555A with custom PCAL IRQ handling:
|
* - PCAL6524/PCAL9555A with custom PCAL IRQ handling:
|
||||||
* Input latch register 0x40 + 2 * bank_size RW
|
* Input latch register 0x40 + 2 * bank_size RW
|
||||||
|
* Pull-up/pull-down enable reg 0x40 + 3 * bank_size RW
|
||||||
|
* Pull-up/pull-down select reg 0x40 + 4 * bank_size RW
|
||||||
* Interrupt mask register 0x40 + 5 * bank_size RW
|
* Interrupt mask register 0x40 + 5 * bank_size RW
|
||||||
* Interrupt status register 0x40 + 6 * bank_size R
|
* Interrupt status register 0x40 + 6 * bank_size R
|
||||||
*
|
*
|
||||||
@ -247,7 +251,8 @@ static bool pca953x_readable_register(struct device *dev, unsigned int reg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (chip->driver_data & PCA_PCAL) {
|
if (chip->driver_data & PCA_PCAL) {
|
||||||
bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_IRQ_MASK |
|
bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_PULL_EN |
|
||||||
|
PCAL9xxx_BANK_PULL_SEL | PCAL9xxx_BANK_IRQ_MASK |
|
||||||
PCAL9xxx_BANK_IRQ_STAT;
|
PCAL9xxx_BANK_IRQ_STAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,7 +273,8 @@ static bool pca953x_writeable_register(struct device *dev, unsigned int reg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (chip->driver_data & PCA_PCAL)
|
if (chip->driver_data & PCA_PCAL)
|
||||||
bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_IRQ_MASK;
|
bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_PULL_EN |
|
||||||
|
PCAL9xxx_BANK_PULL_SEL | PCAL9xxx_BANK_IRQ_MASK;
|
||||||
|
|
||||||
return pca953x_check_register(chip, reg, bank);
|
return pca953x_check_register(chip, reg, bank);
|
||||||
}
|
}
|
||||||
@ -473,6 +479,61 @@ exit:
|
|||||||
mutex_unlock(&chip->i2c_lock);
|
mutex_unlock(&chip->i2c_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip,
|
||||||
|
unsigned int offset,
|
||||||
|
unsigned long config)
|
||||||
|
{
|
||||||
|
u8 pull_en_reg = pca953x_recalc_addr(chip, PCAL953X_PULL_EN, offset,
|
||||||
|
true, false);
|
||||||
|
u8 pull_sel_reg = pca953x_recalc_addr(chip, PCAL953X_PULL_SEL, offset,
|
||||||
|
true, false);
|
||||||
|
u8 bit = BIT(offset % BANK_SZ);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pull-up/pull-down configuration requires PCAL extended
|
||||||
|
* registers
|
||||||
|
*/
|
||||||
|
if (!(chip->driver_data & PCA_PCAL))
|
||||||
|
return -ENOTSUPP;
|
||||||
|
|
||||||
|
mutex_lock(&chip->i2c_lock);
|
||||||
|
|
||||||
|
/* Disable pull-up/pull-down */
|
||||||
|
ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, 0);
|
||||||
|
if (ret)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* Configure pull-up/pull-down */
|
||||||
|
if (config == PIN_CONFIG_BIAS_PULL_UP)
|
||||||
|
ret = regmap_write_bits(chip->regmap, pull_sel_reg, bit, bit);
|
||||||
|
else if (config == PIN_CONFIG_BIAS_PULL_DOWN)
|
||||||
|
ret = regmap_write_bits(chip->regmap, pull_sel_reg, bit, 0);
|
||||||
|
if (ret)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* Enable pull-up/pull-down */
|
||||||
|
ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, bit);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
mutex_unlock(&chip->i2c_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pca953x_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
|
||||||
|
unsigned long config)
|
||||||
|
{
|
||||||
|
struct pca953x_chip *chip = gpiochip_get_data(gc);
|
||||||
|
|
||||||
|
switch (config) {
|
||||||
|
case PIN_CONFIG_BIAS_PULL_UP:
|
||||||
|
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||||
|
return pca953x_gpio_set_pull_up_down(chip, offset, config);
|
||||||
|
default:
|
||||||
|
return -ENOTSUPP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
|
static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
|
||||||
{
|
{
|
||||||
struct gpio_chip *gc;
|
struct gpio_chip *gc;
|
||||||
@ -485,6 +546,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
|
|||||||
gc->set = pca953x_gpio_set_value;
|
gc->set = pca953x_gpio_set_value;
|
||||||
gc->get_direction = pca953x_gpio_get_direction;
|
gc->get_direction = pca953x_gpio_get_direction;
|
||||||
gc->set_multiple = pca953x_gpio_set_multiple;
|
gc->set_multiple = pca953x_gpio_set_multiple;
|
||||||
|
gc->set_config = pca953x_gpio_set_config;
|
||||||
gc->can_sleep = true;
|
gc->can_sleep = true;
|
||||||
|
|
||||||
gc->base = chip->gpio_start;
|
gc->base = chip->gpio_start;
|
||||||
|
Loading…
Reference in New Issue
Block a user