Loading drivers/gpio/gpio-pca953x.c +302 −182 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <linux/module.h> #include <linux/of_platform.h> #include <linux/platform_data/pca953x.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> Loading @@ -30,6 +31,8 @@ #define PCA953X_INVERT 0x02 #define PCA953X_DIRECTION 0x03 #define REG_ADDR_MASK 0x3f #define REG_ADDR_EXT 0x40 #define REG_ADDR_AI 0x80 #define PCA957X_IN 0x00 Loading Loading @@ -58,7 +61,7 @@ #define PCA_GPIO_MASK 0x00FF #define PCAL_GPIO_MASK 0x1f #define PCAL_PINCTRL_MASK 0xe0 #define PCAL_PINCTRL_MASK 0x60 #define PCA_INT 0x0100 #define PCA_PCAL 0x0200 Loading Loading @@ -119,25 +122,27 @@ struct pca953x_reg_config { int direction; int output; int input; int invert; }; static const struct pca953x_reg_config pca953x_regs = { .direction = PCA953X_DIRECTION, .output = PCA953X_OUTPUT, .input = PCA953X_INPUT, .invert = PCA953X_INVERT, }; static const struct pca953x_reg_config pca957x_regs = { .direction = PCA957X_CFG, .output = PCA957X_OUT, .input = PCA957X_IN, .invert = PCA957X_INVRT, }; struct pca953x_chip { unsigned gpio_start; u8 reg_output[MAX_BANK]; u8 reg_direction[MAX_BANK]; struct mutex i2c_lock; struct regmap *regmap; #ifdef CONFIG_GPIO_PCA953X_IRQ struct mutex irq_lock; Loading @@ -154,131 +159,191 @@ struct pca953x_chip { struct regulator *regulator; const struct pca953x_reg_config *regs; int (*write_regs)(struct pca953x_chip *, int, u8 *); int (*read_regs)(struct pca953x_chip *, int, u8 *); }; static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val, int off) static int pca953x_bank_shift(struct pca953x_chip *chip) { int ret; int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); int offset = off / BANK_SZ; return fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); } ret = i2c_smbus_read_byte_data(chip->client, (reg << bank_shift) + offset); *val = ret; #define PCA953x_BANK_INPUT BIT(0) #define PCA953x_BANK_OUTPUT BIT(1) #define PCA953x_BANK_POLARITY BIT(2) #define PCA953x_BANK_CONFIG BIT(3) if (ret < 0) { dev_err(&chip->client->dev, "failed reading register\n"); return ret; } #define PCA957x_BANK_INPUT BIT(0) #define PCA957x_BANK_POLARITY BIT(1) #define PCA957x_BANK_BUSHOLD BIT(2) #define PCA957x_BANK_CONFIG BIT(4) #define PCA957x_BANK_OUTPUT BIT(5) return 0; } #define PCAL9xxx_BANK_IN_LATCH BIT(8 + 2) #define PCAL9xxx_BANK_IRQ_MASK BIT(8 + 5) #define PCAL9xxx_BANK_IRQ_STAT BIT(8 + 6) static int pca953x_write_single(struct pca953x_chip *chip, int reg, u32 val, int off) { int ret; int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); int offset = off / BANK_SZ; /* * We care about the following registers: * - Standard set, below 0x40, each port can be replicated up to 8 times * - PCA953x standard * Input port 0x00 + 0 * bank_size R * Output port 0x00 + 1 * bank_size RW * Polarity Inversion port 0x00 + 2 * bank_size RW * Configuration port 0x00 + 3 * bank_size RW * - PCA957x with mixed up registers * Input port 0x00 + 0 * bank_size R * Polarity Inversion port 0x00 + 1 * bank_size RW * Bus hold port 0x00 + 2 * bank_size RW * Configuration port 0x00 + 4 * bank_size RW * Output port 0x00 + 5 * bank_size RW * * - Extended set, above 0x40, often chip specific. * - PCAL6524/PCAL9555A with custom PCAL IRQ handling: * Input latch register 0x40 + 2 * bank_size RW * Interrupt mask register 0x40 + 5 * bank_size RW * Interrupt status register 0x40 + 6 * bank_size R * * - Registers with bit 0x80 set, the AI bit * The bit is cleared and the registers fall into one of the * categories above. */ ret = i2c_smbus_write_byte_data(chip->client, (reg << bank_shift) + offset, val); static bool pca953x_check_register(struct pca953x_chip *chip, unsigned int reg, u32 checkbank) { int bank_shift = pca953x_bank_shift(chip); int bank = (reg & REG_ADDR_MASK) >> bank_shift; int offset = reg & (BIT(bank_shift) - 1); if (ret < 0) { dev_err(&chip->client->dev, "failed writing register\n"); return ret; /* Special PCAL extended register check. */ if (reg & REG_ADDR_EXT) { if (!(chip->driver_data & PCA_PCAL)) return false; bank += 8; } return 0; /* Register is not in the matching bank. */ if (!(BIT(bank) & checkbank)) return false; /* Register is not within allowed range of bank. */ if (offset >= NBANK(chip)) return false; return true; } static int pca953x_write_regs_8(struct pca953x_chip *chip, int reg, u8 *val) static bool pca953x_readable_register(struct device *dev, unsigned int reg) { return i2c_smbus_write_byte_data(chip->client, reg, *val); struct pca953x_chip *chip = dev_get_drvdata(dev); u32 bank; if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) { bank = PCA953x_BANK_INPUT | PCA953x_BANK_OUTPUT | PCA953x_BANK_POLARITY | PCA953x_BANK_CONFIG; } else { bank = PCA957x_BANK_INPUT | PCA957x_BANK_OUTPUT | PCA957x_BANK_POLARITY | PCA957x_BANK_CONFIG | PCA957x_BANK_BUSHOLD; } static int pca953x_write_regs_16(struct pca953x_chip *chip, int reg, u8 *val) { u16 word = get_unaligned((u16 *)val); if (chip->driver_data & PCA_PCAL) { bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_IRQ_MASK | PCAL9xxx_BANK_IRQ_STAT; } return i2c_smbus_write_word_data(chip->client, reg << 1, word); return pca953x_check_register(chip, reg, bank); } static int pca957x_write_regs_16(struct pca953x_chip *chip, int reg, u8 *val) static bool pca953x_writeable_register(struct device *dev, unsigned int reg) { int ret; ret = i2c_smbus_write_byte_data(chip->client, reg << 1, val[0]); if (ret < 0) return ret; struct pca953x_chip *chip = dev_get_drvdata(dev); u32 bank; return i2c_smbus_write_byte_data(chip->client, (reg << 1) + 1, val[1]); if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) { bank = PCA953x_BANK_OUTPUT | PCA953x_BANK_POLARITY | PCA953x_BANK_CONFIG; } else { bank = PCA957x_BANK_OUTPUT | PCA957x_BANK_POLARITY | PCA957x_BANK_CONFIG | PCA957x_BANK_BUSHOLD; } 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; if (chip->driver_data & PCA_PCAL) bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_IRQ_MASK; return i2c_smbus_write_i2c_block_data(chip->client, pinctrl | addr | REG_ADDR_AI, NBANK(chip), val); return pca953x_check_register(chip, reg, bank); } static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val) static bool pca953x_volatile_register(struct device *dev, unsigned int reg) { int ret = 0; struct pca953x_chip *chip = dev_get_drvdata(dev); u32 bank; ret = chip->write_regs(chip, reg, val); if (ret < 0) { dev_err(&chip->client->dev, "failed writing register\n"); return ret; } if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) bank = PCA953x_BANK_INPUT; else bank = PCA957x_BANK_INPUT; return 0; if (chip->driver_data & PCA_PCAL) bank |= PCAL9xxx_BANK_IRQ_STAT; return pca953x_check_register(chip, reg, bank); } static int pca953x_read_regs_8(struct pca953x_chip *chip, int reg, u8 *val) const struct regmap_config pca953x_i2c_regmap = { .reg_bits = 8, .val_bits = 8, .readable_reg = pca953x_readable_register, .writeable_reg = pca953x_writeable_register, .volatile_reg = pca953x_volatile_register, .cache_type = REGCACHE_RBTREE, .max_register = 0x7f, }; static u8 pca953x_recalc_addr(struct pca953x_chip *chip, int reg, int off, bool write, bool addrinc) { int ret; int bank_shift = pca953x_bank_shift(chip); int addr = (reg & PCAL_GPIO_MASK) << bank_shift; int pinctrl = (reg & PCAL_PINCTRL_MASK) << 1; u8 regaddr = pinctrl | addr | (off / BANK_SZ); ret = i2c_smbus_read_byte_data(chip->client, reg); *val = ret; /* Single byte read doesn't need AI bit set. */ if (!addrinc) return regaddr; return ret; /* Chips with 24 and more GPIOs always support Auto Increment */ if (write && NBANK(chip) > 2) regaddr |= REG_ADDR_AI; /* PCA9575 needs address-increment on multi-byte writes */ if (PCA_CHIP_TYPE(chip->driver_data) == PCA957X_TYPE) regaddr |= REG_ADDR_AI; return regaddr; } static int pca953x_read_regs_16(struct pca953x_chip *chip, int reg, u8 *val) static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val) { u8 regaddr = pca953x_recalc_addr(chip, reg, 0, true, true); int ret; ret = i2c_smbus_read_word_data(chip->client, reg << 1); put_unaligned(ret, (u16 *)val); ret = regmap_bulk_write(chip->regmap, regaddr, val, NBANK(chip)); if (ret < 0) { dev_err(&chip->client->dev, "failed writing register\n"); return ret; } 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, pinctrl | addr | REG_ADDR_AI, NBANK(chip), val); return 0; } static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val) { u8 regaddr = pca953x_recalc_addr(chip, reg, 0, false, true); int ret; ret = chip->read_regs(chip, reg, val); ret = regmap_bulk_read(chip->regmap, regaddr, val, NBANK(chip)); if (ret < 0) { dev_err(&chip->client->dev, "failed reading register\n"); return ret; Loading @@ -290,18 +355,13 @@ static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val) static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) { struct pca953x_chip *chip = gpiochip_get_data(gc); u8 reg_val; u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off, true, false); u8 bit = BIT(off % BANK_SZ); int ret; mutex_lock(&chip->i2c_lock); reg_val = chip->reg_direction[off / BANK_SZ] | (1u << (off % BANK_SZ)); ret = pca953x_write_single(chip, chip->regs->direction, reg_val, off); if (ret) goto exit; chip->reg_direction[off / BANK_SZ] = reg_val; exit: ret = regmap_write_bits(chip->regmap, dirreg, bit, bit); mutex_unlock(&chip->i2c_lock); return ret; } Loading @@ -310,31 +370,21 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, unsigned off, int val) { struct pca953x_chip *chip = gpiochip_get_data(gc); u8 reg_val; u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off, true, false); u8 outreg = pca953x_recalc_addr(chip, chip->regs->output, off, true, false); u8 bit = BIT(off % BANK_SZ); int ret; mutex_lock(&chip->i2c_lock); /* set output level */ if (val) reg_val = chip->reg_output[off / BANK_SZ] | (1u << (off % BANK_SZ)); else reg_val = chip->reg_output[off / BANK_SZ] & ~(1u << (off % BANK_SZ)); ret = pca953x_write_single(chip, chip->regs->output, reg_val, off); ret = regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0); if (ret) goto exit; chip->reg_output[off / BANK_SZ] = reg_val; /* then direction */ reg_val = chip->reg_direction[off / BANK_SZ] & ~(1u << (off % BANK_SZ)); ret = pca953x_write_single(chip, chip->regs->direction, reg_val, off); if (ret) goto exit; chip->reg_direction[off / BANK_SZ] = reg_val; ret = regmap_write_bits(chip->regmap, dirreg, bit, 0); exit: mutex_unlock(&chip->i2c_lock); return ret; Loading @@ -343,11 +393,14 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) { struct pca953x_chip *chip = gpiochip_get_data(gc); u8 inreg = pca953x_recalc_addr(chip, chip->regs->input, off, true, false); u8 bit = BIT(off % BANK_SZ); u32 reg_val; int ret; mutex_lock(&chip->i2c_lock); ret = pca953x_read_single(chip, chip->regs->input, ®_val, off); ret = regmap_read(chip->regmap, inreg, ®_val); mutex_unlock(&chip->i2c_lock); if (ret < 0) { /* NOTE: diagnostic already emitted; that's all we should Loading @@ -357,45 +410,37 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) return 0; } return (reg_val & (1u << (off % BANK_SZ))) ? 1 : 0; return !!(reg_val & bit); } static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) { struct pca953x_chip *chip = gpiochip_get_data(gc); u8 reg_val; int ret; u8 outreg = pca953x_recalc_addr(chip, chip->regs->output, off, true, false); u8 bit = BIT(off % BANK_SZ); mutex_lock(&chip->i2c_lock); if (val) reg_val = chip->reg_output[off / BANK_SZ] | (1u << (off % BANK_SZ)); else reg_val = chip->reg_output[off / BANK_SZ] & ~(1u << (off % BANK_SZ)); ret = pca953x_write_single(chip, chip->regs->output, reg_val, off); if (ret) goto exit; chip->reg_output[off / BANK_SZ] = reg_val; exit: regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0); mutex_unlock(&chip->i2c_lock); } static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off) { struct pca953x_chip *chip = gpiochip_get_data(gc); u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off, true, false); u8 bit = BIT(off % BANK_SZ); u32 reg_val; int ret; mutex_lock(&chip->i2c_lock); ret = pca953x_read_single(chip, chip->regs->direction, ®_val, off); ret = regmap_read(chip->regmap, dirreg, ®_val); mutex_unlock(&chip->i2c_lock); if (ret < 0) return ret; return !!(reg_val & (1u << (off % BANK_SZ))); return !!(reg_val & bit); } static void pca953x_gpio_set_multiple(struct gpio_chip *gc, Loading @@ -403,14 +448,15 @@ static void pca953x_gpio_set_multiple(struct gpio_chip *gc, { struct pca953x_chip *chip = gpiochip_get_data(gc); unsigned int bank_mask, bank_val; int bank_shift, bank; int bank; u8 reg_val[MAX_BANK]; int ret; bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); mutex_lock(&chip->i2c_lock); memcpy(reg_val, chip->reg_output, NBANK(chip)); ret = pca953x_read_regs(chip, chip->regs->output, reg_val); if (ret) goto exit; for (bank = 0; bank < NBANK(chip); bank++) { bank_mask = mask[bank / sizeof(*mask)] >> ((bank % sizeof(*mask)) * 8); Loading @@ -422,13 +468,7 @@ static void pca953x_gpio_set_multiple(struct gpio_chip *gc, } } ret = i2c_smbus_write_i2c_block_data(chip->client, chip->regs->output << bank_shift, NBANK(chip), reg_val); if (ret) goto exit; memcpy(chip->reg_output, reg_val, NBANK(chip)); pca953x_write_regs(chip, chip->regs->output, reg_val); exit: mutex_unlock(&chip->i2c_lock); } Loading Loading @@ -487,6 +527,10 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) u8 new_irqs; int level, i; u8 invert_irq_mask[MAX_BANK]; int reg_direction[MAX_BANK]; regmap_bulk_read(chip->regmap, chip->regs->direction, reg_direction, NBANK(chip)); if (chip->driver_data & PCA_PCAL) { /* Enable latch on interrupt-enabled inputs */ Loading @@ -502,7 +546,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) /* Look for any newly setup interrupt */ for (i = 0; i < NBANK(chip); i++) { new_irqs = chip->irq_trig_fall[i] | chip->irq_trig_raise[i]; new_irqs &= ~chip->reg_direction[i]; new_irqs &= reg_direction[i]; while (new_irqs) { level = __ffs(new_irqs); Loading Loading @@ -567,6 +611,7 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) bool pending_seen = false; bool trigger_seen = false; u8 trigger[MAX_BANK]; int reg_direction[MAX_BANK]; int ret, i; if (chip->driver_data & PCA_PCAL) { Loading Loading @@ -597,8 +642,10 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) return false; /* Remove output pins from the equation */ regmap_bulk_read(chip->regmap, chip->regs->direction, reg_direction, NBANK(chip)); for (i = 0; i < NBANK(chip); i++) cur_stat[i] &= chip->reg_direction[i]; cur_stat[i] &= reg_direction[i]; memcpy(old_stat, chip->irq_stat, NBANK(chip)); Loading Loading @@ -652,6 +699,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base) { struct i2c_client *client = chip->client; int reg_direction[MAX_BANK]; int ret, i; if (client->irq && irq_base != -1 Loading @@ -666,8 +714,10 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, * interrupt. We have to rely on the previous read for * this purpose. */ regmap_bulk_read(chip->regmap, chip->regs->direction, reg_direction, NBANK(chip)); for (i = 0; i < NBANK(chip); i++) chip->irq_stat[i] &= chip->reg_direction[i]; chip->irq_stat[i] &= reg_direction[i]; mutex_init(&chip->irq_lock); ret = devm_request_threaded_irq(&client->dev, Loading Loading @@ -715,20 +765,19 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, } #endif static int device_pca953x_init(struct pca953x_chip *chip, u32 invert) static int device_pca95xx_init(struct pca953x_chip *chip, u32 invert) { int ret; u8 val[MAX_BANK]; chip->regs = &pca953x_regs; ret = pca953x_read_regs(chip, chip->regs->output, chip->reg_output); if (ret) ret = regcache_sync_region(chip->regmap, chip->regs->output, chip->regs->output + NBANK(chip)); if (ret != 0) goto out; ret = pca953x_read_regs(chip, chip->regs->direction, chip->reg_direction); if (ret) ret = regcache_sync_region(chip->regmap, chip->regs->direction, chip->regs->direction + NBANK(chip)); if (ret != 0) goto out; /* set platform specific polarity inversion */ Loading @@ -737,7 +786,7 @@ static int device_pca953x_init(struct pca953x_chip *chip, u32 invert) else memset(val, 0, NBANK(chip)); ret = pca953x_write_regs(chip, PCA953X_INVERT, val); ret = pca953x_write_regs(chip, chip->regs->invert, val); out: return ret; } Loading @@ -747,22 +796,7 @@ static int device_pca957x_init(struct pca953x_chip *chip, u32 invert) int ret; u8 val[MAX_BANK]; chip->regs = &pca957x_regs; ret = pca953x_read_regs(chip, chip->regs->output, chip->reg_output); if (ret) goto out; ret = pca953x_read_regs(chip, chip->regs->direction, chip->reg_direction); if (ret) goto out; /* set platform specific polarity inversion */ if (invert) memset(val, 0xFF, NBANK(chip)); else memset(val, 0, NBANK(chip)); ret = pca953x_write_regs(chip, PCA957X_INVRT, val); ret = device_pca95xx_init(chip, invert); if (ret) goto out; Loading Loading @@ -853,6 +887,16 @@ static int pca953x_probe(struct i2c_client *client, } } i2c_set_clientdata(client, chip); chip->regmap = devm_regmap_init_i2c(client, &pca953x_i2c_regmap); if (IS_ERR(chip->regmap)) { ret = PTR_ERR(chip->regmap); goto err_exit; } regcache_mark_dirty(chip->regmap); mutex_init(&chip->i2c_lock); /* * In case we have an i2c-mux controlled by a GPIO provided by an Loading @@ -878,24 +922,13 @@ static int pca953x_probe(struct i2c_client *client, */ pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK); if (chip->gpio_chip.ngpio <= 8) { chip->write_regs = pca953x_write_regs_8; chip->read_regs = pca953x_read_regs_8; } else if (chip->gpio_chip.ngpio >= 24) { chip->write_regs = pca953x_write_regs_24; chip->read_regs = pca953x_read_regs_24; if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) { chip->regs = &pca953x_regs; ret = device_pca95xx_init(chip, invert); } else { if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) chip->write_regs = pca953x_write_regs_16; else chip->write_regs = pca957x_write_regs_16; chip->read_regs = pca953x_read_regs_16; } if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) ret = device_pca953x_init(chip, invert); else chip->regs = &pca957x_regs; ret = device_pca957x_init(chip, invert); } if (ret) goto err_exit; Loading @@ -914,7 +947,6 @@ static int pca953x_probe(struct i2c_client *client, dev_warn(&client->dev, "setup failed, %d\n", ret); } i2c_set_clientdata(client, chip); return 0; err_exit: Loading Loading @@ -943,6 +975,91 @@ static int pca953x_remove(struct i2c_client *client) return ret; } #ifdef CONFIG_PM_SLEEP static int pca953x_regcache_sync(struct device *dev) { struct pca953x_chip *chip = dev_get_drvdata(dev); int ret; /* * The ordering between direction and output is important, * sync these registers first and only then sync the rest. */ ret = regcache_sync_region(chip->regmap, chip->regs->direction, chip->regs->direction + NBANK(chip)); if (ret != 0) { dev_err(dev, "Failed to sync GPIO dir registers: %d\n", ret); return ret; } ret = regcache_sync_region(chip->regmap, chip->regs->output, chip->regs->output + NBANK(chip)); if (ret != 0) { dev_err(dev, "Failed to sync GPIO out registers: %d\n", ret); return ret; } #ifdef CONFIG_GPIO_PCA953X_IRQ if (chip->driver_data & PCA_PCAL) { ret = regcache_sync_region(chip->regmap, PCAL953X_IN_LATCH, PCAL953X_IN_LATCH + NBANK(chip)); if (ret != 0) { dev_err(dev, "Failed to sync INT latch registers: %d\n", ret); return ret; } ret = regcache_sync_region(chip->regmap, PCAL953X_INT_MASK, PCAL953X_INT_MASK + NBANK(chip)); if (ret != 0) { dev_err(dev, "Failed to sync INT mask registers: %d\n", ret); return ret; } } #endif return 0; } static int pca953x_suspend(struct device *dev) { struct pca953x_chip *chip = dev_get_drvdata(dev); regcache_cache_only(chip->regmap, true); regulator_disable(chip->regulator); return 0; } static int pca953x_resume(struct device *dev) { struct pca953x_chip *chip = dev_get_drvdata(dev); int ret; ret = regulator_enable(chip->regulator); if (ret != 0) { dev_err(dev, "Failed to enable regulator: %d\n", ret); return 0; } regcache_cache_only(chip->regmap, false); regcache_mark_dirty(chip->regmap); ret = pca953x_regcache_sync(dev); if (ret) return ret; ret = regcache_sync(chip->regmap); if (ret != 0) { dev_err(dev, "Failed to restore register map: %d\n", ret); return ret; } return 0; } #endif /* convenience to stop overlong match-table lines */ #define OF_953X(__nrgpio, __int) (void *)(__nrgpio | PCA953X_TYPE | __int) #define OF_957X(__nrgpio, __int) (void *)(__nrgpio | PCA957X_TYPE | __int) Loading Loading @@ -986,9 +1103,12 @@ static const struct of_device_id pca953x_dt_ids[] = { MODULE_DEVICE_TABLE(of, pca953x_dt_ids); static SIMPLE_DEV_PM_OPS(pca953x_pm_ops, pca953x_suspend, pca953x_resume); static struct i2c_driver pca953x_driver = { .driver = { .name = "pca953x", .pm = &pca953x_pm_ops, .of_match_table = pca953x_dt_ids, .acpi_match_table = ACPI_PTR(pca953x_acpi_ids), }, Loading Loading
drivers/gpio/gpio-pca953x.c +302 −182 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <linux/module.h> #include <linux/of_platform.h> #include <linux/platform_data/pca953x.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> Loading @@ -30,6 +31,8 @@ #define PCA953X_INVERT 0x02 #define PCA953X_DIRECTION 0x03 #define REG_ADDR_MASK 0x3f #define REG_ADDR_EXT 0x40 #define REG_ADDR_AI 0x80 #define PCA957X_IN 0x00 Loading Loading @@ -58,7 +61,7 @@ #define PCA_GPIO_MASK 0x00FF #define PCAL_GPIO_MASK 0x1f #define PCAL_PINCTRL_MASK 0xe0 #define PCAL_PINCTRL_MASK 0x60 #define PCA_INT 0x0100 #define PCA_PCAL 0x0200 Loading Loading @@ -119,25 +122,27 @@ struct pca953x_reg_config { int direction; int output; int input; int invert; }; static const struct pca953x_reg_config pca953x_regs = { .direction = PCA953X_DIRECTION, .output = PCA953X_OUTPUT, .input = PCA953X_INPUT, .invert = PCA953X_INVERT, }; static const struct pca953x_reg_config pca957x_regs = { .direction = PCA957X_CFG, .output = PCA957X_OUT, .input = PCA957X_IN, .invert = PCA957X_INVRT, }; struct pca953x_chip { unsigned gpio_start; u8 reg_output[MAX_BANK]; u8 reg_direction[MAX_BANK]; struct mutex i2c_lock; struct regmap *regmap; #ifdef CONFIG_GPIO_PCA953X_IRQ struct mutex irq_lock; Loading @@ -154,131 +159,191 @@ struct pca953x_chip { struct regulator *regulator; const struct pca953x_reg_config *regs; int (*write_regs)(struct pca953x_chip *, int, u8 *); int (*read_regs)(struct pca953x_chip *, int, u8 *); }; static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val, int off) static int pca953x_bank_shift(struct pca953x_chip *chip) { int ret; int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); int offset = off / BANK_SZ; return fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); } ret = i2c_smbus_read_byte_data(chip->client, (reg << bank_shift) + offset); *val = ret; #define PCA953x_BANK_INPUT BIT(0) #define PCA953x_BANK_OUTPUT BIT(1) #define PCA953x_BANK_POLARITY BIT(2) #define PCA953x_BANK_CONFIG BIT(3) if (ret < 0) { dev_err(&chip->client->dev, "failed reading register\n"); return ret; } #define PCA957x_BANK_INPUT BIT(0) #define PCA957x_BANK_POLARITY BIT(1) #define PCA957x_BANK_BUSHOLD BIT(2) #define PCA957x_BANK_CONFIG BIT(4) #define PCA957x_BANK_OUTPUT BIT(5) return 0; } #define PCAL9xxx_BANK_IN_LATCH BIT(8 + 2) #define PCAL9xxx_BANK_IRQ_MASK BIT(8 + 5) #define PCAL9xxx_BANK_IRQ_STAT BIT(8 + 6) static int pca953x_write_single(struct pca953x_chip *chip, int reg, u32 val, int off) { int ret; int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); int offset = off / BANK_SZ; /* * We care about the following registers: * - Standard set, below 0x40, each port can be replicated up to 8 times * - PCA953x standard * Input port 0x00 + 0 * bank_size R * Output port 0x00 + 1 * bank_size RW * Polarity Inversion port 0x00 + 2 * bank_size RW * Configuration port 0x00 + 3 * bank_size RW * - PCA957x with mixed up registers * Input port 0x00 + 0 * bank_size R * Polarity Inversion port 0x00 + 1 * bank_size RW * Bus hold port 0x00 + 2 * bank_size RW * Configuration port 0x00 + 4 * bank_size RW * Output port 0x00 + 5 * bank_size RW * * - Extended set, above 0x40, often chip specific. * - PCAL6524/PCAL9555A with custom PCAL IRQ handling: * Input latch register 0x40 + 2 * bank_size RW * Interrupt mask register 0x40 + 5 * bank_size RW * Interrupt status register 0x40 + 6 * bank_size R * * - Registers with bit 0x80 set, the AI bit * The bit is cleared and the registers fall into one of the * categories above. */ ret = i2c_smbus_write_byte_data(chip->client, (reg << bank_shift) + offset, val); static bool pca953x_check_register(struct pca953x_chip *chip, unsigned int reg, u32 checkbank) { int bank_shift = pca953x_bank_shift(chip); int bank = (reg & REG_ADDR_MASK) >> bank_shift; int offset = reg & (BIT(bank_shift) - 1); if (ret < 0) { dev_err(&chip->client->dev, "failed writing register\n"); return ret; /* Special PCAL extended register check. */ if (reg & REG_ADDR_EXT) { if (!(chip->driver_data & PCA_PCAL)) return false; bank += 8; } return 0; /* Register is not in the matching bank. */ if (!(BIT(bank) & checkbank)) return false; /* Register is not within allowed range of bank. */ if (offset >= NBANK(chip)) return false; return true; } static int pca953x_write_regs_8(struct pca953x_chip *chip, int reg, u8 *val) static bool pca953x_readable_register(struct device *dev, unsigned int reg) { return i2c_smbus_write_byte_data(chip->client, reg, *val); struct pca953x_chip *chip = dev_get_drvdata(dev); u32 bank; if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) { bank = PCA953x_BANK_INPUT | PCA953x_BANK_OUTPUT | PCA953x_BANK_POLARITY | PCA953x_BANK_CONFIG; } else { bank = PCA957x_BANK_INPUT | PCA957x_BANK_OUTPUT | PCA957x_BANK_POLARITY | PCA957x_BANK_CONFIG | PCA957x_BANK_BUSHOLD; } static int pca953x_write_regs_16(struct pca953x_chip *chip, int reg, u8 *val) { u16 word = get_unaligned((u16 *)val); if (chip->driver_data & PCA_PCAL) { bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_IRQ_MASK | PCAL9xxx_BANK_IRQ_STAT; } return i2c_smbus_write_word_data(chip->client, reg << 1, word); return pca953x_check_register(chip, reg, bank); } static int pca957x_write_regs_16(struct pca953x_chip *chip, int reg, u8 *val) static bool pca953x_writeable_register(struct device *dev, unsigned int reg) { int ret; ret = i2c_smbus_write_byte_data(chip->client, reg << 1, val[0]); if (ret < 0) return ret; struct pca953x_chip *chip = dev_get_drvdata(dev); u32 bank; return i2c_smbus_write_byte_data(chip->client, (reg << 1) + 1, val[1]); if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) { bank = PCA953x_BANK_OUTPUT | PCA953x_BANK_POLARITY | PCA953x_BANK_CONFIG; } else { bank = PCA957x_BANK_OUTPUT | PCA957x_BANK_POLARITY | PCA957x_BANK_CONFIG | PCA957x_BANK_BUSHOLD; } 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; if (chip->driver_data & PCA_PCAL) bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_IRQ_MASK; return i2c_smbus_write_i2c_block_data(chip->client, pinctrl | addr | REG_ADDR_AI, NBANK(chip), val); return pca953x_check_register(chip, reg, bank); } static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val) static bool pca953x_volatile_register(struct device *dev, unsigned int reg) { int ret = 0; struct pca953x_chip *chip = dev_get_drvdata(dev); u32 bank; ret = chip->write_regs(chip, reg, val); if (ret < 0) { dev_err(&chip->client->dev, "failed writing register\n"); return ret; } if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) bank = PCA953x_BANK_INPUT; else bank = PCA957x_BANK_INPUT; return 0; if (chip->driver_data & PCA_PCAL) bank |= PCAL9xxx_BANK_IRQ_STAT; return pca953x_check_register(chip, reg, bank); } static int pca953x_read_regs_8(struct pca953x_chip *chip, int reg, u8 *val) const struct regmap_config pca953x_i2c_regmap = { .reg_bits = 8, .val_bits = 8, .readable_reg = pca953x_readable_register, .writeable_reg = pca953x_writeable_register, .volatile_reg = pca953x_volatile_register, .cache_type = REGCACHE_RBTREE, .max_register = 0x7f, }; static u8 pca953x_recalc_addr(struct pca953x_chip *chip, int reg, int off, bool write, bool addrinc) { int ret; int bank_shift = pca953x_bank_shift(chip); int addr = (reg & PCAL_GPIO_MASK) << bank_shift; int pinctrl = (reg & PCAL_PINCTRL_MASK) << 1; u8 regaddr = pinctrl | addr | (off / BANK_SZ); ret = i2c_smbus_read_byte_data(chip->client, reg); *val = ret; /* Single byte read doesn't need AI bit set. */ if (!addrinc) return regaddr; return ret; /* Chips with 24 and more GPIOs always support Auto Increment */ if (write && NBANK(chip) > 2) regaddr |= REG_ADDR_AI; /* PCA9575 needs address-increment on multi-byte writes */ if (PCA_CHIP_TYPE(chip->driver_data) == PCA957X_TYPE) regaddr |= REG_ADDR_AI; return regaddr; } static int pca953x_read_regs_16(struct pca953x_chip *chip, int reg, u8 *val) static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val) { u8 regaddr = pca953x_recalc_addr(chip, reg, 0, true, true); int ret; ret = i2c_smbus_read_word_data(chip->client, reg << 1); put_unaligned(ret, (u16 *)val); ret = regmap_bulk_write(chip->regmap, regaddr, val, NBANK(chip)); if (ret < 0) { dev_err(&chip->client->dev, "failed writing register\n"); return ret; } 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, pinctrl | addr | REG_ADDR_AI, NBANK(chip), val); return 0; } static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val) { u8 regaddr = pca953x_recalc_addr(chip, reg, 0, false, true); int ret; ret = chip->read_regs(chip, reg, val); ret = regmap_bulk_read(chip->regmap, regaddr, val, NBANK(chip)); if (ret < 0) { dev_err(&chip->client->dev, "failed reading register\n"); return ret; Loading @@ -290,18 +355,13 @@ static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val) static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) { struct pca953x_chip *chip = gpiochip_get_data(gc); u8 reg_val; u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off, true, false); u8 bit = BIT(off % BANK_SZ); int ret; mutex_lock(&chip->i2c_lock); reg_val = chip->reg_direction[off / BANK_SZ] | (1u << (off % BANK_SZ)); ret = pca953x_write_single(chip, chip->regs->direction, reg_val, off); if (ret) goto exit; chip->reg_direction[off / BANK_SZ] = reg_val; exit: ret = regmap_write_bits(chip->regmap, dirreg, bit, bit); mutex_unlock(&chip->i2c_lock); return ret; } Loading @@ -310,31 +370,21 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, unsigned off, int val) { struct pca953x_chip *chip = gpiochip_get_data(gc); u8 reg_val; u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off, true, false); u8 outreg = pca953x_recalc_addr(chip, chip->regs->output, off, true, false); u8 bit = BIT(off % BANK_SZ); int ret; mutex_lock(&chip->i2c_lock); /* set output level */ if (val) reg_val = chip->reg_output[off / BANK_SZ] | (1u << (off % BANK_SZ)); else reg_val = chip->reg_output[off / BANK_SZ] & ~(1u << (off % BANK_SZ)); ret = pca953x_write_single(chip, chip->regs->output, reg_val, off); ret = regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0); if (ret) goto exit; chip->reg_output[off / BANK_SZ] = reg_val; /* then direction */ reg_val = chip->reg_direction[off / BANK_SZ] & ~(1u << (off % BANK_SZ)); ret = pca953x_write_single(chip, chip->regs->direction, reg_val, off); if (ret) goto exit; chip->reg_direction[off / BANK_SZ] = reg_val; ret = regmap_write_bits(chip->regmap, dirreg, bit, 0); exit: mutex_unlock(&chip->i2c_lock); return ret; Loading @@ -343,11 +393,14 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) { struct pca953x_chip *chip = gpiochip_get_data(gc); u8 inreg = pca953x_recalc_addr(chip, chip->regs->input, off, true, false); u8 bit = BIT(off % BANK_SZ); u32 reg_val; int ret; mutex_lock(&chip->i2c_lock); ret = pca953x_read_single(chip, chip->regs->input, ®_val, off); ret = regmap_read(chip->regmap, inreg, ®_val); mutex_unlock(&chip->i2c_lock); if (ret < 0) { /* NOTE: diagnostic already emitted; that's all we should Loading @@ -357,45 +410,37 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) return 0; } return (reg_val & (1u << (off % BANK_SZ))) ? 1 : 0; return !!(reg_val & bit); } static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) { struct pca953x_chip *chip = gpiochip_get_data(gc); u8 reg_val; int ret; u8 outreg = pca953x_recalc_addr(chip, chip->regs->output, off, true, false); u8 bit = BIT(off % BANK_SZ); mutex_lock(&chip->i2c_lock); if (val) reg_val = chip->reg_output[off / BANK_SZ] | (1u << (off % BANK_SZ)); else reg_val = chip->reg_output[off / BANK_SZ] & ~(1u << (off % BANK_SZ)); ret = pca953x_write_single(chip, chip->regs->output, reg_val, off); if (ret) goto exit; chip->reg_output[off / BANK_SZ] = reg_val; exit: regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0); mutex_unlock(&chip->i2c_lock); } static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off) { struct pca953x_chip *chip = gpiochip_get_data(gc); u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off, true, false); u8 bit = BIT(off % BANK_SZ); u32 reg_val; int ret; mutex_lock(&chip->i2c_lock); ret = pca953x_read_single(chip, chip->regs->direction, ®_val, off); ret = regmap_read(chip->regmap, dirreg, ®_val); mutex_unlock(&chip->i2c_lock); if (ret < 0) return ret; return !!(reg_val & (1u << (off % BANK_SZ))); return !!(reg_val & bit); } static void pca953x_gpio_set_multiple(struct gpio_chip *gc, Loading @@ -403,14 +448,15 @@ static void pca953x_gpio_set_multiple(struct gpio_chip *gc, { struct pca953x_chip *chip = gpiochip_get_data(gc); unsigned int bank_mask, bank_val; int bank_shift, bank; int bank; u8 reg_val[MAX_BANK]; int ret; bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); mutex_lock(&chip->i2c_lock); memcpy(reg_val, chip->reg_output, NBANK(chip)); ret = pca953x_read_regs(chip, chip->regs->output, reg_val); if (ret) goto exit; for (bank = 0; bank < NBANK(chip); bank++) { bank_mask = mask[bank / sizeof(*mask)] >> ((bank % sizeof(*mask)) * 8); Loading @@ -422,13 +468,7 @@ static void pca953x_gpio_set_multiple(struct gpio_chip *gc, } } ret = i2c_smbus_write_i2c_block_data(chip->client, chip->regs->output << bank_shift, NBANK(chip), reg_val); if (ret) goto exit; memcpy(chip->reg_output, reg_val, NBANK(chip)); pca953x_write_regs(chip, chip->regs->output, reg_val); exit: mutex_unlock(&chip->i2c_lock); } Loading Loading @@ -487,6 +527,10 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) u8 new_irqs; int level, i; u8 invert_irq_mask[MAX_BANK]; int reg_direction[MAX_BANK]; regmap_bulk_read(chip->regmap, chip->regs->direction, reg_direction, NBANK(chip)); if (chip->driver_data & PCA_PCAL) { /* Enable latch on interrupt-enabled inputs */ Loading @@ -502,7 +546,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) /* Look for any newly setup interrupt */ for (i = 0; i < NBANK(chip); i++) { new_irqs = chip->irq_trig_fall[i] | chip->irq_trig_raise[i]; new_irqs &= ~chip->reg_direction[i]; new_irqs &= reg_direction[i]; while (new_irqs) { level = __ffs(new_irqs); Loading Loading @@ -567,6 +611,7 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) bool pending_seen = false; bool trigger_seen = false; u8 trigger[MAX_BANK]; int reg_direction[MAX_BANK]; int ret, i; if (chip->driver_data & PCA_PCAL) { Loading Loading @@ -597,8 +642,10 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) return false; /* Remove output pins from the equation */ regmap_bulk_read(chip->regmap, chip->regs->direction, reg_direction, NBANK(chip)); for (i = 0; i < NBANK(chip); i++) cur_stat[i] &= chip->reg_direction[i]; cur_stat[i] &= reg_direction[i]; memcpy(old_stat, chip->irq_stat, NBANK(chip)); Loading Loading @@ -652,6 +699,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base) { struct i2c_client *client = chip->client; int reg_direction[MAX_BANK]; int ret, i; if (client->irq && irq_base != -1 Loading @@ -666,8 +714,10 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, * interrupt. We have to rely on the previous read for * this purpose. */ regmap_bulk_read(chip->regmap, chip->regs->direction, reg_direction, NBANK(chip)); for (i = 0; i < NBANK(chip); i++) chip->irq_stat[i] &= chip->reg_direction[i]; chip->irq_stat[i] &= reg_direction[i]; mutex_init(&chip->irq_lock); ret = devm_request_threaded_irq(&client->dev, Loading Loading @@ -715,20 +765,19 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, } #endif static int device_pca953x_init(struct pca953x_chip *chip, u32 invert) static int device_pca95xx_init(struct pca953x_chip *chip, u32 invert) { int ret; u8 val[MAX_BANK]; chip->regs = &pca953x_regs; ret = pca953x_read_regs(chip, chip->regs->output, chip->reg_output); if (ret) ret = regcache_sync_region(chip->regmap, chip->regs->output, chip->regs->output + NBANK(chip)); if (ret != 0) goto out; ret = pca953x_read_regs(chip, chip->regs->direction, chip->reg_direction); if (ret) ret = regcache_sync_region(chip->regmap, chip->regs->direction, chip->regs->direction + NBANK(chip)); if (ret != 0) goto out; /* set platform specific polarity inversion */ Loading @@ -737,7 +786,7 @@ static int device_pca953x_init(struct pca953x_chip *chip, u32 invert) else memset(val, 0, NBANK(chip)); ret = pca953x_write_regs(chip, PCA953X_INVERT, val); ret = pca953x_write_regs(chip, chip->regs->invert, val); out: return ret; } Loading @@ -747,22 +796,7 @@ static int device_pca957x_init(struct pca953x_chip *chip, u32 invert) int ret; u8 val[MAX_BANK]; chip->regs = &pca957x_regs; ret = pca953x_read_regs(chip, chip->regs->output, chip->reg_output); if (ret) goto out; ret = pca953x_read_regs(chip, chip->regs->direction, chip->reg_direction); if (ret) goto out; /* set platform specific polarity inversion */ if (invert) memset(val, 0xFF, NBANK(chip)); else memset(val, 0, NBANK(chip)); ret = pca953x_write_regs(chip, PCA957X_INVRT, val); ret = device_pca95xx_init(chip, invert); if (ret) goto out; Loading Loading @@ -853,6 +887,16 @@ static int pca953x_probe(struct i2c_client *client, } } i2c_set_clientdata(client, chip); chip->regmap = devm_regmap_init_i2c(client, &pca953x_i2c_regmap); if (IS_ERR(chip->regmap)) { ret = PTR_ERR(chip->regmap); goto err_exit; } regcache_mark_dirty(chip->regmap); mutex_init(&chip->i2c_lock); /* * In case we have an i2c-mux controlled by a GPIO provided by an Loading @@ -878,24 +922,13 @@ static int pca953x_probe(struct i2c_client *client, */ pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK); if (chip->gpio_chip.ngpio <= 8) { chip->write_regs = pca953x_write_regs_8; chip->read_regs = pca953x_read_regs_8; } else if (chip->gpio_chip.ngpio >= 24) { chip->write_regs = pca953x_write_regs_24; chip->read_regs = pca953x_read_regs_24; if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) { chip->regs = &pca953x_regs; ret = device_pca95xx_init(chip, invert); } else { if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) chip->write_regs = pca953x_write_regs_16; else chip->write_regs = pca957x_write_regs_16; chip->read_regs = pca953x_read_regs_16; } if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) ret = device_pca953x_init(chip, invert); else chip->regs = &pca957x_regs; ret = device_pca957x_init(chip, invert); } if (ret) goto err_exit; Loading @@ -914,7 +947,6 @@ static int pca953x_probe(struct i2c_client *client, dev_warn(&client->dev, "setup failed, %d\n", ret); } i2c_set_clientdata(client, chip); return 0; err_exit: Loading Loading @@ -943,6 +975,91 @@ static int pca953x_remove(struct i2c_client *client) return ret; } #ifdef CONFIG_PM_SLEEP static int pca953x_regcache_sync(struct device *dev) { struct pca953x_chip *chip = dev_get_drvdata(dev); int ret; /* * The ordering between direction and output is important, * sync these registers first and only then sync the rest. */ ret = regcache_sync_region(chip->regmap, chip->regs->direction, chip->regs->direction + NBANK(chip)); if (ret != 0) { dev_err(dev, "Failed to sync GPIO dir registers: %d\n", ret); return ret; } ret = regcache_sync_region(chip->regmap, chip->regs->output, chip->regs->output + NBANK(chip)); if (ret != 0) { dev_err(dev, "Failed to sync GPIO out registers: %d\n", ret); return ret; } #ifdef CONFIG_GPIO_PCA953X_IRQ if (chip->driver_data & PCA_PCAL) { ret = regcache_sync_region(chip->regmap, PCAL953X_IN_LATCH, PCAL953X_IN_LATCH + NBANK(chip)); if (ret != 0) { dev_err(dev, "Failed to sync INT latch registers: %d\n", ret); return ret; } ret = regcache_sync_region(chip->regmap, PCAL953X_INT_MASK, PCAL953X_INT_MASK + NBANK(chip)); if (ret != 0) { dev_err(dev, "Failed to sync INT mask registers: %d\n", ret); return ret; } } #endif return 0; } static int pca953x_suspend(struct device *dev) { struct pca953x_chip *chip = dev_get_drvdata(dev); regcache_cache_only(chip->regmap, true); regulator_disable(chip->regulator); return 0; } static int pca953x_resume(struct device *dev) { struct pca953x_chip *chip = dev_get_drvdata(dev); int ret; ret = regulator_enable(chip->regulator); if (ret != 0) { dev_err(dev, "Failed to enable regulator: %d\n", ret); return 0; } regcache_cache_only(chip->regmap, false); regcache_mark_dirty(chip->regmap); ret = pca953x_regcache_sync(dev); if (ret) return ret; ret = regcache_sync(chip->regmap); if (ret != 0) { dev_err(dev, "Failed to restore register map: %d\n", ret); return ret; } return 0; } #endif /* convenience to stop overlong match-table lines */ #define OF_953X(__nrgpio, __int) (void *)(__nrgpio | PCA953X_TYPE | __int) #define OF_957X(__nrgpio, __int) (void *)(__nrgpio | PCA957X_TYPE | __int) Loading Loading @@ -986,9 +1103,12 @@ static const struct of_device_id pca953x_dt_ids[] = { MODULE_DEVICE_TABLE(of, pca953x_dt_ids); static SIMPLE_DEV_PM_OPS(pca953x_pm_ops, pca953x_suspend, pca953x_resume); static struct i2c_driver pca953x_driver = { .driver = { .name = "pca953x", .pm = &pca953x_pm_ops, .of_match_table = pca953x_dt_ids, .acpi_match_table = ACPI_PTR(pca953x_acpi_ids), }, Loading