summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpio-pca953x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpio-pca953x.c')
-rw-r--r--drivers/gpio/gpio-pca953x.c409
1 files changed, 249 insertions, 160 deletions
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 9c693ae..2405946 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -16,6 +16,7 @@
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/i2c.h>
#include <linux/i2c/pca953x.h>
#include <linux/slab.h>
@@ -45,6 +46,7 @@
#define PCA957X_TYPE 0x2000
static const struct i2c_device_id pca953x_id[] = {
+ { "pca9505", 40 | PCA953X_TYPE | PCA_INT, },
{ "pca9534", 8 | PCA953X_TYPE | PCA_INT, },
{ "pca9535", 16 | PCA953X_TYPE | PCA_INT, },
{ "pca9536", 4 | PCA953X_TYPE, },
@@ -70,19 +72,24 @@ static const struct i2c_device_id pca953x_id[] = {
};
MODULE_DEVICE_TABLE(i2c, pca953x_id);
+#define MAX_BANK 5
+#define BANK_SZ 8
+
+#define NBANK(chip) (chip->gpio_chip.ngpio / BANK_SZ)
+
struct pca953x_chip {
unsigned gpio_start;
- u32 reg_output;
- u32 reg_direction;
+ u8 reg_output[MAX_BANK];
+ u8 reg_direction[MAX_BANK];
struct mutex i2c_lock;
#ifdef CONFIG_GPIO_PCA953X_IRQ
struct mutex irq_lock;
- u32 irq_mask;
- u32 irq_stat;
- u32 irq_trig_raise;
- u32 irq_trig_fall;
- int irq_base;
+ u8 irq_mask[MAX_BANK];
+ u8 irq_stat[MAX_BANK];
+ u8 irq_trig_raise[MAX_BANK];
+ u8 irq_trig_fall[MAX_BANK];
+ struct irq_domain *domain;
#endif
struct i2c_client *client;
@@ -91,33 +98,69 @@ struct pca953x_chip {
int chip_type;
};
-static int pca953x_write_reg(struct pca953x_chip *chip, int reg, u32 val)
+static int pca953x_read_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;
+
+ ret = i2c_smbus_read_byte_data(chip->client,
+ (reg << bank_shift) + offset);
+ *val = ret;
+
+ if (ret < 0) {
+ dev_err(&chip->client->dev, "failed reading register\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pca953x_write_single(struct pca953x_chip *chip, int reg, u32 val,
+ int off)
+{
+ int ret = 0;
+ int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);
+ int offset = off / BANK_SZ;
+
+ ret = i2c_smbus_write_byte_data(chip->client,
+ (reg << bank_shift) + offset, val);
+
+ if (ret < 0) {
+ dev_err(&chip->client->dev, "failed writing register\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val)
{
int ret = 0;
if (chip->gpio_chip.ngpio <= 8)
- ret = i2c_smbus_write_byte_data(chip->client, reg, val);
- else if (chip->gpio_chip.ngpio == 24) {
- cpu_to_le32s(&val);
+ ret = i2c_smbus_write_byte_data(chip->client, reg, *val);
+ else if (chip->gpio_chip.ngpio >= 24) {
+ int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);
ret = i2c_smbus_write_i2c_block_data(chip->client,
- (reg << 2) | REG_ADDR_AI,
- 3,
- (u8 *) &val);
+ (reg << bank_shift) | REG_ADDR_AI,
+ NBANK(chip), val);
}
else {
switch (chip->chip_type) {
case PCA953X_TYPE:
ret = i2c_smbus_write_word_data(chip->client,
- reg << 1, val);
+ reg << 1, (u16) *val);
break;
case PCA957X_TYPE:
ret = i2c_smbus_write_byte_data(chip->client, reg << 1,
- val & 0xff);
+ val[0]);
if (ret < 0)
break;
ret = i2c_smbus_write_byte_data(chip->client,
(reg << 1) + 1,
- (val & 0xff00) >> 8);
+ val[1]);
break;
}
}
@@ -130,26 +173,24 @@ static int pca953x_write_reg(struct pca953x_chip *chip, int reg, u32 val)
return 0;
}
-static int pca953x_read_reg(struct pca953x_chip *chip, int reg, u32 *val)
+static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val)
{
int ret;
if (chip->gpio_chip.ngpio <= 8) {
ret = i2c_smbus_read_byte_data(chip->client, reg);
*val = ret;
- }
- else if (chip->gpio_chip.ngpio == 24) {
- *val = 0;
+ } else if (chip->gpio_chip.ngpio >= 24) {
+ int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);
+
ret = i2c_smbus_read_i2c_block_data(chip->client,
- (reg << 2) | REG_ADDR_AI,
- 3,
- (u8 *) val);
- le32_to_cpus(val);
+ (reg << bank_shift) | REG_ADDR_AI,
+ NBANK(chip), val);
} else {
ret = i2c_smbus_read_word_data(chip->client, reg << 1);
- *val = ret;
+ val[0] = (u16)ret & 0xFF;
+ val[1] = (u16)ret >> 8;
}
-
if (ret < 0) {
dev_err(&chip->client->dev, "failed reading register\n");
return ret;
@@ -161,13 +202,13 @@ static int pca953x_read_reg(struct pca953x_chip *chip, int reg, u32 *val)
static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
{
struct pca953x_chip *chip;
- uint reg_val;
+ u8 reg_val;
int ret, offset = 0;
chip = container_of(gc, struct pca953x_chip, gpio_chip);
mutex_lock(&chip->i2c_lock);
- reg_val = chip->reg_direction | (1u << off);
+ reg_val = chip->reg_direction[off / BANK_SZ] | (1u << (off % BANK_SZ));
switch (chip->chip_type) {
case PCA953X_TYPE:
@@ -177,11 +218,11 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
offset = PCA957X_CFG;
break;
}
- ret = pca953x_write_reg(chip, offset, reg_val);
+ ret = pca953x_write_single(chip, offset, reg_val, off);
if (ret)
goto exit;
- chip->reg_direction = reg_val;
+ chip->reg_direction[off / BANK_SZ] = reg_val;
ret = 0;
exit:
mutex_unlock(&chip->i2c_lock);
@@ -192,7 +233,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
unsigned off, int val)
{
struct pca953x_chip *chip;
- uint reg_val;
+ u8 reg_val;
int ret, offset = 0;
chip = container_of(gc, struct pca953x_chip, gpio_chip);
@@ -200,9 +241,11 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
mutex_lock(&chip->i2c_lock);
/* set output level */
if (val)
- reg_val = chip->reg_output | (1u << off);
+ reg_val = chip->reg_output[off / BANK_SZ]
+ | (1u << (off % BANK_SZ));
else
- reg_val = chip->reg_output & ~(1u << off);
+ reg_val = chip->reg_output[off / BANK_SZ]
+ & ~(1u << (off % BANK_SZ));
switch (chip->chip_type) {
case PCA953X_TYPE:
@@ -212,14 +255,14 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
offset = PCA957X_OUT;
break;
}
- ret = pca953x_write_reg(chip, offset, reg_val);
+ ret = pca953x_write_single(chip, offset, reg_val, off);
if (ret)
goto exit;
- chip->reg_output = reg_val;
+ chip->reg_output[off / BANK_SZ] = reg_val;
/* then direction */
- reg_val = chip->reg_direction & ~(1u << off);
+ reg_val = chip->reg_direction[off / BANK_SZ] & ~(1u << (off % BANK_SZ));
switch (chip->chip_type) {
case PCA953X_TYPE:
offset = PCA953X_DIRECTION;
@@ -228,11 +271,11 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
offset = PCA957X_CFG;
break;
}
- ret = pca953x_write_reg(chip, offset, reg_val);
+ ret = pca953x_write_single(chip, offset, reg_val, off);
if (ret)
goto exit;
- chip->reg_direction = reg_val;
+ chip->reg_direction[off / BANK_SZ] = reg_val;
ret = 0;
exit:
mutex_unlock(&chip->i2c_lock);
@@ -256,7 +299,7 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
offset = PCA957X_IN;
break;
}
- ret = pca953x_read_reg(chip, offset, &reg_val);
+ ret = pca953x_read_single(chip, offset, &reg_val, off);
mutex_unlock(&chip->i2c_lock);
if (ret < 0) {
/* NOTE: diagnostic already emitted; that's all we should
@@ -272,16 +315,18 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
{
struct pca953x_chip *chip;
- u32 reg_val;
+ u8 reg_val;
int ret, offset = 0;
chip = container_of(gc, struct pca953x_chip, gpio_chip);
mutex_lock(&chip->i2c_lock);
if (val)
- reg_val = chip->reg_output | (1u << off);
+ reg_val = chip->reg_output[off / BANK_SZ]
+ | (1u << (off % BANK_SZ));
else
- reg_val = chip->reg_output & ~(1u << off);
+ reg_val = chip->reg_output[off / BANK_SZ]
+ & ~(1u << (off % BANK_SZ));
switch (chip->chip_type) {
case PCA953X_TYPE:
@@ -291,11 +336,11 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
offset = PCA957X_OUT;
break;
}
- ret = pca953x_write_reg(chip, offset, reg_val);
+ ret = pca953x_write_single(chip, offset, reg_val, off);
if (ret)
goto exit;
- chip->reg_output = reg_val;
+ chip->reg_output[off / BANK_SZ] = reg_val;
exit:
mutex_unlock(&chip->i2c_lock);
}
@@ -326,21 +371,21 @@ static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
struct pca953x_chip *chip;
chip = container_of(gc, struct pca953x_chip, gpio_chip);
- return chip->irq_base + off;
+ return irq_create_mapping(chip->domain, off);
}
static void pca953x_irq_mask(struct irq_data *d)
{
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
- chip->irq_mask &= ~(1 << (d->irq - chip->irq_base));
+ chip->irq_mask[d->hwirq / BANK_SZ] &= ~(1 << (d->hwirq % BANK_SZ));
}
static void pca953x_irq_unmask(struct irq_data *d)
{
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
- chip->irq_mask |= 1 << (d->irq - chip->irq_base);
+ chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ);
}
static void pca953x_irq_bus_lock(struct irq_data *d)
@@ -353,17 +398,20 @@ static void pca953x_irq_bus_lock(struct irq_data *d)
static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
{
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
- u32 new_irqs;
- u32 level;
+ u8 new_irqs;
+ int level, i;
/* Look for any newly setup interrupt */
- new_irqs = chip->irq_trig_fall | chip->irq_trig_raise;
- new_irqs &= ~chip->reg_direction;
-
- while (new_irqs) {
- level = __ffs(new_irqs);
- pca953x_gpio_direction_input(&chip->gpio_chip, level);
- new_irqs &= ~(1 << level);
+ 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];
+
+ while (new_irqs) {
+ level = __ffs(new_irqs);
+ pca953x_gpio_direction_input(&chip->gpio_chip,
+ level + (BANK_SZ * i));
+ new_irqs &= ~(1 << level);
+ }
}
mutex_unlock(&chip->irq_lock);
@@ -372,8 +420,8 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
{
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
- u32 level = d->irq - chip->irq_base;
- u32 mask = 1 << level;
+ int bank_nb = d->hwirq / BANK_SZ;
+ u8 mask = 1 << (d->hwirq % BANK_SZ);
if (!(type & IRQ_TYPE_EDGE_BOTH)) {
dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
@@ -382,14 +430,14 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
}
if (type & IRQ_TYPE_EDGE_FALLING)
- chip->irq_trig_fall |= mask;
+ chip->irq_trig_fall[bank_nb] |= mask;
else
- chip->irq_trig_fall &= ~mask;
+ chip->irq_trig_fall[bank_nb] &= ~mask;
if (type & IRQ_TYPE_EDGE_RISING)
- chip->irq_trig_raise |= mask;
+ chip->irq_trig_raise[bank_nb] |= mask;
else
- chip->irq_trig_raise &= ~mask;
+ chip->irq_trig_raise[bank_nb] &= ~mask;
return 0;
}
@@ -403,13 +451,13 @@ static struct irq_chip pca953x_irq_chip = {
.irq_set_type = pca953x_irq_set_type,
};
-static u32 pca953x_irq_pending(struct pca953x_chip *chip)
+static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending)
{
- u32 cur_stat;
- u32 old_stat;
- u32 pending;
- u32 trigger;
- int ret, offset = 0;
+ u8 cur_stat[MAX_BANK];
+ u8 old_stat[MAX_BANK];
+ u8 pendings = 0;
+ u8 trigger[MAX_BANK], triggers = 0;
+ int ret, i, offset = 0;
switch (chip->chip_type) {
case PCA953X_TYPE:
@@ -419,60 +467,88 @@ static u32 pca953x_irq_pending(struct pca953x_chip *chip)
offset = PCA957X_IN;
break;
}
- ret = pca953x_read_reg(chip, offset, &cur_stat);
+ ret = pca953x_read_regs(chip, offset, cur_stat);
if (ret)
return 0;
/* Remove output pins from the equation */
- cur_stat &= chip->reg_direction;
+ for (i = 0; i < NBANK(chip); i++)
+ cur_stat[i] &= chip->reg_direction[i];
- old_stat = chip->irq_stat;
- trigger = (cur_stat ^ old_stat) & chip->irq_mask;
+ memcpy(old_stat, chip->irq_stat, NBANK(chip));
+
+ for (i = 0; i < NBANK(chip); i++) {
+ trigger[i] = (cur_stat[i] ^ old_stat[i]) & chip->irq_mask[i];
+ triggers += trigger[i];
+ }
- if (!trigger)
+ if (!triggers)
return 0;
- chip->irq_stat = cur_stat;
+ memcpy(chip->irq_stat, cur_stat, NBANK(chip));
- pending = (old_stat & chip->irq_trig_fall) |
- (cur_stat & chip->irq_trig_raise);
- pending &= trigger;
+ for (i = 0; i < NBANK(chip); i++) {
+ pending[i] = (old_stat[i] & chip->irq_trig_fall[i]) |
+ (cur_stat[i] & chip->irq_trig_raise[i]);
+ pending[i] &= trigger[i];
+ pendings += pending[i];
+ }
- return pending;
+ return pendings;
}
static irqreturn_t pca953x_irq_handler(int irq, void *devid)
{
struct pca953x_chip *chip = devid;
- u32 pending;
- u32 level;
-
- pending = pca953x_irq_pending(chip);
+ u8 pending[MAX_BANK];
+ u8 level;
+ int i;
- if (!pending)
+ if (!pca953x_irq_pending(chip, pending))
return IRQ_HANDLED;
- do {
- level = __ffs(pending);
- handle_nested_irq(level + chip->irq_base);
-
- pending &= ~(1 << level);
- } while (pending);
+ for (i = 0; i < NBANK(chip); i++) {
+ while (pending[i]) {
+ level = __ffs(pending[i]);
+ handle_nested_irq(irq_find_mapping(chip->domain,
+ level + (BANK_SZ * i)));
+ pending[i] &= ~(1 << level);
+ }
+ }
return IRQ_HANDLED;
}
+static int pca953x_gpio_irq_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ irq_clear_status_flags(irq, IRQ_NOREQUEST);
+ irq_set_chip_data(irq, d->host_data);
+ irq_set_chip(irq, &pca953x_irq_chip);
+ irq_set_nested_thread(irq, true);
+#ifdef CONFIG_ARM
+ set_irq_flags(irq, IRQF_VALID);
+#else
+ irq_set_noprobe(irq);
+#endif
+
+ return 0;
+}
+
+static const struct irq_domain_ops pca953x_irq_simple_ops = {
+ .map = pca953x_gpio_irq_map,
+ .xlate = irq_domain_xlate_twocell,
+};
+
static int pca953x_irq_setup(struct pca953x_chip *chip,
const struct i2c_device_id *id,
int irq_base)
{
struct i2c_client *client = chip->client;
- int ret, offset = 0;
- u32 temporary;
+ int ret, i, offset = 0;
if (irq_base != -1
&& (id->driver_data & PCA_INT)) {
- int lvl;
switch (chip->chip_type) {
case PCA953X_TYPE:
@@ -482,38 +558,29 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
offset = PCA957X_IN;
break;
}
- ret = pca953x_read_reg(chip, offset, &temporary);
- chip->irq_stat = temporary;
+ ret = pca953x_read_regs(chip, offset, chip->irq_stat);
if (ret)
- goto out_failed;
+ return ret;
/*
* There is no way to know which GPIO line generated the
* interrupt. We have to rely on the previous read for
* this purpose.
*/
- chip->irq_stat &= chip->reg_direction;
+ for (i = 0; i < NBANK(chip); i++)
+ chip->irq_stat[i] &= chip->reg_direction[i];
mutex_init(&chip->irq_lock);
- chip->irq_base = irq_alloc_descs(-1, irq_base, chip->gpio_chip.ngpio, -1);
- if (chip->irq_base < 0)
- goto out_failed;
-
- for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
- int irq = lvl + chip->irq_base;
-
- irq_clear_status_flags(irq, IRQ_NOREQUEST);
- irq_set_chip_data(irq, chip);
- irq_set_chip(irq, &pca953x_irq_chip);
- irq_set_nested_thread(irq, true);
-#ifdef CONFIG_ARM
- set_irq_flags(irq, IRQF_VALID);
-#else
- irq_set_noprobe(irq);
-#endif
- }
+ chip->domain = irq_domain_add_simple(client->dev.of_node,
+ chip->gpio_chip.ngpio,
+ irq_base,
+ &pca953x_irq_simple_ops,
+ NULL);
+ if (!chip->domain)
+ return -ENODEV;
- ret = request_threaded_irq(client->irq,
+ ret = devm_request_threaded_irq(&client->dev,
+ client->irq,
NULL,
pca953x_irq_handler,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
@@ -521,26 +588,15 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
if (ret) {
dev_err(&client->dev, "failed to request irq %d\n",
client->irq);
- goto out_failed;
+ return ret;
}
chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
}
return 0;
-
-out_failed:
- chip->irq_base = -1;
- return ret;
}
-static void pca953x_irq_teardown(struct pca953x_chip *chip)
-{
- if (chip->irq_base != -1) {
- irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio);
- free_irq(chip->client->irq, chip);
- }
-}
#else /* CONFIG_GPIO_PCA953X_IRQ */
static int pca953x_irq_setup(struct pca953x_chip *chip,
const struct i2c_device_id *id,
@@ -553,10 +609,6 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
return 0;
}
-
-static void pca953x_irq_teardown(struct pca953x_chip *chip)
-{
-}
#endif
/*
@@ -602,57 +654,71 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert)
}
#endif
-static int __devinit device_pca953x_init(struct pca953x_chip *chip, u32 invert)
+static int device_pca953x_init(struct pca953x_chip *chip, u32 invert)
{
int ret;
+ u8 val[MAX_BANK];
- ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
+ ret = pca953x_read_regs(chip, PCA953X_OUTPUT, chip->reg_output);
if (ret)
goto out;
- ret = pca953x_read_reg(chip, PCA953X_DIRECTION,
- &chip->reg_direction);
+ ret = pca953x_read_regs(chip, PCA953X_DIRECTION,
+ chip->reg_direction);
if (ret)
goto out;
/* set platform specific polarity inversion */
- ret = pca953x_write_reg(chip, PCA953X_INVERT, invert);
+ if (invert)
+ memset(val, 0xFF, NBANK(chip));
+ else
+ memset(val, 0, NBANK(chip));
+
+ ret = pca953x_write_regs(chip, PCA953X_INVERT, val);
out:
return ret;
}
-static int __devinit device_pca957x_init(struct pca953x_chip *chip, u32 invert)
+static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
{
int ret;
- u32 val = 0;
+ u8 val[MAX_BANK];
/* Let every port in proper state, that could save power */
- pca953x_write_reg(chip, PCA957X_PUPD, 0x0);
- pca953x_write_reg(chip, PCA957X_CFG, 0xffff);
- pca953x_write_reg(chip, PCA957X_OUT, 0x0);
-
- ret = pca953x_read_reg(chip, PCA957X_IN, &val);
+ memset(val, 0, NBANK(chip));
+ pca953x_write_regs(chip, PCA957X_PUPD, val);
+ memset(val, 0xFF, NBANK(chip));
+ pca953x_write_regs(chip, PCA957X_CFG, val);
+ memset(val, 0, NBANK(chip));
+ pca953x_write_regs(chip, PCA957X_OUT, val);
+
+ ret = pca953x_read_regs(chip, PCA957X_IN, val);
if (ret)
goto out;
- ret = pca953x_read_reg(chip, PCA957X_OUT, &chip->reg_output);
+ ret = pca953x_read_regs(chip, PCA957X_OUT, chip->reg_output);
if (ret)
goto out;
- ret = pca953x_read_reg(chip, PCA957X_CFG, &chip->reg_direction);
+ ret = pca953x_read_regs(chip, PCA957X_CFG, chip->reg_direction);
if (ret)
goto out;
/* set platform specific polarity inversion */
- pca953x_write_reg(chip, PCA957X_INVRT, invert);
+ if (invert)
+ memset(val, 0xFF, NBANK(chip));
+ else
+ memset(val, 0, NBANK(chip));
+ pca953x_write_regs(chip, PCA957X_INVRT, val);
/* To enable register 6, 7 to controll pull up and pull down */
- pca953x_write_reg(chip, PCA957X_BKEN, 0x202);
+ memset(val, 0x02, NBANK(chip));
+ pca953x_write_regs(chip, PCA957X_BKEN, val);
return 0;
out:
return ret;
}
-static int __devinit pca953x_probe(struct i2c_client *client,
+static int pca953x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pca953x_platform_data *pdata;
@@ -661,7 +727,8 @@ static int __devinit pca953x_probe(struct i2c_client *client,
int ret;
u32 invert = 0;
- chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
+ chip = devm_kzalloc(&client->dev,
+ sizeof(struct pca953x_chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
@@ -696,15 +763,15 @@ static int __devinit pca953x_probe(struct i2c_client *client,
else
ret = device_pca957x_init(chip, invert);
if (ret)
- goto out_failed;
+ return ret;
ret = pca953x_irq_setup(chip, id, irq_base);
if (ret)
- goto out_failed;
+ return ret;
ret = gpiochip_add(&chip->gpio_chip);
if (ret)
- goto out_failed_irq;
+ return ret;
if (pdata && pdata->setup) {
ret = pdata->setup(client, chip->gpio_chip.base,
@@ -715,12 +782,6 @@ static int __devinit pca953x_probe(struct i2c_client *client,
i2c_set_clientdata(client, chip);
return 0;
-
-out_failed_irq:
- pca953x_irq_teardown(chip);
-out_failed:
- kfree(chip);
- return ret;
}
static int pca953x_remove(struct i2c_client *client)
@@ -746,14 +807,42 @@ static int pca953x_remove(struct i2c_client *client)
return ret;
}
- pca953x_irq_teardown(chip);
- kfree(chip);
return 0;
}
+static const struct of_device_id pca953x_dt_ids[] = {
+ { .compatible = "nxp,pca9505", },
+ { .compatible = "nxp,pca9534", },
+ { .compatible = "nxp,pca9535", },
+ { .compatible = "nxp,pca9536", },
+ { .compatible = "nxp,pca9537", },
+ { .compatible = "nxp,pca9538", },
+ { .compatible = "nxp,pca9539", },
+ { .compatible = "nxp,pca9554", },
+ { .compatible = "nxp,pca9555", },
+ { .compatible = "nxp,pca9556", },
+ { .compatible = "nxp,pca9557", },
+ { .compatible = "nxp,pca9574", },
+ { .compatible = "nxp,pca9575", },
+
+ { .compatible = "maxim,max7310", },
+ { .compatible = "maxim,max7312", },
+ { .compatible = "maxim,max7313", },
+ { .compatible = "maxim,max7315", },
+
+ { .compatible = "ti,pca6107", },
+ { .compatible = "ti,tca6408", },
+ { .compatible = "ti,tca6416", },
+ { .compatible = "ti,tca6424", },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, pca953x_dt_ids);
+
static struct i2c_driver pca953x_driver = {
.driver = {
.name = "pca953x",
+ .of_match_table = pca953x_dt_ids,
},
.probe = pca953x_probe,
.remove = pca953x_remove,