summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpio-pcf857x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpio-pcf857x.c')
-rw-r--r--drivers/gpio/gpio-pcf857x.c118
1 files changed, 57 insertions, 61 deletions
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index cec2f2c78255..3de1d3ad7472 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -7,18 +7,16 @@
#include <linux/gpio/driver.h>
#include <linux/i2c.h>
-#include <linux/platform_data/pcf857x.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
+#include <linux/property.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
-
static const struct i2c_device_id pcf857x_id[] = {
{ "pcf8574", 8 },
{ "pcf8574a", 8 },
@@ -37,7 +35,6 @@ static const struct i2c_device_id pcf857x_id[] = {
};
MODULE_DEVICE_TABLE(i2c, pcf857x_id);
-#ifdef CONFIG_OF
static const struct of_device_id pcf857x_of_table[] = {
{ .compatible = "nxp,pcf8574" },
{ .compatible = "nxp,pcf8574a" },
@@ -55,7 +52,6 @@ static const struct of_device_id pcf857x_of_table[] = {
{ }
};
MODULE_DEVICE_TABLE(of, pcf857x_of_table);
-#endif
/*
* The pcf857x, pca857x, and pca967x chips only expose one read and one
@@ -73,11 +69,11 @@ struct pcf857x {
struct gpio_chip chip;
struct i2c_client *client;
struct mutex lock; /* protect 'out' */
- unsigned out; /* software latch */
- unsigned status; /* current status */
- unsigned irq_enabled; /* enabled irqs */
+ unsigned int out; /* software latch */
+ unsigned int status; /* current status */
+ unsigned int irq_enabled; /* enabled irqs */
- int (*write)(struct i2c_client *client, unsigned data);
+ int (*write)(struct i2c_client *client, unsigned int data);
int (*read)(struct i2c_client *client);
};
@@ -85,19 +81,19 @@ struct pcf857x {
/* Talk to 8-bit I/O expander */
-static int i2c_write_le8(struct i2c_client *client, unsigned data)
+static int i2c_write_le8(struct i2c_client *client, unsigned int data)
{
return i2c_smbus_write_byte(client, data);
}
static int i2c_read_le8(struct i2c_client *client)
{
- return (int)i2c_smbus_read_byte(client);
+ return i2c_smbus_read_byte(client);
}
/* Talk to 16-bit I/O expander */
-static int i2c_write_le16(struct i2c_client *client, unsigned word)
+static int i2c_write_le16(struct i2c_client *client, unsigned int word)
{
u8 buf[2] = { word & 0xff, word >> 8, };
int status;
@@ -119,10 +115,10 @@ static int i2c_read_le16(struct i2c_client *client)
/*-------------------------------------------------------------------------*/
-static int pcf857x_input(struct gpio_chip *chip, unsigned offset)
+static int pcf857x_input(struct gpio_chip *chip, unsigned int offset)
{
- struct pcf857x *gpio = gpiochip_get_data(chip);
- int status;
+ struct pcf857x *gpio = gpiochip_get_data(chip);
+ int status;
mutex_lock(&gpio->lock);
gpio->out |= (1 << offset);
@@ -132,20 +128,35 @@ static int pcf857x_input(struct gpio_chip *chip, unsigned offset)
return status;
}
-static int pcf857x_get(struct gpio_chip *chip, unsigned offset)
+static int pcf857x_get(struct gpio_chip *chip, unsigned int offset)
{
- struct pcf857x *gpio = gpiochip_get_data(chip);
- int value;
+ struct pcf857x *gpio = gpiochip_get_data(chip);
+ int value;
value = gpio->read(gpio->client);
return (value < 0) ? value : !!(value & (1 << offset));
}
-static int pcf857x_output(struct gpio_chip *chip, unsigned offset, int value)
+static int pcf857x_get_multiple(struct gpio_chip *chip, unsigned long *mask,
+ unsigned long *bits)
{
- struct pcf857x *gpio = gpiochip_get_data(chip);
- unsigned bit = 1 << offset;
- int status;
+ struct pcf857x *gpio = gpiochip_get_data(chip);
+ int value = gpio->read(gpio->client);
+
+ if (value < 0)
+ return value;
+
+ *bits &= ~*mask;
+ *bits |= value & *mask;
+
+ return 0;
+}
+
+static int pcf857x_output(struct gpio_chip *chip, unsigned int offset, int value)
+{
+ struct pcf857x *gpio = gpiochip_get_data(chip);
+ unsigned int bit = 1 << offset;
+ int status;
mutex_lock(&gpio->lock);
if (value)
@@ -158,16 +169,28 @@ static int pcf857x_output(struct gpio_chip *chip, unsigned offset, int value)
return status;
}
-static void pcf857x_set(struct gpio_chip *chip, unsigned offset, int value)
+static void pcf857x_set(struct gpio_chip *chip, unsigned int offset, int value)
{
pcf857x_output(chip, offset, value);
}
+static void pcf857x_set_multiple(struct gpio_chip *chip, unsigned long *mask,
+ unsigned long *bits)
+{
+ struct pcf857x *gpio = gpiochip_get_data(chip);
+
+ mutex_lock(&gpio->lock);
+ gpio->out &= ~*mask;
+ gpio->out |= *bits & *mask;
+ gpio->write(gpio->client, gpio->out);
+ mutex_unlock(&gpio->lock);
+}
+
/*-------------------------------------------------------------------------*/
static irqreturn_t pcf857x_irq(int irq, void *data)
{
- struct pcf857x *gpio = data;
+ struct pcf857x *gpio = data;
unsigned long change, i, status;
status = gpio->read(gpio->client);
@@ -250,18 +273,11 @@ static const struct irq_chip pcf857x_irq_chip = {
static int pcf857x_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
- struct pcf857x_platform_data *pdata = dev_get_platdata(&client->dev);
- struct device_node *np = client->dev.of_node;
- struct pcf857x *gpio;
- unsigned int n_latch = 0;
- int status;
-
- if (IS_ENABLED(CONFIG_OF) && np)
- of_property_read_u32(np, "lines-initial-states", &n_latch);
- else if (pdata)
- n_latch = pdata->n_latch;
- else
- dev_dbg(&client->dev, "no platform data\n");
+ struct pcf857x *gpio;
+ unsigned int n_latch = 0;
+ int status;
+
+ device_property_read_u32(&client->dev, "lines-initial-states", &n_latch);
/* Allocate, initialize, and register this gpio_chip. */
gpio = devm_kzalloc(&client->dev, sizeof(*gpio), GFP_KERNEL);
@@ -270,12 +286,14 @@ static int pcf857x_probe(struct i2c_client *client)
mutex_init(&gpio->lock);
- gpio->chip.base = pdata ? pdata->gpio_base : -1;
+ gpio->chip.base = -1;
gpio->chip.can_sleep = true;
gpio->chip.parent = &client->dev;
gpio->chip.owner = THIS_MODULE;
gpio->chip.get = pcf857x_get;
+ gpio->chip.get_multiple = pcf857x_get_multiple;
gpio->chip.set = pcf857x_set;
+ gpio->chip.set_multiple = pcf857x_set_multiple;
gpio->chip.direction_input = pcf857x_input;
gpio->chip.direction_output = pcf857x_output;
gpio->chip.ngpio = id->driver_data;
@@ -377,17 +395,6 @@ static int pcf857x_probe(struct i2c_client *client)
if (status < 0)
goto fail;
- /* Let platform code set up the GPIOs and their users.
- * Now is the first time anyone could use them.
- */
- if (pdata && pdata->setup) {
- status = pdata->setup(client,
- gpio->chip.base, gpio->chip.ngpio,
- pdata->context);
- if (status < 0)
- dev_warn(&client->dev, "setup --> %d\n", status);
- }
-
dev_info(&client->dev, "probed\n");
return 0;
@@ -399,16 +406,6 @@ fail:
return status;
}
-static void pcf857x_remove(struct i2c_client *client)
-{
- struct pcf857x_platform_data *pdata = dev_get_platdata(&client->dev);
- struct pcf857x *gpio = i2c_get_clientdata(client);
-
- if (pdata && pdata->teardown)
- pdata->teardown(client, gpio->chip.base, gpio->chip.ngpio,
- pdata->context);
-}
-
static void pcf857x_shutdown(struct i2c_client *client)
{
struct pcf857x *gpio = i2c_get_clientdata(client);
@@ -420,10 +417,9 @@ static void pcf857x_shutdown(struct i2c_client *client)
static struct i2c_driver pcf857x_driver = {
.driver = {
.name = "pcf857x",
- .of_match_table = of_match_ptr(pcf857x_of_table),
+ .of_match_table = pcf857x_of_table,
},
.probe_new = pcf857x_probe,
- .remove = pcf857x_remove,
.shutdown = pcf857x_shutdown,
.id_table = pcf857x_id,
};