Loading drivers/platform/msm/qcom-geni-se.c +31 −6 Original line number Diff line number Diff line Loading @@ -1260,6 +1260,35 @@ int geni_se_tx_dma_prep(struct device *wrapper_dev, void __iomem *base, } EXPORT_SYMBOL(geni_se_tx_dma_prep); /** * geni_se_rx_dma_start() - Prepare the Serial Engine registers for RX DMA transfers. * @base: Base address of the SE register block. * @rx_len: Length of the RX buffer. * @rx_dma: Pointer to store the mapped DMA address. * * This function is used to prepare the Serial Engine registers for DMA RX. * * Return: None. */ void geni_se_rx_dma_start(void __iomem *base, int rx_len, dma_addr_t *rx_dma) { if (!*rx_dma || !base || !rx_len) return; geni_write_reg(7, base, SE_DMA_RX_IRQ_EN_SET); geni_write_reg(GENI_SE_DMA_PTR_L(*rx_dma), base, SE_DMA_RX_PTR_L); geni_write_reg(GENI_SE_DMA_PTR_H(*rx_dma), base, SE_DMA_RX_PTR_H); /* RX does not have EOT bit */ geni_write_reg(0, base, SE_DMA_RX_ATTR); /* Ensure that above register writes went through */ mb(); geni_write_reg(rx_len, base, SE_DMA_RX_LEN); } EXPORT_SYMBOL(geni_se_rx_dma_start); /** * geni_se_rx_dma_prep() - Prepare the Serial Engine for RX DMA transfer * @wrapper_dev: QUPv3 Wrapper Device to which the RX buffer is mapped. Loading @@ -1285,12 +1314,8 @@ int geni_se_rx_dma_prep(struct device *wrapper_dev, void __iomem *base, if (ret) return ret; geni_write_reg(7, base, SE_DMA_RX_IRQ_EN_SET); geni_write_reg(GENI_SE_DMA_PTR_L(*rx_dma), base, SE_DMA_RX_PTR_L); geni_write_reg(GENI_SE_DMA_PTR_H(*rx_dma), base, SE_DMA_RX_PTR_H); /* RX does not have EOT bit */ geni_write_reg(0, base, SE_DMA_RX_ATTR); geni_write_reg(rx_len, base, SE_DMA_RX_LEN); geni_se_rx_dma_start(base, rx_len, rx_dma); return 0; } EXPORT_SYMBOL(geni_se_rx_dma_prep); Loading drivers/tty/serial/msm_geni_serial.c +32 −37 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <linux/tty_flip.h> #include <linux/ioctl.h> #include <linux/pinctrl/consumer.h> #include <linux/dma-mapping.h> /* UART specific GENI registers */ #define SE_UART_LOOPBACK_CFG (0x22C) Loading Loading @@ -1091,7 +1092,6 @@ static void start_rx_sequencer(struct uart_port *uport) unsigned int geni_m_irq_en; unsigned int geni_status; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); int ret; u32 geni_se_param = UART_PARAM_RFR_OPEN; if (port->startup_in_progress) Loading @@ -1099,17 +1099,11 @@ static void start_rx_sequencer(struct uart_port *uport) geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); if (geni_status & S_GENI_CMD_ACTIVE) { if (port->xfer_mode == SE_DMA && !port->rx_dma) { if (port->xfer_mode == SE_DMA) { IPC_LOG_MSG(port->ipc_log_misc, "%s: GENI: 0x%x\n", __func__, geni_status); ret = geni_se_rx_dma_prep(port->wrapper_dev, uport->membase, port->rx_buf, DMA_RX_BUF_SIZE, geni_se_rx_dma_start(uport->membase, DMA_RX_BUF_SIZE, &port->rx_dma); if (ret) { IPC_LOG_MSG(port->ipc_log_misc, "%s: RX buff Fail %d\n", __func__, ret); goto exit_start_rx_sequencer; } } msm_geni_serial_stop_rx(uport); } Loading @@ -1131,21 +1125,14 @@ static void start_rx_sequencer(struct uart_port *uport) geni_write_reg_nolog(geni_m_irq_en, uport->membase, SE_GENI_M_IRQ_EN); } else if (port->xfer_mode == SE_DMA) { ret = geni_se_rx_dma_prep(port->wrapper_dev, uport->membase, port->rx_buf, DMA_RX_BUF_SIZE, &port->rx_dma); if (ret) { dev_err(uport->dev, "%s: RX Prep dma failed %d\n", __func__, ret); msm_geni_serial_stop_rx(uport); goto exit_start_rx_sequencer; } geni_se_rx_dma_start(uport->membase, DMA_RX_BUF_SIZE, &port->rx_dma); } /* * Ensure the writes to the secondary sequencer and interrupt enables * go through. */ mb(); exit_start_rx_sequencer: geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); IPC_LOG_MSG(port->ipc_log_misc, "%s: 0x%x, dma_dbg:0x%x\n", __func__, geni_status, geni_read_reg(uport->membase, SE_DMA_DEBUG_REG0)); Loading Loading @@ -1272,12 +1259,9 @@ static void stop_rx_sequencer(struct uart_port *uport) msm_geni_serial_abort_rx(uport); } exit_rx_seq: if (port->xfer_mode == SE_DMA && port->rx_dma) { if (port->xfer_mode == SE_DMA && port->rx_dma) msm_geni_serial_rx_fsm_rst(uport); geni_se_rx_dma_unprep(port->wrapper_dev, port->rx_dma, DMA_RX_BUF_SIZE); port->rx_dma = (dma_addr_t)NULL; } geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); IPC_LOG_MSG(port->ipc_log_misc, "%s: 0x%x\n", __func__, geni_status); } Loading Loading @@ -1467,16 +1451,13 @@ static int msm_geni_serial_handle_dma_rx(struct uart_port *uport, bool drop_rx) if (!(geni_status & S_GENI_CMD_ACTIVE)) return 0; geni_se_rx_dma_unprep(msm_port->wrapper_dev, msm_port->rx_dma, DMA_RX_BUF_SIZE); msm_port->rx_dma = (dma_addr_t)NULL; rx_bytes = geni_read_reg_nolog(uport->membase, SE_DMA_RX_LEN_IN); if (unlikely(!msm_port->rx_buf)) { IPC_LOG_MSG(msm_port->ipc_log_rx, "%s: NULL Rx_buf\n", __func__); return 0; } rx_bytes = geni_read_reg_nolog(uport->membase, SE_DMA_RX_LEN_IN); if (unlikely(!rx_bytes)) { IPC_LOG_MSG(msm_port->ipc_log_rx, "%s: Size %d\n", __func__, rx_bytes); Loading @@ -1498,10 +1479,9 @@ static int msm_geni_serial_handle_dma_rx(struct uart_port *uport, bool drop_rx) dump_ipc(msm_port->ipc_log_rx, "DMA Rx", (char *)msm_port->rx_buf, 0, rx_bytes); exit_handle_dma_rx: ret = geni_se_rx_dma_prep(msm_port->wrapper_dev, uport->membase, msm_port->rx_buf, DMA_RX_BUF_SIZE, &msm_port->rx_dma); if (ret) IPC_LOG_MSG(msm_port->ipc_log_rx, "%s: %d\n", __func__, ret); geni_se_rx_dma_start(uport->membase, DMA_RX_BUF_SIZE, &msm_port->rx_dma); return ret; } Loading Loading @@ -1787,6 +1767,7 @@ static int msm_geni_serial_port_setup(struct uart_port *uport) int ret = 0; struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); unsigned long cfg0, cfg1; dma_addr_t dma_address; unsigned int rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT; set_rfr_wm(msm_port); Loading @@ -1812,14 +1793,15 @@ static int msm_geni_serial_port_setup(struct uart_port *uport) goto exit_portsetup; } msm_port->rx_buf = devm_kzalloc(uport->dev, DMA_RX_BUF_SIZE, GFP_KERNEL); msm_port->rx_buf = dma_alloc_coherent(msm_port->wrapper_dev, DMA_RX_BUF_SIZE, &dma_address, GFP_KERNEL); if (!msm_port->rx_buf) { devm_kfree(uport->dev, msm_port->rx_fifo); msm_port->rx_fifo = NULL; ret = -ENOMEM; goto exit_portsetup; } msm_port->rx_dma = dma_address; } else { /* * Make an unconditional cancel on the main sequencer to reset Loading @@ -1841,12 +1823,12 @@ static int msm_geni_serial_port_setup(struct uart_port *uport) ret = geni_se_init(uport->membase, msm_port->rx_wm, msm_port->rx_rfr); if (ret) { dev_err(uport->dev, "%s: Fail\n", __func__); goto exit_portsetup; goto free_dma; } ret = geni_se_select_mode(uport->membase, msm_port->xfer_mode); if (ret) goto exit_portsetup; goto free_dma; msm_port->port_setup = true; /* Loading @@ -1854,6 +1836,14 @@ static int msm_geni_serial_port_setup(struct uart_port *uport) * framework. */ mb(); return 0; free_dma: if (msm_port->rx_dma) { dma_free_coherent(msm_port->wrapper_dev, DMA_RX_BUF_SIZE, msm_port->rx_buf, msm_port->rx_dma); msm_port->rx_dma = (dma_addr_t)NULL; } exit_portsetup: return ret; } Loading Loading @@ -2805,6 +2795,11 @@ static int msm_geni_serial_remove(struct platform_device *pdev) wakeup_source_trash(&port->geni_wake); uart_remove_one_port(drv, &port->uport); if (port->rx_dma) { dma_free_coherent(port->wrapper_dev, DMA_RX_BUF_SIZE, port->rx_buf, port->rx_dma); port->rx_dma = (dma_addr_t)NULL; } return 0; } Loading include/linux/qcom-geni-se.h +19 −0 Original line number Diff line number Diff line Loading @@ -667,6 +667,19 @@ int geni_se_clk_freq_match(struct se_geni_rsc *rsc, unsigned long req_freq, int geni_se_tx_dma_prep(struct device *wrapper_dev, void __iomem *base, void *tx_buf, int tx_len, dma_addr_t *tx_dma); /** * geni_se_rx_dma_start() - Prepare the Serial Engine registers for RX DMA transfers. * @base: Base address of the SE register block. * @rx_len: Length of the RX buffer. * @rx_dma: Pointer to store the mapped DMA address. * * This function is used to prepare the Serial Engine registers for DMA RX. * * Return: None. */ void geni_se_rx_dma_start(void __iomem *base, int rx_len, dma_addr_t *rx_dma); /** * geni_se_rx_dma_prep() - Prepare the Serial Engine for RX DMA transfer * @wrapper_dev: QUPv3 Wrapper Device to which the TX buffer is mapped. Loading Loading @@ -795,6 +808,7 @@ int geni_se_iommu_free_buf(struct device *wrapper_dev, dma_addr_t *iova, */ void geni_se_dump_dbg_regs(struct se_geni_rsc *rsc, void __iomem *base, void *ipc); #else static inline unsigned int geni_read_reg_nolog(void __iomem *base, int offset) { Loading Loading @@ -981,5 +995,10 @@ static void geni_se_dump_dbg_regs(struct se_geni_rsc *rsc, void __iomem *base, { } static void geni_se_rx_dma_start(void __iomem *base, int rx_len, dma_addr_t *rx_dma) { } #endif #endif Loading
drivers/platform/msm/qcom-geni-se.c +31 −6 Original line number Diff line number Diff line Loading @@ -1260,6 +1260,35 @@ int geni_se_tx_dma_prep(struct device *wrapper_dev, void __iomem *base, } EXPORT_SYMBOL(geni_se_tx_dma_prep); /** * geni_se_rx_dma_start() - Prepare the Serial Engine registers for RX DMA transfers. * @base: Base address of the SE register block. * @rx_len: Length of the RX buffer. * @rx_dma: Pointer to store the mapped DMA address. * * This function is used to prepare the Serial Engine registers for DMA RX. * * Return: None. */ void geni_se_rx_dma_start(void __iomem *base, int rx_len, dma_addr_t *rx_dma) { if (!*rx_dma || !base || !rx_len) return; geni_write_reg(7, base, SE_DMA_RX_IRQ_EN_SET); geni_write_reg(GENI_SE_DMA_PTR_L(*rx_dma), base, SE_DMA_RX_PTR_L); geni_write_reg(GENI_SE_DMA_PTR_H(*rx_dma), base, SE_DMA_RX_PTR_H); /* RX does not have EOT bit */ geni_write_reg(0, base, SE_DMA_RX_ATTR); /* Ensure that above register writes went through */ mb(); geni_write_reg(rx_len, base, SE_DMA_RX_LEN); } EXPORT_SYMBOL(geni_se_rx_dma_start); /** * geni_se_rx_dma_prep() - Prepare the Serial Engine for RX DMA transfer * @wrapper_dev: QUPv3 Wrapper Device to which the RX buffer is mapped. Loading @@ -1285,12 +1314,8 @@ int geni_se_rx_dma_prep(struct device *wrapper_dev, void __iomem *base, if (ret) return ret; geni_write_reg(7, base, SE_DMA_RX_IRQ_EN_SET); geni_write_reg(GENI_SE_DMA_PTR_L(*rx_dma), base, SE_DMA_RX_PTR_L); geni_write_reg(GENI_SE_DMA_PTR_H(*rx_dma), base, SE_DMA_RX_PTR_H); /* RX does not have EOT bit */ geni_write_reg(0, base, SE_DMA_RX_ATTR); geni_write_reg(rx_len, base, SE_DMA_RX_LEN); geni_se_rx_dma_start(base, rx_len, rx_dma); return 0; } EXPORT_SYMBOL(geni_se_rx_dma_prep); Loading
drivers/tty/serial/msm_geni_serial.c +32 −37 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <linux/tty_flip.h> #include <linux/ioctl.h> #include <linux/pinctrl/consumer.h> #include <linux/dma-mapping.h> /* UART specific GENI registers */ #define SE_UART_LOOPBACK_CFG (0x22C) Loading Loading @@ -1091,7 +1092,6 @@ static void start_rx_sequencer(struct uart_port *uport) unsigned int geni_m_irq_en; unsigned int geni_status; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); int ret; u32 geni_se_param = UART_PARAM_RFR_OPEN; if (port->startup_in_progress) Loading @@ -1099,17 +1099,11 @@ static void start_rx_sequencer(struct uart_port *uport) geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); if (geni_status & S_GENI_CMD_ACTIVE) { if (port->xfer_mode == SE_DMA && !port->rx_dma) { if (port->xfer_mode == SE_DMA) { IPC_LOG_MSG(port->ipc_log_misc, "%s: GENI: 0x%x\n", __func__, geni_status); ret = geni_se_rx_dma_prep(port->wrapper_dev, uport->membase, port->rx_buf, DMA_RX_BUF_SIZE, geni_se_rx_dma_start(uport->membase, DMA_RX_BUF_SIZE, &port->rx_dma); if (ret) { IPC_LOG_MSG(port->ipc_log_misc, "%s: RX buff Fail %d\n", __func__, ret); goto exit_start_rx_sequencer; } } msm_geni_serial_stop_rx(uport); } Loading @@ -1131,21 +1125,14 @@ static void start_rx_sequencer(struct uart_port *uport) geni_write_reg_nolog(geni_m_irq_en, uport->membase, SE_GENI_M_IRQ_EN); } else if (port->xfer_mode == SE_DMA) { ret = geni_se_rx_dma_prep(port->wrapper_dev, uport->membase, port->rx_buf, DMA_RX_BUF_SIZE, &port->rx_dma); if (ret) { dev_err(uport->dev, "%s: RX Prep dma failed %d\n", __func__, ret); msm_geni_serial_stop_rx(uport); goto exit_start_rx_sequencer; } geni_se_rx_dma_start(uport->membase, DMA_RX_BUF_SIZE, &port->rx_dma); } /* * Ensure the writes to the secondary sequencer and interrupt enables * go through. */ mb(); exit_start_rx_sequencer: geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); IPC_LOG_MSG(port->ipc_log_misc, "%s: 0x%x, dma_dbg:0x%x\n", __func__, geni_status, geni_read_reg(uport->membase, SE_DMA_DEBUG_REG0)); Loading Loading @@ -1272,12 +1259,9 @@ static void stop_rx_sequencer(struct uart_port *uport) msm_geni_serial_abort_rx(uport); } exit_rx_seq: if (port->xfer_mode == SE_DMA && port->rx_dma) { if (port->xfer_mode == SE_DMA && port->rx_dma) msm_geni_serial_rx_fsm_rst(uport); geni_se_rx_dma_unprep(port->wrapper_dev, port->rx_dma, DMA_RX_BUF_SIZE); port->rx_dma = (dma_addr_t)NULL; } geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); IPC_LOG_MSG(port->ipc_log_misc, "%s: 0x%x\n", __func__, geni_status); } Loading Loading @@ -1467,16 +1451,13 @@ static int msm_geni_serial_handle_dma_rx(struct uart_port *uport, bool drop_rx) if (!(geni_status & S_GENI_CMD_ACTIVE)) return 0; geni_se_rx_dma_unprep(msm_port->wrapper_dev, msm_port->rx_dma, DMA_RX_BUF_SIZE); msm_port->rx_dma = (dma_addr_t)NULL; rx_bytes = geni_read_reg_nolog(uport->membase, SE_DMA_RX_LEN_IN); if (unlikely(!msm_port->rx_buf)) { IPC_LOG_MSG(msm_port->ipc_log_rx, "%s: NULL Rx_buf\n", __func__); return 0; } rx_bytes = geni_read_reg_nolog(uport->membase, SE_DMA_RX_LEN_IN); if (unlikely(!rx_bytes)) { IPC_LOG_MSG(msm_port->ipc_log_rx, "%s: Size %d\n", __func__, rx_bytes); Loading @@ -1498,10 +1479,9 @@ static int msm_geni_serial_handle_dma_rx(struct uart_port *uport, bool drop_rx) dump_ipc(msm_port->ipc_log_rx, "DMA Rx", (char *)msm_port->rx_buf, 0, rx_bytes); exit_handle_dma_rx: ret = geni_se_rx_dma_prep(msm_port->wrapper_dev, uport->membase, msm_port->rx_buf, DMA_RX_BUF_SIZE, &msm_port->rx_dma); if (ret) IPC_LOG_MSG(msm_port->ipc_log_rx, "%s: %d\n", __func__, ret); geni_se_rx_dma_start(uport->membase, DMA_RX_BUF_SIZE, &msm_port->rx_dma); return ret; } Loading Loading @@ -1787,6 +1767,7 @@ static int msm_geni_serial_port_setup(struct uart_port *uport) int ret = 0; struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); unsigned long cfg0, cfg1; dma_addr_t dma_address; unsigned int rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT; set_rfr_wm(msm_port); Loading @@ -1812,14 +1793,15 @@ static int msm_geni_serial_port_setup(struct uart_port *uport) goto exit_portsetup; } msm_port->rx_buf = devm_kzalloc(uport->dev, DMA_RX_BUF_SIZE, GFP_KERNEL); msm_port->rx_buf = dma_alloc_coherent(msm_port->wrapper_dev, DMA_RX_BUF_SIZE, &dma_address, GFP_KERNEL); if (!msm_port->rx_buf) { devm_kfree(uport->dev, msm_port->rx_fifo); msm_port->rx_fifo = NULL; ret = -ENOMEM; goto exit_portsetup; } msm_port->rx_dma = dma_address; } else { /* * Make an unconditional cancel on the main sequencer to reset Loading @@ -1841,12 +1823,12 @@ static int msm_geni_serial_port_setup(struct uart_port *uport) ret = geni_se_init(uport->membase, msm_port->rx_wm, msm_port->rx_rfr); if (ret) { dev_err(uport->dev, "%s: Fail\n", __func__); goto exit_portsetup; goto free_dma; } ret = geni_se_select_mode(uport->membase, msm_port->xfer_mode); if (ret) goto exit_portsetup; goto free_dma; msm_port->port_setup = true; /* Loading @@ -1854,6 +1836,14 @@ static int msm_geni_serial_port_setup(struct uart_port *uport) * framework. */ mb(); return 0; free_dma: if (msm_port->rx_dma) { dma_free_coherent(msm_port->wrapper_dev, DMA_RX_BUF_SIZE, msm_port->rx_buf, msm_port->rx_dma); msm_port->rx_dma = (dma_addr_t)NULL; } exit_portsetup: return ret; } Loading Loading @@ -2805,6 +2795,11 @@ static int msm_geni_serial_remove(struct platform_device *pdev) wakeup_source_trash(&port->geni_wake); uart_remove_one_port(drv, &port->uport); if (port->rx_dma) { dma_free_coherent(port->wrapper_dev, DMA_RX_BUF_SIZE, port->rx_buf, port->rx_dma); port->rx_dma = (dma_addr_t)NULL; } return 0; } Loading
include/linux/qcom-geni-se.h +19 −0 Original line number Diff line number Diff line Loading @@ -667,6 +667,19 @@ int geni_se_clk_freq_match(struct se_geni_rsc *rsc, unsigned long req_freq, int geni_se_tx_dma_prep(struct device *wrapper_dev, void __iomem *base, void *tx_buf, int tx_len, dma_addr_t *tx_dma); /** * geni_se_rx_dma_start() - Prepare the Serial Engine registers for RX DMA transfers. * @base: Base address of the SE register block. * @rx_len: Length of the RX buffer. * @rx_dma: Pointer to store the mapped DMA address. * * This function is used to prepare the Serial Engine registers for DMA RX. * * Return: None. */ void geni_se_rx_dma_start(void __iomem *base, int rx_len, dma_addr_t *rx_dma); /** * geni_se_rx_dma_prep() - Prepare the Serial Engine for RX DMA transfer * @wrapper_dev: QUPv3 Wrapper Device to which the TX buffer is mapped. Loading Loading @@ -795,6 +808,7 @@ int geni_se_iommu_free_buf(struct device *wrapper_dev, dma_addr_t *iova, */ void geni_se_dump_dbg_regs(struct se_geni_rsc *rsc, void __iomem *base, void *ipc); #else static inline unsigned int geni_read_reg_nolog(void __iomem *base, int offset) { Loading Loading @@ -981,5 +995,10 @@ static void geni_se_dump_dbg_regs(struct se_geni_rsc *rsc, void __iomem *base, { } static void geni_se_rx_dma_start(void __iomem *base, int rx_len, dma_addr_t *rx_dma) { } #endif #endif