aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-74x164.c
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2012-09-10 16:35:39 -0400
committerLinus Walleij <linus.walleij@linaro.org>2012-09-11 17:49:32 -0400
commit20bc4d5d565159eb2b942bf4b7fae86fba94e32c (patch)
tree863f5b79177c3e0bbb3b35268edb190d8acfe8fb /drivers/gpio/gpio-74x164.c
parenta7ff477bb7e5ec9536e8aac02e8856a4bcc595a3 (diff)
gpio: 74x164: Add support for the daisy-chaining
The shift registers have an output pin that, when enabled, propagates the values of its internal register to the pins. If another value comes to the register while the output pin is disabled, this new value will makae the older shift into the next register in the chain. This patch adds support for daisy-chaining the registers, using the regular SPI chip select mechanism to manage the output pin, and the registers-number dt property to set the number of chained registers. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpio-74x164.c')
-rw-r--r--drivers/gpio/gpio-74x164.c68
1 files changed, 61 insertions, 7 deletions
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index 2e31bd35769a..ed3e55161bdc 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -14,14 +14,18 @@
14#include <linux/spi/spi.h> 14#include <linux/spi/spi.h>
15#include <linux/spi/74x164.h> 15#include <linux/spi/74x164.h>
16#include <linux/gpio.h> 16#include <linux/gpio.h>
17#include <linux/of_gpio.h>
17#include <linux/slab.h> 18#include <linux/slab.h>
18#include <linux/module.h> 19#include <linux/module.h>
19 20
21#define GEN_74X164_NUMBER_GPIOS 8
22
20struct gen_74x164_chip { 23struct gen_74x164_chip {
21 struct spi_device *spi; 24 struct spi_device *spi;
25 u8 *buffer;
22 struct gpio_chip gpio_chip; 26 struct gpio_chip gpio_chip;
23 struct mutex lock; 27 struct mutex lock;
24 u8 port_config; 28 u32 registers;
25}; 29};
26 30
27static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc) 31static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)
@@ -31,17 +35,47 @@ static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)
31 35
32static int __gen_74x164_write_config(struct gen_74x164_chip *chip) 36static int __gen_74x164_write_config(struct gen_74x164_chip *chip)
33{ 37{
34 return spi_write(chip->spi, 38 struct spi_message message;
35 &chip->port_config, sizeof(chip->port_config)); 39 struct spi_transfer *msg_buf;
40 int i, ret = 0;
41
42 msg_buf = kzalloc(chip->registers * sizeof(struct spi_transfer),
43 GFP_KERNEL);
44 if (!msg_buf)
45 return -ENOMEM;
46
47 spi_message_init(&message);
48
49 /*
50 * Since the registers are chained, every byte sent will make
51 * the previous byte shift to the next register in the
52 * chain. Thus, the first byte send will end up in the last
53 * register at the end of the transfer. So, to have a logical
54 * numbering, send the bytes in reverse order so that the last
55 * byte of the buffer will end up in the last register.
56 */
57 for (i = chip->registers - 1; i >= 0; i--) {
58 msg_buf[i].tx_buf = chip->buffer +i;
59 msg_buf[i].len = sizeof(u8);
60 spi_message_add_tail(msg_buf + i, &message);
61 }
62
63 ret = spi_sync(chip->spi, &message);
64
65 kfree(msg_buf);
66
67 return ret;
36} 68}
37 69
38static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset) 70static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
39{ 71{
40 struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc); 72 struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
73 u8 bank = offset / 8;
74 u8 pin = offset % 8;
41 int ret; 75 int ret;
42 76
43 mutex_lock(&chip->lock); 77 mutex_lock(&chip->lock);
44 ret = (chip->port_config >> offset) & 0x1; 78 ret = (chip->buffer[bank] >> pin) & 0x1;
45 mutex_unlock(&chip->lock); 79 mutex_unlock(&chip->lock);
46 80
47 return ret; 81 return ret;
@@ -51,12 +85,14 @@ static void gen_74x164_set_value(struct gpio_chip *gc,
51 unsigned offset, int val) 85 unsigned offset, int val)
52{ 86{
53 struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc); 87 struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
88 u8 bank = offset / 8;
89 u8 pin = offset % 8;
54 90
55 mutex_lock(&chip->lock); 91 mutex_lock(&chip->lock);
56 if (val) 92 if (val)
57 chip->port_config |= (1 << offset); 93 chip->buffer[bank] |= (1 << pin);
58 else 94 else
59 chip->port_config &= ~(1 << offset); 95 chip->buffer[bank] &= ~(1 << pin);
60 96
61 __gen_74x164_write_config(chip); 97 __gen_74x164_write_config(chip);
62 mutex_unlock(&chip->lock); 98 mutex_unlock(&chip->lock);
@@ -75,6 +111,11 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
75 struct gen_74x164_chip_platform_data *pdata; 111 struct gen_74x164_chip_platform_data *pdata;
76 int ret; 112 int ret;
77 113
114 if (!spi->dev.of_node) {
115 dev_err(&spi->dev, "No device tree data available.\n");
116 return -EINVAL;
117 }
118
78 /* 119 /*
79 * bits_per_word cannot be configured in platform data 120 * bits_per_word cannot be configured in platform data
80 */ 121 */
@@ -104,7 +145,20 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
104 chip->gpio_chip.direction_output = gen_74x164_direction_output; 145 chip->gpio_chip.direction_output = gen_74x164_direction_output;
105 chip->gpio_chip.get = gen_74x164_get_value; 146 chip->gpio_chip.get = gen_74x164_get_value;
106 chip->gpio_chip.set = gen_74x164_set_value; 147 chip->gpio_chip.set = gen_74x164_set_value;
107 chip->gpio_chip.ngpio = 8; 148
149 if (of_property_read_u32(spi->dev.of_node, "registers-number", &chip->registers)) {
150 dev_err(&spi->dev, "Missing registers-number property in the DT.\n");
151 ret = -EINVAL;
152 goto exit_destroy;
153 }
154
155 chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers;
156 chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL);
157 if (!chip->buffer) {
158 ret = -ENOMEM;
159 goto exit_destroy;
160 }
161
108 chip->gpio_chip.can_sleep = 1; 162 chip->gpio_chip.can_sleep = 1;
109 chip->gpio_chip.dev = &spi->dev; 163 chip->gpio_chip.dev = &spi->dev;
110 chip->gpio_chip.owner = THIS_MODULE; 164 chip->gpio_chip.owner = THIS_MODULE;