Re: [PATCH v1 1/2] serial: msm_geni: Skip UART TX when no cable is connected
Casey Connolly <[email protected]>
| Newsgroups | org.u-boot-project.lists.u-boot |
|---|---|
| Message-ID | <[email protected]> |
Hi Aswin, On 27/08/2026 09:34, Aswin Murugan wrote: > Add MSM_GENI_SERIAL_CABLE_DETECT Kconfig option and detect a > persistent RX-line BREAK condition (no S_GP_IRQ_3 after > S_GP_IRQ_2) to identify a disconnected debug UART cable, and > suppress TX output in that case to avoid driving an > unterminated line. > > Signed-off-by: Aswin Murugan <[email protected]> > --- > drivers/serial/Kconfig | 9 +++++++ > drivers/serial/serial_msm_geni.c | 41 ++++++++++++++++++++++++++++++++ > 2 files changed, 50 insertions(+) > > diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig > index ffc58d663ff..326088c7027 100644 > --- a/drivers/serial/Kconfig > +++ b/drivers/serial/Kconfig > @@ -1020,6 +1020,15 @@ config MSM_GENI_SERIAL > Driver works in FIFO mode. > Multiple baudrates supported. > > +config MSM_GENI_SERIAL_CABLE_DETECT > + bool "Disable GENI UART TX when no cable/console is connected" > + depends on MSM_GENI_SERIAL > + default n Please explain in the commit message why it's desirable to suppress UART TX in this case, if it's purely for optimising boot time I'd suggest something like default y if CONFIG_LOGLEVEL < 6 default n Then no need to set it in the defconfig. > + help > + Detect a UART RX-line BREAK condition, which indicates that no > + cable is connected to the debug UART port, and suppress UART TX > + output. > + > config MXS_AUART_SERIAL > bool "MXS AUART" > depends on DM_SERIAL > diff --git a/drivers/serial/serial_msm_geni.c b/drivers/serial/serial_msm_geni.c > index ff91e0018fa..8bf5f6eea26 100644 > --- a/drivers/serial/serial_msm_geni.c > +++ b/drivers/serial/serial_msm_geni.c > @@ -98,6 +98,7 @@ struct msm_serial_data { > u32 baud; > u32 oversampling; > struct clk *se; > + bool cable_connected; > }; > > unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200, > @@ -298,6 +299,28 @@ static u32 qcom_geni_serial_tx_empty(u64 base) > return !readl(base + SE_GENI_TX_FIFO_STATUS); > } > > +/** > + * qcom_geni_serial_is_cable_connected() - Check UART RX-line BREAK condition. > + * @base: Pointer to the concerned serial engine. > + * > + * A serial cable that is not connected leaves the RX line in a state that > + * the UART hardware reports as a BREAK condition that never ends, i.e. > + * S_GP_IRQ_2 (RX_BREAK_START) gets set without a following S_GP_IRQ_3 > + * (RX_BREAK_END). This function checks the secondary sequencer IRQ status > + * for that pattern. > + * > + * Return: false, if no cable is connected, true otherwise. > + */ > +static bool qcom_geni_serial_is_cable_connected(u64 base) > +{ > + u32 s_irq_status = readl(base + SE_GENI_S_IRQ_STATUS); > + > + if ((s_irq_status & S_GP_IRQ_2_EN) && !(s_irq_status & S_GP_IRQ_3_EN)) > + return false; > + > + return true; > +} > + > /** > * geni_se_setup_s_cmd() - Setup the secondary sequencer > * @se: Pointer to the concerned serial engine. > @@ -384,6 +407,10 @@ static int msm_serial_putc(struct udevice *dev, const char ch) > { > struct msm_serial_data *priv = dev_get_priv(dev); > > + if (CONFIG_IS_ENABLED(MSM_GENI_SERIAL_CABLE_DETECT) && > + !priv->cable_connected) > + return 0; > + > writel(DEF_TX_WM, priv->base + SE_GENI_TX_WATERMARK_REG); > qcom_geni_serial_setup_tx(priv->base, 1); > > @@ -565,6 +592,11 @@ static int msm_serial_probe(struct udevice *dev) > qcom_geni_serial_start_rx(dev); > qcom_geni_serial_start_tx(priv->base); > > + if (CONFIG_IS_ENABLED(MSM_GENI_SERIAL_CABLE_DETECT)) > + priv->cable_connected = qcom_geni_serial_is_cable_connected(priv->base); > + else > + priv->cable_connected = true; > + > return 0; > } > > @@ -615,6 +647,8 @@ static struct udevice init_dev = { > #error Clocks cannot be set at early debug. Change CONFIG_BAUDRATE > #endif > > +static bool debug_uart_cable_connected = true; > + > static inline void _debug_uart_init(void) > { > phys_addr_t base = CONFIG_VAL(DEBUG_UART_BASE); > @@ -623,12 +657,19 @@ static inline void _debug_uart_init(void) > writel(DEF_RX_WM, base + SE_GENI_RX_WATERMARK_REG); > geni_serial_baud(base, CLK_DIV, CONFIG_BAUDRATE); > qcom_geni_serial_start_tx(base); > + > + if (CONFIG_IS_ENABLED(MSM_GENI_SERIAL_CABLE_DETECT)) > + debug_uart_cable_connected = qcom_geni_serial_is_cable_connected(base); > } > > static inline void _debug_uart_putc(int ch) > { > phys_addr_t base = CONFIG_VAL(DEBUG_UART_BASE); > > + if (CONFIG_IS_ENABLED(MSM_GENI_SERIAL_CABLE_DETECT) && > + !debug_uart_cable_connected) > + return; > + > writel(DEF_TX_WM, base + SE_GENI_TX_WATERMARK_REG); > qcom_geni_serial_setup_tx(base, 1); > qcom_geni_serial_poll_bit(&init_dev, SE_GENI_M_IRQ_STATUS, -- // Casey (she/her)