static void serial_omap_start_rxdma(struct uart_omap_port *up) { #ifdef CONFIG_OMAP3_PM /* Disallow OCP bus idle. UART TX irqs are not seen during * bus idle. Alternative is to set kernel timer at fifo * drain rate. */ unsigned int tmp; tmp = (serial_in(up, UART_OMAP_SYSC) & 0x7) | (1 << 3); serial_out(up, UART_OMAP_SYSC, tmp); /* no-idle */ #endif if (up->uart_dma.rx_dma_channel == 0xFF) { omap_request_dma(uart_dma_rx[up->pdev->id-1],"UART Rx DMA", (void *)uart_rx_dma_callback,up, &(up->uart_dma.rx_dma_channel)); omap_set_dma_src_params(up->uart_dma.rx_dma_channel, 0, OMAP_DMA_AMODE_CONSTANT, UART_BASE(up->pdev->id - 1), 0, 0); omap_set_dma_dest_params(up->uart_dma.rx_dma_channel, 0, OMAP_DMA_AMODE_POST_INC, up->uart_dma.rx_buf_dma_phys, 0, 0); omap_set_dma_transfer_params(up->uart_dma.rx_dma_channel, OMAP_DMA_DATA_TYPE_S8, up->uart_dma.rx_buf_size, 1, OMAP_DMA_SYNC_ELEMENT, uart_dma_rx[up->pdev->id-1], 0); } up->uart_dma.prev_rx_dma_pos = up->uart_dma.rx_buf_dma_phys; omap_writel(0, OMAP34XX_DMA4_BASE + OMAP_DMA4_CDAC(up->uart_dma.rx_dma_channel)); omap_start_dma(up->uart_dma.rx_dma_channel); mod_timer(&up->uart_dma.rx_timer, jiffies + usecs_to_jiffies(up->uart_dma.rx_timeout)); up->uart_dma.rx_dma_state = 1; }
static void serial_omap_rx_timeout(unsigned long uart_no) { struct uart_omap_port *up = ui[uart_no - 1]; unsigned int curr_dma_pos; curr_dma_pos = omap_readl(OMAP34XX_DMA4_BASE + OMAP_DMA4_CDAC(up->uart_dma.rx_dma_channel)); if ((curr_dma_pos == up->uart_dma.prev_rx_dma_pos) || (curr_dma_pos == 0)) { /* * If there is no transfer rx happening for 10sec then stop the dma * else just restart the timer. See if 10 sec can be improved. */ if (jiffies_to_msecs(jiffies - isr8250_activity) < 10000) mod_timer(&up->uart_dma.rx_timer, jiffies + usecs_to_jiffies(up->uart_dma.rx_timeout)); else { del_timer(&up->uart_dma.rx_timer); serial_omap_stop_rxdma(up); up->ier |= UART_IER_RDI; serial_out(up, UART_IER, up->ier); } return; } else { unsigned int curr_transmitted_size = curr_dma_pos - up->uart_dma.prev_rx_dma_pos; up->port.icount.rx += curr_transmitted_size; tty_insert_flip_string(up->port.state->port.tty, up->uart_dma.rx_buf + (up->uart_dma.prev_rx_dma_pos - up->uart_dma.rx_buf_dma_phys), curr_transmitted_size); queue_work(omap_serial_workqueue, &up->tty_work); up->uart_dma.prev_rx_dma_pos = curr_dma_pos; if (up->uart_dma.rx_buf_size + up->uart_dma.rx_buf_dma_phys == curr_dma_pos) { serial_omap_start_rxdma(up); } else mod_timer(&up->uart_dma.rx_timer, jiffies + usecs_to_jiffies(up->uart_dma.rx_timeout)); isr8250_activity = jiffies; } }