Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

Merge branch 'ib-pca953x' into devel

parents c5510b8d b7657430
Loading
Loading
Loading
Loading
+302 −182
Original line number Diff line number Diff line
@@ -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>

@@ -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
@@ -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
@@ -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;
@@ -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;
@@ -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;
}
@@ -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;
@@ -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, &reg_val, off);
	ret = regmap_read(chip->regmap, inreg, &reg_val);
	mutex_unlock(&chip->i2c_lock);
	if (ret < 0) {
		/* 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)
		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, &reg_val, off);
	ret = regmap_read(chip->regmap, dirreg, &reg_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,
@@ -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);
@@ -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);
}
@@ -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 */
@@ -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);
@@ -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) {
@@ -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));

@@ -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
@@ -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,
@@ -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 */
@@ -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;
}
@@ -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;

@@ -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
@@ -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;

@@ -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:
@@ -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)
@@ -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),
	},