aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMilo Kim <milo.kim@ti.com>2013-12-05 21:18:42 -0500
committerLee Jones <lee.jones@linaro.org>2014-01-21 03:27:57 -0500
commit0cc59b9d98d554168915b3765a14e8b4ad75918c (patch)
tree7939471290934e3482ecc8bc5a679e455159c205 /drivers
parent25a7a6f4a200e2eb04d87fb1c06130b1a85aa688 (diff)
gpio: add LP3943 I2C GPIO expander driver
This is one of LP3943 MFD driver. LP3943 is configurable as a GPIO expander, up to 16 GPIOs. * Application note: how to configure LP3943 as a GPIO expander http://www.ti.com/lit/an/snva287a/snva287a.pdf * Supported GPIO controller operations request, free, direction_input, direction_output, get and set * GPIO direction register not supported LP3943 doesn't have the GPIO direction register. It only provides input and output status registers. So, private data for the direction should be handled manually. This variable is updated whenever the direction is changed and used in 'get' operation. * Pin assignment A driver data, 'pin_used' is checked when a GPIO is requested. If the GPIO is already assigned, then returns as failure. If the GPIO is available, 'pin_used' is set. When the GPIO is not used anymore, then it is cleared. It is defined as unsigned long type for atomic bit operation APIs, but only LSB 16bits are used because LP3943 has 16 outputs. Signed-off-by: Milo Kim <milo.kim@ti.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/Kconfig8
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-lp3943.c242
3 files changed, 251 insertions, 0 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 0f0444475bf0..7ef68e65918f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -381,6 +381,14 @@ config GPIO_ARIZONA
381 help 381 help
382 Support for GPIOs on Wolfson Arizona class devices. 382 Support for GPIOs on Wolfson Arizona class devices.
383 383
384config GPIO_LP3943
385 tristate "TI/National Semiconductor LP3943 GPIO expander"
386 depends on MFD_LP3943
387 help
388 GPIO driver for LP3943 MFD.
389 LP3943 can be used as a GPIO expander which provides up to 16 GPIOs.
390 Open drain outputs are required for this usage.
391
384config GPIO_MAX7300 392config GPIO_MAX7300
385 tristate "Maxim MAX7300 GPIO expander" 393 tristate "Maxim MAX7300 GPIO expander"
386 depends on I2C 394 depends on I2C
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 7971e36b8b12..95927b61c201 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
35obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o 35obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
36obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o 36obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o
37obj-$(CONFIG_GPIO_INTEL_MID) += gpio-intel-mid.o 37obj-$(CONFIG_GPIO_INTEL_MID) += gpio-intel-mid.o
38obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o
38obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o 39obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o
39obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o 40obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o
40obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o 41obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o
diff --git a/drivers/gpio/gpio-lp3943.c b/drivers/gpio/gpio-lp3943.c
new file mode 100644
index 000000000000..7b8db88ebb7b
--- /dev/null
+++ b/drivers/gpio/gpio-lp3943.c
@@ -0,0 +1,242 @@
1/*
2 * TI/National Semiconductor LP3943 GPIO driver
3 *
4 * Copyright 2013 Texas Instruments
5 *
6 * Author: Milo Kim <milo.kim@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2.
11 */
12
13#include <linux/bitops.h>
14#include <linux/err.h>
15#include <linux/gpio.h>
16#include <linux/i2c.h>
17#include <linux/mfd/lp3943.h>
18#include <linux/module.h>
19#include <linux/platform_device.h>
20#include <linux/slab.h>
21
22enum lp3943_gpios {
23 LP3943_GPIO1,
24 LP3943_GPIO2,
25 LP3943_GPIO3,
26 LP3943_GPIO4,
27 LP3943_GPIO5,
28 LP3943_GPIO6,
29 LP3943_GPIO7,
30 LP3943_GPIO8,
31 LP3943_GPIO9,
32 LP3943_GPIO10,
33 LP3943_GPIO11,
34 LP3943_GPIO12,
35 LP3943_GPIO13,
36 LP3943_GPIO14,
37 LP3943_GPIO15,
38 LP3943_GPIO16,
39 LP3943_MAX_GPIO,
40};
41
42struct lp3943_gpio {
43 struct gpio_chip chip;
44 struct lp3943 *lp3943;
45 u16 input_mask; /* 1 = GPIO is input direction, 0 = output */
46};
47
48static inline struct lp3943_gpio *to_lp3943_gpio(struct gpio_chip *_chip)
49{
50 return container_of(_chip, struct lp3943_gpio, chip);
51}
52
53static int lp3943_gpio_request(struct gpio_chip *chip, unsigned offset)
54{
55 struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
56 struct lp3943 *lp3943 = lp3943_gpio->lp3943;
57
58 /* Return an error if the pin is already assigned */
59 if (test_and_set_bit(offset, &lp3943->pin_used))
60 return -EBUSY;
61
62 return 0;
63}
64
65static void lp3943_gpio_free(struct gpio_chip *chip, unsigned offset)
66{
67 struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
68 struct lp3943 *lp3943 = lp3943_gpio->lp3943;
69
70 clear_bit(offset, &lp3943->pin_used);
71}
72
73static int lp3943_gpio_set_mode(struct lp3943_gpio *lp3943_gpio, u8 offset,
74 u8 val)
75{
76 struct lp3943 *lp3943 = lp3943_gpio->lp3943;
77 const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
78
79 return lp3943_update_bits(lp3943, mux[offset].reg, mux[offset].mask,
80 val << mux[offset].shift);
81}
82
83static int lp3943_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
84{
85 struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
86
87 lp3943_gpio->input_mask |= BIT(offset);
88
89 return lp3943_gpio_set_mode(lp3943_gpio, offset, LP3943_GPIO_IN);
90}
91
92static int lp3943_get_gpio_in_status(struct lp3943_gpio *lp3943_gpio,
93 struct gpio_chip *chip, unsigned offset)
94{
95 u8 addr, read;
96 int err;
97
98 switch (offset) {
99 case LP3943_GPIO1 ... LP3943_GPIO8:
100 addr = LP3943_REG_GPIO_A;
101 break;
102 case LP3943_GPIO9 ... LP3943_GPIO16:
103 addr = LP3943_REG_GPIO_B;
104 offset = offset - 8;
105 break;
106 default:
107 return -EINVAL;
108 }
109
110 err = lp3943_read_byte(lp3943_gpio->lp3943, addr, &read);
111 if (err)
112 return err;
113
114 return !!(read & BIT(offset));
115}
116
117static int lp3943_get_gpio_out_status(struct lp3943_gpio *lp3943_gpio,
118 struct gpio_chip *chip, unsigned offset)
119{
120 struct lp3943 *lp3943 = lp3943_gpio->lp3943;
121 const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
122 u8 read;
123 int err;
124
125 err = lp3943_read_byte(lp3943, mux[offset].reg, &read);
126 if (err)
127 return err;
128
129 read = (read & mux[offset].mask) >> mux[offset].shift;
130
131 if (read == LP3943_GPIO_OUT_HIGH)
132 return 1;
133 else if (read == LP3943_GPIO_OUT_LOW)
134 return 0;
135 else
136 return -EINVAL;
137}
138
139static int lp3943_gpio_get(struct gpio_chip *chip, unsigned offset)
140{
141 struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
142
143 /*
144 * Limitation:
145 * LP3943 doesn't have the GPIO direction register. It provides
146 * only input and output status registers.
147 * So, direction info is required to handle the 'get' operation.
148 * This variable is updated whenever the direction is changed and
149 * it is used here.
150 */
151
152 if (lp3943_gpio->input_mask & BIT(offset))
153 return lp3943_get_gpio_in_status(lp3943_gpio, chip, offset);
154 else
155 return lp3943_get_gpio_out_status(lp3943_gpio, chip, offset);
156}
157
158static void lp3943_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
159{
160 struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
161 u8 data;
162
163 if (value)
164 data = LP3943_GPIO_OUT_HIGH;
165 else
166 data = LP3943_GPIO_OUT_LOW;
167
168 lp3943_gpio_set_mode(lp3943_gpio, offset, data);
169}
170
171static int lp3943_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
172 int value)
173{
174 struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
175
176 lp3943_gpio_set(chip, offset, value);
177 lp3943_gpio->input_mask &= ~BIT(offset);
178
179 return 0;
180}
181
182static const struct gpio_chip lp3943_gpio_chip = {
183 .label = "lp3943",
184 .owner = THIS_MODULE,
185 .request = lp3943_gpio_request,
186 .free = lp3943_gpio_free,
187 .direction_input = lp3943_gpio_direction_input,
188 .get = lp3943_gpio_get,
189 .direction_output = lp3943_gpio_direction_output,
190 .set = lp3943_gpio_set,
191 .base = -1,
192 .ngpio = LP3943_MAX_GPIO,
193 .can_sleep = 1,
194};
195
196static int lp3943_gpio_probe(struct platform_device *pdev)
197{
198 struct lp3943 *lp3943 = dev_get_drvdata(pdev->dev.parent);
199 struct lp3943_gpio *lp3943_gpio;
200
201 lp3943_gpio = devm_kzalloc(&pdev->dev, sizeof(*lp3943_gpio),
202 GFP_KERNEL);
203 if (!lp3943_gpio)
204 return -ENOMEM;
205
206 lp3943_gpio->lp3943 = lp3943;
207 lp3943_gpio->chip = lp3943_gpio_chip;
208 lp3943_gpio->chip.dev = &pdev->dev;
209
210 platform_set_drvdata(pdev, lp3943_gpio);
211
212 return gpiochip_add(&lp3943_gpio->chip);
213}
214
215static int lp3943_gpio_remove(struct platform_device *pdev)
216{
217 struct lp3943_gpio *lp3943_gpio = platform_get_drvdata(pdev);
218
219 return gpiochip_remove(&lp3943_gpio->chip);
220}
221
222static const struct of_device_id lp3943_gpio_of_match[] = {
223 { .compatible = "ti,lp3943-gpio", },
224 { }
225};
226MODULE_DEVICE_TABLE(of, lp3943_gpio_of_match);
227
228static struct platform_driver lp3943_gpio_driver = {
229 .probe = lp3943_gpio_probe,
230 .remove = lp3943_gpio_remove,
231 .driver = {
232 .name = "lp3943-gpio",
233 .owner = THIS_MODULE,
234 .of_match_table = of_match_ptr(lp3943_gpio_of_match),
235 },
236};
237module_platform_driver(lp3943_gpio_driver);
238
239MODULE_DESCRIPTION("LP3943 GPIO driver");
240MODULE_ALIAS("platform:lp3943-gpio");
241MODULE_AUTHOR("Milo Kim");
242MODULE_LICENSE("GPL");