Skip to content

Commit

Permalink
pinctrl: spear: switch plgpio to irqchip helpers
Browse files Browse the repository at this point in the history
This switches the SPEAr PLGPIO driver over to using the irqchip
helpers.

As part of this effort, also get rid of the strange irq_base
calculation and failure to use d->hwirq for obtaining a local
irqchip offset.

Cc: Viresh Kumar <viresh.linux@gmail.com>
Cc: Shiraz Hashim <shiraz.linux.kernel@gmail.com>
Cc: spear-devel@list.st.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
  • Loading branch information
Linus Walleij committed Jun 19, 2014
1 parent aebdc8a commit 22763bf
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 51 deletions.
1 change: 1 addition & 0 deletions drivers/pinctrl/spear/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ config PINCTRL_SPEAR1340
config PINCTRL_SPEAR_PLGPIO
bool "SPEAr SoC PLGPIO Controller"
depends on GPIOLIB && PINCTRL_SPEAR
select GPIOLIB_IRQCHIP
help
Say yes here to support PLGPIO controller on ST Microelectronics SPEAr
SoCs.
Expand Down
81 changes: 30 additions & 51 deletions drivers/pinctrl/spear/pinctrl-plgpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@

#include <linux/clk.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/gpio/driver.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
Expand Down Expand Up @@ -54,7 +53,6 @@ struct plgpio_regs {
*
* lock: lock for guarding gpio registers
* base: base address of plgpio block
* irq_base: irq number of plgpio0
* chip: gpio framework specific chip information structure
* p2o: function ptr for pin to offset conversion. This is required only for
* machines where mapping b/w pin and offset is not 1-to-1.
Expand All @@ -68,8 +66,6 @@ struct plgpio {
spinlock_t lock;
void __iomem *base;
struct clk *clk;
unsigned irq_base;
struct irq_domain *irq_domain;
struct gpio_chip chip;
int (*p2o)(int pin); /* pin_to_offset */
int (*o2p)(int offset); /* offset_to_pin */
Expand Down Expand Up @@ -280,21 +276,12 @@ static void plgpio_free(struct gpio_chip *chip, unsigned offset)
pinctrl_free_gpio(gpio);
}

static int plgpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct plgpio *plgpio = container_of(chip, struct plgpio, chip);

if (IS_ERR_VALUE(plgpio->irq_base))
return -EINVAL;

return irq_find_mapping(plgpio->irq_domain, offset);
}

/* PLGPIO IRQ */
static void plgpio_irq_disable(struct irq_data *d)
{
struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
int offset = d->irq - plgpio->irq_base;
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
int offset = d->hwirq;
unsigned long flags;

/* get correct offset for "offset" pin */
Expand All @@ -311,8 +298,9 @@ static void plgpio_irq_disable(struct irq_data *d)

static void plgpio_irq_enable(struct irq_data *d)
{
struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
int offset = d->irq - plgpio->irq_base;
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
int offset = d->hwirq;
unsigned long flags;

/* get correct offset for "offset" pin */
Expand All @@ -329,8 +317,9 @@ static void plgpio_irq_enable(struct irq_data *d)

static int plgpio_irq_set_type(struct irq_data *d, unsigned trigger)
{
struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
int offset = d->irq - plgpio->irq_base;
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
int offset = d->hwirq;
void __iomem *reg_off;
unsigned int supported_type = 0, val;

Expand Down Expand Up @@ -369,7 +358,8 @@ static struct irq_chip plgpio_irqchip = {

static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc)
{
struct plgpio *plgpio = irq_get_handler_data(irq);
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
struct irq_chip *irqchip = irq_desc_get_chip(desc);
int regs_count, count, pin, offset, i = 0;
unsigned long pending;
Expand Down Expand Up @@ -410,7 +400,8 @@ static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc)

/* get correct irq line number */
pin = i * MAX_GPIO_PER_REG + pin;
generic_handle_irq(plgpio_to_irq(&plgpio->chip, pin));
generic_handle_irq(
irq_find_mapping(gc->irqdomain, pin));
}
}
chained_irq_exit(irqchip, desc);
Expand Down Expand Up @@ -523,10 +514,9 @@ static int plgpio_probe_dt(struct platform_device *pdev, struct plgpio *plgpio)
}
static int plgpio_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct plgpio *plgpio;
struct resource *res;
int ret, irq, i;
int ret, irq;

plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL);
if (!plgpio) {
Expand Down Expand Up @@ -563,18 +553,17 @@ static int plgpio_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, plgpio);
spin_lock_init(&plgpio->lock);

plgpio->irq_base = -1;
plgpio->chip.base = -1;
plgpio->chip.request = plgpio_request;
plgpio->chip.free = plgpio_free;
plgpio->chip.direction_input = plgpio_direction_input;
plgpio->chip.direction_output = plgpio_direction_output;
plgpio->chip.get = plgpio_get_value;
plgpio->chip.set = plgpio_set_value;
plgpio->chip.to_irq = plgpio_to_irq;
plgpio->chip.label = dev_name(&pdev->dev);
plgpio->chip.dev = &pdev->dev;
plgpio->chip.owner = THIS_MODULE;
plgpio->chip.of_node = pdev->dev.of_node;

if (!IS_ERR(plgpio->clk)) {
ret = clk_prepare(plgpio->clk);
Expand All @@ -592,35 +581,25 @@ static int plgpio_probe(struct platform_device *pdev)

irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_info(&pdev->dev, "irqs not supported\n");
return 0;
}

plgpio->irq_base = irq_alloc_descs(-1, 0, plgpio->chip.ngpio, 0);
if (IS_ERR_VALUE(plgpio->irq_base)) {
/* we would not support irq for gpio */
dev_warn(&pdev->dev, "couldn't allocate irq base\n");
dev_info(&pdev->dev, "PLGPIO registered without IRQs\n");
return 0;
}

plgpio->irq_domain = irq_domain_add_legacy(np, plgpio->chip.ngpio,
plgpio->irq_base, 0, &irq_domain_simple_ops, NULL);
if (WARN_ON(!plgpio->irq_domain)) {
dev_err(&pdev->dev, "irq domain init failed\n");
irq_free_descs(plgpio->irq_base, plgpio->chip.ngpio);
ret = -ENXIO;
ret = gpiochip_irqchip_add(&plgpio->chip,
&plgpio_irqchip,
0,
handle_simple_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_err(&pdev->dev, "failed to add irqchip to gpiochip\n");
goto remove_gpiochip;
}

irq_set_chained_handler(irq, plgpio_irq_handler);
for (i = 0; i < plgpio->chip.ngpio; i++) {
irq_set_chip_and_handler(i + plgpio->irq_base, &plgpio_irqchip,
handle_simple_irq);
set_irq_flags(i + plgpio->irq_base, IRQF_VALID);
irq_set_chip_data(i + plgpio->irq_base, plgpio);
}
gpiochip_set_chained_irqchip(&plgpio->chip,
&plgpio_irqchip,
irq,
plgpio_irq_handler);

irq_set_handler_data(irq, plgpio);
dev_info(&pdev->dev, "PLGPIO registered with IRQs\n");

return 0;
Expand Down

0 comments on commit 22763bf

Please sign in to comment.