diff options
Diffstat (limited to 'doc')
26 files changed, 3806 insertions, 22 deletions
diff --git a/doc/README.SPL b/doc/README.SPL index e4a5ac3..5368586 100644 --- a/doc/README.SPL +++ b/doc/README.SPL @@ -78,3 +78,33 @@ an SPL CPU in boards.cfg as follows: This this case CPU will be set to "normal_cpu" during the main u-boot build and "spl_cpu" during the SPL build. + + +Debugging +--------- + +When building SPL with DEBUG set you may also need to set CONFIG_PANIC_HANG +as in most cases do_reset is not defined within SPL. + + +Estimating stack usage +---------------------- + +With gcc 4.6 (and later) and the use of GNU cflow it is possible to estimate +stack usage at various points in run sequence of SPL. The -fstack-usage option +to gcc will produce '.su' files (such as arch/arm/cpu/armv7/syslib.su) that +will give stack usage information and cflow can construct program flow. + +Must have gcc 4.6 or later, which supports -fstack-usage + +1) Build normally +2) Perform the following shell command to generate a list of C files used in +SPL: +$ find spl -name '*.su' | sed -e 's:^spl/::' -e 's:[.]su$:.c:' > used-spl.list +3) Execute cflow: +$ cflow --main=board_init_r `cat used-spl.list` 2>&1 | $PAGER + +cflow will spit out a number of warnings as it does not parse +the config files and picks functions based on #ifdef. Parsing the '.i' +files instead introduces another set of headaches. These warnings are +not usually important to understanding the flow, however. diff --git a/doc/README.ext4 b/doc/README.ext4 new file mode 100644 index 0000000..b3ea8b7 --- /dev/null +++ b/doc/README.ext4 @@ -0,0 +1,46 @@ +This patch series adds support for ext4 ls,load and write features in uboot +Journaling is supported for write feature. + +To Enable ext2 ls and load commands, modify the board specific config file with +#define CONFIG_CMD_EXT2 + +To Enable ext4 ls and load commands, modify the board specific config file with +#define CONFIG_CMD_EXT4 + +To enable ext4 write command, modify the board specific config file with +#define CONFIG_CMD_EXT4 +#define CONFIG_CMD_EXT4_WRITE + +Steps to test: + +1. After applying the patch, ext4 specific commands can be seen + in the boot loader prompt using + UBOOT #help + + ext4load- load binary file from a Ext4 file system + ext4ls - list files in a directory (default /) + ext4write- create a file in ext4 formatted partition + +2. To list the files in ext4 formatted partition, execute + ext4ls <interface> <dev[:part]> [directory] + For example: + UBOOT #ext4ls mmc 0:5 /usr/lib + +3. To read and load a file from an ext4 formatted partition to RAM, execute + ext4load <interface> <dev[:part]> [addr] [filename] [bytes] + For example: + UBOOT #ext4load mmc 2:2 0x30007fc0 uImage + +4. To write a file to a ext4 formatted partition. + a) First load a file to RAM at a particular address for example 0x30007fc0. + Now execute ext4write command + ext4write <interface> <dev[:part]> [filename] [Address] [sizebytes] + For example: + UBOOT #ext4write mmc 2:2 /boot/uImage 0x30007fc0 6183120 + (here 6183120 is the size of the file to be written) + Note: Absolute path is required for the file to be written + +References : + -- ext4 implementation in Linux Kernel + -- Uboot existing ext2 load and ls implementation + -- Journaling block device JBD2 implementation in linux Kernel diff --git a/doc/README.nand b/doc/README.nand index 1602b5e..c130189 100644 --- a/doc/README.nand +++ b/doc/README.nand @@ -228,6 +228,8 @@ NAND locking command (for chips with active LOCKPRE pin) "nand unlock [offset] [size]" unlock consecutive area (can be called multiple times for different areas) + "nand unlock.allexcept [offset] [size]" + unlock all except specified consecutive area I have tested the code with board containing 128MiB NAND large page chips and 32MiB small page chips. diff --git a/doc/README.scrapyard b/doc/README.scrapyard index 4b5558d..5929a8e 100644 --- a/doc/README.scrapyard +++ b/doc/README.scrapyard @@ -11,6 +11,7 @@ easily if here is something they might want to dig for... Board Arch CPU removed Commit last known maintainer/contact ============================================================================= +apollon arm omap24xx - 2012-09-06 Kyungmin Park <kyungmin.park@samsung.com> tb0229 mips mips32 - 2011-12-12 rmu powerpc MPC850 fb82fd7 2011-12-07 Wolfgang Denk <wd@denx.de> OXC powerpc MPC8240 309a292 2011-12-07 diff --git a/doc/SPL/README.omap3 b/doc/SPL/README.omap3 index a543e65..c77ca43 100644 --- a/doc/SPL/README.omap3 +++ b/doc/SPL/README.omap3 @@ -50,25 +50,3 @@ For the areas that reside within DDR1 they must not be used prior to s_init() completing. Note that CONFIG_SYS_TEXT_BASE must be clear of the areas that SPL uses while running. This is why we have two versions of the memory map that only vary in where the BSS and malloc pool reside. - -Estimating stack usage ----------------------- - -With gcc 4.6 (and later) and the use of GNU cflow it is possible to estimate -stack usage at various points in run sequence of SPL. The -fstack-usage option -to gcc will produce '.su' files (such as arch/arm/cpu/armv7/syslib.su) that -will give stack usage information and cflow can construct program flow. - -Must have gcc 4.6 or later, which supports -fstack-usage - -1) Build normally -2) Perform the following shell command to generate a list of C files used in -SPL: -$ find spl -name '*.su' | sed -e 's:^spl/::' -e 's:[.]su$:.c:' > used-spl.list -3) Execute cflow: -$ cflow --main=board_init_r `cat used-spl.list` 2>&1 | $PAGER - -cflow will spit out a number of warnings as it does not parse -the config files and picks functions based on #ifdef. Parsing the '.i' -files instead introduces another set of headaches. These warnings are -not usually important to understanding the flow, however. diff --git a/doc/driver-model/UDM-block.txt b/doc/driver-model/UDM-block.txt new file mode 100644 index 0000000..5d5c776 --- /dev/null +++ b/doc/driver-model/UDM-block.txt @@ -0,0 +1,279 @@ +The U-Boot Driver Model Project +=============================== +Block device subsystem analysis +=============================== + +Pavel Herrmann <morpheus.ibis@gmail.com> +2012-03-08 + +I) Overview +----------- + + U-Boot currently implements several distinct APIs for block devices - some + drivers use the SATA API, some drivers use the IDE API, sym53c8xx and + AHCI use the SCSI API, mg_disk has a separate API, and systemace also has a + separate API. There are also MMC and USB APIs used outside of drivers/block, + those will be detailed in their specific documents. + + Block devices are described by block_dev_desc structure, that holds, among + other things, the read/write/erase callbacks. Block device structures are + stored in any way depending on the API, but can be accessed by + + block_dev_desc_t * $api_get_dev(int dev) + + function, as seen in disk/part.c. + + 1) SATA interface + ----------------- + + The SATA interface drivers implement the following functions: + + int init_sata(int dev) + int scan_sata(int dev) + ulong sata_read(int dev, ulong blknr, ulong blkcnt, void *buffer) + ulong sata_write(int dev, ulong blknr, ulong blkcnt, const void *buffer) + + Block devices are kept in sata_dev_desc[], which is prefilled with values + common to all SATA devices in cmd_sata.c, and then modified in init_sata + function in the drivers. Callbacks of the block device use SATA API + directly. The sata_get_dev function is defined in cmd_sata.c. + + 2) SCSI interface + ----------------- + + The SCSI interface drivers implement the following functions: + + void scsi_print_error(ccb *pccb) + int scsi_exec(ccb *pccb) + void scsi_bus_reset(void) + void scsi_low_level_init(int busdevfunc) + + The SCSI API works through the scsi_exec function, the actual operation + requested is found in the ccb structure. + + Block devices are kept in scsi_dev_desc[], which lives only in cmd_scsi.c. + Callbacks of the block device use functions from cmd_scsi.c, which in turn + call scsi_exec of the controller. The scsi_get_dev function is also defined + in cmd_scsi.c. + + 3) mg_disk interface + -------------------- + + The mg_disk interface drivers implement the following functions: + + struct mg_drv_data* mg_get_drv_data (void) + uint mg_disk_init (void) + uint mg_disk_read (u32 addr, u8 *buff, u32 len) + uint mg_disk_write(u32 addr, u8 *buff, u32 len) + uint mg_disk_write_sects(void *buff, u32 sect_num, u32 sect_cnt) + uint mg_disk_read_sects(void *buff, u32 sect_num, u32 sect_cnt) + + The mg_get_drv_data function is to be overridden per-board, but there are no + board in-tree that do this. + + Only one driver for this API exists, and it only supports one block device. + Callbacks for this device are implemented in mg_disk.c and call the mg_disk + API. The mg_disk_get_dev function is defined in mg_disk.c and ignores the + device number, always returning the same device. + + 4) systemace interface + ---------------------- + + The systemace interface does not define any driver API, and has no command + itself. The single defined function is systemace_get_devs() from + systemace.c, which returns a single static structure for the only supported + block device. Callbacks for this device are also implemented in systemace.c. + + 5) IDE interface + ---------------- + + The IDE interface drivers implement the following functions, but only if + CONFIG_IDE_AHB is set: + + uchar ide_read_register(int dev, unsigned int port); + void ide_write_register(int dev, unsigned int port, unsigned char val); + void ide_read_data(int dev, ulong *sect_buf, int words); + void ide_write_data(int dev, ulong *sect_buf, int words); + + The first two functions are called from ide_inb()/ide_outb(), and will + default to direct memory access if CONFIG_IDE_AHB is not set, or + ide_inb()/ide_outb() functions will get overridden by the board altogether. + + The second two functions are called from input_data()/output_data() + functions, and also default to direct memory access, but cannot be + overridden by the board. + + One function shared by IDE drivers (but not defined in ide.h) is + int ide_preinit(void) + This function gets called from ide_init in cmd_ide.c if CONFIG_IDE_PREINIT + is defined, and will do the driver-specific initialization of the device. + + Block devices are kept in ide_dev_desc[], which is filled in cmd_ide.c. + Callbacks of the block device are defined in cmd_ide.c, and use the + ide_inb()/ide_outb()/input_data()/output_data() functions mentioned above. + The ide_get_dev function is defined in cmd_ide.c. + +II) Approach +------------ + + A new block controller core and an associated API will be created to mimic the + current SATA API, its drivers will have the following ops: + + struct block_ctrl_ops { + int scan(instance *i); + int reset(instance *i, int port); + lbaint_t read(instance *i, int port, lbaint_t start, lbatin_t length, + void *buffer); + lbaint_t write(instance *i, int port, lbaint_t start, lbatin_t length, + void*buffer); + } + + The current sata_init() function will be changed into the driver probe() + function. The read() and write() functions should never be called directly, + instead they should be called by block device driver for disks. + + Other block APIs would either be transformed into this API, or be kept as + legacy for old drivers, or be dropped altogether. + + Legacy driver APIs will each have its own driver core that will contain the + shared logic, which is currently located mostly in cmd_* files. Callbacks for + block device drivers will then probably be implemented as a part of the core + logic, and will use the driver ops (which will copy current state of + respective APIs) to do the work. + + All drivers will be cleaned up, most ifdefs should be converted into + platform_data, to enable support for multiple devices with different settings. + + A new block device core will also be created, and will keep track of all + block devices on all interfaces. + + Current block_dev_desc structure will be changed to fit the driver model, all + identification and configuration will be placed in private data, and + a single accessor and modifier will be defined, to accommodate the need for + different sets of options for different interfaces, while keeping the + structure small. The new block device drivers will have the following ops + structure (lbaint_t is either 32bit or 64bit unsigned, depending on + CONFIG_LBA48): + + struct blockdev_ops { + lbaint_t (*block_read)(struct instance *i, lbaint_t start, lbaint_t blkcnt, + void *buffer); + lbaint_t (*block_write)(struct instance *i, lbaint_t start, lbaint_t blkcnt, + void *buffer); + lbaint_t (*block_erase)(struct instance *i, lbaint_t start, lbaint_t blkcnt + ); + int (*get_option)(struct instance *i, enum blockdev_option_code op, + struct option *res); + int (*set_option)(struct instance *i, enum blockdev_option_code op, + struct option *val); + } + + struct option { + uint32_t flags + union data { + uint64_t data_u; + char* data_s; + void* data_p; + } + } + + enum blockdev_option_code { + BLKD_OPT_IFTYPE=0, + BLKD_OPT_TYPE, + BLKD_OPT_BLOCKSIZE, + BLKD_OPT_BLOCKCOUNT, + BLKD_OPT_REMOVABLE, + BLKD_OPT_LBA48, + BLKD_OPT_VENDOR, + BLKD_OPT_PRODICT, + BLKD_OPT_REVISION, + BLKD_OPT_SCSILUN, + BLKD_OPT_SCSITARGET, + BLKD_OPT_OFFSET + } + + Flags in option above will contain the type of returned data (which should be + checked against what is expected, even though the option requested should + specify it), and a flag to indicate whether the returned pointer needs to be + free()'d. + + The block device core will contain the logic now located in disk/part.c and + related files, and will be used to forward requests to block devices. The API + for the block device core will copy the ops of a block device (with a string + identifier instead of instance pointer). This means that partitions will also + be handled by the block device core, and exported as block devices, making + them transparent to the rest of the code. + + Sadly, this will change how file systems can access the devices, and thus will + affect a lot of places. However, these changes should be localized and easy to + implement. + + AHCI driver will be rewritten to fit the new unified block controller API, + making SCSI API easy to merge with sym53c8xx, or remove it once the device + driver has died. + + Optionally, IDE core may be changed into one driver with unified block + controller API, as most of it is already in one place and device drivers are + just sets of hooks. Additionally, mg_disk driver is unused and may be removed + in near future. + + + +III) Analysis of in-tree drivers +-------------------------------- + + 1) ahci.c + --------- + SCSI API, will be rewritten for a different API. + + 2) ata_piix.c + ------------- + SATA API, easy to port. + + 3) fsl_sata.c + ------------- + SATA API, few CONFIG macros, easy to port. + + 4) ftide020.c + ------------- + IDE API, defines CONFIG_IDE_AHB and ide_preinit hook functions. + + 5) mg_disk.c + ------------ + Single driver with mg_disk API, not much to change, easy to port. + + 6) mvsata_ide.c + --------------- + IDE API, only defines ide_preinit hook function. + + 7) mxc_ata.c + ------------ + IDE API, only defines ide_preinit hook function. + + 8) pata_bfin.c + -------------- + SATA API, easy to port. + + 9) sata_dwc.c + ------------- + SATA API, easy to port. + + 10) sata_sil3114.c + ------------------ + SATA API, easy to port. + + 11) sata_sil.c + -------------- + SATA API, easy to port. + + 12) sil680.c + ------------ + IDE API, only defines ide_preinit hook function. + + 13) sym53c8xx.c + --------------- + SCSI API, may be merged with code from cmd_scsi. + + 14) systemace.c + --------------- + Single driver with systemace API, not much to change, easy to port. diff --git a/doc/driver-model/UDM-cores.txt b/doc/driver-model/UDM-cores.txt new file mode 100644 index 0000000..4e13188 --- /dev/null +++ b/doc/driver-model/UDM-cores.txt @@ -0,0 +1,126 @@ +The U-Boot Driver Model Project +=============================== +Driver cores API document +========================= + +Pavel Herrmann <morpheus.ibis@gmail.com> + +1) Overview +----------- + Driver cores will be used as a wrapper for devices of the same type, and as + an abstraction for device driver APIs. For each driver API (which roughly + correspond to device types), there will be one driver core. Each driver core + will implement three APIs - a driver API (which will be the same as API of + drivers the core wraps around), a core API (which will be implemented by all + cores) and a command API (core-specific API which will be exposed to + commands). + + A) Command API + The command API will provide access to shared functionality for a specific + device, which is currently located mostly in commands. Commands will be + rewritten to be more lightweight by using this API. As this API will be + different for each core, it is out of scope of this document. + + B) Driver API + The driver API will act as a wrapper around actual device drivers, + providing a single entrypoint for device access. All functions in this API + have an instance* argument (probably called "this" or "i"), which will be + examined by the core, and a correct function for the specified driver will + get called. + + If the core gets called with a group instance pointer (as discussed in + design), it will automatically select the instance that is associated + with this core, and use it as target of the call. if the group contains + multiple instances of a single type, the caller must explicitly use an + accessor to select the correct instance. + + This accessor will look like: + struct instance *get_instance_from_group(struct instance *group, int i) + + When called with a non-group instance, it will simply return the instance. + + C) Core API + The core API will be implemented by all cores, and will provide + functionality for getting driver instances from non-driver code. This API + will consist of following functions: + + int get_count(struct instance *core); + struct instance* get_instance(struct instance *core, int index); + int init(struct instance *core); + int bind(struct instance *core, struct instance *dev, void *ops, + void *hint); + int unbind(struct instance *core, instance *dev); + int replace(struct instance *core, struct_instance *new_dev, + struct instance *old_dev); + int destroy(struct instance *core); + int reloc(struct instance *new_core, struct instance *old_core); + + The 'hint' parameter of bind() serves for additional data a driver can + pass to the core, to help it create the correct internal state for this + instance. the replace() function will get called during instance + relocation, and will replace the old instance with the new one, keeping + the internal state untouched. + + +2) Lifetime of a driver core +---------------------------- + Driver cores will be initialized at runtime, to limit memory footprint in + early-init stage, when we have to fit into ~1KB of memory. All active cores + will be stored in a tree structure (referenced as "Core tree") in global data, + which provides good tradeoff between size and access time. + Every core will have a number constant associated with it, which will be used + to find the instance in Core tree, and to refer to the core in all calls + working with the Core tree. + The Core Tree should be implemented using B-tree (or a similar structure) + to guarantee acceptable time overhead in all cases. + + Code for working with the core (i2c in this example) follows: + + core_init(CORE_I2C); + This will check whether we already have a i2c core, and if not it creates + a new instance and adds it into the Core tree. This will not be exported, + all code should depend on get_core_instance to init the core when + necessary. + + get_core_instance(CORE_I2C); + This is an accessor into the Core tree, which will return the instance + of i2c core, creating it if necessary + + core_bind(CORE_I2C, instance, driver_ops); + This will get called in bind() function of a driver, and will add the + instance into cores internal list of devices. If the core is not found, it + will get created. + + driver_activate(instance *inst); + This call will recursively activate all devices necessary for using the + specified device. the code could be simplified as: + { + if (is_activated(inst)) + return; + driver_activate(inst->bus); + get_driver(inst)->probe(inst); + } + + The case with multiple parents will need to be handled here as well. + get_driver is an accessor to available drivers, which will get struct + driver based on a name in the instance. + + i2c_write(instance *inst, ...); + An actual call to some method of the driver. This code will look like: + { + driver_activate(inst); + struct instance *core = get_core_instance(CORE_I2C); + device_ops = get_ops(inst); + device_ops->write(...); + } + + get_ops will not be an exported function, it will be internal and specific + to the core, as it needs to know how are the ops stored, and what type + they are. + + Please note that above examples represent the algorithm, not the actual code, + as they are missing checks for validity of return values. + + core_init() function will get called the first time the core is requested, + either by core_link() or core_get_instance(). This way, the cores will get + created only when they are necessary, which will reduce our memory footprint. diff --git a/doc/driver-model/UDM-design.txt b/doc/driver-model/UDM-design.txt new file mode 100644 index 0000000..185f477 --- /dev/null +++ b/doc/driver-model/UDM-design.txt @@ -0,0 +1,315 @@ +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 diff --git a/doc/driver-model/UDM-fpga.txt b/doc/driver-model/UDM-fpga.txt new file mode 100644 index 0000000..4f9df94 --- /dev/null +++ b/doc/driver-model/UDM-fpga.txt @@ -0,0 +1,115 @@ +The U-Boot Driver Model Project +=============================== +I/O system analysis +=================== +Marek Vasut <marek.vasut@gmail.com> +2012-02-21 + +I) Overview +----------- + +The current FPGA implementation is handled by command "fpga". This command in +turn calls the following functions: + +fpga_info() +fpga_load() +fpga_dump() + +These functions are implemented by what appears to be FPGA multiplexer, located +in drivers/fpga/fpga.c . This code determines which device to operate with +depending on the device ID. + +The fpga_info() function is multiplexer of the functions providing information +about the particular FPGA device. These functions are implemented in the drivers +for the particular FPGA device: + +xilinx_info() +altera_info() +lattice_info() + +Similar approach is used for fpga_load(), which multiplexes "xilinx_load()", +"altera_load()" and "lattice_load()" and is used to load firmware into the FPGA +device. + +The fpga_dump() function, which prints the contents of the FPGA device, is no +different either, by multiplexing "xilinx_dump()", "altera_dump()" and +"lattice_dump()" functions. + +Finally, each new FPGA device is registered by calling "fpga_add()" function. +This function takes two arguments, the second one being particularly important, +because it's basically what will become platform_data. Currently, it's data that +are passed to the driver from the board/platform code. + +II) Approach +------------ + +The path to conversion of the FPGA subsystem will be very straightforward, since +the FPGA subsystem is already quite dynamic. Multiple things will need to be +modified though. + +First is the registration of the new FPGA device towards the FPGA core. This +will be achieved by calling: + + fpga_device_register(struct instance *i, const struct fpga_ops *ops); + +The particularly interesting part is the struct fpga_ops, which contains +operations supported by the FPGA device. These are basically the already used +calls in the current implementation: + +struct fpga_ops { + int info(struct instance *i); + int load(struct instance *i, const char *buf, size_t size); + int dump(struct instance *i, const char *buf, size_t size); +} + +The other piece that'll have to be modified is how the devices are tracked. +It'll be necessary to introduce a linked list of devices within the FPGA core +instead of tracking them by ID number. + +Next, the "Xilinx_desc", "Lattice_desc" and "Altera_desc" structures will have +to be moved to driver's private_data. Finally, structures passed from the board +and/or platform files, like "Xilinx_Virtex2_Slave_SelectMap_fns" would be passed +via platform_data to the driver. + +III) Analysis of in-tree drivers +-------------------------------- + + 1) Altera driver + ---------------- + The driver is realized using the following files: + + drivers/fpga/altera.c + drivers/fpga/ACEX1K.c + drivers/fpga/cyclon2.c + drivers/fpga/stratixII.c + + All of the sub-drivers implement basically the same info-load-dump interface + and there's no expected problem during the conversion. The driver itself will + be realised by altera.c and all the sub-drivers will be linked in. The + distinction will be done by passing different platform data. + + 2) Lattice driver + ----------------- + The driver is realized using the following files: + + drivers/fpga/lattice.c + drivers/fpga/ivm_core.c + + This driver also implements the standard interface, but to realise the + operations with the FPGA device, uses functions from "ivm_core.c" file. This + file implements the main communications logic and has to be linked in together + with "lattice.c". No problem converting is expected here. + + 3) Xilinx driver + ---------------- + The driver is realized using the following files: + + drivers/fpga/xilinx.c + drivers/fpga/spartan2.c + drivers/fpga/spartan3.c + drivers/fpga/virtex2.c + + This set of sub-drivers is special by defining a big set of macros in + "include/spartan3.h" and similar files. These macros would need to be either + rewritten or replaced. Otherwise, there are no problems expected during the + conversion process. diff --git a/doc/driver-model/UDM-gpio.txt b/doc/driver-model/UDM-gpio.txt new file mode 100644 index 0000000..8ff0a96 --- /dev/null +++ b/doc/driver-model/UDM-gpio.txt @@ -0,0 +1,106 @@ +The U-Boot Driver Model Project +=============================== +GPIO analysis +============= +Viktor Krivak <viktor.krivak@gmail.com> +2012-02-24 + +I) Overview +----------- + + At this moment U-Boot provides standard API that consists of 7 functions. + + int gpio_request(unsigned gpio, const char *label) + int gpio_free(unsigned gpio) + int gpio_direction_input(unsigned gpio) + int gpio_direction_output(unsigned gpio, int value) + int gpio_get_value(unsigned gpio) + void gpio_set_value(unsigned gpio, int value) + + Methods "gpio_request()" and "gpio_free()" are used for claiming and releasing + GPIOs. First one should check if the desired pin exists and if the pin wasn't + requested already elsewhere. The method also has a label argument that can be + used for debug purposes. The label argument should be copied into the internal + memory, but only if the DEBUG macro is set. The "gpio_free()" is the exact + opposite. It releases the particular pin. Other methods are used for setting + input or output direction and obtaining or setting values of the pins. + +II) Approach +------------ + + 1) Request and free GPIO + ------------------------ + + The "gpio_request()" implementation is basically the same for all boards. + The function checks if the particular GPIO is correct and checks if the + GPIO pin is still free. If the conditions are met, the method marks the + GPIO claimed in it's internal structure. If macro DEBUG is defined, the + function also copies the label argument to the structure. If the pin is + already locked, the function returns -1 and if DEBUG is defined, certain + debug output is generated, including the contents of the label argument. + The "gpio_free()" function releases the lock and eventually deallocates + data used by the copied label argument. + + 2) Internal data + ---------------- + + Internal data are driver specific. They have to contain some mechanism to + realise the locking though. This can be done for example using a bit field. + + 3) Operations provided by the driver + ------------------------------------ + + The driver operations basically meet API that is already defined and used. + Except for "gpio_request()" and "gpio_free()", all methods can be converted in + a simple manner. The driver provides the following structure: + + struct gpio_driver_ops { + int (*gpio_request)(struct instance *i, unsigned gpio, + const char *label); + int (*gpio_free)(struct instance *i, unsigned gpio); + int (*gpio_direction_input)(struct instance *i, unsigned gpio); + int (*gpio_direction_output)(struct instance *i, unsigned gpio, + int value); + int (*gpio_get_value)(struct instance *i, unsigned gpio); + void (*gpio_set_value)(struct instance *i, unsigned gpio, int value); + } + +III) Analysis of in-tree drivers +-------------------------------- + + 1) altera_pio.c + --------------- + Meets standard API. Implements gpio_request() properly. Simple conversion + possible. + + 2) at91_gpio.c + -------------- + Don't meet standard API. Need some other methods to implement. + + 3) da8xx_gpio.c + --------------- + Meets standard API. Implements gpio_request() properly. Simple conversion + possible. + + 4) kw_gpio.c + ------------ + Doesn't meet standard API. Needs some other methods to implement and move some + methods to another file. + + 5) mpc83xx_gpio.c + ----------------- + Meets standard API. Doesn't implement gpio_request() properly (only checks + if the pin is valid). Simple conversion possible. + + 6) mvgpio.c + ----------- + Meets standard API. Doesn't implement gpio_request() properly (only checks + if the pin is valid). Simple conversion possible. + + 7) mvgpio.h + ----------- + Wrong placement. Will be moved to another location. + + 8) mvmfp.c + ---------- + Wrong placement. Will be moved to another location. diff --git a/doc/driver-model/UDM-hwmon.txt b/doc/driver-model/UDM-hwmon.txt new file mode 100644 index 0000000..cc5d529 --- /dev/null +++ b/doc/driver-model/UDM-hwmon.txt @@ -0,0 +1,118 @@ +The U-Boot Driver Model Project +=============================== +Hwmon device subsystem analysis +=============================== + +Tomas Hlavacek <tmshlvck@gmail.com> +2012-03-02 + +I) Overview +----------- + +U-Boot currently implements one API for HW monitoring devices. The +interface is defined in include/dtt.h and comprises of functions: + + void dtt_init(void); + int dtt_init_one(int); + int dtt_read(int sensor, int reg); + int dtt_write(int sensor, int reg, int val); + int dtt_get_temp(int sensor); + +The functions are implemented by a proper device driver in drivers/hwmon +directory and the driver to be compiled in is selected in a Makefile. +Drivers are mutually exclusive. + +Drivers depends on I2O code and naturally on board specific data. There are +few ad-hoc constants put in dtt.h file and driver headers and code. This +has to be consolidated into board specific data or driver headers if those +constants makes sense globally. + + +II) Approach +------------ + + 1) New API + ---------- + In the UDM each hwmon driver would register itself by a function + + int hwmon_device_register(struct instance *i, + struct hwmon_device_ops *o); + + The structure being defined as follows: + + struct hwmon_device_ops { + int (*read)(struct instance *i, int sensor, int reg); + int (*write)(struct instance *i, int sensor, int reg, + int val); + int (*get_temp)(struct instance *i, int sensor); + }; + + + 2) Conversion thougths + ---------------------- + U-Boot hwmon drivers exports virtually the same functions (with exceptions) + and we are considering low number of drivers and code anyway. The interface + is already similar and unified by the interface defined in dtt.h. + Current initialization functions dtt_init() and dtt_init_one() will be + converted into probe() and hwmon_device_register(), so the funcionality will + be kept in more proper places. Besides implementing core registration and + initialization we need to do code cleanup, especially separate + driver-specific and HW specific constants. + + 3) Special consideration due to early initialization + ---------------------------------------------------- + The dtt_init() function call is used during early initialization in + board/gdsys/405ex/io64.c for starting up fans. The dtt code is perfectly + usable in the early stage because it uses only local variables and no heap + memory is required at this level. However the underlying code of I2C has to + keep the same properties with regard to possibility of running in early + initialization stage. + +III) Analysis of in-tree drivers +-------------------------------- + + 1) drivers/hwmon/lm81.c + ----------------------- + The driver is standard dtt. Simple conversion is possible. + + + 2) drivers/hwmon/ds1722.c + ------------------------- + The driver is not standard dtt, but interface is similar to dtt. + The interface has to be changed in order to comply to above mentioned + specification. + + + 3) drivers/hwmon/ds1775.c + ------------------------- + The driver is standard dtt. Simple conversion is possible. + + + 4) drivers/hwmon/lm73.c + ----------------------- + The driver is standard dtt. Simple conversion is possible. + + + 5) drivers/hwmon/lm63.c + ----------------------- + The driver is standard dtt. Simple conversion is possible. + + + 6) drivers/hwmon/adt7460.c + -------------------------- + The driver is standard dtt. Simple conversion is possible. + + + 7) drivers/hwmon/lm75.c + ----------------------- + The driver is standard dtt. Simple conversion is possible. + + + 8) drivers/hwmon/ds1621.c + ------------------------- + The driver is standard dtt. Simple conversion is possible. + + + 9) drivers/hwmon/adm1021.c + -------------------------- + The driver is standard dtt. Simple conversion is possible. diff --git a/doc/driver-model/UDM-keyboard.txt b/doc/driver-model/UDM-keyboard.txt new file mode 100644 index 0000000..ef3761d --- /dev/null +++ b/doc/driver-model/UDM-keyboard.txt @@ -0,0 +1,47 @@ +The U-Boot Driver Model Project +=============================== +Keyboard input analysis +======================= +Marek Vasut <marek.vasut@gmail.com> +2012-02-20 + +I) Overview +----------- + +The keyboard drivers are most often registered with STDIO subsystem. There are +components of the keyboard drivers though, which operate in severe ad-hoc +manner, often being related to interrupt-driven keypress reception. This +components will require the most sanitization of all parts of keyboard input +subsystem. + +Otherwise, the keyboard is no different from other standard input but with the +necessity to decode scancodes. These are decoded using tables provided by +keyboard drivers. These tables are often driver specific. + +II) Approach +------------ + +The most problematic part is the interrupt driven keypress reception. For this, +the buffers that are currently shared throughout the whole U-Boot would need to +be converted into driver's private data. + +III) Analysis of in-tree drivers +-------------------------------- + + 1) board/mpl/common/kbd.c + ------------------------- + This driver is a classic STDIO driver, no problem with conversion is expected. + Only necessary change will be to move this driver to a proper location. + + 2) board/rbc823/kbd.c + --------------------- + This driver is a classic STDIO driver, no problem with conversion is expected. + Only necessary change will be to move this driver to a proper location. + + 3) drivers/input/keyboard.c + --------------------------- + This driver is special in many ways. Firstly because this is a universal stub + driver for converting scancodes from i8042 and the likes. Secondly because the + buffer is filled by various other ad-hoc implementations of keyboard input by + using this buffer as an extern. This will need to be fixed by allowing drivers + to pass certain routines to this driver via platform data. diff --git a/doc/driver-model/UDM-mmc.txt b/doc/driver-model/UDM-mmc.txt new file mode 100644 index 0000000..bed4306 --- /dev/null +++ b/doc/driver-model/UDM-mmc.txt @@ -0,0 +1,319 @@ +The U-Boot Driver Model Project +=============================== +MMC system analysis +=================== +Marek Vasut <marek.vasut@gmail.com> +2012-02-25 + +I) Overview +----------- + +The MMC subsystem is already quite dynamic in it's nature. It's only necessary +to flip the subsystem to properly defined API. + +The probing process of MMC drivers start by calling "mmc_initialize()", +implemented by MMC framework, from the architecture initialization file. The +"mmc_initialize()" function in turn calls "board_mmc_init()" function and if +this doesn't succeed, "cpu_mmc_init()" function is called. It is important to +note that both of the "*_mmc_init()" functions have weak aliases to functions +which automatically fail. + +Both of the "*_mmc_init()" functions though serve only one purpose. To call +driver specific probe function, which in turn actually registers the driver with +MMC subsystem. Each of the driver specific probe functions is currently done in +very ad-hoc manner. + +The registration with the MMC subsystem is done by calling "mmc_register()", +whose argument is a runtime configured structure of information about the MMC +driver. Currently, the information structure is intermixed with driver's internal +data. The description of the structure follows: + +struct mmc { + /* + * API: Allows this driver to be a member of the linked list of all MMC drivers + * registered with MMC subsystem + */ + struct list_head link; + + /* DRIVER: Name of the registered driver */ + char name[32]; + + /* DRIVER: Driver's private data */ + void *priv; + + /* DRIVER: Voltages the host bus can provide */ + uint voltages; + + /* API: Version of the card */ + uint version; + + /* API: Test if the driver was already initialized */ + uint has_init; + + /* DRIVER: Minimum frequency the host bus can provide */ + uint f_min; + + /* DRIVER: Maximum frequency the host bus can provide */ + uint f_max; + + /* API: Is the card SDHC */ + int high_capacity; + + /* API: Actual width of the bus used by the current card */ + uint bus_width; + + /* + * DRIVER: Clock frequency to be configured on the host bus, this is read-only + * for the driver. + */ + uint clock; + + /* API: Capabilities of the card */ + uint card_caps; + + /* DRIVER: MMC bus capabilities */ + uint host_caps; + + /* API: Configuration and ID data retrieved from the card */ + uint ocr; + uint scr[2]; + uint csd[4]; + uint cid[4]; + ushort rca; + + /* API: Partition configuration */ + char part_config; + + /* API: Number of partitions */ + char part_num; + + /* API: Transmission speed */ + uint tran_speed; + + /* API: Read block length */ + uint read_bl_len; + + /* API: Write block length */ + uint write_bl_len; + + /* API: Erase group size */ + uint erase_grp_size; + + /* API: Capacity of the card */ + u64 capacity; + + /* API: Descriptor of this block device */ + block_dev_desc_t block_dev; + + /* DRIVER: Function used to submit command to the card */ + int (*send_cmd)(struct mmc *mmc, + struct mmc_cmd *cmd, struct mmc_data *data); + + /* DRIVER: Function used to configure the host */ + void (*set_ios)(struct mmc *mmc); + + /* DRIVER: Function used to initialize the host */ + int (*init)(struct mmc *mmc); + + /* DRIVER: Function used to report the status of Card Detect pin */ + int (*getcd)(struct mmc *mmc); + + /* + * DRIVER: Maximum amount of blocks sent during multiblock xfer, + * set to 0 to autodetect. + */ + uint b_max; +}; + +The API above is the new API used by most of the drivers. There're still drivers +in the tree that use old, legacy API though. + +2) Approach +----------- + +To convert the MMC subsystem to a proper driver model, the "struct mmc" +structure will have to be properly split in the first place. The result will +consist of multiple parts, first will be the structure defining operations +provided by the MMC driver: + +struct mmc_driver_ops { + /* Function used to submit command to the card */ + int (*send_cmd)(struct mmc *mmc, + struct mmc_cmd *cmd, struct mmc_data *data); + /* DRIVER: Function used to configure the host */ + void (*set_ios)(struct mmc *mmc); + /* Function used to initialize the host */ + int (*init)(struct mmc *mmc); + /* Function used to report the status of Card Detect pin */ + int (*getcd)(struct mmc *mmc); +} + +The second part will define the parameters of the MMC driver: + +struct mmc_driver_params { + /* Voltages the host bus can provide */ + uint32_t voltages; + /* Minimum frequency the host bus can provide */ + uint32_t f_min; + /* Maximum frequency the host bus can provide */ + uint32_t f_max; + /* MMC bus capabilities */ + uint32_t host_caps; + /* + * Maximum amount of blocks sent during multiblock xfer, + * set to 0 to autodetect. + */ + uint32_t b_max; +} + +And finally, the internal per-card data of the MMC subsystem core: + +struct mmc_card_props { + /* Version of the card */ + uint32_t version; + /* Test if the driver was already initializes */ + bool has_init; + /* Is the card SDHC */ + bool high_capacity; + /* Actual width of the bus used by the current card */ + uint8_t bus_width; + /* Capabilities of the card */ + uint32_t card_caps; + /* Configuration and ID data retrieved from the card */ + uint32_t ocr; + uint32_t scr[2]; + uint32_t csd[4]; + uint32_t cid[4]; + uint16_t rca; + /* Partition configuration */ + uint8_t part_config; + /* Number of partitions */ + uint8_t part_num; + /* Transmission speed */ + uint32_t tran_speed; + /* Read block length */ + uint32_t read_bl_len; + /* Write block length */ + uint32_t write_bl_len; + /* Erase group size */ + uint32_t erase_grp_size; + /* Capacity of the card */ + uint64_t capacity; + /* Descriptor of this block device */ + block_dev_desc_t block_dev; +} + +The probe() function will then register the MMC driver by calling: + + mmc_device_register(struct instance *i, struct mmc_driver_ops *o, + struct mmc_driver_params *p); + +The struct mmc_driver_params will have to be dynamic in some cases, but the +driver shouldn't modify it's contents elsewhere than in probe() call. + +Next, since the MMC drivers will now be consistently registered into the driver +tree from board file, the functions "board_mmc_init()" and "cpu_mmc_init()" will +disappear altogether. + +As for the legacy drivers, these will either be converted or removed altogether. + +III) Analysis of in-tree drivers +-------------------------------- + + 1) arm_pl180_mmci.c + ------------------- + Follows the new API and also has a good encapsulation of the whole driver. The + conversion here will be simple. + + 2) atmel_mci.c + -------------- + This driver uses the legacy API and should be removed unless converted. It is + probably possbible to replace this driver with gen_atmel_mci.c . No conversion + will be done on this driver. + + 3) bfin_sdh.c + ------------- + Follows the new API and also has a good encapsulation of the whole driver. The + conversion here will be simple. + + 4) davinci_mmc.c + ---------------- + Follows the new API and also has a good encapsulation of the whole driver. The + conversion here will be simple. + + 5) fsl_esdhc.c + -------------- + Follows the new API and also has a good encapsulation of the whole driver. The + conversion here will be simple, unless some problem appears due to the FDT + component of the driver. + + 6) ftsdc010_esdhc.c + ------------------- + Follows the new API and also has a good encapsulation of the whole driver. The + conversion here will be simple. + + 7) gen_atmel_mci.c + ------------------ + Follows the new API and also has a good encapsulation of the whole driver. The + conversion here will be simple. + + 8) mmc_spi.c + ------------ + Follows the new API and also has a good encapsulation of the whole driver. The + conversion here will be simple. + + 9) mv_sdhci.c + ------------- + This is a component of the SDHCI support, allowing it to run on Marvell + Kirkwood chip. It is probable the SDHCI support will have to be modified to + allow calling functions from this file based on information passed via + platform_data. + + 10) mxcmmc.c + ------------ + Follows the new API and also has a good encapsulation of the whole driver. The + conversion here will be simple. + + 11) mxsmmc.c + ------------ + Follows the new API and also has a good encapsulation of the whole driver. The + conversion here will be simple. + + 12) omap_hsmmc.c + ---------------- + Follows the new API and also has a good encapsulation of the whole driver. The + conversion here will be simple. + + 13) pxa_mmc.c + ------------- + This driver uses the legacy API and is written in a severely ad-hoc manner. + This driver will be removed in favor of pxa_mmc_gen.c, which is proved to work + better and is already well tested. No conversion will be done on this driver + anymore. + + 14) pxa_mmc_gen.c + ----------------- + Follows the new API and also has a good encapsulation of the whole driver. The + conversion here will be simple. + + 15) s5p_mmc.c + ------------- + Follows the new API and also has a good encapsulation of the whole driver. The + conversion here will be simple. + + 16) sdhci.c + ----------- + Follows the new API and also has a good encapsulation of the whole driver. The + conversion here will be simple, though it'd be necessary to modify this driver + to also support the Kirkwood series and probably also Tegra series of CPUs. + See the respective parts of this section for details. + + 17) sh_mmcif.c + -------------- + Follows the new API and also has a good encapsulation of the whole driver. The + conversion here will be simple. + + 18) tegra2_mmc.c + ---------------- + Follows the new API and also has a good encapsulation of the whole driver. The + conversion here will be simple. diff --git a/doc/driver-model/UDM-net.txt b/doc/driver-model/UDM-net.txt new file mode 100644 index 0000000..e2ea8f5 --- /dev/null +++ b/doc/driver-model/UDM-net.txt @@ -0,0 +1,434 @@ +The U-Boot Driver Model Project +=============================== +Net system analysis +=================== +Marek Vasut <marek.vasut@gmail.com> +2012-03-03 + +I) Overview +----------- + +The networking subsystem already supports multiple devices. Therefore the +conversion shall not be very hard. + +The network subsystem is operated from net/eth.c, which tracks all registered +ethernet interfaces and calls their particular functions registered via +eth_register(). + +The eth_register() is called from the network driver initialization function, +which in turn is called most often either from "board_net_init()" or +"cpu_net_init()". This function has one important argument, which is the +"struct eth_device", defined at include/net.h: + +struct eth_device { + /* DRIVER: Name of the device */ + char name[NAMESIZE]; + /* DRIVER: MAC address */ + unsigned char enetaddr[6]; + /* DRIVER: Register base address */ + int iobase; + /* CORE: state of the device */ + int state; + + /* DRIVER: Device initialization function */ + int (*init) (struct eth_device*, bd_t*); + /* DRIVER: Function for sending packets */ + int (*send) (struct eth_device*, volatile void* packet, int length); + /* DRIVER: Function for receiving packets */ + int (*recv) (struct eth_device*); + /* DRIVER: Function to cease operation of the device */ + void (*halt) (struct eth_device*); + /* DRIVER: Function to send multicast packet (OPTIONAL) */ + int (*mcast) (struct eth_device*, u32 ip, u8 set); + /* DRIVER: Function to change ethernet MAC address */ + int (*write_hwaddr) (struct eth_device*); + /* CORE: Next device in the linked list of devices managed by net core */ + struct eth_device *next; + /* CORE: Device index */ + int index; + /* DRIVER: Driver's private data */ + void *priv; +}; + +This structure defines the particular driver, though also contains elements that +should not be exposed to the driver, like core state. + +Small, but important part of the networking subsystem is the PHY management +layer, whose drivers are contained in drivers/net/phy. These drivers register in +a very similar manner to network drivers, by calling "phy_register()" with the +argument of "struct phy_driver": + +struct phy_driver { + /* DRIVER: Name of the PHY driver */ + char *name; + /* DRIVER: UID of the PHY driver */ + unsigned int uid; + /* DRIVER: Mask for UID of the PHY driver */ + unsigned int mask; + /* DRIVER: MMDS of the PHY driver */ + unsigned int mmds; + /* DRIVER: Features the PHY driver supports */ + u32 features; + /* DRIVER: Initialize the PHY hardware */ + int (*probe)(struct phy_device *phydev); + /* DRIVER: Reconfigure the PHY hardware */ + int (*config)(struct phy_device *phydev); + /* DRIVER: Turn on the PHY hardware, allow it to send/receive */ + int (*startup)(struct phy_device *phydev); + /* DRIVER: Turn off the PHY hardware */ + int (*shutdown)(struct phy_device *phydev); + /* CORE: Allows this driver to be part of list of drivers */ + struct list_head list; +}; + +II) Approach +------------ + +To convert the elements of network subsystem to proper driver model method, the +"struct eth_device" will have to be split into multiple components. The first +will be a structure defining the driver operations: + +struct eth_driver_ops { + int (*init)(struct instance*, bd_t*); + int (*send)(struct instance*, void *packet, int length); + int (*recv)(struct instance*); + void (*halt)(struct instance*); + int (*mcast)(struct instance*, u32 ip, u8 set); + int (*write_hwaddr)(struct instance*); +}; + +Next, there'll be platform data which will be per-driver and will replace the +"priv" part of "struct eth_device". Last part will be the per-device core state. + +With regards to the PHY part of the API, the "struct phy_driver" is almost ready +to be used with the new driver model approach. The only change will be the +replacement of per-driver initialization functions and removal of +"phy_register()" function in favor or driver model approach. + +III) Analysis of in-tree drivers +-------------------------------- + + 1) drivers/net/4xx_enet.c + ------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 2) drivers/net/altera_tse.c + --------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 3) drivers/net/armada100_fec.c + ------------------------------ + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 4) drivers/net/at91_emac.c + -------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 5) drivers/net/ax88180.c + ------------------------ + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 6) drivers/net/ax88796.c + ------------------------ + + This file contains a components of the NE2000 driver, implementing only + different parts on the NE2000 clone AX88796. This being no standalone driver, + no conversion will be done here. + + 7) drivers/net/bfin_mac.c + ------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 8) drivers/net/calxedaxgmac.c + ----------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 9) drivers/net/cs8900.c + ----------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 10) drivers/net/davinci_emac.c + ------------------------------ + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 11) drivers/net/dc2114x.c + ------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 12) drivers/net/designware.c + ---------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 13) drivers/net/dm9000x.c + ------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 14) drivers/net/dnet.c + ---------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 15) drivers/net/e1000.c + ----------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 16) drivers/net/e1000_spi.c + --------------------------- + + Driver for the SPI bus integrated on the Intel E1000. This is not part of the + network stack. + + 17) drivers/net/eepro100.c + -------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 18) drivers/net/enc28j60.c + -------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 19) drivers/net/ep93xx_eth.c + ---------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 20) drivers/net/ethoc.c + ----------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 21) drivers/net/fec_mxc.c + ------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 22) drivers/net/fsl_mcdmafec.c + ------------------------------ + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 23) drivers/net/fsl_mdio.c + -------------------------- + + This file contains driver for FSL MDIO interface, which is not part of the + networking stack. + + 24) drivers/net/ftgmac100.c + --------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 25) drivers/net/ftmac100.c + -------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 26) drivers/net/greth.c + ----------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 27) drivers/net/inca-ip_sw.c + ---------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 28) drivers/net/ks8695eth.c + --------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 29) drivers/net/lan91c96.c + -------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 30) drivers/net/macb.c + ---------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 31) drivers/net/mcffec.c + ------------------------ + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 32) drivers/net/mcfmii.c + ------------------------ + + This file contains MII interface driver for MCF FEC. + + 33) drivers/net/mpc512x_fec.c + ----------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 34) drivers/net/mpc5xxx_fec.c + ----------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 35) drivers/net/mvgbe.c + ----------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 36) drivers/net/natsemi.c + ------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 37) drivers/net/ne2000_base.c + ----------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. This driver contains the core + implementation of NE2000, which needs a few external functions, implemented by + AX88796, NE2000 etc. + + 38) drivers/net/ne2000.c + ------------------------ + + This file implements external functions necessary for native NE2000 compatible + networking card to work. + + 39) drivers/net/netarm_eth.c + ---------------------------- + + This driver uses the old, legacy, network API and will either have to be + converted or removed. + + 40) drivers/net/netconsole.c + ---------------------------- + + This is actually an STDIO driver. + + 41) drivers/net/ns8382x.c + ------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 42) drivers/net/pcnet.c + ----------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 43) drivers/net/plb2800_eth.c + ----------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 44) drivers/net/rtl8139.c + ------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 45) drivers/net/rtl8169.c + ------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 46) drivers/net/sh_eth.c + ------------------------ + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 47) drivers/net/smc91111.c + -------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 48) drivers/net/smc911x.c + ------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 49) drivers/net/tsec.c + ---------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 50) drivers/net/tsi108_eth.c + ---------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 51) drivers/net/uli526x.c + ------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 52) drivers/net/vsc7385.c + ------------------------- + + This is a driver that only uploads firmware to a switch. This is not subject + of conversion. + + 53) drivers/net/xilinx_axi_emac.c + --------------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. + + 54) drivers/net/xilinx_emaclite.c + --------------------------------- + + This driver uses the standard new networking API, therefore there should be no + obstacles throughout the conversion process. diff --git a/doc/driver-model/UDM-pci.txt b/doc/driver-model/UDM-pci.txt new file mode 100644 index 0000000..b65e9ea --- /dev/null +++ b/doc/driver-model/UDM-pci.txt @@ -0,0 +1,265 @@ +The U-Boot Driver Model Project +=============================== +PCI subsystem analysis +====================== + +Pavel Herrmann <morpheus.ibis@gmail.com> +2012-03-17 + +I) Overview +----------- + + U-Boot already supports multiple PCI busses, stored in a linked-list of + pci_controller structures. This structure contains generic driver data, bus + interface operations and private data for the driver. + + Bus interface operations for PCI are (names are self-explanatory): + + read_byte() + read_word() + read_dword() + write_byte() + write_word() + write_dword() + + Each driver has to implement dword operations, and either implement word and + byte operations, or use shared $operation_config_$type_via_dword (eg. + read_config_byte_via_dword and similar) function. These functions are used + for config space I/O (read_config_dword and similar functions of the PCI + subsystem), which is used to configure the connected devices for standard MMIO + operations. All data transfers by respective device drivers are then done by + MMIO + + Each driver also defines a separate init function, which has unique symbol + name, and thus more drivers can be compiled in without colliding. This init + function is typically called from pci_init_board(), different for each + particular board. + + Some boards also define a function called fixup_irq, which gets called after + scanning the PCI bus for devices, and should dismiss any interrupts. + + Several drivers are also located in arch/ and should be moved to drivers/pci. + +II) Approach +------------ + + The pci_controller structure needs to be broken down to fit the new driver + model. Due to a large number of members, this will be done through three + distinct accessors, one for memory regions, one for config table and one for + everything else. That will make the pci_ops structure look like this: + + struct pci_ops { + int (*read_byte)(struct instance *bus, pci_dev_t *dev, int addr, + u8 *buf); + int (*read_word)(struct instance *bus, pci_dev_t *dev, int addr, + u16 *buf); + int (*read_dword)(struct instance *bus, pci_dev_t *dev, int addr, + u32 *buf); + int (*write_byte)(struct instance *bus, pci_dev_t *dev, int addr, + u8 val); + int (*write_byte)(struct instance *bus, pci_dev_t *dev, int addr, + u8 val); + int (*write_dword)(struct instance *bus, pci_dev_t *dev, int addr, + u32 val); + void (*fixup_irq)(struct instance *bus, pci_dev_t *dev); + struct pci_region* (*get_region)(struct instance *, uint num); + struct pci_config_table* (*get_cfg_table)(struct instance *bus); + uint (*get_option)(struct instance * bus, enum pci_option_code op); + } + + enum pci_option_code { + PCI_OPT_BUS_NUMBER=0, + PCI_OPT_REGION_COUNT, + PCI_OPT_INDIRECT_TYPE, + PCI_OPT_AUTO_MEM, + PCI_OPT_AUTO_IO, + PCI_OPT_AUTO_PREFETCH, + PCI_OPT_AUTO_FB, + PCI_OPT_CURRENT_BUS, + PCI_OPT_CFG_ADDR, + } + + The return value for get_option will be an unsigned integer value for any + option code. If the option currently is a pointer to pci_region, it will + return an index for get_region function. Special case has to be made for + PCI_OPT_CFG_ADDR, which should be interpreted as a pointer, but it is only + used for equality in find_hose_by_cfg_addr, and thus can be returned as an + uint. Other function using cfg_addr value are read/write functions for + specific drivers (especially ops for indirect bridges), and thus have access + to private_data of the driver instance. + + The config table accessor will return a pointer to a NULL-terminated array of + pci_config_table, which is supplied by the board in platform_data, or NULL if + the board didn't specify one. This table is used to override PnP + auto-initialization, or to specific initialization functions for non-PNP + devices. + + Transparent PCI-PCI bridges will get their own driver, and will forward all + operations to operations of their parent bus. This however makes it + impossible to use instances to identify devices, as not all devices will be + directly visible to the respective bus driver. + + Init functions of controller drivers will be moved to their respective + probe() functions, in accordance to the driver model. + + The PCI core will handle all mapping functions currently found in pci.c, as + well as proxy functions for read/write operations of the drivers. The PCI + core will also handle bus scanning and device configuration. + + The PnP helper functions currently in pci_auto.c will also be a part of PCI + core, but they will be exposed only to PCI controller drivers, not to other + device drivers. + + The PCI API for device drivers will remain largely unchanged, most drivers + will require no changes at all, and all modifications will be limited to + changing the pci_controlle into instance*. + +III) Analysis of in-tree drivers +-------------------------------- + + A) drivers in drivers/pci/ + -------------------------- + + 1) pci_indirect.c + ----------------- + Shared driver for indirect PCI bridges, several CONFIG macros - will + require significant cleanup. + + 2) pci_ixp.c + ------------ + Standard driver, specifies all read/write functions separately. + + 3) pci_sh4.c + ------------ + Shared init function for SH4 drivers, uses dword for read/write ops. + + 4) pci_sh7751.c + --------------- + Standard driver, uses SH4 shared init. + + 5) pci_sh7780.c + --------------- + Standard driver, uses SH4 shared init. + + 6) tsi108_pci.c + --------------- + Standard driver, uses dword for read/write ops. + + 7) fsl_pci_init.c + ----------------- + Driver for PCI and PCI-e, uses indirect functions. + + 8) pci_ftpci100.c + ----------------- + Standard driver, uses indirect functions, has separate scan/setup + functions. + + B) driver in arch/ + ------------------ + + 1) x86/lib/pci_type1.c + ---------------------- + Standard driver, specifies all read/write functions separately. + + 2) m68k/cpu/mcf5445x/pci.c + -------------------------- + Standard driver, specifies all read/write functions separately. + + 3) m68k/cpu/mcf547x_8x/pci.c + ---------------------------- + Standard driver, specifies all read/write functions separately. + + 4) powerpc/cpu/mpc824x/pci.c + ---------------------------- + Standard driver, uses indirect functions, does not setup HW. + + 5) powerpc/cpu/mpc8260/pci.c + ---------------------------- + Standard driver, uses indirect functions. + + 6) powerpc/cpu/ppc4xx/4xx_pci.c + ------------------------------- + Standard driver, uses indirect functions. + + 7) powerpc/cpu/ppc4xx/4xx_pcie.c + -------------------------------- + PCI-e driver, specifies all read/write functions separately. + + 8) powerpc/cpu/mpc83xx/pci.c + ---------------------------- + Standard driver, uses indirect functions. + + 9) powerpc/cpu/mpc83xx/pcie.c + ----------------------------- + PCI-e driver, specifies all read/write functions separately. + + 10) powerpc/cpu/mpc5xxx/pci_mpc5200.c + ------------------------------------- + Standard driver, uses dword for read/write ops. + + 11) powerpc/cpu/mpc512x/pci.c + ----------------------------- + Standard driver, uses indirect functions. + + 12) powerpc/cpu/mpc8220/pci.c + ----------------------------- + Standard driver, specifies all read/write functions separately. + + 13) powerpc/cpu/mpc85xx/pci.c + ----------------------------- + Standard driver, uses indirect functions, has two busses. + + C) drivers in board/ + -------------------- + + 1) eltec/elppc/pci.c + -------------------- + Standard driver, uses indirect functions. + + 2) amirix/ap1000/pci.c + ---------------------- + Standard driver, specifies all read/write functions separately. + + 3) prodrive/p3mx/pci.c + ---------------------- + Standard driver, uses dword for read/write ops, has two busses. + + 4) esd/cpci750/pci.c + -------------------- + Standard driver, uses dword for read/write ops, has two busses. + + 5) esd/common/pci.c + ------------------- + Standard driver, uses dword for read/write ops. + + 6) dave/common/pci.c + -------------------- + Standard driver, uses dword for read/write ops. + + 7) ppmc7xx/pci.c + ---------------- + Standard driver, uses indirect functions. + + 8) pcippc2/cpc710_pci.c + ----------------------- + Standard driver, uses indirect functions, has two busses. + + 9) Marvell/db64360/pci.c + ------------------------ + Standard driver, uses dword for read/write ops, has two busses. + + 10) Marvell/db64460/pci.c + ------------------------- + Standard driver, uses dword for read/write ops, has two busses. + + 11) evb64260/pci.c + ------------------ + Standard driver, uses dword for read/write ops, has two busses. + + 12) armltd/integrator/pci.c + --------------------------- + Standard driver, specifies all read/write functions separately. + + All drivers will be moved to drivers/pci. Several drivers seem + similar/identical, especially those located under board, and may be merged + into one. diff --git a/doc/driver-model/UDM-pcmcia.txt b/doc/driver-model/UDM-pcmcia.txt new file mode 100644 index 0000000..fc31461 --- /dev/null +++ b/doc/driver-model/UDM-pcmcia.txt @@ -0,0 +1,78 @@ +The U-Boot Driver Model Project +=============================== +PCMCIA analysis +=============== +Viktor Krivak <viktor.krivak@gmail.com> +2012-03-17 + +I) Overview +----------- + + U-boot implements only 2 methods to interoperate with pcmcia. One to turn + device on and other to turn device off. Names of these methods are usually + pcmcia_on() and pcmcia_off() without any parameters. Some files in driver + directory implements only internal API. These methods aren't used outside + driver directory and they are not converted to new driver model. + +II) Approach +----------- + + 1) New API + ---------- + + Current API is preserved and all internal methods are hiden. + + struct ops { + void (*pcmcia_on)(struct instance *i); + void (*pcmcia_off)(struct instance *i); + } + + 2) Conversion + ------------- + + In header file pcmcia.h are some other variables which are used for + additional configuration. But all have to be moved to platform data or to + specific driver implementation. + + 3) Platform data + ---------------- + + Many boards have custom implementation of internal API. Pointers to these + methods are stored in platform_data. But the most implementations for Intel + 82365 and compatible PC Card controllers and Yenta-compatible + PCI-to-CardBus controllers implement whole API per board. In these cases + pcmcia_on() and pcmcia_off() behave only as wrappers and call specific + board methods. + +III) Analysis of in-tree drivers +-------------------------------- + + 1) i82365.c + ----------- + Driver methods have different name i82365_init() and i82365_exit but + all functionality is the same. Board files board/atc/ti113x.c and + board/cpc45/pd67290.c use their own implementation of these method. + In this case all methods in driver behave only as wrappers. + + 2) marubun_pcmcia.c + ------------------- + Meets standard API behaviour. Simple conversion. + + 3) mpc8xx_pcmcia.c + ------------------ + Meets standard API behaviour. Simple conversion. + + 4) rpx_pcmcia.c + --------------- + Implements only internal API used in other drivers. Non of methods + implemented here are used outside driver model. + + 5) ti_pci1410a.c + ---------------- + Has different API but methods in this file are never called. Probably + dead code. + + 6)tqm8xx_pcmcia.c + ----------------- + Implements only internal API used in other drivers. Non of methods + implemented here are used outside driver model. diff --git a/doc/driver-model/UDM-power.txt b/doc/driver-model/UDM-power.txt new file mode 100644 index 0000000..9ac1a5f --- /dev/null +++ b/doc/driver-model/UDM-power.txt @@ -0,0 +1,88 @@ +The U-Boot Driver Model Project +=============================== +POWER analysis +============== +Viktor Krivak <viktor.krivak@gmail.com> +2012-03-09 + +I) Overview +----------- + + 1) Actual state + --------------- + + At this moment power doesn't contain API. There are many methods for + initialization of some board specific functions but only few does what is + expected. Basically only one file contains something meaningful for this + driver. + + 2) Current implementation + ------------------------- + + In file twl6030.c are methods twl6030_stop_usb_charging() and + twl6030_start_usb_charging() for start and stop charging from USB. There are + also methods to get information about battery state and initialization of + battery charging. Only these methods are used in converted API. + + +II) Approach +------------ + + 1) New API + ---------- + + New API implements only functions specific for managing power. All board + specific init methods are moved to other files. Name of methods are + self-explanatory. + + struct ops { + void (*start_usb_charging)(struct instance *i); + void (*stop_usb_charging)(struct instance *i); + int (*get_battery_current)(struct instance *i); + int (*get_battery_voltage)(struct instance *i); + void (*init_battery_charging)(struct instance *i); + } + + 2) Conversions of other methods + ------------------------------- + + Methods that can't be converted to new API are moved to board file or to + special file for board hacks. + +III) Analysis of in-tree drivers +-------------------------------- + + 1) ftpmu010.c + ------------- + All methods of this file are moved to another location. + void ftpmu010_32768osc_enable(void): Move to boards hacks + void ftpmu010_mfpsr_select_dev(unsigned int dev): Move to board file + arch/nds32/lib/board.c + void ftpmu010_mfpsr_diselect_dev(unsigned int dev): Dead code + void ftpmu010_dlldis_disable(void): Dead code + void ftpmu010_sdram_clk_disable(unsigned int cr0): Move to board file + arch/nds32/lib/board.c + void ftpmu010_sdramhtc_set(unsigned int val): Move to board file + arch/nds32/lib/board.c + + 2) twl4030.c + ------------ + All methods of this file are moved to another location. + void twl4030_power_reset_init(void): Move to board hacks + void twl4030_pmrecv_vsel_cfg(u8 vsel_reg, u8 vsel_val, u8 dev_grp, + u8 dev_grp_sel): Move to board hacks + void twl4030_power_init(void): Move to board hacks + void twl4030_power_mmc_init(void): Move to board hacks + + 3) twl6030.c + ------------ + Some methods are converted to new API and rest are moved to another location. + void twl6030_stop_usb_charging(void): Convert to new API + void twl6030_start_usb_charging(void): Convert to new API + int twl6030_get_battery_current(void): Convert to new API + int twl6030_get_battery_voltage(void): Convert to new API + void twl6030_init_battery_charging(void): Convert to new API + void twl6030_power_mmc_init(): Move to board file + drivers/mmc/omap_hsmmc.c + void twl6030_usb_device_settings(): Move to board file + drivers/usb/musb/omap3.c diff --git a/doc/driver-model/UDM-rtc.txt b/doc/driver-model/UDM-rtc.txt new file mode 100644 index 0000000..5d9fb33 --- /dev/null +++ b/doc/driver-model/UDM-rtc.txt @@ -0,0 +1,258 @@ +============================= +RTC device subsystem analysis +============================= + +Tomas Hlavacek <tmshlvck@gmail.com> +2012-03-10 + +I) Overview +----------- + +U-Boot currently implements one common API for RTC devices. The interface +is defined in include/rtc.h and comprises of functions and structures: + + struct rtc_time { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; + }; + + int rtc_get (struct rtc_time *); + int rtc_set (struct rtc_time *); + void rtc_reset (void); + +The functions are implemented by a proper device driver in drivers/rtc +directory and the driver to be compiled in is selected in a Makefile. +Drivers are mutually exclusive. + +Drivers depends on date code in drivers/rtc/date.c and naturally on board +specific data. + +II) Approach +------------ + + 1) New API + ---------- + In the UDM each rtc driver would register itself by a function + + int rtc_device_register(struct instance *i, + struct rtc_device_ops *o); + + The structure being defined as follows: + + struct rtc_device_ops { + int (*get_time)(struct instance *i, struct rtc_time *t); + int (*set_time)(struct instance *i, struct rtc_time *t); + int (*reset)(struct instance *i); + }; + + + 2) Conversion thougths + ---------------------- + U-Boot RTC drivers exports the same functions and therefore the conversion + of the drivers is straight-forward. There is no initialization needed. + + +III) Analysis of in-tree drivers +-------------------------------- + + 1) drivers/rtc/rv3029.c + ----------------------- + The driver is standard rtc. Simple conversion is possible. + + + 2) drivers/rtc/s3c24x0_rtc.c + ---------------------------- + The driver is standard rtc. Simple conversion is possible. + + + 3) drivers/rtc/pt7c4338.c + ------------------------- + The driver is standard rtc. Simple conversion is possible. + + + 4) drivers/rtc/mvrtc.c + ---------------------- + The driver is standard rtc. Simple conversion is possible. + + + 5) drivers/rtc/ftrtc010.c + ------------------------- + The driver is standard rtc. Simple conversion is possible. + + + 6) drivers/rtc/mpc5xxx.c + ------------------------ + The driver is standard rtc. Simple conversion is possible. + + + 7) drivers/rtc/ds164x.c + ----------------------- + The driver is standard rtc. Simple conversion is possible. + + + 8) drivers/rtc/rs5c372.c + ------------------------ + The driver is standard rtc. Simple conversion is possible. + + + 9) drivers/rtc/m41t94.c + ----------------------- + The driver is standard rtc. Simple conversion is possible. + + + 10) drivers/rtc/mc13xxx-rtc.c + ----------------------------- + The driver is standard rtc. Simple conversion is possible. + + + 11) drivers/rtc/mcfrtc.c + ------------------------ + The driver is standard rtc. Simple conversion is possible. + + + 12) drivers/rtc/davinci.c + ------------------------- + The driver is standard rtc. Simple conversion is possible. + + + 13) drivers/rtc/rx8025.c + ------------------------ + The driver is standard rtc. Simple conversion is possible. + + + 14) drivers/rtc/bfin_rtc.c + -------------------------- + The driver is standard rtc. Simple conversion is possible. + + + 15) drivers/rtc/m41t62.c + ------------------------ + The driver is standard rtc. Simple conversion is possible. + + + 16) drivers/rtc/ds1306.c + ------------------------ + The driver is standard rtc. Simple conversion is possible. + + + 17) drivers/rtc/mpc8xx.c + ------------------------ + The driver is standard rtc. Simple conversion is possible. + + + 18) drivers/rtc/ds3231.c + ------------------------ + The driver is standard rtc. Simple conversion is possible. + + + 19) drivers/rtc/ds12887.c + ------------------------- + The driver is standard rtc. Simple conversion is possible. + + + 20) drivers/rtc/ds1302.c + ------------------------ + The driver is standard rtc. Simple conversion is possible. + + + 21) drivers/rtc/ds1374.c + ------------------------ + The driver is standard rtc. Simple conversion is possible. + + + 22) drivers/rtc/ds174x.c + ------------------------ + The driver is standard rtc. Simple conversion is possible. + + + 23) drivers/rtc/m41t60.c + ------------------------ + The driver is standard rtc. Simple conversion is possible. + + + 24) drivers/rtc/m48t35ax.c + -------------------------- + The driver is standard rtc. Simple conversion is possible. + + + 25) drivers/rtc/pl031.c + ----------------------- + The driver is standard rtc. Simple conversion is possible. + + + 26) drivers/rtc/x1205.c + ----------------------- + The driver is standard rtc. Simple conversion is possible. + + + 27) drivers/rtc/m41t11.c + ------------------------ + The driver is standard rtc. Simple conversion is possible. + + + 28) drivers/rtc/pcf8563.c + ------------------------- + The driver is standard rtc. Simple conversion is possible. + + + 29) drivers/rtc/mk48t59.c + ------------------------- + Macros needs cleanup. Besides that the driver is standard rtc. + Simple conversion is possible. + + + 30) drivers/rtc/mxsrtc.c + ------------------------ + The driver is standard rtc. Simple conversion is possible. + + + 31) drivers/rtc/ds1307.c + ------------------------ + The driver is standard rtc. Simple conversion is possible. + + + 32) drivers/rtc/ds1556.c + ------------------------ + The driver is standard rtc. Simple conversion is possible. + + + 33) drivers/rtc/rtc4543.c + ------------------------- + The driver is standard rtc. Simple conversion is possible. + + + 34) drivers/rtc/s3c44b0_rtc.c + ----------------------------- + The driver is standard rtc. Simple conversion is possible. + + + 35) drivers/rtc/ds1337.c + ------------------------ + The driver is standard rtc. Simple conversion is possible. + + + 36) drivers/rtc/isl1208.c + ------------------------- + The driver is standard rtc. Simple conversion is possible. + + + 37) drivers/rtc/max6900.c + ------------------------- + The driver is standard rtc. Simple conversion is possible. + + + 38) drivers/rtc/mc146818.c + -------------------------- + The driver is standard rtc. Simple conversion is possible. + + + 39) drivers/rtc/at91sam9_rtt.c + ------------------------------ + The driver is standard rtc. Simple conversion is possible. diff --git a/doc/driver-model/UDM-serial.txt b/doc/driver-model/UDM-serial.txt new file mode 100644 index 0000000..e9c274d --- /dev/null +++ b/doc/driver-model/UDM-serial.txt @@ -0,0 +1,191 @@ +The U-Boot Driver Model Project +=============================== +Serial I/O analysis +=================== +Marek Vasut <marek.vasut@gmail.com> +2012-02-20 + +I) Overview +----------- + +The serial port support currently requires the driver to export the following +functions: + + serial_putc() ...... Output a character + serial_puts() ...... Output string, often done using serial_putc() + serial_tstc() ...... Test if incoming character is in a buffer + serial_getc() ...... Retrieve incoming character + serial_setbrg() .... Configure port options + serial_init() ...... Initialize the hardware + +The simpliest implementation, supporting only one port, simply defines these six +functions and calls them. Such calls are scattered all around U-Boot, especiall +serial_putc(), serial_puts(), serial_tstc() and serial_getc(). The serial_init() +and serial_setbrg() are often called from platform-dependent places. + +It's important to consider current implementation of CONFIG_SERIAL_MULTI though. +This resides in common/serial.c and behaves as a multiplexer for serial ports. +This, by calling serial_assign(), allows user to switch I/O from one serial port +to another. Though the environmental variables "stdin", "stdout", "stderr" +remain set to "serial". + +These variables are managed by the IOMUX. This resides in common/iomux.c and +manages all console input/output from U-Boot. For serial port, only one IOMUX is +always registered, called "serial" and the switching of different serial ports +is done by code in common/serial.c. + +On a final note, it's important to mention function default_serial_console(), +which is platform specific and reports the default serial console for the +platform, unless proper environment variable overrides this. + +II) Approach +------------ + +Drivers not using CONFIG_SERIAL_MULTI already will have to be converted to +similar approach. The probe() function of a driver will call a function +registering the driver with a STDIO subsystem core, stdio_device_register(). + +The serial_init() function will now be replaced by probe() function of the +driver, the rest of the components of the driver will be converted to standard +STDIO driver calls. See [ UDM-stdio.txt ] for details. + +The serial_setbrg() function depends on global data pointer. This is wrong, +since there is likely to be user willing to configure different baudrate on two +different serial ports. The function will be replaced with STDIO's "conf()" +call, with STDIO_CONFIG_SERIAL_BAUDRATE argument. + +III) Analysis of in-tree drivers +-------------------------------- + + 1) altera_jtag_uart.c + --------------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 2) altera_uart.c + ---------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 3) arm_dcc.c + ------------ + No support for CONFIG_SERIAL_MULTI. Simple conversion possible, unless used + with CONFIG_ARM_DCC_MULTI. Then it registers another separate IOMUX. + + 4) atmel_usart.c + ---------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 5) mcfuart.c + ------------ + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 6) ns16550.c + ------------ + This driver seems complicated and certain consideration will need to be made + during conversion. This driver is implemented in very universal manner, + therefore it'll be necessary to properly design it's platform_data. + + 7) ns9750_serial.c + ------------------ + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 8) opencores_yanu.c + ------------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 9) s3c4510b_uart.c + ------------------ + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 10) s3c64xx.c + ------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 11) sandbox.c + ------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 12) serial.c + ------------ + This is a complementary part of NS16550 UART driver, see above. + + 13) serial_clps7111.c + --------------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 14) serial_imx.c + ---------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. This driver + might be removed in favor of serial_mxc.c . + + 15) serial_ixp.c + ---------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 16) serial_ks8695.c + ------------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 17) serial_lh7a40x.c + -------------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 18) serial_lpc2292.c + -------------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 19) serial_max3100.c + -------------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 20) serial_mxc.c + ---------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 21) serial_netarm.c + ------------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 22) serial_pl01x.c + ------------------ + No support for CONFIG_SERIAL_MULTI. Simple conversion possible, though this + driver in fact contains two drivers in total. + + 23) serial_pxa.c + ---------------- + This driver is a bit complicated, but due to clean support for + CONFIG_SERIAL_MULTI, there are no expected obstructions throughout the + conversion process. + + 24) serial_s3c24x0.c + -------------------- + This driver, being quite ad-hoc might need some work to bring back to shape. + + 25) serial_s3c44b0.c + -------------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 26) serial_s5p.c + ---------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 27) serial_sa1100.c + ------------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 28) serial_sh.c + --------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 29) serial_xuartlite.c + ---------------------- + No support for CONFIG_SERIAL_MULTI. Simple conversion possible. + + 30) usbtty.c + ------------ + This driver seems very complicated and entangled with USB framework. The + conversion might be complicated here. + + 31) arch/powerpc/cpu/mpc512x/serial.c + ------------------------------------- + This driver supports CONFIG_SERIAL_MULTI. This driver will need to be moved to + proper place. diff --git a/doc/driver-model/UDM-spi.txt b/doc/driver-model/UDM-spi.txt new file mode 100644 index 0000000..7442a32 --- /dev/null +++ b/doc/driver-model/UDM-spi.txt @@ -0,0 +1,200 @@ +The U-Boot Driver Model Project +=============================== +SPI analysis +============ +Viktor Krivak <viktor.krivak@gmail.com> +2012-03-03 + +I) Overview +----------- + + 1) The SPI driver + ----------------- + + At this moment U-Boot provides standard API that consist of 7 functions: + + void spi_init(void); + struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode); + void spi_free_slave(struct spi_slave *slave); + int spi_claim_bus(struct spi_slave *slave); + void spi_release_bus(struct spi_slave *slave); + int spi_xfer(struct spi_slave *slave, unsigned int bitlen, + const void *dout, void *din, unsigned long flags); + int spi_cs_is_valid(unsigned int bus, unsigned int cs); + void spi_cs_activate(struct spi_slave *slave); + void spi_cs_deactivate(struct spi_slave *slave); + void spi_set_speed(struct spi_slave *slave, uint hz); + + Method spi_init() is usually empty. All necessary configuration are sets by + spi_setup_slave(). But this configuration is usually stored only in memory. + No real hardware sets are made. All hardware settings are provided by method + spi_claim_bus(). This method claims the bus and it can't be claimed again + until it's release. That's mean all calls of method spi_claim_bus() will + fail. But lots of cpu implementation don't meet this behaviour. + Method spi_release_bus() does exact opposite. It release bus directly by + some hardware sets. spi_free_slave() only free memory allocated by + spi_setup_slave(). Method spi_xfer() do actually read and write operation + throw specified bus and cs. Other methods are self explanatory. + + 2) Current limitations + ---------------------- + + Theoretically at this moment api allows use more then one bus per device at + the time. But in real this can be achieved only when all buses have their + own base addresses in memory. + + +II) Approach +------------ + + 1) Claiming bus + --------------- + + The current api cannot be used because struct spi_slave have to be in + private data. In that case user are prohibited to use different bus on one + device at same time. But when base memory address for bus are different. + It's possible make more instance of this driver. Otherwise it can't can be + done because of hardware limitation. + + 2) API change + ------------- + + Method spi_init() is moved to probe. Methods spi_setup_slave() and + spi_claim_bus() are joined to one method. This method checks if desired bus + exists and is available then configure necessary hardware and claims bus. + Method spi_release_bus() and spi_free_slave() are also joined to meet this + new approach. Other function remain same. Only struct spi_slave was change + to instance. + + struct ops { + int (*spi_request_bus)(struct instance *i, unsigned int bus, + unsigned int cs, unsigned int max_hz, + unsigned int mode); + void (*spi_release_bus)(struct instance *i); + int (*spi_xfer) (struct instance *i, unsigned int bitlen, + const void *dout, void *din, unsigned long flags); + int (*spi_cs_is_valid)(struct instance *i, unsigned int bus, + unsigned int cs); + void (*spi_cs_activate)(struct instance *i); + void (*spi_cs_deactivate)(struct instance *i); + void (*spi_set_speed)(struct instance *i, uint hz); + } + + 3) Legacy API + ------------- + + To easy conversion of the whole driver. Original and new api can exist next + to each other. New API is designed to be only a wrapper that extracts + necessary information from private_data and use old api. When driver can + use more than one bus at the time. New API require multiple instance. One + for each bus. In this case spi_slave have to be copied in each instance. + + 4) Conversion TIME-LINE + ----------------------- + + To prevent build corruption api conversion have to be processed in several + independent steps. In first step all old API methods are renamed. After that + new API and core function are implemented. Next step is conversion of all + board init methods to set platform data. After all these steps it is possible + to start conversion of all remaining calls. This procedure guarantees that + build procedure and binaries are never broken. + +III) Analysis of in-tree drivers +-------------------------------- + + 1) altera_spi.c + --------------- + All methods have designated structure. Simple conversion possible. + + 2) andes_spi.c + -------------- + All methods have designated structure. Simple conversion possible. + + 3) andes_spi.h + -------------- + Support file for andes_spi.c. No conversion is needed. + + 4) armada100_spi.c + ------------------ + All methods have designated structure. Simple conversion possible. + + 5) atmel_dataflash_spi.c + ------------------------ + Wrong placement. Will be moved to another location. + + 6) atmel_spi.c + -------------- + Supports more than one bus. Need some minor change. + + 7) atmel_spi.h + -------------- + Support file for andes_spi.c. No conversion is needed. + + 8) bfin_spi.c + ------------- + Supports more than one bus. Need some minor change. + + 9) cf_spi.c + ----------- + Cooperate with some cpu specific methods from other files. Hard conversion. + + 10) davinci_spi.c + ----------------- + All methods have designated structure. Simple conversion possible. + + 11) davinci_spi.h + ----------------- + Support file for davinci_spi.h. No conversion is needed. + + 12) fsl_espi.c + -------------- + All methods have designated structure. Simple conversion possible. + + 13) kirkwood_spi.c + ------------------ + All methods have designated structure. Simple conversion possible. + + 14) mpc8xxx_spi.c + ----------------- + All methods have designated structure. Simple conversion possible. + + 15) mpc52xx_spi.c + ----------------- + All methods have designated structure. Simple conversion possible. + + 16) mxc_spi.c + ------------- + All methods have designated structure. Simple conversion possible. + + 17) mxs_spi.c + ------------- + All methods have designated structure. Simple conversion possible. + + 18) oc_tiny_spi.c + ----------------- + Supports more than one bus. Need some minor change. + + 19) omap3_spi.c + --------------- + Supports more than one bus. Need some minor change. + + 20) omap3_spi.h + --------------- + Support file for omap3_spi.c. No conversion is needed. + + 21) sh_spi.c + ------------ + All methods have designated structure. Simple conversion possible. + + 22) sh_spi.h + ------------ + Support file for sh_spi.h. No conversion is needed. + + 23) soft_spi.c + -------------- + Use many board specific method linked from other files. Need careful debugging. + + 24) tegra2_spi.c + ---------------- + Some hardware specific problem when releasing bus. diff --git a/doc/driver-model/UDM-stdio.txt b/doc/driver-model/UDM-stdio.txt new file mode 100644 index 0000000..a6c484f --- /dev/null +++ b/doc/driver-model/UDM-stdio.txt @@ -0,0 +1,191 @@ +The U-Boot Driver Model Project +=============================== +I/O system analysis +=================== +Marek Vasut <marek.vasut@gmail.com> +2012-02-20 + +I) Overview +----------- + +The console input and output is currently done using the STDIO subsystem in +U-Boot. The design of this subsystem is already flexible enough to be easily +converted to new driver model approach. Minor changes will need to be done +though. + +Each device that wants to register with STDIO subsystem has to define struct +stdio_dev, defined in include/stdio_dev.h and containing the following fields: + +struct stdio_dev { + int flags; /* Device flags: input/output/system */ + int ext; /* Supported extensions */ + char name[16]; /* Device name */ + +/* GENERAL functions */ + + int (*start) (void); /* To start the device */ + int (*stop) (void); /* To stop the device */ + +/* OUTPUT functions */ + + void (*putc) (const char c); /* To put a char */ + void (*puts) (const char *s); /* To put a string (accelerator) */ + +/* INPUT functions */ + + int (*tstc) (void); /* To test if a char is ready... */ + int (*getc) (void); /* To get that char */ + +/* Other functions */ + + void *priv; /* Private extensions */ + struct list_head list; +}; + +Currently used flags are DEV_FLAGS_INPUT, DEV_FLAGS_OUTPUT and DEV_FLAGS_SYSTEM, +extensions being only one, the DEV_EXT_VIDEO. + +The private extensions are now used as a per-device carrier of private data and +finally list allows this structure to be a member of linked list of STDIO +devices. + +The STDIN, STDOUT and STDERR routing is handled by environment variables +"stdin", "stdout" and "stderr". By configuring the variable to the name of a +driver, functions of such driver are called to execute that particular +operation. + +II) Approach +------------ + + 1) Similarity of serial, video and keyboard drivers + --------------------------------------------------- + + All of these drivers can be unified under the STDIO subsystem if modified + slightly. The serial drivers basically define both input and output functions + and need function to configure baudrate. The keyboard drivers provide only + input. On the other hand, video drivers provide output, but need to be + configured in certain way. This configuration might be dynamic, therefore the + STDIO has to be modified to provide such flexibility. + + 2) Unification of serial, video and keyboard drivers + ---------------------------------------------------- + + Every STDIO device would register a structure containing operation it supports + with the STDIO core by calling: + + int stdio_device_register(struct instance *i, struct stdio_device_ops *o); + + The structure being defined as follows: + + struct stdio_device_ops { + void (*putc)(struct instance *i, const char c); + void (*puts)(struct instance *i, const char *s); /* OPTIONAL */ + + int (*tstc)(struct instance *i); + int (*getc)(struct instance *i); + + int (*init)(struct instance *i); + int (*exit)(struct instance *i); + int (*conf)(struct instance *i, enum stdio_config c, const void *data); + }; + + The "putc()" function will emit a character, the "puts()" function will emit a + string. If both of these are set to NULL, the device is considered STDIN only, + aka input only device. + + The "getc()" retrieves a character from a STDIN device, while "tstc()" tests + if there is a character in the buffer of STDIN device. In case these two are + set to NULL, this device is STDOUT / STDERR device. + + Setting all "putc()", "puts()", "getc()" and "tstc()" calls to NULL isn't an + error condition, though such device does nothing. By instroducing tests for + these functions being NULL, the "flags" and "ext" fields from original struct + stdio_dev can be eliminated. + + The "init()" and "exit()" calls are replacement for "start()" and "exit()" + calls in the old approach. The "priv" part of the old struct stdio_dev will be + replaced by common private data in the driver model and the struct list_head + list will be eliminated by introducing common STDIO core, that tracks all the + STDIO devices. + + Lastly, the "conf()" call will allow the user to configure various options of + the driver. The enum stdio_config contains all possible configuration options + available to the STDIO devices, const void *data being the argument to be + configured. Currently, the enum stdio_config will contain at least the + following options: + + enum stdio_config { + STDIO_CONFIG_SERIAL_BAUDRATE, + }; + + 3) Transformation of stdio routing + ---------------------------------- + + By allowing multiple instances of drivers, the environment variables "stdin", + "stdout" and "stderr" can no longer be set to the name of the driver. + Therefore the STDIO core, tracking all of the STDIO devices in the system will + need to have a small amount of internal data for each device: + + struct stdio_device_node { + struct instance *i; + struct stdio_device_ops *ops; + uint8_t id; + uint8_t flags; + struct list_head list; + } + + The "id" is the order of the instance of the same driver. The "flags" variable + allows multiple drivers to be used at the same time and even for different + purpose. The following flags will be defined: + + STDIO_FLG_STDIN ..... This device will be used as an input device. All input + from all devices with this flag set will be received + and passed to the upper layers. + STDIO_FLG_STDOUT .... This device will be used as an output device. All + output sent to stdout will be routed to all devices + with this flag set. + STDIO_FLG_STDERR .... This device will be used as an standard error output + device. All output sent to stderr will be routed to + all devices with this flag set. + + The "list" member of this structure allows to have a linked list of all + registered STDIO devices. + +III) Analysis of in-tree drivers +-------------------------------- + +For in-depth analysis of serial port drivers, refer to [ UDM-serial.txt ]. +For in-depth analysis of keyboard drivers, refer to [ UDM-keyboard.txt ]. +For in-depth analysis of video drivers, refer to [ UDM-video.txt ]. + + 1) arch/blackfin/cpu/jtag-console.c + ----------------------------------- + This driver is a classic STDIO driver, no problem with conversion is expected. + + 2) board/mpl/pati/pati.c + ------------------------ + This driver registers with the STDIO framework, though it uses a lot of ad-hoc + stuff which will need to be sorted out. + + 3) board/netphone/phone_console.c + --------------------------------- + This driver is a classic STDIO driver, no problem with conversion is expected. + + 4) drivers/net/netconsole.c + --------------------------- + This driver is a classic STDIO driver, no problem with conversion is expected. + +IV) Other involved files (To be removed) +---------------------------------------- + +common/cmd_console.c +common/cmd_log.c +common/cmd_terminal.c +common/console.c +common/fdt_support.c +common/iomux.c +common/lcd.c +common/serial.c +common/stdio.c +common/usb_kbd.c +doc/README.iomux diff --git a/doc/driver-model/UDM-tpm.txt b/doc/driver-model/UDM-tpm.txt new file mode 100644 index 0000000..91a953a --- /dev/null +++ b/doc/driver-model/UDM-tpm.txt @@ -0,0 +1,48 @@ +The U-Boot Driver Model Project +=============================== +TPM system analysis +=================== +Marek Vasut <marek.vasut@gmail.com> +2012-02-23 + +I) Overview +----------- + +There is currently only one TPM chip driver available and therefore the API +controlling it is very much based on this. The API is very simple: + + int tis_open(void); + int tis_close(void); + int tis_sendrecv(const u8 *sendbuf, size_t send_size, + u8 *recvbuf, size_t *recv_len); + +The command operating the TPM chip only provides operations to send and receive +bytes from the chip. + +II) Approach +------------ + +The API can't be generalised too much considering there's only one TPM chip +supported. But it's a good idea to split the tis_sendrecv() function in two +functions. Therefore the new API will use register the TPM chip by calling: + + tpm_device_register(struct instance *i, const struct tpm_ops *ops); + +And the struct tpm_ops will contain the following members: + + struct tpm_ops { + int (*tpm_open)(struct instance *i); + int (*tpm_close)(struct instance *i); + int (*tpm_send)(const uint8_t *buf, const size_t size); + int (*tpm_recv)(uint8_t *buf, size_t *size); + }; + +The behaviour of "tpm_open()" and "tpm_close()" will basically copy the +behaviour of "tis_open()" and "tis_close()". The "tpm_send()" will be based on +the "tis_senddata()" and "tis_recv()" will be based on "tis_readresponse()". + +III) Analysis of in-tree drivers +-------------------------------- + +There is only one in-tree driver present, the "drivers/tpm/generic_lpc_tpm.c", +which will be simply converted as outlined in previous chapter. diff --git a/doc/driver-model/UDM-twserial.txt b/doc/driver-model/UDM-twserial.txt new file mode 100644 index 0000000..289416a --- /dev/null +++ b/doc/driver-model/UDM-twserial.txt @@ -0,0 +1,47 @@ +================================== +TWserial device subsystem analysis +================================== + +Tomas Hlavacek<tmshlvck@gmail.com> +2012-03-21 + +I) Overview +----------- + +U-Boot currently implements one common API for TWSerial devices. The interface +is defined in include/tws.h and comprises of functions: + + int tws_read(uchar *buffer, int len); + int tws_write(uchar *buffer, int len); + +The functions are implemented by a proper device driver in drivers/twserial +directory and the driver to be compiled in is selected in a Makefile. There is +only one driver present now. + +The driver depends on ad-hoc code in board specific data, namely functions: + + void tws_ce(unsigned bit); + void tws_wr(unsigned bit); + void tws_clk(unsigned bit); + void tws_data(unsigned bit); + unsigned tws_data_read(void); + void tws_data_config_output(unsigned output); + +implemented in include/configs/inka4x0.h . + +II) Approach +------------ + + U-Boot TWserial drivers exports two simple functions and therefore the conversion + of the driver and creating a core for it is not needed. It should be consolidated + with include/configs/inka4x0.h and taken to the misc/ dir. + + +III) Analysis of in-tree drivers +-------------------------------- + + 1) drivers/twserial/soft_tws.c + ------------------------------ + The driver is the only TWserial driver. The ad-hoc part in + include/configs/inka4x0.h and the core soft_tws driver should be consolidated + to one compact driver and moved to misc/ . diff --git a/doc/driver-model/UDM-usb.txt b/doc/driver-model/UDM-usb.txt new file mode 100644 index 0000000..5ce85b5 --- /dev/null +++ b/doc/driver-model/UDM-usb.txt @@ -0,0 +1,94 @@ +The U-Boot Driver Model Project +=============================== +USB analysis +============ +Marek Vasut <marek.vasut@gmail.com> +2012-02-16 + +I) Overview +----------- + + 1) The USB Host driver + ---------------------- + There are basically four or five USB host drivers. All such drivers currently + provide at least the following fuctions: + + usb_lowlevel_init() ... Do the initialization of the USB controller hardware + usb_lowlevel_stop() ... Do the shutdown of the USB controller hardware + + usb_event_poll() ...... Poll interrupt from USB device, often used by KBD + + submit_control_msg() .. Submit message via Control endpoint + submit_int_msg() ...... Submit message via Interrupt endpoint + submit_bulk_msg() ..... Submit message via Bulk endpoint + + + This allows for the host driver to be easily abstracted. + + 2) The USB hierarchy + -------------------- + + In the current implementation, the USB Host driver provides operations to + communicate via the USB bus. This is realised by providing access to a USB + root port to which an USB root hub is attached. The USB bus is scanned and for + each newly found device, a struct usb_device is allocated. See common/usb.c + and include/usb.h for details. + +II) Approach +------------ + + 1) The USB Host driver + ---------------------- + + Converting the host driver will follow the classic driver model consideration. + Though, the host driver will have to call a function that registers a root + port with the USB core in it's probe() function, let's call this function + + usb_register_root_port(&ops); + + This will allow the USB core to track all available root ports. The ops + parameter will contain structure describing operations supported by the root + port: + + struct usb_port_ops { + void (*usb_event_poll)(); + int (*submit_control_msg)(); + int (*submit_int_msg)(); + int (*submit_bulk_msg)(); + } + + 2) The USB hierarchy and hub drivers + ------------------------------------ + + Converting the USB heirarchy should be fairy simple, considering the already + dynamic nature of the implementation. The current usb_hub_device structure + will have to be converted to a struct instance. Every such instance will + contain components of struct usb_device and struct usb_hub_device in it's + private data, providing only accessors in order to properly encapsulate the + driver. + + By registering the root port, the USB framework will instantiate a USB hub + driver, which is always present, the root hub. The root hub and any subsequent + hub instance is represented by struct instance and it's private data contain + amongst others common bits from struct usb_device. + + Note the USB hub driver is partly defying the usual method of registering a + set of callbacks to a particular core driver. Instead, a static set of + functions is defined and the USB hub instance is passed to those. This creates + certain restrictions as of how the USB hub driver looks, but considering the + specification for USB hub is given and a different type of USB hub won't ever + exist, this approach is ok: + + - Report how many ports does this hub have: + uint get_nr_ports(struct instance *hub); + - Get pointer to device connected to a port: + struct instance *(*get_child)(struct instance *hub, int port); + - Instantiate and configure device on port: + struct instance *(*enum_dev_on_port)(struct instance *hub, int port); + + 3) USB device drivers + --------------------- + + The USB device driver, in turn, will have to register various ops structures + with certain cores. For example, USB disc driver will have to register it's + ops with core handling USB discs etc. diff --git a/doc/driver-model/UDM-video.txt b/doc/driver-model/UDM-video.txt new file mode 100644 index 0000000..342aeee --- /dev/null +++ b/doc/driver-model/UDM-video.txt @@ -0,0 +1,74 @@ +The U-Boot Driver Model Project +=============================== +Video output analysis +===================== +Marek Vasut <marek.vasut@gmail.com> +2012-02-20 + +I) Overview +----------- + +The video drivers are most often registered with video subsystem. This subsystem +often expects to be allowed access to framebuffer of certain parameters. This +subsystem also provides calls for STDIO subsystem to allow it to output +characters on the screen. For this part, see [ UDM-stdio.txt ]. + +Therefore the API has two parts, the video driver part and the part where the +video driver core registers with STDIO API. + +The video driver part will follow the current cfb_console approach, though +allowing it to be more dynamic. + +II) Approach +------------ + +Registering the video driver into the video driver core is done by calling the +following function from the driver probe() function: + + video_device_register(struct instance *i, GraphicDevice *gd); + +Because the video driver core is in charge or rendering characters as well as +bitmaps on the screen, it will in turn call stdio_device_register(i, so), where +"i" is the same instance as the video driver's one. But "so" will be special +static struct stdio_device_ops handling the character output. + + +III) Analysis of in-tree drivers +-------------------------------- + + 1) arch/powerpc/cpu/mpc8xx/video.c + ---------------------------------- + This driver copies the cfb_console [ see drivers/video/cfb_console.c ] + approach and acts only as a STDIO device. Therefore there are currently two + possible approaches, first being the conversion of this driver to usual STDIO + device and second, long-term one, being conversion of this driver to video + driver that provides console. + + 2) arch/x86/lib/video.c + ----------------------- + This driver registers two separate STDIO devices and should be therefore + converted as such. + + 3) board/bf527-ezkit/video.c + ---------------------------- + This driver seems bogus as it behaves as STDIO device, but provides no input + or output capabilities. It relies on DEV_EXT_VIDEO, which is no longer in use + or present otherwise than as a dead code/define. + + 4) board/bf533-stamp/video.c + ---------------------------- + This driver seems bogus as it behaves as STDIO device, but provides no input + or output capabilities. It relies on DEV_EXT_VIDEO, which is no longer in use + or present otherwise than as a dead code/define. + + 5) board/bf548-ezkit/video.c + ---------------------------- + This driver seems bogus as it behaves as STDIO device, but provides no input + or output capabilities. It relies on DEV_EXT_VIDEO, which is no longer in use + or present otherwise than as a dead code/define. + + 6) board/cm-bf548/video.c + ---------------------------- + This driver seems bogus as it behaves as STDIO device, but provides no input + or output capabilities. It relies on DEV_EXT_VIDEO, which is no longer in use + or present otherwise than as a dead code/define. diff --git a/doc/driver-model/UDM-watchdog.txt b/doc/driver-model/UDM-watchdog.txt new file mode 100644 index 0000000..271bd26 --- /dev/null +++ b/doc/driver-model/UDM-watchdog.txt @@ -0,0 +1,334 @@ +The U-Boot Driver Model Project +=============================== +Watchdog device subsystem analysis +================================== + +Tomas Hlavacek <tmshlvck@gmail.com> +2012-03-09 + +I) Overview +----------- + +U-Boot currently implements an API for HW watchdog devices as explicit drivers +in drivers/watchdog directory. There are also drivers for both hardware and +software watchdog on particular CPUs implemented in arch/*/cpu/*/cpu.c. There +are macros in include/watchdog.h that selects between SW and HW watchdog and +assembly SW implementation. + +The current common interface comprises of one set out of these two possible +variants: + + 1) + void watchdog_reset(void); + int watchdog_disable(void); + int watchdog_init(void); + + 2) + void hw_watchdog_reset(void); + void hw_watchdog_init(void); + +The watchdog implementations are also spread through board/*/*.c that in +some cases. The API and semantics is in most cases same as the above +mentioned common functions. + + +II) Approach +------------ + + 1) New API + ---------- + + In the UDM each watchdog driver would register itself by a function + + int watchdog_device_register(struct instance *i, + const struct watchdog_device_ops *o); + + The structure being defined as follows: + + struct watchdog_device_ops { + int (*disable)(struct instance *i); + void (*reset)(struct instance *i); + }; + + The watchdog_init() function will be dissolved into probe() function. + + 2) Conversion thougths + ---------------------- + + Conversion of watchdog implementations to a new API could be divided + to three subsections: a) HW implementations, which are mostly compliant + to the above mentioned API; b) SW implementations, which are compliant + to the above mentioned API and c) SW implementations that are not compliant + to the API and has to be rectified or partially rewritten. + +III) Analysis of in-tree drivers +-------------------------------- + + 1) drivers/watchdog/at91sam9_wdt.c + ---------------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 2) drivers/watchdog/ftwdt010_wdt.c + ---------------------------------- + The driver is ad-hoc HW watchdog. Conversion has to take into account + driver parts spread in include/faraday/*. Restructuring the driver and + code cleanup has to be considered. + + + 3) arch/arm/cpu/arm1136/mx31/timer.c + ------------------------------------ + The driver is semi-standard ad-hoc HW watchdog. Conversion has to take + into account driver parts spread in the timer.c file. + + + 4) arch/arm/cpu/arm926ejs/davinci/timer.c + ----------------------------------------- + The driver is ad-hoc semi-standard HW watchdog. Conversion has to take + into account driver parts spread in the timer.c file. + + + 5) arch/arm/cpu/armv7/omap-common/hwinit-common.c + ------------------------------------------------- + The driver is non-standard ad-hoc HW watchdog. Conversion is possible + but functions has to be renamed and constants moved to another places. + + + 6) arch/arm/cpu/armv7/omap3/board.c + ----------------------------------- + The driver is non-standard ad-hoc HW watchdog. Conversion is possible + but functions has to be renamed and constants moved to another places. + + + 7) arch/blackfin/cpu/watchdog.c + ------------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 8) arch/m68k/cpu/mcf523x/cpu.c + ------------------------------ + The driver is standard HW watchdog. Simple conversion is possible. + + + 9) arch/m68k/cpu/mcf52x2/cpu.c + ------------------------------ + The driver is standard HW watchdog. Simple conversion is possible. + + + 10) arch/m68k/cpu/mcf532x/cpu.c + ------------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 11) arch/m68k/cpu/mcf547x_8x/cpu.c + ---------------------------------- + The driver is standard HW watchdog (there is slight naming convention + violation that has to be rectified). Simple conversion is possible. + + + 12) arch/powerpc/cpu/74xx_7xx/cpu.c + ----------------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 13) arch/powerpc/cpu/mpc512x/cpu.c + ---------------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 14) arch/powerpc/cpu/mpc5xx/cpu.c + --------------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 15) arch/powerpc/cpu/mpc5xxx/cpu.c + ---------------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 16) arch/powerpc/cpu/mpc8260/cpu.c + ---------------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 17) arch/powerpc/cpu/mpc83xx/cpu.c + ---------------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 18) arch/powerpc/cpu/mpc85xx/cpu.c + ---------------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 19) arch/powerpc/cpu/mpc86xx/cpu.c + ---------------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 20) arch/powerpc/cpu/mpc8xx/cpu.c + + The driver is standard HW watchdog. Simple conversion is possible. + + + 21) arch/powerpc/cpu/ppc4xx/cpu.c + --------------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 22) arch/sh/cpu/sh2/watchdog.c + ------------------------------ + The driver is standard HW watchdog. Simple conversion is possible. + + + 23) arch/sh/cpu/sh3/watchdog.c + ------------------------------ + The driver is standard HW watchdog. Simple conversion is possible. + + + 24) arch/sh/cpu/sh4/watchdog.c + ------------------------------ + The driver is standard HW watchdog. Simple conversion is possible. + + + 25) board/amcc/luan/luan.c + -------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 26) board/amcc/yosemite/yosemite.c + ---------------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 27) board/apollon/apollon.c + --------------------------- + The driver is standard HW watchdog however the watchdog_init() + function is called in early initialization. Simple conversion is possible. + + + 28) board/bmw/m48t59y.c + ----------------------- + Special watchdog driver. Dead code. To be removed. + + + 29) board/davedenx/qong/qong.c + ------------------------------ + The driver is standard HW watchdog. Simple conversion is possible. + + + 30) board/dvlhost/watchdog.c + ---------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 31) board/eNET/eNET.c + --------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 32) board/eltec/elppc/elppc.c + ----------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 33) board/enbw/enbw_cmc/enbw_cmc.c + ---------------------------------- + Only function proxy call. Code cleanup needed. + + + 34) board/freescale/mx31pdk/mx31pdk.c + ------------------------------------- + Only function proxy call. Code cleanup needed. + + + 35) board/gth2/gth2.c + --------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 36) board/lwmon5/lwmon5.c + ------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 37) board/manroland/mucmc52/mucmc52.c + ------------------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 38) board/manroland/uc101/uc101.c + --------------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 39) board/mousse/m48t59y.c + -------------------------- + Special watchdog driver. Dead code. To be removed. + + + 40) board/mvblue/mvblue.c + ------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 41) board/netphone/netphone.c + ----------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 42) board/netta/netta.c + ----------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 43) board/netta2/netta2.c + ------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 44) board/omicron/calimain/calimain.c + ------------------------------------- + Only function proxy call. Code cleanup needed. + + + 45) board/pcippc2/pcippc2.c + --------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 46) board/pcs440ep/pcs440ep.c + ----------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 47) board/stx/stxxtc/stxxtc.c + ----------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 48) board/ti/omap2420h4/omap2420h4.c + ------------------------------------ + The driver is standard HW watchdog. Simple conversion is possible. + + + 49) board/ttcontrol/vision2/vision2.c + ------------------------------------- + The driver is standard HW watchdog but namespace is polluted by + non-standard macros. Simple conversion is possible, code cleanup + needed. + + + 50) board/v38b/v38b.c + --------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 51) board/ve8313/ve8313.c + ------------------------- + The driver is standard HW watchdog. Simple conversion is possible. + + + 52) board/w7o/watchdog.c + ------------------------ + The driver is standard HW watchdog. Simple conversion is possible. |