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)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.