Commit 1269625177f120d659f66b18de4b532b16c44561
1 parent
b979d3d4c5
Exists in
v2017.01-smarct4x
and in
25 other branches
dm: Update the of-platdata README for the new features
Revise the content based on the v2 additions. This is kept as a separate patch to avoid confusing those who have already reviewed the v1 series. Signed-off-by: Simon Glass <sjg@chromium.org> Suggested-by: Tom Rini <trini@konsulko.com>
Showing 1 changed file with 76 additions and 34 deletions Side-by-side Diff
doc/driver-model/of-plat.txt
... | ... | @@ -19,24 +19,28 @@ |
19 | 19 | case the overhead of device tree access may be too great. |
20 | 20 | |
21 | 21 | It is possible to create platform data manually by defining C structures |
22 | -for it, and referencing that data in a U_BOOT_DEVICE() declaration. This | |
23 | -bypasses the use of device tree completely, but is an available option for | |
24 | -SPL. | |
22 | +for it, and reference that data in a U_BOOT_DEVICE() declaration. This | |
23 | +bypasses the use of device tree completely, effectively creating a parallel | |
24 | +configuration mechanism. But it is an available option for SPL. | |
25 | 25 | |
26 | -As an alternative, a new 'of-platdata' feature is provided. This converts | |
26 | +As an alternative, a new 'of-platdata' feature is provided. This converts the | |
27 | 27 | device tree contents into C code which can be compiled into the SPL binary. |
28 | 28 | This saves the 3KB of code overhead and perhaps a few hundred more bytes due |
29 | 29 | to more efficient storage of the data. |
30 | 30 | |
31 | +Note: Quite a bit of thought has gone into the design of this feature. | |
32 | +However it still has many rough edges and comments and suggestions are | |
33 | +strongly encouraged! Quite possibly there is a much better approach. | |
31 | 34 | |
35 | + | |
32 | 36 | Caveats |
33 | 37 | ------- |
34 | 38 | |
35 | 39 | There are many problems with this features. It should only be used when |
36 | -stricly necessary. Notable problems include: | |
40 | +strictly necessary. Notable problems include: | |
37 | 41 | |
38 | - - Device tree does not describe data types but the C code must define a | |
39 | - type for each property. Thesee are guessed using heuristics which | |
42 | + - Device tree does not describe data types. But the C code must define a | |
43 | + type for each property. These are guessed using heuristics which | |
40 | 44 | are wrong in several fairly common cases. For example an 8-byte value |
41 | 45 | is considered to be a 2-item integer array, and is byte-swapped. A |
42 | 46 | boolean value that is not present means 'false', but cannot be |
43 | 47 | |
... | ... | @@ -45,14 +49,15 @@ |
45 | 49 | |
46 | 50 | - Naming of nodes and properties is automatic. This means that they follow |
47 | 51 | the naming in the device tree, which may result in C identifiers that |
48 | - look a bit strange | |
52 | + look a bit strange. | |
49 | 53 | |
50 | 54 | - It is not possible to find a value given a property name. Code must use |
51 | 55 | the associated C member variable directly in the code. This makes |
52 | 56 | the code less robust in the face of device-tree changes. It also |
53 | 57 | makes it very unlikely that your driver code will be useful for more |
54 | 58 | than one SoC. Even if the code is common, each SoC will end up with |
55 | - a different C struct and format for the platform data. | |
59 | + a different C struct name, and a likely a different format for the | |
60 | + platform data. | |
56 | 61 | |
57 | 62 | - The platform data is provided to drivers as a C structure. The driver |
58 | 63 | must use the same structure to access the data. Since a driver |
... | ... | @@ -112,7 +117,6 @@ |
112 | 117 | fdt32_t interrupts[3]; |
113 | 118 | fdt32_t num_slots; |
114 | 119 | fdt32_t reg[2]; |
115 | - bool u_boot_dm_pre_reloc; | |
116 | 120 | fdt32_t vmmc_supply; |
117 | 121 | }; |
118 | 122 | |
... | ... | @@ -125,7 +129,10 @@ |
125 | 129 | .clock_freq_min_max = {0x61a80, 0x8f0d180}, |
126 | 130 | .vmmc_supply = 0xb, |
127 | 131 | .num_slots = 0x1, |
128 | - .clocks = {{&dtv_clock_controller_at_ff760000, 456}, {&dtv_clock_controller_at_ff760000, 68}, {&dtv_clock_controller_at_ff760000, 114}, {&dtv_clock_controller_at_ff760000, 118}}, | |
132 | + .clocks = {{&dtv_clock_controller_at_ff760000, 456}, | |
133 | + {&dtv_clock_controller_at_ff760000, 68}, | |
134 | + {&dtv_clock_controller_at_ff760000, 114}, | |
135 | + {&dtv_clock_controller_at_ff760000, 118}}, | |
129 | 136 | .cap_mmc_highspeed = true, |
130 | 137 | .disable_wp = true, |
131 | 138 | .bus_width = 0x4, |
... | ... | @@ -136,6 +143,7 @@ |
136 | 143 | U_BOOT_DEVICE(dwmmc_at_ff0c0000) = { |
137 | 144 | .name = "rockchip_rk3288_dw_mshc", |
138 | 145 | .platdata = &dtv_dwmmc_at_ff0c0000, |
146 | + .platdata_size = sizeof(dtv_dwmmc_at_ff0c0000), | |
139 | 147 | }; |
140 | 148 | |
141 | 149 | The device is then instantiated at run-time and the platform data can be |
142 | 150 | |
... | ... | @@ -149,15 +157,31 @@ |
149 | 157 | therefore do nothing in such a driver. |
150 | 158 | |
151 | 159 | |
160 | +Converting of-platdata to a useful form | |
161 | +--------------------------------------- | |
162 | + | |
163 | +Of course it would be possible use the of-platdata directly in your driver | |
164 | +whenever configuration information is required. However this meands that the | |
165 | +driver will not be able to support device tree, since the of-platdata | |
166 | +structure is not available when device tree is used. It would make no sense | |
167 | +to use this structure if device tree were available, since the structure has | |
168 | +all the limitations metioned in caveats above. | |
169 | + | |
170 | +Therefore it is recommended that the of-platdata structure should be used | |
171 | +only in the probe() method of your driver. It cannot be used in the | |
172 | +ofdata_to_platdata() method since this is not called when platform data is | |
173 | +already present. | |
174 | + | |
175 | + | |
152 | 176 | How to structure your driver |
153 | 177 | ---------------------------- |
154 | 178 | |
155 | 179 | Drivers should always support device tree as an option. The of-platdata |
156 | 180 | feature is intended as a add-on to existing drivers. |
157 | 181 | |
158 | -Your driver should directly access the platdata struct in its probe() | |
159 | -method. The existing device tree decoding logic should be kept in the | |
160 | -ofdata_to_platdata() and wrapped with #ifdef. | |
182 | +Your driver should convert the platdata struct in its probe() method. The | |
183 | +existing device tree decoding logic should be kept in the | |
184 | +ofdata_to_platdata() method and wrapped with #if. | |
161 | 185 | |
162 | 186 | For example: |
163 | 187 | |
164 | 188 | |
... | ... | @@ -165,13 +189,12 @@ |
165 | 189 | |
166 | 190 | struct mmc_platdata { |
167 | 191 | #if CONFIG_IS_ENABLED(SPL_OF_PLATDATA) |
168 | - /* Put this first */ | |
192 | + /* Put this first since driver model will copy the data here */ | |
169 | 193 | struct dtd_mmc dtplat; |
170 | 194 | #endif |
171 | 195 | /* |
172 | 196 | * Other fields can go here, to be filled in by decoding from |
173 | - * the device tree. They will point to random memory in the | |
174 | - * of-plat case. | |
197 | + * the device tree (or the C structures when of-platdata is used). | |
175 | 198 | */ |
176 | 199 | int fifo_depth; |
177 | 200 | }; |
... | ... | @@ -179,6 +202,7 @@ |
179 | 202 | static int mmc_ofdata_to_platdata(struct udevice *dev) |
180 | 203 | { |
181 | 204 | #if !CONFIG_IS_ENABLED(SPL_OF_PLATDATA) |
205 | + /* Decode the device tree data */ | |
182 | 206 | struct mmc_platdata *plat = dev_get_platdata(dev); |
183 | 207 | const void *blob = gd->fdt_blob; |
184 | 208 | int node = dev->of_offset; |
185 | 209 | |
186 | 210 | |
187 | 211 | |
... | ... | @@ -192,15 +216,15 @@ |
192 | 216 | static int mmc_probe(struct udevice *dev) |
193 | 217 | { |
194 | 218 | struct mmc_platdata *plat = dev_get_platdata(dev); |
219 | + | |
195 | 220 | #if CONFIG_IS_ENABLED(SPL_OF_PLATDATA) |
221 | + /* Decode the of-platdata from the C structures */ | |
196 | 222 | struct dtd_mmc *dtplat = &plat->dtplat; |
197 | 223 | |
198 | - /* Set up the device from the dtplat data */ | |
199 | - writel(dtplat->fifo_depth, ...) | |
200 | - #else | |
224 | + plat->fifo_depth = dtplat->fifo_depth; | |
225 | + #endif | |
201 | 226 | /* Set up the device from the plat data */ |
202 | 227 | writel(plat->fifo_depth, ...) |
203 | - #endif | |
204 | 228 | } |
205 | 229 | |
206 | 230 | static const struct udevice_id mmc_ids[] = { |
207 | 231 | |
208 | 232 | |
209 | 233 | |
210 | 234 | |
... | ... | @@ -220,23 +244,35 @@ |
220 | 244 | |
221 | 245 | |
222 | 246 | In the case where SPL_OF_PLATDATA is enabled, platdata_auto_alloc_size is |
223 | -ignored, and the platform data points to the C structure data. In the case | |
224 | -where device tree is used, the platform data is allocated, and starts | |
225 | -zeroed. In this case the ofdata_to_platdata() method should set up the | |
226 | -platform data. | |
247 | +still used to allocate space for the platform data. This is different from | |
248 | +the normal behaviour and is triggered by the use of of-platdata (strictly | |
249 | +speaking it is a non-zero platdata_size which triggers this). | |
227 | 250 | |
228 | -SPL must use either of-platdata or device tree. Drivers cannot use both. | |
229 | -The device tree becomes in accessible when CONFIG_SPL_OF_PLATDATA is enabled, | |
230 | -since the device-tree access code is not compiled in. | |
251 | +The of-platdata struct contents is copied from the C structure data to the | |
252 | +start of the newly allocated area. In the case where device tree is used, | |
253 | +the platform data is allocated, and starts zeroed. In this case the | |
254 | +ofdata_to_platdata() method should still set up the platform data (and the | |
255 | +of-platdata struct will not be present). | |
231 | 256 | |
257 | +SPL must use either of-platdata or device tree. Drivers cannot use both at | |
258 | +the same time, but they must support device tree. Supporting of-platdata is | |
259 | +optional. | |
232 | 260 | |
261 | +The device tree becomes in accessible when CONFIG_SPL_OF_PLATDATA is enabled, | |
262 | +since the device-tree access code is not compiled in. A corollary is that | |
263 | +a board can only move to using of-platdata if all the drivers it uses support | |
264 | +it. There would be little point in having some drivers require the device | |
265 | +tree data, since then libfdt would still be needed for those drivers and | |
266 | +there would be no code-size benefit. | |
267 | + | |
233 | 268 | Internals |
234 | 269 | --------- |
235 | 270 | |
236 | 271 | The dt-structs.h file includes the generated file |
237 | 272 | (include/generated//dt-structs.h) if CONFIG_SPL_OF_PLATDATA is enabled. |
238 | 273 | Otherwise (such as in U-Boot proper) these structs are not available. This |
239 | -prevents them being used inadvertently. | |
274 | +prevents them being used inadvertently. All usage must be bracketed with | |
275 | +#if CONFIG_IS_ENABLED(SPL_OF_PLATDATA). | |
240 | 276 | |
241 | 277 | The dt-platdata.c file contains the device declarations and is is built in |
242 | 278 | spl/dt-platdata.c. |
243 | 279 | |
244 | 280 | |
245 | 281 | |
246 | 282 | |
247 | 283 | |
248 | 284 | |
... | ... | @@ -249,21 +285,27 @@ |
249 | 285 | The beginnings of a libfdt Python module are provided. So far this only |
250 | 286 | implements a subset of the features. |
251 | 287 | |
252 | -The 'swig' tool is needed to build the libfdt Python module. | |
288 | +The 'swig' tool is needed to build the libfdt Python module. If this is not | |
289 | +found then the Python model is not used and a fallback is used instead, which | |
290 | +makes use of fdtget. | |
253 | 291 | |
254 | 292 | |
293 | +Credits | |
294 | +------- | |
295 | + | |
296 | +This is an implementation of an idea by Tom Rini <trini@konsulko.com>. | |
297 | + | |
298 | + | |
255 | 299 | Future work |
256 | 300 | ----------- |
257 | -- Add unit tests | |
258 | -- Add a sandbox_spl functional test | |
259 | 301 | - Consider programmatically reading binding files instead of device tree |
260 | 302 | contents |
261 | -- Drop the device tree data from the SPL image | |
262 | 303 | - Complete the phandle feature |
263 | -- Get this running on a Rockchip board | |
264 | 304 | - Move to using a full Python libfdt module |
265 | 305 | |
266 | 306 | -- |
267 | 307 | Simon Glass <sjg@chromium.org> |
308 | +Google, Inc | |
268 | 309 | 6/6/16 |
310 | +Updated Independence Day 2016 |