Esempio n. 1
0
static void gpio_ack_irq(unsigned int irq)
{
	unsigned int gpio_irq = irq - IRQ_COUNT;
	unsigned long flags;
	hw_raw_local_irq_save ( flags );
	__raw_writel( ~(1<< gpio_irq), EXTINT_STATUS_REG);
	hw_raw_local_irq_restore ( flags );
}
Esempio n. 2
0
int pnx_gpio_clear_irq(unsigned int irq)
{
	unsigned int gpio_irq;
	unsigned long flags;
	gpio_irq = irq - IRQ_COUNT;
	if (!check_gpio_irq(gpio_irq))
		return -EINVAL;
	hw_raw_local_irq_save ( flags );
	__raw_writel( ~(1<< gpio_irq), EXTINT_STATUS_REG);
	hw_raw_local_irq_restore ( flags );
	return 0;
}
Esempio n. 3
0
/*
 * PNX EXTINT : only EXTINT 3 is managed by Linux
 * We need to unmask the GPIO bank interrupt as soon as possible to
 * avoid missing GPIO interrupts for other lines in the bank.
 * Then we need to mask-read-clear-unmask the triggered GPIO lines
 * in the bank to avoid missing nested interrupts for a GPIO line.
 * If we wait to unmask individual GPIO lines in the bank after the
 * line's interrupt handler has been run, we may miss some nested
 * interrupts.
 */
static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{
	unsigned long isr;
	unsigned long flags;
	unsigned int gpio_irq;

	/* LPA TBD */
	desc->chip->ack(irq);

	/* read status */
	hw_raw_local_irq_save ( flags );
	isr = __raw_readl(EXTINT_STATUS_REG) & __raw_readl(EXTINT_ENABLE3_REG);
	/* clear IRQ source(s)*/
	__raw_writel(~isr, EXTINT_STATUS_REG);
	hw_raw_local_irq_restore ( flags );

	gpio_irq = IRQ_COUNT;
	for (; isr != 0; isr >>= 1, gpio_irq++) {
		struct irq_desc *d;
		if (!(isr & 1))
			continue;
		d = irq_desc + gpio_irq;
#ifdef CONFIG_DEBUG_EXTINT
		printk(KERN_ERR "got something from EXTINT#%i line\n",
		       gpio_irq - IRQ_COUNT);
#endif
		desc_handle_irq(gpio_irq, d);
	}

#ifdef CONFIG_NKERNEL
	/*
	 * interrupt forwarding routine of osware masks INTC_IID_EXT2
	 * so we have to unmask it after irq handling
	 */
	hw_raw_local_irq_save ( flags );
	__raw_writel((1<<26 | 1<<16), INTC_REQUESTx(IRQ_EXTINT3));
	hw_raw_local_irq_restore ( flags );
#endif
}
Esempio n. 4
0
static void p9_xos_flow(unsigned int event, void *cookie)
{
	struct p9_xos_driver *drv = cookie;
	struct p9_xos_endpoint *ep;
	unsigned long flags;
	long int state = 0;

	prolog("e=%u c=%p", event, cookie);

	hw_raw_local_irq_save(flags);

	BUG_ON(event != 0);

	/* get empty packets */
	ep = &drv->ep[WR_EP];
	p9_xos_deque_move(ep->lqueue, &ep->regs[LHEAD], ep);

	if (ep->regs[STARVATION]) { /* Linux needs empty packets */
		ep->regs[STARVATION] = 0;
		set_bit(MUST_WRITE, &state);
	}

	/* get data */
	ep = &drv->ep[RD_EP];
	p9_xos_deque_move(ep->lqueue, &ep->regs[LHEAD], ep);
	if (ep->regs[STARVATION]) { /* RTK needs empty packets */
		drv->wake_status = 2;
		set_bit(MUST_SYNC, &state);
	}

	if (deque_head(ep->lqueue) != deque_null) {
		drv->wake_status = 2;
		set_bit(MUST_READ, &state);
	}

	hw_raw_local_irq_restore(flags);

	if (test_bit(MUST_SYNC, &state))
		queue_work(drv->workqueue, &drv->swork);

	if (test_bit(MUST_WRITE, &state))
		queue_work(drv->workqueue, &drv->wwork);

	if (test_bit(MUST_READ, &state))
		queue_work(drv->workqueue, &drv->rwork);

	if (drv->wake_status == 2)
		wake_lock(&drv->wake_lock);

	epilog();
}
Esempio n. 5
0
static void p9_xos_sync_work(struct work_struct *work)
{
	struct p9_xos_driver *drv;
	struct p9_xos_endpoint *ep;
	unsigned long flags;

	prolog("w=%p", work);

	drv = container_of(work, struct p9_xos_driver, swork);

	/* send data */
	ep = &drv->ep[WR_EP];
	hw_raw_local_irq_save(flags);
	p9_xos_deque_move(&ep->regs[RHEAD], ep->rqueue, ep);
	hw_raw_local_irq_restore(flags);

	/* send empty packets if needed */
	ep = &drv->ep[RD_EP];
	if (nb_free_packets >= MIN_PACKETS_TO_RELEASE || ep->regs[STARVATION]) {
		nb_free_packets = 0;
		hw_raw_local_irq_save(flags);
		p9_xos_deque_move(&ep->regs[RHEAD], ep->rqueue, ep);
		hw_raw_local_irq_restore(flags);
	}

	xos_ctrl_raise(drv->ctrl, P9_XOS_EVENT);

	if ((!drv->wake_count) && (drv->wake_status == 1)) {
		drv->wake_status = 0;
		wake_unlock(&drv->wake_lock);
		wmb();
		if (drv->wake_status == 2)
			wake_lock(&drv->wake_lock);
	}

	epilog();
}
Esempio n. 6
0
static void _write_gpio_pin(struct gpio_bank *bank, int gpio, int gpio_value)
{
	void __iomem *reg = bank->gpio_base;
	unsigned long flags;
	unsigned long l = 0;

	reg += PNX_GPIO_OUTPUT_OFFSET;
	hw_raw_local_irq_save(flags);
	l = __raw_readl(reg);
	if (gpio_value)
		l |= 1 << gpio;
	else
		l &= ~(1 << gpio);
	__raw_writel(l, reg);
	hw_raw_local_irq_restore(flags);

}
Esempio n. 7
0
static void _set_gpio_mode(struct gpio_bank *bank, int gpio, int mode)
{
	void __iomem *reg = bank->mux_base;
	unsigned long flags;
	unsigned long l;

	/* select direction register */
	if(gpio >= 16) {
		reg += PNX_MUX2_OFFSET;
		gpio -= 16;
	}

	hw_raw_local_irq_save(flags);
	/* apply mux mode */
	/* width 2 bit */
	l = __raw_readl(reg);
	l &= ~(3 << (gpio * 2));
	l |= (mode << (gpio * 2));
	__raw_writel(l, reg);
	hw_raw_local_irq_restore(flags);
}
Esempio n. 8
0
static int __init pnx_gpio_probe(struct platform_device *pdev)
{
	int i,j;
	int gpio = 0;
	struct gpio_bank *bank;
	struct gpio_data *data = pdev->dev.platform_data;
	unsigned long flags;

	initialized = 1;

	printk(KERN_INFO "PNX GPIO\n");
	gpio_bank_desc = data->gpio_bank_desc;
	gpio_bank_count = data->nb_banks;

	for (i = 0; i < gpio_bank_count; i++) {
		int gpio_count = 32; /* 32 GPIO per bank */
		bank = &gpio_bank_desc[i];
		bank->reserved_map = 0; /* must always be initialized */
		spin_lock_init(&bank->lock);

		/* check if bank is managed by PNX GPIO driver */
		if ((bank->gpio_base != 0) && (bank->mux_base != 0)) {
		bank->chip.request = pnx_gpio_acquire;
		bank->chip.free = pnx_gpio_release;
		bank->chip.direction_input = gpio_input;
		bank->chip.get = gpio_get;
		bank->chip.direction_output = gpio_output;
		bank->chip.set = gpio_set;
		bank->chip.to_irq = gpio_2irq;
		bank->chip.label = "gpio";
		bank->chip.base = gpio;

		bank->chip.ngpio = gpio_count;

		gpiochip_add(&bank->chip);
		}
		gpio += gpio_count;
	}

#ifdef CONFIG_MODEM_BLACK_BOX
	/* set init value */
	printk(KERN_INFO "PNX GPIO initialize SCON\n");

	/* configure MUX and PAD settings */
	for (i = 0; i< SCON_REGISTER_NB; i++)
		__raw_writel(pnx_scon_init_config[i].scon_reg_value,
			     pnx_scon_init_config[i].scon_reg_addr);

	/* configure GPIO direction and value */
	for (i=0; i < gpio_to_configure; i++) {
		int index;

		bank = get_gpio_bank(pnx_gpio_init_config[i].gpio);
		index = get_gpio_index(pnx_gpio_init_config[i].gpio);
		_set_gpio_direction(bank, index, pnx_gpio_init_config[i].dir);
		_write_gpio_pin(bank, index, pnx_gpio_init_config[i].value);
	}

	/* reserve GPIO used by Modem */
	for (i = 0; i < pnx_modem_gpio_reserved_nb; i++) {
		int index;

		bank = get_gpio_bank(pnx_modem_gpio_reserved[i]);
		index = get_gpio_index(pnx_modem_gpio_reserved[i]);
		bank->reserved_map |= (1 << index);
	}

	/* configure EXTINT used by modem */
	for (i = 0; i< pnx_modem_extint_nb; i++)
		__raw_writel(pnx_extint_init_config[i].reg_value,
			     pnx_extint_init_config[i].reg_addr);

	printk(KERN_INFO "PNX GPIO Driver\n");
#endif

	/* for extint */
	for (j = IRQ_COUNT; j < IRQ_COUNT + NR_EXTINT; j++) {
		set_irq_chip(j, &gpio_irq_chip);
		set_irq_handler(j, handle_simple_irq);
		set_irq_flags(j, IRQF_VALID);
	}

	hw_raw_local_irq_save ( flags );
	/* mask all EXT IRQ sources before registring handler */
	/* read status */
	j = __raw_readl(EXTINT_STATUS_REG) & __raw_readl(EXTINT_ENABLE3_REG);
	/* clear IRQ source(s)*/
	__raw_writel(j, EXTINT_STATUS_REG);

	__raw_writel(0, EXTINT_ENABLE3_REG);

	/* set irq in low level */
	set_irq_type(IRQ_EXTINT3, IRQF_TRIGGER_LOW);

	/* chained GPIO-IRQ on EXTINT3 */
	set_irq_chained_handler(IRQ_EXTINT3, gpio_irq_handler);
	hw_raw_local_irq_restore ( flags );

	return 0;
}