diff mbox series

[v2,1/6] lib: utils/fdt: Add fdt_parse_phandle_with_args() API

Message ID 20210709131059.1502293-2-anup.patel@wdc.com
State Superseded
Headers show
Series GPIO reset support | expand

Commit Message

Anup Patel July 9, 2021, 1:10 p.m. UTC
The libfdt project does not have a generic API to parse phandle
with args from a DT node so we add fdt_parse_phandle_with_args()
for this purpose. This new API will be useful to FDT based drivers.

Signed-off-by: Anup Patel <anup.patel@wdc.com>
---
 include/sbi_utils/fdt/fdt_helper.h | 11 +++++++
 lib/utils/fdt/fdt_helper.c         | 47 ++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)

Comments

Atish Patra July 9, 2021, 6:20 p.m. UTC | #1
On Fri, Jul 9, 2021 at 6:11 AM Anup Patel <anup.patel@wdc.com> wrote:
>
> The libfdt project does not have a generic API to parse phandle
> with args from a DT node so we add fdt_parse_phandle_with_args()
> for this purpose. This new API will be useful to FDT based drivers.
>
> Signed-off-by: Anup Patel <anup.patel@wdc.com>
> ---
>  include/sbi_utils/fdt/fdt_helper.h | 11 +++++++
>  lib/utils/fdt/fdt_helper.c         | 47 ++++++++++++++++++++++++++++++
>  2 files changed, 58 insertions(+)
>
> diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
> index 871f9b9..55b9382 100644
> --- a/include/sbi_utils/fdt/fdt_helper.h
> +++ b/include/sbi_utils/fdt/fdt_helper.h
> @@ -17,6 +17,13 @@ struct fdt_match {
>         void *data;
>  };
>
> +#define FDT_MAX_PHANDLE_ARGS 16
> +struct fdt_phandle_args {
> +       int node_offset;
> +       int args_count;
> +       u32 args[FDT_MAX_PHANDLE_ARGS];
> +};
> +
>  struct platform_uart_data {
>         unsigned long addr;
>         unsigned long freq;
> @@ -32,6 +39,10 @@ int fdt_find_match(void *fdt, int startoff,
>                    const struct fdt_match *match_table,
>                    const struct fdt_match **out_match);
>
> +int fdt_parse_phandle_with_args(void *fdt, int nodeoff,
> +                               const char *prop, const char *cells_prop,
> +                               int index, struct fdt_phandle_args *out_args);
> +
>  int fdt_get_node_addr_size(void *fdt, int node, unsigned long *addr,
>                            unsigned long *size);
>
> diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> index de77196..a970c0f 100644
> --- a/lib/utils/fdt/fdt_helper.c
> +++ b/lib/utils/fdt/fdt_helper.c
> @@ -72,6 +72,53 @@ int fdt_find_match(void *fdt, int startoff,
>         return SBI_ENODEV;
>  }
>
> +int fdt_parse_phandle_with_args(void *fdt, int nodeoff,
> +                               const char *prop, const char *cells_prop,
> +                               int index, struct fdt_phandle_args *out_args)
> +{
> +       u32 i, pcells;
> +       int len, pnodeoff;
> +       const fdt32_t *list, *list_end, *val;
> +
> +       if (!fdt || (nodeoff < 0) || !prop || !cells_prop || !out_args)
> +               return SBI_EINVAL;
> +
> +       list = fdt_getprop(fdt, nodeoff, prop, &len);
> +       if (!list)
> +               return SBI_ENOENT;
> +       list_end = list + (len / sizeof(*list));
> +
> +       while (list < list_end) {
> +               pnodeoff = fdt_node_offset_by_phandle(fdt,
> +                                               fdt32_to_cpu(*list));
> +               if (pnodeoff < 0)
> +                       return pnodeoff;
> +               list++;
> +
> +               val = fdt_getprop(fdt, pnodeoff, cells_prop, &len);
> +               if (!val)
> +                       return SBI_ENOENT;
> +               pcells = fdt32_to_cpu(*val);
> +               if (FDT_MAX_PHANDLE_ARGS < pcells)
> +                       return SBI_EINVAL;
> +               if (list + pcells > list_end)
> +                       return SBI_ENOENT;
> +
> +               if (index > 0) {
> +                       list += pcells;
> +                       index--;
> +               } else {
> +                       out_args->node_offset = pnodeoff;
> +                       out_args->args_count = pcells;
> +                       for (i = 0; i < pcells; i++)
> +                               out_args->args[i] = fdt32_to_cpu(list[i]);
> +                       return 0;
> +               }
> +       }
> +
> +       return SBI_ENOENT;
> +}
> +
>  static int fdt_translate_address(void *fdt, uint64_t reg, int parent,
>                                  unsigned long *addr)
>  {
> --
> 2.25.1
>
>
> --
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi

Reviewed-by: Atish Patra <atish.patra@wdc.com>
diff mbox series

Patch

diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
index 871f9b9..55b9382 100644
--- a/include/sbi_utils/fdt/fdt_helper.h
+++ b/include/sbi_utils/fdt/fdt_helper.h
@@ -17,6 +17,13 @@  struct fdt_match {
 	void *data;
 };
 
+#define FDT_MAX_PHANDLE_ARGS 16
+struct fdt_phandle_args {
+	int node_offset;
+	int args_count;
+	u32 args[FDT_MAX_PHANDLE_ARGS];
+};
+
 struct platform_uart_data {
 	unsigned long addr;
 	unsigned long freq;
@@ -32,6 +39,10 @@  int fdt_find_match(void *fdt, int startoff,
 		   const struct fdt_match *match_table,
 		   const struct fdt_match **out_match);
 
+int fdt_parse_phandle_with_args(void *fdt, int nodeoff,
+				const char *prop, const char *cells_prop,
+				int index, struct fdt_phandle_args *out_args);
+
 int fdt_get_node_addr_size(void *fdt, int node, unsigned long *addr,
 			   unsigned long *size);
 
diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
index de77196..a970c0f 100644
--- a/lib/utils/fdt/fdt_helper.c
+++ b/lib/utils/fdt/fdt_helper.c
@@ -72,6 +72,53 @@  int fdt_find_match(void *fdt, int startoff,
 	return SBI_ENODEV;
 }
 
+int fdt_parse_phandle_with_args(void *fdt, int nodeoff,
+				const char *prop, const char *cells_prop,
+				int index, struct fdt_phandle_args *out_args)
+{
+	u32 i, pcells;
+	int len, pnodeoff;
+	const fdt32_t *list, *list_end, *val;
+
+	if (!fdt || (nodeoff < 0) || !prop || !cells_prop || !out_args)
+		return SBI_EINVAL;
+
+	list = fdt_getprop(fdt, nodeoff, prop, &len);
+	if (!list)
+		return SBI_ENOENT;
+	list_end = list + (len / sizeof(*list));
+
+	while (list < list_end) {
+		pnodeoff = fdt_node_offset_by_phandle(fdt,
+						fdt32_to_cpu(*list));
+		if (pnodeoff < 0)
+			return pnodeoff;
+		list++;
+
+		val = fdt_getprop(fdt, pnodeoff, cells_prop, &len);
+		if (!val)
+			return SBI_ENOENT;
+		pcells = fdt32_to_cpu(*val);
+		if (FDT_MAX_PHANDLE_ARGS < pcells)
+			return SBI_EINVAL;
+		if (list + pcells > list_end)
+			return SBI_ENOENT;
+
+		if (index > 0) {
+			list += pcells;
+			index--;
+		} else {
+			out_args->node_offset = pnodeoff;
+			out_args->args_count = pcells;
+			for (i = 0; i < pcells; i++)
+				out_args->args[i] = fdt32_to_cpu(list[i]);
+			return 0;
+		}
+	}
+
+	return SBI_ENOENT;
+}
+
 static int fdt_translate_address(void *fdt, uint64_t reg, int parent,
 				 unsigned long *addr)
 {