aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-tc3589x.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2014-04-09 07:38:33 -0400
committerLinus Walleij <linus.walleij@linaro.org>2014-04-28 15:35:07 -0400
commitcf42f1cfe419f20425fc0c27b9930b6b51fe77b2 (patch)
treea744672ab6fb7de257ef82a073c72ce4e1b755e6 /drivers/gpio/gpio-tc3589x.c
parent5c81f2078b7be63be49916128cc86bc17be7f348 (diff)
gpio: tc3589x: use gpiolib irqchip helpers
Now that the gpiolib irqchip helpers can support nested, threaded IRQ handlers, switch the TC3589x driver over to using this new infrastructure. Tested on the Ux500. Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpio-tc3589x.c')
-rw-r--r--drivers/gpio/gpio-tc3589x.c114
1 files changed, 23 insertions, 91 deletions
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
index 4b0d8ccbe561..51f7cbd9ff71 100644
--- a/drivers/gpio/gpio-tc3589x.c
+++ b/drivers/gpio/gpio-tc3589x.c
@@ -12,8 +12,6 @@
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/gpio.h> 13#include <linux/gpio.h>
14#include <linux/of.h> 14#include <linux/of.h>
15#include <linux/irq.h>
16#include <linux/irqdomain.h>
17#include <linux/interrupt.h> 15#include <linux/interrupt.h>
18#include <linux/mfd/tc3589x.h> 16#include <linux/mfd/tc3589x.h>
19 17
@@ -31,7 +29,6 @@ struct tc3589x_gpio {
31 struct tc3589x *tc3589x; 29 struct tc3589x *tc3589x;
32 struct device *dev; 30 struct device *dev;
33 struct mutex irq_lock; 31 struct mutex irq_lock;
34 struct irq_domain *domain;
35 /* Caches of interrupt control registers for bus_lock */ 32 /* Caches of interrupt control registers for bus_lock */
36 u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS]; 33 u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
37 u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS]; 34 u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
@@ -92,30 +89,6 @@ static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
92 return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0); 89 return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0);
93} 90}
94 91
95/**
96 * tc3589x_gpio_irq_get_irq(): Map a hardware IRQ on a chip to a Linux IRQ
97 *
98 * @tc3589x_gpio: tc3589x_gpio_irq controller to operate on.
99 * @irq: index of the hardware interrupt requested in the chip IRQs
100 *
101 * Useful for drivers to request their own IRQs.
102 */
103static int tc3589x_gpio_irq_get_irq(struct tc3589x_gpio *tc3589x_gpio,
104 int hwirq)
105{
106 if (!tc3589x_gpio)
107 return -EINVAL;
108
109 return irq_create_mapping(tc3589x_gpio->domain, hwirq);
110}
111
112static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
113{
114 struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
115
116 return tc3589x_gpio_irq_get_irq(tc3589x_gpio, offset);
117}
118
119static struct gpio_chip template_chip = { 92static struct gpio_chip template_chip = {
120 .label = "tc3589x", 93 .label = "tc3589x",
121 .owner = THIS_MODULE, 94 .owner = THIS_MODULE,
@@ -123,13 +96,13 @@ static struct gpio_chip template_chip = {
123 .get = tc3589x_gpio_get, 96 .get = tc3589x_gpio_get,
124 .direction_output = tc3589x_gpio_direction_output, 97 .direction_output = tc3589x_gpio_direction_output,
125 .set = tc3589x_gpio_set, 98 .set = tc3589x_gpio_set,
126 .to_irq = tc3589x_gpio_to_irq,
127 .can_sleep = true, 99 .can_sleep = true,
128}; 100};
129 101
130static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type) 102static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
131{ 103{
132 struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); 104 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
105 struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
133 int offset = d->hwirq; 106 int offset = d->hwirq;
134 int regoffset = offset / 8; 107 int regoffset = offset / 8;
135 int mask = 1 << (offset % 8); 108 int mask = 1 << (offset % 8);
@@ -156,14 +129,16 @@ static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
156 129
157static void tc3589x_gpio_irq_lock(struct irq_data *d) 130static void tc3589x_gpio_irq_lock(struct irq_data *d)
158{ 131{
159 struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); 132 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
133 struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
160 134
161 mutex_lock(&tc3589x_gpio->irq_lock); 135 mutex_lock(&tc3589x_gpio->irq_lock);
162} 136}
163 137
164static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d) 138static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
165{ 139{
166 struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); 140 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
141 struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
167 struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; 142 struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
168 static const u8 regmap[] = { 143 static const u8 regmap[] = {
169 [REG_IBE] = TC3589x_GPIOIBE0, 144 [REG_IBE] = TC3589x_GPIOIBE0,
@@ -191,7 +166,8 @@ static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
191 166
192static void tc3589x_gpio_irq_mask(struct irq_data *d) 167static void tc3589x_gpio_irq_mask(struct irq_data *d)
193{ 168{
194 struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); 169 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
170 struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
195 int offset = d->hwirq; 171 int offset = d->hwirq;
196 int regoffset = offset / 8; 172 int regoffset = offset / 8;
197 int mask = 1 << (offset % 8); 173 int mask = 1 << (offset % 8);
@@ -201,7 +177,8 @@ static void tc3589x_gpio_irq_mask(struct irq_data *d)
201 177
202static void tc3589x_gpio_irq_unmask(struct irq_data *d) 178static void tc3589x_gpio_irq_unmask(struct irq_data *d)
203{ 179{
204 struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); 180 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
181 struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
205 int offset = d->hwirq; 182 int offset = d->hwirq;
206 int regoffset = offset / 8; 183 int regoffset = offset / 8;
207 int mask = 1 << (offset % 8); 184 int mask = 1 << (offset % 8);
@@ -239,7 +216,8 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
239 while (stat) { 216 while (stat) {
240 int bit = __ffs(stat); 217 int bit = __ffs(stat);
241 int line = i * 8 + bit; 218 int line = i * 8 + bit;
242 int irq = tc3589x_gpio_irq_get_irq(tc3589x_gpio, line); 219 int irq = irq_find_mapping(tc3589x_gpio->chip.irqdomain,
220 line);
243 221
244 handle_nested_irq(irq); 222 handle_nested_irq(irq);
245 stat &= ~(1 << bit); 223 stat &= ~(1 << bit);
@@ -251,59 +229,6 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
251 return IRQ_HANDLED; 229 return IRQ_HANDLED;
252} 230}
253 231
254static int tc3589x_gpio_irq_map(struct irq_domain *d, unsigned int irq,
255 irq_hw_number_t hwirq)
256{
257 struct tc3589x *tc3589x_gpio = d->host_data;
258
259 irq_set_chip_data(irq, tc3589x_gpio);
260 irq_set_chip_and_handler(irq, &tc3589x_gpio_irq_chip,
261 handle_simple_irq);
262 irq_set_nested_thread(irq, 1);
263#ifdef CONFIG_ARM
264 set_irq_flags(irq, IRQF_VALID);
265#else
266 irq_set_noprobe(irq);
267#endif
268
269 return 0;
270}
271
272static void tc3589x_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)
273{
274#ifdef CONFIG_ARM
275 set_irq_flags(irq, 0);
276#endif
277 irq_set_chip_and_handler(irq, NULL, NULL);
278 irq_set_chip_data(irq, NULL);
279}
280
281static struct irq_domain_ops tc3589x_irq_ops = {
282 .map = tc3589x_gpio_irq_map,
283 .unmap = tc3589x_gpio_irq_unmap,
284 .xlate = irq_domain_xlate_twocell,
285};
286
287static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio,
288 struct device_node *np)
289{
290 /*
291 * If this results in a linear domain, irq_create_mapping() will
292 * take care of allocating IRQ descriptors at runtime. When a base
293 * is provided, the IRQ descriptors will be allocated when the
294 * domain is instantiated.
295 */
296 tc3589x_gpio->domain = irq_domain_add_simple(np,
297 tc3589x_gpio->chip.ngpio, 0, &tc3589x_irq_ops,
298 tc3589x_gpio);
299 if (!tc3589x_gpio->domain) {
300 dev_err(tc3589x_gpio->dev, "Failed to create irqdomain\n");
301 return -ENOSYS;
302 }
303
304 return 0;
305}
306
307static int tc3589x_gpio_probe(struct platform_device *pdev) 232static int tc3589x_gpio_probe(struct platform_device *pdev)
308{ 233{
309 struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); 234 struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
@@ -349,10 +274,6 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
349 if (ret < 0) 274 if (ret < 0)
350 return ret; 275 return ret;
351 276
352 ret = tc3589x_gpio_irq_init(tc3589x_gpio, np);
353 if (ret)
354 return ret;
355
356 ret = devm_request_threaded_irq(&pdev->dev, 277 ret = devm_request_threaded_irq(&pdev->dev,
357 irq, NULL, tc3589x_gpio_irq, 278 irq, NULL, tc3589x_gpio_irq,
358 IRQF_ONESHOT, "tc3589x-gpio", 279 IRQF_ONESHOT, "tc3589x-gpio",
@@ -368,6 +289,17 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
368 return ret; 289 return ret;
369 } 290 }
370 291
292 ret = gpiochip_irqchip_add(&tc3589x_gpio->chip,
293 &tc3589x_gpio_irq_chip,
294 0,
295 handle_simple_irq,
296 IRQ_TYPE_NONE);
297 if (ret) {
298 dev_err(&pdev->dev,
299 "could not connect irqchip to gpiochip\n");
300 return ret;
301 }
302
371 if (pdata && pdata->setup) 303 if (pdata && pdata->setup)
372 pdata->setup(tc3589x, tc3589x_gpio->chip.base); 304 pdata->setup(tc3589x, tc3589x_gpio->chip.base);
373 305