summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ixp4xx/common.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2019-01-25 22:58:39 +0100
committerLinus Walleij <linus.walleij@linaro.org>2019-04-23 16:02:13 +0200
commit55ec465e733e60d2d524bd42ff19b66ed21f01df (patch)
treea55db9bcff920c42ba476e229b5808e0a1c8857f /arch/arm/mach-ixp4xx/common.c
parent813e7d36f22762f89856048a32446c8972309566 (diff)
downloadlinux-55ec465e733e60d2d524bd42ff19b66ed21f01df.tar.bz2
ARM: ixp4xx: Switch to use new IRQ+GPIO drivers
This deletes the old irq+gpiochip combo from the IXP4xx machine and switches it over to use the new drivers merged in respective subsystem. Cc: Jason Cooper <jason@lakedaemon.net> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com> Acked-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'arch/arm/mach-ixp4xx/common.c')
-rw-r--r--arch/arm/mach-ixp4xx/common.c318
1 files changed, 22 insertions, 296 deletions
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index aa8fd248c125..71683dfc48f9 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -27,11 +27,11 @@
#include <linux/clockchips.h>
#include <linux/io.h>
#include <linux/export.h>
-#include <linux/gpio/driver.h>
#include <linux/cpu.h>
#include <linux/pci.h>
#include <linux/sched_clock.h>
#include <linux/bitops.h>
+#include <linux/irqchip/irq-ixp4xx.h>
#include <mach/udc.h>
#include <mach/hardware.h>
#include <mach/io.h>
@@ -58,7 +58,6 @@
(IXP4XX_OST_RELOAD_MASK + 1) * HZ) * \
(IXP4XX_OST_RELOAD_MASK + 1)
-static struct irq_domain *ixp4xx_irqdomain;
static void __init ixp4xx_clocksource_init(void);
static void __init ixp4xx_clockevent_init(void);
static struct clock_event_device clockevent_ixp4xx;
@@ -95,266 +94,18 @@ void __init ixp4xx_map_io(void)
iotable_init(ixp4xx_io_desc, ARRAY_SIZE(ixp4xx_io_desc));
}
-/*
- * GPIO-functions
- */
-/*
- * The following converted to the real HW bits the gpio_line_config
- */
-/* GPIO pin types */
-#define IXP4XX_GPIO_OUT 0x1
-#define IXP4XX_GPIO_IN 0x2
-
-/* GPIO signal types */
-#define IXP4XX_GPIO_LOW 0
-#define IXP4XX_GPIO_HIGH 1
-
-/* GPIO Clocks */
-#define IXP4XX_GPIO_CLK_0 14
-#define IXP4XX_GPIO_CLK_1 15
-
-static void gpio_line_config(u8 line, u32 direction)
-{
- if (direction == IXP4XX_GPIO_IN)
- *IXP4XX_GPIO_GPOER |= (1 << line);
- else
- *IXP4XX_GPIO_GPOER &= ~(1 << line);
-}
-
-static void gpio_line_get(u8 line, int *value)
-{
- *value = (*IXP4XX_GPIO_GPINR >> line) & 0x1;
-}
-
-static void gpio_line_set(u8 line, int value)
-{
- if (value == IXP4XX_GPIO_HIGH)
- *IXP4XX_GPIO_GPOUTR |= (1 << line);
- else if (value == IXP4XX_GPIO_LOW)
- *IXP4XX_GPIO_GPOUTR &= ~(1 << line);
-}
-
-/*************************************************************************
- * IXP4xx chipset IRQ handling
- *
- * TODO: GPIO IRQs should be marked invalid until the user of the IRQ
- * (be it PCI or something else) configures that GPIO line
- * as an IRQ.
- **************************************************************************/
-enum ixp4xx_irq_type {
- IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE
-};
-
-/* Each bit represents an IRQ: 1: edge-triggered, 0: level triggered */
-static unsigned long long ixp4xx_irq_edge = 0;
-
-/*
- * IRQ -> GPIO mapping table
- */
-static signed char irq2gpio[32] = {
- -1, -1, -1, -1, -1, -1, 0, 1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, -1, -1,
-};
-
-static int ixp4xx_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
-{
- int irq;
-
- for (irq = 0; irq < 32; irq++) {
- if (irq2gpio[irq] == gpio)
- return irq;
- }
- return -EINVAL;
-}
-
-static int ixp4xx_set_irq_type(struct irq_data *d, unsigned int type)
-{
- int line = irq2gpio[d->hwirq];
- u32 int_style;
- enum ixp4xx_irq_type irq_type;
- volatile u32 *int_reg;
-
- /*
- * Only for GPIO IRQs
- * all other IRQs are simply active low
- */
- if (line < 0)
- return 0;
-
- switch (type){
- case IRQ_TYPE_EDGE_BOTH:
- int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
- irq_type = IXP4XX_IRQ_EDGE;
- break;
- case IRQ_TYPE_EDGE_RISING:
- int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
- irq_type = IXP4XX_IRQ_EDGE;
- break;
- case IRQ_TYPE_EDGE_FALLING:
- int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
- irq_type = IXP4XX_IRQ_EDGE;
- break;
- case IRQ_TYPE_LEVEL_HIGH:
- int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
- irq_type = IXP4XX_IRQ_LEVEL;
- break;
- case IRQ_TYPE_LEVEL_LOW:
- int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
- irq_type = IXP4XX_IRQ_LEVEL;
- break;
- default:
- return -EINVAL;
- }
-
- if (irq_type == IXP4XX_IRQ_EDGE)
- ixp4xx_irq_edge |= (1 << d->hwirq);
- else
- ixp4xx_irq_edge &= ~(1 << d->hwirq);
-
- if (line >= 8) { /* pins 8-15 */
- line -= 8;
- int_reg = IXP4XX_GPIO_GPIT2R;
- } else { /* pins 0-7 */
- int_reg = IXP4XX_GPIO_GPIT1R;
- }
-
- /* Clear the style for the appropriate pin */
- *int_reg &= ~(IXP4XX_GPIO_STYLE_CLEAR <<
- (line * IXP4XX_GPIO_STYLE_SIZE));
-
- *IXP4XX_GPIO_GPISR = (1 << line);
-
- /* Set the new style */
- *int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
-
- /* Configure the line as an input */
- gpio_line_config(irq2gpio[d->hwirq], IXP4XX_GPIO_IN);
-
- return 0;
-}
-
-static void ixp4xx_irq_mask(struct irq_data *d)
-{
- if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && d->hwirq >= 32)
- *IXP4XX_ICMR2 &= ~(1 << (d->hwirq - 32));
- else
- *IXP4XX_ICMR &= ~(1 << d->hwirq);
-}
-
-static void ixp4xx_irq_ack(struct irq_data *d)
-{
- int line = (d->hwirq < 32) ? irq2gpio[d->hwirq] : -1;
-
- if (line >= 0)
- *IXP4XX_GPIO_GPISR = (1 << line);
-}
-
-/*
- * Level triggered interrupts on GPIO lines can only be cleared when the
- * interrupt condition disappears.
- */
-static void ixp4xx_irq_unmask(struct irq_data *d)
-{
- if (!(ixp4xx_irq_edge & (1 << d->hwirq)))
- ixp4xx_irq_ack(d);
-
- if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && d->hwirq >= 32)
- *IXP4XX_ICMR2 |= (1 << (d->hwirq - 32));
- else
- *IXP4XX_ICMR |= (1 << d->hwirq);
-}
-
-static struct irq_chip ixp4xx_irq_chip = {
- .name = "IXP4xx",
- .irq_ack = ixp4xx_irq_ack,
- .irq_mask = ixp4xx_irq_mask,
- .irq_unmask = ixp4xx_irq_unmask,
- .irq_set_type = ixp4xx_set_irq_type,
-};
-
-asmlinkage void __exception_irq_entry ixp4xx_handle_irq(struct pt_regs *regs)
-{
- unsigned long status;
- int i;
-
- status = *IXP4XX_ICIP;
-
- for_each_set_bit(i, &status, 32)
- handle_domain_irq(ixp4xx_irqdomain, i, regs);
-
- /*
- * IXP465/IXP435 has an upper IRQ status register
- */
- if ((cpu_is_ixp46x() || cpu_is_ixp43x())) {
- status = *IXP4XX_ICIP2;
- for_each_set_bit(i, &status, 32)
- handle_domain_irq(ixp4xx_irqdomain, i + 32, regs);
- }
-}
-
-static int ixp4xx_irqdomain_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hwirq)
-{
- irq_set_chip_data(irq, &ixp4xx_irq_chip);
- irq_set_chip_and_handler(irq, &ixp4xx_irq_chip, handle_level_irq);
- irq_set_probe(irq);
-
- return 0;
-}
-
-static void ixp4xx_irqdomain_unmap(struct irq_domain *d, unsigned int irq)
-{
- irq_set_chip_and_handler(irq, NULL, NULL);
- irq_set_chip_data(irq, NULL);
-}
-
-static const struct irq_domain_ops ixp4xx_irqdomain_ops = {
- .map = ixp4xx_irqdomain_map,
- .unmap = ixp4xx_irqdomain_unmap,
-};
-
void __init ixp4xx_init_irq(void)
{
- int nr_irqs;
-
/*
* ixp4xx does not implement the XScale PWRMODE register
* so it must not call cpu_do_idle().
*/
cpu_idle_poll_ctrl(true);
- /* Route all sources to IRQ instead of FIQ */
- *IXP4XX_ICLR = 0x0;
-
- /* Disable all interrupt */
- *IXP4XX_ICMR = 0x0;
-
- if (cpu_is_ixp46x() || cpu_is_ixp43x()) {
- /* Route upper 32 sources to IRQ instead of FIQ */
- *IXP4XX_ICLR2 = 0x00;
-
- /* Disable upper 32 interrupts */
- *IXP4XX_ICMR2 = 0x00;
-
- nr_irqs = 64;
- } else {
- nr_irqs = 32;
- }
-
- ixp4xx_irqdomain = irq_domain_add_simple(NULL, nr_irqs, IRQ_IXP4XX_BASE,
- &ixp4xx_irqdomain_ops,
- NULL);
- if (!ixp4xx_irqdomain) {
- pr_crit("can not add primary irqdomain\n");
- return;
- }
-
- set_handle_irq(ixp4xx_handle_irq);
+ ixp4xx_irq_init(IXP4XX_INTC_BASE_PHYS,
+ (cpu_is_ixp46x() || cpu_is_ixp43x()));
}
-
/*************************************************************************
* IXP4xx timer tick
* We use OS timer1 on the CPU for the timer tick and the timestamp
@@ -408,6 +159,24 @@ static struct resource ixp4xx_udc_resources[] = {
},
};
+static struct resource ixp4xx_gpio_resource[] = {
+ {
+ .start = IXP4XX_GPIO_BASE_PHYS,
+ .end = IXP4XX_GPIO_BASE_PHYS + 0xfff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ixp4xx_gpio_device = {
+ .name = "ixp4xx-gpio",
+ .id = -1,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .resource = ixp4xx_gpio_resource,
+ .num_resources = ARRAY_SIZE(ixp4xx_gpio_resource),
+};
+
/*
* USB device controller. The IXP4xx uses the same controller as PXA25X,
* so we just use the same device.
@@ -423,6 +192,7 @@ static struct platform_device ixp4xx_udc_device = {
};
static struct platform_device *ixp4xx_devices[] __initdata = {
+ &ixp4xx_gpio_device,
&ixp4xx_udc_device,
};
@@ -457,56 +227,12 @@ static struct platform_device *ixp46x_devices[] __initdata = {
unsigned long ixp4xx_exp_bus_size;
EXPORT_SYMBOL(ixp4xx_exp_bus_size);
-static int ixp4xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
-{
- gpio_line_config(gpio, IXP4XX_GPIO_IN);
-
- return 0;
-}
-
-static int ixp4xx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
- int level)
-{
- gpio_line_set(gpio, level);
- gpio_line_config(gpio, IXP4XX_GPIO_OUT);
-
- return 0;
-}
-
-static int ixp4xx_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
-{
- int value;
-
- gpio_line_get(gpio, &value);
-
- return value;
-}
-
-static void ixp4xx_gpio_set_value(struct gpio_chip *chip, unsigned gpio,
- int value)
-{
- gpio_line_set(gpio, value);
-}
-
-static struct gpio_chip ixp4xx_gpio_chip = {
- .label = "IXP4XX_GPIO_CHIP",
- .direction_input = ixp4xx_gpio_direction_input,
- .direction_output = ixp4xx_gpio_direction_output,
- .get = ixp4xx_gpio_get_value,
- .set = ixp4xx_gpio_set_value,
- .to_irq = ixp4xx_gpio_to_irq,
- .base = 0,
- .ngpio = 16,
-};
-
void __init ixp4xx_sys_init(void)
{
ixp4xx_exp_bus_size = SZ_16M;
platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices));
- gpiochip_add_data(&ixp4xx_gpio_chip, NULL);
-
if (cpu_is_ixp46x()) {
int region;