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)

Reply via email to