/* * When the summary IRQ is raised, any number of GPIO lines may be high. * It is the job of the summary handler to find all those GPIO lines * which have been set as summary IRQ lines and which are triggered, * and to call their interrupt handlers. */ static void owl_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned long bank, gpio_in_bank, pending, gpioctl; struct irq_chip *chip = irq_desc_get_chip(desc); chained_irq_enter(chip, desc); gpioctl = act_readl(INTC_GPIOCTL); bank = irq - OWL_IRQ_GPIOA; if (bank >= 0 && bank < 5) { if (gpioctl & (1 << ((bank * 5)))) { /* check pending status in one gpio bank */ pending = act_readl(GPIO_REG_INTC_PD(bank * 32)); while (pending != 0) { gpio_in_bank = ffs(pending) - 1; generic_handle_irq(owl_gpio_to_irq( &owl_gpio_chip, bank * 32 + gpio_in_bank)); pending &= ~GPIO_BIT(gpio_in_bank); } } } chained_irq_exit(chip, desc); }
static void owl_gpio_pad_set(int gpio, int val) { int i; unsigned long irq_flags; unsigned int dat; if(owl_gpio_pad_data == NULL) return; for(i = 0; i < owl_gpio_pad_data->size; i++) { if(owl_gpio_pad_data->gpio_pads[i].gpio == gpio) { spin_lock_irqsave(&owl_gpio_lock, irq_flags); if(val) { owl_gpio_pad_data->gpio_pads[i].ref_count++; if(owl_gpio_pad_data->gpio_pads[i].ref_count != 1) { spin_unlock_irqrestore(&owl_gpio_lock, irq_flags); return; } } else { owl_gpio_pad_data->gpio_pads[i].ref_count--; if(owl_gpio_pad_data->gpio_pads[i].ref_count != 0) { spin_unlock_irqrestore(&owl_gpio_lock, irq_flags); return; } } dat = act_readl(SPS_PWR_CTL) & (~owl_gpio_pad_data->gpio_pads[i].mask); dat |= val << owl_gpio_pad_data->gpio_pads[i].bit; act_writel(dat, owl_gpio_pad_data->gpio_pads[i].reg); spin_unlock_irqrestore(&owl_gpio_lock, irq_flags); return; } } }
static int owl_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { unsigned long irq_flags; spin_lock_irqsave(&owl_gpio_lock, irq_flags); act_writel(act_readl(GPIO_REG_OUTEN(offset)) & ~GPIO_BIT(offset), GPIO_REG_OUTEN(offset)); act_writel(act_readl(GPIO_REG_INEN(offset)) | GPIO_BIT(offset), GPIO_REG_INEN(offset)); spin_unlock_irqrestore(&owl_gpio_lock, irq_flags); return 0; }
static void owl_gpio_irq_unmask(struct irq_data *d) { int gpio = d->hwirq; unsigned long irq_flags; unsigned int val; spin_lock_irqsave(&owl_gpio_lock, irq_flags); val = act_readl(GPIO_REG_INTC_MASK(gpio)); val |= GPIO_BIT(gpio); act_writel(val, GPIO_REG_INTC_MASK(gpio)); val = act_readl(INTC_GPIOCTL); val |= 0x1 << (GPIO_BANK(gpio) * 5 + 1); act_writel(val, INTC_GPIOCTL); spin_unlock_irqrestore(&owl_gpio_lock, irq_flags); }
void write_clkreg_val(struct owl_clkreq *reg, int val) { unsigned long read_back; unsigned long flags; spin_lock_irqsave(&cmureg_update_lock, flags); regs[reg->reg_no] = act_readl((u32)reg->reg_hw); regs[reg->reg_no] &= ~reg->mask; regs[reg->reg_no] |= (val << reg->offset) & reg->mask; act_writel(regs[reg->reg_no], (u32)reg->reg_hw); read_back = act_readl((u32)reg->reg_hw); if (read_back != regs[reg->reg_no]) { printk(KERN_WARNING "%s/%d: CMUREG read back error\n", __FILE__, __LINE__); act_writel(regs[reg->reg_no], (u32)reg->reg_hw); } spin_unlock_irqrestore(&cmureg_update_lock, flags); }
static void owl_gpio_set(struct gpio_chip *chip, unsigned offset, int val) { unsigned int dat; dat = act_readl(GPIO_REG_DAT(offset)); if (val) dat |= GPIO_BIT(offset); else dat &= ~GPIO_BIT(offset); act_writel(dat, GPIO_REG_DAT(offset)); }
static int owl_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type) { int gpio = d->hwirq; unsigned long irq_flags; unsigned int type, val, offset; spin_lock_irqsave(&owl_gpio_lock, irq_flags); if (flow_type & IRQ_TYPE_EDGE_BOTH) __irq_set_handler_locked(d->irq, handle_edge_irq); else __irq_set_handler_locked(d->irq, handle_level_irq); flow_type &= IRQ_TYPE_SENSE_MASK; switch (flow_type) { case IRQ_TYPE_EDGE_RISING: type = GPIO_INT_TYPE_RISING; break; case IRQ_TYPE_EDGE_FALLING: type = GPIO_INT_TYPE_FALLING; break; case IRQ_TYPE_LEVEL_HIGH: type = GPIO_INT_TYPE_HIGH; break; case IRQ_TYPE_LEVEL_LOW: type = GPIO_INT_TYPE_LOW; break; default: pr_err("[GPIO] %s: gpio %d, unknow irq type %d\n", __func__, gpio, flow_type); return -1; } offset = (GPIO_IN_BANK(gpio) < 16) ? 4 : 0; val = act_readl(GPIO_REG_INTC_TYPE(gpio)+offset); val &= ~(0x3 << ((gpio%16) * 2)); val |= type << ((gpio%16) * 2); act_writel(val, (GPIO_REG_INTC_TYPE(gpio)+offset)); spin_unlock_irqrestore(&owl_gpio_lock, irq_flags); return 0; }
static void owl_gpio_irq_ack(struct irq_data *d) { unsigned long irq_flags, bank; unsigned int val; bank = d->hwirq >> 5; spin_lock_irqsave(&owl_gpio_lock, irq_flags); /* clear GPIO* IRQ pending */ val = act_readl(INTC_GPIOCTL); switch (bank) { case 0: val &= ~(GPIO_GBPD|GPIO_GCPD|GPIO_GDPD|GPIO_GEPD); break; case 1: val &= ~(GPIO_GAPD|GPIO_GCPD|GPIO_GDPD|GPIO_GEPD); break; case 2: val &= ~(GPIO_GAPD|GPIO_GBPD|GPIO_GDPD|GPIO_GEPD); break; case 3: val &= ~(GPIO_GAPD|GPIO_GBPD|GPIO_GCPD|GPIO_GEPD); break; case 4: val &= ~(GPIO_GAPD|GPIO_GBPD|GPIO_GCPD|GPIO_GDPD); break; default: printk(KERN_INFO "[GPIO] %s(): invalid GPIO bank number %lu\n", __func__, bank); return; } act_writel(val, INTC_GPIOCTL); spin_unlock_irqrestore(&owl_gpio_lock, irq_flags); }
static int owl_gpio_get(struct gpio_chip *chip, unsigned offset) { return act_readl(GPIO_REG_DAT(offset)) & GPIO_BIT(offset); }
int read_clkreg_val(struct owl_clkreq *reg) { regs[reg->reg_no] = act_readl((u32)reg->reg_hw); return ((regs[reg->reg_no])®->mask)>>reg->offset; }