[PATCH v8 2/2] serial: zynqmp: Fetch baudrate from dtb and update

Michal Simek michal.simek at amd.com
Mon Oct 2 12:16:12 CEST 2023


Hi Simon,

On 9/21/23 13:20, Venkatesh Yadav Abbarapu wrote:
> From: Algapally Santosh Sagar <santoshsagar.algapally at amd.com>
> 
> The baudrate configured in .config is taken by default by serial. If
> change of baudrate is required then the .config needs to changed and
> u-boot recompilation is required or the u-boot environment needs to be
> updated.
> 
> To avoid this, support is added to fetch the baudrate directly from the
> device tree file and update.
> The serial, prints the log with the configured baudrate in the dtb.
> The commit c4df0f6f315c ("arm: mvebu: Espressobin: Set default value for
> $fdtfile env variable") is taken as reference for changing the default
> environment variable.
> 
> The default environment stores the default baudrate value, When default
> baudrate and dtb baudrate are not same glitches are seen on the serial.
> So, the environment also needs to be updated with the dtb baudrate to
> avoid the glitches on the serial.
> 
> Also add test to cover this new function.
> 
> Signed-off-by: Algapally Santosh Sagar <santoshsagar.algapally at amd.com>
> Signed-off-by: Venkatesh Yadav Abbarapu <venkatesh.abbarapu at amd.com>
> ---
>   arch/sandbox/dts/test.dts      |  1 +
>   doc/README.serial_dt_baud      | 41 ++++++++++++++++++++++++++++
>   drivers/core/ofnode.c          | 18 +++++++++++++
>   drivers/serial/Kconfig         |  9 +++++++
>   drivers/serial/serial-uclass.c | 49 ++++++++++++++++++++++++++++++++++
>   include/dm/ofnode.h            | 14 ++++++++--
>   include/env_default.h          |  6 ++++-
>   include/serial.h               |  7 +++++
>   test/dm/serial.c               |  1 +
>   9 files changed, 143 insertions(+), 3 deletions(-)
>   create mode 100644 doc/README.serial_dt_baud
> 
> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> index f351d5cb84..deb57f146a 100644
> --- a/arch/sandbox/dts/test.dts
> +++ b/arch/sandbox/dts/test.dts
> @@ -1499,6 +1499,7 @@
>   		other-node = "/some-bus/c-test at 5";
>   		int-values = <0x1937 72993>;
>   		u-boot,acpi-ssdt-order = <&acpi_test2 &acpi_test1>;
> +		stdout-path = "serial0:115200n8";
>   		chosen-test {
>   			compatible = "denx,u-boot-fdt-test";
>   			reg = <9 1>;
> diff --git a/doc/README.serial_dt_baud b/doc/README.serial_dt_baud
> new file mode 100644
> index 0000000000..f8768d0e1b
> --- /dev/null
> +++ b/doc/README.serial_dt_baud
> @@ -0,0 +1,41 @@
> +Fetch serial baudrate from DT
> +-----------------------------
> +
> +To support fetching of baudrate from DT, the following is done:-
> +
> +The baudrate configured in Kconfig symbol CONFIG_BAUDRATE is taken by default by serial.
> +If change of baudrate is required then the Kconfig symbol CONFIG_BAUDRATE needs to
> +changed and U-Boot recompilation is required or the U-Boot environment needs to be updated.
> +
> +To avoid this, add support to fetch the baudrate directly from the device tree file and
> +update the environment.
> +
> +The default environment stores the default baudrate value. When default baudrate and dtb
> +baudrate are not same glitches are seen on the serial.
> +So, the environment also needs to be updated with the dtb baudrate to avoid the glitches on
> +the serial which is enabled by OF_SERIAL_BAUD.
> +
> +The Kconfig SPL_ENV_SUPPORT needs to be enabled to allow patching in SPL.
> +
> +The Kconfig DEFAULT_ENV_IS_RW which is enabled by OF_SERIAL_BAUD with making the environment
> +writable.
> +
> +The ofnode_read_baud() function parses and fetches the baudrate value from the DT. This value
> +is validated and updated to baudrate during serial init. Padding is added at the end of the
> +default environment and the dt baudrate is updated with the latest value.
> +
> +Example:-
> +
> +The serial port options are of the form "bbbbpnf", where "bbbb" is the baud rate, "p" is parity ("n", "o", or "e"),
> +"n" is number of bits, and "f" is flow control ("r" for RTS or omit it). Default is "115200n8".
> +
> +chosen {
> +		bootargs = "earlycon console=ttyPS0,115200 clk_ignore_unused root=/dev/ram0 rw init_fatal_sh=1";
> +		stdout-path = "serial0:115200n8";
> +	};
> +
> +From the chosen node, stdout-path property is obtained as string.
> +
> +	stdout-path = "serial0:115200n8";
> +
> +The string is parsed to get the baudrate 115200. This string is converted to integer and updated to the environment.
> diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
> index 8df16e56af..42f51ca93c 100644
> --- a/drivers/core/ofnode.c
> +++ b/drivers/core/ofnode.c
> @@ -895,6 +895,24 @@ ofnode ofnode_get_chosen_node(const char *name)
>   	return ofnode_path(prop);
>   }
>   
> +int ofnode_read_baud(void)
> +{
> +	const char *str, *p;
> +	u32 baud;
> +
> +	str = ofnode_read_chosen_string("stdout-path");
> +	if (!str)
> +		return -EINVAL;
> +
> +	/* Parse string serial0:115200n8 */
> +	p = strchr(str, ':');
> +	if (!p)
> +		return -EINVAL;
> +
> +	baud = dectoul(p + 1, NULL);
> +	return baud;
> +}
> +
>   const void *ofnode_read_aliases_prop(const char *propname, int *sizep)
>   {
>   	ofnode node;
> diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
> index 4d27034c3f..7fdf600dc5 100644
> --- a/drivers/serial/Kconfig
> +++ b/drivers/serial/Kconfig
> @@ -24,6 +24,15 @@ config BAUDRATE
>   	  in the SPL stage (most drivers) or for choosing a default baudrate
>   	  in the absence of an environment setting (serial_mxc.c).
>   
> +config OF_SERIAL_BAUD
> +	bool "Fetch serial baudrate from device tree"
> +	depends on DM_SERIAL && SPL_ENV_SUPPORT
> +	select DEFAULT_ENV_IS_RW
> +	help
> +	  Select this to enable fetching and setting of the baudrate
> +	  configured in the DT. Replace the default baudrate with the DT
> +	  baudrate and also set it to the environment.
> +
>   config DEFAULT_ENV_IS_RW
>   	bool "Make default environment as writable"
>   	help
> diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
> index 067fae2614..a6291d21d2 100644
> --- a/drivers/serial/serial-uclass.c
> +++ b/drivers/serial/serial-uclass.c
> @@ -154,12 +154,61 @@ static void serial_find_console_or_panic(void)
>   }
>   #endif /* CONFIG_SERIAL_PRESENT */
>   
> +/**
> + * check_valid_baudrate() - Check whether baudrate is valid or not
> + *
> + * @baud: baud rate to check
> + * Return: 0 if OK, -ve on error
> + */
> +static int check_valid_baudrate(int baud)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(baudrate_table); ++i) {
> +		if (baud == baudrate_table[i])
> +			return 0;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +int fetch_baud_from_dtb(void)
> +{
> +	int baud_value, ret;
> +
> +	baud_value = ofnode_read_baud();
> +	ret = check_valid_baudrate(baud_value);
> +	if (ret)
> +		return ret;
> +
> +	return baud_value;
> +}
> +
>   /* Called prior to relocation */
>   int serial_init(void)
>   {
>   #if CONFIG_IS_ENABLED(SERIAL_PRESENT)
>   	serial_find_console_or_panic();
>   	gd->flags |= GD_FLG_SERIAL_READY;
> +
> +	if (IS_ENABLED(CONFIG_OF_SERIAL_BAUD)) {
> +		int ret = 0;
> +		char *ptr = (char*)&default_environment[0];
> +
> +		/*
> +		 * Fetch the baudrate from the dtb and update the value in the
> +		 * default environment.
> +		 */
> +		ret = fetch_baud_from_dtb();
> +		if (ret != -EINVAL && ret != -EFAULT) {
> +			gd->baudrate = ret;
> +
> +			while (*ptr != '\0' && *(ptr + 1) != '\0')
> +				ptr++;
> +			ptr += 2;
> +			sprintf(ptr, "baudrate=%d", gd->baudrate);
> +		}
> +	}
>   	serial_setbrg();
>   #endif
>   
> diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
> index 0f38b3e736..f0854cc28d 100644
> --- a/include/dm/ofnode.h
> +++ b/include/dm/ofnode.h
> @@ -942,12 +942,22 @@ const char *ofnode_read_chosen_string(const char *propname);
>   ofnode ofnode_get_chosen_node(const char *propname);
>   
>   /**
> - * ofnode_read_aliases_prop() - get the value of a aliases property
> + * ofnode_read_baud() - get the baudrate from string value of chosen property
>    *
> - * This looks for a property within the /aliases node and returns its value
> + * This looks for stdout-path property within the /chosen node and parses its
> + * value to return baudrate.
>    *
>    * This only works with the control FDT.
>    *
> + * Return: baudrate value if found, else -ve error code
> + */
> +int ofnode_read_baud(void);
> +
> +/**
> + * ofnode_read_aliases_prop() - get the value of a aliases property
> + *
> + * This looks for a property within the /aliases node and returns its value
> + *
>    * @propname: Property name to look for
>    * @sizep: Returns size of property, or `FDT_ERR_...` error code if function
>    *	returns NULL
> diff --git a/include/env_default.h b/include/env_default.h
> index 227cad7c34..2ca4a087d3 100644
> --- a/include/env_default.h
> +++ b/include/env_default.h
> @@ -42,7 +42,7 @@ const char default_environment[] = {
>   #if defined(CONFIG_BOOTDELAY)
>   	"bootdelay="	__stringify(CONFIG_BOOTDELAY)	"\0"
>   #endif
> -#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
> +#if !defined(CONFIG_OF_SERIAL_BAUD) && defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
>   	"baudrate="	__stringify(CONFIG_BAUDRATE)	"\0"
>   #endif
>   #ifdef	CONFIG_LOADS_ECHO
> @@ -118,6 +118,10 @@ const char default_environment[] = {
>   #endif
>   #ifdef	CFG_EXTRA_ENV_SETTINGS
>   	CFG_EXTRA_ENV_SETTINGS
> +#endif
> +#ifdef CONFIG_OF_SERIAL_BAUD
> +	/* Padding for baudrate at the end when environment is writable */
> +	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
>   #endif
>   	"\0"
>   #else /* CONFIG_USE_DEFAULT_ENV_FILE */
> diff --git a/include/serial.h b/include/serial.h
> index 42bdf3759c..b21a452a3a 100644
> --- a/include/serial.h
> +++ b/include/serial.h
> @@ -337,6 +337,13 @@ int serial_setconfig(struct udevice *dev, uint config);
>    */
>   int serial_getinfo(struct udevice *dev, struct serial_device_info *info);
>   
> +/**
> + * fetch_baud_from_dtb() - Fetch the baudrate value from DT
> + *
> + * Return: baudrate if OK, -ve on error
> + */
> +int fetch_baud_from_dtb(void);
> +
>   void atmel_serial_initialize(void);
>   void mcf_serial_initialize(void);
>   void mpc85xx_serial_initialize(void);
> diff --git a/test/dm/serial.c b/test/dm/serial.c
> index 37d17a65f1..34b783e062 100644
> --- a/test/dm/serial.c
> +++ b/test/dm/serial.c
> @@ -29,6 +29,7 @@ static int dm_test_serial(struct unit_test_state *uts)
>   					      &dev_serial));
>   
>   	ut_assertok(serial_tstc());
> +	ut_asserteq(115200, fetch_baud_from_dtb());
>   	/*
>   	 * test with default config which is the only one supported by
>   	 * sandbox_serial driver

Can you please review this patch?

Thanks,
Michal


More information about the U-Boot mailing list