Commit 3e42f200 authored by Linus Walleij's avatar Linus Walleij

Merge branch 'ib-pca953x' into devel

parents c5510b8d b7657430
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/platform_data/pca953x.h> #include <linux/platform_data/pca953x.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -30,6 +31,8 @@ ...@@ -30,6 +31,8 @@
#define PCA953X_INVERT 0x02 #define PCA953X_INVERT 0x02
#define PCA953X_DIRECTION 0x03 #define PCA953X_DIRECTION 0x03
#define REG_ADDR_MASK 0x3f
#define REG_ADDR_EXT 0x40
#define REG_ADDR_AI 0x80 #define REG_ADDR_AI 0x80
#define PCA957X_IN 0x00 #define PCA957X_IN 0x00
...@@ -58,7 +61,7 @@ ...@@ -58,7 +61,7 @@
#define PCA_GPIO_MASK 0x00FF #define PCA_GPIO_MASK 0x00FF
#define PCAL_GPIO_MASK 0x1f #define PCAL_GPIO_MASK 0x1f
#define PCAL_PINCTRL_MASK 0xe0 #define PCAL_PINCTRL_MASK 0x60
#define PCA_INT 0x0100 #define PCA_INT 0x0100
#define PCA_PCAL 0x0200 #define PCA_PCAL 0x0200
...@@ -119,25 +122,27 @@ struct pca953x_reg_config { ...@@ -119,25 +122,27 @@ struct pca953x_reg_config {
int direction; int direction;
int output; int output;
int input; int input;
int invert;
}; };
static const struct pca953x_reg_config pca953x_regs = { static const struct pca953x_reg_config pca953x_regs = {
.direction = PCA953X_DIRECTION, .direction = PCA953X_DIRECTION,
.output = PCA953X_OUTPUT, .output = PCA953X_OUTPUT,
.input = PCA953X_INPUT, .input = PCA953X_INPUT,
.invert = PCA953X_INVERT,
}; };
static const struct pca953x_reg_config pca957x_regs = { static const struct pca953x_reg_config pca957x_regs = {
.direction = PCA957X_CFG, .direction = PCA957X_CFG,
.output = PCA957X_OUT, .output = PCA957X_OUT,
.input = PCA957X_IN, .input = PCA957X_IN,
.invert = PCA957X_INVRT,
}; };
struct pca953x_chip { struct pca953x_chip {
unsigned gpio_start; unsigned gpio_start;
u8 reg_output[MAX_BANK];
u8 reg_direction[MAX_BANK];
struct mutex i2c_lock; struct mutex i2c_lock;
struct regmap *regmap;
#ifdef CONFIG_GPIO_PCA953X_IRQ #ifdef CONFIG_GPIO_PCA953X_IRQ
struct mutex irq_lock; struct mutex irq_lock;
...@@ -154,87 +159,177 @@ struct pca953x_chip { ...@@ -154,87 +159,177 @@ struct pca953x_chip {
struct regulator *regulator; struct regulator *regulator;
const struct pca953x_reg_config *regs; 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, static int pca953x_bank_shift(struct pca953x_chip *chip)
int off)
{ {
int ret; return fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);
int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); }
int offset = off / BANK_SZ;
ret = i2c_smbus_read_byte_data(chip->client, #define PCA953x_BANK_INPUT BIT(0)
(reg << bank_shift) + offset); #define PCA953x_BANK_OUTPUT BIT(1)
*val = ret; #define PCA953x_BANK_POLARITY BIT(2)
#define PCA953x_BANK_CONFIG BIT(3)
if (ret < 0) { #define PCA957x_BANK_INPUT BIT(0)
dev_err(&chip->client->dev, "failed reading register\n"); #define PCA957x_BANK_POLARITY BIT(1)
return ret; #define PCA957x_BANK_BUSHOLD BIT(2)
#define PCA957x_BANK_CONFIG BIT(4)
#define PCA957x_BANK_OUTPUT BIT(5)
#define PCAL9xxx_BANK_IN_LATCH BIT(8 + 2)
#define PCAL9xxx_BANK_IRQ_MASK BIT(8 + 5)
#define PCAL9xxx_BANK_IRQ_STAT BIT(8 + 6)
/*
* 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.
*/
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);
/* 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_single(struct pca953x_chip *chip, int reg, u32 val, static bool pca953x_readable_register(struct device *dev, unsigned int reg)
int off)
{ {
int ret; struct pca953x_chip *chip = dev_get_drvdata(dev);
int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); u32 bank;
int offset = off / BANK_SZ;
ret = i2c_smbus_write_byte_data(chip->client, if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) {
(reg << bank_shift) + offset, val); 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;
}
if (ret < 0) { if (chip->driver_data & PCA_PCAL) {
dev_err(&chip->client->dev, "failed writing register\n"); bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_IRQ_MASK |
return ret; PCAL9xxx_BANK_IRQ_STAT;
} }
return 0; return pca953x_check_register(chip, reg, bank);
} }
static int pca953x_write_regs_8(struct pca953x_chip *chip, int reg, u8 *val) static bool pca953x_writeable_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;
static int pca953x_write_regs_16(struct pca953x_chip *chip, int reg, u8 *val) if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) {
{ bank = PCA953x_BANK_OUTPUT | PCA953x_BANK_POLARITY |
u16 word = get_unaligned((u16 *)val); PCA953x_BANK_CONFIG;
} else {
bank = PCA957x_BANK_OUTPUT | PCA957x_BANK_POLARITY |
PCA957x_BANK_CONFIG | PCA957x_BANK_BUSHOLD;
}
return i2c_smbus_write_word_data(chip->client, reg << 1, word); if (chip->driver_data & PCA_PCAL)
bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_IRQ_MASK;
return pca953x_check_register(chip, reg, bank);
} }
static int pca957x_write_regs_16(struct pca953x_chip *chip, int reg, u8 *val) static bool pca953x_volatile_register(struct device *dev, unsigned int reg)
{ {
int ret; struct pca953x_chip *chip = dev_get_drvdata(dev);
u32 bank;
ret = i2c_smbus_write_byte_data(chip->client, reg << 1, val[0]); if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE)
if (ret < 0) bank = PCA953x_BANK_INPUT;
return ret; else
bank = PCA957x_BANK_INPUT;
return i2c_smbus_write_byte_data(chip->client, (reg << 1) + 1, val[1]); if (chip->driver_data & PCA_PCAL)
bank |= PCAL9xxx_BANK_IRQ_STAT;
return pca953x_check_register(chip, reg, bank);
} }
static int pca953x_write_regs_24(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 bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); int bank_shift = pca953x_bank_shift(chip);
int addr = (reg & PCAL_GPIO_MASK) << bank_shift; int addr = (reg & PCAL_GPIO_MASK) << bank_shift;
int pinctrl = (reg & PCAL_PINCTRL_MASK) << 1; int pinctrl = (reg & PCAL_PINCTRL_MASK) << 1;
u8 regaddr = pinctrl | addr | (off / BANK_SZ);
return i2c_smbus_write_i2c_block_data(chip->client, /* Single byte read doesn't need AI bit set. */
pinctrl | addr | REG_ADDR_AI, if (!addrinc)
NBANK(chip), val); return regaddr;
/* 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_write_regs(struct pca953x_chip *chip, int reg, u8 *val) static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val)
{ {
int ret = 0; u8 regaddr = pca953x_recalc_addr(chip, reg, 0, true, true);
int ret;
ret = chip->write_regs(chip, reg, val); ret = regmap_bulk_write(chip->regmap, regaddr, val, NBANK(chip));
if (ret < 0) { if (ret < 0) {
dev_err(&chip->client->dev, "failed writing register\n"); dev_err(&chip->client->dev, "failed writing register\n");
return ret; return ret;
...@@ -243,42 +338,12 @@ static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val) ...@@ -243,42 +338,12 @@ static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val)
return 0; return 0;
} }
static int pca953x_read_regs_8(struct pca953x_chip *chip, int reg, u8 *val)
{
int ret;
ret = i2c_smbus_read_byte_data(chip->client, reg);
*val = ret;
return ret;
}
static int pca953x_read_regs_16(struct pca953x_chip *chip, int reg, u8 *val)
{
int ret;
ret = i2c_smbus_read_word_data(chip->client, reg << 1);
put_unaligned(ret, (u16 *)val);
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);
}
static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val) 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; int ret;
ret = chip->read_regs(chip, reg, val); ret = regmap_bulk_read(chip->regmap, regaddr, val, NBANK(chip));
if (ret < 0) { if (ret < 0) {
dev_err(&chip->client->dev, "failed reading register\n"); dev_err(&chip->client->dev, "failed reading register\n");
return ret; return ret;
...@@ -290,18 +355,13 @@ static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val) ...@@ -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) static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
{ {
struct pca953x_chip *chip = gpiochip_get_data(gc); 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; int ret;
mutex_lock(&chip->i2c_lock); mutex_lock(&chip->i2c_lock);
reg_val = chip->reg_direction[off / BANK_SZ] | (1u << (off % BANK_SZ)); ret = regmap_write_bits(chip->regmap, dirreg, bit, bit);
ret = pca953x_write_single(chip, chip->regs->direction, reg_val, off);
if (ret)
goto exit;
chip->reg_direction[off / BANK_SZ] = reg_val;
exit:
mutex_unlock(&chip->i2c_lock); mutex_unlock(&chip->i2c_lock);
return ret; return ret;
} }
...@@ -310,31 +370,21 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, ...@@ -310,31 +370,21 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
unsigned off, int val) unsigned off, int val)
{ {
struct pca953x_chip *chip = gpiochip_get_data(gc); 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; int ret;
mutex_lock(&chip->i2c_lock); mutex_lock(&chip->i2c_lock);
/* set output level */ /* set output level */
if (val) ret = regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0);
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) if (ret)
goto exit; goto exit;
chip->reg_output[off / BANK_SZ] = reg_val;
/* then direction */ /* then direction */
reg_val = chip->reg_direction[off / BANK_SZ] & ~(1u << (off % BANK_SZ)); ret = regmap_write_bits(chip->regmap, dirreg, bit, 0);
ret = pca953x_write_single(chip, chip->regs->direction, reg_val, off);
if (ret)
goto exit;
chip->reg_direction[off / BANK_SZ] = reg_val;
exit: exit:
mutex_unlock(&chip->i2c_lock); mutex_unlock(&chip->i2c_lock);
return ret; return ret;
...@@ -343,11 +393,14 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, ...@@ -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) static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
{ {
struct pca953x_chip *chip = gpiochip_get_data(gc); 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; u32 reg_val;
int ret; int ret;
mutex_lock(&chip->i2c_lock); mutex_lock(&chip->i2c_lock);
ret = pca953x_read_single(chip, chip->regs->input, &reg_val, off); ret = regmap_read(chip->regmap, inreg, &reg_val);
mutex_unlock(&chip->i2c_lock); mutex_unlock(&chip->i2c_lock);
if (ret < 0) { if (ret < 0) {
/* NOTE: diagnostic already emitted; that's all we should /* NOTE: diagnostic already emitted; that's all we should
...@@ -357,45 +410,37 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) ...@@ -357,45 +410,37 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
return 0; 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) static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
{ {
struct pca953x_chip *chip = gpiochip_get_data(gc); struct pca953x_chip *chip = gpiochip_get_data(gc);
u8 reg_val; u8 outreg = pca953x_recalc_addr(chip, chip->regs->output, off,
int ret; true, false);
u8 bit = BIT(off % BANK_SZ);
mutex_lock(&chip->i2c_lock); mutex_lock(&chip->i2c_lock);
if (val) regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0);
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:
mutex_unlock(&chip->i2c_lock); mutex_unlock(&chip->i2c_lock);
} }
static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off) static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off)
{ {
struct pca953x_chip *chip = gpiochip_get_data(gc); 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; u32 reg_val;
int ret; int ret;
mutex_lock(&chip->i2c_lock); mutex_lock(&chip->i2c_lock);
ret = pca953x_read_single(chip, chip->regs->direction, &reg_val, off); ret = regmap_read(chip->regmap, dirreg, &reg_val);
mutex_unlock(&chip->i2c_lock); mutex_unlock(&chip->i2c_lock);
if (ret < 0) if (ret < 0)
return ret; return ret;
return !!(reg_val & (1u << (off % BANK_SZ))); return !!(reg_val & bit);
} }
static void pca953x_gpio_set_multiple(struct gpio_chip *gc, static void pca953x_gpio_set_multiple(struct gpio_chip *gc,
...@@ -403,14 +448,15 @@ static void pca953x_gpio_set_multiple(struct gpio_chip *gc, ...@@ -403,14 +448,15 @@ static void pca953x_gpio_set_multiple(struct gpio_chip *gc,
{ {
struct pca953x_chip *chip = gpiochip_get_data(gc); struct pca953x_chip *chip = gpiochip_get_data(gc);
unsigned int bank_mask, bank_val; unsigned int bank_mask, bank_val;
int bank_shift, bank; int bank;
u8 reg_val[MAX_BANK]; u8 reg_val[MAX_BANK];
int ret; int ret;
bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);
mutex_lock(&chip->i2c_lock); 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++) { for (bank = 0; bank < NBANK(chip); bank++) {
bank_mask = mask[bank / sizeof(*mask)] >> bank_mask = mask[bank / sizeof(*mask)] >>
((bank % sizeof(*mask)) * 8); ((bank % sizeof(*mask)) * 8);
...@@ -422,13 +468,7 @@ static void pca953x_gpio_set_multiple(struct gpio_chip *gc, ...@@ -422,13 +468,7 @@ static void pca953x_gpio_set_multiple(struct gpio_chip *gc,
} }
} }
ret = i2c_smbus_write_i2c_block_data(chip->client, pca953x_write_regs(chip, chip->regs->output, reg_val);
chip->regs->output << bank_shift,
NBANK(chip), reg_val);
if (ret)
goto exit;
memcpy(chip->reg_output, reg_val, NBANK(chip));
exit: exit:
mutex_unlock(&chip->i2c_lock); mutex_unlock(&chip->i2c_lock);
} }
...@@ -487,6 +527,10 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) ...@@ -487,6 +527,10 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
u8 new_irqs; u8 new_irqs;
int level, i; int level, i;
u8 invert_irq_mask[MAX_BANK]; 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) { if (chip->driver_data & PCA_PCAL) {
/* Enable latch on interrupt-enabled inputs */ /* Enable latch on interrupt-enabled inputs */
...@@ -502,7 +546,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) ...@@ -502,7 +546,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
/* Look for any newly setup interrupt */ /* Look for any newly setup interrupt */
for (i = 0; i < NBANK(chip); i++) { for (i = 0; i < NBANK(chip); i++) {
new_irqs = chip->irq_trig_fall[i] | chip->irq_trig_raise[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) { while (new_irqs) {
level = __ffs(new_irqs); level = __ffs(new_irqs);
...@@ -567,6 +611,7 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) ...@@ -567,6 +611,7 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending)
bool pending_seen = false; bool pending_seen = false;
bool trigger_seen = false; bool trigger_seen = false;
u8 trigger[MAX_BANK]; u8 trigger[MAX_BANK];
int reg_direction[MAX_BANK];
int ret, i; int ret, i;
if (chip->driver_data & PCA_PCAL) { if (chip->driver_data & PCA_PCAL) {
...@@ -597,8 +642,10 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) ...@@ -597,8 +642,10 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending)
return false; return false;
/* Remove output pins from the equation */ /* 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++) 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)); memcpy(old_stat, chip->irq_stat, NBANK(chip));
...@@ -652,6 +699,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, ...@@ -652,6 +699,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
int irq_base) int irq_base)
{ {
struct i2c_client *client = chip->client; struct i2c_client *client = chip->client;
int reg_direction[MAX_BANK];
int ret, i; int ret, i;
if (client->irq && irq_base != -1 if (client->irq && irq_base != -1
...@@ -666,8 +714,10 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, ...@@ -666,8 +714,10 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
* interrupt. We have to rely on the previous read for * interrupt. We have to rely on the previous read for
* this purpose. * this purpose.
*/ */
regmap_bulk_read(chip->regmap, chip->regs->direction,
reg_direction, NBANK(chip));
for (i = 0; i < NBANK(chip); i++) 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); mutex_init(&chip->irq_lock);
ret = devm_request_threaded_irq(&client->dev, ret = devm_request_threaded_irq(&client->dev,
...@@ -715,20 +765,19 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, ...@@ -715,20 +765,19 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
} }
#endif #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; int ret;
u8 val[MAX_BANK]; u8 val[MAX_BANK];
chip->regs = &pca953x_regs; ret = regcache_sync_region(chip->regmap, chip->regs->output,
chip->regs->output + NBANK(chip));
ret = pca953x_read_regs(chip, chip->regs->output, chip->reg_output); if (ret != 0)
if (ret)
goto out; goto out;
ret = pca953x_read_regs(chip, chip->regs->direction, ret = regcache_sync_region(chip->regmap, chip->regs->direction,
chip->reg_direction); chip->regs->direction + NBANK(chip));
if (ret) if (ret != 0)
goto out; goto out;
/* set platform specific polarity inversion */ /* set platform specific polarity inversion */
...@@ -737,7 +786,7 @@ static int device_pca953x_init(struct pca953x_chip *chip, u32 invert) ...@@ -737,7 +786,7 @@ static int device_pca953x_init(struct pca953x_chip *chip, u32 invert)
else else
memset(val, 0, NBANK(chip)); memset(val, 0, NBANK(chip));
ret = pca953x_write_regs(chip, PCA953X_INVERT, val); ret = pca953x_write_regs(chip, chip->regs->invert, val);
out: out:
return ret; return ret;
} }
...@@ -747,22 +796,7 @@ static int device_pca957x_init(struct pca953x_chip *chip, u32 invert) ...@@ -747,22 +796,7 @@ static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
int ret; int ret;
u8 val[MAX_BANK]; u8 val[MAX_BANK];
chip->regs = &pca957x_regs; ret = device_pca95xx_init(chip, invert);
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);
if (ret) if (ret)
goto out; goto out;
...@@ -853,6 +887,16 @@ static int pca953x_probe(struct i2c_client *client, ...@@ -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); mutex_init(&chip->i2c_lock);
/* /*
* In case we have an i2c-mux controlled by a GPIO provided by an * In case we have an i2c-mux controlled by a GPIO provided by an
...@@ -878,24 +922,13 @@ static int pca953x_probe(struct i2c_client *client, ...@@ -878,24 +922,13 @@ static int pca953x_probe(struct i2c_client *client,
*/ */
pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK); pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK);
if (chip->gpio_chip.ngpio <= 8) { if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) {
chip->write_regs = pca953x_write_regs_8; chip->regs = &pca953x_regs;
chip->read_regs = pca953x_read_regs_8; ret = device_pca95xx_init(chip, invert);
} else if (chip->gpio_chip.ngpio >= 24) {
chip->write_regs = pca953x_write_regs_24;
chip->read_regs = pca953x_read_regs_24;
} else { } else {
if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) chip->regs = &pca957x_regs;
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
ret = device_pca957x_init(chip, invert); ret = device_pca957x_init(chip, invert);
}
if (ret) if (ret)
goto err_exit; goto err_exit;
...@@ -914,7 +947,6 @@ static int pca953x_probe(struct i2c_client *client, ...@@ -914,7 +947,6 @@ static int pca953x_probe(struct i2c_client *client,
dev_warn(&client->dev, "setup failed, %d\n", ret); dev_warn(&client->dev, "setup failed, %d\n", ret);
} }
i2c_set_clientdata(client, chip);
return 0; return 0;
err_exit: err_exit:
...@@ -943,6 +975,91 @@ static int pca953x_remove(struct i2c_client *client) ...@@ -943,6 +975,91 @@ static int pca953x_remove(struct i2c_client *client)
return ret; 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 */ /* convenience to stop overlong match-table lines */
#define OF_953X(__nrgpio, __int) (void *)(__nrgpio | PCA953X_TYPE | __int) #define OF_953X(__nrgpio, __int) (void *)(__nrgpio | PCA953X_TYPE | __int)
#define OF_957X(__nrgpio, __int) (void *)(__nrgpio | PCA957X_TYPE | __int) #define OF_957X(__nrgpio, __int) (void *)(__nrgpio | PCA957X_TYPE | __int)
...@@ -986,9 +1103,12 @@ static const struct of_device_id pca953x_dt_ids[] = { ...@@ -986,9 +1103,12 @@ static const struct of_device_id pca953x_dt_ids[] = {
MODULE_DEVICE_TABLE(of, 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 = { static struct i2c_driver pca953x_driver = {
.driver = { .driver = {
.name = "pca953x", .name = "pca953x",
.pm = &pca953x_pm_ops,
.of_match_table = pca953x_dt_ids, .of_match_table = pca953x_dt_ids,
.acpi_match_table = ACPI_PTR(pca953x_acpi_ids), .acpi_match_table = ACPI_PTR(pca953x_acpi_ids),
}, },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment