diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-26 15:09:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-26 15:09:58 -0400 |
commit | b27186abb37b7bd19e0ca434f4f425c807dbd708 (patch) | |
tree | 8f20702cf0744cc66907d3b8578a8083cd25d680 /scripts/dtc/treesource.c | |
parent | 0ef7791e2bfb2e10aa95dc492eab72074cef9942 (diff) | |
parent | d061864b89c3234b53d8884027b0cd6f06bd3149 (diff) |
Merge tag 'devicetree-for-4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux
Pull Devicetree updates from Rob Herring:
"A bit bigger than normal as I've been busy this cycle.
There's a few things with dependencies and a few things subsystem
maintainers didn't pick up, so I'm taking them thru my tree.
The fixes from Johan didn't get into linux-next, but they've been
waiting for some time now and they are what's left of what subsystem
maintainers didn't pick up.
Summary:
- Sync dtc with upstream version v1.4.7-14-gc86da84d30e4
- Work to get rid of direct accesses to struct device_node name and
type pointers in preparation for removing them. New helpers for
parsing DT cpu nodes and conversions to use the helpers. printk
conversions to %pOFn for printing DT node names. Most went thru
subystem trees, so this is the remainder.
- Fixes to DT child node lookups to actually be restricted to child
nodes instead of treewide.
- Refactoring of dtb targets out of arch code. This makes the support
more uniform and enables building all dtbs on c6x, microblaze, and
powerpc.
- Various DT binding updates for Renesas r8a7744 SoC
- Vendor prefixes for Facebook, OLPC
- Restructuring of some ARM binding docs moving some peripheral
bindings out of board/SoC binding files
- New "secure-chosen" binding for secure world settings on ARM
- Dual licensing of 2 DT IRQ binding headers"
* tag 'devicetree-for-4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (78 commits)
ARM: dt: relicense two DT binding IRQ headers
power: supply: twl4030-charger: fix OF sibling-node lookup
NFC: nfcmrvl_uart: fix OF child-node lookup
net: stmmac: dwmac-sun8i: fix OF child-node lookup
net: bcmgenet: fix OF child-node lookup
drm/msm: fix OF child-node lookup
drm/mediatek: fix OF sibling-node lookup
of: Add missing exports of node name compare functions
dt-bindings: Add OLPC vendor prefix
dt-bindings: misc: bk4: Add device tree binding for Liebherr's BK4 SPI bus
dt-bindings: thermal: samsung: Add SPDX license identifier
dt-bindings: clock: samsung: Add SPDX license identifiers
dt-bindings: timer: ostm: Add R7S9210 support
dt-bindings: phy: rcar-gen2: Add r8a7744 support
dt-bindings: can: rcar_can: Add r8a7744 support
dt-bindings: timer: renesas, cmt: Document r8a7744 CMT support
dt-bindings: watchdog: renesas-wdt: Document r8a7744 support
dt-bindings: thermal: rcar: Add device tree support for r8a7744
Documentation: dt: Add binding for /secure-chosen/stdout-path
dt-bindings: arm: zte: Move sysctrl bindings to their own doc
...
Diffstat (limited to 'scripts/dtc/treesource.c')
-rw-r--r-- | scripts/dtc/treesource.c | 225 |
1 files changed, 135 insertions, 90 deletions
diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c index 2461a3d068a0..f2874f1d1465 100644 --- a/scripts/dtc/treesource.c +++ b/scripts/dtc/treesource.c | |||
@@ -61,24 +61,14 @@ static bool isstring(char c) | |||
61 | || strchr("\a\b\t\n\v\f\r", c)); | 61 | || strchr("\a\b\t\n\v\f\r", c)); |
62 | } | 62 | } |
63 | 63 | ||
64 | static void write_propval_string(FILE *f, struct data val) | 64 | static void write_propval_string(FILE *f, const char *s, size_t len) |
65 | { | 65 | { |
66 | const char *str = val.val; | 66 | const char *end = s + len - 1; |
67 | int i; | 67 | assert(*end == '\0'); |
68 | struct marker *m = val.markers; | ||
69 | |||
70 | assert(str[val.len-1] == '\0'); | ||
71 | 68 | ||
72 | while (m && (m->offset == 0)) { | ||
73 | if (m->type == LABEL) | ||
74 | fprintf(f, "%s: ", m->ref); | ||
75 | m = m->next; | ||
76 | } | ||
77 | fprintf(f, "\""); | 69 | fprintf(f, "\""); |
78 | 70 | while (s < end) { | |
79 | for (i = 0; i < (val.len-1); i++) { | 71 | char c = *s++; |
80 | char c = str[i]; | ||
81 | |||
82 | switch (c) { | 72 | switch (c) { |
83 | case '\a': | 73 | case '\a': |
84 | fprintf(f, "\\a"); | 74 | fprintf(f, "\\a"); |
@@ -108,91 +98,78 @@ static void write_propval_string(FILE *f, struct data val) | |||
108 | fprintf(f, "\\\""); | 98 | fprintf(f, "\\\""); |
109 | break; | 99 | break; |
110 | case '\0': | 100 | case '\0': |
111 | fprintf(f, "\", "); | 101 | fprintf(f, "\\0"); |
112 | while (m && (m->offset <= (i + 1))) { | ||
113 | if (m->type == LABEL) { | ||
114 | assert(m->offset == (i+1)); | ||
115 | fprintf(f, "%s: ", m->ref); | ||
116 | } | ||
117 | m = m->next; | ||
118 | } | ||
119 | fprintf(f, "\""); | ||
120 | break; | 102 | break; |
121 | default: | 103 | default: |
122 | if (isprint((unsigned char)c)) | 104 | if (isprint((unsigned char)c)) |
123 | fprintf(f, "%c", c); | 105 | fprintf(f, "%c", c); |
124 | else | 106 | else |
125 | fprintf(f, "\\x%02hhx", c); | 107 | fprintf(f, "\\x%02"PRIx8, c); |
126 | } | 108 | } |
127 | } | 109 | } |
128 | fprintf(f, "\""); | 110 | fprintf(f, "\""); |
129 | |||
130 | /* Wrap up any labels at the end of the value */ | ||
131 | for_each_marker_of_type(m, LABEL) { | ||
132 | assert (m->offset == val.len); | ||
133 | fprintf(f, " %s:", m->ref); | ||
134 | } | ||
135 | } | 111 | } |
136 | 112 | ||
137 | static void write_propval_cells(FILE *f, struct data val) | 113 | static void write_propval_int(FILE *f, const char *p, size_t len, size_t width) |
138 | { | 114 | { |
139 | void *propend = val.val + val.len; | 115 | const char *end = p + len; |
140 | fdt32_t *cp = (fdt32_t *)val.val; | 116 | assert(len % width == 0); |
141 | struct marker *m = val.markers; | ||
142 | |||
143 | fprintf(f, "<"); | ||
144 | for (;;) { | ||
145 | while (m && (m->offset <= ((char *)cp - val.val))) { | ||
146 | if (m->type == LABEL) { | ||
147 | assert(m->offset == ((char *)cp - val.val)); | ||
148 | fprintf(f, "%s: ", m->ref); | ||
149 | } | ||
150 | m = m->next; | ||
151 | } | ||
152 | 117 | ||
153 | fprintf(f, "0x%x", fdt32_to_cpu(*cp++)); | 118 | for (; p < end; p += width) { |
154 | if ((void *)cp >= propend) | 119 | switch (width) { |
120 | case 1: | ||
121 | fprintf(f, " %02"PRIx8, *(const uint8_t*)p); | ||
122 | break; | ||
123 | case 2: | ||
124 | fprintf(f, " 0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p)); | ||
125 | break; | ||
126 | case 4: | ||
127 | fprintf(f, " 0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p)); | ||
128 | break; | ||
129 | case 8: | ||
130 | fprintf(f, " 0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p)); | ||
155 | break; | 131 | break; |
156 | fprintf(f, " "); | 132 | } |
157 | } | 133 | } |
134 | } | ||
158 | 135 | ||
159 | /* Wrap up any labels at the end of the value */ | 136 | static bool has_data_type_information(struct marker *m) |
160 | for_each_marker_of_type(m, LABEL) { | 137 | { |
161 | assert (m->offset == val.len); | 138 | return m->type >= TYPE_UINT8; |
162 | fprintf(f, " %s:", m->ref); | ||
163 | } | ||
164 | fprintf(f, ">"); | ||
165 | } | 139 | } |
166 | 140 | ||
167 | static void write_propval_bytes(FILE *f, struct data val) | 141 | static struct marker *next_type_marker(struct marker *m) |
168 | { | 142 | { |
169 | void *propend = val.val + val.len; | 143 | while (m && !has_data_type_information(m)) |
170 | const char *bp = val.val; | 144 | m = m->next; |
171 | struct marker *m = val.markers; | 145 | return m; |
172 | 146 | } | |
173 | fprintf(f, "["); | ||
174 | for (;;) { | ||
175 | while (m && (m->offset == (bp-val.val))) { | ||
176 | if (m->type == LABEL) | ||
177 | fprintf(f, "%s: ", m->ref); | ||
178 | m = m->next; | ||
179 | } | ||
180 | 147 | ||
181 | fprintf(f, "%02hhx", (unsigned char)(*bp++)); | 148 | size_t type_marker_length(struct marker *m) |
182 | if ((const void *)bp >= propend) | 149 | { |
183 | break; | 150 | struct marker *next = next_type_marker(m->next); |
184 | fprintf(f, " "); | ||
185 | } | ||
186 | 151 | ||
187 | /* Wrap up any labels at the end of the value */ | 152 | if (next) |
188 | for_each_marker_of_type(m, LABEL) { | 153 | return next->offset - m->offset; |
189 | assert (m->offset == val.len); | 154 | return 0; |
190 | fprintf(f, " %s:", m->ref); | ||
191 | } | ||
192 | fprintf(f, "]"); | ||
193 | } | 155 | } |
194 | 156 | ||
195 | static void write_propval(FILE *f, struct property *prop) | 157 | static const char *delim_start[] = { |
158 | [TYPE_UINT8] = "[", | ||
159 | [TYPE_UINT16] = "/bits/ 16 <", | ||
160 | [TYPE_UINT32] = "<", | ||
161 | [TYPE_UINT64] = "/bits/ 64 <", | ||
162 | [TYPE_STRING] = "", | ||
163 | }; | ||
164 | static const char *delim_end[] = { | ||
165 | [TYPE_UINT8] = " ]", | ||
166 | [TYPE_UINT16] = " >", | ||
167 | [TYPE_UINT32] = " >", | ||
168 | [TYPE_UINT64] = " >", | ||
169 | [TYPE_STRING] = "", | ||
170 | }; | ||
171 | |||
172 | static enum markertype guess_value_type(struct property *prop) | ||
196 | { | 173 | { |
197 | int len = prop->val.len; | 174 | int len = prop->val.len; |
198 | const char *p = prop->val.val; | 175 | const char *p = prop->val.val; |
@@ -201,11 +178,6 @@ static void write_propval(FILE *f, struct property *prop) | |||
201 | int nnotstringlbl = 0, nnotcelllbl = 0; | 178 | int nnotstringlbl = 0, nnotcelllbl = 0; |
202 | int i; | 179 | int i; |
203 | 180 | ||
204 | if (len == 0) { | ||
205 | fprintf(f, ";\n"); | ||
206 | return; | ||
207 | } | ||
208 | |||
209 | for (i = 0; i < len; i++) { | 181 | for (i = 0; i < len; i++) { |
210 | if (! isstring(p[i])) | 182 | if (! isstring(p[i])) |
211 | nnotstring++; | 183 | nnotstring++; |
@@ -220,17 +192,91 @@ static void write_propval(FILE *f, struct property *prop) | |||
220 | nnotcelllbl++; | 192 | nnotcelllbl++; |
221 | } | 193 | } |
222 | 194 | ||
223 | fprintf(f, " = "); | ||
224 | if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul)) | 195 | if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul)) |
225 | && (nnotstringlbl == 0)) { | 196 | && (nnotstringlbl == 0)) { |
226 | write_propval_string(f, prop->val); | 197 | return TYPE_STRING; |
227 | } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { | 198 | } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { |
228 | write_propval_cells(f, prop->val); | 199 | return TYPE_UINT32; |
229 | } else { | ||
230 | write_propval_bytes(f, prop->val); | ||
231 | } | 200 | } |
232 | 201 | ||
233 | fprintf(f, ";\n"); | 202 | return TYPE_UINT8; |
203 | } | ||
204 | |||
205 | static void write_propval(FILE *f, struct property *prop) | ||
206 | { | ||
207 | size_t len = prop->val.len; | ||
208 | struct marker *m = prop->val.markers; | ||
209 | struct marker dummy_marker; | ||
210 | enum markertype emit_type = TYPE_NONE; | ||
211 | |||
212 | if (len == 0) { | ||
213 | fprintf(f, ";\n"); | ||
214 | return; | ||
215 | } | ||
216 | |||
217 | fprintf(f, " = "); | ||
218 | |||
219 | if (!next_type_marker(m)) { | ||
220 | /* data type information missing, need to guess */ | ||
221 | dummy_marker.type = guess_value_type(prop); | ||
222 | dummy_marker.next = prop->val.markers; | ||
223 | dummy_marker.offset = 0; | ||
224 | dummy_marker.ref = NULL; | ||
225 | m = &dummy_marker; | ||
226 | } | ||
227 | |||
228 | struct marker *m_label = prop->val.markers; | ||
229 | for_each_marker(m) { | ||
230 | size_t chunk_len; | ||
231 | const char *p = &prop->val.val[m->offset]; | ||
232 | |||
233 | if (!has_data_type_information(m)) | ||
234 | continue; | ||
235 | |||
236 | chunk_len = type_marker_length(m); | ||
237 | if (!chunk_len) | ||
238 | chunk_len = len - m->offset; | ||
239 | |||
240 | if (emit_type != TYPE_NONE) | ||
241 | fprintf(f, "%s, ", delim_end[emit_type]); | ||
242 | emit_type = m->type; | ||
243 | |||
244 | for_each_marker_of_type(m_label, LABEL) { | ||
245 | if (m_label->offset > m->offset) | ||
246 | break; | ||
247 | fprintf(f, "%s: ", m_label->ref); | ||
248 | } | ||
249 | |||
250 | fprintf(f, "%s", delim_start[emit_type]); | ||
251 | |||
252 | if (chunk_len <= 0) | ||
253 | continue; | ||
254 | |||
255 | switch(emit_type) { | ||
256 | case TYPE_UINT16: | ||
257 | write_propval_int(f, p, chunk_len, 2); | ||
258 | break; | ||
259 | case TYPE_UINT32: | ||
260 | write_propval_int(f, p, chunk_len, 4); | ||
261 | break; | ||
262 | case TYPE_UINT64: | ||
263 | write_propval_int(f, p, chunk_len, 8); | ||
264 | break; | ||
265 | case TYPE_STRING: | ||
266 | write_propval_string(f, p, chunk_len); | ||
267 | break; | ||
268 | default: | ||
269 | write_propval_int(f, p, chunk_len, 1); | ||
270 | } | ||
271 | } | ||
272 | |||
273 | /* Wrap up any labels at the end of the value */ | ||
274 | for_each_marker_of_type(m_label, LABEL) { | ||
275 | assert (m_label->offset == len); | ||
276 | fprintf(f, " %s:", m_label->ref); | ||
277 | } | ||
278 | |||
279 | fprintf(f, "%s;\n", delim_end[emit_type] ? : ""); | ||
234 | } | 280 | } |
235 | 281 | ||
236 | static void write_tree_source_node(FILE *f, struct node *tree, int level) | 282 | static void write_tree_source_node(FILE *f, struct node *tree, int level) |
@@ -281,4 +327,3 @@ void dt_to_source(FILE *f, struct dt_info *dti) | |||
281 | 327 | ||
282 | write_tree_source_node(f, dti->dt, 0); | 328 | write_tree_source_node(f, dti->dt, 0); |
283 | } | 329 | } |
284 | |||