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)