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

Simon Glass sjg at chromium.org
Tue Apr 25 20:01:02 CEST 2023


Hi Venkatesh,

On Tue, 25 Apr 2023 at 06:05, Venkatesh Yadav Abbarapu
<venkatesh.abbarapu at amd.com> 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.
>
> Signed-off-by: Algapally Santosh Sagar <santoshsagar.algapally at amd.com>
> Signed-off-by: Venkatesh Yadav Abbarapu <venkatesh.abbarapu at amd.com>
> ---
>  drivers/serial/serial-uclass.c | 32 +++++++++++++++++++++++++++
>  include/env_default.h          |  7 ++++--
>  include/env_internal.h         |  2 +-
>  include/fdtdec.h               |  8 +++++++
>  include/serial.h               |  1 +
>  lib/fdtdec.c                   | 40 ++++++++++++++++++++++++++++++++++
>  6 files changed, 87 insertions(+), 3 deletions(-)

Can you please add something to doc/ for this feature?

>
> diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
> index 067fae2614..d77d3bda36 100644
> --- a/drivers/serial/serial-uclass.c
> +++ b/drivers/serial/serial-uclass.c
> @@ -154,12 +154,44 @@ static void serial_find_console_or_panic(void)
>  }
>  #endif /* CONFIG_SERIAL_PRESENT */
>
> +#ifdef CONFIG_SERIAL_DT_BAUD

Please drop this #ifdef

> +int serial_get_valid_baudrate(int baud)
> +{
> +       int i;
> +
> +       for (i = 0; i < ARRAY_SIZE(baudrate_table); ++i) {
> +               if (baud == baudrate_table[i])
> +                       return 0;
> +       }
> +
> +       return -EINVAL;
> +}
> +#endif
> +
>  /* 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;
> +#ifdef CONFIG_SERIAL_DT_BAUD

if (IS_ENABLED(CONFIG_SERIAL_DT_BAUD)

You also should add a Kconfig option. I suggest naming it
OF_SERIAL_BOARD since we typically put an OF_ prefix on such options.

> +       int ret = 0;
> +       char *ptr = &default_environment[0];
> +
> +       /*
> +        * Fetch the baudrate from the dtb and update the value in the
> +        * default environment.
> +        */
> +       ret = fdtdec_get_baud_from_dtb(gd->fdt_blob);
> +       if (ret != -EINVAL && ret != -EFAULT) {
> +               gd->baudrate = ret;
> +
> +               while (*ptr != '\0' && *(ptr + 1) != '\0')
> +                       ptr++;
> +               ptr += 2;
> +               sprintf(ptr, "baudrate=%d", gd->baudrate);
> +       }
> +#endif
>         serial_setbrg();
>  #endif
>
> diff --git a/include/env_default.h b/include/env_default.h
> index c0df39d62f..4f286ffc9e 100644
> --- a/include/env_default.h
> +++ b/include/env_default.h
> @@ -23,7 +23,7 @@ env_t embedded_environment __UBOOT_ENV_SECTION__(environment) = {
>         {
>  #elif defined(DEFAULT_ENV_INSTANCE_STATIC)
>  static char default_environment[] = {
> -#elif defined(DEFAULT_ENV_IS_RW)
> +#elif defined(CONFIG_DEFAULT_ENV_IS_RW)
>  char default_environment[] = {
>  #else
>  const char default_environment[] = {
> @@ -44,7 +44,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_SERIAL_DT_BAUD) && defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
>         "baudrate="     __stringify(CONFIG_BAUDRATE)    "\0"
>  #endif
>  #ifdef CONFIG_LOADS_ECHO
> @@ -120,6 +120,9 @@ const char default_environment[] = {
>  #endif
>  #ifdef CFG_EXTRA_ENV_SETTINGS
>         CFG_EXTRA_ENV_SETTINGS
> +#endif
> +#ifdef CONFIG_SERIAL_DT_BAUD
> +       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"

What is this for?

>  #endif
>         "\0"
>  #else /* CONFIG_USE_DEFAULT_ENV_FILE */
> diff --git a/include/env_internal.h b/include/env_internal.h
> index 6a69494646..fcb464263f 100644
> --- a/include/env_internal.h
> +++ b/include/env_internal.h
> @@ -89,7 +89,7 @@ typedef struct environment_s {
>  extern env_t embedded_environment;
>  #endif /* ENV_IS_EMBEDDED */
>
> -#ifdef DEFAULT_ENV_IS_RW
> +#ifdef CONFIG_DEFAULT_ENV_IS_RW

What is this change for?

>  extern char default_environment[];
>  #else
>  extern const char default_environment[];
> diff --git a/include/fdtdec.h b/include/fdtdec.h
> index aa61a0fca1..48937a7a46 100644
> --- a/include/fdtdec.h
> +++ b/include/fdtdec.h
> @@ -657,6 +657,14 @@ int fdtdec_get_alias_seq(const void *blob, const char *base, int node,
>   */
>  int fdtdec_get_alias_highest_id(const void *blob, const char *base);

Could you make this an ofnode_...() function instead? Then you can
call ofnode_read_chosen_string() from your function.

We are trying to drop the fdtdec API.

>
> +/**
> + * Get baudrate from the dtb
> + *
> + * @param blob         Device tree blob (if NULL, then error is returned)
> + * @return Baud rate value, or -ve error .

Return: Baud ...

(we changed to that syntax to work with Sphinx)

But this should become ofnode_read_baud(void)

Exported functions should be documented in the header file, not the C file

> + */
> +int fdtdec_get_baud_from_dtb(const void *blob);
> +
>  /**
>   * Get a property from the /chosen node
>   *
> diff --git a/include/serial.h b/include/serial.h
> index 42bdf3759c..48834b517c 100644
> --- a/include/serial.h
> +++ b/include/serial.h
> @@ -337,6 +337,7 @@ int serial_setconfig(struct udevice *dev, uint config);
>   */
>  int serial_getinfo(struct udevice *dev, struct serial_device_info *info);
>
> +int serial_get_valid_baudrate(int baud);

check_valid_baudrate() would be better since it is checking the
provided rate, not returning a valid rate (as I understand it).

This needs function docs

>  void atmel_serial_initialize(void);
>  void mcf_serial_initialize(void);
>  void mpc85xx_serial_initialize(void);
> diff --git a/lib/fdtdec.c b/lib/fdtdec.c
> index 0827e16859..2fcc12148e 100644
> --- a/lib/fdtdec.c
> +++ b/lib/fdtdec.c
> @@ -570,6 +570,46 @@ int fdtdec_get_alias_highest_id(const void *blob, const char *base)
>         return max;
>  }
>
> +#ifdef CONFIG_SERIAL_DT_BAUD
> +int fdtdec_get_baud_from_dtb(const void *blob)
> +{
> +       const char *str, *p, *baud_start;
> +       u32 baud;
> +
> +       if (!blob)
> +               return -EFAULT;
> +
> +       str = fdtdec_get_chosen_prop(blob, "stdout-path");
> +       if (!str)
> +               return -EINVAL;
> +
> +       p = strchr(str, ':');
> +       if (!p)
> +               return -EINVAL;
> +
> +       baud = 0;
> +       baud_start = p + 1;

It would help to have a comment about the format you are parsing, e.g.
an example string.

I thought it was something like: "serial0:115200n8" in which case I
think you could do:

p = strchr(str, ':')
if (p) {
   uint baud = dectoul(p + 1, NULL);

   ...

}
> +       while (*baud_start != '\0') {
> +               /*
> +                * Uart binding is <baud>{<parity>{<bits>{...}}}
> +                * So the baudrate either is the whole string, or
> +                * ends in the parity characters.
> +                */
> +               if (*baud_start == 'n' || *baud_start == 'o' ||
> +                   *baud_start == 'e')
> +                       break;
> +
> +               baud = baud * 10 + (*baud_start - '0');
> +               baud_start++;
> +       }
> +
> +       if (serial_get_valid_baudrate(baud) == -EINVAL)
> +               return -EINVAL;

ret = func ...
if (ret)
   return ret

(i.e. don't change the error number, and catch all errors that it might return)

> +
> +       return baud;
> +}
> +#endif
> +
>  const char *fdtdec_get_chosen_prop(const void *blob, const char *name)
>  {
>         int chosen_node;
> --
> 2.17.1
>

Regards,
Simon


More information about the U-Boot mailing list