Patchwork [U-Boot,01/14] dm: Initial import of design documents

login
register
mail settings
Submitter Marek Vasut
Date Aug. 8, 2012, 11:42 a.m.
Message ID <1344426150-1229-1-git-send-email-marex@denx.de>
Download mbox | patch
Permalink /patch/175900/
State Accepted
Headers show

Comments

Marek Vasut - Aug. 8, 2012, 11:42 a.m.
From: Marek Vasut <marek.vasut@gmail.com>

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   |  315 +++++++++++++++++++++++++++++++++++++
 doc/driver-model/UDM-fpga.txt     |  115 ++++++++++++++
 doc/driver-model/UDM-keyboard.txt |   47 ++++++
 doc/driver-model/UDM-serial.txt   |  191 ++++++++++++++++++++++
 doc/driver-model/UDM-stdio.txt    |  191 ++++++++++++++++++++++
 doc/driver-model/UDM-tpm.txt      |   48 ++++++
 doc/driver-model/UDM-usb.txt      |   94 +++++++++++
 doc/driver-model/UDM-video.txt    |   74 +++++++++
 8 files changed, 1075 insertions(+)
 create mode 100644 doc/driver-model/UDM-design.txt
 create mode 100644 doc/driver-model/UDM-fpga.txt
 create mode 100644 doc/driver-model/UDM-keyboard.txt
 create mode 100644 doc/driver-model/UDM-serial.txt
 create mode 100644 doc/driver-model/UDM-stdio.txt
 create mode 100644 doc/driver-model/UDM-tpm.txt
 create mode 100644 doc/driver-model/UDM-usb.txt
 create mode 100644 doc/driver-model/UDM-video.txt
Stephen Warren - Aug. 8, 2012, 6:20 p.m.
On 08/08/2012 05:42 AM, Marek Vasut wrote:
> From: Marek Vasut <marek.vasut@gmail.com>
> 
> 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.

> diff --git a/doc/driver-model/UDM-design.txt b/doc/driver-model/UDM-design.txt

> +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.

Given the above descriptions of the two stages, ...

> +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);

... the comments here should probably say which stage each function will
be run at.

> +
> +    /* 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);

The need for this function implies that some other functions (both bind
and probe?) are to be called before relocation. Isn't the pre-relocation
environment rather strict, and hence this will require a bunch of
changes to driver code to initialize differently? Why not just
initialize everything after relocation; IIRC, that's how most things are
initialized now, isn't it?

Related, if you're intending to allow drivers to be loaded from e.g. the
filesystem later, that will happen after relocation. There will then be
a discrepancy between the environment where bind/probe get run for a
built-in driver vs. a dynamically loaded driver.
Marek Vasut - Aug. 8, 2012, 6:37 p.m.
Dear Stephen Warren,

> On 08/08/2012 05:42 AM, Marek Vasut wrote:
> > From: Marek Vasut <marek.vasut@gmail.com>
> > 
> > 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.
> > 
> > diff --git a/doc/driver-model/UDM-design.txt
> > b/doc/driver-model/UDM-design.txt
> > 
> > +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.
> 
> Given the above descriptions of the two stages, ...
> 
> > +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);
> 
> ... the comments here should probably say which stage each function will
> be run at.

The drivers must be agnostic to where they're executed

> > +
> > +    /* 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);
> 
> The need for this function implies that some other functions (both bind
> and probe?) are to be called before relocation.

They can be called after reloc too.

> Isn't the pre-relocation
> environment rather strict

Yes

> and hence this will require a bunch of
> changes to driver code to initialize differently?

No

> Why not just
> initialize everything after relocation; IIRC, that's how most things are
> initialized now, isn't it?

You want eg. i2c bus running before relocation to init your DRAM controller. Or 
serial console for debug output.

> Related, if you're intending to allow drivers to be loaded from e.g. the
> filesystem later

Not now, but we keep that in mind. Btw. (!) we're writing a bootloader here, not 
an operating system.

> that will happen after relocation. There will then be
> a discrepancy between the environment where bind/probe get run for a
> built-in driver vs. a dynamically loaded driver.

Will there?

Best regards,
Marek Vasut
Stephen Warren - Aug. 8, 2012, 7:11 p.m.
On 08/08/2012 12:37 PM, Marek Vasut wrote:
> Dear Stephen Warren,
> 
>> On 08/08/2012 05:42 AM, Marek Vasut wrote:
>>> From: Marek Vasut <marek.vasut@gmail.com>
>>>
>>> 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.
>>>
>>> diff --git a/doc/driver-model/UDM-design.txt
>>> b/doc/driver-model/UDM-design.txt
>>>
>>> +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.
>>
>> Given the above descriptions of the two stages, ...
>>
>>> +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);
>>
>> ... the comments here should probably say which stage each function will
>> be run at.
> 
> The drivers must be agnostic to where they're executed
> 
>>> +
>>> +    /* 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);
>>
>> The need for this function implies that some other functions (both bind
>> and probe?) are to be called before relocation.
> 
> They can be called after reloc too.
> 
>> Isn't the pre-relocation
>> environment rather strict
> 
> Yes

Maybe I'm misinterpreting the exact definition of the stages, but isn't
the pre-relocation stage restricted by e.g. a lack of ability to access
global data, so you have to store everything in the "gd" global data
pointer, or something like that? If that's not the case, perhaps
explicitly spelling out which restrictions do/don't exist in the
definition of the stages above would be helpful to prevent anyone else
reading them the wrong way.

>> and hence this will require a bunch of
>> changes to driver code to initialize differently?
> 
> No

If what I said is above, that's certainly not true of most driver
initialization code today, so migrating to an environment where global
data wasn't allowed would require changes, wouldn't it?

>> Why not just
>> initialize everything after relocation; IIRC, that's how most things are
>> initialized now, isn't it?
> 
> You want eg. i2c bus running before relocation to init your DRAM controller. Or 
> serial console for debug output.
> 
>> Related, if you're intending to allow drivers to be loaded from e.g. the
>> filesystem later
> 
> Not now, but we keep that in mind. Btw. (!) we're writing a bootloader here, not 
> an operating system.

Sure. I was surprised when you wrote about that feature, but my comment
was triggered by your patch series explicitly mentioning loading drivers
at run-time.

>> that will happen after relocation. There will then be
>> a discrepancy between the environment where bind/probe get run for a
>> built-in driver vs. a dynamically loaded driver.
> 
> Will there?

Yes. If bind/probe are called early, then they can't use certain
features like dynamic memory allocation. If they're called late, then
those features are available. Now perhaps you can decide to disallow
their use anyway so that the code doesn't care, but that would require
careful enforcement through either detailed code review, or perhaps
forcing affected functions to be stored in a particular linker section
and checking for symbol references outside that section (e.g. like
__init in the Linux kernel).
Marek Vasut - Aug. 8, 2012, 7:19 p.m.
Dear Stephen Warren,

> On 08/08/2012 12:37 PM, Marek Vasut wrote:
> > Dear Stephen Warren,
> > 
> >> On 08/08/2012 05:42 AM, Marek Vasut wrote:
> >>> From: Marek Vasut <marek.vasut@gmail.com>
> >>> 
> >>> 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.
> >>> 
> >>> diff --git a/doc/driver-model/UDM-design.txt
> >>> b/doc/driver-model/UDM-design.txt
> >>> 
> >>> +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.
> >> 
> >> Given the above descriptions of the two stages, ...
> >> 
> >>> +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);
> >> 
> >> ... the comments here should probably say which stage each function will
> >> be run at.
> > 
> > The drivers must be agnostic to where they're executed
> > 
> >>> +
> >>> +    /* 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);
> >> 
> >> The need for this function implies that some other functions (both bind
> >> and probe?) are to be called before relocation.
> > 
> > They can be called after reloc too.
> > 
> >> Isn't the pre-relocation
> >> environment rather strict
> > 
> > Yes
> 
> Maybe I'm misinterpreting the exact definition of the stages, but isn't
> the pre-relocation stage restricted by e.g. a lack of ability to access
> global data, so you have to store everything in the "gd" global data
> pointer

Correct! That's why the early allocator must only use global-data-alike space.

> or something like that? If that's not the case, perhaps
> explicitly spelling out which restrictions do/don't exist in the
> definition of the stages above would be helpful to prevent anyone else
> reading them the wrong way.

That's the case actually ... just making the information more accurate might 
help.

> >> and hence this will require a bunch of
> >> changes to driver code to initialize differently?
> > 
> > No
> 
> If what I said is above, that's certainly not true of most driver
> initialization code today, so migrating to an environment where global
> data wasn't allowed would require changes, wouldn't it?

Global data should eventually dissolve completely, yes. Drivers will definitelly 
need adjustments.

> >> Why not just
> >> initialize everything after relocation; IIRC, that's how most things are
> >> initialized now, isn't it?
> > 
> > You want eg. i2c bus running before relocation to init your DRAM
> > controller. Or serial console for debug output.
> > 
> >> Related, if you're intending to allow drivers to be loaded from e.g. the
> >> filesystem later
> > 
> > Not now, but we keep that in mind. Btw. (!) we're writing a bootloader
> > here, not an operating system.
> 
> Sure. I was surprised when you wrote about that feature, but my comment
> was triggered by your patch series explicitly mentioning loading drivers
> at run-time.

Yes, we thought about it at the early stages, but postponed it later on to start 
small.

> >> that will happen after relocation. There will then be
> >> a discrepancy between the environment where bind/probe get run for a
> >> built-in driver vs. a dynamically loaded driver.
> > 
> > Will there?
> 
> Yes. If bind/probe are called early, then they can't use certain
> features like dynamic memory allocation.

Yes they can, see the early malloc patches.

> If they're called late, then
> those features are available. Now perhaps you can decide to disallow
> their use anyway so that the code doesn't care, but that would require
> careful enforcement through either detailed code review, or perhaps
> forcing affected functions to be stored in a particular linker section
> and checking for symbol references outside that section (e.g. like
> __init in the Linux kernel).

No, we want to be able to use dynamic allocation (we even need it for the driver 
model to work at all).

Best regards,
Marek Vasut
Wolfgang Denk - Sept. 2, 2012, 4 p.m.
Dear Marek Vasut,

In message <1344426150-1229-1-git-send-email-marex@denx.de> you wrote:
> From: Marek Vasut <marek.vasut@gmail.com>
> 
> 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   |  315 +++++++++++++++++++++++++++++++++++++
>  doc/driver-model/UDM-fpga.txt     |  115 ++++++++++++++
>  doc/driver-model/UDM-keyboard.txt |   47 ++++++
>  doc/driver-model/UDM-serial.txt   |  191 ++++++++++++++++++++++
>  doc/driver-model/UDM-stdio.txt    |  191 ++++++++++++++++++++++
>  doc/driver-model/UDM-tpm.txt      |   48 ++++++
>  doc/driver-model/UDM-usb.txt      |   94 +++++++++++
>  doc/driver-model/UDM-video.txt    |   74 +++++++++
>  8 files changed, 1075 insertions(+)
>  create mode 100644 doc/driver-model/UDM-design.txt
>  create mode 100644 doc/driver-model/UDM-fpga.txt
>  create mode 100644 doc/driver-model/UDM-keyboard.txt
>  create mode 100644 doc/driver-model/UDM-serial.txt
>  create mode 100644 doc/driver-model/UDM-stdio.txt
>  create mode 100644 doc/driver-model/UDM-tpm.txt
>  create mode 100644 doc/driver-model/UDM-usb.txt
>  create mode 100644 doc/driver-model/UDM-video.txt

Applied, thanks.

Best regards,

Wolfgang Denk
Vikram Narayanan - Sept. 2, 2012, 4:31 p.m.
Hello Wolfgang Denk,

On 9/2/2012 9:30 PM, Wolfgang Denk wrote:
> Dear Marek Vasut,
>
> In message<1344426150-1229-1-git-send-email-marex@denx.de>  you wrote:
>> From: Marek Vasut<marek.vasut@gmail.com>
>>
>> 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   |  315 +++++++++++++++++++++++++++++++++++++
>>   doc/driver-model/UDM-fpga.txt     |  115 ++++++++++++++
>>   doc/driver-model/UDM-keyboard.txt |   47 ++++++
>>   doc/driver-model/UDM-serial.txt   |  191 ++++++++++++++++++++++
>>   doc/driver-model/UDM-stdio.txt    |  191 ++++++++++++++++++++++
>>   doc/driver-model/UDM-tpm.txt      |   48 ++++++
>>   doc/driver-model/UDM-usb.txt      |   94 +++++++++++
>>   doc/driver-model/UDM-video.txt    |   74 +++++++++

May I know to which tree these patches are going in? I couldn't see it 
in the u-boot.git.

Regards,
Vikram
Marek Vasut - Sept. 2, 2012, 4:49 p.m.
Dear Vikram Narayanan,

> Hello Wolfgang Denk,
> 
> On 9/2/2012 9:30 PM, Wolfgang Denk wrote:
> > Dear Marek Vasut,
> > 
> > In message<1344426150-1229-1-git-send-email-marex@denx.de>  you wrote:
> >> From: Marek Vasut<marek.vasut@gmail.com>
> >> 
> >> 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   |  315
> >>   +++++++++++++++++++++++++++++++++++++ doc/driver-model/UDM-fpga.txt  
> >>     |  115 ++++++++++++++
> >>   doc/driver-model/UDM-keyboard.txt |   47 ++++++
> >>   doc/driver-model/UDM-serial.txt   |  191 ++++++++++++++++++++++
> >>   doc/driver-model/UDM-stdio.txt    |  191 ++++++++++++++++++++++
> >>   doc/driver-model/UDM-tpm.txt      |   48 ++++++
> >>   doc/driver-model/UDM-usb.txt      |   94 +++++++++++
> >>   doc/driver-model/UDM-video.txt    |   74 +++++++++
> 
> May I know to which tree these patches are going in? I couldn't see it
> in the u-boot.git.

u-boot.git when pushed

> Regards,
> Vikram

Best regards,
Marek Vasut
Wolfgang Denk - Sept. 2, 2012, 8:29 p.m.
Dear Vikram Narayanan,

In message <504389E1.4060604@gmail.com> you wrote:
> 
> May I know to which tree these patches are going in? I couldn't see it 
> in the u-boot.git.

Master.

It takes a while until I push the stuff out to the public server.

You should see them now.

Best regards,

Wolfgang Denk

Patch

diff --git a/doc/driver-model/UDM-design.txt b/doc/driver-model/UDM-design.txt
new file mode 100644
index 0000000..362cad8
--- /dev/null
+++ b/doc/driver-model/UDM-design.txt
@@ -0,0 +1,315 @@ 
+The U-Boot Driver Model Project
+===============================
+Design document
+===============
+Marek Vasut <marek.vasut@gmail.com>
+Pavel Herrmann <morpheus.ibis@gmail.com>
+2012-05-17
+
+I) The modular concept
+----------------------
+
+The driver core design is done with modularity in mind. The long-term plan is to
+extend this modularity to allow loading not only drivers, but various other
+objects into U-Boot at runtime -- like commands, support for other boards etc.
+
+II) Driver core initialization stages
+-------------------------------------
+
+The drivers have to be initialized in two stages, since the U-Boot bootloader
+runs in two stages itself. The first stage is the one which is executed before
+the bootloader itself is relocated. The second stage then happens after
+relocation.
+
+  1) First stage
+  --------------
+
+  The first stage runs after the bootloader did very basic hardware init. This
+  means the stack pointer was configured, caches disabled and that's about it.
+  The problem with this part is the memory management isn't running at all. To
+  make things even worse, at this point, the RAM is still likely uninitialized
+  and therefore unavailable.
+
+  2) Second stage
+  ---------------
+
+  At this stage, the bootloader has initialized RAM and is running from it's
+  final location. Dynamic memory allocations are working at this point. Most of
+  the driver initialization is executed here.
+
+III) The drivers
+----------------
+
+  1) The structure of a driver
+  ----------------------------
+
+  The driver will contain a structure located in a separate section, which
+  will allow linker to create a list of compiled-in drivers at compile time.
+  Let's call this list "driver_list".
+
+  struct driver __attribute__((section(driver_list))) {
+    /* The name of the driver */
+    char		name[STATIC_CONFIG_DRIVER_NAME_LENGTH];
+
+    /*
+     * This function should connect this driver with cores it depends on and
+     * with other drivers, likely bus drivers
+     */
+    int			(*bind)(struct instance *i);
+
+    /* This function actually initializes the hardware. */
+    int			(*probe)(struct instance *i);
+
+    /*
+     * The function of the driver called when U-Boot finished relocation.
+     * This is particularly important to eg. move pointers to DMA buffers
+     * and such from the location before relocation to their final location.
+     */
+    int			(*reloc)(struct instance *i);
+
+    /*
+     * This is called when the driver is shuting down, to deinitialize the
+     * hardware.
+     */
+    int			(*remove)(struct instance *i);
+
+    /* This is called to remove the driver from the driver tree */
+    int			(*unbind)(struct instance *i);
+
+    /* This is a list of cores this driver depends on */
+    struct driver	*cores[];
+  };
+
+  The cores[] array in here is very important. It allows u-boot to figure out,
+  in compile-time, which possible cores can be activated at runtime. Therefore
+  if there are cores that won't be ever activated, GCC LTO might remove them
+  from the final binary. Actually, this information might be used to drive build
+  of the cores.
+
+  FIXME: Should *cores[] be really struct driver, pointing to drivers that
+         represent the cores? Shouldn't it be core instance pointer?
+
+  2) Instantiation of a driver
+  ----------------------------
+
+  The driver is instantiated by calling:
+
+    driver_bind(struct instance *bus, const struct driver_info *di)
+
+  The "struct instance *bus" is a pointer to a bus with which this driver should
+  be registered with. The "root" bus pointer is supplied to the board init
+  functions.
+
+  FIXME: We need some functions that will return list of busses of certain type
+         registered with the system so the user can find proper instance even if
+	 he has no bus pointer (this will come handy if the user isn't
+	 registering the driver from board init function, but somewhere else).
+
+  The "const struct driver_info *di" pointer points to a structure defining the
+  driver to be registered. The structure is defined as follows:
+
+  struct driver_info {
+	char			name[STATIC_CONFIG_DRIVER_NAME_LENGTH];
+	void			*platform_data;
+  }
+
+  The instantiation of a driver by calling driver_bind() creates an instance
+  of the driver by allocating "struct driver_instance". Note that only struct
+  instance is passed to the driver. The wrapping struct driver_instance is there
+  for purposes of the driver core:
+
+  struct driver_instance {
+    uint32_t          flags;
+    struct instance   i;
+  };
+
+  struct instance {
+	/* Pointer to a driver information passed by driver_register() */
+  	const struct driver_info	*info;
+	/* Pointer to a bus this driver is bound with */
+	struct instance			*bus;
+	/* Pointer to this driver's own private data */
+	void				*private_data;
+	/* Pointer to the first block of successor nodes (optional) */
+	struct successor_block 		*succ;
+  }
+
+  The instantiation of a driver does not mean the hardware is initialized. The
+  driver_bind() call only creates the instance of the driver, fills in the "bus"
+  pointer and calls the drivers' .bind() function. The .bind() function of the
+  driver should hook the driver with the remaining cores and/or drivers it
+  depends on.
+
+  It's important to note here, that in case the driver instance has multiple
+  parents, such parent can be connected with this instance by calling:
+
+    driver_link(struct instance *parent, struct instance *dev);
+
+  This will connect the other parent driver with the newly instantiated driver.
+  Note that this must be called after driver_bind() and before driver_acticate()
+  (driver_activate() will be explained below). To allow struct instance to have
+  multiple parent pointer, the struct instance *bus will utilize it's last bit
+  to indicate if this is a pointer to struct instance or to an array if
+  instances, struct successor block. The approach is similar as the approach to
+  *succ in struct instance, described in the following paragraph.
+
+  The last pointer of the struct instance, the pointer to successor nodes, is
+  used only in case of a bus driver. Otherwise the pointer contains NULL value.
+  The last bit of this field indicates if this is a bus having a single child
+  node (so the last bit is 0) or if this bus has multiple child nodes (the last
+  bit is 1). In the former case, the driver core should clear the last bit and
+  this pointer points directly to the child node. In the later case of a bus
+  driver, the pointer points to an instance of structure:
+
+  struct successor_block {
+    /* Array of pointers to instances of devices attached to this bus */
+    struct instance                     *dev[BLOCKING_FACTOR];
+    /* Pointer to next block of successors */
+    struct successor_block              *next;
+  }
+
+  Some of the *dev[] array members might be NULL in case there are no more
+  devices attached. The *next is NULL in case the list of attached devices
+  doesn't continue anymore. The BLOCKING_FACTOR is used to allocate multiple
+  slots for successor devices at once to avoid fragmentation of memory.
+
+  3) The bind() function of a driver
+  ----------------------------------
+
+  The bind function of a driver connects the driver with various cores the
+  driver provides functions for. The driver model related part will look like
+  the following example for a bus driver:
+
+  int driver_bind(struct instance *in)
+  {
+  	...
+        core_bind(&core_i2c_static_instance, in, i2c_bus_funcs);
+        ...
+  }
+
+  FIXME: What if we need to run-time determine, depending on some hardware
+         register, what kind of i2c_bus_funcs to pass?
+
+  This makes the i2c core aware of a new bus. The i2c_bus_funcs is a constant
+  structure of functions any i2c bus driver must provide to work. This will
+  allow the i2c command operate with the bus. The core_i2c_static_instance is
+  the pointer to the instance of a core this driver provides function to.
+
+  FIXME: Maybe replace "core-i2c" with CORE_I2C global pointer to an instance of
+         the core?
+
+  4) The instantiation of a core driver
+  -------------------------------------
+
+  The core driver is special in the way that it's single-instance driver. It is
+  always present in the system, though it might not be activated. The fact that
+  it's single instance allows it to be instantiated at compile time.
+
+  Therefore, all possible structures of this driver can be in read-only memory,
+  especially struct driver and struct driver_instance. But the successor list,
+  which needs special treatment.
+
+  To solve the problem with a successor list and the core driver flags, a new
+  entry in struct gd (global data) will be introduced. This entry will point to
+  runtime allocated array of struct driver_instance. It will be possible to
+  allocate the exact amount of struct driver_instance necessary, as the number
+  of cores that might be activated will be known at compile time. The cores will
+  then behave like any usual driver.
+
+  Pointers to the struct instance of cores can be computed at compile time,
+  therefore allowing the resulting u-boot binary to save some overhead.
+
+  5) The probe() function of a driver
+  -----------------------------------
+
+  The probe function of a driver allocates necessary resources and does required
+  initialization of the hardware itself. This is usually called only when the
+  driver is needed, as a part of the defered probe mechanism.
+
+  The driver core should implement a function called
+
+    int driver_activate(struct instance *in);
+
+  which should call the .probe() function of the driver and then configure the
+  state of the driver instance to "ACTIVATED". This state of a driver instance
+  should be stored in a wrap-around structure for the structure instance, the
+  struct driver_instance.
+
+  6) The command side interface to a driver
+  -----------------------------------------
+
+  The U-Boot command shall communicate only with the specific driver core. The
+  driver core in turn exports necessary API towards the command.
+
+  7) Demonstration imaginary board
+  --------------------------------
+
+  Consider the following computer:
+
+  *
+  |
+  +-- System power management logic
+  |
+  +-- CPU clock controlling logc
+  |
+  +-- NAND controller
+  |   |
+  |   +-- NAND flash chip
+  |
+  +-- 128MB of DDR DRAM
+  |
+  +-- I2C bus #0
+  |   |
+  |   +-- RTC
+  |   |
+  |   +-- EEPROM #0
+  |   |
+  |   +-- EEPROM #1
+  |
+  +-- USB host-only IP core
+  |   |
+  |   +-- USB storage device
+  |
+  +-- USB OTG-capable IP core
+  |   |
+  |   +-- connection to the host PC
+  |
+  +-- GPIO
+  |   |
+  |   +-- User LED #0
+  |   |
+  |   +-- User LED #1
+  |
+  +-- UART0
+  |
+  +-- UART1
+  |
+  +-- Ethernet controller #0
+  |
+  +-- Ethernet controller #1
+  |
+  +-- Audio codec
+  |
+  +-- PCI bridge
+  |   |
+  |   +-- Ethernet controller #2
+  |   |
+  |   +-- SPI host card
+  |   |   |
+  |   |   +-- Audio amplifier (must be operational before codec)
+  |   |
+  |   +-- GPIO host card
+  |       |
+  |       +-- User LED #2
+  |
+  +-- LCD controller
+  |
+  +-- PWM controller (must be enabled after LCD controller)
+  |
+  +-- SPI host controller
+  |   |
+  |   +-- SD/MMC connected via SPI
+  |   |
+  |   +-- SPI flash
+  |
+  +-- CPLD/FPGA with stored configuration of the board
diff --git a/doc/driver-model/UDM-fpga.txt b/doc/driver-model/UDM-fpga.txt
new file mode 100644
index 0000000..4f9df94
--- /dev/null
+++ b/doc/driver-model/UDM-fpga.txt
@@ -0,0 +1,115 @@ 
+The U-Boot Driver Model Project
+===============================
+I/O system analysis
+===================
+Marek Vasut <marek.vasut@gmail.com>
+2012-02-21
+
+I) Overview
+-----------
+
+The current FPGA implementation is handled by command "fpga". This command in
+turn calls the following functions:
+
+fpga_info()
+fpga_load()
+fpga_dump()
+
+These functions are implemented by what appears to be FPGA multiplexer, located
+in drivers/fpga/fpga.c . This code determines which device to operate with
+depending on the device ID.
+
+The fpga_info() function is multiplexer of the functions providing information
+about the particular FPGA device. These functions are implemented in the drivers
+for the particular FPGA device:
+
+xilinx_info()
+altera_info()
+lattice_info()
+
+Similar approach is used for fpga_load(), which multiplexes "xilinx_load()",
+"altera_load()" and "lattice_load()" and is used to load firmware into the FPGA
+device.
+
+The fpga_dump() function, which prints the contents of the FPGA device, is no
+different either, by multiplexing "xilinx_dump()", "altera_dump()" and
+"lattice_dump()" functions.
+
+Finally, each new FPGA device is registered by calling "fpga_add()" function.
+This function takes two arguments, the second one being particularly important,
+because it's basically what will become platform_data. Currently, it's data that
+are passed to the driver from the board/platform code.
+
+II) Approach
+------------
+
+The path to conversion of the FPGA subsystem will be very straightforward, since
+the FPGA subsystem is already quite dynamic. Multiple things will need to be
+modified though.
+
+First is the registration of the new FPGA device towards the FPGA core. This
+will be achieved by calling:
+
+  fpga_device_register(struct instance *i, const struct fpga_ops *ops);
+
+The particularly interesting part is the struct fpga_ops, which contains
+operations supported by the FPGA device. These are basically the already used
+calls in the current implementation:
+
+struct fpga_ops {
+  int info(struct instance *i);
+  int load(struct instance *i, const char *buf, size_t size);
+  int dump(struct instance *i, const char *buf, size_t size);
+}
+
+The other piece that'll have to be modified is how the devices are tracked.
+It'll be necessary to introduce a linked list of devices within the FPGA core
+instead of tracking them by ID number.
+
+Next, the "Xilinx_desc", "Lattice_desc" and "Altera_desc" structures will have
+to be moved to driver's private_data. Finally, structures passed from the board
+and/or platform files, like "Xilinx_Virtex2_Slave_SelectMap_fns" would be passed
+via platform_data to the driver.
+
+III) Analysis of in-tree drivers
+--------------------------------
+
+  1) Altera driver
+  ----------------
+  The driver is realized using the following files:
+
+    drivers/fpga/altera.c
+    drivers/fpga/ACEX1K.c
+    drivers/fpga/cyclon2.c
+    drivers/fpga/stratixII.c
+
+  All of the sub-drivers implement basically the same info-load-dump interface
+  and there's no expected problem during the conversion. The driver itself will
+  be realised by altera.c and all the sub-drivers will be linked in. The
+  distinction will be done by passing different platform data.
+
+  2) Lattice driver
+  -----------------
+  The driver is realized using the following files:
+
+    drivers/fpga/lattice.c
+    drivers/fpga/ivm_core.c
+
+  This driver also implements the standard interface, but to realise the
+  operations with the FPGA device, uses functions from "ivm_core.c" file. This
+  file implements the main communications logic and has to be linked in together
+  with "lattice.c". No problem converting is expected here.
+
+  3) Xilinx driver
+  ----------------
+  The driver is realized using the following files:
+
+    drivers/fpga/xilinx.c
+    drivers/fpga/spartan2.c
+    drivers/fpga/spartan3.c
+    drivers/fpga/virtex2.c
+
+  This set of sub-drivers is special by defining a big set of macros in
+  "include/spartan3.h" and similar files. These macros would need to be either
+  rewritten or replaced. Otherwise, there are no problems expected during the
+  conversion process.
diff --git a/doc/driver-model/UDM-keyboard.txt b/doc/driver-model/UDM-keyboard.txt
new file mode 100644
index 0000000..ef3761d
--- /dev/null
+++ b/doc/driver-model/UDM-keyboard.txt
@@ -0,0 +1,47 @@ 
+The U-Boot Driver Model Project
+===============================
+Keyboard input analysis
+=======================
+Marek Vasut <marek.vasut@gmail.com>
+2012-02-20
+
+I) Overview
+-----------
+
+The keyboard drivers are most often registered with STDIO subsystem. There are
+components of the keyboard drivers though, which operate in severe ad-hoc
+manner, often being related to interrupt-driven keypress reception. This
+components will require the most sanitization of all parts of keyboard input
+subsystem.
+
+Otherwise, the keyboard is no different from other standard input but with the
+necessity to decode scancodes. These are decoded using tables provided by
+keyboard drivers. These tables are often driver specific.
+
+II) Approach
+------------
+
+The most problematic part is the interrupt driven keypress reception. For this,
+the buffers that are currently shared throughout the whole U-Boot would need to
+be converted into driver's private data.
+
+III) Analysis of in-tree drivers
+--------------------------------
+
+  1) board/mpl/common/kbd.c
+  -------------------------
+  This driver is a classic STDIO driver, no problem with conversion is expected.
+  Only necessary change will be to move this driver to a proper location.
+
+  2) board/rbc823/kbd.c
+  ---------------------
+  This driver is a classic STDIO driver, no problem with conversion is expected.
+  Only necessary change will be to move this driver to a proper location.
+
+  3) drivers/input/keyboard.c
+  ---------------------------
+  This driver is special in many ways. Firstly because this is a universal stub
+  driver for converting scancodes from i8042 and the likes. Secondly because the
+  buffer is filled by various other ad-hoc implementations of keyboard input by
+  using this buffer as an extern. This will need to be fixed by allowing drivers
+  to pass certain routines to this driver via platform data.
diff --git a/doc/driver-model/UDM-serial.txt b/doc/driver-model/UDM-serial.txt
new file mode 100644
index 0000000..e9c274d
--- /dev/null
+++ b/doc/driver-model/UDM-serial.txt
@@ -0,0 +1,191 @@ 
+The U-Boot Driver Model Project
+===============================
+Serial I/O analysis
+===================
+Marek Vasut <marek.vasut@gmail.com>
+2012-02-20
+
+I) Overview
+-----------
+
+The serial port support currently requires the driver to export the following
+functions:
+
+  serial_putc() ...... Output a character
+  serial_puts() ...... Output string, often done using serial_putc()
+  serial_tstc() ...... Test if incoming character is in a buffer
+  serial_getc() ...... Retrieve incoming character
+  serial_setbrg() .... Configure port options
+  serial_init() ...... Initialize the hardware
+
+The simpliest implementation, supporting only one port, simply defines these six
+functions and calls them. Such calls are scattered all around U-Boot, especiall
+serial_putc(), serial_puts(), serial_tstc() and serial_getc(). The serial_init()
+and serial_setbrg() are often called from platform-dependent places.
+
+It's important to consider current implementation of CONFIG_SERIAL_MULTI though.
+This resides in common/serial.c and behaves as a multiplexer for serial ports.
+This, by calling serial_assign(), allows user to switch I/O from one serial port
+to another. Though the environmental variables "stdin", "stdout", "stderr"
+remain set to "serial".
+
+These variables are managed by the IOMUX. This resides in common/iomux.c and
+manages all console input/output from U-Boot. For serial port, only one IOMUX is
+always registered, called "serial" and the switching of different serial ports
+is done by code in common/serial.c.
+
+On a final note, it's important to mention function default_serial_console(),
+which is platform specific and reports the default serial console for the
+platform, unless proper environment variable overrides this.
+
+II) Approach
+------------
+
+Drivers not using CONFIG_SERIAL_MULTI already will have to be converted to
+similar approach. The probe() function of a driver will call a function
+registering the driver with a STDIO subsystem core, stdio_device_register().
+
+The serial_init() function will now be replaced by probe() function of the
+driver, the rest of the components of the driver will be converted to standard
+STDIO driver calls. See [ UDM-stdio.txt ] for details.
+
+The serial_setbrg() function depends on global data pointer. This is wrong,
+since there is likely to be user willing to configure different baudrate on two
+different serial ports. The function will be replaced with STDIO's "conf()"
+call, with STDIO_CONFIG_SERIAL_BAUDRATE argument.
+
+III) Analysis of in-tree drivers
+--------------------------------
+
+  1) altera_jtag_uart.c
+  ---------------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  2) altera_uart.c
+  ----------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  3) arm_dcc.c
+  ------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible, unless used
+  with CONFIG_ARM_DCC_MULTI. Then it registers another separate IOMUX.
+
+  4) atmel_usart.c
+  ----------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  5) mcfuart.c
+  ------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  6) ns16550.c
+  ------------
+  This driver seems complicated and certain consideration will need to be made
+  during conversion. This driver is implemented in very universal manner,
+  therefore it'll be necessary to properly design it's platform_data.
+
+  7) ns9750_serial.c
+  ------------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  8) opencores_yanu.c
+  -------------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  9) s3c4510b_uart.c
+  ------------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  10) s3c64xx.c
+  -------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  11) sandbox.c
+  -------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  12) serial.c
+  ------------
+  This is a complementary part of NS16550 UART driver, see above.
+
+  13) serial_clps7111.c
+  ---------------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  14) serial_imx.c
+  ----------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible. This driver
+  might be removed in favor of serial_mxc.c .
+
+  15) serial_ixp.c
+  ----------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  16) serial_ks8695.c
+  -------------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  17) serial_lh7a40x.c
+  --------------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  18) serial_lpc2292.c
+  --------------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  19) serial_max3100.c
+  --------------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  20) serial_mxc.c
+  ----------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  21) serial_netarm.c
+  -------------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  22) serial_pl01x.c
+  ------------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible, though this
+  driver in fact contains two drivers in total.
+
+  23) serial_pxa.c
+  ----------------
+  This driver is a bit complicated, but due to clean support for
+  CONFIG_SERIAL_MULTI, there are no expected obstructions throughout the
+  conversion process.
+
+  24) serial_s3c24x0.c
+  --------------------
+  This driver, being quite ad-hoc might need some work to bring back to shape.
+
+  25) serial_s3c44b0.c
+  --------------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  26) serial_s5p.c
+  ----------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  27) serial_sa1100.c
+  -------------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  28) serial_sh.c
+  ---------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  29) serial_xuartlite.c
+  ----------------------
+  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
+
+  30) usbtty.c
+  ------------
+  This driver seems very complicated and entangled with USB framework. The
+  conversion might be complicated here.
+
+  31) arch/powerpc/cpu/mpc512x/serial.c
+  -------------------------------------
+  This driver supports CONFIG_SERIAL_MULTI. This driver will need to be moved to
+  proper place.
diff --git a/doc/driver-model/UDM-stdio.txt b/doc/driver-model/UDM-stdio.txt
new file mode 100644
index 0000000..a6c484f
--- /dev/null
+++ b/doc/driver-model/UDM-stdio.txt
@@ -0,0 +1,191 @@ 
+The U-Boot Driver Model Project
+===============================
+I/O system analysis
+===================
+Marek Vasut <marek.vasut@gmail.com>
+2012-02-20
+
+I) Overview
+-----------
+
+The console input and output is currently done using the STDIO subsystem in
+U-Boot. The design of this subsystem is already flexible enough to be easily
+converted to new driver model approach. Minor changes will need to be done
+though.
+
+Each device that wants to register with STDIO subsystem has to define struct
+stdio_dev, defined in include/stdio_dev.h and containing the following fields:
+
+struct stdio_dev {
+        int     flags;                  /* Device flags: input/output/system */
+        int     ext;                    /* Supported extensions              */
+        char    name[16];               /* Device name                       */
+
+/* GENERAL functions */
+
+        int (*start) (void);            /* To start the device               */
+        int (*stop) (void);             /* To stop the device                */
+
+/* OUTPUT functions */
+
+        void (*putc) (const char c);    /* To put a char                     */
+        void (*puts) (const char *s);   /* To put a string (accelerator)     */
+
+/* INPUT functions */
+
+        int (*tstc) (void);             /* To test if a char is ready...     */
+        int (*getc) (void);             /* To get that char                  */
+
+/* Other functions */
+
+        void *priv;                     /* Private extensions                */
+        struct list_head list;
+};
+
+Currently used flags are DEV_FLAGS_INPUT, DEV_FLAGS_OUTPUT and DEV_FLAGS_SYSTEM,
+extensions being only one, the DEV_EXT_VIDEO.
+
+The private extensions are now used as a per-device carrier of private data and
+finally list allows this structure to be a member of linked list of STDIO
+devices.
+
+The STDIN, STDOUT and STDERR routing is handled by environment variables
+"stdin", "stdout" and "stderr". By configuring the variable to the name of a
+driver, functions of such driver are called to execute that particular
+operation.
+
+II) Approach
+------------
+
+  1) Similarity of serial, video and keyboard drivers
+  ---------------------------------------------------
+
+  All of these drivers can be unified under the STDIO subsystem if modified
+  slightly. The serial drivers basically define both input and output functions
+  and need function to configure baudrate. The keyboard drivers provide only
+  input. On the other hand, video drivers provide output, but need to be
+  configured in certain way. This configuration might be dynamic, therefore the
+  STDIO has to be modified to provide such flexibility.
+
+  2) Unification of serial, video and keyboard drivers
+  ----------------------------------------------------
+
+  Every STDIO device would register a structure containing operation it supports
+  with the STDIO core by calling:
+
+    int stdio_device_register(struct instance *i, struct stdio_device_ops *o);
+
+  The structure being defined as follows:
+
+  struct stdio_device_ops {
+    void (*putc)(struct instance *i, const char c);
+    void (*puts)(struct instance *i, const char *s);    /* OPTIONAL */
+
+    int  (*tstc)(struct instance *i);
+    int  (*getc)(struct instance *i);
+
+    int  (*init)(struct instance *i);
+    int  (*exit)(struct instance *i);
+    int  (*conf)(struct instance *i, enum stdio_config c, const void *data);
+  };
+
+  The "putc()" function will emit a character, the "puts()" function will emit a
+  string. If both of these are set to NULL, the device is considered STDIN only,
+  aka input only device.
+
+  The "getc()" retrieves a character from a STDIN device, while "tstc()" tests
+  if there is a character in the buffer of STDIN device. In case these two are
+  set to NULL, this device is STDOUT / STDERR device.
+
+  Setting all "putc()", "puts()", "getc()" and "tstc()" calls to NULL isn't an
+  error condition, though such device does nothing. By instroducing tests for
+  these functions being NULL, the "flags" and "ext" fields from original struct
+  stdio_dev can be eliminated.
+
+  The "init()" and "exit()" calls are replacement for "start()" and "exit()"
+  calls in the old approach. The "priv" part of the old struct stdio_dev will be
+  replaced by common private data in the driver model and the struct list_head
+  list will be eliminated by introducing common STDIO core, that tracks all the
+  STDIO devices.
+
+  Lastly, the "conf()" call will allow the user to configure various options of
+  the driver. The enum stdio_config contains all possible configuration options
+  available to the STDIO devices, const void *data being the argument to be
+  configured. Currently, the enum stdio_config will contain at least the
+  following options:
+
+  enum stdio_config {
+    STDIO_CONFIG_SERIAL_BAUDRATE,
+  };
+
+  3) Transformation of stdio routing
+  ----------------------------------
+
+  By allowing multiple instances of drivers, the environment variables "stdin",
+  "stdout" and "stderr" can no longer be set to the name of the driver.
+  Therefore the STDIO core, tracking all of the STDIO devices in the system will
+  need to have a small amount of internal data for each device:
+
+  struct stdio_device_node {
+    struct instance          *i;
+    struct stdio_device_ops  *ops;
+    uint8_t                  id;
+    uint8_t                  flags;
+    struct list_head         list;
+  }
+
+  The "id" is the order of the instance of the same driver. The "flags" variable
+  allows multiple drivers to be used at the same time and even for different
+  purpose. The following flags will be defined:
+
+    STDIO_FLG_STDIN ..... This device will be used as an input device. All input
+                          from all devices with this flag set will be received
+			  and passed to the upper layers.
+    STDIO_FLG_STDOUT .... This device will be used as an output device. All
+                          output sent to stdout will be routed to all devices
+			  with this flag set.
+    STDIO_FLG_STDERR .... This device will be used as an standard error output
+                          device. All output sent to stderr will be routed to
+			  all devices with this flag set.
+
+  The "list" member of this structure allows to have a linked list of all
+  registered STDIO devices.
+
+III) Analysis of in-tree drivers
+--------------------------------
+
+For in-depth analysis of serial port drivers, refer to [ UDM-serial.txt ].
+For in-depth analysis of keyboard drivers, refer to [ UDM-keyboard.txt ].
+For in-depth analysis of video drivers, refer to [ UDM-video.txt ].
+
+  1) arch/blackfin/cpu/jtag-console.c
+  -----------------------------------
+  This driver is a classic STDIO driver, no problem with conversion is expected.
+
+  2) board/mpl/pati/pati.c
+  ------------------------
+  This driver registers with the STDIO framework, though it uses a lot of ad-hoc
+  stuff which will need to be sorted out.
+
+  3) board/netphone/phone_console.c
+  ---------------------------------
+  This driver is a classic STDIO driver, no problem with conversion is expected.
+
+  4) drivers/net/netconsole.c
+  ---------------------------
+  This driver is a classic STDIO driver, no problem with conversion is expected.
+
+IV) Other involved files (To be removed)
+----------------------------------------
+
+common/cmd_console.c
+common/cmd_log.c
+common/cmd_terminal.c
+common/console.c
+common/fdt_support.c
+common/iomux.c
+common/lcd.c
+common/serial.c
+common/stdio.c
+common/usb_kbd.c
+doc/README.iomux
diff --git a/doc/driver-model/UDM-tpm.txt b/doc/driver-model/UDM-tpm.txt
new file mode 100644
index 0000000..91a953a
--- /dev/null
+++ b/doc/driver-model/UDM-tpm.txt
@@ -0,0 +1,48 @@ 
+The U-Boot Driver Model Project
+===============================
+TPM system analysis
+===================
+Marek Vasut <marek.vasut@gmail.com>
+2012-02-23
+
+I) Overview
+-----------
+
+There is currently only one TPM chip driver available and therefore the API
+controlling it is very much based on this. The API is very simple:
+
+  int tis_open(void);
+  int tis_close(void);
+  int tis_sendrecv(const u8 *sendbuf, size_t send_size,
+                         u8 *recvbuf, size_t *recv_len);
+
+The command operating the TPM chip only provides operations to send and receive
+bytes from the chip.
+
+II) Approach
+------------
+
+The API can't be generalised too much considering there's only one TPM chip
+supported. But it's a good idea to split the tis_sendrecv() function in two
+functions. Therefore the new API will use register the TPM chip by calling:
+
+  tpm_device_register(struct instance *i, const struct tpm_ops *ops);
+
+And the struct tpm_ops will contain the following members:
+
+  struct tpm_ops {
+    int (*tpm_open)(struct instance *i);
+    int (*tpm_close)(struct instance *i);
+    int (*tpm_send)(const uint8_t *buf, const size_t size);
+    int (*tpm_recv)(uint8_t *buf, size_t *size);
+  };
+
+The behaviour of "tpm_open()" and "tpm_close()" will basically copy the
+behaviour of "tis_open()" and "tis_close()". The "tpm_send()" will be based on
+the "tis_senddata()" and "tis_recv()" will be based on "tis_readresponse()".
+
+III) Analysis of in-tree drivers
+--------------------------------
+
+There is only one in-tree driver present, the "drivers/tpm/generic_lpc_tpm.c",
+which will be simply converted as outlined in previous chapter.
diff --git a/doc/driver-model/UDM-usb.txt b/doc/driver-model/UDM-usb.txt
new file mode 100644
index 0000000..5ce85b5
--- /dev/null
+++ b/doc/driver-model/UDM-usb.txt
@@ -0,0 +1,94 @@ 
+The U-Boot Driver Model Project
+===============================
+USB analysis
+============
+Marek Vasut <marek.vasut@gmail.com>
+2012-02-16
+
+I) Overview
+-----------
+
+  1) The USB Host driver
+  ----------------------
+  There are basically four or five USB host drivers. All such drivers currently
+  provide at least the following fuctions:
+
+    usb_lowlevel_init() ... Do the initialization of the USB controller hardware
+    usb_lowlevel_stop() ... Do the shutdown of the USB controller hardware
+
+    usb_event_poll() ...... Poll interrupt from USB device, often used by KBD
+
+    submit_control_msg() .. Submit message via Control endpoint
+    submit_int_msg() ...... Submit message via Interrupt endpoint
+    submit_bulk_msg() ..... Submit message via Bulk endpoint
+
+
+    This allows for the host driver to be easily abstracted.
+
+  2) The USB hierarchy
+  --------------------
+
+  In the current implementation, the USB Host driver provides operations to
+  communicate via the USB bus. This is realised by providing access to a USB
+  root port to which an USB root hub is attached. The USB bus is scanned and for
+  each newly found device, a struct usb_device is allocated. See common/usb.c
+  and include/usb.h for details.
+
+II) Approach
+------------
+
+  1) The USB Host driver
+  ----------------------
+
+  Converting the host driver will follow the classic driver model consideration.
+  Though, the host driver will have to call a function that registers a root
+  port with the USB core in it's probe() function, let's call this function
+
+    usb_register_root_port(&ops);
+
+  This will allow the USB core to track all available root ports. The ops
+  parameter will contain structure describing operations supported by the root
+  port:
+
+  struct usb_port_ops {
+    void   (*usb_event_poll)();
+    int    (*submit_control_msg)();
+    int    (*submit_int_msg)();
+    int    (*submit_bulk_msg)();
+  }
+
+  2) The USB hierarchy and hub drivers
+  ------------------------------------
+
+  Converting the USB heirarchy should be fairy simple, considering the already
+  dynamic nature of the implementation. The current usb_hub_device structure
+  will have to be converted to a struct instance. Every such instance will
+  contain components of struct usb_device and struct usb_hub_device in it's
+  private data, providing only accessors in order to properly encapsulate the
+  driver.
+
+  By registering the root port, the USB framework will instantiate a USB hub
+  driver, which is always present, the root hub. The root hub and any subsequent
+  hub instance is represented by struct instance and it's private data contain
+  amongst others common bits from struct usb_device.
+
+  Note the USB hub driver is partly defying the usual method of registering a
+  set of callbacks to a particular core driver. Instead, a static set of
+  functions is defined and the USB hub instance is passed to those. This creates
+  certain restrictions as of how the USB hub driver looks, but considering the
+  specification for USB hub is given and a different type of USB hub won't ever
+  exist, this approach is ok:
+
+  - Report how many ports does this hub have:
+      uint get_nr_ports(struct instance *hub);
+  - Get pointer to device connected to a port:
+      struct instance *(*get_child)(struct instance *hub, int port);
+  - Instantiate and configure device on port:
+      struct instance *(*enum_dev_on_port)(struct instance *hub, int port);
+
+  3) USB device drivers
+  ---------------------
+
+  The USB device driver, in turn, will have to register various ops structures
+  with certain cores. For example, USB disc driver will have to register it's
+  ops with core handling USB discs etc.
diff --git a/doc/driver-model/UDM-video.txt b/doc/driver-model/UDM-video.txt
new file mode 100644
index 0000000..342aeee
--- /dev/null
+++ b/doc/driver-model/UDM-video.txt
@@ -0,0 +1,74 @@ 
+The U-Boot Driver Model Project
+===============================
+Video output analysis
+=====================
+Marek Vasut <marek.vasut@gmail.com>
+2012-02-20
+
+I) Overview
+-----------
+
+The video drivers are most often registered with video subsystem. This subsystem
+often expects to be allowed access to framebuffer of certain parameters. This
+subsystem also provides calls for STDIO subsystem to allow it to output
+characters on the screen. For this part, see [ UDM-stdio.txt ].
+
+Therefore the API has two parts, the video driver part and the part where the
+video driver core registers with STDIO API.
+
+The video driver part will follow the current cfb_console approach, though
+allowing it to be more dynamic.
+
+II) Approach
+------------
+
+Registering the video driver into the video driver core is done by calling the
+following function from the driver probe() function:
+
+  video_device_register(struct instance *i, GraphicDevice *gd);
+
+Because the video driver core is in charge or rendering characters as well as
+bitmaps on the screen, it will in turn call stdio_device_register(i, so), where
+"i" is the same instance as the video driver's one. But "so" will be special
+static struct stdio_device_ops handling the character output.
+
+
+III) Analysis of in-tree drivers
+--------------------------------
+
+  1) arch/powerpc/cpu/mpc8xx/video.c
+  ----------------------------------
+  This driver copies the cfb_console [ see drivers/video/cfb_console.c ]
+  approach and acts only as a STDIO device. Therefore there are currently two
+  possible approaches, first being the conversion of this driver to usual STDIO
+  device and second, long-term one, being conversion of this driver to video
+  driver that provides console.
+
+  2) arch/x86/lib/video.c
+  -----------------------
+  This driver registers two separate STDIO devices and should be therefore
+  converted as such.
+
+  3) board/bf527-ezkit/video.c
+  ----------------------------
+  This driver seems bogus as it behaves as STDIO device, but provides no input
+  or output capabilities. It relies on DEV_EXT_VIDEO, which is no longer in use
+  or present otherwise than as a dead code/define.
+
+  4) board/bf533-stamp/video.c
+  ----------------------------
+  This driver seems bogus as it behaves as STDIO device, but provides no input
+  or output capabilities. It relies on DEV_EXT_VIDEO, which is no longer in use
+  or present otherwise than as a dead code/define.
+
+  5) board/bf548-ezkit/video.c
+  ----------------------------
+  This driver seems bogus as it behaves as STDIO device, but provides no input
+  or output capabilities. It relies on DEV_EXT_VIDEO, which is no longer in use
+  or present otherwise than as a dead code/define.
+
+  6) board/cm-bf548/video.c
+  ----------------------------
+  This driver seems bogus as it behaves as STDIO device, but provides no input
+  or output capabilities. It relies on DEV_EXT_VIDEO, which is no longer in use
+  or present otherwise than as a dead code/define.