Marek Vasut | 909bbcc | 2012-08-08 01:42:17 +0000 | [diff] [blame] | 1 | The U-Boot Driver Model Project |
| 2 | =============================== |
| 3 | Design document |
| 4 | =============== |
| 5 | Marek Vasut <marek.vasut@gmail.com> |
| 6 | Pavel Herrmann <morpheus.ibis@gmail.com> |
| 7 | 2012-05-17 |
| 8 | |
| 9 | I) The modular concept |
| 10 | ---------------------- |
| 11 | |
| 12 | The driver core design is done with modularity in mind. The long-term plan is to |
| 13 | extend this modularity to allow loading not only drivers, but various other |
| 14 | objects into U-Boot at runtime -- like commands, support for other boards etc. |
| 15 | |
| 16 | II) Driver core initialization stages |
| 17 | ------------------------------------- |
| 18 | |
| 19 | The drivers have to be initialized in two stages, since the U-Boot bootloader |
| 20 | runs in two stages itself. The first stage is the one which is executed before |
| 21 | the bootloader itself is relocated. The second stage then happens after |
| 22 | relocation. |
| 23 | |
| 24 | 1) First stage |
| 25 | -------------- |
| 26 | |
| 27 | The first stage runs after the bootloader did very basic hardware init. This |
| 28 | means the stack pointer was configured, caches disabled and that's about it. |
| 29 | The problem with this part is the memory management isn't running at all. To |
| 30 | make things even worse, at this point, the RAM is still likely uninitialized |
| 31 | and therefore unavailable. |
| 32 | |
| 33 | 2) Second stage |
| 34 | --------------- |
| 35 | |
| 36 | At this stage, the bootloader has initialized RAM and is running from it's |
| 37 | final location. Dynamic memory allocations are working at this point. Most of |
| 38 | the driver initialization is executed here. |
| 39 | |
| 40 | III) The drivers |
| 41 | ---------------- |
| 42 | |
| 43 | 1) The structure of a driver |
| 44 | ---------------------------- |
| 45 | |
| 46 | The driver will contain a structure located in a separate section, which |
| 47 | will allow linker to create a list of compiled-in drivers at compile time. |
| 48 | Let's call this list "driver_list". |
| 49 | |
| 50 | struct driver __attribute__((section(driver_list))) { |
| 51 | /* The name of the driver */ |
| 52 | char name[STATIC_CONFIG_DRIVER_NAME_LENGTH]; |
| 53 | |
| 54 | /* |
| 55 | * This function should connect this driver with cores it depends on and |
| 56 | * with other drivers, likely bus drivers |
| 57 | */ |
| 58 | int (*bind)(struct instance *i); |
| 59 | |
| 60 | /* This function actually initializes the hardware. */ |
| 61 | int (*probe)(struct instance *i); |
| 62 | |
| 63 | /* |
| 64 | * The function of the driver called when U-Boot finished relocation. |
| 65 | * This is particularly important to eg. move pointers to DMA buffers |
| 66 | * and such from the location before relocation to their final location. |
| 67 | */ |
| 68 | int (*reloc)(struct instance *i); |
| 69 | |
| 70 | /* |
| 71 | * This is called when the driver is shuting down, to deinitialize the |
| 72 | * hardware. |
| 73 | */ |
| 74 | int (*remove)(struct instance *i); |
| 75 | |
| 76 | /* This is called to remove the driver from the driver tree */ |
| 77 | int (*unbind)(struct instance *i); |
| 78 | |
| 79 | /* This is a list of cores this driver depends on */ |
| 80 | struct driver *cores[]; |
| 81 | }; |
| 82 | |
| 83 | The cores[] array in here is very important. It allows u-boot to figure out, |
| 84 | in compile-time, which possible cores can be activated at runtime. Therefore |
| 85 | if there are cores that won't be ever activated, GCC LTO might remove them |
| 86 | from the final binary. Actually, this information might be used to drive build |
| 87 | of the cores. |
| 88 | |
| 89 | FIXME: Should *cores[] be really struct driver, pointing to drivers that |
Wolfgang Denk | ec7fbf5 | 2013-10-04 17:43:24 +0200 | [diff] [blame] | 90 | represent the cores? Shouldn't it be core instance pointer? |
Marek Vasut | 909bbcc | 2012-08-08 01:42:17 +0000 | [diff] [blame] | 91 | |
| 92 | 2) Instantiation of a driver |
| 93 | ---------------------------- |
| 94 | |
| 95 | The driver is instantiated by calling: |
| 96 | |
| 97 | driver_bind(struct instance *bus, const struct driver_info *di) |
| 98 | |
| 99 | The "struct instance *bus" is a pointer to a bus with which this driver should |
| 100 | be registered with. The "root" bus pointer is supplied to the board init |
| 101 | functions. |
| 102 | |
| 103 | FIXME: We need some functions that will return list of busses of certain type |
Wolfgang Denk | ec7fbf5 | 2013-10-04 17:43:24 +0200 | [diff] [blame] | 104 | registered with the system so the user can find proper instance even if |
Marek Vasut | 909bbcc | 2012-08-08 01:42:17 +0000 | [diff] [blame] | 105 | he has no bus pointer (this will come handy if the user isn't |
| 106 | registering the driver from board init function, but somewhere else). |
| 107 | |
| 108 | The "const struct driver_info *di" pointer points to a structure defining the |
| 109 | driver to be registered. The structure is defined as follows: |
| 110 | |
| 111 | struct driver_info { |
| 112 | char name[STATIC_CONFIG_DRIVER_NAME_LENGTH]; |
| 113 | void *platform_data; |
| 114 | } |
| 115 | |
| 116 | The instantiation of a driver by calling driver_bind() creates an instance |
| 117 | of the driver by allocating "struct driver_instance". Note that only struct |
| 118 | instance is passed to the driver. The wrapping struct driver_instance is there |
| 119 | for purposes of the driver core: |
| 120 | |
| 121 | struct driver_instance { |
| 122 | uint32_t flags; |
| 123 | struct instance i; |
| 124 | }; |
| 125 | |
| 126 | struct instance { |
| 127 | /* Pointer to a driver information passed by driver_register() */ |
| 128 | const struct driver_info *info; |
| 129 | /* Pointer to a bus this driver is bound with */ |
| 130 | struct instance *bus; |
| 131 | /* Pointer to this driver's own private data */ |
| 132 | void *private_data; |
| 133 | /* Pointer to the first block of successor nodes (optional) */ |
| 134 | struct successor_block *succ; |
| 135 | } |
| 136 | |
| 137 | The instantiation of a driver does not mean the hardware is initialized. The |
| 138 | driver_bind() call only creates the instance of the driver, fills in the "bus" |
| 139 | pointer and calls the drivers' .bind() function. The .bind() function of the |
| 140 | driver should hook the driver with the remaining cores and/or drivers it |
| 141 | depends on. |
| 142 | |
| 143 | It's important to note here, that in case the driver instance has multiple |
| 144 | parents, such parent can be connected with this instance by calling: |
| 145 | |
| 146 | driver_link(struct instance *parent, struct instance *dev); |
| 147 | |
| 148 | This will connect the other parent driver with the newly instantiated driver. |
| 149 | Note that this must be called after driver_bind() and before driver_acticate() |
| 150 | (driver_activate() will be explained below). To allow struct instance to have |
| 151 | multiple parent pointer, the struct instance *bus will utilize it's last bit |
| 152 | to indicate if this is a pointer to struct instance or to an array if |
| 153 | instances, struct successor block. The approach is similar as the approach to |
| 154 | *succ in struct instance, described in the following paragraph. |
| 155 | |
| 156 | The last pointer of the struct instance, the pointer to successor nodes, is |
| 157 | used only in case of a bus driver. Otherwise the pointer contains NULL value. |
| 158 | The last bit of this field indicates if this is a bus having a single child |
| 159 | node (so the last bit is 0) or if this bus has multiple child nodes (the last |
| 160 | bit is 1). In the former case, the driver core should clear the last bit and |
| 161 | this pointer points directly to the child node. In the later case of a bus |
| 162 | driver, the pointer points to an instance of structure: |
| 163 | |
| 164 | struct successor_block { |
| 165 | /* Array of pointers to instances of devices attached to this bus */ |
| 166 | struct instance *dev[BLOCKING_FACTOR]; |
| 167 | /* Pointer to next block of successors */ |
| 168 | struct successor_block *next; |
| 169 | } |
| 170 | |
| 171 | Some of the *dev[] array members might be NULL in case there are no more |
| 172 | devices attached. The *next is NULL in case the list of attached devices |
| 173 | doesn't continue anymore. The BLOCKING_FACTOR is used to allocate multiple |
| 174 | slots for successor devices at once to avoid fragmentation of memory. |
| 175 | |
| 176 | 3) The bind() function of a driver |
| 177 | ---------------------------------- |
| 178 | |
| 179 | The bind function of a driver connects the driver with various cores the |
| 180 | driver provides functions for. The driver model related part will look like |
| 181 | the following example for a bus driver: |
| 182 | |
| 183 | int driver_bind(struct instance *in) |
| 184 | { |
| 185 | ... |
Wolfgang Denk | ec7fbf5 | 2013-10-04 17:43:24 +0200 | [diff] [blame] | 186 | core_bind(&core_i2c_static_instance, in, i2c_bus_funcs); |
| 187 | ... |
Marek Vasut | 909bbcc | 2012-08-08 01:42:17 +0000 | [diff] [blame] | 188 | } |
| 189 | |
| 190 | FIXME: What if we need to run-time determine, depending on some hardware |
Wolfgang Denk | ec7fbf5 | 2013-10-04 17:43:24 +0200 | [diff] [blame] | 191 | register, what kind of i2c_bus_funcs to pass? |
Marek Vasut | 909bbcc | 2012-08-08 01:42:17 +0000 | [diff] [blame] | 192 | |
| 193 | This makes the i2c core aware of a new bus. The i2c_bus_funcs is a constant |
| 194 | structure of functions any i2c bus driver must provide to work. This will |
| 195 | allow the i2c command operate with the bus. The core_i2c_static_instance is |
| 196 | the pointer to the instance of a core this driver provides function to. |
| 197 | |
| 198 | FIXME: Maybe replace "core-i2c" with CORE_I2C global pointer to an instance of |
Wolfgang Denk | ec7fbf5 | 2013-10-04 17:43:24 +0200 | [diff] [blame] | 199 | the core? |
Marek Vasut | 909bbcc | 2012-08-08 01:42:17 +0000 | [diff] [blame] | 200 | |
| 201 | 4) The instantiation of a core driver |
| 202 | ------------------------------------- |
| 203 | |
| 204 | The core driver is special in the way that it's single-instance driver. It is |
| 205 | always present in the system, though it might not be activated. The fact that |
| 206 | it's single instance allows it to be instantiated at compile time. |
| 207 | |
| 208 | Therefore, all possible structures of this driver can be in read-only memory, |
| 209 | especially struct driver and struct driver_instance. But the successor list, |
| 210 | which needs special treatment. |
| 211 | |
| 212 | To solve the problem with a successor list and the core driver flags, a new |
| 213 | entry in struct gd (global data) will be introduced. This entry will point to |
| 214 | runtime allocated array of struct driver_instance. It will be possible to |
| 215 | allocate the exact amount of struct driver_instance necessary, as the number |
| 216 | of cores that might be activated will be known at compile time. The cores will |
| 217 | then behave like any usual driver. |
| 218 | |
| 219 | Pointers to the struct instance of cores can be computed at compile time, |
| 220 | therefore allowing the resulting u-boot binary to save some overhead. |
| 221 | |
| 222 | 5) The probe() function of a driver |
| 223 | ----------------------------------- |
| 224 | |
| 225 | The probe function of a driver allocates necessary resources and does required |
| 226 | initialization of the hardware itself. This is usually called only when the |
| 227 | driver is needed, as a part of the defered probe mechanism. |
| 228 | |
| 229 | The driver core should implement a function called |
| 230 | |
| 231 | int driver_activate(struct instance *in); |
| 232 | |
| 233 | which should call the .probe() function of the driver and then configure the |
| 234 | state of the driver instance to "ACTIVATED". This state of a driver instance |
| 235 | should be stored in a wrap-around structure for the structure instance, the |
| 236 | struct driver_instance. |
| 237 | |
| 238 | 6) The command side interface to a driver |
| 239 | ----------------------------------------- |
| 240 | |
| 241 | The U-Boot command shall communicate only with the specific driver core. The |
| 242 | driver core in turn exports necessary API towards the command. |
| 243 | |
| 244 | 7) Demonstration imaginary board |
| 245 | -------------------------------- |
| 246 | |
| 247 | Consider the following computer: |
| 248 | |
| 249 | * |
| 250 | | |
| 251 | +-- System power management logic |
| 252 | | |
| 253 | +-- CPU clock controlling logc |
| 254 | | |
| 255 | +-- NAND controller |
| 256 | | | |
| 257 | | +-- NAND flash chip |
| 258 | | |
| 259 | +-- 128MB of DDR DRAM |
| 260 | | |
| 261 | +-- I2C bus #0 |
| 262 | | | |
| 263 | | +-- RTC |
| 264 | | | |
| 265 | | +-- EEPROM #0 |
| 266 | | | |
| 267 | | +-- EEPROM #1 |
| 268 | | |
| 269 | +-- USB host-only IP core |
| 270 | | | |
| 271 | | +-- USB storage device |
| 272 | | |
| 273 | +-- USB OTG-capable IP core |
| 274 | | | |
| 275 | | +-- connection to the host PC |
| 276 | | |
| 277 | +-- GPIO |
| 278 | | | |
| 279 | | +-- User LED #0 |
| 280 | | | |
| 281 | | +-- User LED #1 |
| 282 | | |
| 283 | +-- UART0 |
| 284 | | |
| 285 | +-- UART1 |
| 286 | | |
| 287 | +-- Ethernet controller #0 |
| 288 | | |
| 289 | +-- Ethernet controller #1 |
| 290 | | |
| 291 | +-- Audio codec |
| 292 | | |
| 293 | +-- PCI bridge |
| 294 | | | |
| 295 | | +-- Ethernet controller #2 |
| 296 | | | |
| 297 | | +-- SPI host card |
| 298 | | | | |
| 299 | | | +-- Audio amplifier (must be operational before codec) |
| 300 | | | |
| 301 | | +-- GPIO host card |
| 302 | | | |
| 303 | | +-- User LED #2 |
| 304 | | |
| 305 | +-- LCD controller |
| 306 | | |
| 307 | +-- PWM controller (must be enabled after LCD controller) |
| 308 | | |
| 309 | +-- SPI host controller |
| 310 | | | |
| 311 | | +-- SD/MMC connected via SPI |
| 312 | | | |
| 313 | | +-- SPI flash |
| 314 | | |
| 315 | +-- CPLD/FPGA with stored configuration of the board |