Loading drivers/platform/msm/qcom-geni-se.c +11 −12 Original line number Diff line number Diff line Loading @@ -402,7 +402,7 @@ EXPORT_SYMBOL(geni_setup_s_cmd); */ void geni_cancel_m_cmd(void __iomem *base) { geni_write_reg(M_GENI_CMD_CANCEL, base, SE_GENI_S_CMD_CTRL_REG); geni_write_reg(M_GENI_CMD_CANCEL, base, SE_GENI_M_CMD_CTRL_REG); } EXPORT_SYMBOL(geni_cancel_m_cmd); Loading Loading @@ -684,16 +684,14 @@ int se_geni_resources_off(struct se_geni_rsc *rsc) if (unlikely(!geni_se_dev || !geni_se_dev->bus_bw)) return -ENODEV; ret = pinctrl_select_state(rsc->geni_pinctrl, rsc->geni_gpio_sleep); if (ret) { GENI_SE_ERR(geni_se_dev->log_ctx, false, NULL, "%s: Error %d pinctrl_select_state\n", __func__, ret); return ret; } ret = se_geni_clks_off(rsc); if (ret) GENI_SE_ERR(geni_se_dev->log_ctx, false, NULL, "%s: Error %d turning off clocks\n", __func__, ret); ret = pinctrl_select_state(rsc->geni_pinctrl, rsc->geni_gpio_sleep); if (ret) GENI_SE_ERR(geni_se_dev->log_ctx, false, NULL, "%s: Error %d pinctrl_select_state\n", __func__, ret); return ret; } EXPORT_SYMBOL(se_geni_resources_off); Loading Loading @@ -802,19 +800,20 @@ int se_geni_resources_on(struct se_geni_rsc *rsc) if (unlikely(!geni_se_dev)) return -EPROBE_DEFER; ret = se_geni_clks_on(rsc); ret = pinctrl_select_state(rsc->geni_pinctrl, rsc->geni_gpio_active); if (ret) { GENI_SE_ERR(geni_se_dev->log_ctx, false, NULL, "%s: Error %d during clks_on\n", __func__, ret); "%s: Error %d pinctrl_select_state\n", __func__, ret); return ret; } ret = pinctrl_select_state(rsc->geni_pinctrl, rsc->geni_gpio_active); ret = se_geni_clks_on(rsc); if (ret) { GENI_SE_ERR(geni_se_dev->log_ctx, false, NULL, "%s: Error %d pinctrl_select_state\n", __func__, ret); se_geni_clks_off(rsc); "%s: Error %d during clks_on\n", __func__, ret); pinctrl_select_state(rsc->geni_pinctrl, rsc->geni_gpio_sleep); } return ret; } EXPORT_SYMBOL(se_geni_resources_on); Loading drivers/tty/serial/msm_geni_serial.c +137 −66 Original line number Diff line number Diff line Loading @@ -164,6 +164,7 @@ struct msm_geni_serial_port { int ioctl_count; int edge_count; unsigned int tx_yield_count; bool manual_flow; }; static const struct uart_ops msm_geni_serial_pops; Loading Loading @@ -266,16 +267,18 @@ static bool check_transfers_inflight(struct uart_port *uport) /* Possible stop tx is called multiple times. */ m_cmd_active = geni_status & M_GENI_CMD_ACTIVE; if (port->xfer_mode == SE_DMA) if (port->xfer_mode == SE_DMA) { tx_fifo_status = port->tx_dma ? 1 : 0; else rx_fifo_status = geni_read_reg_nolog(uport->membase, SE_DMA_RX_LEN_IN); } else { tx_fifo_status = geni_read_reg_nolog(uport->membase, SE_GENI_TX_FIFO_STATUS); tx_active = m_cmd_active || tx_fifo_status; rx_fifo_status = geni_read_reg_nolog(uport->membase, SE_GENI_RX_FIFO_STATUS); if (rx_fifo_status) rx_active = true; } tx_active = m_cmd_active || tx_fifo_status; rx_active = rx_fifo_status ? true : false; if (rx_active || tx_active || !uart_circ_empty(xmit)) xfer_on = true; Loading Loading @@ -303,10 +306,12 @@ static void wait_for_transfers_inflight(struct uart_port *uport) 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); IPC_LOG_MSG(port->ipc_log_misc, "%s IOS 0x%x geni status 0x%x rx fifo 0x%x\n", __func__, geni_ios, geni_status, rx_fifo_status); "%s IOS 0x%x geni status 0x%x rx: fifo 0x%x dma 0x%x\n", __func__, geni_ios, geni_status, rx_fifo_status, rx_dma); } } Loading Loading @@ -405,13 +410,9 @@ static unsigned int msm_geni_serial_get_mctrl(struct uart_port *uport) { u32 geni_ios = 0; unsigned int mctrl = TIOCM_DSR | TIOCM_CAR; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); if (device_pending_suspend(uport)) { IPC_LOG_MSG(port->ipc_log_misc, "%s.Device is suspended.\n", __func__); if (device_pending_suspend(uport)) return TIOCM_DSR | TIOCM_CAR | TIOCM_CTS; } geni_ios = geni_read_reg_nolog(uport->membase, SE_GENI_IOS); if (!(geni_ios & IO2_DATA_IN)) Loading @@ -436,8 +437,12 @@ static void msm_geni_serial_set_mctrl(struct uart_port *uport, "%s.Device is suspended.\n", __func__); return; } if (!(mctrl & TIOCM_RTS)) if (!(mctrl & TIOCM_RTS)) { uart_manual_rfr |= (UART_MANUAL_RFR_EN | UART_RFR_NOT_READY); port->manual_flow = true; } else { port->manual_flow = false; } geni_write_reg_nolog(uart_manual_rfr, uport->membase, SE_UART_MANUAL_RFR); /* Write to flow control must complete before return to client*/ Loading Loading @@ -542,7 +547,7 @@ static int msm_geni_serial_poll_bit(struct uart_port *uport, * Total polling iterations based on FIFO worth of bytes to be * sent at current baud .Add a little fluff to the wait. */ total_iter = ((fifo_bits * USEC_PER_SEC) / baud); total_iter = ((fifo_bits * USEC_PER_SEC) / baud) / 10; total_iter += 50; } Loading Loading @@ -920,19 +925,12 @@ static void msm_geni_serial_tx_fsm_rst(struct uart_port *uport) geni_write_reg_nolog(tx_irq_en, uport->membase, SE_DMA_TX_IRQ_EN_SET); } static void msm_geni_serial_stop_tx(struct uart_port *uport) static void stop_tx_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); if (!uart_console(uport) && device_pending_suspend(uport)) { dev_err(uport->dev, "%s.Device is suspended.\n", __func__); IPC_LOG_MSG(port->ipc_log_misc, "%s.Device is suspended.\n", __func__); return; } geni_m_irq_en = geni_read_reg_nolog(uport->membase, SE_GENI_M_IRQ_EN); geni_m_irq_en &= ~M_CMD_DONE_EN; if (port->xfer_mode == FIFO_MODE) { Loading @@ -948,9 +946,7 @@ static void msm_geni_serial_stop_tx(struct uart_port *uport) } } port->xmit_size = 0; geni_write_reg_nolog(geni_m_irq_en, uport->membase, SE_GENI_M_IRQ_EN); geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); /* Possible stop tx is called multiple times. */ Loading @@ -970,13 +966,9 @@ static void msm_geni_serial_stop_tx(struct uart_port *uport) IPC_LOG_MSG(port->ipc_log_misc, "%s\n", __func__); } static void msm_geni_serial_start_rx(struct uart_port *uport) static void msm_geni_serial_stop_tx(struct uart_port *uport) { unsigned int geni_s_irq_en; unsigned int geni_m_irq_en; unsigned int geni_status; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); int ret; if (!uart_console(uport) && device_pending_suspend(uport)) { dev_err(uport->dev, "%s.Device is suspended.\n", __func__); Loading @@ -984,6 +976,16 @@ static void msm_geni_serial_start_rx(struct uart_port *uport) "%s.Device is suspended.\n", __func__); return; } stop_tx_sequencer(uport); } static void start_rx_sequencer(struct uart_port *uport) { unsigned int geni_s_irq_en; unsigned int geni_m_irq_en; unsigned int geni_status; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); int ret; geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); if (geni_status & S_GENI_CMD_ACTIVE) Loading Loading @@ -1011,7 +1013,7 @@ static void msm_geni_serial_start_rx(struct uart_port *uport) dev_err(uport->dev, "%s: RX Prep dma failed %d\n", __func__, ret); msm_geni_serial_stop_rx(uport); goto exit_geni_serial_start_rx; goto exit_start_rx_sequencer; } } /* Loading @@ -1020,10 +1022,24 @@ static void msm_geni_serial_start_rx(struct uart_port *uport) */ mb(); geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); exit_geni_serial_start_rx: exit_start_rx_sequencer: IPC_LOG_MSG(port->ipc_log_misc, "%s 0x%x\n", __func__, geni_status); } static void msm_geni_serial_start_rx(struct uart_port *uport) { struct msm_geni_serial_port *port = GET_DEV_PORT(uport); if (!uart_console(uport) && device_pending_suspend(uport)) { dev_err(uport->dev, "%s.Device is suspended.\n", __func__); IPC_LOG_MSG(port->ipc_log_misc, "%s.Device is suspended.\n", __func__); return; } start_rx_sequencer(&port->uport); } static void msm_geni_serial_rx_fsm_rst(struct uart_port *uport) { unsigned int rx_irq_en; Loading @@ -1043,19 +1059,15 @@ static void msm_geni_serial_rx_fsm_rst(struct uart_port *uport) geni_write_reg_nolog(rx_irq_en, uport->membase, SE_DMA_RX_IRQ_EN_SET); } static void msm_geni_serial_stop_rx(struct uart_port *uport) static void stop_rx_sequencer(struct uart_port *uport) { unsigned int geni_s_irq_en; unsigned int geni_m_irq_en; unsigned int geni_status; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); u32 irq_clear = S_CMD_DONE_EN; bool done; if (!uart_console(uport) && device_pending_suspend(uport)) { IPC_LOG_MSG(port->ipc_log_misc, "%s.Device is suspended.\n", __func__); return; } IPC_LOG_MSG(port->ipc_log_misc, "%s\n", __func__); if (port->xfer_mode == FIFO_MODE) { geni_s_irq_en = geni_read_reg_nolog(uport->membase, Loading @@ -1069,28 +1081,47 @@ static void msm_geni_serial_stop_rx(struct uart_port *uport) SE_GENI_S_IRQ_EN); geni_write_reg_nolog(geni_m_irq_en, uport->membase, SE_GENI_M_IRQ_EN); } else 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); /* Possible stop rx is called multiple times. */ if (!(geni_status & S_GENI_CMD_ACTIVE)) return; goto exit_rx_seq; geni_cancel_s_cmd(uport->membase); /* * Ensure that the cancel goes through before polling for the * cancel control bit. */ mb(); msm_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG, done = msm_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG, S_GENI_CMD_CANCEL, false); geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); if (!done) IPC_LOG_MSG(port->ipc_log_misc, "%s Cancel fail 0x%x\n", __func__, geni_status); geni_write_reg_nolog(irq_clear, uport->membase, SE_GENI_S_IRQ_CLEAR); if ((geni_status & S_GENI_CMD_ACTIVE)) msm_geni_serial_abort_rx(uport); exit_rx_seq: 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; } } static void msm_geni_serial_stop_rx(struct uart_port *uport) { struct msm_geni_serial_port *port = GET_DEV_PORT(uport); if (!uart_console(uport) && device_pending_suspend(uport)) { IPC_LOG_MSG(port->ipc_log_misc, "%s.Device is suspended.\n", __func__); return; } stop_rx_sequencer(uport); } static int handle_rx_hs(struct uart_port *uport, Loading Loading @@ -1890,7 +1921,7 @@ static unsigned int msm_geni_serial_tx_empty(struct uart_port *uport) struct msm_geni_serial_port *port = GET_DEV_PORT(uport); if (!uart_console(uport) && device_pending_suspend(uport)) return 0; return 1; if (port->xfer_mode == SE_DMA) tx_fifo_status = port->tx_dma ? 1 : 0; Loading Loading @@ -2377,6 +2408,11 @@ static int msm_geni_serial_probe(struct platform_device *pdev) goto exit_geni_serial_probe; } /* Optional to use the Rx pin as wakeup irq */ dev_port->wakeup_irq = platform_get_irq(pdev, 1); if ((dev_port->wakeup_irq < 0 && !is_console)) dev_info(&pdev->dev, "No wakeup IRQ configured\n"); dev_port->serial_rsc.geni_pinctrl = devm_pinctrl_get(&pdev->dev); if (IS_ERR_OR_NULL(dev_port->serial_rsc.geni_pinctrl)) { dev_err(&pdev->dev, "No pinctrl config specified!\n"); Loading @@ -2391,6 +2427,16 @@ static int msm_geni_serial_probe(struct platform_device *pdev) ret = PTR_ERR(dev_port->serial_rsc.geni_gpio_active); goto exit_geni_serial_probe; } /* * For clients who setup an Inband wakeup, leave the GPIO pins * always connected to the core, else move the pins to their * defined "sleep" state. */ if (dev_port->wakeup_irq > 0) { dev_port->serial_rsc.geni_gpio_sleep = dev_port->serial_rsc.geni_gpio_active; } else { dev_port->serial_rsc.geni_gpio_sleep = pinctrl_lookup_state(dev_port->serial_rsc.geni_pinctrl, PINCTRL_SLEEP); Loading @@ -2399,6 +2445,7 @@ static int msm_geni_serial_probe(struct platform_device *pdev) ret = PTR_ERR(dev_port->serial_rsc.geni_gpio_sleep); goto exit_geni_serial_probe; } } wakeup_source_init(&dev_port->geni_wake, dev_name(&pdev->dev)); dev_port->tx_fifo_depth = DEF_FIFO_DEPTH_WORDS; Loading @@ -2414,11 +2461,6 @@ static int msm_geni_serial_probe(struct platform_device *pdev) goto exit_geni_serial_probe; } /* Optional to use the Rx pin as wakeup irq */ dev_port->wakeup_irq = platform_get_irq(pdev, 1); if ((dev_port->wakeup_irq < 0 && !is_console)) dev_info(&pdev->dev, "No wakeup IRQ configured\n"); uport->private_data = (void *)drv; platform_set_drvdata(pdev, dev_port); if (is_console) { Loading Loading @@ -2462,25 +2504,42 @@ static int msm_geni_serial_runtime_suspend(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct msm_geni_serial_port *port = platform_get_drvdata(pdev); int ret = 0; u32 uart_manual_rfr = 0; u32 geni_status = geni_read_reg_nolog(port->uport.membase, SE_GENI_STATUS); wait_for_transfers_inflight(&port->uport); /* * Disable Interrupt * Manual RFR On. * Stop Rx. * Resources off */ disable_irq(port->uport.irq); /* * If the clients haven't done a manual flow on/off then go ahead and * set this to manual flow on. */ if (!port->manual_flow) { uart_manual_rfr |= (UART_MANUAL_RFR_EN | UART_RFR_READY); geni_write_reg_nolog(uart_manual_rfr, port->uport.membase, SE_UART_MANUAL_RFR); /* * Ensure that the manual flow on writes go through before * doing a stop_rx else we could end up flowing off the peer. */ mb(); } stop_rx_sequencer(&port->uport); if ((geni_status & M_GENI_CMD_ACTIVE)) stop_tx_sequencer(&port->uport); ret = se_geni_resources_off(&port->serial_rsc); if (ret) { dev_err(dev, "%s: Error ret %d\n", __func__, ret); goto exit_runtime_suspend; } if (port->wakeup_irq > 0) { struct se_geni_rsc *rsc = &port->serial_rsc; port->edge_count = 0; ret = pinctrl_select_state(rsc->geni_pinctrl, rsc->geni_gpio_active); if (ret) { dev_err(dev, "%s: Error %d pinctrl_select_state\n", __func__, ret); goto exit_runtime_suspend; } enable_irq(port->wakeup_irq); } IPC_LOG_MSG(port->ipc_log_pwr, "%s:\n", __func__); Loading @@ -2503,12 +2562,24 @@ static int msm_geni_serial_runtime_resume(struct device *dev) __pm_stay_awake(&port->geni_wake); if (port->wakeup_irq > 0) disable_irq(port->wakeup_irq); /* * Resources On. * Start Rx. * Auto RFR. * Enable IRQ. */ ret = se_geni_resources_on(&port->serial_rsc); if (ret) { dev_err(dev, "%s: Error ret %d\n", __func__, ret); __pm_relax(&port->geni_wake); goto exit_runtime_resume; } start_rx_sequencer(&port->uport); if (!port->manual_flow) geni_write_reg_nolog(0, port->uport.membase, SE_UART_MANUAL_RFR); /* Ensure that the Rx is running before enabling interrupts */ mb(); enable_irq(port->uport.irq); IPC_LOG_MSG(port->ipc_log_pwr, "%s:\n", __func__); exit_runtime_resume: Loading Loading
drivers/platform/msm/qcom-geni-se.c +11 −12 Original line number Diff line number Diff line Loading @@ -402,7 +402,7 @@ EXPORT_SYMBOL(geni_setup_s_cmd); */ void geni_cancel_m_cmd(void __iomem *base) { geni_write_reg(M_GENI_CMD_CANCEL, base, SE_GENI_S_CMD_CTRL_REG); geni_write_reg(M_GENI_CMD_CANCEL, base, SE_GENI_M_CMD_CTRL_REG); } EXPORT_SYMBOL(geni_cancel_m_cmd); Loading Loading @@ -684,16 +684,14 @@ int se_geni_resources_off(struct se_geni_rsc *rsc) if (unlikely(!geni_se_dev || !geni_se_dev->bus_bw)) return -ENODEV; ret = pinctrl_select_state(rsc->geni_pinctrl, rsc->geni_gpio_sleep); if (ret) { GENI_SE_ERR(geni_se_dev->log_ctx, false, NULL, "%s: Error %d pinctrl_select_state\n", __func__, ret); return ret; } ret = se_geni_clks_off(rsc); if (ret) GENI_SE_ERR(geni_se_dev->log_ctx, false, NULL, "%s: Error %d turning off clocks\n", __func__, ret); ret = pinctrl_select_state(rsc->geni_pinctrl, rsc->geni_gpio_sleep); if (ret) GENI_SE_ERR(geni_se_dev->log_ctx, false, NULL, "%s: Error %d pinctrl_select_state\n", __func__, ret); return ret; } EXPORT_SYMBOL(se_geni_resources_off); Loading Loading @@ -802,19 +800,20 @@ int se_geni_resources_on(struct se_geni_rsc *rsc) if (unlikely(!geni_se_dev)) return -EPROBE_DEFER; ret = se_geni_clks_on(rsc); ret = pinctrl_select_state(rsc->geni_pinctrl, rsc->geni_gpio_active); if (ret) { GENI_SE_ERR(geni_se_dev->log_ctx, false, NULL, "%s: Error %d during clks_on\n", __func__, ret); "%s: Error %d pinctrl_select_state\n", __func__, ret); return ret; } ret = pinctrl_select_state(rsc->geni_pinctrl, rsc->geni_gpio_active); ret = se_geni_clks_on(rsc); if (ret) { GENI_SE_ERR(geni_se_dev->log_ctx, false, NULL, "%s: Error %d pinctrl_select_state\n", __func__, ret); se_geni_clks_off(rsc); "%s: Error %d during clks_on\n", __func__, ret); pinctrl_select_state(rsc->geni_pinctrl, rsc->geni_gpio_sleep); } return ret; } EXPORT_SYMBOL(se_geni_resources_on); Loading
drivers/tty/serial/msm_geni_serial.c +137 −66 Original line number Diff line number Diff line Loading @@ -164,6 +164,7 @@ struct msm_geni_serial_port { int ioctl_count; int edge_count; unsigned int tx_yield_count; bool manual_flow; }; static const struct uart_ops msm_geni_serial_pops; Loading Loading @@ -266,16 +267,18 @@ static bool check_transfers_inflight(struct uart_port *uport) /* Possible stop tx is called multiple times. */ m_cmd_active = geni_status & M_GENI_CMD_ACTIVE; if (port->xfer_mode == SE_DMA) if (port->xfer_mode == SE_DMA) { tx_fifo_status = port->tx_dma ? 1 : 0; else rx_fifo_status = geni_read_reg_nolog(uport->membase, SE_DMA_RX_LEN_IN); } else { tx_fifo_status = geni_read_reg_nolog(uport->membase, SE_GENI_TX_FIFO_STATUS); tx_active = m_cmd_active || tx_fifo_status; rx_fifo_status = geni_read_reg_nolog(uport->membase, SE_GENI_RX_FIFO_STATUS); if (rx_fifo_status) rx_active = true; } tx_active = m_cmd_active || tx_fifo_status; rx_active = rx_fifo_status ? true : false; if (rx_active || tx_active || !uart_circ_empty(xmit)) xfer_on = true; Loading Loading @@ -303,10 +306,12 @@ static void wait_for_transfers_inflight(struct uart_port *uport) 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); IPC_LOG_MSG(port->ipc_log_misc, "%s IOS 0x%x geni status 0x%x rx fifo 0x%x\n", __func__, geni_ios, geni_status, rx_fifo_status); "%s IOS 0x%x geni status 0x%x rx: fifo 0x%x dma 0x%x\n", __func__, geni_ios, geni_status, rx_fifo_status, rx_dma); } } Loading Loading @@ -405,13 +410,9 @@ static unsigned int msm_geni_serial_get_mctrl(struct uart_port *uport) { u32 geni_ios = 0; unsigned int mctrl = TIOCM_DSR | TIOCM_CAR; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); if (device_pending_suspend(uport)) { IPC_LOG_MSG(port->ipc_log_misc, "%s.Device is suspended.\n", __func__); if (device_pending_suspend(uport)) return TIOCM_DSR | TIOCM_CAR | TIOCM_CTS; } geni_ios = geni_read_reg_nolog(uport->membase, SE_GENI_IOS); if (!(geni_ios & IO2_DATA_IN)) Loading @@ -436,8 +437,12 @@ static void msm_geni_serial_set_mctrl(struct uart_port *uport, "%s.Device is suspended.\n", __func__); return; } if (!(mctrl & TIOCM_RTS)) if (!(mctrl & TIOCM_RTS)) { uart_manual_rfr |= (UART_MANUAL_RFR_EN | UART_RFR_NOT_READY); port->manual_flow = true; } else { port->manual_flow = false; } geni_write_reg_nolog(uart_manual_rfr, uport->membase, SE_UART_MANUAL_RFR); /* Write to flow control must complete before return to client*/ Loading Loading @@ -542,7 +547,7 @@ static int msm_geni_serial_poll_bit(struct uart_port *uport, * Total polling iterations based on FIFO worth of bytes to be * sent at current baud .Add a little fluff to the wait. */ total_iter = ((fifo_bits * USEC_PER_SEC) / baud); total_iter = ((fifo_bits * USEC_PER_SEC) / baud) / 10; total_iter += 50; } Loading Loading @@ -920,19 +925,12 @@ static void msm_geni_serial_tx_fsm_rst(struct uart_port *uport) geni_write_reg_nolog(tx_irq_en, uport->membase, SE_DMA_TX_IRQ_EN_SET); } static void msm_geni_serial_stop_tx(struct uart_port *uport) static void stop_tx_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); if (!uart_console(uport) && device_pending_suspend(uport)) { dev_err(uport->dev, "%s.Device is suspended.\n", __func__); IPC_LOG_MSG(port->ipc_log_misc, "%s.Device is suspended.\n", __func__); return; } geni_m_irq_en = geni_read_reg_nolog(uport->membase, SE_GENI_M_IRQ_EN); geni_m_irq_en &= ~M_CMD_DONE_EN; if (port->xfer_mode == FIFO_MODE) { Loading @@ -948,9 +946,7 @@ static void msm_geni_serial_stop_tx(struct uart_port *uport) } } port->xmit_size = 0; geni_write_reg_nolog(geni_m_irq_en, uport->membase, SE_GENI_M_IRQ_EN); geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); /* Possible stop tx is called multiple times. */ Loading @@ -970,13 +966,9 @@ static void msm_geni_serial_stop_tx(struct uart_port *uport) IPC_LOG_MSG(port->ipc_log_misc, "%s\n", __func__); } static void msm_geni_serial_start_rx(struct uart_port *uport) static void msm_geni_serial_stop_tx(struct uart_port *uport) { unsigned int geni_s_irq_en; unsigned int geni_m_irq_en; unsigned int geni_status; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); int ret; if (!uart_console(uport) && device_pending_suspend(uport)) { dev_err(uport->dev, "%s.Device is suspended.\n", __func__); Loading @@ -984,6 +976,16 @@ static void msm_geni_serial_start_rx(struct uart_port *uport) "%s.Device is suspended.\n", __func__); return; } stop_tx_sequencer(uport); } static void start_rx_sequencer(struct uart_port *uport) { unsigned int geni_s_irq_en; unsigned int geni_m_irq_en; unsigned int geni_status; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); int ret; geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); if (geni_status & S_GENI_CMD_ACTIVE) Loading Loading @@ -1011,7 +1013,7 @@ static void msm_geni_serial_start_rx(struct uart_port *uport) dev_err(uport->dev, "%s: RX Prep dma failed %d\n", __func__, ret); msm_geni_serial_stop_rx(uport); goto exit_geni_serial_start_rx; goto exit_start_rx_sequencer; } } /* Loading @@ -1020,10 +1022,24 @@ static void msm_geni_serial_start_rx(struct uart_port *uport) */ mb(); geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); exit_geni_serial_start_rx: exit_start_rx_sequencer: IPC_LOG_MSG(port->ipc_log_misc, "%s 0x%x\n", __func__, geni_status); } static void msm_geni_serial_start_rx(struct uart_port *uport) { struct msm_geni_serial_port *port = GET_DEV_PORT(uport); if (!uart_console(uport) && device_pending_suspend(uport)) { dev_err(uport->dev, "%s.Device is suspended.\n", __func__); IPC_LOG_MSG(port->ipc_log_misc, "%s.Device is suspended.\n", __func__); return; } start_rx_sequencer(&port->uport); } static void msm_geni_serial_rx_fsm_rst(struct uart_port *uport) { unsigned int rx_irq_en; Loading @@ -1043,19 +1059,15 @@ static void msm_geni_serial_rx_fsm_rst(struct uart_port *uport) geni_write_reg_nolog(rx_irq_en, uport->membase, SE_DMA_RX_IRQ_EN_SET); } static void msm_geni_serial_stop_rx(struct uart_port *uport) static void stop_rx_sequencer(struct uart_port *uport) { unsigned int geni_s_irq_en; unsigned int geni_m_irq_en; unsigned int geni_status; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); u32 irq_clear = S_CMD_DONE_EN; bool done; if (!uart_console(uport) && device_pending_suspend(uport)) { IPC_LOG_MSG(port->ipc_log_misc, "%s.Device is suspended.\n", __func__); return; } IPC_LOG_MSG(port->ipc_log_misc, "%s\n", __func__); if (port->xfer_mode == FIFO_MODE) { geni_s_irq_en = geni_read_reg_nolog(uport->membase, Loading @@ -1069,28 +1081,47 @@ static void msm_geni_serial_stop_rx(struct uart_port *uport) SE_GENI_S_IRQ_EN); geni_write_reg_nolog(geni_m_irq_en, uport->membase, SE_GENI_M_IRQ_EN); } else 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); /* Possible stop rx is called multiple times. */ if (!(geni_status & S_GENI_CMD_ACTIVE)) return; goto exit_rx_seq; geni_cancel_s_cmd(uport->membase); /* * Ensure that the cancel goes through before polling for the * cancel control bit. */ mb(); msm_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG, done = msm_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG, S_GENI_CMD_CANCEL, false); geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); if (!done) IPC_LOG_MSG(port->ipc_log_misc, "%s Cancel fail 0x%x\n", __func__, geni_status); geni_write_reg_nolog(irq_clear, uport->membase, SE_GENI_S_IRQ_CLEAR); if ((geni_status & S_GENI_CMD_ACTIVE)) msm_geni_serial_abort_rx(uport); exit_rx_seq: 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; } } static void msm_geni_serial_stop_rx(struct uart_port *uport) { struct msm_geni_serial_port *port = GET_DEV_PORT(uport); if (!uart_console(uport) && device_pending_suspend(uport)) { IPC_LOG_MSG(port->ipc_log_misc, "%s.Device is suspended.\n", __func__); return; } stop_rx_sequencer(uport); } static int handle_rx_hs(struct uart_port *uport, Loading Loading @@ -1890,7 +1921,7 @@ static unsigned int msm_geni_serial_tx_empty(struct uart_port *uport) struct msm_geni_serial_port *port = GET_DEV_PORT(uport); if (!uart_console(uport) && device_pending_suspend(uport)) return 0; return 1; if (port->xfer_mode == SE_DMA) tx_fifo_status = port->tx_dma ? 1 : 0; Loading Loading @@ -2377,6 +2408,11 @@ static int msm_geni_serial_probe(struct platform_device *pdev) goto exit_geni_serial_probe; } /* Optional to use the Rx pin as wakeup irq */ dev_port->wakeup_irq = platform_get_irq(pdev, 1); if ((dev_port->wakeup_irq < 0 && !is_console)) dev_info(&pdev->dev, "No wakeup IRQ configured\n"); dev_port->serial_rsc.geni_pinctrl = devm_pinctrl_get(&pdev->dev); if (IS_ERR_OR_NULL(dev_port->serial_rsc.geni_pinctrl)) { dev_err(&pdev->dev, "No pinctrl config specified!\n"); Loading @@ -2391,6 +2427,16 @@ static int msm_geni_serial_probe(struct platform_device *pdev) ret = PTR_ERR(dev_port->serial_rsc.geni_gpio_active); goto exit_geni_serial_probe; } /* * For clients who setup an Inband wakeup, leave the GPIO pins * always connected to the core, else move the pins to their * defined "sleep" state. */ if (dev_port->wakeup_irq > 0) { dev_port->serial_rsc.geni_gpio_sleep = dev_port->serial_rsc.geni_gpio_active; } else { dev_port->serial_rsc.geni_gpio_sleep = pinctrl_lookup_state(dev_port->serial_rsc.geni_pinctrl, PINCTRL_SLEEP); Loading @@ -2399,6 +2445,7 @@ static int msm_geni_serial_probe(struct platform_device *pdev) ret = PTR_ERR(dev_port->serial_rsc.geni_gpio_sleep); goto exit_geni_serial_probe; } } wakeup_source_init(&dev_port->geni_wake, dev_name(&pdev->dev)); dev_port->tx_fifo_depth = DEF_FIFO_DEPTH_WORDS; Loading @@ -2414,11 +2461,6 @@ static int msm_geni_serial_probe(struct platform_device *pdev) goto exit_geni_serial_probe; } /* Optional to use the Rx pin as wakeup irq */ dev_port->wakeup_irq = platform_get_irq(pdev, 1); if ((dev_port->wakeup_irq < 0 && !is_console)) dev_info(&pdev->dev, "No wakeup IRQ configured\n"); uport->private_data = (void *)drv; platform_set_drvdata(pdev, dev_port); if (is_console) { Loading Loading @@ -2462,25 +2504,42 @@ static int msm_geni_serial_runtime_suspend(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct msm_geni_serial_port *port = platform_get_drvdata(pdev); int ret = 0; u32 uart_manual_rfr = 0; u32 geni_status = geni_read_reg_nolog(port->uport.membase, SE_GENI_STATUS); wait_for_transfers_inflight(&port->uport); /* * Disable Interrupt * Manual RFR On. * Stop Rx. * Resources off */ disable_irq(port->uport.irq); /* * If the clients haven't done a manual flow on/off then go ahead and * set this to manual flow on. */ if (!port->manual_flow) { uart_manual_rfr |= (UART_MANUAL_RFR_EN | UART_RFR_READY); geni_write_reg_nolog(uart_manual_rfr, port->uport.membase, SE_UART_MANUAL_RFR); /* * Ensure that the manual flow on writes go through before * doing a stop_rx else we could end up flowing off the peer. */ mb(); } stop_rx_sequencer(&port->uport); if ((geni_status & M_GENI_CMD_ACTIVE)) stop_tx_sequencer(&port->uport); ret = se_geni_resources_off(&port->serial_rsc); if (ret) { dev_err(dev, "%s: Error ret %d\n", __func__, ret); goto exit_runtime_suspend; } if (port->wakeup_irq > 0) { struct se_geni_rsc *rsc = &port->serial_rsc; port->edge_count = 0; ret = pinctrl_select_state(rsc->geni_pinctrl, rsc->geni_gpio_active); if (ret) { dev_err(dev, "%s: Error %d pinctrl_select_state\n", __func__, ret); goto exit_runtime_suspend; } enable_irq(port->wakeup_irq); } IPC_LOG_MSG(port->ipc_log_pwr, "%s:\n", __func__); Loading @@ -2503,12 +2562,24 @@ static int msm_geni_serial_runtime_resume(struct device *dev) __pm_stay_awake(&port->geni_wake); if (port->wakeup_irq > 0) disable_irq(port->wakeup_irq); /* * Resources On. * Start Rx. * Auto RFR. * Enable IRQ. */ ret = se_geni_resources_on(&port->serial_rsc); if (ret) { dev_err(dev, "%s: Error ret %d\n", __func__, ret); __pm_relax(&port->geni_wake); goto exit_runtime_resume; } start_rx_sequencer(&port->uport); if (!port->manual_flow) geni_write_reg_nolog(0, port->uport.membase, SE_UART_MANUAL_RFR); /* Ensure that the Rx is running before enabling interrupts */ mb(); enable_irq(port->uport.irq); IPC_LOG_MSG(port->ipc_log_pwr, "%s:\n", __func__); exit_runtime_resume: Loading