Merge tag 'xilinx-for-v2023.01-rc3' of https://source.denx.de/u-boot/custodians/u...
[platform/kernel/u-boot.git] / drivers / core / tag.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2021 Linaro Limited
4  *                      Author: AKASHI Takahiro
5  */
6
7 #include <malloc.h>
8 #include <asm/global_data.h>
9 #include <dm/root.h>
10 #include <dm/tag.h>
11 #include <linux/err.h>
12 #include <linux/list.h>
13 #include <linux/types.h>
14
15 struct udevice;
16
17 DECLARE_GLOBAL_DATA_PTR;
18
19 static const char *const tag_name[] = {
20         [DM_TAG_PLAT]           = "plat",
21         [DM_TAG_PARENT_PLAT]    = "parent_plat",
22         [DM_TAG_UC_PLAT]        = "uclass_plat",
23
24         [DM_TAG_PRIV]           = "priv",
25         [DM_TAG_PARENT_PRIV]    = "parent_priv",
26         [DM_TAG_UC_PRIV]        = "uclass_priv",
27         [DM_TAG_DRIVER_DATA]    = "driver_data",
28
29         [DM_TAG_EFI]            = "efi",
30 };
31
32 const char *tag_get_name(enum dm_tag_t tag)
33 {
34         return tag_name[tag];
35 }
36
37 int dev_tag_set_ptr(struct udevice *dev, enum dm_tag_t tag, void *ptr)
38 {
39         struct dmtag_node *node;
40
41         if (!dev || tag >= DM_TAG_COUNT)
42                 return -EINVAL;
43
44         list_for_each_entry(node, &gd->dmtag_list, sibling) {
45                 if (node->dev == dev && node->tag == tag)
46                         return -EEXIST;
47         }
48
49         node = calloc(sizeof(*node), 1);
50         if (!node)
51                 return -ENOMEM;
52
53         node->dev = dev;
54         node->tag = tag;
55         node->ptr = ptr;
56         list_add_tail(&node->sibling, (struct list_head *)&gd->dmtag_list);
57
58         return 0;
59 }
60
61 int dev_tag_set_val(struct udevice *dev, enum dm_tag_t tag, ulong val)
62 {
63         struct dmtag_node *node;
64
65         if (!dev || tag >= DM_TAG_COUNT)
66                 return -EINVAL;
67
68         list_for_each_entry(node, &gd->dmtag_list, sibling) {
69                 if (node->dev == dev && node->tag == tag)
70                         return -EEXIST;
71         }
72
73         node = calloc(sizeof(*node), 1);
74         if (!node)
75                 return -ENOMEM;
76
77         node->dev = dev;
78         node->tag = tag;
79         node->val = val;
80         list_add_tail(&node->sibling, (struct list_head *)&gd->dmtag_list);
81
82         return 0;
83 }
84
85 int dev_tag_get_ptr(struct udevice *dev, enum dm_tag_t tag, void **ptrp)
86 {
87         struct dmtag_node *node;
88
89         if (!dev || tag >= DM_TAG_COUNT)
90                 return -EINVAL;
91
92         list_for_each_entry(node, &gd->dmtag_list, sibling) {
93                 if (node->dev == dev && node->tag == tag) {
94                         *ptrp = node->ptr;
95                         return 0;
96                 }
97         }
98
99         return -ENOENT;
100 }
101
102 int dev_tag_get_val(struct udevice *dev, enum dm_tag_t tag, ulong *valp)
103 {
104         struct dmtag_node *node;
105
106         if (!dev || tag >= DM_TAG_COUNT)
107                 return -EINVAL;
108
109         list_for_each_entry(node, &gd->dmtag_list, sibling) {
110                 if (node->dev == dev && node->tag == tag) {
111                         *valp = node->val;
112                         return 0;
113                 }
114         }
115
116         return -ENOENT;
117 }
118
119 int dev_tag_del(struct udevice *dev, enum dm_tag_t tag)
120 {
121         struct dmtag_node *node, *tmp;
122
123         if (!dev || tag >= DM_TAG_COUNT)
124                 return -EINVAL;
125
126         list_for_each_entry_safe(node, tmp, &gd->dmtag_list, sibling) {
127                 if (node->dev == dev && node->tag == tag) {
128                         list_del(&node->sibling);
129                         free(node);
130
131                         return 0;
132                 }
133         }
134
135         return -ENOENT;
136 }
137
138 int dev_tag_del_all(struct udevice *dev)
139 {
140         struct dmtag_node *node, *tmp;
141         bool found = false;
142
143         if (!dev)
144                 return -EINVAL;
145
146         list_for_each_entry_safe(node, tmp, &gd->dmtag_list, sibling) {
147                 if (node->dev == dev) {
148                         list_del(&node->sibling);
149                         free(node);
150                         found = true;
151                 }
152         }
153
154         if (found)
155                 return 0;
156
157         return -ENOENT;
158 }
159
160 void dev_tag_collect_stats(struct dm_stats *stats)
161 {
162         struct dmtag_node *node;
163
164         list_for_each_entry(node, &gd->dmtag_list, sibling) {
165                 stats->tag_count++;
166                 stats->tag_size += sizeof(struct dmtag_node);
167         }
168 }