[1/1] lib: utils/fdt: Parse for UART "clocks" property if "clock-frequency" is absent

Xiang W wxjstz at 126.com
Tue Apr 11 22:35:34 PDT 2023


在 2023-04-06星期四的 14:26 +0800,Tan En De写道:
> For UART node, current implementation of fdt_parse_uart_node_common() checks for "clock-frequency" property only.
> However, for UART node that uses more than one clock,
> "clock-frequency" may need to be parsed from the phandle specified in "clocks" property.
> So, this commit adds in logic to parse "clocks" property if "clock-frequency" is absent.
> 
> Signed-off-by: Tan En De <ende.tan at starfivetech.com>
> Signed-off-by: Tan Jun Liang <junliang.tan at starfivetech.com>
> ---
>  include/sbi_utils/fdt/fdt_helper.h |  6 +++
>  lib/utils/fdt/fdt_helper.c         | 65 +++++++++++++++++++++++++++++-
>  2 files changed, 69 insertions(+), 2 deletions(-)
> 
> diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
> index 39d7f3a..d84040e 100644
> --- a/include/sbi_utils/fdt/fdt_helper.h
> +++ b/include/sbi_utils/fdt/fdt_helper.h
> @@ -32,6 +32,12 @@ struct platform_uart_data {
>         unsigned long reg_shift;
>         unsigned long reg_io_width;
>         unsigned long reg_offset;
> +       /*
> +        * For multi-clock UART node.
> +        * clock_index shall be set to zero-indexed main clock's index in the "clocks" list,
> +        * from which freq will be obtained for baud calculation.
> +        */
> +       unsigned long clock_index;
Where is clock_index set. Don't see specific driver modifications. It can be sent with
the patch to modify the driver

Regards,
Xiang W
>  };
>  
>  const struct fdt_match *fdt_match_node(void *fdt, int nodeoff,
> diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> index 48bc2fe..d68d886 100644
> --- a/lib/utils/fdt/fdt_helper.c
> +++ b/lib/utils/fdt/fdt_helper.c
> @@ -313,6 +313,62 @@ int fdt_parse_timebase_frequency(void *fdt, unsigned long *freq)
>         return 0;
>  }
>  
> +/*
> + * For multi-clock UART node.
> + * Parse "clocks" property in UART node to set uart->freq.
> + * "clocks" property is an array of clock phandle and clock specifier pairs.
> + * Before calling this function, uart->clock_index shall be set with
> + * the index of the pair containing the main UART clock's phandle,
> + * which baudrate calculation will be based on.
> + * Return 0 on success, else return -1.
> + */
> +static int fdt_parse_uart_clocks_prop(void *fdt, int nodeoffset,
> +                               struct platform_uart_data *uart)
> +{
> +       const fdt32_t *clocks_val, *clock_cells_val, *clock_frequency_val;
> +       uint32_t clock_phandle, cell_index, clock_cells;
> +       int clocks_len, clock_offset, clock_cells_len, clock_frequency_len;
> +       unsigned long clock_index = uart->clock_index;
> +
> +       /* clocks_val is a flattened array of values, made from the phandle and specifier pairs. */
> +       clocks_val = (fdt32_t *)fdt_getprop(fdt, nodeoffset, "clocks", &clocks_len);
> +       if (!(clocks_len > 0 && clocks_val))
> +               return -1;
> +
> +       cell_index = 0; /* index into the clocks_val */
> +       for (int i = 0; i <= clock_index; i++) {
> +               /* In case of out-of-bound access to the clocks_val array, return -1. */
> +               if (cell_index + 1 > clocks_len)
> +                       return -1;
> +               /* Else, parse the phandle */
> +               clock_phandle = fdt32_to_cpu(clocks_val[cell_index]);
> +               clock_offset = fdt_node_offset_by_phandle(fdt, clock_phandle);
> +               /*
> +                * "#clock-cells" is a required property,
> +                * it tells how many cells the clock specifier takes.
> +                */
> +               clock_cells_val = (fdt32_t *)fdt_getprop(fdt, clock_offset, "#clock-cells", &clock_cells_len);
> +               if (clock_cells_len > 0 && clock_cells_val)
> +                       clock_cells = fdt32_to_cpu(*clock_cells_val);
> +               else
> +                       return -1;
> +               /*
> +                * Advance clock_index to get cell index to next phandle.
> +                * Each phandle and clock specifier pair consists of
> +                * 1 phandle and clock_cells number of specifiers.
> +                */
> +               cell_index += 1 + clock_cells;
> +       }
> +       /* Finally, obtain the uart->freq from "clock-freqeuncy" property */
> +       clock_frequency_val = (fdt32_t *)fdt_getprop(fdt, clock_offset, "clock-frequency", &clock_frequency_len);
> +       if (clock_frequency_len > 0 && clock_frequency_val)
> +               uart->freq = fdt32_to_cpu(*clock_frequency_val);
> +       else
> +               return -1;
> +
> +       return 0;
> +}
> +
>  static int fdt_parse_uart_node_common(void *fdt, int nodeoffset,
>                                       struct platform_uart_data *uart,
>                                       unsigned long default_freq,
> @@ -338,8 +394,13 @@ static int fdt_parse_uart_node_common(void *fdt, int nodeoffset,
>         val = (fdt32_t *)fdt_getprop(fdt, nodeoffset, "clock-frequency", &len);
>         if (len > 0 && val)
>                 uart->freq = fdt32_to_cpu(*val);
> -       else
> -               uart->freq = default_freq;
> +       else {
> +               /* If "clock-frequency" property is absent, try parse for "clocks" property */
> +               rc = fdt_parse_uart_clocks_prop(fdt, nodeoffset, uart);
> +               /* Fall back to default frequency in case of failure to parse */
> +               if (rc < 0)
> +                       uart->freq = default_freq;
> +       }
>  
>         val = (fdt32_t *)fdt_getprop(fdt, nodeoffset, "current-speed", &len);
>         if (len > 0 && val)
> -- 
> 2.34.1
> 
> 



More information about the opensbi mailing list