/**
 * serial_omap_irq() - This handles the interrupt from one port
 * @irq: uart port irq number
 * @dev_id: uart port info
 */
static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
{
	struct uart_omap_port *up = dev_id;
	unsigned int iir, lsr;
	unsigned long flags;

	spin_lock_irqsave(&up->port.lock, flags);
#ifdef CONFIG_PM
	/*
	 * This will enable the clock for some reason if the
	 * clocks get disabled. This would enable the ICK also
	 * in case if the Idle state is set and the PRCM modul
	 * just shutdown the ICK because of inactivity.
	 */
	omap_uart_enable_clock_from_irq(up->pdev->id);
#endif

	iir = serial_in(up, UART_IIR);
	if (iir & UART_IIR_NO_INT) {
		spin_unlock_irqrestore(&up->port.lock, flags);
		return IRQ_NONE;
	}

	lsr = serial_in(up, UART_LSR);
	if (iir & UART_IIR_RLSI) {
		if (!up->use_dma) {
			if (lsr & UART_LSR_DR) {
				receive_chars(up, &lsr);
				if (omap_is_console_port(&up->port) &&
						(up->plat_hold_wakelock)) {
					spin_unlock(&up->port.lock);
					up->plat_hold_wakelock(up, WAKELK_IRQ);
					spin_lock(&up->port.lock);
				}
			}
		} else {
			up->ier &= ~UART_IER_RDI;
			serial_out(up, UART_IER, up->ier);
			if (serial_omap_start_rxdma(up) != 0)
				if (lsr & UART_LSR_DR)
					receive_chars(up, &lsr);
		}
	}

	check_modem_status(up);
	if ((lsr & UART_LSR_THRE) && (iir & UART_IIR_THRI))
		transmit_chars(up);

	spin_unlock_irqrestore(&up->port.lock, flags);
	up->port_activity = jiffies;
	return IRQ_HANDLED;
}
Exemple #2
0
static void uart_tx_dma_callback(int lch, u16 ch_status, void *data)
{
	struct uart_omap_port *up = (struct uart_omap_port *)data;
	struct circ_buf *xmit = &up->port.state->xmit;

	xmit->tail = (xmit->tail + up->uart_dma.tx_buf_size) & \
			(UART_XMIT_SIZE - 1);
	up->port.icount.tx += up->uart_dma.tx_buf_size;

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(&up->port);

	if (uart_circ_empty(xmit)) {
		spin_lock(&(up->uart_dma.tx_lock));
		serial_omap_stop_tx(&up->port);
		up->uart_dma.tx_dma_used = false;
		spin_unlock(&(up->uart_dma.tx_lock));
			if (up->plat_hold_wakelock)
				(up->plat_hold_wakelock(up, WAKELK_TX));
	} else {

#ifdef CONFIG_PM
		/*
		 * This will enable the clock for some reason if the
		 * clocks get disabled. This would enable the ICK also
		 * in case if the Idle state is set and the PRCM modul
		 * just shutdown the ICK because of inactivity.
		 */
		omap_uart_enable_clock_from_irq(up->pdev->id);
#endif

		omap_stop_dma(up->uart_dma.tx_dma_channel);
		serial_omap_continue_tx(up);
	}
	up->port_activity = jiffies;
	return;
}