static void gpio_irq_handler(int irq, void *param) { struct gpio_irq_def *irq_def = (struct gpio_irq_def *)param; rt_uint32_t pend, enable; int port, pin; rt_uint32_t addr; pin = 0; port = irq - PIOD_INTERRUPT; addr = GPIOn_INT_STA_ADDR(port); pend = readl(addr); addr = GPIOn_INT_CTRL_ADDR(port); enable = readl(addr); pend &= enable; while (pend) { if ((pend & 0x1) && (irq_def->irq_cb[pin] != RT_NULL)) { dbg_log(DBG_LOG, "do irq callback...\n", port, pin); irq_def->irq_cb[pin](irq_def->irq_arg[pin]); } pin++; pend = pend >> 1; gpio_ack_irq(port, pin); } }
void gpio_irq_handler(int irq, void *param) { struct jz_gpio_irq_def *irq_def = (struct jz_gpio_irq_def *)param; uint32_t pend,mask; uint32_t pin_id; enum gpio_port port = (IRQ_GPIO0 - irq); enum gpio_pin pin; RT_ASSERT(param != RT_NULL); GPIO_DBG("GPIO irq handler,irq=%d\n",irq); pend = readl(GPIO_PXFLG(port)); mask = readl(GPIO_PXMSK(port)); GPIO_DBG("port =%d pend =%08x mask =%08x\n",port,pend,mask); pend = pend & ~mask; while(pend) { pin_id = _fls(pend) - 1; pin = 0x01 << pin_id; GPIO_DBG("PORT%d PIN%d interrupt happened..\n",port,pin_id); if(irq_def->irq_cb[pin_id] != RT_NULL) { GPIO_DBG("do irq callback...\n",port,pin); irq_def->irq_cb[pin_id](irq_def->irq_arg[pin_id]); } pend &= ~(0x01 << pin_id); gpio_ack_irq(port, pin); } }
static int gpio_set_irq_type(struct irq_data *d, unsigned int type) { unsigned int gpio = irq_to_gpio(d->irq); unsigned int gpio_mask = 1 << (gpio % 32); void __iomem *base = GPIO_BASE(gpio / 32); unsigned int reg_both, reg_level, reg_type; reg_type = __raw_readl(base + GPIO_INT_TYPE); reg_level = __raw_readl(base + GPIO_INT_LEVEL); reg_both = __raw_readl(base + GPIO_INT_BOTH_EDGE); switch (type) { case IRQ_TYPE_EDGE_BOTH: reg_type &= ~gpio_mask; reg_both |= gpio_mask; break; case IRQ_TYPE_EDGE_RISING: reg_type &= ~gpio_mask; reg_both &= ~gpio_mask; reg_level &= ~gpio_mask; break; case IRQ_TYPE_EDGE_FALLING: reg_type &= ~gpio_mask; reg_both &= ~gpio_mask; reg_level |= gpio_mask; break; case IRQ_TYPE_LEVEL_HIGH: reg_type |= gpio_mask; reg_level &= ~gpio_mask; break; case IRQ_TYPE_LEVEL_LOW: reg_type |= gpio_mask; reg_level |= gpio_mask; break; default: return -EINVAL; } __raw_writel(reg_type, base + GPIO_INT_TYPE); __raw_writel(reg_level, base + GPIO_INT_LEVEL); __raw_writel(reg_both, base + GPIO_INT_BOTH_EDGE); gpio_ack_irq(d); return 0; }
void gpio_irq_disable(enum gpio_port port, enum gpio_pin pin) { rt_uint32_t addr; rt_uint32_t offset; rt_uint32_t data; RT_ASSERT((GPIO_PORT_C < port) && (port < GPIO_PORT_NUM)); RT_ASSERT((GPIO_PIN_0 <= pin) && (pin < GPIO_PIN_NUM)); gpio_ack_irq(port - GPIO_PORT_D, pin); addr = GPIOn_INT_CTRL_ADDR(port - GPIO_PORT_D); offset = pin; data = readl(addr); data &= ~(0x1 << offset); writel(data, addr); dbg_log(DBG_LOG, "[line]:%d offset:%d addr:%08x data:%08x\n", __LINE__, offset, addr, *((rt_uint32_t *)addr)); }