Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9505c04d authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "serial: msm_geni_serial: Bailout from suspend if RX data is pending"

parents a63e3516 f46551cd
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
 */

#include <linux/clk.h>
@@ -1541,6 +1541,10 @@ void geni_se_dump_dbg_regs(struct se_geni_rsc *rsc, void __iomem *base,
	u32 se_dma_rx_len_in = 0;
	u32 se_dma_tx_len = 0;
	u32 se_dma_tx_len_in = 0;
	u32 geni_m_irq_en = 0;
	u32 geni_s_irq_en = 0;
	u32 geni_dma_tx_irq_en = 0;
	u32 geni_dma_rx_irq_en = 0;
	struct geni_se_device *geni_se_dev;

	if (!ipc)
@@ -1569,6 +1573,10 @@ void geni_se_dump_dbg_regs(struct se_geni_rsc *rsc, void __iomem *base,
	se_dma_rx_len_in = geni_read_reg(base, SE_DMA_RX_LEN_IN);
	se_dma_tx_len = geni_read_reg(base, SE_DMA_TX_LEN);
	se_dma_tx_len_in = geni_read_reg(base, SE_DMA_TX_LEN_IN);
	geni_m_irq_en = geni_read_reg(base, SE_GENI_M_IRQ_EN);
	geni_s_irq_en = geni_read_reg(base, SE_GENI_S_IRQ_EN);
	geni_dma_tx_irq_en = geni_read_reg(base, SE_DMA_TX_IRQ_EN);
	geni_dma_rx_irq_en = geni_read_reg(base, SE_DMA_RX_IRQ_EN);

	GENI_SE_DBG(ipc, false, NULL,
	"%s: m_cmd0:0x%x, m_irq_status:0x%x, geni_status:0x%x, geni_ios:0x%x\n",
@@ -1580,7 +1588,11 @@ void geni_se_dump_dbg_regs(struct se_geni_rsc *rsc, void __iomem *base,
	"se_dma_dbg:0x%x, m_cmd_ctrl:0x%x, dma_rxlen:0x%x, dma_rxlen_in:0x%x\n",
	se_dma_dbg, m_cmd_ctrl, se_dma_rx_len, se_dma_rx_len_in);
	GENI_SE_DBG(ipc, false, NULL,
	"dma_txlen:0x%x, dma_txlen_in:0x%x\n", se_dma_tx_len, se_dma_tx_len_in);
	"dma_txlen:0x%x, dma_txlen_in:0x%x s_irq_status:0x%x\n",
	se_dma_tx_len, se_dma_tx_len_in, s_irq_status);
	GENI_SE_DBG(ipc, false, NULL,
	"dma_txirq_en:0x%x, dma_rxirq_en:0x%x geni_m_irq_en:0x%x geni_s_irq_en:0x%x\n",
	geni_dma_tx_irq_en, geni_dma_rx_irq_en, geni_m_irq_en, geni_s_irq_en);
}
EXPORT_SYMBOL(geni_se_dump_dbg_regs);

+31 −31
Original line number Diff line number Diff line
@@ -114,8 +114,8 @@

#define WAKEBYTE_TIMEOUT_MSEC	(2000)
#define WAIT_XFER_MAX_ITER	(2)
#define WAIT_XFER_MAX_TIMEOUT_US	(10000)
#define WAIT_XFER_MIN_TIMEOUT_US	(9000)
#define WAIT_XFER_MAX_TIMEOUT_US	(150)
#define WAIT_XFER_MIN_TIMEOUT_US	(100)
#define IPC_LOG_PWR_PAGES	(10)
#define IPC_LOG_MISC_PAGES	(30)
#define IPC_LOG_TX_RX_PAGES	(30)
@@ -460,7 +460,6 @@ static void wait_for_transfers_inflight(struct uart_port *uport)
	int iter = 0;
	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
	unsigned int geni_status;
	bool CTS, RX;

	geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
	/* Possible stop rx is called before this. */
@@ -477,19 +476,8 @@ static void wait_for_transfers_inflight(struct uart_port *uport)
		}
	}
	if (check_transfers_inflight(uport)) {
		u32 geni_status = geni_read_reg_nolog(uport->membase,
								SE_GENI_STATUS);
		u32 geni_ios = geni_read_reg_nolog(uport->membase, SE_GENI_IOS);
		u32 rx_fifo_status = geni_read_reg_nolog(uport->membase,
							SE_GENI_RX_FIFO_STATUS);
		u32 rx_dma =
			geni_read_reg_nolog(uport->membase, SE_DMA_RX_LEN_IN);
		CTS = geni_ios & 0x2; // b[1] = UART CTS <- Peer RFR
		RX = geni_ios & 0x1;  // b[0] = UART RX <- Peer TX

		IPC_LOG_MSG(port->ipc_log_misc,
		"%s: geni=0x%x rx_fifo=0x%x rx_dma=0x%x, CTS_IO=%d, RX_IO=%d\n",
		 __func__, geni_status, rx_fifo_status, rx_dma, CTS, RX);
		geni_se_dump_dbg_regs(&port->serial_rsc,
				uport->membase, port->ipc_log_misc);
	}
}

@@ -1346,16 +1334,20 @@ static void start_rx_sequencer(struct uart_port *uport)
	if (geni_status & S_GENI_CMD_ACTIVE) {
		if (port->xfer_mode == SE_DMA) {
			IPC_LOG_MSG(port->ipc_log_misc,
				"%s: GENI: 0x%x\n", __func__, geni_status);
				"%s: mapping rx dma GENI: 0x%x\n",
				__func__, geni_status);
			geni_se_rx_dma_start(uport->membase, DMA_RX_BUF_SIZE,
								&port->rx_dma);
		}
		msm_geni_serial_stop_rx(uport);
	}

	if (port->xfer_mode == SE_DMA)
	if (port->xfer_mode == SE_DMA) {
		IPC_LOG_MSG(port->ipc_log_misc,
			"%s. mapping rx dma\n", __func__);
		geni_se_rx_dma_start(uport->membase, DMA_RX_BUF_SIZE,
							&port->rx_dma);
	}

	/* Start RX with the RFR_OPEN to keep RFR in always ready state */
	geni_setup_s_cmd(uport->membase, UART_START_READ, geni_se_param);
@@ -1425,6 +1417,7 @@ static int stop_rx_sequencer(struct uart_port *uport)
	bool is_rx_active;
	unsigned int stale_delay;
	u32 dma_rx_status, s_irq_status;
	int usage_count;

	IPC_LOG_MSG(port->ipc_log_misc, "%s\n", __func__);

@@ -1438,7 +1431,6 @@ static int stop_rx_sequencer(struct uart_port *uport)
	}

	if (!uart_console(uport)) {
		msm_geni_serial_set_manual_flow(false, port);
		/*
		 * Wait for the stale timeout to happen if there
		 * is any data pending in the rx fifo.
@@ -1467,6 +1459,14 @@ static int stop_rx_sequencer(struct uart_port *uport)
			IPC_LOG_MSG(port->ipc_log_misc, "%s: Interrupt delay\n",
					__func__);
			handle_rx_dma_xfer(s_irq_status, uport);
			if (!port->ioctl_count) {
				usage_count = atomic_read(&uport->dev->power.usage_count);
				IPC_LOG_MSG(port->ipc_log_misc,
					"%s: Abort Stop Rx, extend the PM timer, usage_count:%d\n",
					__func__, usage_count);
				pm_runtime_mark_last_busy(uport->dev);
				return -EBUSY;
			}
		}
	}

@@ -1555,9 +1555,6 @@ static int stop_rx_sequencer(struct uart_port *uport)
	port->s_cmd = false;

exit_rx_seq:
	if (!uart_console(uport))
		msm_geni_serial_set_manual_flow(true, port);

	geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
	IPC_LOG_MSG(port->ipc_log_misc, "%s: End 0x%x dma_dbg:0x%x\n",
		    __func__, geni_status,
@@ -1992,6 +1989,8 @@ static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport)
			msm_geni_serial_handle_dma_rx(uport,
						drop_rx);
			if (!(dma_rx_status & RX_GENI_CANCEL_IRQ)) {
				IPC_LOG_MSG(msm_port->ipc_log_misc,
				"%s. mapping rx dma\n", __func__);
				geni_se_rx_dma_start(uport->membase,
				DMA_RX_BUF_SIZE, &msm_port->rx_dma);
			} else {
@@ -2062,12 +2061,8 @@ static void msm_geni_serial_handle_isr(struct uart_port *uport,
		goto exit_geni_serial_isr;
	}

	if (m_irq_status & (M_IO_DATA_ASSERT_EN | M_IO_DATA_DEASSERT_EN)) {
	if (m_irq_status & (M_IO_DATA_ASSERT_EN | M_IO_DATA_DEASSERT_EN))
		uport->icount.cts++;
		IPC_LOG_MSG(msm_port->ipc_log_misc,
			"%s. cts counter:%d\n", __func__,
				uport->icount.cts);
	}

	if (s_irq_status & S_RX_FIFO_WR_ERR_EN) {
		uport->icount.overrun++;
@@ -3313,9 +3308,11 @@ static int msm_geni_serial_runtime_suspend(struct device *dev)
	u32 geni_status = geni_read_reg_nolog(port->uport.membase,
							SE_GENI_STATUS);

	IPC_LOG_MSG(port->ipc_log_pwr, "%s: Start\n", __func__);
	/* Flow off from UART */
	msm_geni_serial_set_manual_flow(false, port);
	wait_for_transfers_inflight(&port->uport);
	/*
	 * Manual RFR On.
	 * Stop Rx.
	 * Disable Interrupt
	 * Resources off
@@ -3324,17 +3321,20 @@ static int msm_geni_serial_runtime_suspend(struct device *dev)
	if (ret) {
		IPC_LOG_MSG(port->ipc_log_pwr, "%s: stop rx failed %d\n",
							__func__, ret);
		/* Flow on from UART */
		msm_geni_serial_allow_rx(port);
		return -EBUSY;
	}
	geni_status = geni_read_reg_nolog(port->uport.membase, SE_GENI_STATUS);

	geni_status = geni_read_reg_nolog(port->uport.membase, SE_GENI_STATUS);
	if ((geni_status & M_GENI_CMD_ACTIVE))
		stop_tx_sequencer(&port->uport);

	disable_irq(port->uport.irq);

	/*
	 * Above stop_rx disabled the flow so we need to enable it here
	 * Flow on from UART
	 * Above before stop_rx disabled the flow so we need to enable it here
	 * Make sure wake up interrupt is enabled before RFR is made low
	 */
	msm_geni_serial_allow_rx(port);
@@ -3349,7 +3349,7 @@ static int msm_geni_serial_runtime_suspend(struct device *dev)
		port->edge_count = 0;
		enable_irq(port->wakeup_irq);
	}
	IPC_LOG_MSG(port->ipc_log_pwr, "%s:\n", __func__);
	IPC_LOG_MSG(port->ipc_log_pwr, "%s: End\n", __func__);
	__pm_relax(port->geni_wake);
exit_runtime_suspend:
	return ret;