aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2014-09-26 08:19:52 -0400
committerLinus Walleij <linus.walleij@linaro.org>2014-09-26 08:39:08 -0400
commit3f97d5fcf99cb87f590ffe1d9422b2a26a8ef3ed (patch)
treefd68ce986e6042edebb64bf8ad51aa7f222503f7 /drivers/gpio
parent83141a771975f4e54402ab05e5cbbc3c56f45bdd (diff)
gpio: handle also nested irqchips in the chained handler set-up
To unify how we connect cascaded IRQ chips to parent IRQs, if NULL us passed as handler to the gpiochip_set_chained_irqchip() function, assume the chips is nested rather than chained, and we still get the parent set up correctly by way of this function call. Alter the drivers for tc3589x and stmpe to use this to set up their chained handlers as a demonstration of the usage. Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-stmpe.c18
-rw-r--r--drivers/gpio/gpio-tc3589x.c5
-rw-r--r--drivers/gpio/gpiolib.c34
3 files changed, 36 insertions, 21 deletions
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
index 845025a57240..b0b342787c37 100644
--- a/drivers/gpio/gpio-stmpe.c
+++ b/drivers/gpio/gpio-stmpe.c
@@ -308,6 +308,12 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
308 if (ret) 308 if (ret)
309 goto out_free; 309 goto out_free;
310 310
311 ret = gpiochip_add(&stmpe_gpio->chip);
312 if (ret) {
313 dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
314 goto out_disable;
315 }
316
311 if (irq > 0) { 317 if (irq > 0) {
312 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, 318 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
313 stmpe_gpio_irq, IRQF_ONESHOT, 319 stmpe_gpio_irq, IRQF_ONESHOT,
@@ -324,14 +330,13 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
324 if (ret) { 330 if (ret) {
325 dev_err(&pdev->dev, 331 dev_err(&pdev->dev,
326 "could not connect irqchip to gpiochip\n"); 332 "could not connect irqchip to gpiochip\n");
327 return ret; 333 goto out_disable;
328 } 334 }
329 }
330 335
331 ret = gpiochip_add(&stmpe_gpio->chip); 336 gpiochip_set_chained_irqchip(&stmpe_gpio->chip,
332 if (ret) { 337 &stmpe_gpio_irq_chip,
333 dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); 338 irq,
334 goto out_disable; 339 NULL);
335 } 340 }
336 341
337 if (pdata && pdata->setup) 342 if (pdata && pdata->setup)
@@ -343,6 +348,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
343 348
344out_disable: 349out_disable:
345 stmpe_disable(stmpe, STMPE_BLOCK_GPIO); 350 stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
351 gpiochip_remove(&stmpe_gpio->chip);
346out_free: 352out_free:
347 kfree(stmpe_gpio); 353 kfree(stmpe_gpio);
348 return ret; 354 return ret;
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
index 7324869c38e0..ae0f6466eb09 100644
--- a/drivers/gpio/gpio-tc3589x.c
+++ b/drivers/gpio/gpio-tc3589x.c
@@ -300,6 +300,11 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
300 return ret; 300 return ret;
301 } 301 }
302 302
303 gpiochip_set_chained_irqchip(&tc3589x_gpio->chip,
304 &tc3589x_gpio_irq_chip,
305 irq,
306 NULL);
307
303 if (pdata && pdata->setup) 308 if (pdata && pdata->setup)
304 pdata->setup(tc3589x, tc3589x_gpio->chip.base); 309 pdata->setup(tc3589x, tc3589x_gpio->chip.base);
305 310
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 9362b5b817af..6e00c82be142 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -385,13 +385,14 @@ static struct gpio_chip *find_chip_by_name(const char *name)
385 */ 385 */
386 386
387/** 387/**
388 * gpiochip_add_chained_irqchip() - adds a chained irqchip to a gpiochip 388 * gpiochip_set_chained_irqchip() - sets a chained irqchip to a gpiochip
389 * @gpiochip: the gpiochip to add the irqchip to 389 * @gpiochip: the gpiochip to set the irqchip chain to
390 * @irqchip: the irqchip to add to the gpiochip 390 * @irqchip: the irqchip to chain to the gpiochip
391 * @parent_irq: the irq number corresponding to the parent IRQ for this 391 * @parent_irq: the irq number corresponding to the parent IRQ for this
392 * chained irqchip 392 * chained irqchip
393 * @parent_handler: the parent interrupt handler for the accumulated IRQ 393 * @parent_handler: the parent interrupt handler for the accumulated IRQ
394 * coming out of the gpiochip 394 * coming out of the gpiochip. If the interrupt is nested rather than
395 * cascaded, pass NULL in this handler argument
395 */ 396 */
396void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, 397void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
397 struct irq_chip *irqchip, 398 struct irq_chip *irqchip,
@@ -400,23 +401,26 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
400{ 401{
401 unsigned int offset; 402 unsigned int offset;
402 403
403 if (gpiochip->can_sleep) {
404 chip_err(gpiochip, "you cannot have chained interrupts on a chip that may sleep\n");
405 return;
406 }
407 if (!gpiochip->irqdomain) { 404 if (!gpiochip->irqdomain) {
408 chip_err(gpiochip, "called %s before setting up irqchip\n", 405 chip_err(gpiochip, "called %s before setting up irqchip\n",
409 __func__); 406 __func__);
410 return; 407 return;
411 } 408 }
412 409
413 irq_set_chained_handler(parent_irq, parent_handler); 410 if (parent_handler) {
414 411 if (gpiochip->can_sleep) {
415 /* 412 chip_err(gpiochip,
416 * The parent irqchip is already using the chip_data for this 413 "you cannot have chained interrupts on a "
417 * irqchip, so our callbacks simply use the handler_data. 414 "chip that may sleep\n");
418 */ 415 return;
419 irq_set_handler_data(parent_irq, gpiochip); 416 }
417 irq_set_chained_handler(parent_irq, parent_handler);
418 /*
419 * The parent irqchip is already using the chip_data for this
420 * irqchip, so our callbacks simply use the handler_data.
421 */
422 irq_set_handler_data(parent_irq, gpiochip);
423 }
420 424
421 /* Set the parent IRQ for all affected IRQs */ 425 /* Set the parent IRQ for all affected IRQs */
422 for (offset = 0; offset < gpiochip->ngpio; offset++) 426 for (offset = 0; offset < gpiochip->ngpio; offset++)