pinctrl: coh901: convert driver to use gpiolib irqchip
This converts the COH901 pin control driver to register its chained irq handler and irqchip using the helpers in the gpiolib core. Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
e0bc34a3da
commit
523dcce72c
|
@ -324,6 +324,7 @@ config PINCTRL_U300
|
|||
config PINCTRL_COH901
|
||||
bool "ST-Ericsson U300 COH 901 335/571 GPIO"
|
||||
depends on GPIOLIB && ARCH_U300 && PINCTRL_U300
|
||||
select GPIOLIB_IRQCHIP
|
||||
help
|
||||
Say yes here to support GPIO interface on ST-Ericsson U300.
|
||||
The names of the two IP block variants supported are
|
||||
|
|
|
@ -8,17 +8,14 @@
|
|||
* Author: Jonas Aaberg <jonas.aberg@stericsson.com>
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
|
@ -61,9 +58,17 @@
|
|||
#define U300_GPIO_PINS_PER_PORT 8
|
||||
#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS)
|
||||
|
||||
struct u300_gpio_port {
|
||||
struct u300_gpio *gpio;
|
||||
char name[8];
|
||||
int irq;
|
||||
int number;
|
||||
u8 toggle_edge_mode;
|
||||
};
|
||||
|
||||
struct u300_gpio {
|
||||
struct gpio_chip chip;
|
||||
struct list_head port_list;
|
||||
struct u300_gpio_port ports[U300_GPIO_NUM_PORTS];
|
||||
struct clk *clk;
|
||||
void __iomem *base;
|
||||
struct device *dev;
|
||||
|
@ -78,16 +83,6 @@ struct u300_gpio {
|
|||
u32 iev;
|
||||
};
|
||||
|
||||
struct u300_gpio_port {
|
||||
struct list_head node;
|
||||
struct u300_gpio *gpio;
|
||||
char name[8];
|
||||
struct irq_domain *domain;
|
||||
int irq;
|
||||
int number;
|
||||
u8 toggle_edge_mode;
|
||||
};
|
||||
|
||||
/*
|
||||
* Macro to expand to read a specific register found in the "gpio"
|
||||
* struct. It requires the struct u300_gpio *gpio variable to exist in
|
||||
|
@ -308,39 +303,6 @@ static int u300_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct u300_gpio *gpio = to_u300_gpio(chip);
|
||||
int portno = offset >> 3;
|
||||
struct u300_gpio_port *port = NULL;
|
||||
struct list_head *p;
|
||||
int retirq;
|
||||
bool found = false;
|
||||
|
||||
list_for_each(p, &gpio->port_list) {
|
||||
port = list_entry(p, struct u300_gpio_port, node);
|
||||
if (port->number == portno) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
dev_err(gpio->dev, "could not locate port for GPIO %d IRQ\n",
|
||||
offset);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The local hwirqs on the port are the lower three bits, there
|
||||
* are exactly 8 IRQs per port since they are 8-bit
|
||||
*/
|
||||
retirq = irq_find_mapping(port->domain, (offset & 0x7));
|
||||
|
||||
dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d from port %d\n",
|
||||
offset, retirq, port->number);
|
||||
return retirq;
|
||||
}
|
||||
|
||||
/* Returning -EINVAL means "supported but not available" */
|
||||
int u300_gpio_config_get(struct gpio_chip *chip,
|
||||
unsigned offset,
|
||||
|
@ -461,7 +423,6 @@ static struct gpio_chip u300_gpio_chip = {
|
|||
.set = u300_gpio_set,
|
||||
.direction_input = u300_gpio_direction_input,
|
||||
.direction_output = u300_gpio_direction_output,
|
||||
.to_irq = u300_gpio_to_irq,
|
||||
};
|
||||
|
||||
static void u300_toggle_trigger(struct u300_gpio *gpio, unsigned offset)
|
||||
|
@ -485,9 +446,10 @@ static void u300_toggle_trigger(struct u300_gpio *gpio, unsigned offset)
|
|||
|
||||
static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger)
|
||||
{
|
||||
struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
|
||||
struct u300_gpio *gpio = port->gpio;
|
||||
int offset = (port->number << 3) + d->hwirq;
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
|
||||
struct u300_gpio *gpio = to_u300_gpio(chip);
|
||||
struct u300_gpio_port *port = &gpio->ports[d->hwirq >> 3];
|
||||
int offset = d->hwirq;
|
||||
u32 val;
|
||||
|
||||
if ((trigger & IRQF_TRIGGER_RISING) &&
|
||||
|
@ -521,9 +483,10 @@ static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger)
|
|||
|
||||
static void u300_gpio_irq_enable(struct irq_data *d)
|
||||
{
|
||||
struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
|
||||
struct u300_gpio *gpio = port->gpio;
|
||||
int offset = (port->number << 3) + d->hwirq;
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
|
||||
struct u300_gpio *gpio = to_u300_gpio(chip);
|
||||
struct u300_gpio_port *port = &gpio->ports[d->hwirq >> 3];
|
||||
int offset = d->hwirq;
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -537,9 +500,9 @@ static void u300_gpio_irq_enable(struct irq_data *d)
|
|||
|
||||
static void u300_gpio_irq_disable(struct irq_data *d)
|
||||
{
|
||||
struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
|
||||
struct u300_gpio *gpio = port->gpio;
|
||||
int offset = (port->number << 3) + d->hwirq;
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
|
||||
struct u300_gpio *gpio = to_u300_gpio(chip);
|
||||
int offset = d->hwirq;
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -549,45 +512,24 @@ static void u300_gpio_irq_disable(struct irq_data *d)
|
|||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static int u300_gpio_irq_reqres(struct irq_data *d)
|
||||
{
|
||||
struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
|
||||
struct u300_gpio *gpio = port->gpio;
|
||||
|
||||
if (gpio_lock_as_irq(&gpio->chip, d->hwirq)) {
|
||||
dev_err(gpio->dev,
|
||||
"unable to lock HW IRQ %lu for IRQ\n",
|
||||
d->hwirq);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void u300_gpio_irq_relres(struct irq_data *d)
|
||||
{
|
||||
struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
|
||||
struct u300_gpio *gpio = port->gpio;
|
||||
|
||||
gpio_unlock_as_irq(&gpio->chip, d->hwirq);
|
||||
}
|
||||
|
||||
static struct irq_chip u300_gpio_irqchip = {
|
||||
.name = "u300-gpio-irqchip",
|
||||
.irq_enable = u300_gpio_irq_enable,
|
||||
.irq_disable = u300_gpio_irq_disable,
|
||||
.irq_set_type = u300_gpio_irq_type,
|
||||
.irq_request_resources = u300_gpio_irq_reqres,
|
||||
.irq_release_resources = u300_gpio_irq_relres,
|
||||
};
|
||||
|
||||
static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
|
||||
{
|
||||
struct u300_gpio_port *port = irq_get_handler_data(irq);
|
||||
struct u300_gpio *gpio = port->gpio;
|
||||
struct irq_chip *parent_chip = irq_get_chip(irq);
|
||||
struct gpio_chip *chip = irq_get_handler_data(irq);
|
||||
struct u300_gpio *gpio = to_u300_gpio(chip);
|
||||
struct u300_gpio_port *port = &gpio->ports[irq - chip->base];
|
||||
int pinoffset = port->number << 3; /* get the right stride */
|
||||
unsigned long val;
|
||||
|
||||
desc->irq_data.chip->irq_ack(&desc->irq_data);
|
||||
chained_irq_enter(parent_chip, desc);
|
||||
|
||||
/* Read event register */
|
||||
val = readl(U300_PIN_REG(pinoffset, iev));
|
||||
/* Mask relevant bits */
|
||||
|
@ -600,8 +542,8 @@ static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
|
|||
int irqoffset;
|
||||
|
||||
for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) {
|
||||
int pin_irq = irq_find_mapping(port->domain, irqoffset);
|
||||
int offset = pinoffset + irqoffset;
|
||||
int pin_irq = irq_find_mapping(chip->irqdomain, offset);
|
||||
|
||||
dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n",
|
||||
pin_irq, offset);
|
||||
|
@ -615,7 +557,7 @@ static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
|
|||
}
|
||||
}
|
||||
|
||||
desc->irq_data.chip->irq_unmask(&desc->irq_data);
|
||||
chained_irq_exit(parent_chip, desc);
|
||||
}
|
||||
|
||||
static void __init u300_gpio_init_pin(struct u300_gpio *gpio,
|
||||
|
@ -666,20 +608,6 @@ static void __init u300_gpio_init_coh901571(struct u300_gpio *gpio)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void u300_gpio_free_ports(struct u300_gpio *gpio)
|
||||
{
|
||||
struct u300_gpio_port *port;
|
||||
struct list_head *p, *n;
|
||||
|
||||
list_for_each_safe(p, n, &gpio->port_list) {
|
||||
port = list_entry(p, struct u300_gpio_port, node);
|
||||
list_del(&port->node);
|
||||
if (port->domain)
|
||||
irq_domain_remove(port->domain);
|
||||
kfree(port);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we map a GPIO in the local gpio_chip pin space to a pin in
|
||||
* the local pinctrl pin space. The pin controller used is
|
||||
|
@ -770,59 +698,6 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
|
|||
gpio->base + U300_GPIO_CR);
|
||||
u300_gpio_init_coh901571(gpio);
|
||||
|
||||
/* Add each port with its IRQ separately */
|
||||
INIT_LIST_HEAD(&gpio->port_list);
|
||||
for (portno = 0 ; portno < U300_GPIO_NUM_PORTS; portno++) {
|
||||
struct u300_gpio_port *port =
|
||||
kmalloc(sizeof(struct u300_gpio_port), GFP_KERNEL);
|
||||
|
||||
if (!port) {
|
||||
dev_err(gpio->dev, "out of memory\n");
|
||||
err = -ENOMEM;
|
||||
goto err_no_port;
|
||||
}
|
||||
|
||||
snprintf(port->name, 8, "gpio%d", portno);
|
||||
port->number = portno;
|
||||
port->gpio = gpio;
|
||||
|
||||
port->irq = platform_get_irq(pdev, portno);
|
||||
|
||||
dev_dbg(gpio->dev, "register IRQ %d for port %s\n", port->irq,
|
||||
port->name);
|
||||
|
||||
port->domain = irq_domain_add_linear(pdev->dev.of_node,
|
||||
U300_GPIO_PINS_PER_PORT,
|
||||
&irq_domain_simple_ops,
|
||||
port);
|
||||
if (!port->domain) {
|
||||
err = -ENOMEM;
|
||||
goto err_no_domain;
|
||||
}
|
||||
|
||||
irq_set_chained_handler(port->irq, u300_gpio_irq_handler);
|
||||
irq_set_handler_data(port->irq, port);
|
||||
|
||||
/* For each GPIO pin set the unique IRQ handler */
|
||||
for (i = 0; i < U300_GPIO_PINS_PER_PORT; i++) {
|
||||
int irqno = irq_create_mapping(port->domain, i);
|
||||
|
||||
dev_dbg(gpio->dev, "GPIO%d on port %s gets IRQ %d\n",
|
||||
gpio->chip.base + (port->number << 3) + i,
|
||||
port->name, irqno);
|
||||
irq_set_chip_and_handler(irqno, &u300_gpio_irqchip,
|
||||
handle_simple_irq);
|
||||
set_irq_flags(irqno, IRQF_VALID);
|
||||
irq_set_chip_data(irqno, port);
|
||||
}
|
||||
|
||||
/* Turns off irq force (test register) for this port */
|
||||
writel(0x0, gpio->base + portno * gpio->stride + ifr);
|
||||
|
||||
list_add_tail(&port->node, &gpio->port_list);
|
||||
}
|
||||
dev_dbg(gpio->dev, "initialized %d GPIO ports\n", portno);
|
||||
|
||||
#ifdef CONFIG_OF_GPIO
|
||||
gpio->chip.of_node = pdev->dev.of_node;
|
||||
#endif
|
||||
|
@ -832,6 +707,36 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
|
|||
goto err_no_chip;
|
||||
}
|
||||
|
||||
err = gpiochip_irqchip_add(&gpio->chip,
|
||||
&u300_gpio_irqchip,
|
||||
0,
|
||||
handle_simple_irq,
|
||||
IRQ_TYPE_EDGE_FALLING);
|
||||
if (err) {
|
||||
dev_err(gpio->dev, "no GPIO irqchip\n");
|
||||
goto err_no_irqchip;
|
||||
}
|
||||
|
||||
/* Add each port with its IRQ separately */
|
||||
for (portno = 0 ; portno < U300_GPIO_NUM_PORTS; portno++) {
|
||||
struct u300_gpio_port *port = &gpio->ports[portno];
|
||||
|
||||
snprintf(port->name, 8, "gpio%d", portno);
|
||||
port->number = portno;
|
||||
port->gpio = gpio;
|
||||
|
||||
port->irq = platform_get_irq(pdev, portno);
|
||||
|
||||
gpiochip_set_chained_irqchip(&gpio->chip,
|
||||
&u300_gpio_irqchip,
|
||||
port->irq,
|
||||
u300_gpio_irq_handler);
|
||||
|
||||
/* Turns off irq force (test register) for this port */
|
||||
writel(0x0, gpio->base + portno * gpio->stride + ifr);
|
||||
}
|
||||
dev_dbg(gpio->dev, "initialized %d GPIO ports\n", portno);
|
||||
|
||||
/*
|
||||
* Add pinctrl pin ranges, the pin controller must be registered
|
||||
* at this point
|
||||
|
@ -850,12 +755,10 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
err_no_range:
|
||||
err_no_irqchip:
|
||||
if (gpiochip_remove(&gpio->chip))
|
||||
dev_err(&pdev->dev, "failed to remove gpio chip\n");
|
||||
err_no_chip:
|
||||
err_no_domain:
|
||||
err_no_port:
|
||||
u300_gpio_free_ports(gpio);
|
||||
clk_disable_unprepare(gpio->clk);
|
||||
dev_err(&pdev->dev, "module ERROR:%d\n", err);
|
||||
return err;
|
||||
|
@ -874,7 +777,6 @@ static int __exit u300_gpio_remove(struct platform_device *pdev)
|
|||
dev_err(gpio->dev, "unable to remove gpiochip: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
u300_gpio_free_ports(gpio);
|
||||
clk_disable_unprepare(gpio->clk);
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue