|
@@ -157,35 +157,35 @@ static unsigned char gpio_int_enabled[3];
|
|
static unsigned char gpio_int_type1[3];
|
|
static unsigned char gpio_int_type1[3];
|
|
static unsigned char gpio_int_type2[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]));
|
|
|
|
+
|
|
|
|
+ __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]));
|
|
|
|
+}
|
|
|
|
|
|
-static unsigned char data_register_offset[8] = {
|
|
|
|
- 0x00, 0x04, 0x08, 0x0c, 0x20, 0x30, 0x38, 0x40,
|
|
|
|
|
|
+/* 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)
|
|
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);
|
|
local_irq_save(flags);
|
|
if (direction == GPIO_OUT) {
|
|
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));
|
|
gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
|
|
update_gpio_int_params(line >> 3);
|
|
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);
|
|
v = __raw_readb(data_direction_register);
|
|
@@ -228,7 +224,7 @@ EXPORT_SYMBOL(gpio_line_config);
|
|
|
|
|
|
int gpio_direction_input(unsigned gpio)
|
|
int gpio_direction_input(unsigned gpio)
|
|
{
|
|
{
|
|
- if (gpio > EP93XX_GPIO_LINE_H(7))
|
|
|
|
|
|
+ if (gpio > EP93XX_GPIO_LINE_MAX)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
ep93xx_gpio_set_direction(gpio, GPIO_IN);
|
|
ep93xx_gpio_set_direction(gpio, GPIO_IN);
|
|
@@ -239,7 +235,7 @@ EXPORT_SYMBOL(gpio_direction_input);
|
|
|
|
|
|
int gpio_direction_output(unsigned gpio, int value)
|
|
int gpio_direction_output(unsigned gpio, int value)
|
|
{
|
|
{
|
|
- if (gpio > EP93XX_GPIO_LINE_H(7))
|
|
|
|
|
|
+ if (gpio > EP93XX_GPIO_LINE_MAX)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
gpio_set_value(gpio, value);
|
|
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);
|
|
status = __raw_readb(EP93XX_GPIO_A_INT_STATUS);
|
|
for (i = 0; i < 8; i++) {
|
|
for (i = 0; i < 8; i++) {
|
|
if (status & (1 << 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);
|
|
status = __raw_readb(EP93XX_GPIO_B_INT_STATUS);
|
|
for (i = 0; i < 8; i++) {
|
|
for (i = 0; i < 8; i++) {
|
|
if (status & (1 << 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)
|
|
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);
|
|
desc_handle_irq(gpio_irq, irq_desc + gpio_irq);
|
|
}
|
|
}
|
|
|
|
|
|
static void ep93xx_gpio_irq_mask_ack(unsigned int 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 = 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);
|
|
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)
|
|
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;
|
|
int port = line >> 3;
|
|
|
|
|
|
gpio_int_unmasked[port] &= ~(1 << (line & 7));
|
|
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)
|
|
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;
|
|
int port = line >> 3;
|
|
|
|
|
|
gpio_int_unmasked[port] |= 1 << (line & 7);
|
|
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)
|
|
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) {
|
|
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) {
|
|
} 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) {
|
|
} 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) {
|
|
} 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 {
|
|
} else {
|
|
- gpio_int_enabled[port] &= ~(1 << line);
|
|
|
|
|
|
+ gpio_int_enabled[port] &= ~port_mask;
|
|
}
|
|
}
|
|
update_gpio_int_params(port);
|
|
update_gpio_int_params(port);
|
|
|
|
|
|
@@ -402,15 +394,16 @@ static struct irq_chip ep93xx_gpio_irq_chip = {
|
|
|
|
|
|
void __init ep93xx_init_irq(void)
|
|
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_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK);
|
|
vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_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);
|
|
set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler);
|