]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
dm: Initial import of design documents
authorMarek Vasut <marek.vasut@gmail.com>
Wed, 8 Aug 2012 01:42:17 +0000 (01:42 +0000)
committerWolfgang Denk <wd@denx.de>
Sun, 2 Sep 2012 15:55:53 +0000 (17:55 +0200)
This patch contains UDM-design.txt, which is document containing
general description of the driver model. The remaining files contains
descriptions of conversion process of particular subsystems.

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
doc/driver-model/UDM-design.txt [new file with mode: 0644]
doc/driver-model/UDM-fpga.txt [new file with mode: 0644]
doc/driver-model/UDM-keyboard.txt [new file with mode: 0644]
doc/driver-model/UDM-serial.txt [new file with mode: 0644]
doc/driver-model/UDM-stdio.txt [new file with mode: 0644]
doc/driver-model/UDM-tpm.txt [new file with mode: 0644]
doc/driver-model/UDM-usb.txt [new file with mode: 0644]
doc/driver-model/UDM-video.txt [new file with mode: 0644]

diff --git a/doc/driver-model/UDM-design.txt b/doc/driver-model/UDM-design.txt
new file mode 100644 (file)
index 0000000..185f477
--- /dev/null
@@ -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 (file)
index 0000000..4f9df94
--- /dev/null
@@ -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-keyboard.txt b/doc/driver-model/UDM-keyboard.txt
new file mode 100644 (file)
index 0000000..ef3761d
--- /dev/null
@@ -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-serial.txt b/doc/driver-model/UDM-serial.txt
new file mode 100644 (file)
index 0000000..e9c274d
--- /dev/null
@@ -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-stdio.txt b/doc/driver-model/UDM-stdio.txt
new file mode 100644 (file)
index 0000000..a6c484f
--- /dev/null
@@ -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 (file)
index 0000000..91a953a
--- /dev/null
@@ -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-usb.txt b/doc/driver-model/UDM-usb.txt
new file mode 100644 (file)
index 0000000..5ce85b5
--- /dev/null
@@ -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 (file)
index 0000000..342aeee
--- /dev/null
@@ -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.