aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpio/Kconfig1
-rw-r--r--drivers/gpio/gpio-tc3589x.c114
2 files changed, 24 insertions, 91 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index a86c49a605c6..5ad9e927baba 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -579,6 +579,7 @@ config GPIO_STP_XWAY
579config GPIO_TC3589X 579config GPIO_TC3589X
580 bool "TC3589X GPIOs" 580 bool "TC3589X GPIOs"
581 depends on MFD_TC3589X 581 depends on MFD_TC3589X
582 select GPIOLIB_IRQCHIP
582 help 583 help
583 This enables support for the GPIOs found on the TC3589X 584 This enables support for the GPIOs found on the TC3589X
584 I/O Expander. 585 I/O Expander.
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