summaryrefslogtreecommitdiff
path: root/doc/driver-model/UDM-design.txt
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2014-02-26 15:59:27 -0700
committerTom Rini <trini@ti.com>2014-03-04 12:15:30 -0500
commitf9aa6a1086f6b7da1814a2c95feefa91c9c4b593 (patch)
treeafc79b7da6aa52de764ed53bf6b4c3a63a03b0df /doc/driver-model/UDM-design.txt
parent95a260a98c010321cdc5f2acd1f4272b9c0a19dc (diff)
downloadu-boot-imx-f9aa6a1086f6b7da1814a2c95feefa91c9c4b593.zip
u-boot-imx-f9aa6a1086f6b7da1814a2c95feefa91c9c4b593.tar.gz
u-boot-imx-f9aa6a1086f6b7da1814a2c95feefa91c9c4b593.tar.bz2
dm: Remove old driver model documentation
This documentation pertains to the planned implementation of driver model in U-Boot for each subsystem, but it has not been superseded. It is probably better to have this documentation in the source code for each subsystem where possible, so that docbook will pick it up. Where this does not make sense, new documentation can be placed in some suitable file in doc/driver-model. Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'doc/driver-model/UDM-design.txt')
-rw-r--r--doc/driver-model/UDM-design.txt315
1 files changed, 0 insertions, 315 deletions
diff --git a/doc/driver-model/UDM-design.txt b/doc/driver-model/UDM-design.txt
deleted file mode 100644
index 9f03bba..0000000
--- a/doc/driver-model/UDM-design.txt
+++ /dev/null
@@ -1,315 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-Design document
-===============
-Marek Vasut <marek.vasut@gmail.com>
-Pavel Herrmann <morpheus.ibis@gmail.com>
-2012-05-17
-
-I) The modular concept
-----------------------
-
-The driver core design is done with modularity in mind. The long-term plan is to
-extend this modularity to allow loading not only drivers, but various other
-objects into U-Boot at runtime -- like commands, support for other boards etc.
-
-II) Driver core initialization stages
--------------------------------------
-
-The drivers have to be initialized in two stages, since the U-Boot bootloader
-runs in two stages itself. The first stage is the one which is executed before
-the bootloader itself is relocated. The second stage then happens after
-relocation.
-
- 1) First stage
- --------------
-
- The first stage runs after the bootloader did very basic hardware init. This
- means the stack pointer was configured, caches disabled and that's about it.
- The problem with this part is the memory management isn't running at all. To
- make things even worse, at this point, the RAM is still likely uninitialized
- and therefore unavailable.
-
- 2) Second stage
- ---------------
-
- At this stage, the bootloader has initialized RAM and is running from it's
- final location. Dynamic memory allocations are working at this point. Most of
- the driver initialization is executed here.
-
-III) The drivers
-----------------
-
- 1) The structure of a driver
- ----------------------------
-
- The driver will contain a structure located in a separate section, which
- will allow linker to create a list of compiled-in drivers at compile time.
- Let's call this list "driver_list".
-
- struct driver __attribute__((section(driver_list))) {
- /* The name of the driver */
- char name[STATIC_CONFIG_DRIVER_NAME_LENGTH];
-
- /*
- * This function should connect this driver with cores it depends on and
- * with other drivers, likely bus drivers
- */
- int (*bind)(struct instance *i);
-
- /* This function actually initializes the hardware. */
- int (*probe)(struct instance *i);
-
- /*
- * The function of the driver called when U-Boot finished relocation.
- * This is particularly important to eg. move pointers to DMA buffers
- * and such from the location before relocation to their final location.
- */
- int (*reloc)(struct instance *i);
-
- /*
- * This is called when the driver is shuting down, to deinitialize the
- * hardware.
- */
- int (*remove)(struct instance *i);
-
- /* This is called to remove the driver from the driver tree */
- int (*unbind)(struct instance *i);
-
- /* This is a list of cores this driver depends on */
- struct driver *cores[];
- };
-
- The cores[] array in here is very important. It allows u-boot to figure out,
- in compile-time, which possible cores can be activated at runtime. Therefore
- if there are cores that won't be ever activated, GCC LTO might remove them
- from the final binary. Actually, this information might be used to drive build
- of the cores.
-
- FIXME: Should *cores[] be really struct driver, pointing to drivers that
- represent the cores? Shouldn't it be core instance pointer?
-
- 2) Instantiation of a driver
- ----------------------------
-
- The driver is instantiated by calling:
-
- driver_bind(struct instance *bus, const struct driver_info *di)
-
- The "struct instance *bus" is a pointer to a bus with which this driver should
- be registered with. The "root" bus pointer is supplied to the board init
- functions.
-
- FIXME: We need some functions that will return list of busses of certain type
- registered with the system so the user can find proper instance even if
- he has no bus pointer (this will come handy if the user isn't
- registering the driver from board init function, but somewhere else).
-
- The "const struct driver_info *di" pointer points to a structure defining the
- driver to be registered. The structure is defined as follows:
-
- struct driver_info {
- char name[STATIC_CONFIG_DRIVER_NAME_LENGTH];
- void *platform_data;
- }
-
- The instantiation of a driver by calling driver_bind() creates an instance
- of the driver by allocating "struct driver_instance". Note that only struct
- instance is passed to the driver. The wrapping struct driver_instance is there
- for purposes of the driver core:
-
- struct driver_instance {
- uint32_t flags;
- struct instance i;
- };
-
- struct instance {
- /* Pointer to a driver information passed by driver_register() */
- const struct driver_info *info;
- /* Pointer to a bus this driver is bound with */
- struct instance *bus;
- /* Pointer to this driver's own private data */
- void *private_data;
- /* Pointer to the first block of successor nodes (optional) */
- struct successor_block *succ;
- }
-
- The instantiation of a driver does not mean the hardware is initialized. The
- driver_bind() call only creates the instance of the driver, fills in the "bus"
- pointer and calls the drivers' .bind() function. The .bind() function of the
- driver should hook the driver with the remaining cores and/or drivers it
- depends on.
-
- It's important to note here, that in case the driver instance has multiple
- parents, such parent can be connected with this instance by calling:
-
- driver_link(struct instance *parent, struct instance *dev);
-
- This will connect the other parent driver with the newly instantiated driver.
- Note that this must be called after driver_bind() and before driver_acticate()
- (driver_activate() will be explained below). To allow struct instance to have
- multiple parent pointer, the struct instance *bus will utilize it's last bit
- to indicate if this is a pointer to struct instance or to an array if
- instances, struct successor block. The approach is similar as the approach to
- *succ in struct instance, described in the following paragraph.
-
- The last pointer of the struct instance, the pointer to successor nodes, is
- used only in case of a bus driver. Otherwise the pointer contains NULL value.
- The last bit of this field indicates if this is a bus having a single child
- node (so the last bit is 0) or if this bus has multiple child nodes (the last
- bit is 1). In the former case, the driver core should clear the last bit and
- this pointer points directly to the child node. In the later case of a bus
- driver, the pointer points to an instance of structure:
-
- struct successor_block {
- /* Array of pointers to instances of devices attached to this bus */
- struct instance *dev[BLOCKING_FACTOR];
- /* Pointer to next block of successors */
- struct successor_block *next;
- }
-
- Some of the *dev[] array members might be NULL in case there are no more
- devices attached. The *next is NULL in case the list of attached devices
- doesn't continue anymore. The BLOCKING_FACTOR is used to allocate multiple
- slots for successor devices at once to avoid fragmentation of memory.
-
- 3) The bind() function of a driver
- ----------------------------------
-
- The bind function of a driver connects the driver with various cores the
- driver provides functions for. The driver model related part will look like
- the following example for a bus driver:
-
- int driver_bind(struct instance *in)
- {
- ...
- core_bind(&core_i2c_static_instance, in, i2c_bus_funcs);
- ...
- }
-
- FIXME: What if we need to run-time determine, depending on some hardware
- register, what kind of i2c_bus_funcs to pass?
-
- This makes the i2c core aware of a new bus. The i2c_bus_funcs is a constant
- structure of functions any i2c bus driver must provide to work. This will
- allow the i2c command operate with the bus. The core_i2c_static_instance is
- the pointer to the instance of a core this driver provides function to.
-
- FIXME: Maybe replace "core-i2c" with CORE_I2C global pointer to an instance of
- the core?
-
- 4) The instantiation of a core driver
- -------------------------------------
-
- The core driver is special in the way that it's single-instance driver. It is
- always present in the system, though it might not be activated. The fact that
- it's single instance allows it to be instantiated at compile time.
-
- Therefore, all possible structures of this driver can be in read-only memory,
- especially struct driver and struct driver_instance. But the successor list,
- which needs special treatment.
-
- To solve the problem with a successor list and the core driver flags, a new
- entry in struct gd (global data) will be introduced. This entry will point to
- runtime allocated array of struct driver_instance. It will be possible to
- allocate the exact amount of struct driver_instance necessary, as the number
- of cores that might be activated will be known at compile time. The cores will
- then behave like any usual driver.
-
- Pointers to the struct instance of cores can be computed at compile time,
- therefore allowing the resulting u-boot binary to save some overhead.
-
- 5) The probe() function of a driver
- -----------------------------------
-
- The probe function of a driver allocates necessary resources and does required
- initialization of the hardware itself. This is usually called only when the
- driver is needed, as a part of the defered probe mechanism.
-
- The driver core should implement a function called
-
- int driver_activate(struct instance *in);
-
- which should call the .probe() function of the driver and then configure the
- state of the driver instance to "ACTIVATED". This state of a driver instance
- should be stored in a wrap-around structure for the structure instance, the
- struct driver_instance.
-
- 6) The command side interface to a driver
- -----------------------------------------
-
- The U-Boot command shall communicate only with the specific driver core. The
- driver core in turn exports necessary API towards the command.
-
- 7) Demonstration imaginary board
- --------------------------------
-
- Consider the following computer:
-
- *
- |
- +-- System power management logic
- |
- +-- CPU clock controlling logc
- |
- +-- NAND controller
- | |
- | +-- NAND flash chip
- |
- +-- 128MB of DDR DRAM
- |
- +-- I2C bus #0
- | |
- | +-- RTC
- | |
- | +-- EEPROM #0
- | |
- | +-- EEPROM #1
- |
- +-- USB host-only IP core
- | |
- | +-- USB storage device
- |
- +-- USB OTG-capable IP core
- | |
- | +-- connection to the host PC
- |
- +-- GPIO
- | |
- | +-- User LED #0
- | |
- | +-- User LED #1
- |
- +-- UART0
- |
- +-- UART1
- |
- +-- Ethernet controller #0
- |
- +-- Ethernet controller #1
- |
- +-- Audio codec
- |
- +-- PCI bridge
- | |
- | +-- Ethernet controller #2
- | |
- | +-- SPI host card
- | | |
- | | +-- Audio amplifier (must be operational before codec)
- | |
- | +-- GPIO host card
- | |
- | +-- User LED #2
- |
- +-- LCD controller
- |
- +-- PWM controller (must be enabled after LCD controller)
- |
- +-- SPI host controller
- | |
- | +-- SD/MMC connected via SPI
- | |
- | +-- SPI flash
- |
- +-- CPLD/FPGA with stored configuration of the board