Low GPIO pins use an interrupt in SC interrupts space. However it's possible to handle them as if all the GPIO interrupts are instead tied to single GPIO handler, which later decodes GEDR register and chain-calls next IRQ handler. So split first 11 interrupts into system part (IRQ_GPIO0_SC - IRQ_GPIO10_SC) which work exactly like the rest of system controller interrupts and real GPIO interrupts (IRQ_GPIO0..IRQ_GPIO10). A single handler sa1100_gpio_handler then decodes and calls next handler. Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> Tested-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
70 lines
1.5 KiB
C
70 lines
1.5 KiB
C
/*
|
|
* linux/arch/arm/mach-sa1100/gpio.c
|
|
*
|
|
* Generic SA-1100 GPIO handling
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
#include <linux/gpio.h>
|
|
#include <linux/init.h>
|
|
#include <linux/module.h>
|
|
#include <linux/io.h>
|
|
#include <mach/hardware.h>
|
|
#include <mach/irqs.h>
|
|
|
|
static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset)
|
|
{
|
|
return GPLR & GPIO_GPIO(offset);
|
|
}
|
|
|
|
static void sa1100_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
|
{
|
|
if (value)
|
|
GPSR = GPIO_GPIO(offset);
|
|
else
|
|
GPCR = GPIO_GPIO(offset);
|
|
}
|
|
|
|
static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset)
|
|
{
|
|
unsigned long flags;
|
|
|
|
local_irq_save(flags);
|
|
GPDR &= ~GPIO_GPIO(offset);
|
|
local_irq_restore(flags);
|
|
return 0;
|
|
}
|
|
|
|
static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int value)
|
|
{
|
|
unsigned long flags;
|
|
|
|
local_irq_save(flags);
|
|
sa1100_gpio_set(chip, offset, value);
|
|
GPDR |= GPIO_GPIO(offset);
|
|
local_irq_restore(flags);
|
|
return 0;
|
|
}
|
|
|
|
static int sa1100_to_irq(struct gpio_chip *chip, unsigned offset)
|
|
{
|
|
return IRQ_GPIO0 + offset;
|
|
}
|
|
|
|
static struct gpio_chip sa1100_gpio_chip = {
|
|
.label = "gpio",
|
|
.direction_input = sa1100_direction_input,
|
|
.direction_output = sa1100_direction_output,
|
|
.set = sa1100_gpio_set,
|
|
.get = sa1100_gpio_get,
|
|
.to_irq = sa1100_to_irq,
|
|
.base = 0,
|
|
.ngpio = GPIO_MAX + 1,
|
|
};
|
|
|
|
void __init sa1100_init_gpio(void)
|
|
{
|
|
gpiochip_add(&sa1100_gpio_chip);
|
|
}
|