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

Merge branch 'ib-pca953x' into devel

parents c5510b8d b7657430
......@@ -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,87 +159,177 @@ 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)
#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,
int off)
static bool pca953x_readable_register(struct device *dev, unsigned int reg)
{
int ret;
int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);
int offset = off / BANK_SZ;
struct pca953x_chip *chip = dev_get_drvdata(dev);
u32 bank;
ret = i2c_smbus_write_byte_data(chip->client,
(reg << bank_shift) + offset, val);
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;
}
if (ret < 0) {
dev_err(&chip->client->dev, "failed writing register\n");
return ret;
if (chip->driver_data & PCA_PCAL) {
bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_IRQ_MASK |
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)
{
u16 word = get_unaligned((u16 *)val);
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;
}
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 (ret < 0)
return ret;
if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE)
bank = PCA953x_BANK_INPUT;
else
bank = PCA957x_BANK_INPUT;
if (chip->driver_data & PCA_PCAL)
bank |= PCAL9xxx_BANK_IRQ_STAT;
return i2c_smbus_write_byte_data(chip->client, (reg << 1) + 1, val[1]);
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 pinctrl = (reg & PCAL_PINCTRL_MASK) << 1;
u8 regaddr = pinctrl | addr | (off / BANK_SZ);
/* Single byte read doesn't need AI bit set. */
if (!addrinc)
return regaddr;
/* Chips with 24 and more GPIOs always support Auto Increment */
if (write && NBANK(chip) > 2)
regaddr |= REG_ADDR_AI;
return i2c_smbus_write_i2c_block_data(chip->client,
pinctrl | addr | REG_ADDR_AI,
NBANK(chip), val);
/* 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)
{
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) {
dev_err(&chip->client->dev, "failed writing register\n");
return ret;
......@@ -243,42 +338,12 @@ static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val)
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)
{
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),
},
......
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