Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+65 −90
Original line number Original line Diff line number Diff line
@@ -38,90 +38,6 @@
#include <asm/mach/irq.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.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
 * 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
 *       (be it PCI or something else) configures that GPIO line
 *       as an IRQ.
 *       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)
static void ixp4xx_irq_mask(unsigned int irq)
{
{
	if (cpu_is_ixp46x() && irq >= 32)
	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 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;
	int line = (irq < 32) ? irq2gpio[irq] : -1;


	if (line >= 0)
	if (line >= 0)
@@ -209,12 +182,14 @@ static struct irqchip ixp4xx_irq_level_chip = {
	.ack	= ixp4xx_irq_mask,
	.ack	= ixp4xx_irq_mask,
	.mask	= ixp4xx_irq_mask,
	.mask	= ixp4xx_irq_mask,
	.unmask	= ixp4xx_irq_level_unmask,
	.unmask	= ixp4xx_irq_level_unmask,
	.type	= ixp4xx_set_irq_type
};
};


static struct irqchip ixp4xx_irq_edge_chip = {
static struct irqchip ixp4xx_irq_edge_chip = {
	.ack	= ixp4xx_irq_ack,
	.ack	= ixp4xx_irq_ack,
	.mask	= ixp4xx_irq_mask,
	.mask	= ixp4xx_irq_mask,
	.unmask	= ixp4xx_irq_unmask,
	.unmask	= ixp4xx_irq_unmask,
	.type	= ixp4xx_set_irq_type
};
};


static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type)
static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type)
+2 −5
Original line number Original line Diff line number Diff line
@@ -30,11 +30,8 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);


void __init coyote_pci_preinit(void)
void __init coyote_pci_preinit(void)
{
{
	gpio_line_config(COYOTE_PCI_SLOT0_PIN,
	set_irq_type(IRQ_COYOTE_PCI_SLOT0, IRQT_LOW);
			IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
	set_irq_type(IRQ_COYOTE_PCI_SLOT1, IRQT_LOW);

	gpio_line_config(COYOTE_PCI_SLOT1_PIN,
			IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);


	gpio_line_isr_clear(COYOTE_PCI_SLOT0_PIN);
	gpio_line_isr_clear(COYOTE_PCI_SLOT0_PIN);
	gpio_line_isr_clear(COYOTE_PCI_SLOT1_PIN);
	gpio_line_isr_clear(COYOTE_PCI_SLOT1_PIN);
+11 −17
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@ extern void ixp4xx_pci_preinit(void);
extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
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);
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
 * The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h
 * Slot 0 isn't actually populated with a card connector but
 * Slot 0 isn't actually populated with a card connector but
@@ -42,19 +43,12 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
 * slot populated or someone with good soldering skills has
 * slot populated or someone with good soldering skills has
 * some free time.
 * 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)
void __init gtwx5715_pci_preinit(void)
{
{
	gtwx5715_init_gpio(GTWX5715_PCI_SLOT0_INTA_GPIO,	IXP4XX_GPIO_IN);
	set_irq_type(GTWX5715_PCI_SLOT0_INTA_IRQ, IRQT_LOW);
	gtwx5715_init_gpio(GTWX5715_PCI_SLOT1_INTA_GPIO,	IXP4XX_GPIO_IN);
	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();
	ixp4xx_pci_preinit();
}
}
+4 −8
Original line number Original line Diff line number Diff line
@@ -27,14 +27,10 @@


void __init ixdp425_pci_preinit(void)
void __init ixdp425_pci_preinit(void)
{
{
	gpio_line_config(IXDP425_PCI_INTA_PIN,
	set_irq_type(IRQ_IXDP425_PCI_INTA, IRQT_LOW);
				IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
	set_irq_type(IRQ_IXDP425_PCI_INTB, IRQT_LOW);
	gpio_line_config(IXDP425_PCI_INTB_PIN, 
	set_irq_type(IRQ_IXDP425_PCI_INTC, IRQT_LOW);
				IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
	set_irq_type(IRQ_IXDP425_PCI_INTD, IRQT_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);


	gpio_line_isr_clear(IXDP425_PCI_INTA_PIN);
	gpio_line_isr_clear(IXDP425_PCI_INTA_PIN);
	gpio_line_isr_clear(IXDP425_PCI_INTB_PIN);
	gpio_line_isr_clear(IXDP425_PCI_INTB_PIN);
+2 −2
Original line number Original line Diff line number Diff line
@@ -29,8 +29,8 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);


void __init ixdpg425_pci_preinit(void)
void __init ixdpg425_pci_preinit(void)
{
{
	gpio_line_config(6, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
	set_irq_type(IRQ_IXP4XX_GPIO6, IRQT_LOW);
	gpio_line_config(7, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
	set_irq_type(IRQ_IXP4XX_GPIO7, IRQT_LOW);


	gpio_line_isr_clear(6);
	gpio_line_isr_clear(6);
	gpio_line_isr_clear(7);
	gpio_line_isr_clear(7);
Loading