static void set_gpio_irqenable(struct mxs_gpio_port *port, u32 index,
                               int enable)
{
    if (enable) {
        __mxs_setl(1 << index, port->base + PINCTRL_IRQEN(port->id));
        __mxs_setl(1 << index, port->base + PINCTRL_PIN2IRQ(port->id));
    } else {
        __mxs_clrl(1 << index, port->base + PINCTRL_IRQEN(port->id));
    }
}
Esempio n. 2
0
void mxs_gpio_init(void)
{
	int i;

	for (i = 0; i < PINCTRL_BANKS; i++) {
		writel(0, MXS_PINCTRL_BASE + PINCTRL_PIN2IRQ(i));
		writel(0, MXS_PINCTRL_BASE + PINCTRL_IRQEN(i));
		/* Use SCT address here to clear the IRQSTAT bits */
		writel(0xffffffff, MXS_PINCTRL_BASE + PINCTRL_IRQSTAT(i) + 8);
	}
}
/* MXS has one interrupt *per* gpio port */
static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
{
    u32 irq_stat;
    struct mxs_gpio_port *port = (struct mxs_gpio_port *)get_irq_data(irq);
    u32 gpio_irq_no_base = port->virtual_irq_start;

    desc->irq_data.chip->irq_ack(&desc->irq_data);

    irq_stat = __raw_readl(port->base + PINCTRL_IRQSTAT(port->id)) &
               __raw_readl(port->base + PINCTRL_IRQEN(port->id));

    while (irq_stat != 0) {
        int irqoffset = fls(irq_stat) - 1;
        generic_handle_irq(gpio_irq_no_base + irqoffset);
        irq_stat &= ~(1 << irqoffset);
    }
}
int __init mxs_gpio_init(struct mxs_gpio_port *port, int cnt)
{
    int i, j;

    /* save for local usage */
    mxs_gpio_ports = port;
    gpio_table_size = cnt;

    pr_info("MXS GPIO hardware\n");

    for (i = 0; i < cnt; i++) {
        /* disable the interrupt and clear the status */
        __raw_writel(0, port[i].base + PINCTRL_PIN2IRQ(i));
        __raw_writel(0, port[i].base + PINCTRL_IRQEN(i));

        /* clear address has to be used to clear IRQSTAT bits */
        __mxs_clrl(~0U, port[i].base + PINCTRL_IRQSTAT(i));

        for (j = port[i].virtual_irq_start;
                j < port[i].virtual_irq_start + 32; j++) {
            set_irq_chip(j, &gpio_irq_chip);
            set_irq_handler(j, handle_level_irq);
            set_irq_flags(j, IRQF_VALID);
        }

        /* setup one handler for each entry */
        set_irq_chained_handler(port[i].irq, mxs_gpio_irq_handler);
        set_irq_data(port[i].irq, &port[i]);

        /* register gpio chip */
        port[i].chip.direction_input = mxs_gpio_direction_input;
        port[i].chip.direction_output = mxs_gpio_direction_output;
        port[i].chip.get = mxs_gpio_get;
        port[i].chip.set = mxs_gpio_set;
        port[i].chip.to_irq = mxs_gpio_to_irq;
        port[i].chip.base = i * 32;
        port[i].chip.ngpio = 32;

        /* its a serious configuration bug when it fails */
        BUG_ON(gpiochip_add(&port[i].chip) < 0);
    }

    return 0;
}