diff options
Diffstat (limited to 'drivers/gpio/gpio-pca953x.c')
-rw-r--r-- | drivers/gpio/gpio-pca953x.c | 81 |
1 files changed, 54 insertions, 27 deletions
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index d2ead4b1cf61..c55ad157e820 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -12,7 +12,7 @@ */ #include <linux/acpi.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h> #include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/init.h> @@ -25,29 +25,44 @@ #include <asm/unaligned.h> -#define PCA953X_INPUT 0 -#define PCA953X_OUTPUT 1 -#define PCA953X_INVERT 2 -#define PCA953X_DIRECTION 3 +#define PCA953X_INPUT 0x00 +#define PCA953X_OUTPUT 0x01 +#define PCA953X_INVERT 0x02 +#define PCA953X_DIRECTION 0x03 #define REG_ADDR_AI 0x80 -#define PCA957X_IN 0 -#define PCA957X_INVRT 1 -#define PCA957X_BKEN 2 -#define PCA957X_PUPD 3 -#define PCA957X_CFG 4 -#define PCA957X_OUT 5 -#define PCA957X_MSK 6 -#define PCA957X_INTS 7 - -#define PCAL953X_IN_LATCH 34 -#define PCAL953X_INT_MASK 37 -#define PCAL953X_INT_STAT 38 +#define PCA957X_IN 0x00 +#define PCA957X_INVRT 0x01 +#define PCA957X_BKEN 0x02 +#define PCA957X_PUPD 0x03 +#define PCA957X_CFG 0x04 +#define PCA957X_OUT 0x05 +#define PCA957X_MSK 0x06 +#define PCA957X_INTS 0x07 + +#define PCAL953X_OUT_STRENGTH 0x20 +#define PCAL953X_IN_LATCH 0x22 +#define PCAL953X_PULL_EN 0x23 +#define PCAL953X_PULL_SEL 0x24 +#define PCAL953X_INT_MASK 0x25 +#define PCAL953X_INT_STAT 0x26 +#define PCAL953X_OUT_CONF 0x27 + +#define PCAL6524_INT_EDGE 0x28 +#define PCAL6524_INT_CLR 0x2a +#define PCAL6524_IN_STATUS 0x2b +#define PCAL6524_OUT_INDCONF 0x2c +#define PCAL6524_DEBOUNCE 0x2d #define PCA_GPIO_MASK 0x00FF + +#define PCAL_GPIO_MASK 0x1f +#define PCAL_PINCTRL_MASK 0xe0 + #define PCA_INT 0x0100 #define PCA_PCAL 0x0200 +#define PCA_LATCH_INT (PCA_PCAL | PCA_INT) #define PCA953X_TYPE 0x1000 #define PCA957X_TYPE 0x2000 #define PCA_TYPE_MASK 0xF000 @@ -207,9 +222,11 @@ static int pca957x_write_regs_16(struct pca953x_chip *chip, int reg, u8 *val) static int pca953x_write_regs_24(struct pca953x_chip *chip, int reg, u8 *val) { int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); + int addr = (reg & PCAL_GPIO_MASK) << bank_shift; + int pinctrl = (reg & PCAL_PINCTRL_MASK) << 1; return i2c_smbus_write_i2c_block_data(chip->client, - (reg << bank_shift) | REG_ADDR_AI, + pinctrl | addr | REG_ADDR_AI, NBANK(chip), val); } @@ -249,9 +266,11 @@ static int pca953x_read_regs_16(struct pca953x_chip *chip, int reg, u8 *val) static int pca953x_read_regs_24(struct pca953x_chip *chip, int reg, u8 *val) { int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); + int addr = (reg & PCAL_GPIO_MASK) << bank_shift; + int pinctrl = (reg & PCAL_PINCTRL_MASK) << 1; return i2c_smbus_read_i2c_block_data(chip->client, - (reg << bank_shift) | REG_ADDR_AI, + pinctrl | addr | REG_ADDR_AI, NBANK(chip), val); } @@ -522,6 +541,15 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) return 0; } +static void pca953x_irq_shutdown(struct irq_data *d) +{ + struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); + u8 mask = 1 << (d->hwirq % BANK_SZ); + + chip->irq_trig_raise[d->hwirq / BANK_SZ] &= ~mask; + chip->irq_trig_fall[d->hwirq / BANK_SZ] &= ~mask; +} + static struct irq_chip pca953x_irq_chip = { .name = "pca953x", .irq_mask = pca953x_irq_mask, @@ -529,6 +557,7 @@ static struct irq_chip pca953x_irq_chip = { .irq_bus_lock = pca953x_irq_bus_lock, .irq_bus_sync_unlock = pca953x_irq_bus_sync_unlock, .irq_set_type = pca953x_irq_set_type, + .irq_shutdown = pca953x_irq_shutdown, }; static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) @@ -810,13 +839,11 @@ static int pca953x_probe(struct i2c_client *client, chip->driver_data = i2c_id->driver_data; } else { const struct acpi_device_id *acpi_id; - const struct of_device_id *match; + struct device *dev = &client->dev; - match = of_match_device(pca953x_dt_ids, &client->dev); - if (match) { - chip->driver_data = (int)(uintptr_t)match->data; - } else { - acpi_id = acpi_match_device(pca953x_acpi_ids, &client->dev); + chip->driver_data = (uintptr_t)of_device_get_match_data(dev); + if (!chip->driver_data) { + acpi_id = acpi_match_device(pca953x_acpi_ids, dev); if (!acpi_id) { ret = -ENODEV; goto err_exit; @@ -936,8 +963,8 @@ static const struct of_device_id pca953x_dt_ids[] = { { .compatible = "nxp,pca9575", .data = OF_957X(16, PCA_INT), }, { .compatible = "nxp,pca9698", .data = OF_953X(40, 0), }, - { .compatible = "nxp,pcal6524", .data = OF_953X(24, PCA_INT), }, - { .compatible = "nxp,pcal9555a", .data = OF_953X(16, PCA_INT), }, + { .compatible = "nxp,pcal6524", .data = OF_953X(24, PCA_LATCH_INT), }, + { .compatible = "nxp,pcal9555a", .data = OF_953X(16, PCA_LATCH_INT), }, { .compatible = "maxim,max7310", .data = OF_953X( 8, 0), }, { .compatible = "maxim,max7312", .data = OF_953X(16, PCA_INT), }, |