コード例 #1
0
ファイル: gpio-owl.c プロジェクト: alsandeep/kernel-4.x
/*
 * 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);
}
コード例 #2
0
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;
		}
	}
}
コード例 #3
0
ファイル: gpio-owl.c プロジェクト: alsandeep/kernel-4.x
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;
}
コード例 #4
0
ファイル: gpio-owl.c プロジェクト: alsandeep/kernel-4.x
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);
}
コード例 #5
0
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);
}
コード例 #6
0
ファイル: gpio-owl.c プロジェクト: alsandeep/kernel-4.x
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));
}
コード例 #7
0
ファイル: gpio-owl.c プロジェクト: alsandeep/kernel-4.x
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;
}
コード例 #8
0
ファイル: gpio-owl.c プロジェクト: alsandeep/kernel-4.x
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);
}
コード例 #9
0
ファイル: gpio-owl.c プロジェクト: alsandeep/kernel-4.x
static int owl_gpio_get(struct gpio_chip *chip, unsigned offset)
{
	return act_readl(GPIO_REG_DAT(offset)) & GPIO_BIT(offset);
}
コード例 #10
0
int read_clkreg_val(struct owl_clkreq *reg)
{
	regs[reg->reg_no] = act_readl((u32)reg->reg_hw);
	return ((regs[reg->reg_no])&reg->mask)>>reg->offset;
}