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

Commit 7ca72253 authored by Herbert Valerio Riedel's avatar Herbert Valerio Riedel Committed by Russell King
Browse files

[ARM] 4669/1: ep93xx: simplify GPIO code and cleanups



This patch renumbers the (virtual) GPIO line numbering to have all
irq-capable gpio lines <= EP93XX_GPIO_LINE_MAX_IRQ by swapping the
port f range with the port c range; This simplifies code such as

 #define IRQ_EP93XX_GPIO(x)  (64 + (((x) + (((x) >> 2) & 8)) & 0x1f))

or

 if (line >= 0 && line < 16) {
    /* Port A/B */
 } else if (line >= 40 && line < 48) {
    /* Port F */
 }

considerably; in addition to the renumbering this patch also
introduces macro constants EP93XX_GPIO_LINE_MAX_IRQ and
EP93XX_GPIO_LINE_MAX, and replaces most magic numbers by those and
invocations of gpio_to_irq()/irq_to_gpio().

Signed-off-by: default avatarHerbert Valerio Riedel <hvr@gnu.org>
Acked-by: default avatarLennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 4e9f9fd5
Loading
Loading
Loading
Loading
+70 −77
Original line number Diff line number Diff line
@@ -157,35 +157,35 @@ static unsigned char gpio_int_enabled[3];
static unsigned char gpio_int_type1[3];
static unsigned char gpio_int_type2[3];

static void update_gpio_int_params(int abf)
/* Port ordering is: A B F */
static const u8 int_type1_register_offset[3]	= { 0x90, 0xac, 0x4c };
static const u8 int_type2_register_offset[3]	= { 0x94, 0xb0, 0x50 };
static const u8 eoi_register_offset[3]		= { 0x98, 0xb4, 0x54 };
static const u8 int_en_register_offset[3]	= { 0x9c, 0xb8, 0x5c };

static void update_gpio_int_params(unsigned port)
{
	if (abf == 0) {
		__raw_writeb(0, EP93XX_GPIO_A_INT_ENABLE);
		__raw_writeb(gpio_int_type2[0], EP93XX_GPIO_A_INT_TYPE2);
		__raw_writeb(gpio_int_type1[0], EP93XX_GPIO_A_INT_TYPE1);
		__raw_writeb(gpio_int_unmasked[0] & gpio_int_enabled[0], EP93XX_GPIO_A_INT_ENABLE);
	} else if (abf == 1) {
		__raw_writeb(0, EP93XX_GPIO_B_INT_ENABLE);
		__raw_writeb(gpio_int_type2[1], EP93XX_GPIO_B_INT_TYPE2);
		__raw_writeb(gpio_int_type1[1], EP93XX_GPIO_B_INT_TYPE1);
		__raw_writeb(gpio_int_unmasked[1] & gpio_int_enabled[1], EP93XX_GPIO_B_INT_ENABLE);
	} else if (abf == 2) {
		__raw_writeb(0, EP93XX_GPIO_F_INT_ENABLE);
		__raw_writeb(gpio_int_type2[2], EP93XX_GPIO_F_INT_TYPE2);
		__raw_writeb(gpio_int_type1[2], EP93XX_GPIO_F_INT_TYPE1);
		__raw_writeb(gpio_int_unmasked[2] & gpio_int_enabled[2], EP93XX_GPIO_F_INT_ENABLE);
	} else {
		BUG();
	}
}
	BUG_ON(port > 2);

	__raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port]));

	__raw_writeb(gpio_int_type2[port],
		EP93XX_GPIO_REG(int_type2_register_offset[port]));

static unsigned char data_register_offset[8] = {
	0x00, 0x04, 0x08, 0x0c, 0x20, 0x30, 0x38, 0x40,
	__raw_writeb(gpio_int_type1[port],
		EP93XX_GPIO_REG(int_type1_register_offset[port]));

	__raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
		EP93XX_GPIO_REG(int_en_register_offset[port]));
}

/* Port ordering is: A B F D E C G H */
static const u8 data_register_offset[8] = {
	0x00, 0x04, 0x30, 0x0c, 0x20, 0x08, 0x38, 0x40,
};

static unsigned char data_direction_register_offset[8] = {
	0x10, 0x14, 0x18, 0x1c, 0x24, 0x34, 0x3c, 0x44,
static const u8 data_direction_register_offset[8] = {
	0x10, 0x14, 0x34, 0x1c, 0x24, 0x18, 0x3c, 0x44,
};

static void ep93xx_gpio_set_direction(unsigned line, int direction)
@@ -199,14 +199,10 @@ static void ep93xx_gpio_set_direction(unsigned line, int direction)

	local_irq_save(flags);
	if (direction == GPIO_OUT) {
		if (line >= 0 && line < 16) {
			/* Port A/B.  */
		if (line >= 0 && line <= EP93XX_GPIO_LINE_MAX_IRQ) {
			/* Port A/B/F */
			gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
			update_gpio_int_params(line >> 3);
		} else if (line >= 40 && line < 48) {
			/* Port F.  */
			gpio_int_unmasked[2] &= ~(1 << (line & 7));
			update_gpio_int_params(2);
		}

		v = __raw_readb(data_direction_register);
@@ -228,7 +224,7 @@ EXPORT_SYMBOL(gpio_line_config);

int gpio_direction_input(unsigned gpio)
{
	if (gpio > EP93XX_GPIO_LINE_H(7))
	if (gpio > EP93XX_GPIO_LINE_MAX)
		return -EINVAL;

	ep93xx_gpio_set_direction(gpio, GPIO_IN);
@@ -239,7 +235,7 @@ EXPORT_SYMBOL(gpio_direction_input);

int gpio_direction_output(unsigned gpio, int value)
{
	if (gpio > EP93XX_GPIO_LINE_H(7))
	if (gpio > EP93XX_GPIO_LINE_MAX)
		return -EINVAL;

	gpio_set_value(gpio, value);
@@ -290,47 +286,50 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
	status = __raw_readb(EP93XX_GPIO_A_INT_STATUS);
	for (i = 0; i < 8; i++) {
		if (status & (1 << i)) {
			desc = irq_desc + IRQ_EP93XX_GPIO(0) + i;
			desc_handle_irq(IRQ_EP93XX_GPIO(0) + i, desc);
			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i;
			desc = irq_desc + gpio_irq;
			desc_handle_irq(gpio_irq, desc);
		}
	}

	status = __raw_readb(EP93XX_GPIO_B_INT_STATUS);
	for (i = 0; i < 8; i++) {
		if (status & (1 << i)) {
			desc = irq_desc + IRQ_EP93XX_GPIO(8) + i;
			desc_handle_irq(IRQ_EP93XX_GPIO(8) + i, desc);
			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i;
			desc = irq_desc + gpio_irq;
			desc_handle_irq(gpio_irq, desc);
		}
	}
}

static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
{
	int gpio_irq = IRQ_EP93XX_GPIO(16) + (((irq + 1) & 7) ^ 4);
	/*
	 * map discontiguous hw irq range to continous sw irq range:
	 *
	 *  IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7})
	 */
	int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */
	int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx;

	desc_handle_irq(gpio_irq, irq_desc + gpio_irq);
}

static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
{
	int line = irq - IRQ_EP93XX_GPIO(0);
	int line = irq_to_gpio(irq);
	int port = line >> 3;
	int port_mask = 1 << (line & 7);

	gpio_int_unmasked[port] &= ~(1 << (line & 7));
	gpio_int_unmasked[port] &= ~port_mask;
	update_gpio_int_params(port);

	if (port == 0) {
		__raw_writel(1 << (line & 7), EP93XX_GPIO_A_INT_ACK);
	} else if (port == 1) {
		__raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK);
	} else if (port == 2) {
		__raw_writel(1 << (line & 7), EP93XX_GPIO_F_INT_ACK);
	}
	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
}

static void ep93xx_gpio_irq_mask(unsigned int irq)
{
	int line = irq - IRQ_EP93XX_GPIO(0);
	int line = irq_to_gpio(irq);
	int port = line >> 3;

	gpio_int_unmasked[port] &= ~(1 << (line & 7));
@@ -339,7 +338,7 @@ static void ep93xx_gpio_irq_mask(unsigned int irq)

static void ep93xx_gpio_irq_unmask(unsigned int irq)
{
	int line = irq - IRQ_EP93XX_GPIO(0);
	int line = irq_to_gpio(irq);
	int port = line >> 3;

	gpio_int_unmasked[port] |= 1 << (line & 7);
@@ -354,37 +353,30 @@ static void ep93xx_gpio_irq_unmask(unsigned int irq)
 */
static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
{
	int port;
	int line;
	const int gpio = irq_to_gpio(irq);
	const int port = gpio >> 3;
	const int port_mask = 1 << (gpio & 7);

	line = irq - IRQ_EP93XX_GPIO(0);
	if (line >= 0 && line < 16) {
		ep93xx_gpio_set_direction(line, GPIO_IN);
	} else {
		ep93xx_gpio_set_direction(EP93XX_GPIO_LINE_F(line-16), GPIO_IN);
	}

	port = line >> 3;
	line &= 7;
	ep93xx_gpio_set_direction(gpio, GPIO_IN);

	if (type & IRQT_RISING) {
		gpio_int_enabled[port] |= 1 << line;
		gpio_int_type1[port] |= 1 << line;
		gpio_int_type2[port] |= 1 << line;
		gpio_int_enabled[port] |= port_mask;
		gpio_int_type1[port] |= port_mask;
		gpio_int_type2[port] |= port_mask;
	} else if (type & IRQT_FALLING) {
		gpio_int_enabled[port] |= 1 << line;
		gpio_int_type1[port] |= 1 << line;
		gpio_int_type2[port] &= ~(1 << line);
		gpio_int_enabled[port] |= port_mask;
		gpio_int_type1[port] |= port_mask;
		gpio_int_type2[port] &= ~port_mask;
	} else if (type & IRQT_HIGH) {
		gpio_int_enabled[port] |= 1 << line;
		gpio_int_type1[port] &= ~(1 << line);
		gpio_int_type2[port] |= 1 << line;
		gpio_int_enabled[port] |= port_mask;
		gpio_int_type1[port] &= ~port_mask;
		gpio_int_type2[port] |= port_mask;
	} else if (type & IRQT_LOW) {
		gpio_int_enabled[port] |= 1 << line;
		gpio_int_type1[port] &= ~(1 << line);
		gpio_int_type2[port] &= ~(1 << line);
		gpio_int_enabled[port] |= port_mask;
		gpio_int_type1[port] &= ~port_mask;
		gpio_int_type2[port] &= ~port_mask;
	} else {
		gpio_int_enabled[port] &= ~(1 << line);
		gpio_int_enabled[port] &= ~port_mask;
	}
	update_gpio_int_params(port);

@@ -402,15 +394,16 @@ static struct irq_chip ep93xx_gpio_irq_chip = {

void __init ep93xx_init_irq(void)
{
	int irq;
	int gpio_irq;

	vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK);
	vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK);

	for (irq = IRQ_EP93XX_GPIO(0); irq <= IRQ_EP93XX_GPIO(23); irq++) {
		set_irq_chip(irq, &ep93xx_gpio_irq_chip);
		set_irq_handler(irq, handle_level_irq);
		set_irq_flags(irq, IRQF_VALID);
	for (gpio_irq = gpio_to_irq(0);
	     gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
		set_irq_chip(gpio_irq, &ep93xx_gpio_irq_chip);
		set_irq_handler(gpio_irq, handle_level_irq);
		set_irq_flags(gpio_irq, IRQF_VALID);
	}

	set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler);
+12 −15
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@
#define EP93XX_GPIO_LINE_EGPIO15	EP93XX_GPIO_LINE_B(7)

/* GPIO port C.  */
#define EP93XX_GPIO_LINE_C(x)		((x) + 16)
#define EP93XX_GPIO_LINE_C(x)		((x) + 40)
#define EP93XX_GPIO_LINE_ROW0		EP93XX_GPIO_LINE_C(0)
#define EP93XX_GPIO_LINE_ROW1		EP93XX_GPIO_LINE_C(1)
#define EP93XX_GPIO_LINE_ROW2		EP93XX_GPIO_LINE_C(2)
@@ -61,7 +61,7 @@
#define EP93XX_GPIO_LINE_IDEDA2		EP93XX_GPIO_LINE_E(7)

/* GPIO port F.  */
#define EP93XX_GPIO_LINE_F(x)		((x) + 40)
#define EP93XX_GPIO_LINE_F(x)		((x) + 16)
#define EP93XX_GPIO_LINE_WP		EP93XX_GPIO_LINE_F(0)
#define EP93XX_GPIO_LINE_MCCD1		EP93XX_GPIO_LINE_F(1)
#define EP93XX_GPIO_LINE_MCCD2		EP93XX_GPIO_LINE_F(2)
@@ -93,11 +93,17 @@
#define EP93XX_GPIO_LINE_DD6		EP93XX_GPIO_LINE_H(6)
#define EP93XX_GPIO_LINE_DD7		EP93XX_GPIO_LINE_H(7)

/* maximum value for gpio line identifiers */
#define EP93XX_GPIO_LINE_MAX		EP93XX_GPIO_LINE_H(7)

/* maximum value for irq capable line identifiers */
#define EP93XX_GPIO_LINE_MAX_IRQ	EP93XX_GPIO_LINE_F(7)

/* new generic GPIO API - see Documentation/gpio.txt */

static inline int gpio_request(unsigned gpio, const char *label)
{
	if (gpio > EP93XX_GPIO_LINE_H(7))
	if (gpio > EP93XX_GPIO_LINE_MAX)
		return -EINVAL;
	return 0;
}
@@ -116,29 +122,20 @@ void gpio_set_value(unsigned gpio, int value);
/*
 * Map GPIO A0..A7  (0..7)  to irq 64..71,
 *          B0..B7  (7..15) to irq 72..79, and
 *          F0..F7 (40..47) to irq 80..87.
 *          F0..F7 (16..24) to irq 80..87.
 */

static inline int gpio_to_irq(unsigned gpio)
{
	if (gpio <= EP93XX_GPIO_LINE_EGPIO15)
	if (gpio <= EP93XX_GPIO_LINE_MAX_IRQ)
		return 64 + gpio;

	if (gpio >= EP93XX_GPIO_LINE_F(0) && gpio <= EP93XX_GPIO_LINE_F(7))
		return 80 + (gpio - EP93XX_GPIO_LINE_F(0));

	return -EINVAL;
}

static inline int irq_to_gpio(unsigned irq)
{
	if (irq >= 64 && irq <= 79)
		return irq - 64;

	if (irq >= 80 && irq <= 87)
		return (irq - 80) + EP93XX_GPIO_LINE_F(0);

	return -EINVAL;
	return irq - gpio_to_irq(0);
}

/* obsolete specific GPIO API */
+0 −6
Original line number Diff line number Diff line
@@ -67,12 +67,6 @@
#define IRQ_EP93XX_SAI			60
#define EP93XX_VIC2_VALID_IRQ_MASK	0x1fffffff

/*
 * Map GPIO A0..A7 to irq 64..71, B0..B7 to 72..79, and
 * F0..F7 to 80..87.
 */
#define IRQ_EP93XX_GPIO(x)		(64 + (((x) + (((x) >> 2) & 8)) & 0x1f))

#define NR_EP93XX_IRQS			(64 + 24)

#define EP93XX_BOARD_IRQ(x)		(NR_EP93XX_IRQS + (x))