static void sirfsoc_uart_stop_rx(struct uart_port *port) { struct sirfsoc_uart_port *sirfport = to_sirfport(port); struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0); if (sirfport->rx_dma_chan) { if (!sirfport->is_atlas7) wr_regl(port, ureg->sirfsoc_int_en_reg, rd_regl(port, ureg->sirfsoc_int_en_reg) & ~(SIRFUART_RX_DMA_INT_EN(port, uint_en) | uint_en->sirfsoc_rx_done_en)); else wr_regl(port, SIRFUART_INT_EN_CLR, SIRFUART_RX_DMA_INT_EN(port, uint_en)| uint_en->sirfsoc_rx_done_en); dmaengine_terminate_all(sirfport->rx_dma_chan); } else { if (!sirfport->is_atlas7) wr_regl(port, ureg->sirfsoc_int_en_reg, rd_regl(port, ureg->sirfsoc_int_en_reg)& ~(SIRFUART_RX_IO_INT_EN(port, uint_en))); else wr_regl(port, SIRFUART_INT_EN_CLR, SIRFUART_RX_IO_INT_EN(port, uint_en)); } }
static void sirfsoc_uart_start_rx(struct uart_port *port) { struct sirfsoc_uart_port *sirfport = to_sirfport(port); struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; sirfport->rx_io_count = 0; wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET); wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0); wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START); if (sirfport->rx_dma_chan) sirfsoc_uart_start_next_rx_dma(port); else { if (!sirfport->is_atlas7) wr_regl(port, ureg->sirfsoc_int_en_reg, rd_regl(port, ureg->sirfsoc_int_en_reg) | SIRFUART_RX_IO_INT_EN(port, uint_en)); else wr_regl(port, ureg->sirfsoc_int_en_reg, SIRFUART_RX_IO_INT_EN(port, uint_en)); } }
static int sirfsoc_uart_startup(struct uart_port *port) { struct sirfsoc_uart_port *sirfport = to_sirfport(port); struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; unsigned int index = port->line; int ret; irq_modify_status(port->irq, IRQ_NOREQUEST, IRQ_NOAUTOEN); ret = request_irq(port->irq, sirfsoc_uart_isr, 0, SIRFUART_PORT_NAME, sirfport); if (ret != 0) { dev_err(port->dev, "UART%d request IRQ line (%d) failed.\n", index, port->irq); goto irq_err; } /* initial hardware settings */ wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, rd_regl(port, ureg->sirfsoc_tx_dma_io_ctrl) | SIRFUART_IO_MODE); wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) | SIRFUART_IO_MODE); wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) & ~SIRFUART_RX_DMA_FLUSH); wr_regl(port, ureg->sirfsoc_tx_dma_io_len, 0); wr_regl(port, ureg->sirfsoc_rx_dma_io_len, 0); wr_regl(port, ureg->sirfsoc_tx_rx_en, SIRFUART_RX_EN | SIRFUART_TX_EN); if (sirfport->uart_reg->uart_type == SIRF_USP_UART) wr_regl(port, ureg->sirfsoc_mode1, SIRFSOC_USP_ENDIAN_CTRL_LSBF | SIRFSOC_USP_EN); wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_RESET); wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET); wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0); wr_regl(port, ureg->sirfsoc_tx_fifo_ctrl, SIRFUART_FIFO_THD(port)); wr_regl(port, ureg->sirfsoc_rx_fifo_ctrl, SIRFUART_FIFO_THD(port)); if (sirfport->rx_dma_chan) wr_regl(port, ureg->sirfsoc_rx_fifo_level_chk, SIRFUART_RX_FIFO_CHK_SC(port->line, 0x1) | SIRFUART_RX_FIFO_CHK_LC(port->line, 0x2) | SIRFUART_RX_FIFO_CHK_HC(port->line, 0x4)); if (sirfport->tx_dma_chan) { sirfport->tx_dma_state = TX_DMA_IDLE; wr_regl(port, ureg->sirfsoc_tx_fifo_level_chk, SIRFUART_TX_FIFO_CHK_SC(port->line, 0x1b) | SIRFUART_TX_FIFO_CHK_LC(port->line, 0xe) | SIRFUART_TX_FIFO_CHK_HC(port->line, 0x4)); } sirfport->ms_enabled = false; if (sirfport->uart_reg->uart_type == SIRF_USP_UART && sirfport->hw_flow_ctrl) { irq_modify_status(gpio_to_irq(sirfport->cts_gpio), IRQ_NOREQUEST, IRQ_NOAUTOEN); ret = request_irq(gpio_to_irq(sirfport->cts_gpio), sirfsoc_uart_usp_cts_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "usp_cts_irq", sirfport); if (ret != 0) { dev_err(port->dev, "UART-USP:request gpio irq fail\n"); goto init_rx_err; } } if (sirfport->uart_reg->uart_type == SIRF_REAL_UART && sirfport->rx_dma_chan) wr_regl(port, ureg->sirfsoc_swh_dma_io, SIRFUART_CLEAR_RX_ADDR_EN); if (sirfport->uart_reg->uart_type == SIRF_USP_UART && sirfport->rx_dma_chan) wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) | SIRFSOC_USP_FRADDR_CLR_EN); if (sirfport->rx_dma_chan && !sirfport->is_hrt_enabled) { sirfport->is_hrt_enabled = true; sirfport->rx_period_time = 20000000; sirfport->rx_last_pos = -1; sirfport->pio_fetch_cnt = 0; sirfport->rx_dma_items.xmit.tail = sirfport->rx_dma_items.xmit.head = 0; hrtimer_start(&sirfport->hrt, ns_to_ktime(sirfport->rx_period_time), HRTIMER_MODE_REL); } wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START); if (sirfport->rx_dma_chan) sirfsoc_uart_start_next_rx_dma(port); else { if (!sirfport->is_atlas7) wr_regl(port, ureg->sirfsoc_int_en_reg, rd_regl(port, ureg->sirfsoc_int_en_reg) | SIRFUART_RX_IO_INT_EN(uint_en, sirfport->uart_reg->uart_type)); else wr_regl(port, ureg->sirfsoc_int_en_reg, SIRFUART_RX_IO_INT_EN(uint_en, sirfport->uart_reg->uart_type)); } enable_irq(port->irq); return 0; init_rx_err: free_irq(port->irq, sirfport); irq_err: return ret; }