summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2021-01-20 17:12:26 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-01-20 18:49:01 +0100
commit4776a4a0a29c64b954a445ff65848bd376a50fcc (patch)
treeeffc80ea866eb8f2f9d28fac01a6937ed116d397
parent532b7cecdd4bee0e50c704b1281194c88f19cef1 (diff)
downloadlinux-4776a4a0a29c64b954a445ff65848bd376a50fcc.tar.gz
linux-4776a4a0a29c64b954a445ff65848bd376a50fcc.tar.bz2
linux-4776a4a0a29c64b954a445ff65848bd376a50fcc.zip
serial: remove sirf prima/atlas driver
The CSR SiRF prima2/atlas platforms are getting removed, so this driver is no longer needed. Cc: Barry Song <baohua@kernel.org> Signed-off-by: Arnd Bergmann <arnd@arndb.de> Link: https://lore.kernel.org/r/20210120161324.3728294-1-arnd@kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--Documentation/devicetree/bindings/serial/sirf-uart.txt34
-rw-r--r--drivers/tty/serial/Kconfig22
-rw-r--r--drivers/tty/serial/Makefile1
-rw-r--r--drivers/tty/serial/sirfsoc_uart.c1503
-rw-r--r--drivers/tty/serial/sirfsoc_uart.h447
5 files changed, 0 insertions, 2007 deletions
diff --git a/Documentation/devicetree/bindings/serial/sirf-uart.txt b/Documentation/devicetree/bindings/serial/sirf-uart.txt
deleted file mode 100644
index 1e48bbbeecc6..000000000000
--- a/Documentation/devicetree/bindings/serial/sirf-uart.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-* CSR SiRFprimaII/atlasVI Universal Synchronous Asynchronous Receiver/Transmitter *
-
-Required properties:
-- compatible : Should be "sirf,prima2-uart", "sirf, prima2-usp-uart",
- "sirf,atlas7-uart" or "sirf,atlas7-usp-uart".
-- reg : Offset and length of the register set for the device
-- interrupts : Should contain uart interrupt
-- fifosize : Should define hardware rx/tx fifo size
-- clocks : Should contain uart clock number
-
-Optional properties:
-- uart-has-rtscts: we have hardware flow controller pins in hardware
-- rts-gpios: RTS pin for USP-based UART if uart-has-rtscts is true
-- cts-gpios: CTS pin for USP-based UART if uart-has-rtscts is true
-
-Example:
-
-uart0: uart@b0050000 {
- cell-index = <0>;
- compatible = "sirf,prima2-uart";
- reg = <0xb0050000 0x1000>;
- interrupts = <17>;
- fifosize = <128>;
- clocks = <&clks 13>;
-};
-
-On the board-specific dts, we can put rts-gpios and cts-gpios like
-
-usp@b0090000 {
- compatible = "sirf,prima2-usp-uart";
- uart-has-rtscts;
- rts-gpios = <&gpio 15 0>;
- cts-gpios = <&gpio 46 0>;
-};
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 83f6ca4bf210..22e86ba4f827 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -276,28 +276,6 @@ config SERIAL_SAMSUNG_CONSOLE
your boot loader about how to pass options to the kernel at
boot time.)
-config SERIAL_SIRFSOC
- tristate "SiRF SoC Platform Serial port support"
- depends on ARCH_SIRF
- select SERIAL_CORE
- help
- Support for the on-chip UART on the CSR SiRFprimaII series,
- providing /dev/ttySiRF0, 1 and 2 (note, some machines may not
- provide all of these ports, depending on how the serial port
- pins are configured).
-
-config SERIAL_SIRFSOC_CONSOLE
- bool "Support for console on SiRF SoC serial port"
- depends on SERIAL_SIRFSOC=y
- select SERIAL_CORE_CONSOLE
- help
- Even if you say Y here, the currently visible virtual console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttySiRFx". (Try "man bootparam" or see the documentation of
- your boot loader about how to pass options to the kernel at
- boot time.)
-
config SERIAL_TEGRA
tristate "NVIDIA Tegra20/30 SoC serial controller"
depends on ARCH_TEGRA && TEGRA20_APB_DMA
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index ec2b74091f0c..931dc1d6885e 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -69,7 +69,6 @@ obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o
obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o
obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o
obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
-obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o
obj-$(CONFIG_SERIAL_TEGRA) += serial-tegra.o
obj-$(CONFIG_SERIAL_TEGRA_TCU) += tegra-tcu.o
obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c
deleted file mode 100644
index 38622f2a30a9..000000000000
--- a/drivers/tty/serial/sirfsoc_uart.c
+++ /dev/null
@@ -1,1503 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for CSR SiRFprimaII onboard UARTs.
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- */
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/sysrq.h>
-#include <linux/console.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/clk.h>
-#include <linux/of.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/of_gpio.h>
-#include <linux/dmaengine.h>
-#include <linux/dma-direction.h>
-#include <linux/dma-mapping.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-
-#include "sirfsoc_uart.h"
-
-static unsigned int
-sirfsoc_uart_pio_tx_chars(struct sirfsoc_uart_port *sirfport, int count);
-static unsigned int
-sirfsoc_uart_pio_rx_chars(struct uart_port *port, unsigned int max_rx_count);
-static struct uart_driver sirfsoc_uart_drv;
-
-static void sirfsoc_uart_tx_dma_complete_callback(void *param);
-static const struct sirfsoc_baudrate_to_regv baudrate_to_regv[] = {
- {4000000, 2359296},
- {3500000, 1310721},
- {3000000, 1572865},
- {2500000, 1245186},
- {2000000, 1572866},
- {1500000, 1245188},
- {1152000, 1638404},
- {1000000, 1572869},
- {921600, 1114120},
- {576000, 1245196},
- {500000, 1245198},
- {460800, 1572876},
- {230400, 1310750},
- {115200, 1310781},
- {57600, 1310843},
- {38400, 1114328},
- {19200, 1114545},
- {9600, 1114979},
-};
-
-static struct sirfsoc_uart_port *sirf_ports[SIRFSOC_UART_NR];
-
-static inline struct sirfsoc_uart_port *to_sirfport(struct uart_port *port)
-{
- return container_of(port, struct sirfsoc_uart_port, port);
-}
-
-static inline unsigned int sirfsoc_uart_tx_empty(struct uart_port *port)
-{
- unsigned long reg;
- struct sirfsoc_uart_port *sirfport = to_sirfport(port);
- struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
- struct sirfsoc_fifo_status *ufifo_st = &sirfport->uart_reg->fifo_status;
- reg = rd_regl(port, ureg->sirfsoc_tx_fifo_status);
- return (reg & ufifo_st->ff_empty(port)) ? TIOCSER_TEMT : 0;
-}
-
-static unsigned int sirfsoc_uart_get_mctrl(struct uart_port *port)
-{
- struct sirfsoc_uart_port *sirfport = to_sirfport(port);
- struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
- if (!sirfport->hw_flow_ctrl || !sirfport->ms_enabled)
- goto cts_asserted;
- if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
- if (!(rd_regl(port, ureg->sirfsoc_afc_ctrl) &
- SIRFUART_AFC_CTS_STATUS))
- goto cts_asserted;
- else
- goto cts_deasserted;
- } else {
- if (!gpio_get_value(sirfport->cts_gpio))
- goto cts_asserted;
- else
- goto cts_deasserted;
- }
-cts_deasserted:
- return TIOCM_CAR | TIOCM_DSR;
-cts_asserted:
- return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
-}
-
-static void sirfsoc_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct sirfsoc_uart_port *sirfport = to_sirfport(port);
- struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
- unsigned int assert = mctrl & TIOCM_RTS;
- unsigned int val = assert ? SIRFUART_AFC_CTRL_RX_THD : 0x0;
- unsigned int current_val;
-
- if (mctrl & TIOCM_LOOP) {
- if (sirfport->uart_reg->uart_type == SIRF_REAL_UART)
- wr_regl(port, ureg->sirfsoc_line_ctrl,
- rd_regl(port, ureg->sirfsoc_line_ctrl) |
- SIRFUART_LOOP_BACK);
- else
- wr_regl(port, ureg->sirfsoc_mode1,
- rd_regl(port, ureg->sirfsoc_mode1) |
- SIRFSOC_USP_LOOP_BACK_CTRL);
- } else {
- if (sirfport->uart_reg->uart_type == SIRF_REAL_UART)
- wr_regl(port, ureg->sirfsoc_line_ctrl,
- rd_regl(port, ureg->sirfsoc_line_ctrl) &
- ~SIRFUART_LOOP_BACK);
- else
- wr_regl(port, ureg->sirfsoc_mode1,
- rd_regl(port, ureg->sirfsoc_mode1) &
- ~SIRFSOC_USP_LOOP_BACK_CTRL);
- }
-
- if (!sirfport->hw_flow_ctrl || !sirfport->ms_enabled)
- return;
- if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
- current_val = rd_regl(port, ureg->sirfsoc_afc_ctrl) & ~0xFF;
- val |= current_val;
- wr_regl(port, ureg->sirfsoc_afc_ctrl, val);
- } else {
- if (!val)
- gpio_set_value(sirfport->rts_gpio, 1);
- else
- gpio_set_value(sirfport->rts_gpio, 0);
- }
-}
-
-static void sirfsoc_uart_stop_tx(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;
-
- if (sirfport->tx_dma_chan) {
- if (sirfport->tx_dma_state == TX_DMA_RUNNING) {
- dmaengine_pause(sirfport->tx_dma_chan);
- sirfport->tx_dma_state = TX_DMA_PAUSE;
- } else {
- if (!sirfport->is_atlas7)
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- rd_regl(port, ureg->sirfsoc_int_en_reg) &
- ~uint_en->sirfsoc_txfifo_empty_en);
- else
- wr_regl(port, ureg->sirfsoc_int_en_clr_reg,
- uint_en->sirfsoc_txfifo_empty_en);
- }
- } else {
- if (sirfport->uart_reg->uart_type == SIRF_USP_UART)
- wr_regl(port, ureg->sirfsoc_tx_rx_en, rd_regl(port,
- ureg->sirfsoc_tx_rx_en) & ~SIRFUART_TX_EN);
- if (!sirfport->is_atlas7)
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- rd_regl(port, ureg->sirfsoc_int_en_reg) &
- ~uint_en->sirfsoc_txfifo_empty_en);
- else
- wr_regl(port, ureg->sirfsoc_int_en_clr_reg,
- uint_en->sirfsoc_txfifo_empty_en);
- }
-}
-
-static void sirfsoc_uart_tx_with_dma(struct sirfsoc_uart_port *sirfport)
-{
- struct uart_port *port = &sirfport->port;
- struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
- struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
- struct circ_buf *xmit = &port->state->xmit;
- unsigned long tran_size;
- unsigned long tran_start;
- unsigned long pio_tx_size;
-
- tran_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
- tran_start = (unsigned long)(xmit->buf + xmit->tail);
- if (uart_circ_empty(xmit) || uart_tx_stopped(port) ||
- !tran_size)
- return;
- if (sirfport->tx_dma_state == TX_DMA_PAUSE) {
- dmaengine_resume(sirfport->tx_dma_chan);
- return;
- }
- if (sirfport->tx_dma_state == TX_DMA_RUNNING)
- return;
- if (!sirfport->is_atlas7)
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- rd_regl(port, ureg->sirfsoc_int_en_reg)&
- ~(uint_en->sirfsoc_txfifo_empty_en));
- else
- wr_regl(port, ureg->sirfsoc_int_en_clr_reg,
- uint_en->sirfsoc_txfifo_empty_en);
- /*
- * DMA requires buffer address and buffer length are both aligned with
- * 4 bytes, so we use PIO for
- * 1. if address is not aligned with 4bytes, use PIO for the first 1~3
- * bytes, and move to DMA for the left part aligned with 4bytes
- * 2. if buffer length is not aligned with 4bytes, use DMA for aligned
- * part first, move to PIO for the left 1~3 bytes
- */
- if (tran_size < 4 || BYTES_TO_ALIGN(tran_start)) {
- wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_STOP);
- wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl,
- rd_regl(port, ureg->sirfsoc_tx_dma_io_ctrl)|
- SIRFUART_IO_MODE);
- if (BYTES_TO_ALIGN(tran_start)) {
- pio_tx_size = sirfsoc_uart_pio_tx_chars(sirfport,
- BYTES_TO_ALIGN(tran_start));
- tran_size -= pio_tx_size;
- }
- if (tran_size < 4)
- sirfsoc_uart_pio_tx_chars(sirfport, tran_size);
- if (!sirfport->is_atlas7)
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- rd_regl(port, ureg->sirfsoc_int_en_reg)|
- uint_en->sirfsoc_txfifo_empty_en);
- else
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- uint_en->sirfsoc_txfifo_empty_en);
- wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_START);
- } else {
- /* tx transfer mode switch into dma mode */
- wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_STOP);
- 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_tx_fifo_op, SIRFUART_FIFO_START);
- tran_size &= ~(0x3);
-
- sirfport->tx_dma_addr = dma_map_single(port->dev,
- xmit->buf + xmit->tail,
- tran_size, DMA_TO_DEVICE);
- sirfport->tx_dma_desc = dmaengine_prep_slave_single(
- sirfport->tx_dma_chan, sirfport->tx_dma_addr,
- tran_size, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
- if (!sirfport->tx_dma_desc) {
- dev_err(port->dev, "DMA prep slave single fail\n");
- return;
- }
- sirfport->tx_dma_desc->callback =
- sirfsoc_uart_tx_dma_complete_callback;
- sirfport->tx_dma_desc->callback_param = (void *)sirfport;
- sirfport->transfer_size = tran_size;
-
- dmaengine_submit(sirfport->tx_dma_desc);
- dma_async_issue_pending(sirfport->tx_dma_chan);
- sirfport->tx_dma_state = TX_DMA_RUNNING;
- }
-}
-
-static void sirfsoc_uart_start_tx(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;
- if (sirfport->tx_dma_chan)
- sirfsoc_uart_tx_with_dma(sirfport);
- else {
- if (sirfport->uart_reg->uart_type == SIRF_USP_UART)
- wr_regl(port, ureg->sirfsoc_tx_rx_en, rd_regl(port,
- ureg->sirfsoc_tx_rx_en) | SIRFUART_TX_EN);
- wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_STOP);
- sirfsoc_uart_pio_tx_chars(sirfport, port->fifosize);
- wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_START);
- if (!sirfport->is_atlas7)
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- rd_regl(port, ureg->sirfsoc_int_en_reg)|
- uint_en->sirfsoc_txfifo_empty_en);
- else
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- uint_en->sirfsoc_txfifo_empty_en);
- }
-}
-
-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(uint_en,
- sirfport->uart_reg->uart_type) |
- uint_en->sirfsoc_rx_done_en));
- else
- wr_regl(port, ureg->sirfsoc_int_en_clr_reg,
- SIRFUART_RX_DMA_INT_EN(uint_en,
- sirfport->uart_reg->uart_type)|
- 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(uint_en,
- sirfport->uart_reg->uart_type)));
- else
- wr_regl(port, ureg->sirfsoc_int_en_clr_reg,
- SIRFUART_RX_IO_INT_EN(uint_en,
- sirfport->uart_reg->uart_type));
- }
-}
-
-static void sirfsoc_uart_disable_ms(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;
-
- if (!sirfport->hw_flow_ctrl)
- return;
- sirfport->ms_enabled = false;
- if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
- wr_regl(port, ureg->sirfsoc_afc_ctrl,
- rd_regl(port, ureg->sirfsoc_afc_ctrl) & ~0x3FF);
- if (!sirfport->is_atlas7)
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- rd_regl(port, ureg->sirfsoc_int_en_reg)&
- ~uint_en->sirfsoc_cts_en);
- else
- wr_regl(port, ureg->sirfsoc_int_en_clr_reg,
- uint_en->sirfsoc_cts_en);
- } else
- disable_irq(gpio_to_irq(sirfport->cts_gpio));
-}
-
-static irqreturn_t sirfsoc_uart_usp_cts_handler(int irq, void *dev_id)
-{
- struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)dev_id;
- struct uart_port *port = &sirfport->port;
- spin_lock(&port->lock);
- if (gpio_is_valid(sirfport->cts_gpio) && sirfport->ms_enabled)
- uart_handle_cts_change(port,
- !gpio_get_value(sirfport->cts_gpio));
- spin_unlock(&port->lock);
- return IRQ_HANDLED;
-}
-
-static void sirfsoc_uart_enable_ms(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;
-
- if (!sirfport->hw_flow_ctrl)
- return;
- sirfport->ms_enabled = true;
- if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
- wr_regl(port, ureg->sirfsoc_afc_ctrl,
- rd_regl(port, ureg->sirfsoc_afc_ctrl) |
- SIRFUART_AFC_TX_EN | SIRFUART_AFC_RX_EN |
- SIRFUART_AFC_CTRL_RX_THD);
- if (!sirfport->is_atlas7)
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- rd_regl(port, ureg->sirfsoc_int_en_reg)
- | uint_en->sirfsoc_cts_en);
- else
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- uint_en->sirfsoc_cts_en);
- } else
- enable_irq(gpio_to_irq(sirfport->cts_gpio));
-}
-
-static void sirfsoc_uart_break_ctl(struct uart_port *port, int break_state)
-{
- struct sirfsoc_uart_port *sirfport = to_sirfport(port);
- struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
- if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
- unsigned long ulcon = rd_regl(port, ureg->sirfsoc_line_ctrl);
- if (break_state)
- ulcon |= SIRFUART_SET_BREAK;
- else
- ulcon &= ~SIRFUART_SET_BREAK;
- wr_regl(port, ureg->sirfsoc_line_ctrl, ulcon);
- }
-}
-
-static unsigned int
-sirfsoc_uart_pio_rx_chars(struct uart_port *port, unsigned int max_rx_count)
-{
- struct sirfsoc_uart_port *sirfport = to_sirfport(port);
- struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
- struct sirfsoc_fifo_status *ufifo_st = &sirfport->uart_reg->fifo_status;
- unsigned int ch, rx_count = 0;
- struct tty_struct *tty;
- tty = tty_port_tty_get(&port->state->port);
- if (!tty)
- return -ENODEV;
- while (!(rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
- ufifo_st->ff_empty(port))) {
- ch = rd_regl(port, ureg->sirfsoc_rx_fifo_data) |
- SIRFUART_DUMMY_READ;
- if (unlikely(uart_handle_sysrq_char(port, ch)))
- continue;
- uart_insert_char(port, 0, 0, ch, TTY_NORMAL);
- rx_count++;
- if (rx_count >= max_rx_count)
- break;
- }
-
- port->icount.rx += rx_count;
-
- return rx_count;
-}
-
-static unsigned int
-sirfsoc_uart_pio_tx_chars(struct sirfsoc_uart_port *sirfport, int count)
-{
- struct uart_port *port = &sirfport->port;
- struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
- struct sirfsoc_fifo_status *ufifo_st = &sirfport->uart_reg->fifo_status;
- struct circ_buf *xmit = &port->state->xmit;
- unsigned int num_tx = 0;
- while (!uart_circ_empty(xmit) &&
- !(rd_regl(port, ureg->sirfsoc_tx_fifo_status) &
- ufifo_st->ff_full(port)) &&
- count--) {
- wr_regl(port, ureg->sirfsoc_tx_fifo_data,
- xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- num_tx++;
- }
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
- return num_tx;
-}
-
-static void sirfsoc_uart_tx_dma_complete_callback(void *param)
-{
- struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)param;
- struct uart_port *port = &sirfport->port;
- struct circ_buf *xmit = &port->state->xmit;
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- xmit->tail = (xmit->tail + sirfport->transfer_size) &
- (UART_XMIT_SIZE - 1);
- port->icount.tx += sirfport->transfer_size;
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
- if (sirfport->tx_dma_addr)
- dma_unmap_single(port->dev, sirfport->tx_dma_addr,
- sirfport->transfer_size, DMA_TO_DEVICE);
- sirfport->tx_dma_state = TX_DMA_IDLE;
- sirfsoc_uart_tx_with_dma(sirfport);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static irqreturn_t sirfsoc_uart_isr(int irq, void *dev_id)
-{
- unsigned long intr_status;
- unsigned long cts_status;
- unsigned long flag = TTY_NORMAL;
- struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)dev_id;
- struct uart_port *port = &sirfport->port;
- struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
- struct sirfsoc_fifo_status *ufifo_st = &sirfport->uart_reg->fifo_status;
- struct sirfsoc_int_status *uint_st = &sirfport->uart_reg->uart_int_st;
- struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
- struct uart_state *state = port->state;
- struct circ_buf *xmit = &port->state->xmit;
- spin_lock(&port->lock);
- intr_status = rd_regl(port, ureg->sirfsoc_int_st_reg);
- wr_regl(port, ureg->sirfsoc_int_st_reg, intr_status);
- intr_status &= rd_regl(port, ureg->sirfsoc_int_en_reg);
- if (unlikely(intr_status & (SIRFUART_ERR_INT_STAT(uint_st,
- sirfport->uart_reg->uart_type)))) {
- if (intr_status & uint_st->sirfsoc_rxd_brk) {
- port->icount.brk++;
- if (uart_handle_break(port))
- goto recv_char;
- }
- if (intr_status & uint_st->sirfsoc_rx_oflow) {
- port->icount.overrun++;
- flag = TTY_OVERRUN;
- }
- if (intr_status & uint_st->sirfsoc_frm_err) {
- port->icount.frame++;
- flag = TTY_FRAME;
- }
- if (intr_status & uint_st->sirfsoc_parity_err) {
- port->icount.parity++;
- flag = TTY_PARITY;
- }
- 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);
- intr_status &= port->read_status_mask;
- uart_insert_char(port, intr_status,
- uint_en->sirfsoc_rx_oflow_en, 0, flag);
- }
-recv_char:
- if ((sirfport->uart_reg->uart_type == SIRF_REAL_UART) &&
- (intr_status & SIRFUART_CTS_INT_ST(uint_st)) &&
- !sirfport->tx_dma_state) {
- cts_status = rd_regl(port, ureg->sirfsoc_afc_ctrl) &
- SIRFUART_AFC_CTS_STATUS;
- if (cts_status != 0)
- cts_status = 0;
- else
- cts_status = 1;
- uart_handle_cts_change(port, cts_status);
- wake_up_interruptible(&state->port.delta_msr_wait);
- }
- if (!sirfport->rx_dma_chan &&
- (intr_status & SIRFUART_RX_IO_INT_ST(uint_st))) {
- /*
- * chip will trigger continuous RX_TIMEOUT interrupt
- * in RXFIFO empty and not trigger if RXFIFO recevice
- * data in limit time, original method use RX_TIMEOUT
- * will trigger lots of useless interrupt in RXFIFO
- * empty.RXFIFO received one byte will trigger RX_DONE
- * interrupt.use RX_DONE to wait for data received
- * into RXFIFO, use RX_THD/RX_FULL for lots data receive
- * and use RX_TIMEOUT for the last left data.
- */
- if (intr_status & uint_st->sirfsoc_rx_done) {
- if (!sirfport->is_atlas7) {
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- rd_regl(port, ureg->sirfsoc_int_en_reg)
- & ~(uint_en->sirfsoc_rx_done_en));
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- rd_regl(port, ureg->sirfsoc_int_en_reg)
- | (uint_en->sirfsoc_rx_timeout_en));
- } else {
- wr_regl(port, ureg->sirfsoc_int_en_clr_reg,
- uint_en->sirfsoc_rx_done_en);
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- uint_en->sirfsoc_rx_timeout_en);
- }
- } else {
- if (intr_status & uint_st->sirfsoc_rx_timeout) {
- if (!sirfport->is_atlas7) {
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- rd_regl(port, ureg->sirfsoc_int_en_reg)
- & ~(uint_en->sirfsoc_rx_timeout_en));
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- rd_regl(port, ureg->sirfsoc_int_en_reg)
- | (uint_en->sirfsoc_rx_done_en));
- } else {
- wr_regl(port,
- ureg->sirfsoc_int_en_clr_reg,
- uint_en->sirfsoc_rx_timeout_en);
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- uint_en->sirfsoc_rx_done_en);
- }
- }
- sirfsoc_uart_pio_rx_chars(port, port->fifosize);
- }
- }
- spin_unlock(&port->lock);
- tty_flip_buffer_push(&state->port);
- spin_lock(&port->lock);
- if (intr_status & uint_st->sirfsoc_txfifo_empty) {
- if (sirfport->tx_dma_chan)
- sirfsoc_uart_tx_with_dma(sirfport);
- else {
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- spin_unlock(&port->lock);
- return IRQ_HANDLED;
- } else {
- sirfsoc_uart_pio_tx_chars(sirfport,
- port->fifosize);
- if ((uart_circ_empty(xmit)) &&
- (rd_regl(port, ureg->sirfsoc_tx_fifo_status) &
- ufifo_st->ff_empty(port)))
- sirfsoc_uart_stop_tx(port);
- }
- }
- }
- spin_unlock(&port->lock);
-
- return IRQ_HANDLED;
-}
-
-static void sirfsoc_uart_rx_dma_complete_callback(void *param)
-{
-}
-
-/* submit rx dma task into dmaengine */
-static void sirfsoc_uart_start_next_rx_dma(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_dma_io_ctrl,
- rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
- ~SIRFUART_IO_MODE);
- sirfport->rx_dma_items.xmit.tail =
- sirfport->rx_dma_items.xmit.head = 0;
- sirfport->rx_dma_items.desc =
- dmaengine_prep_dma_cyclic(sirfport->rx_dma_chan,
- sirfport->rx_dma_items.dma_addr, SIRFSOC_RX_DMA_BUF_SIZE,
- SIRFSOC_RX_DMA_BUF_SIZE / 2,
- DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
- if (IS_ERR_OR_NULL(sirfport->rx_dma_items.desc)) {
- dev_err(port->dev, "DMA slave single fail\n");
- return;
- }
- sirfport->rx_dma_items.desc->callback =
- sirfsoc_uart_rx_dma_complete_callback;
- sirfport->rx_dma_items.desc->callback_param = sirfport;
- sirfport->rx_dma_items.cookie =
- dmaengine_submit(sirfport->rx_dma_items.desc);
- dma_async_issue_pending(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(uint_en,
- sirfport->uart_reg->uart_type));
- else
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- SIRFUART_RX_DMA_INT_EN(uint_en,
- sirfport->uart_reg->uart_type));
-}
-
-static unsigned int
-sirfsoc_usp_calc_sample_div(unsigned long set_rate,
- unsigned long ioclk_rate, unsigned long *sample_reg)
-{
- unsigned long min_delta = ~0UL;
- unsigned short sample_div;
- unsigned long ioclk_div = 0;
- unsigned long temp_delta;
-
- for (sample_div = SIRF_USP_MIN_SAMPLE_DIV;
- sample_div <= SIRF_MAX_SAMPLE_DIV; sample_div++) {
- temp_delta = ioclk_rate -
- (ioclk_rate + (set_rate * sample_div) / 2)
- / (set_rate * sample_div) * set_rate * sample_div;
-
- temp_delta = (temp_delta > 0) ? temp_delta : -temp_delta;
- if (temp_delta < min_delta) {
- ioclk_div = (2 * ioclk_rate /
- (set_rate * sample_div) + 1) / 2 - 1;
- if (ioclk_div > SIRF_IOCLK_DIV_MAX)
- continue;
- min_delta = temp_delta;
- *sample_reg = sample_div;
- if (!temp_delta)
- break;
- }
- }
- return ioclk_div;
-}
-
-static unsigned int
-sirfsoc_uart_calc_sample_div(unsigned long baud_rate,
- unsigned long ioclk_rate, unsigned long *set_baud)
-{
- unsigned long min_delta = ~0UL;
- unsigned short sample_div;
- unsigned int regv = 0;
- unsigned long ioclk_div;
- unsigned long baud_tmp;
- int temp_delta;
-
- for (sample_div = SIRF_MIN_SAMPLE_DIV;
- sample_div <= SIRF_MAX_SAMPLE_DIV; sample_div++) {
- ioclk_div = (ioclk_rate / (baud_rate * (sample_div + 1))) - 1;
- if (ioclk_div > SIRF_IOCLK_DIV_MAX)
- continue;
- baud_tmp = ioclk_rate / ((ioclk_div + 1) * (sample_div + 1));
- temp_delta = baud_tmp - baud_rate;
- temp_delta = (temp_delta > 0) ? temp_delta : -temp_delta;
- if (temp_delta < min_delta) {
- regv = regv & (~SIRF_IOCLK_DIV_MASK);
- regv = regv | ioclk_div;
- regv = regv & (~SIRF_SAMPLE_DIV_MASK);
- regv = regv | (sample_div << SIRF_SAMPLE_DIV_SHIFT);
- min_delta = temp_delta;
- *set_baud = baud_tmp;
- }
- }
- return regv;
-}
-
-static void sirfsoc_uart_set_termios(struct uart_port *port,
- struct ktermios *termios,
- struct ktermios *old)
-{
- 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 long config_reg = 0;
- unsigned long baud_rate;
- unsigned long set_baud;
- unsigned long flags;
- unsigned long ic;
- unsigned int clk_div_reg = 0;
- unsigned long txfifo_op_reg, ioclk_rate;
- unsigned long rx_time_out;
- int threshold_div;
- u32 data_bit_len, stop_bit_len, len_val;
- unsigned long sample_div_reg = 0xf;
- ioclk_rate = port->uartclk;
-
- switch (termios->c_cflag & CSIZE) {
- default:
- case CS8:
- data_bit_len = 8;
- config_reg |= SIRFUART_DATA_BIT_LEN_8;
- break;
- case CS7:
- data_bit_len = 7;
- config_reg |= SIRFUART_DATA_BIT_LEN_7;
- break;
- case CS6:
- data_bit_len = 6;
- config_reg |= SIRFUART_DATA_BIT_LEN_6;
- break;
- case CS5:
- data_bit_len = 5;
- config_reg |= SIRFUART_DATA_BIT_LEN_5;
- break;
- }
- if (termios->c_cflag & CSTOPB) {
- config_reg |= SIRFUART_STOP_BIT_LEN_2;
- stop_bit_len = 2;
- } else
- stop_bit_len = 1;
-
- spin_lock_irqsave(&port->lock, flags);
- port->read_status_mask = uint_en->sirfsoc_rx_oflow_en;
- port->ignore_status_mask = 0;
- if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= uint_en->sirfsoc_frm_err_en |
- uint_en->sirfsoc_parity_err_en;
- } else {
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= uint_en->sirfsoc_frm_err_en;
- }
- if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
- port->read_status_mask |= uint_en->sirfsoc_rxd_brk_en;
- if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |=
- uint_en->sirfsoc_frm_err_en |
- uint_en->sirfsoc_parity_err_en;
- if (termios->c_cflag & PARENB) {
- if (termios->c_cflag & CMSPAR) {
- if (termios->c_cflag & PARODD)
- config_reg |= SIRFUART_STICK_BIT_MARK;
- else
- config_reg |= SIRFUART_STICK_BIT_SPACE;
- } else {
- if (termios->c_cflag & PARODD)
- config_reg |= SIRFUART_STICK_BIT_ODD;
- else
- config_reg |= SIRFUART_STICK_BIT_EVEN;
- }
- }
- } else {
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |=
- uint_en->sirfsoc_frm_err_en;
- if (termios->c_cflag & PARENB)
- dev_warn(port->dev,
- "USP-UART not support parity err\n");
- }
- if (termios->c_iflag & IGNBRK) {
- port->ignore_status_mask |=
- uint_en->sirfsoc_rxd_brk_en;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |=
- uint_en->sirfsoc_rx_oflow_en;
- }
- if ((termios->c_cflag & CREAD) == 0)
- port->ignore_status_mask |= SIRFUART_DUMMY_READ;
- /* Hardware Flow Control Settings */
- if (UART_ENABLE_MS(port, termios->c_cflag)) {
- if (!sirfport->ms_enabled)
- sirfsoc_uart_enable_ms(port);
- } else {
- if (sirfport->ms_enabled)
- sirfsoc_uart_disable_ms(port);
- }
- baud_rate = uart_get_baud_rate(port, termios, old, 0, 4000000);
- if (ioclk_rate == 150000000) {
- for (ic = 0; ic < SIRF_BAUD_RATE_SUPPORT_NR; ic++)
- if (baud_rate == baudrate_to_regv[ic].baud_rate)
- clk_div_reg = baudrate_to_regv[ic].reg_val;
- }
- set_baud = baud_rate;
- if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
- if (unlikely(clk_div_reg == 0))
- clk_div_reg = sirfsoc_uart_calc_sample_div(baud_rate,
- ioclk_rate, &set_baud);
- wr_regl(port, ureg->sirfsoc_divisor, clk_div_reg);
- } else {
- clk_div_reg = sirfsoc_usp_calc_sample_div(baud_rate,
- ioclk_rate, &sample_div_reg);
- sample_div_reg--;
- set_baud = ((ioclk_rate / (clk_div_reg+1) - 1) /
- (sample_div_reg + 1));
- /* setting usp mode 2 */
- len_val = ((1 << SIRFSOC_USP_MODE2_RXD_DELAY_OFFSET) |
- (1 << SIRFSOC_USP_MODE2_TXD_DELAY_OFFSET));
- len_val |= ((clk_div_reg & SIRFSOC_USP_MODE2_CLK_DIVISOR_MASK)
- << SIRFSOC_USP_MODE2_CLK_DIVISOR_OFFSET);
- wr_regl(port, ureg->sirfsoc_mode2, len_val);
- }
- if (tty_termios_baud_rate(termios))
- tty_termios_encode_baud_rate(termios, set_baud, set_baud);
- /* set receive timeout && data bits len */
- rx_time_out = SIRFSOC_UART_RX_TIMEOUT(set_baud, 20000);
- rx_time_out = SIRFUART_RECV_TIMEOUT_VALUE(rx_time_out);
- txfifo_op_reg = rd_regl(port, ureg->sirfsoc_tx_fifo_op);
- wr_regl(port, ureg->sirfsoc_tx_fifo_op,
- (txfifo_op_reg & ~SIRFUART_FIFO_START));
- if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
- config_reg |= SIRFUART_UART_RECV_TIMEOUT(rx_time_out);
- wr_regl(port, ureg->sirfsoc_line_ctrl, config_reg);
- } else {
- /*tx frame ctrl*/
- len_val = (data_bit_len - 1) << SIRFSOC_USP_TX_DATA_LEN_OFFSET;
- len_val |= (data_bit_len + 1 + stop_bit_len - 1) <<
- SIRFSOC_USP_TX_FRAME_LEN_OFFSET;
- len_val |= ((data_bit_len - 1) <<
- SIRFSOC_USP_TX_SHIFTER_LEN_OFFSET);
- len_val |= (((clk_div_reg & 0xc00) >> 10) <<
- SIRFSOC_USP_TX_CLK_DIVISOR_OFFSET);
- wr_regl(port, ureg->sirfsoc_tx_frame_ctrl, len_val);
- /*rx frame ctrl*/
- len_val = (data_bit_len - 1) << SIRFSOC_USP_RX_DATA_LEN_OFFSET;
- len_val |= (data_bit_len + 1 + stop_bit_len - 1) <<
- SIRFSOC_USP_RX_FRAME_LEN_OFFSET;
- len_val |= (data_bit_len - 1) <<
- SIRFSOC_USP_RX_SHIFTER_LEN_OFFSET;
- len_val |= (((clk_div_reg & 0xf000) >> 12) <<
- SIRFSOC_USP_RX_CLK_DIVISOR_OFFSET);
- wr_regl(port, ureg->sirfsoc_rx_frame_ctrl, len_val);
- /*async param*/
- wr_regl(port, ureg->sirfsoc_async_param_reg,
- (SIRFUART_USP_RECV_TIMEOUT(rx_time_out)) |
- (sample_div_reg & SIRFSOC_USP_ASYNC_DIV2_MASK) <<
- SIRFSOC_USP_ASYNC_DIV2_OFFSET);
- }
- if (sirfport->tx_dma_chan)
- wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_DMA_MODE);
- else
- wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_IO_MODE);
- if (sirfport->rx_dma_chan)
- wr_regl(port, ureg->sirfs