diff options
Diffstat (limited to 'doc/driver-model')
| -rw-r--r-- | doc/driver-model/UDM-block.txt | 279 | ||||
| -rw-r--r-- | doc/driver-model/UDM-cores.txt | 126 | ||||
| -rw-r--r-- | doc/driver-model/UDM-design.txt | 315 | ||||
| -rw-r--r-- | doc/driver-model/UDM-fpga.txt | 115 | ||||
| -rw-r--r-- | doc/driver-model/UDM-gpio.txt | 106 | ||||
| -rw-r--r-- | doc/driver-model/UDM-hwmon.txt | 118 | ||||
| -rw-r--r-- | doc/driver-model/UDM-keyboard.txt | 47 | ||||
| -rw-r--r-- | doc/driver-model/UDM-mmc.txt | 319 | ||||
| -rw-r--r-- | doc/driver-model/UDM-net.txt | 434 | ||||
| -rw-r--r-- | doc/driver-model/UDM-pci.txt | 265 | ||||
| -rw-r--r-- | doc/driver-model/UDM-pcmcia.txt | 78 | ||||
| -rw-r--r-- | doc/driver-model/UDM-power.txt | 88 | ||||
| -rw-r--r-- | doc/driver-model/UDM-rtc.txt | 258 | ||||
| -rw-r--r-- | doc/driver-model/UDM-serial.txt | 191 | ||||
| -rw-r--r-- | doc/driver-model/UDM-spi.txt | 200 | ||||
| -rw-r--r-- | doc/driver-model/UDM-stdio.txt | 191 | ||||
| -rw-r--r-- | doc/driver-model/UDM-tpm.txt | 48 | ||||
| -rw-r--r-- | doc/driver-model/UDM-twserial.txt | 47 | ||||
| -rw-r--r-- | doc/driver-model/UDM-usb.txt | 94 | ||||
| -rw-r--r-- | doc/driver-model/UDM-video.txt | 74 | ||||
| -rw-r--r-- | doc/driver-model/UDM-watchdog.txt | 334 | 
21 files changed, 3727 insertions, 0 deletions
| diff --git a/doc/driver-model/UDM-block.txt b/doc/driver-model/UDM-block.txt new file mode 100644 index 000000000..5d5c77601 --- /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 000000000..4e1318871 --- /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 000000000..185f477b0 --- /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 000000000..4f9df940e --- /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 000000000..8ff0a965c --- /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 000000000..cc5d529c3 --- /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 000000000..ef3761dc2 --- /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 000000000..bed430643 --- /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 000000000..e2ea8f5a6 --- /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 000000000..b65e9ea73 --- /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 000000000..fc31461ca --- /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 000000000..9ac1a5fbb --- /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 000000000..5d9fb333b --- /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 000000000..e9c274d45 --- /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 000000000..7442a32bd --- /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 000000000..a6c484f37 --- /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 000000000..91a953a72 --- /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 000000000..289416acd --- /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 000000000..5ce85b5d6 --- /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 000000000..342aeee48 --- /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 000000000..271bd2633 --- /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. |