blob: a5035beca6e36c0270b2b6efe9bde9bff591ed49 [file] [log] [blame]
Simon Glass069fb772014-02-26 15:59:17 -07001Driver Model
2============
3
4This README contains high-level information about driver model, a unified
5way of declaring and accessing drivers in U-Boot. The original work was done
6by:
7
8 Marek Vasut <marex@denx.de>
9 Pavel Herrmann <morpheus.ibis@gmail.com>
10 Viktor Křivák <viktor.krivak@gmail.com>
11 Tomas Hlavacek <tmshlvck@gmail.com>
12
13This has been both simplified and extended into the current implementation
14by:
15
16 Simon Glass <sjg@chromium.org>
17
18
19Terminology
20-----------
21
22Uclass - a group of devices which operate in the same way. A uclass provides
Chris Packhamf44e5b42014-06-07 10:35:55 +120023 a way of accessing individual devices within the group, but always
Simon Glass069fb772014-02-26 15:59:17 -070024 using the same interface. For example a GPIO uclass provides
25 operations for get/set value. An I2C uclass may have 10 I2C ports,
26 4 with one driver, and 6 with another.
27
28Driver - some code which talks to a peripheral and presents a higher-level
29 interface to it.
30
31Device - an instance of a driver, tied to a particular port or peripheral.
32
33
34How to try it
35-------------
36
37Build U-Boot sandbox and run it:
38
39 make sandbox_config
40 make
41 ./u-boot
42
43 (type 'reset' to exit U-Boot)
44
45
46There is a uclass called 'demo'. This uclass handles
47saying hello, and reporting its status. There are two drivers in this
48uclass:
49
50 - simple: Just prints a message for hello, doesn't implement status
51 - shape: Prints shapes and reports number of characters printed as status
52
53The demo class is pretty simple, but not trivial. The intention is that it
54can be used for testing, so it will implement all driver model features and
55provide good code coverage of them. It does have multiple drivers, it
56handles parameter data and platdata (data which tells the driver how
57to operate on a particular platform) and it uses private driver data.
58
59To try it, see the example session below:
60
61=>demo hello 1
62Hello '@' from 07981110: red 4
63=>demo status 2
64Status: 0
65=>demo hello 2
66g
67r@
68e@@
69e@@@
70n@@@@
71g@@@@@
72=>demo status 2
73Status: 21
74=>demo hello 4 ^
75 y^^^
76 e^^^^^
77l^^^^^^^
78l^^^^^^^
79 o^^^^^
80 w^^^
81=>demo status 4
82Status: 36
83=>
84
85
86Running the tests
87-----------------
88
89The intent with driver model is that the core portion has 100% test coverage
90in sandbox, and every uclass has its own test. As a move towards this, tests
91are provided in test/dm. To run them, try:
92
93 ./test/dm/test-dm.sh
94
95You should see something like this:
96
97 <...U-Boot banner...>
98 Running 12 driver model tests
99 Test: dm_test_autobind
100 Test: dm_test_autoprobe
101 Test: dm_test_children
102 Test: dm_test_fdt
103 Test: dm_test_gpio
104 sandbox_gpio: sb_gpio_get_value: error: offset 4 not reserved
105 Test: dm_test_leak
106 Warning: Please add '#define DEBUG' to the top of common/dlmalloc.c
107 Warning: Please add '#define DEBUG' to the top of common/dlmalloc.c
108 Test: dm_test_lifecycle
109 Test: dm_test_operations
110 Test: dm_test_ordering
111 Test: dm_test_platdata
112 Test: dm_test_remove
113 Test: dm_test_uclass
114 Failures: 0
115
116(You can add '#define DEBUG' as suggested to check for memory leaks)
117
118
119What is going on?
120-----------------
121
122Let's start at the top. The demo command is in common/cmd_demo.c. It does
Chris Packhamf44e5b42014-06-07 10:35:55 +1200123the usual command processing and then:
Simon Glass069fb772014-02-26 15:59:17 -0700124
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200125 struct udevice *demo_dev;
Simon Glass069fb772014-02-26 15:59:17 -0700126
127 ret = uclass_get_device(UCLASS_DEMO, devnum, &demo_dev);
128
129UCLASS_DEMO means the class of devices which implement 'demo'. Other
130classes might be MMC, or GPIO, hashing or serial. The idea is that the
131devices in the class all share a particular way of working. The class
132presents a unified view of all these devices to U-Boot.
133
134This function looks up a device for the demo uclass. Given a device
135number we can find the device because all devices have registered with
136the UCLASS_DEMO uclass.
137
138The device is automatically activated ready for use by uclass_get_device().
139
140Now that we have the device we can do things like:
141
142 return demo_hello(demo_dev, ch);
143
144This function is in the demo uclass. It takes care of calling the 'hello'
145method of the relevant driver. Bearing in mind that there are two drivers,
146this particular device may use one or other of them.
147
148The code for demo_hello() is in drivers/demo/demo-uclass.c:
149
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200150int demo_hello(struct udevice *dev, int ch)
Simon Glass069fb772014-02-26 15:59:17 -0700151{
152 const struct demo_ops *ops = device_get_ops(dev);
153
154 if (!ops->hello)
155 return -ENOSYS;
156
157 return ops->hello(dev, ch);
158}
159
160As you can see it just calls the relevant driver method. One of these is
161in drivers/demo/demo-simple.c:
162
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200163static int simple_hello(struct udevice *dev, int ch)
Simon Glass069fb772014-02-26 15:59:17 -0700164{
165 const struct dm_demo_pdata *pdata = dev_get_platdata(dev);
166
167 printf("Hello from %08x: %s %d\n", map_to_sysmem(dev),
168 pdata->colour, pdata->sides);
169
170 return 0;
171}
172
173
174So that is a trip from top (command execution) to bottom (driver action)
175but it leaves a lot of topics to address.
176
177
178Declaring Drivers
179-----------------
180
181A driver declaration looks something like this (see
182drivers/demo/demo-shape.c):
183
184static const struct demo_ops shape_ops = {
185 .hello = shape_hello,
186 .status = shape_status,
187};
188
189U_BOOT_DRIVER(demo_shape_drv) = {
190 .name = "demo_shape_drv",
191 .id = UCLASS_DEMO,
192 .ops = &shape_ops,
193 .priv_data_size = sizeof(struct shape_data),
194};
195
196
197This driver has two methods (hello and status) and requires a bit of
198private data (accessible through dev_get_priv(dev) once the driver has
199been probed). It is a member of UCLASS_DEMO so will register itself
200there.
201
202In U_BOOT_DRIVER it is also possible to specify special methods for bind
203and unbind, and these are called at appropriate times. For many drivers
204it is hoped that only 'probe' and 'remove' will be needed.
205
206The U_BOOT_DRIVER macro creates a data structure accessible from C,
207so driver model can find the drivers that are available.
208
209The methods a device can provide are documented in the device.h header.
210Briefly, they are:
211
212 bind - make the driver model aware of a device (bind it to its driver)
213 unbind - make the driver model forget the device
214 ofdata_to_platdata - convert device tree data to platdata - see later
215 probe - make a device ready for use
216 remove - remove a device so it cannot be used until probed again
217
218The sequence to get a device to work is bind, ofdata_to_platdata (if using
219device tree) and probe.
220
221
222Platform Data
223-------------
224
225Where does the platform data come from? See demo-pdata.c which
226sets up a table of driver names and their associated platform data.
227The data can be interpreted by the drivers however they like - it is
228basically a communication scheme between the board-specific code and
229the generic drivers, which are intended to work on any board.
230
Chris Packhamf44e5b42014-06-07 10:35:55 +1200231Drivers can access their data via dev->info->platdata. Here is
Simon Glass069fb772014-02-26 15:59:17 -0700232the declaration for the platform data, which would normally appear
233in the board file.
234
235 static const struct dm_demo_cdata red_square = {
236 .colour = "red",
237 .sides = 4.
238 };
239 static const struct driver_info info[] = {
240 {
241 .name = "demo_shape_drv",
242 .platdata = &red_square,
243 },
244 };
245
246 demo1 = driver_bind(root, &info[0]);
247
248
249Device Tree
250-----------
251
252While platdata is useful, a more flexible way of providing device data is
253by using device tree. With device tree we replace the above code with the
254following device tree fragment:
255
256 red-square {
257 compatible = "demo-shape";
258 colour = "red";
259 sides = <4>;
260 };
261
262
263The easiest way to make this work it to add a few members to the driver:
264
265 .platdata_auto_alloc_size = sizeof(struct dm_test_pdata),
266 .ofdata_to_platdata = testfdt_ofdata_to_platdata,
267 .probe = testfdt_drv_probe,
268
269The 'auto_alloc' feature allowed space for the platdata to be allocated
270and zeroed before the driver's ofdata_to_platdata method is called. This
271method reads the information out of the device tree and puts it in
272dev->platdata. Then the probe method is called to set up the device.
273
274Note that both methods are optional. If you provide an ofdata_to_platdata
Chris Packhamf44e5b42014-06-07 10:35:55 +1200275method then it will be called first (after bind). If you provide a probe
Simon Glass069fb772014-02-26 15:59:17 -0700276method it will be called next.
277
278If you don't want to have the platdata automatically allocated then you
279can leave out platdata_auto_alloc_size. In this case you can use malloc
280in your ofdata_to_platdata (or probe) method to allocate the required memory,
281and you should free it in the remove method.
282
283
284Declaring Uclasses
285------------------
286
287The demo uclass is declared like this:
288
289U_BOOT_CLASS(demo) = {
290 .id = UCLASS_DEMO,
291};
292
293It is also possible to specify special methods for probe, etc. The uclass
294numbering comes from include/dm/uclass.h. To add a new uclass, add to the
295end of the enum there, then declare your uclass as above.
296
297
298Data Structures
299---------------
300
301Driver model uses a doubly-linked list as the basic data structure. Some
302nodes have several lists running through them. Creating a more efficient
303data structure might be worthwhile in some rare cases, once we understand
304what the bottlenecks are.
305
306
307Changes since v1
308----------------
309
310For the record, this implementation uses a very similar approach to the
311original patches, but makes at least the following changes:
312
Chris Packhamf44e5b42014-06-07 10:35:55 +1200313- Tried to aggressively remove boilerplate, so that for most drivers there
Simon Glass069fb772014-02-26 15:59:17 -0700314is little or no 'driver model' code to write.
315- Moved some data from code into data structure - e.g. store a pointer to
316the driver operations structure in the driver, rather than passing it
317to the driver bind function.
318- Rename some structures to make them more similar to Linux (struct device
319instead of struct instance, struct platdata, etc.)
320- Change the name 'core' to 'uclass', meaning U-Boot class. It seems that
321this concept relates to a class of drivers (or a subsystem). We shouldn't
322use 'class' since it is a C++ reserved word, so U-Boot class (uclass) seems
323better than 'core'.
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200324- Remove 'struct driver_instance' and just use a single 'struct udevice'.
Simon Glass069fb772014-02-26 15:59:17 -0700325This removes a level of indirection that doesn't seem necessary.
326- Built in device tree support, to avoid the need for platdata
327- Removed the concept of driver relocation, and just make it possible for
328the new driver (created after relocation) to access the old driver data.
329I feel that relocation is a very special case and will only apply to a few
330drivers, many of which can/will just re-init anyway. So the overhead of
331dealing with this might not be worth it.
332- Implemented a GPIO system, trying to keep it simple
333
334
335Things to punt for later
336------------------------
337
338- SPL support - this will have to be present before many drivers can be
339converted, but it seems like we can add it once we are happy with the
340core implementation.
341- Pre-relocation support - similar story
342
343That is not to say that no thinking has gone into these - in fact there
344is quite a lot there. However, getting these right is non-trivial and
345there is a high cost associated with going down the wrong path.
346
347For SPL, it may be possible to fit in a simplified driver model with only
348bind and probe methods, to reduce size.
349
350For pre-relocation we can simply call the driver model init function. Then
351post relocation we throw that away and re-init driver model again. For drivers
352which require some sort of continuity between pre- and post-relocation
353devices, we can provide access to the pre-relocation device pointers.
354
355Uclasses are statically numbered at compile time. It would be possible to
356change this to dynamic numbering, but then we would require some sort of
357lookup service, perhaps searching by name. This is slightly less efficient
358so has been left out for now. One small advantage of dynamic numbering might
359be fewer merge conflicts in uclass-id.h.
360
361
362Simon Glass
363sjg@chromium.org
364April 2013
365Updated 7-May-13
366Updated 14-Jun-13
367Updated 18-Oct-13
368Updated 5-Nov-13