static int s5p_irq_eint_set_type(struct irq_data *data, unsigned int type) { int offs = EINT_OFFSET(data->irq); int shift; u32 ctrl, mask; u32 newvalue = 0; switch (type) { case IRQ_TYPE_EDGE_RISING: newvalue = S5P_IRQ_TYPE_EDGE_RISING; break; case IRQ_TYPE_EDGE_FALLING: newvalue = S5P_IRQ_TYPE_EDGE_FALLING; break; case IRQ_TYPE_EDGE_BOTH: newvalue = S5P_IRQ_TYPE_EDGE_BOTH; break; case IRQ_TYPE_LEVEL_LOW: newvalue = S5P_IRQ_TYPE_LEVEL_LOW; break; case IRQ_TYPE_LEVEL_HIGH: newvalue = S5P_IRQ_TYPE_LEVEL_HIGH; break; default: printk(KERN_ERR "No such irq type %d", type); return -EINVAL; } shift = (offs & 0x7) * 4; mask = 0x7 << shift; ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq))); ctrl &= ~mask; ctrl |= newvalue << shift; __raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq))); if ((0 <= offs) && (offs < 8)) s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE); else if ((8 <= offs) && (offs < 16)) s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE); else if ((16 <= offs) && (offs < 24)) s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE); else if ((24 <= offs) && (offs < 32)) s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE); else printk(KERN_ERR "No such irq number %d", offs); return 0; }
static void exynos4_irq_eint_unmask(struct irq_data *data) { u32 mask; spin_lock(&eint_lock); mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq))); mask &= ~(eint_irq_to_bit(data->irq)); __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq))); spin_unlock(&eint_lock); }
/* s5p_irq_demux_eint * * This function demuxes the IRQ from the group0 external interrupts, * from EINTs 16 to 31. It is designed to be inlined into the specific * handler s5p_irq_demux_eintX_Y. * * Each EINT pend/mask registers handle eight of them. */ static inline void s5p_irq_demux_eint(unsigned int start) { u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start))); u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start))); unsigned int irq; status &= ~mask; status &= 0xff; while (status) { irq = fls(status) - 1; generic_handle_irq(irq + start); status &= ~(1 << irq); } }
static void s5p_irq_eint_unmask(struct irq_data *data) { u32 mask; /* for level triggered interrupts, masking doesn't prevent * the interrupt from becoming pending again. by the time * the handler (either irq or thread) can do its thing to clear * the interrupt, it's too late because it could be pending * already. we have to ack it here, after the handler runs, * or else we get a false interrupt. */ if (irqd_is_level_type(data)) s5p_irq_eint_ack(data); mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq))); mask &= ~(eint_irq_to_bit(data->irq)); __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq))); }
/* exynos_irq_demux_eint * * This function demuxes the IRQ from from EINTs 16 to 31. * It is designed to be inlined into the specific handler * s5p_irq_demux_eintX_Y. * * Each EINT pend/mask registers handle eight of them. */ static inline u32 exynos_irq_demux_eint(unsigned int start) { unsigned int irq; u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start))); u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start))); u32 action = 0; status &= ~mask; status &= 0xff; while (status) { irq = fls(status) - 1; generic_handle_irq(irq + start); status &= ~(1 << irq); ++action; } return action; }
static int exynos4_irq_eint_set_type(struct irq_data *data, unsigned int type) { int offs = EINT_OFFSET(data->irq); int shift; u32 ctrl, mask; u32 newvalue = 0; switch (type) { case IRQ_TYPE_EDGE_RISING: newvalue = S5P_IRQ_TYPE_EDGE_RISING; break; case IRQ_TYPE_EDGE_FALLING: newvalue = S5P_IRQ_TYPE_EDGE_FALLING; break; case IRQ_TYPE_EDGE_BOTH: newvalue = S5P_IRQ_TYPE_EDGE_BOTH; break; case IRQ_TYPE_LEVEL_LOW: newvalue = S5P_IRQ_TYPE_LEVEL_LOW; break; case IRQ_TYPE_LEVEL_HIGH: newvalue = S5P_IRQ_TYPE_LEVEL_HIGH; break; default: printk(KERN_ERR "No such irq type %d", type); return -EINVAL; } shift = (offs & 0x7) * 4; mask = 0x7 << shift; spin_lock(&eint_lock); ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq))); ctrl &= ~mask; ctrl |= newvalue << shift; __raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq))); spin_unlock(&eint_lock); switch (offs) { case 0 ... 7: s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE); break; case 8 ... 15: s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE); break; case 16 ... 23: s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE); break; case 24 ... 31: s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE); break; default: printk(KERN_ERR "No such irq number %d", offs); } return 0; }
static inline void exynos4_irq_eint_ack(struct irq_data *data) { __raw_writel(eint_irq_to_bit(data->irq), S5P_EINT_PEND(EINT_REG_NR(data->irq))); }
static inline void s5p_irq_eint_ack(unsigned int irq) { __raw_writel(eint_irq_to_bit(irq), S5P_EINT_PEND(EINT_REG_NR(irq))); }