aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-mcp23s08.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpio-mcp23s08.c')
-rw-r--r--drivers/gpio/gpio-mcp23s08.c252
1 files changed, 245 insertions, 7 deletions
diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c
index 2deb0c5e54a4..1ac288ea810d 100644
--- a/drivers/gpio/gpio-mcp23s08.c
+++ b/drivers/gpio/gpio-mcp23s08.c
@@ -1,5 +1,13 @@
1/* 1/*
2 * MCP23S08 SPI/GPIO gpio expander driver 2 * MCP23S08 SPI/I2C GPIO gpio expander driver
3 *
4 * The inputs and outputs of the mcp23s08, mcp23s17, mcp23008 and mcp23017 are
5 * supported.
6 * For the I2C versions of the chips (mcp23008 and mcp23017) generation of
7 * interrupts is also supported.
8 * The hardware of the SPI versions of the chips (mcp23s08 and mcp23s17) is
9 * also capable of generating interrupts, but the linux driver does not
10 * support that yet.
3 */ 11 */
4 12
5#include <linux/kernel.h> 13#include <linux/kernel.h>
@@ -12,7 +20,8 @@
12#include <linux/spi/mcp23s08.h> 20#include <linux/spi/mcp23s08.h>
13#include <linux/slab.h> 21#include <linux/slab.h>
14#include <asm/byteorder.h> 22#include <asm/byteorder.h>
15#include <linux/of.h> 23#include <linux/interrupt.h>
24#include <linux/of_irq.h>
16#include <linux/of_device.h> 25#include <linux/of_device.h>
17 26
18/** 27/**
@@ -34,6 +43,7 @@
34#define MCP_DEFVAL 0x03 43#define MCP_DEFVAL 0x03
35#define MCP_INTCON 0x04 44#define MCP_INTCON 0x04
36#define MCP_IOCON 0x05 45#define MCP_IOCON 0x05
46# define IOCON_MIRROR (1 << 6)
37# define IOCON_SEQOP (1 << 5) 47# define IOCON_SEQOP (1 << 5)
38# define IOCON_HAEN (1 << 3) 48# define IOCON_HAEN (1 << 3)
39# define IOCON_ODR (1 << 2) 49# define IOCON_ODR (1 << 2)
@@ -57,8 +67,14 @@ struct mcp23s08 {
57 u8 addr; 67 u8 addr;
58 68
59 u16 cache[11]; 69 u16 cache[11];
70 u16 irq_rise;
71 u16 irq_fall;
72 int irq;
73 bool irq_controller;
60 /* lock protects the cached values */ 74 /* lock protects the cached values */
61 struct mutex lock; 75 struct mutex lock;
76 struct mutex irq_lock;
77 struct irq_domain *irq_domain;
62 78
63 struct gpio_chip chip; 79 struct gpio_chip chip;
64 80
@@ -77,6 +93,11 @@ struct mcp23s08_driver_data {
77 struct mcp23s08 chip[]; 93 struct mcp23s08 chip[];
78}; 94};
79 95
96/* This lock class tells lockdep that GPIO irqs are in a different
97 * category than their parents, so it won't report false recursion.
98 */
99static struct lock_class_key gpio_lock_class;
100
80/*----------------------------------------------------------------------*/ 101/*----------------------------------------------------------------------*/
81 102
82#if IS_ENABLED(CONFIG_I2C) 103#if IS_ENABLED(CONFIG_I2C)
@@ -316,6 +337,195 @@ mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)
316} 337}
317 338
318/*----------------------------------------------------------------------*/ 339/*----------------------------------------------------------------------*/
340static irqreturn_t mcp23s08_irq(int irq, void *data)
341{
342 struct mcp23s08 *mcp = data;
343 int intcap, intf, i;
344 unsigned int child_irq;
345
346 mutex_lock(&mcp->lock);
347 intf = mcp->ops->read(mcp, MCP_INTF);
348 if (intf < 0) {
349 mutex_unlock(&mcp->lock);
350 return IRQ_HANDLED;
351 }
352
353 mcp->cache[MCP_INTF] = intf;
354
355 intcap = mcp->ops->read(mcp, MCP_INTCAP);
356 if (intcap < 0) {
357 mutex_unlock(&mcp->lock);
358 return IRQ_HANDLED;
359 }
360
361 mcp->cache[MCP_INTCAP] = intcap;
362 mutex_unlock(&mcp->lock);
363
364
365 for (i = 0; i < mcp->chip.ngpio; i++) {
366 if ((BIT(i) & mcp->cache[MCP_INTF]) &&
367 ((BIT(i) & intcap & mcp->irq_rise) ||
368 (mcp->irq_fall & ~intcap & BIT(i)))) {
369 child_irq = irq_find_mapping(mcp->irq_domain, i);
370 handle_nested_irq(child_irq);
371 }
372 }
373
374 return IRQ_HANDLED;
375}
376
377static int mcp23s08_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
378{
379 struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
380
381 return irq_find_mapping(mcp->irq_domain, offset);
382}
383
384static void mcp23s08_irq_mask(struct irq_data *data)
385{
386 struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data);
387 unsigned int pos = data->hwirq;
388
389 mcp->cache[MCP_GPINTEN] &= ~BIT(pos);
390}
391
392static void mcp23s08_irq_unmask(struct irq_data *data)
393{
394 struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data);
395 unsigned int pos = data->hwirq;
396
397 mcp->cache[MCP_GPINTEN] |= BIT(pos);
398}
399
400static int mcp23s08_irq_set_type(struct irq_data *data, unsigned int type)
401{
402 struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data);
403 unsigned int pos = data->hwirq;
404 int status = 0;
405
406 if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
407 mcp->cache[MCP_INTCON] &= ~BIT(pos);
408 mcp->irq_rise |= BIT(pos);
409 mcp->irq_fall |= BIT(pos);
410 } else if (type & IRQ_TYPE_EDGE_RISING) {
411 mcp->cache[MCP_INTCON] &= ~BIT(pos);
412 mcp->irq_rise |= BIT(pos);
413 mcp->irq_fall &= ~BIT(pos);
414 } else if (type & IRQ_TYPE_EDGE_FALLING) {
415 mcp->cache[MCP_INTCON] &= ~BIT(pos);
416 mcp->irq_rise &= ~BIT(pos);
417 mcp->irq_fall |= BIT(pos);
418 } else
419 return -EINVAL;
420
421 return status;
422}
423
424static void mcp23s08_irq_bus_lock(struct irq_data *data)
425{
426 struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data);
427
428 mutex_lock(&mcp->irq_lock);
429}
430
431static void mcp23s08_irq_bus_unlock(struct irq_data *data)
432{
433 struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data);
434
435 mutex_lock(&mcp->lock);
436 mcp->ops->write(mcp, MCP_GPINTEN, mcp->cache[MCP_GPINTEN]);
437 mcp->ops->write(mcp, MCP_DEFVAL, mcp->cache[MCP_DEFVAL]);
438 mcp->ops->write(mcp, MCP_INTCON, mcp->cache[MCP_INTCON]);
439 mutex_unlock(&mcp->lock);
440 mutex_unlock(&mcp->irq_lock);
441}
442
443static unsigned int mcp23s08_irq_startup(struct irq_data *data)
444{
445 struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data);
446
447 if (gpio_lock_as_irq(&mcp->chip, data->hwirq))
448 dev_err(mcp->chip.dev,
449 "unable to lock HW IRQ %lu for IRQ usage\n",
450 data->hwirq);
451
452 mcp23s08_irq_unmask(data);
453 return 0;
454}
455
456static void mcp23s08_irq_shutdown(struct irq_data *data)
457{
458 struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data);
459
460 mcp23s08_irq_mask(data);
461 gpio_unlock_as_irq(&mcp->chip, data->hwirq);
462}
463
464static struct irq_chip mcp23s08_irq_chip = {
465 .name = "gpio-mcp23xxx",
466 .irq_mask = mcp23s08_irq_mask,
467 .irq_unmask = mcp23s08_irq_unmask,
468 .irq_set_type = mcp23s08_irq_set_type,
469 .irq_bus_lock = mcp23s08_irq_bus_lock,
470 .irq_bus_sync_unlock = mcp23s08_irq_bus_unlock,
471 .irq_startup = mcp23s08_irq_startup,
472 .irq_shutdown = mcp23s08_irq_shutdown,
473};
474
475static int mcp23s08_irq_setup(struct mcp23s08 *mcp)
476{
477 struct gpio_chip *chip = &mcp->chip;
478 int err, irq, j;
479
480 mutex_init(&mcp->irq_lock);
481
482 mcp->irq_domain = irq_domain_add_linear(chip->of_node, chip->ngpio,
483 &irq_domain_simple_ops, mcp);
484 if (!mcp->irq_domain)
485 return -ENODEV;
486
487 err = devm_request_threaded_irq(chip->dev, mcp->irq, NULL, mcp23s08_irq,
488 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
489 dev_name(chip->dev), mcp);
490 if (err != 0) {
491 dev_err(chip->dev, "unable to request IRQ#%d: %d\n",
492 mcp->irq, err);
493 return err;
494 }
495
496 chip->to_irq = mcp23s08_gpio_to_irq;
497
498 for (j = 0; j < mcp->chip.ngpio; j++) {
499 irq = irq_create_mapping(mcp->irq_domain, j);
500 irq_set_lockdep_class(irq, &gpio_lock_class);
501 irq_set_chip_data(irq, mcp);
502 irq_set_chip(irq, &mcp23s08_irq_chip);
503 irq_set_nested_thread(irq, true);
504#ifdef CONFIG_ARM
505 set_irq_flags(irq, IRQF_VALID);
506#else
507 irq_set_noprobe(irq);
508#endif
509 }
510 return 0;
511}
512
513static void mcp23s08_irq_teardown(struct mcp23s08 *mcp)
514{
515 unsigned int irq, i;
516
517 free_irq(mcp->irq, mcp);
518
519 for (i = 0; i < mcp->chip.ngpio; i++) {
520 irq = irq_find_mapping(mcp->irq_domain, i);
521 if (irq > 0)
522 irq_dispose_mapping(irq);
523 }
524
525 irq_domain_remove(mcp->irq_domain);
526}
527
528/*----------------------------------------------------------------------*/
319 529
320#ifdef CONFIG_DEBUG_FS 530#ifdef CONFIG_DEBUG_FS
321 531
@@ -370,10 +580,11 @@ done:
370/*----------------------------------------------------------------------*/ 580/*----------------------------------------------------------------------*/
371 581
372static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, 582static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
373 void *data, unsigned addr, 583 void *data, unsigned addr, unsigned type,
374 unsigned type, unsigned base, unsigned pullups) 584 unsigned base, unsigned pullups)
375{ 585{
376 int status; 586 int status;
587 bool mirror = false;
377 588
378 mutex_init(&mcp->lock); 589 mutex_init(&mcp->lock);
379 590
@@ -425,20 +636,32 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
425 } 636 }
426 637
427 mcp->chip.base = base; 638 mcp->chip.base = base;
428 mcp->chip.can_sleep = 1; 639 mcp->chip.can_sleep = true;
429 mcp->chip.dev = dev; 640 mcp->chip.dev = dev;
430 mcp->chip.owner = THIS_MODULE; 641 mcp->chip.owner = THIS_MODULE;
431 642
432 /* verify MCP_IOCON.SEQOP = 0, so sequential reads work, 643 /* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
433 * and MCP_IOCON.HAEN = 1, so we work with all chips. 644 * and MCP_IOCON.HAEN = 1, so we work with all chips.
434 */ 645 */
646
435 status = mcp->ops->read(mcp, MCP_IOCON); 647 status = mcp->ops->read(mcp, MCP_IOCON);
436 if (status < 0) 648 if (status < 0)
437 goto fail; 649 goto fail;
438 if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) { 650
651 mcp->irq_controller = of_property_read_bool(mcp->chip.of_node,
652 "interrupt-controller");
653 if (mcp->irq && mcp->irq_controller && (type == MCP_TYPE_017))
654 mirror = of_property_read_bool(mcp->chip.of_node,
655 "microchip,irq-mirror");
656
657 if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror) {
439 /* mcp23s17 has IOCON twice, make sure they are in sync */ 658 /* mcp23s17 has IOCON twice, make sure they are in sync */
440 status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8)); 659 status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));
441 status |= IOCON_HAEN | (IOCON_HAEN << 8); 660 status |= IOCON_HAEN | (IOCON_HAEN << 8);
661 status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8));
662 if (mirror)
663 status |= IOCON_MIRROR | (IOCON_MIRROR << 8);
664
442 status = mcp->ops->write(mcp, MCP_IOCON, status); 665 status = mcp->ops->write(mcp, MCP_IOCON, status);
443 if (status < 0) 666 if (status < 0)
444 goto fail; 667 goto fail;
@@ -470,6 +693,16 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
470 } 693 }
471 694
472 status = gpiochip_add(&mcp->chip); 695 status = gpiochip_add(&mcp->chip);
696 if (status < 0)
697 goto fail;
698
699 if (mcp->irq && mcp->irq_controller) {
700 status = mcp23s08_irq_setup(mcp);
701 if (status) {
702 mcp23s08_irq_teardown(mcp);
703 goto fail;
704 }
705 }
473fail: 706fail:
474 if (status < 0) 707 if (status < 0)
475 dev_dbg(dev, "can't setup chip %d, --> %d\n", 708 dev_dbg(dev, "can't setup chip %d, --> %d\n",
@@ -546,6 +779,7 @@ static int mcp230xx_probe(struct i2c_client *client,
546 if (match || !pdata) { 779 if (match || !pdata) {
547 base = -1; 780 base = -1;
548 pullups = 0; 781 pullups = 0;
782 client->irq = irq_of_parse_and_map(client->dev.of_node, 0);
549 } else { 783 } else {
550 if (!gpio_is_valid(pdata->base)) { 784 if (!gpio_is_valid(pdata->base)) {
551 dev_dbg(&client->dev, "invalid platform data\n"); 785 dev_dbg(&client->dev, "invalid platform data\n");
@@ -559,6 +793,7 @@ static int mcp230xx_probe(struct i2c_client *client,
559 if (!mcp) 793 if (!mcp)
560 return -ENOMEM; 794 return -ENOMEM;
561 795
796 mcp->irq = client->irq;
562 status = mcp23s08_probe_one(mcp, &client->dev, client, client->addr, 797 status = mcp23s08_probe_one(mcp, &client->dev, client, client->addr,
563 id->driver_data, base, pullups); 798 id->driver_data, base, pullups);
564 if (status) 799 if (status)
@@ -579,6 +814,9 @@ static int mcp230xx_remove(struct i2c_client *client)
579 struct mcp23s08 *mcp = i2c_get_clientdata(client); 814 struct mcp23s08 *mcp = i2c_get_clientdata(client);
580 int status; 815 int status;
581 816
817 if (client->irq && mcp->irq_controller)
818 mcp23s08_irq_teardown(mcp);
819
582 status = gpiochip_remove(&mcp->chip); 820 status = gpiochip_remove(&mcp->chip);
583 if (status == 0) 821 if (status == 0)
584 kfree(mcp); 822 kfree(mcp);
@@ -640,7 +878,7 @@ static int mcp23s08_probe(struct spi_device *spi)
640 878
641 match = of_match_device(of_match_ptr(mcp23s08_spi_of_match), &spi->dev); 879 match = of_match_device(of_match_ptr(mcp23s08_spi_of_match), &spi->dev);
642 if (match) { 880 if (match) {
643 type = (int)match->data; 881 type = (int)(uintptr_t)match->data;
644 status = of_property_read_u32(spi->dev.of_node, 882 status = of_property_read_u32(spi->dev.of_node,
645 "microchip,spi-present-mask", &spi_present_mask); 883 "microchip,spi-present-mask", &spi_present_mask);
646 if (status) { 884 if (status) {