tty: serial: qcom-geni-serial: split out the FIFO tx code
qcom_geni_serial_handle_tx() is pretty big, let's move the code that handles the actual writing of data to a separate function which makes sense in preparation for introducing a dma variant of handle_tx(). Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Link: https://lore.kernel.org/r/20221229155030.418800-10-brgl@bgdev.pl Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
3931b8fdec
Коммит
d420fb491c
|
@ -704,53 +704,14 @@ static void qcom_geni_serial_start_rx(struct uart_port *uport)
|
||||||
writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
|
writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done,
|
static int qcom_geni_serial_send_chunk_fifo(struct uart_port *uport,
|
||||||
bool active)
|
unsigned int chunk)
|
||||||
{
|
{
|
||||||
struct qcom_geni_serial_port *port = to_dev_port(uport);
|
struct qcom_geni_serial_port *port = to_dev_port(uport);
|
||||||
struct circ_buf *xmit = &uport->state->xmit;
|
struct circ_buf *xmit = &uport->state->xmit;
|
||||||
size_t avail;
|
size_t remaining = chunk;
|
||||||
size_t remaining;
|
int i, tail = xmit->tail;
|
||||||
size_t pending;
|
|
||||||
int i;
|
|
||||||
u32 status;
|
|
||||||
u32 irq_en;
|
|
||||||
unsigned int chunk;
|
|
||||||
int tail;
|
|
||||||
|
|
||||||
status = readl(uport->membase + SE_GENI_TX_FIFO_STATUS);
|
|
||||||
|
|
||||||
/* Complete the current tx command before taking newly added data */
|
|
||||||
if (active)
|
|
||||||
pending = port->tx_remaining;
|
|
||||||
else
|
|
||||||
pending = uart_circ_chars_pending(xmit);
|
|
||||||
|
|
||||||
/* All data has been transmitted and acknowledged as received */
|
|
||||||
if (!pending && !status && done) {
|
|
||||||
qcom_geni_serial_stop_tx(uport);
|
|
||||||
goto out_write_wakeup;
|
|
||||||
}
|
|
||||||
|
|
||||||
avail = port->tx_fifo_depth - (status & TX_FIFO_WC);
|
|
||||||
avail *= BYTES_PER_FIFO_WORD;
|
|
||||||
|
|
||||||
tail = xmit->tail;
|
|
||||||
chunk = min(avail, pending);
|
|
||||||
if (!chunk)
|
|
||||||
goto out_write_wakeup;
|
|
||||||
|
|
||||||
if (!port->tx_remaining) {
|
|
||||||
qcom_geni_serial_setup_tx(uport, pending);
|
|
||||||
port->tx_remaining = pending;
|
|
||||||
|
|
||||||
irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
|
|
||||||
if (!(irq_en & M_TX_FIFO_WATERMARK_EN))
|
|
||||||
writel(irq_en | M_TX_FIFO_WATERMARK_EN,
|
|
||||||
uport->membase + SE_GENI_M_IRQ_EN);
|
|
||||||
}
|
|
||||||
|
|
||||||
remaining = chunk;
|
|
||||||
for (i = 0; i < chunk; ) {
|
for (i = 0; i < chunk; ) {
|
||||||
unsigned int tx_bytes;
|
unsigned int tx_bytes;
|
||||||
u8 buf[sizeof(u32)];
|
u8 buf[sizeof(u32)];
|
||||||
|
@ -772,7 +733,52 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done,
|
||||||
port->tx_remaining -= tx_bytes;
|
port->tx_remaining -= tx_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
xmit->tail = tail;
|
return tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done,
|
||||||
|
bool active)
|
||||||
|
{
|
||||||
|
struct qcom_geni_serial_port *port = to_dev_port(uport);
|
||||||
|
struct circ_buf *xmit = &uport->state->xmit;
|
||||||
|
size_t avail;
|
||||||
|
size_t pending;
|
||||||
|
u32 status;
|
||||||
|
u32 irq_en;
|
||||||
|
unsigned int chunk;
|
||||||
|
|
||||||
|
status = readl(uport->membase + SE_GENI_TX_FIFO_STATUS);
|
||||||
|
|
||||||
|
/* Complete the current tx command before taking newly added data */
|
||||||
|
if (active)
|
||||||
|
pending = port->tx_remaining;
|
||||||
|
else
|
||||||
|
pending = uart_circ_chars_pending(xmit);
|
||||||
|
|
||||||
|
/* All data has been transmitted and acknowledged as received */
|
||||||
|
if (!pending && !status && done) {
|
||||||
|
qcom_geni_serial_stop_tx(uport);
|
||||||
|
goto out_write_wakeup;
|
||||||
|
}
|
||||||
|
|
||||||
|
avail = port->tx_fifo_depth - (status & TX_FIFO_WC);
|
||||||
|
avail *= BYTES_PER_FIFO_WORD;
|
||||||
|
|
||||||
|
chunk = min(avail, pending);
|
||||||
|
if (!chunk)
|
||||||
|
goto out_write_wakeup;
|
||||||
|
|
||||||
|
if (!port->tx_remaining) {
|
||||||
|
qcom_geni_serial_setup_tx(uport, pending);
|
||||||
|
port->tx_remaining = pending;
|
||||||
|
|
||||||
|
irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
|
||||||
|
if (!(irq_en & M_TX_FIFO_WATERMARK_EN))
|
||||||
|
writel(irq_en | M_TX_FIFO_WATERMARK_EN,
|
||||||
|
uport->membase + SE_GENI_M_IRQ_EN);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmit->tail = qcom_geni_serial_send_chunk_fifo(uport, chunk);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The tx fifo watermark is level triggered and latched. Though we had
|
* The tx fifo watermark is level triggered and latched. Though we had
|
||||||
|
|
Загрузка…
Ссылка в новой задаче