Skip to content

Commit

Permalink
gpio: sx150x: move to irqdomain framework for sx150x driver
Browse files Browse the repository at this point in the history
The sx150x gpio driver used a loop to set liner irq map for gpio pins.
Now we use the irq domain to rebuild this irq mappig and make sure the
codes are still compatible to old users.

this patch also adds IRQF_ONESHOT flag to fix the IRQ flooding issues.

Signed-off-by: Wei Chen <Wei.Chen@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
[Make Kconfig select GPIOLIB_IRQCHIP]
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
  • Loading branch information
Wei Chen authored and Linus Walleij committed Jan 15, 2015
1 parent 3c01b9a commit 093e943
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 54 deletions.
1 change: 1 addition & 0 deletions drivers/gpio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,7 @@ config GPIO_RC5T583
config GPIO_SX150X
bool "Semtech SX150x I2C GPIO expander"
depends on I2C=y
select GPIOLIB_IRQCHIP
default n
help
Say yes here to provide support for Semtech SX150-series I2C
Expand Down
72 changes: 18 additions & 54 deletions drivers/gpio/gpio-sx150x.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,37 +293,20 @@ static int sx150x_gpio_direction_output(struct gpio_chip *gc,
return status;
}

static int sx150x_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
{
struct sx150x_chip *chip;

chip = container_of(gc, struct sx150x_chip, gpio_chip);

if (offset >= chip->dev_cfg->ngpios)
return -EINVAL;

if (chip->irq_base < 0)
return -EINVAL;

return chip->irq_base + offset;
}

static void sx150x_irq_mask(struct irq_data *d)
{
struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
unsigned n;
unsigned n = d->hwirq;

n = d->irq - chip->irq_base;
chip->irq_masked |= (1 << n);
chip->irq_update = n;
}

static void sx150x_irq_unmask(struct irq_data *d)
{
struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
unsigned n;
unsigned n = d->hwirq;

n = d->irq - chip->irq_base;
chip->irq_masked &= ~(1 << n);
chip->irq_update = n;
}
Expand All @@ -336,7 +319,7 @@ static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type)
if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
return -EINVAL;

n = d->irq - chip->irq_base;
n = d->hwirq;

if (flow_type & IRQ_TYPE_EDGE_RISING)
val |= 0x1;
Expand Down Expand Up @@ -371,7 +354,9 @@ static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id)
val);
for (n = 0; n < 8; ++n) {
if (val & (1 << n)) {
sub_irq = chip->irq_base + (i * 8) + n;
sub_irq = irq_find_mapping(
chip->gpio_chip.irqdomain,
(i * 8) + n);
handle_nested_irq(sub_irq);
++nhandled;
}
Expand Down Expand Up @@ -428,12 +413,12 @@ static void sx150x_init_chip(struct sx150x_chip *chip,

chip->client = client;
chip->dev_cfg = &sx150x_devices[driver_data];
chip->gpio_chip.dev = &client->dev;
chip->gpio_chip.label = client->name;
chip->gpio_chip.direction_input = sx150x_gpio_direction_input;
chip->gpio_chip.direction_output = sx150x_gpio_direction_output;
chip->gpio_chip.get = sx150x_gpio_get;
chip->gpio_chip.set = sx150x_gpio_set;
chip->gpio_chip.to_irq = sx150x_gpio_to_irq;
chip->gpio_chip.base = pdata->gpio_base;
chip->gpio_chip.can_sleep = true;
chip->gpio_chip.ngpio = chip->dev_cfg->ngpios;
Expand Down Expand Up @@ -529,31 +514,24 @@ static int sx150x_install_irq_chip(struct sx150x_chip *chip,
int irq_base)
{
int err;
unsigned n;
unsigned irq;

chip->irq_summary = irq_summary;
chip->irq_base = irq_base;

for (n = 0; n < chip->dev_cfg->ngpios; ++n) {
irq = irq_base + n;
irq_set_chip_data(irq, chip);
irq_set_chip_and_handler(irq, &chip->irq_chip, handle_edge_irq);
irq_set_nested_thread(irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq);
#endif
/* Add gpio chip to irq subsystem */
err = gpiochip_irqchip_add(&chip->gpio_chip,
&chip->irq_chip, chip->irq_base,
handle_edge_irq, IRQ_TYPE_EDGE_BOTH);
if (err) {
dev_err(&chip->client->dev,
"could not connect irqchip to gpiochip\n");
return err;
}

err = devm_request_threaded_irq(&chip->client->dev,
irq_summary,
NULL,
sx150x_irq_thread_fn,
IRQF_SHARED | IRQF_TRIGGER_FALLING,
chip->irq_chip.name,
chip);
irq_summary, NULL, sx150x_irq_thread_fn,
IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_FALLING,
chip->irq_chip.name, chip);
if (err < 0) {
chip->irq_summary = -1;
chip->irq_base = -1;
Expand All @@ -562,17 +540,6 @@ static int sx150x_install_irq_chip(struct sx150x_chip *chip,
return err;
}

static void sx150x_remove_irq_chip(struct sx150x_chip *chip)
{
unsigned n;
unsigned irq;

for (n = 0; n < chip->dev_cfg->ngpios; ++n) {
irq = chip->irq_base + n;
irq_set_chip_and_handler(irq, NULL, NULL);
}
}

static int sx150x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
Expand Down Expand Up @@ -626,9 +593,6 @@ static int sx150x_remove(struct i2c_client *client)
chip = i2c_get_clientdata(client);
gpiochip_remove(&chip->gpio_chip);

if (chip->irq_summary >= 0)
sx150x_remove_irq_chip(chip);

return 0;
}

Expand Down

0 comments on commit 093e943

Please sign in to comment.