Commit bdf82b59 authored by Deepak Saxena's avatar Deepak Saxena Committed by Russell King

[ARM] 2836/1: Cleanup IXP4xx GPIO code

Patch from Deepak Saxena

This patch implements the set_irq_type() hooks for configuring GPIO
IRQ type and updates all the platforms to use it instead of the
gpio_line_config() function which is now used to configure input
vs. output on the pins.
Signed-off-by: default avatarDeepak Saxena <dsaxena@plexity.net>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent e605ecd7
......@@ -38,90 +38,6 @@
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
enum ixp4xx_irq_type {
IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE
};
static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type);
/*************************************************************************
* GPIO acces functions
*************************************************************************/
/*
* Configure GPIO line for input, interrupt, or output operation
*
* TODO: Enable/disable the irq_desc based on interrupt or output mode.
* TODO: Should these be named ixp4xx_gpio_?
*/
void gpio_line_config(u8 line, u32 style)
{
static const int gpio2irq[] = {
6, 7, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29
};
u32 enable;
volatile u32 *int_reg;
u32 int_style;
enum ixp4xx_irq_type irq_type;
enable = *IXP4XX_GPIO_GPOER;
if (style & IXP4XX_GPIO_OUT) {
enable &= ~((1) << line);
} else if (style & IXP4XX_GPIO_IN) {
enable |= ((1) << line);
switch (style & IXP4XX_GPIO_INTSTYLE_MASK)
{
case (IXP4XX_GPIO_ACTIVE_HIGH):
int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
irq_type = IXP4XX_IRQ_LEVEL;
break;
case (IXP4XX_GPIO_ACTIVE_LOW):
int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
irq_type = IXP4XX_IRQ_LEVEL;
break;
case (IXP4XX_GPIO_RISING_EDGE):
int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
irq_type = IXP4XX_IRQ_EDGE;
break;
case (IXP4XX_GPIO_FALLING_EDGE):
int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
irq_type = IXP4XX_IRQ_EDGE;
break;
case (IXP4XX_GPIO_TRANSITIONAL):
int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
irq_type = IXP4XX_IRQ_EDGE;
break;
default:
int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
irq_type = IXP4XX_IRQ_LEVEL;
break;
}
if (style & IXP4XX_GPIO_INTSTYLE_MASK)
ixp4xx_config_irq(gpio2irq[line], irq_type);
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));
/* Set the new style */
*int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
}
*IXP4XX_GPIO_GPOER = enable;
}
EXPORT_SYMBOL(gpio_line_config);
/*************************************************************************
* IXP4xx chipset I/O mapping
*************************************************************************/
......@@ -165,6 +81,69 @@ void __init ixp4xx_map_io(void)
* (be it PCI or something else) configures that GPIO line
* as an IRQ.
**************************************************************************/
enum ixp4xx_irq_type {
IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE
};
static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type);
/*
* IRQ -> GPIO mapping table
*/
static int 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_set_irq_type(unsigned int irq, unsigned int type)
{
int line = irq2gpio[irq];
u32 int_style;
enum ixp4xx_irq_type irq_type;
volatile u32 *int_reg;
/*
* Only for GPIO IRQs
*/
if (line < 0)
return -EINVAL;
if (type & IRQT_BOTHEDGE) {
int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
irq_type = IXP4XX_IRQ_EDGE;
} else if (type & IRQT_RISING) {
int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
irq_type = IXP4XX_IRQ_EDGE;
} else if (type & IRQT_FALLING) {
int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
irq_type = IXP4XX_IRQ_EDGE;
} else if (type & IRQT_HIGH) {
int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
irq_type = IXP4XX_IRQ_LEVEL;
} else if (type & IRQT_LOW) {
int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
irq_type = IXP4XX_IRQ_LEVEL;
}
ixp4xx_config_irq(irq, irq_type);
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));
/* Set the new style */
*int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
}
static void ixp4xx_irq_mask(unsigned int irq)
{
if (cpu_is_ixp46x() && irq >= 32)
......@@ -183,12 +162,6 @@ static void ixp4xx_irq_unmask(unsigned int irq)
static void ixp4xx_irq_ack(unsigned int irq)
{
static int 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,
};
int line = (irq < 32) ? irq2gpio[irq] : -1;
if (line >= 0)
......@@ -209,12 +182,14 @@ static struct irqchip ixp4xx_irq_level_chip = {
.ack = ixp4xx_irq_mask,
.mask = ixp4xx_irq_mask,
.unmask = ixp4xx_irq_level_unmask,
.type = ixp4xx_set_irq_type
};
static struct irqchip ixp4xx_irq_edge_chip = {
.ack = ixp4xx_irq_ack,
.mask = ixp4xx_irq_mask,
.unmask = ixp4xx_irq_unmask,
.type = ixp4xx_set_irq_type
};
static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type)
......
......@@ -30,11 +30,8 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
void __init coyote_pci_preinit(void)
{
gpio_line_config(COYOTE_PCI_SLOT0_PIN,
IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
gpio_line_config(COYOTE_PCI_SLOT1_PIN,
IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
set_irq_type(IRQ_COYOTE_PCI_SLOT0, IRQT_LOW);
set_irq_type(IRQ_COYOTE_PCI_SLOT1, IRQT_LOW);
gpio_line_isr_clear(COYOTE_PCI_SLOT0_PIN);
gpio_line_isr_clear(COYOTE_PCI_SLOT1_PIN);
......
......@@ -35,26 +35,20 @@ extern void ixp4xx_pci_preinit(void);
extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
/*
/*
* The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h
* Slot 0 isn't actually populated with a card connector but
* we initialize it anyway in case a future version has the
* slot populated or someone with good soldering skills has
* some free time.
*/
static void gtwx5715_init_gpio(u8 pin, u32 style)
{
gpio_line_config(pin, style | IXP4XX_GPIO_ACTIVE_LOW);
if (style & IXP4XX_GPIO_IN) gpio_line_isr_clear(pin);
}
void __init gtwx5715_pci_preinit(void)
{
gtwx5715_init_gpio(GTWX5715_PCI_SLOT0_INTA_GPIO, IXP4XX_GPIO_IN);
gtwx5715_init_gpio(GTWX5715_PCI_SLOT1_INTA_GPIO, IXP4XX_GPIO_IN);
set_irq_type(GTWX5715_PCI_SLOT0_INTA_IRQ, IRQT_LOW);
set_irq_type(GTWX5715_PCI_SLOT0_INTB_IRQ, IRQT_LOW);
set_irq_type(GTWX5715_PCI_SLOT1_INTA_IRQ, IRQT_LOW);
set_irq_type(GTWX5715_PCI_SLOT1_INTB_IRQ, IRQT_LOW);
ixp4xx_pci_preinit();
}
......
......@@ -27,14 +27,10 @@
void __init ixdp425_pci_preinit(void)
{
gpio_line_config(IXDP425_PCI_INTA_PIN,
IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
gpio_line_config(IXDP425_PCI_INTB_PIN,
IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
gpio_line_config(IXDP425_PCI_INTC_PIN,
IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
gpio_line_config(IXDP425_PCI_INTD_PIN,
IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
set_irq_type(IRQ_IXDP425_PCI_INTA, IRQT_LOW);
set_irq_type(IRQ_IXDP425_PCI_INTB, IRQT_LOW);
set_irq_type(IRQ_IXDP425_PCI_INTC, IRQT_LOW);
set_irq_type(IRQ_IXDP425_PCI_INTD, IRQT_LOW);
gpio_line_isr_clear(IXDP425_PCI_INTA_PIN);
gpio_line_isr_clear(IXDP425_PCI_INTB_PIN);
......
......@@ -29,8 +29,8 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
void __init ixdpg425_pci_preinit(void)
{
gpio_line_config(6, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
gpio_line_config(7, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
set_irq_type(IRQ_IXP4XX_GPIO6, IRQT_LOW);
set_irq_type(IRQ_IXP4XX_GPIO7, IRQT_LOW);
gpio_line_isr_clear(6);
gpio_line_isr_clear(7);
......
......@@ -83,17 +83,6 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
#define IXP4XX_GPIO_OUT 0x1
#define IXP4XX_GPIO_IN 0x2
#define IXP4XX_GPIO_INTSTYLE_MASK 0x7C /* Bits [6:2] define interrupt style */
/*
* GPIO interrupt types.
*/
#define IXP4XX_GPIO_ACTIVE_HIGH 0x4 /* Default */
#define IXP4XX_GPIO_ACTIVE_LOW 0x8
#define IXP4XX_GPIO_RISING_EDGE 0x10
#define IXP4XX_GPIO_FALLING_EDGE 0x20
#define IXP4XX_GPIO_TRANSITIONAL 0x40
/* GPIO signal types */
#define IXP4XX_GPIO_LOW 0
#define IXP4XX_GPIO_HIGH 1
......@@ -102,7 +91,13 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
#define IXP4XX_GPIO_CLK_0 14
#define IXP4XX_GPIO_CLK_1 15
extern void gpio_line_config(u8 line, u32 style);
static inline void gpio_line_config(u8 line, u32 direction)
{
if (direction == IXP4XX_GPIO_OUT)
*IXP4XX_GPIO_GPOER |= (1 << line);
else
*IXP4XX_GPIO_GPOER &= ~(1 << line);
}
static inline void gpio_line_get(u8 line, int *value)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment