Commit 1269625177f120d659f66b18de4b532b16c44561

Authored by Simon Glass
1 parent b979d3d4c5

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