]> Git Repo - J-u-boot.git/commitdiff
doc: Move driver model docs under develop/
authorSimon Glass <[email protected]>
Thu, 18 Mar 2021 07:25:12 +0000 (20:25 +1300)
committerSimon Glass <[email protected]>
Fri, 26 Mar 2021 04:03:10 +0000 (17:03 +1300)
These docs are useful for developers, not users. Move them under that
section.

Suggested-by: Heinrich Schuchardt <[email protected]>
Signed-off-by: Simon Glass <[email protected]>
38 files changed:
doc/develop/driver-model/bind.rst [new file with mode: 0644]
doc/develop/driver-model/debugging.rst [new file with mode: 0644]
doc/develop/driver-model/design.rst [new file with mode: 0644]
doc/develop/driver-model/ethernet.rst [new file with mode: 0644]
doc/develop/driver-model/fdt-fixup.rst [new file with mode: 0644]
doc/develop/driver-model/fs_firmware_loader.rst [new file with mode: 0644]
doc/develop/driver-model/i2c-howto.rst [new file with mode: 0644]
doc/develop/driver-model/index.rst [new file with mode: 0644]
doc/develop/driver-model/livetree.rst [new file with mode: 0644]
doc/develop/driver-model/migration.rst [new file with mode: 0644]
doc/develop/driver-model/of-plat.rst [new file with mode: 0644]
doc/develop/driver-model/pci-info.rst [new file with mode: 0644]
doc/develop/driver-model/pmic-framework.rst [new file with mode: 0644]
doc/develop/driver-model/remoteproc-framework.rst [new file with mode: 0644]
doc/develop/driver-model/serial-howto.rst [new file with mode: 0644]
doc/develop/driver-model/soc-framework.rst [new file with mode: 0644]
doc/develop/driver-model/spi-howto.rst [new file with mode: 0644]
doc/develop/driver-model/usb-info.rst [new file with mode: 0644]
doc/develop/index.rst
doc/driver-model/bind.rst [deleted file]
doc/driver-model/debugging.rst [deleted file]
doc/driver-model/design.rst [deleted file]
doc/driver-model/ethernet.rst [deleted file]
doc/driver-model/fdt-fixup.rst [deleted file]
doc/driver-model/fs_firmware_loader.rst [deleted file]
doc/driver-model/i2c-howto.rst [deleted file]
doc/driver-model/index.rst [deleted file]
doc/driver-model/livetree.rst [deleted file]
doc/driver-model/migration.rst [deleted file]
doc/driver-model/of-plat.rst [deleted file]
doc/driver-model/pci-info.rst [deleted file]
doc/driver-model/pmic-framework.rst [deleted file]
doc/driver-model/remoteproc-framework.rst [deleted file]
doc/driver-model/serial-howto.rst [deleted file]
doc/driver-model/soc-framework.rst [deleted file]
doc/driver-model/spi-howto.rst [deleted file]
doc/driver-model/usb-info.rst [deleted file]
doc/index.rst

diff --git a/doc/develop/driver-model/bind.rst b/doc/develop/driver-model/bind.rst
new file mode 100644 (file)
index 0000000..b19661b
--- /dev/null
@@ -0,0 +1,49 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. sectionauthor:: Patrice Chotard <[email protected]>
+
+Binding/unbinding a driver
+==========================
+
+This document aims to describe the bind and unbind commands.
+
+For debugging purpose, it should be useful to bind or unbind a driver from
+the U-boot command line.
+
+The unbind command calls the remove device driver callback and unbind the
+device from its driver.
+
+The bind command binds a device to its driver.
+
+In some cases it can be useful to be able to bind a device to a driver from
+the command line.
+The obvious example is for versatile devices such as USB gadget.
+Another use case is when the devices are not yet ready at startup and
+require some setup before the drivers are bound (ex: FPGA which bitsream is
+fetched from a mass storage or ethernet)
+
+usage:
+
+bind <node path> <driver>
+bind <class> <index> <driver>
+
+unbind <node path>
+unbind <class> <index>
+unbind <class> <index> <driver>
+
+Where:
+ - <node path> is the node's device tree path
+ - <class> is one of the class available in the list given by the "dm uclass"
+   command or first column of "dm tree" command.
+ - <index> is the index of the parent's node (second column of "dm tree" output).
+ - <driver> is the driver name to bind given by the "dm drivers" command or the by
+   the fourth column of "dm tree" output.
+
+example:
+
+bind usb_dev_generic 0 usb_ether
+unbind usb_dev_generic 0 usb_ether
+or
+unbind eth 1
+
+bind /ocp/omap_dwc3@48380000/usb@48390000 usb_ether
+unbind /ocp/omap_dwc3@48380000/usb@48390000
diff --git a/doc/develop/driver-model/debugging.rst b/doc/develop/driver-model/debugging.rst
new file mode 100644 (file)
index 0000000..bbb2794
--- /dev/null
@@ -0,0 +1,62 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. sectionauthor:: Simon Glass <[email protected]>
+
+Debugging driver model
+======================
+
+This document aims to provide help when you cannot work out why driver model is
+not doing what you expect.
+
+
+Useful techniques in general
+----------------------------
+
+Here are some useful debugging features generally.
+
+   - If you are writing a new feature, consider doing it in sandbox instead of
+     on your board. Sandbox has no limits, allows easy debugging (e.g. gdb) and
+     you can write emulators for most common devices.
+   - Put '#define DEBUG' at the top of a file, to activate all the debug() and
+     log_debug() statements in that file.
+   - Where logging is used, change the logging level, e.g. in SPL with
+     CONFIG_SPL_LOG_MAX_LEVEL=7 (which is LOGL_DEBUG) and
+     CONFIG_LOG_DEFAULT_LEVEL=7
+   - Where logging of return values is implemented with log_msg_ret(), set
+     CONFIG_LOG_ERROR_RETURN=y to see exactly where the error is happening
+   - Make sure you have a debug UART enabled - see CONFIG_DEBUG_UART. With this
+     you can get serial output (printf(), etc.) before the serial driver is
+     running.
+   - Use a JTAG emulator to set breakpoints and single-step through code
+
+Not that most of these increase code/data size somewhat when enabled.
+
+
+Failure to locate a device
+--------------------------
+
+Let's say you have uclass_first_device_err() and it is not finding anything.
+
+If it is returning an error, then that gives you a clue. Look up linux/errno.h
+to see errors. Common ones are:
+
+   - -ENOMEM which indicates that memory is short. If it happens in SPL or
+     before relocation in U-Boot, check CONFIG_SPL_SYS_MALLOC_F_LEN and
+     CONFIG_SYS_MALLOC_F_LEN as they may need to be larger. Add '#define DEBUG'
+     at the very top of malloc_simple.c to get an idea of where your memory is
+     going.
+   - -EINVAL which typically indicates that something was missing or wrong in
+     the device tree node. Check that everything is correct and look at the
+     of_to_plat() method in the driver.
+
+If there is no error, you should check if the device is actually bound. Call
+dm_dump_all() just before you locate the device to make sure it exists.
+
+If it does not exist, check your device tree compatible strings match up with
+what the driver expects (in the struct udevice_id array).
+
+If you are using of-platdata (e.g. CONFIG_SPL_OF_PLATDATA), check that the
+driver name is the same as the first compatible string in the device tree (with
+invalid-variable characters converted to underscore).
+
+If you are really stuck, putting '#define LOG_DEBUG' at the top of
+drivers/core/lists.c should show you what is going on.
diff --git a/doc/develop/driver-model/design.rst b/doc/develop/driver-model/design.rst
new file mode 100644 (file)
index 0000000..4e5cecb
--- /dev/null
@@ -0,0 +1,1016 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. sectionauthor:: Simon Glass <[email protected]>
+
+Design Details
+==============
+
+This README contains high-level information about driver model, a unified
+way of declaring and accessing drivers in U-Boot. The original work was done
+by:
+
+   * Marek Vasut <[email protected]>
+   * Pavel Herrmann <[email protected]>
+   * Viktor Křivák <[email protected]>
+   * Tomas Hlavacek <[email protected]>
+
+This has been both simplified and extended into the current implementation
+by:
+
+   * Simon Glass <[email protected]>
+
+
+Terminology
+-----------
+
+Uclass
+  a group of devices which operate in the same way. A uclass provides
+  a way of accessing individual devices within the group, but always
+  using the same interface. For example a GPIO uclass provides
+  operations for get/set value. An I2C uclass may have 10 I2C ports,
+  4 with one driver, and 6 with another.
+
+Driver
+  some code which talks to a peripheral and presents a higher-level
+  interface to it.
+
+Device
+  an instance of a driver, tied to a particular port or peripheral.
+
+
+How to try it
+-------------
+
+Build U-Boot sandbox and run it::
+
+   make sandbox_defconfig
+   make
+   ./u-boot -d u-boot.dtb
+
+   (type 'reset' to exit U-Boot)
+
+
+There is a uclass called 'demo'. This uclass handles
+saying hello, and reporting its status. There are two drivers in this
+uclass:
+
+   - simple: Just prints a message for hello, doesn't implement status
+   - shape: Prints shapes and reports number of characters printed as status
+
+The demo class is pretty simple, but not trivial. The intention is that it
+can be used for testing, so it will implement all driver model features and
+provide good code coverage of them. It does have multiple drivers, it
+handles parameter data and plat (data which tells the driver how
+to operate on a particular platform) and it uses private driver data.
+
+To try it, see the example session below::
+
+   =>demo hello 1
+   Hello '@' from 07981110: red 4
+   =>demo status 2
+   Status: 0
+   =>demo hello 2
+   g
+   r@
+   e@@
+   e@@@
+   n@@@@
+   g@@@@@
+   =>demo status 2
+   Status: 21
+   =>demo hello 4 ^
+     y^^^
+    e^^^^^
+   l^^^^^^^
+   l^^^^^^^
+    o^^^^^
+     w^^^
+   =>demo status 4
+   Status: 36
+   =>
+
+
+Running the tests
+-----------------
+
+The intent with driver model is that the core portion has 100% test coverage
+in sandbox, and every uclass has its own test. As a move towards this, tests
+are provided in test/dm. To run them, try::
+
+   ./test/py/test.py --bd sandbox --build -k ut_dm -v
+
+You should see something like this::
+
+   (venv)$ ./test/py/test.py --bd sandbox --build -k ut_dm -v
+   +make O=/root/u-boot/build-sandbox -s sandbox_defconfig
+   +make O=/root/u-boot/build-sandbox -s -j8
+   ============================= test session starts ==============================
+   platform linux2 -- Python 2.7.5, pytest-2.9.0, py-1.4.31, pluggy-0.3.1 -- /root/u-boot/venv/bin/python
+   cachedir: .cache
+   rootdir: /root/u-boot, inifile:
+   collected 199 items
+
+   test/py/tests/test_ut.py::test_ut_dm_init PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_adc_bind] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_adc_multi_channel_conversion] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_adc_multi_channel_shot] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_adc_single_channel_conversion] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_adc_single_channel_shot] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_adc_supply] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_adc_wrong_channel_selection] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_autobind] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_autobind_uclass_pdata_alloc] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_autobind_uclass_pdata_valid] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_autoprobe] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_bus_child_post_bind] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_bus_child_post_bind_uclass] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_bus_child_pre_probe_uclass] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_bus_children] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_bus_children_funcs] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_bus_children_iterators] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_bus_parent_data] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_bus_parent_data_uclass] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_bus_parent_ops] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_bus_parent_platdata] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_bus_parent_platdata_uclass] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_children] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_clk_base] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_clk_periph] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_device_get_uclass_id] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_eth] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_eth_act] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_eth_alias] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_eth_prime] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_eth_rotate] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_fdt] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_fdt_offset] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_fdt_pre_reloc] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_fdt_uclass_seq] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_gpio] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_gpio_anon] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_gpio_copy] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_gpio_leak] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_gpio_phandles] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_gpio_requestf] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_i2c_bytewise] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_i2c_find] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_i2c_offset] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_i2c_offset_len] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_i2c_probe_empty] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_i2c_read_write] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_i2c_speed] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_leak] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_led_base] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_led_gpio] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_led_label] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_lifecycle] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_mmc_base] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_net_retry] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_operations] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_ordering] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_pci_base] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_pci_busnum] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_pci_swapcase] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_platdata] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_power_pmic_get] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_power_pmic_io] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_power_regulator_autoset] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_power_regulator_autoset_list] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_power_regulator_get] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_power_regulator_set_get_current] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_power_regulator_set_get_enable] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_power_regulator_set_get_mode] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_power_regulator_set_get_voltage] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_pre_reloc] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_ram_base] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_regmap_base] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_regmap_syscon] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_remoteproc_base] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_remove] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_reset_base] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_reset_walk] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_rtc_base] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_rtc_dual] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_rtc_reset] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_rtc_set_get] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_spi_find] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_spi_flash] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_spi_xfer] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_syscon_base] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_syscon_by_driver_data] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_timer_base] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_uclass] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_uclass_before_ready] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_uclass_devices_find] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_uclass_devices_find_by_name] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_uclass_devices_get] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_uclass_devices_get_by_name] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_usb_base] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_usb_flash] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_usb_keyb] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_usb_multi] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_usb_remove] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_usb_tree] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_usb_tree_remove] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_usb_tree_reorder] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_video_base] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_video_bmp] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_video_bmp_comp] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_video_chars] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_video_context] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_video_rotation1] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_video_rotation2] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_video_rotation3] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_video_text] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_video_truetype] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_video_truetype_bs] PASSED
+   test/py/tests/test_ut.py::test_ut[ut_dm_video_truetype_scroll] PASSED
+
+   ======================= 84 tests deselected by '-kut_dm' =======================
+   ================== 115 passed, 84 deselected in 3.77 seconds ===================
+
+What is going on?
+-----------------
+
+Let's start at the top. The demo command is in cmd/demo.c. It does
+the usual command processing and then:
+
+.. code-block:: c
+
+       struct udevice *demo_dev;
+
+       ret = uclass_get_device(UCLASS_DEMO, devnum, &demo_dev);
+
+UCLASS_DEMO means the class of devices which implement 'demo'. Other
+classes might be MMC, or GPIO, hashing or serial. The idea is that the
+devices in the class all share a particular way of working. The class
+presents a unified view of all these devices to U-Boot.
+
+This function looks up a device for the demo uclass. Given a device
+number we can find the device because all devices have registered with
+the UCLASS_DEMO uclass.
+
+The device is automatically activated ready for use by uclass_get_device().
+
+Now that we have the device we can do things like:
+
+.. code-block:: c
+
+       return demo_hello(demo_dev, ch);
+
+This function is in the demo uclass. It takes care of calling the 'hello'
+method of the relevant driver. Bearing in mind that there are two drivers,
+this particular device may use one or other of them.
+
+The code for demo_hello() is in drivers/demo/demo-uclass.c:
+
+.. code-block:: c
+
+       int demo_hello(struct udevice *dev, int ch)
+       {
+               const struct demo_ops *ops = device_get_ops(dev);
+
+               if (!ops->hello)
+                       return -ENOSYS;
+
+               return ops->hello(dev, ch);
+       }
+
+As you can see it just calls the relevant driver method. One of these is
+in drivers/demo/demo-simple.c:
+
+.. code-block:: c
+
+       static int simple_hello(struct udevice *dev, int ch)
+       {
+               const struct dm_demo_pdata *pdata = dev_get_plat(dev);
+
+               printf("Hello from %08x: %s %d\n", map_to_sysmem(dev),
+                      pdata->colour, pdata->sides);
+
+               return 0;
+       }
+
+
+So that is a trip from top (command execution) to bottom (driver action)
+but it leaves a lot of topics to address.
+
+
+Declaring Drivers
+-----------------
+
+A driver declaration looks something like this (see
+drivers/demo/demo-shape.c):
+
+.. code-block:: c
+
+       static const struct demo_ops shape_ops = {
+               .hello = shape_hello,
+               .status = shape_status,
+       };
+
+       U_BOOT_DRIVER(demo_shape_drv) = {
+               .name   = "demo_shape_drv",
+               .id     = UCLASS_DEMO,
+               .ops    = &shape_ops,
+               .priv_data_size = sizeof(struct shape_data),
+       };
+
+
+This driver has two methods (hello and status) and requires a bit of
+private data (accessible through dev_get_priv(dev) once the driver has
+been probed). It is a member of UCLASS_DEMO so will register itself
+there.
+
+In U_BOOT_DRIVER it is also possible to specify special methods for bind
+and unbind, and these are called at appropriate times. For many drivers
+it is hoped that only 'probe' and 'remove' will be needed.
+
+The U_BOOT_DRIVER macro creates a data structure accessible from C,
+so driver model can find the drivers that are available.
+
+The methods a device can provide are documented in the device.h header.
+Briefly, they are:
+
+   * bind - make the driver model aware of a device (bind it to its driver)
+   * unbind - make the driver model forget the device
+   * of_to_plat - convert device tree data to plat - see later
+   * probe - make a device ready for use
+   * remove - remove a device so it cannot be used until probed again
+
+The sequence to get a device to work is bind, of_to_plat (if using
+device tree) and probe.
+
+
+Platform Data
+-------------
+
+Note: platform data is the old way of doing things. It is
+basically a C structure which is passed to drivers to tell them about
+platform-specific settings like the address of its registers, bus
+speed, etc. Device tree is now the preferred way of handling this.
+Unless you have a good reason not to use device tree (the main one
+being you need serial support in SPL and don't have enough SRAM for
+the cut-down device tree and libfdt libraries) you should stay away
+from platform data.
+
+Platform data is like Linux platform data, if you are familiar with that.
+It provides the board-specific information to start up a device.
+
+Why is this information not just stored in the device driver itself? The
+idea is that the device driver is generic, and can in principle operate on
+any board that has that type of device. For example, with modern
+highly-complex SoCs it is common for the IP to come from an IP vendor, and
+therefore (for example) the MMC controller may be the same on chips from
+different vendors. It makes no sense to write independent drivers for the
+MMC controller on each vendor's SoC, when they are all almost the same.
+Similarly, we may have 6 UARTs in an SoC, all of which are mostly the same,
+but lie at different addresses in the address space.
+
+Using the UART example, we have a single driver and it is instantiated 6
+times by supplying 6 lots of platform data. Each lot of platform data
+gives the driver name and a pointer to a structure containing information
+about this instance - e.g. the address of the register space. It may be that
+one of the UARTS supports RS-485 operation - this can be added as a flag in
+the platform data, which is set for this one port and clear for the rest.
+
+Think of your driver as a generic piece of code which knows how to talk to
+a device, but needs to know where it is, any variant/option information and
+so on. Platform data provides this link between the generic piece of code
+and the specific way it is bound on a particular board.
+
+Examples of platform data include:
+
+   - The base address of the IP block's register space
+   - Configuration options, like:
+      - the SPI polarity and maximum speed for a SPI controller
+      - the I2C speed to use for an I2C device
+      - the number of GPIOs available in a GPIO device
+
+Where does the platform data come from? It is either held in a structure
+which is compiled into U-Boot, or it can be parsed from the Device Tree
+(see 'Device Tree' below).
+
+For an example of how it can be compiled in, see demo-pdata.c which
+sets up a table of driver names and their associated platform data.
+The data can be interpreted by the drivers however they like - it is
+basically a communication scheme between the board-specific code and
+the generic drivers, which are intended to work on any board.
+
+Drivers can access their data via dev->info->plat. Here is
+the declaration for the platform data, which would normally appear
+in the board file.
+
+.. code-block:: c
+
+       static const struct dm_demo_pdata red_square = {
+               .colour = "red",
+               .sides = 4.
+       };
+
+       static const struct driver_info info[] = {
+               {
+                       .name = "demo_shape_drv",
+                       .plat = &red_square,
+               },
+       };
+
+       demo1 = driver_bind(root, &info[0]);
+
+
+Device Tree
+-----------
+
+While plat is useful, a more flexible way of providing device data is
+by using device tree. In U-Boot you should use this where possible. Avoid
+sending patches which make use of the U_BOOT_DRVINFO() macro unless strictly
+necessary.
+
+With device tree we replace the above code with the following device tree
+fragment:
+
+.. code-block:: c
+
+       red-square {
+               compatible = "demo-shape";
+               colour = "red";
+               sides = <4>;
+       };
+
+This means that instead of having lots of U_BOOT_DRVINFO() declarations in
+the board file, we put these in the device tree. This approach allows a lot
+more generality, since the same board file can support many types of boards
+(e,g. with the same SoC) just by using different device trees. An added
+benefit is that the Linux device tree can be used, thus further simplifying
+the task of board-bring up either for U-Boot or Linux devs (whoever gets to
+the board first!).
+
+The easiest way to make this work it to add a few members to the driver:
+
+.. code-block:: c
+
+       .plat_auto = sizeof(struct dm_test_pdata),
+       .of_to_plat = testfdt_of_to_plat,
+
+The 'auto' feature allowed space for the plat to be allocated
+and zeroed before the driver's of_to_plat() method is called. The
+of_to_plat() method, which the driver write supplies, should parse
+the device tree node for this device and place it in dev->plat. Thus
+when the probe method is called later (to set up the device ready for use)
+the platform data will be present.
+
+Note that both methods are optional. If you provide an of_to_plat
+method then it will be called first (during activation). If you provide a
+probe method it will be called next. See Driver Lifecycle below for more
+details.
+
+If you don't want to have the plat automatically allocated then you
+can leave out plat_auto. In this case you can use malloc
+in your of_to_plat (or probe) method to allocate the required memory,
+and you should free it in the remove method.
+
+The driver model tree is intended to mirror that of the device tree. The
+root driver is at device tree offset 0 (the root node, '/'), and its
+children are the children of the root node.
+
+In order for a device tree to be valid, the content must be correct with
+respect to either device tree specification
+(https://www.devicetree.org/specifications/) or the device tree bindings that
+are found in the doc/device-tree-bindings directory.  When not U-Boot specific
+the bindings in this directory tend to come from the Linux Kernel.  As such
+certain design decisions may have been made already for us in terms of how
+specific devices are described and bound.  In most circumstances we wish to
+retain compatibility without additional changes being made to the device tree
+source files.
+
+Declaring Uclasses
+------------------
+
+The demo uclass is declared like this:
+
+.. code-block:: c
+
+       UCLASS_DRIVER(demo) = {
+               .id             = UCLASS_DEMO,
+       };
+
+It is also possible to specify special methods for probe, etc. The uclass
+numbering comes from include/dm/uclass-id.h. To add a new uclass, add to the
+end of the enum there, then declare your uclass as above.
+
+
+Device Sequence Numbers
+-----------------------
+
+U-Boot numbers devices from 0 in many situations, such as in the command
+line for I2C and SPI buses, and the device names for serial ports (serial0,
+serial1, ...). Driver model supports this numbering and permits devices
+to be locating by their 'sequence'. This numbering uniquely identifies a
+device in its uclass, so no two devices within a particular uclass can have
+the same sequence number.
+
+Sequence numbers start from 0 but gaps are permitted. For example, a board
+may have I2C buses 1, 4, 5 but no 0, 2 or 3. The choice of how devices are
+numbered is up to a particular board, and may be set by the SoC in some
+cases. While it might be tempting to automatically renumber the devices
+where there are gaps in the sequence, this can lead to confusion and is
+not the way that U-Boot works.
+
+Where a device gets its sequence number is controlled by the DM_SEQ_ALIAS
+Kconfig option, which can have a different value in U-Boot proper and SPL.
+If this option is not set, aliases are ignored.
+
+Even if CONFIG_DM_SEQ_ALIAS is enabled, the uclass must still have the
+DM_UC_FLAG_SEQ_ALIAS flag set, for its devices to be sequenced by aliases.
+
+With those options set, devices with an alias (e.g. "serial2") will get that
+sequence number (e.g. 2). Other devices get the next available number after all
+aliases and all existing numbers. This means that if there is just a single
+alias "serial2", unaliased serial devices will be assigned 3 or more, with 0 and
+1 being unused.
+
+If CONFIG_DM_SEQ_ALIAS or DM_UC_FLAG_SEQ_ALIAS are not set, all devices will get
+sequence numbers in a simple ordering starting from 0. To find the next number
+to allocate, driver model scans through to find the maximum existing number,
+then uses the next one. It does not attempt to fill in gaps.
+
+.. code-block:: none
+
+       aliases {
+               serial2 = "/serial@22230000";
+       };
+
+This indicates that in the uclass called "serial", the named node
+("/serial@22230000") will be given sequence number 2. Any command or driver
+which requests serial device 2 will obtain this device.
+
+More commonly you can use node references, which expand to the full path:
+
+.. code-block:: none
+
+       aliases {
+               serial2 = &serial_2;
+       };
+       ...
+       serial_2: serial@22230000 {
+       ...
+       };
+
+The alias resolves to the same string in this case, but this version is
+easier to read.
+
+Device sequence numbers are resolved when a device is bound and the number does
+not change for the life of the device.
+
+There are some situations where the uclass must allocate sequence numbers,
+since a strictly increase sequence (with devicetree nodes bound first) is not
+suitable. An example of this is the PCI bus. In this case, you can set the
+uclass DM_UC_FLAG_NO_AUTO_SEQ flag. With this flag set, only devices with an
+alias will be assigned a number by driver model. The rest is left to the uclass
+to sort out, e.g. when enumerating the bus.
+
+Note that changing the sequence number for a device (e.g. in a driver) is not
+permitted. If it is felt to be necessary, ask on the mailing list.
+
+Bus Drivers
+-----------
+
+A common use of driver model is to implement a bus, a device which provides
+access to other devices. Example of buses include SPI and I2C. Typically
+the bus provides some sort of transport or translation that makes it
+possible to talk to the devices on the bus.
+
+Driver model provides some useful features to help with implementing buses.
+Firstly, a bus can request that its children store some 'parent data' which
+can be used to keep track of child state. Secondly, the bus can define
+methods which are called when a child is probed or removed. This is similar
+to the methods the uclass driver provides. Thirdly, per-child platform data
+can be provided to specify things like the child's address on the bus. This
+persists across child probe()/remove() cycles.
+
+For consistency and ease of implementation, the bus uclass can specify the
+per-child platform data, so that it can be the same for all children of buses
+in that uclass. There are also uclass methods which can be called when
+children are bound and probed.
+
+Here an explanation of how a bus fits with a uclass may be useful. Consider
+a USB bus with several devices attached to it, each from a different (made
+up) uclass::
+
+   xhci_usb (UCLASS_USB)
+      eth (UCLASS_ETH)
+      camera (UCLASS_CAMERA)
+      flash (UCLASS_FLASH_STORAGE)
+
+Each of the devices is connected to a different address on the USB bus.
+The bus device wants to store this address and some other information such
+as the bus speed for each device.
+
+To achieve this, the bus device can use dev->parent_plat in each of its
+three children. This can be auto-allocated if the bus driver (or bus uclass)
+has a non-zero value for per_child_plat_auto. If not, then
+the bus device or uclass can allocate the space itself before the child
+device is probed.
+
+Also the bus driver can define the child_pre_probe() and child_post_remove()
+methods to allow it to do some processing before the child is activated or
+after it is deactivated.
+
+Similarly the bus uclass can define the child_post_bind() method to obtain
+the per-child platform data from the device tree and set it up for the child.
+The bus uclass can also provide a child_pre_probe() method. Very often it is
+the bus uclass that controls these features, since it avoids each driver
+having to do the same processing. Of course the driver can still tweak and
+override these activities.
+
+Note that the information that controls this behaviour is in the bus's
+driver, not the child's. In fact it is possible that child has no knowledge
+that it is connected to a bus. The same child device may even be used on two
+different bus types. As an example. the 'flash' device shown above may also
+be connected on a SATA bus or standalone with no bus::
+
+   xhci_usb (UCLASS_USB)
+      flash (UCLASS_FLASH_STORAGE)  - parent data/methods defined by USB bus
+
+   sata (UCLASS_AHCI)
+      flash (UCLASS_FLASH_STORAGE)  - parent data/methods defined by SATA bus
+
+   flash (UCLASS_FLASH_STORAGE)  - no parent data/methods (not on a bus)
+
+Above you can see that the driver for xhci_usb/sata controls the child's
+bus methods. In the third example the device is not on a bus, and therefore
+will not have these methods at all. Consider the case where the flash
+device defines child methods. These would be used for *its* children, and
+would be quite separate from the methods defined by the driver for the bus
+that the flash device is connetced to. The act of attaching a device to a
+parent device which is a bus, causes the device to start behaving like a
+bus device, regardless of its own views on the matter.
+
+The uclass for the device can also contain data private to that uclass.
+But note that each device on the bus may be a member of a different
+uclass, and this data has nothing to do with the child data for each child
+on the bus. It is the bus' uclass that controls the child with respect to
+the bus.
+
+
+Driver Lifecycle
+----------------
+
+Here are the stages that a device goes through in driver model. Note that all
+methods mentioned here are optional - e.g. if there is no probe() method for
+a device then it will not be called. A simple device may have very few
+methods actually defined.
+
+Bind stage
+^^^^^^^^^^
+
+U-Boot discovers devices using one of these two methods:
+
+- Scan the U_BOOT_DRVINFO() definitions. U-Boot looks up the name specified
+  by each, to find the appropriate U_BOOT_DRIVER() definition. In this case,
+  there is no path by which driver_data may be provided, but the U_BOOT_DRVINFO()
+  may provide plat.
+
+- Scan through the device tree definitions. U-Boot looks at top-level
+  nodes in the the device tree. It looks at the compatible string in each node
+  and uses the of_match table of the U_BOOT_DRIVER() structure to find the
+  right driver for each node. In this case, the of_match table may provide a
+  driver_data value, but plat cannot be provided until later.
+
+For each device that is discovered, U-Boot then calls device_bind() to create a
+new device, initializes various core fields of the device object such as name,
+uclass & driver, initializes any optional fields of the device object that are
+applicable such as of_offset, driver_data & plat, and finally calls the
+driver's bind() method if one is defined.
+
+At this point all the devices are known, and bound to their drivers. There
+is a 'struct udevice' allocated for all devices. However, nothing has been
+activated (except for the root device). Each bound device that was created
+from a U_BOOT_DRVINFO() declaration will hold the plat pointer specified
+in that declaration. For a bound device created from the device tree,
+plat will be NULL, but of_offset will be the offset of the device tree
+node that caused the device to be created. The uclass is set correctly for
+the device.
+
+The device's sequence number is assigned, either the requested one or the next
+available one (after all aliases are processed) if nothing particular is
+requested.
+
+The device's bind() method is permitted to perform simple actions, but
+should not scan the device tree node, not initialise hardware, nor set up
+structures or allocate memory. All of these tasks should be left for
+the probe() method.
+
+Note that compared to Linux, U-Boot's driver model has a separate step of
+probe/remove which is independent of bind/unbind. This is partly because in
+U-Boot it may be expensive to probe devices and we don't want to do it until
+they are needed, or perhaps until after relocation.
+
+Reading ofdata
+^^^^^^^^^^^^^^
+
+Most devices have data in the device tree which they can read to find out the
+base address of hardware registers and parameters relating to driver
+operation. This is called 'ofdata' (Open-Firmware data).
+
+The device's of_to_plat() implemnents allocation and reading of
+plat. A parent's ofdata is always read before a child.
+
+The steps are:
+
+   1. If priv_auto is non-zero, then the device-private space
+   is allocated for the device and zeroed. It will be accessible as
+   dev->priv. The driver can put anything it likes in there, but should use
+   it for run-time information, not platform data (which should be static
+   and known before the device is probed).
+
+   2. If plat_auto is non-zero, then the platform data space
+   is allocated. This is only useful for device tree operation, since
+   otherwise you would have to specify the platform data in the
+   U_BOOT_DRVINFO() declaration. The space is allocated for the device and
+   zeroed. It will be accessible as dev->plat.
+
+   3. If the device's uclass specifies a non-zero per_device_auto,
+   then this space is allocated and zeroed also. It is allocated for and
+   stored in the device, but it is uclass data. owned by the uclass driver.
+   It is possible for the device to access it.
+
+   4. If the device's immediate parent specifies a per_child_auto
+   then this space is allocated. This is intended for use by the parent
+   device to keep track of things related to the child. For example a USB
+   flash stick attached to a USB host controller would likely use this
+   space. The controller can hold information about the USB state of each
+   of its children.
+
+   5. If the driver provides an of_to_plat() method, then this is
+   called to convert the device tree data into platform data. This should
+   do various calls like dev_read_u32(dev, ...) to access the node and store
+   the resulting information into dev->plat. After this point, the device
+   works the same way whether it was bound using a device tree node or
+   U_BOOT_DRVINFO() structure. In either case, the platform data is now stored
+   in the plat structure. Typically you will use the
+   plat_auto feature to specify the size of the platform data
+   structure, and U-Boot will automatically allocate and zero it for you before
+   entry to of_to_plat(). But if not, you can allocate it yourself in
+   of_to_plat(). Note that it is preferable to do all the device tree
+   decoding in of_to_plat() rather than in probe(). (Apart from the
+   ugliness of mixing configuration and run-time data, one day it is possible
+   that U-Boot will cache platform data for devices which are regularly
+   de/activated).
+
+   6. The device is marked 'plat valid'.
+
+Note that ofdata reading is always done (for a child and all its parents)
+before probing starts. Thus devices go through two distinct states when
+probing: reading platform data and actually touching the hardware to bring
+the device up.
+
+Having probing separate from ofdata-reading helps deal with of-platdata, where
+the probe() method is common to both DT/of-platdata operation, but the
+of_to_plat() method is implemented differently.
+
+Another case has come up where this separate is useful. Generation of ACPI
+tables uses the of-platdata but does not want to probe the device. Probing
+would cause U-Boot to violate one of its design principles, viz that it
+should only probe devices that are used. For ACPI we want to generate a
+table for each device, even if U-Boot does not use it. In fact it may not
+even be possible to probe the device - e.g. an SD card which is not
+present will cause an error on probe, yet we still must tell Linux about
+the SD card connector in case it is used while Linux is running.
+
+It is important that the of_to_plat() method does not actually probe
+the device itself. However there are cases where other devices must be probed
+in the of_to_plat() method. An example is where a device requires a
+GPIO for it to operate. To select a GPIO obviously requires that the GPIO
+device is probed. This is OK when used by common, core devices such as GPIO,
+clock, interrupts, reset and the like.
+
+If your device relies on its parent setting up a suitable address space, so
+that dev_read_addr() works correctly, then make sure that the parent device
+has its setup code in of_to_plat(). If it has it in the probe method,
+then you cannot call dev_read_addr() from the child device's
+of_to_plat() method. Move it to probe() instead. Buses like PCI can
+fall afoul of this rule.
+
+Activation/probe
+^^^^^^^^^^^^^^^^
+
+When a device needs to be used, U-Boot activates it, by first reading ofdata
+as above and then following these steps (see device_probe()):
+
+   1. All parent devices are probed. It is not possible to activate a device
+   unless its predecessors (all the way up to the root device) are activated.
+   This means (for example) that an I2C driver will require that its bus
+   be activated.
+
+   2. The device's probe() method is called. This should do anything that
+   is required by the device to get it going. This could include checking
+   that the hardware is actually present, setting up clocks for the
+   hardware and setting up hardware registers to initial values. The code
+   in probe() can access:
+
+      - platform data in dev->plat (for configuration)
+      - private data in dev->priv (for run-time state)
+      - uclass data in dev->uclass_priv (for things the uclass stores
+        about this device)
+
+   Note: If you don't use priv_auto then you will need to
+   allocate the priv space here yourself. The same applies also to
+   plat_auto. Remember to free them in the remove() method.
+
+   3. The device is marked 'activated'
+
+   4. The uclass's post_probe() method is called, if one exists. This may
+   cause the uclass to do some housekeeping to record the device as
+   activated and 'known' by the uclass.
+
+Running stage
+^^^^^^^^^^^^^
+
+The device is now activated and can be used. From now until it is removed
+all of the above structures are accessible. The device appears in the
+uclass's list of devices (so if the device is in UCLASS_GPIO it will appear
+as a device in the GPIO uclass). This is the 'running' state of the device.
+
+Removal stage
+^^^^^^^^^^^^^
+
+When the device is no-longer required, you can call device_remove() to
+remove it. This performs the probe steps in reverse:
+
+   1. The uclass's pre_remove() method is called, if one exists. This may
+   cause the uclass to do some housekeeping to record the device as
+   deactivated and no-longer 'known' by the uclass.
+
+   2. All the device's children are removed. It is not permitted to have
+   an active child device with a non-active parent. This means that
+   device_remove() is called for all the children recursively at this point.
+
+   3. The device's remove() method is called. At this stage nothing has been
+   deallocated so platform data, private data and the uclass data will all
+   still be present. This is where the hardware can be shut down. It is
+   intended that the device be completely inactive at this point, For U-Boot
+   to be sure that no hardware is running, it should be enough to remove
+   all devices.
+
+   4. The device memory is freed (platform data, private data, uclass data,
+   parent data).
+
+   Note: Because the platform data for a U_BOOT_DRVINFO() is defined with a
+   static pointer, it is not de-allocated during the remove() method. For
+   a device instantiated using the device tree data, the platform data will
+   be dynamically allocated, and thus needs to be deallocated during the
+   remove() method, either:
+
+      - if the plat_auto is non-zero, the deallocation happens automatically
+        within the driver model core in the unbind stage; or
+
+      - when plat_auto is 0, both the allocation (in probe()
+        or preferably of_to_plat()) and the deallocation in remove()
+        are the responsibility of the driver author.
+
+   5. The device is marked inactive. Note that it is still bound, so the
+   device structure itself is not freed at this point. Should the device be
+   activated again, then the cycle starts again at step 2 above.
+
+Unbind stage
+^^^^^^^^^^^^
+
+The device is unbound. This is the step that actually destroys the device.
+If a parent has children these will be destroyed first. After this point
+the device does not exist and its memory has be deallocated.
+
+
+Special cases for removal
+-------------------------
+
+Some devices need to do clean-up before the OS is called. For example, a USB
+driver may want to stop the bus. This can be done in the remove() method.
+Some special flags are used to determine whether to remove the device:
+
+   DM_FLAG_OS_PREPARE - indicates that the device needs to get ready for OS
+          boot. The device will be removed just before the OS is booted
+   DM_REMOVE_ACTIVE_DMA - indicates that the device uses DMA. This is
+          effectively the same as DM_FLAG_OS_PREPARE, so the device is removed
+          before the OS is booted
+   DM_FLAG_VITAL - indicates that the device is 'vital' to the operation of
+          other devices. It is possible to remove this device after all regular
+          devices are removed. This is useful e.g. for a clock, which need to
+          be active during the device-removal phase.
+
+The dm_remove_devices_flags() function can be used to remove devices based on
+their driver flags.
+
+Data Structures
+---------------
+
+Driver model uses a doubly-linked list as the basic data structure. Some
+nodes have several lists running through them. Creating a more efficient
+data structure might be worthwhile in some rare cases, once we understand
+what the bottlenecks are.
+
+
+Changes since v1
+----------------
+
+For the record, this implementation uses a very similar approach to the
+original patches, but makes at least the following changes:
+
+- Tried to aggressively remove boilerplate, so that for most drivers there
+  is little or no 'driver model' code to write.
+- Moved some data from code into data structure - e.g. store a pointer to
+  the driver operations structure in the driver, rather than passing it
+  to the driver bind function.
+- Rename some structures to make them more similar to Linux (struct udevice
+  instead of struct instance, struct plat, etc.)
+- Change the name 'core' to 'uclass', meaning U-Boot class. It seems that
+  this concept relates to a class of drivers (or a subsystem). We shouldn't
+  use 'class' since it is a C++ reserved word, so U-Boot class (uclass) seems
+  better than 'core'.
+- Remove 'struct driver_instance' and just use a single 'struct udevice'.
+  This removes a level of indirection that doesn't seem necessary.
+- Built in device tree support, to avoid the need for plat
+- Removed the concept of driver relocation, and just make it possible for
+  the new driver (created after relocation) to access the old driver data.
+  I feel that relocation is a very special case and will only apply to a few
+  drivers, many of which can/will just re-init anyway. So the overhead of
+  dealing with this might not be worth it.
+- Implemented a GPIO system, trying to keep it simple
+
+
+Pre-Relocation Support
+----------------------
+
+For pre-relocation we simply call the driver model init function. Only
+drivers marked with DM_FLAG_PRE_RELOC or the device tree 'u-boot,dm-pre-reloc'
+property are initialised prior to relocation. This helps to reduce the driver
+model overhead. This flag applies to SPL and TPL as well, if device tree is
+enabled (CONFIG_OF_CONTROL) there.
+
+Note when device tree is enabled, the device tree 'u-boot,dm-pre-reloc'
+property can provide better control granularity on which device is bound
+before relocation. While with DM_FLAG_PRE_RELOC flag of the driver all
+devices with the same driver are bound, which requires allocation a large
+amount of memory. When device tree is not used, DM_FLAG_PRE_RELOC is the
+only way for statically declared devices via U_BOOT_DRVINFO() to be bound
+prior to relocation.
+
+It is possible to limit this to specific relocation steps, by using
+the more specialized 'u-boot,dm-spl' and 'u-boot,dm-tpl' flags
+in the device tree node. For U-Boot proper you can use 'u-boot,dm-pre-proper'
+which means that it will be processed (and a driver bound) in U-Boot proper
+prior to relocation, but will not be available in SPL or TPL.
+
+To reduce the size of SPL and TPL, only the nodes with pre-relocation properties
+('u-boot,dm-pre-reloc', 'u-boot,dm-spl' or 'u-boot,dm-tpl') are keept in their
+device trees (see README.SPL for details); the remaining nodes are always bound.
+
+Then post relocation we throw that away and re-init driver model again.
+For drivers which require some sort of continuity between pre- and
+post-relocation devices, we can provide access to the pre-relocation
+device pointers, but this is not currently implemented (the root device
+pointer is saved but not made available through the driver model API).
+
+
+SPL Support
+-----------
+
+Driver model can operate in SPL. Its efficient implementation and small code
+size provide for a small overhead which is acceptable for all but the most
+constrained systems.
+
+To enable driver model in SPL, define CONFIG_SPL_DM. You might want to
+consider the following option also. See the main README for more details.
+
+   - CONFIG_SYS_MALLOC_SIMPLE
+   - CONFIG_DM_WARN
+   - CONFIG_DM_DEVICE_REMOVE
+   - CONFIG_DM_STDIO
+
+
+Enabling Driver Model
+---------------------
+
+Driver model is being brought into U-Boot gradually. As each subsystems gets
+support, a uclass is created and a CONFIG to enable use of driver model for
+that subsystem.
+
+For example CONFIG_DM_SERIAL enables driver model for serial. With that
+defined, the old serial support is not enabled, and your serial driver must
+conform to driver model. With that undefined, the old serial support is
+enabled and driver model is not available for serial. This means that when
+you convert a driver, you must either convert all its boards, or provide for
+the driver to be compiled both with and without driver model (generally this
+is not very hard).
+
+See the main README for full details of the available driver model CONFIG
+options.
+
+
+Things to punt for later
+------------------------
+
+Uclasses are statically numbered at compile time. It would be possible to
+change this to dynamic numbering, but then we would require some sort of
+lookup service, perhaps searching by name. This is slightly less efficient
+so has been left out for now. One small advantage of dynamic numbering might
+be fewer merge conflicts in uclass-id.h.
diff --git a/doc/develop/driver-model/ethernet.rst b/doc/develop/driver-model/ethernet.rst
new file mode 100644 (file)
index 0000000..cdbccca
--- /dev/null
@@ -0,0 +1,321 @@
+Ethernet Driver Guide
+=======================
+
+The networking stack in Das U-Boot is designed for multiple network devices
+to be easily added and controlled at runtime.  This guide is meant for people
+who wish to review the net driver stack with an eye towards implementing your
+own ethernet device driver.  Here we will describe a new pseudo 'APE' driver.
+
+Most existing drivers do already - and new network driver MUST - use the
+U-Boot core driver model. Generic information about this can be found in
+doc/driver-model/design.rst, this document will thus focus on the network
+specific code parts.
+Some drivers are still using the old Ethernet interface, differences between
+the two and hints about porting will be handled at the end.
+
+Driver framework
+------------------
+
+A network driver following the driver model must declare itself using
+the UCLASS_ETH .id field in the U-Boot driver struct:
+
+.. code-block:: c
+
+       U_BOOT_DRIVER(eth_ape) = {
+               .name                   = "eth_ape",
+               .id                     = UCLASS_ETH,
+               .of_match               = eth_ape_ids,
+               .of_to_plat     = eth_ape_of_to_plat,
+               .probe                  = eth_ape_probe,
+               .ops                    = &eth_ape_ops,
+               .priv_auto      = sizeof(struct eth_ape_priv),
+               .plat_auto = sizeof(struct eth_ape_pdata),
+               .flags                  = DM_FLAG_ALLOC_PRIV_DMA,
+       };
+
+struct eth_ape_priv contains runtime per-instance data, like buffers, pointers
+to current descriptors, current speed settings, pointers to PHY related data
+(like struct mii_dev) and so on. Declaring its size in .priv_auto
+will let the driver framework allocate it at the right time.
+It can be retrieved using a dev_get_priv(dev) call.
+
+struct eth_ape_pdata contains static platform data, like the MMIO base address,
+a hardware variant, the MAC address. ``struct eth_pdata eth_pdata``
+as the first member of this struct helps to avoid duplicated code.
+If you don't need any more platform data beside the standard member,
+just use sizeof(struct eth_pdata) for the plat_auto.
+
+PCI devices add a line pointing to supported vendor/device ID pairs:
+
+.. code-block:: c
+
+       static struct pci_device_id supported[] = {
+               { PCI_DEVICE(PCI_VENDOR_ID_APE, 0x4223) },
+               {}
+       };
+
+       U_BOOT_PCI_DEVICE(eth_ape, supported);
+
+It is also possible to declare support for a whole class of PCI devices::
+
+       { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_SDHCI << 8, 0xffff00) },
+
+Device probing and instantiation will be handled by the driver model framework,
+so follow the guidelines there. The probe() function would initialise the
+platform specific parts of the hardware, like clocks, resets, GPIOs, the MDIO
+bus. Also it would take care of any special PHY setup (power rails, enable
+bits for internal PHYs, etc.).
+
+Driver methods
+----------------
+
+The real work will be done in the driver method functions the driver provides
+by defining the members of struct eth_ops:
+
+.. code-block:: c
+
+       struct eth_ops {
+               int (*start)(struct udevice *dev);
+               int (*send)(struct udevice *dev, void *packet, int length);
+               int (*recv)(struct udevice *dev, int flags, uchar **packetp);
+               int (*free_pkt)(struct udevice *dev, uchar *packet, int length);
+               void (*stop)(struct udevice *dev);
+               int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
+               int (*write_hwaddr)(struct udevice *dev);
+               int (*read_rom_hwaddr)(struct udevice *dev);
+       };
+
+An up-to-date version of this struct together with more information can be
+found in include/net.h.
+
+Only start, stop, send and recv are required, the rest are optional and are
+handled by generic code or ignored if not provided.
+
+The **start** function initialises the hardware and gets it ready for send/recv
+operations.  You often do things here such as resetting the MAC
+and/or PHY, and waiting for the link to autonegotiate.  You should also take
+the opportunity to program the device's MAC address with the enetaddr member
+of the generic struct eth_pdata (which would be the first member of your
+own plat struct). This allows the rest of U-Boot to dynamically change
+the MAC address and have the new settings be respected.
+
+The **send** function does what you think -- transmit the specified packet
+whose size is specified by length (in bytes). The packet buffer can (and
+will!) be reused for subsequent calls to send(), so it must be no longer
+used when the send() function returns. The easiest way to achieve this is
+to wait until the transmission is complete. Alternatively, if supported by
+the hardware, just waiting for the buffer to be consumed (by some DMA engine)
+might be an option as well.
+Another way of consuming the buffer could be to copy the data to be send,
+then just queue the copied packet (for instance handing it over to a DMA
+engine), and return immediately afterwards.
+In any case you should leave the state such that the send function can be
+called multiple times in a row.
+
+The **recv** function polls for availability of a new packet. If none is
+available, it must return with -EAGAIN.
+If a packet has been received, make sure it is accessible to the CPU
+(invalidate caches if needed), then write its address to the packetp pointer,
+and return the length. If there is an error (receive error, too short or too
+long packet), return 0 if you require the packet to be cleaned up normally,
+or a negative error code otherwise (cleanup not necessary or already done).
+The U-Boot network stack will then process the packet.
+
+If **free_pkt** is defined, U-Boot will call it after a received packet has
+been processed, so the packet buffer can be freed or recycled. Typically you
+would hand it back to the hardware to acquire another packet. free_pkt() will
+be called after recv(), for the same packet, so you don't necessarily need
+to infer the buffer to free from the ``packet`` pointer, but can rely on that
+being the last packet that recv() handled.
+The common code sets up packet buffers for you already in the .bss
+(net_rx_packets), so there should be no need to allocate your own. This doesn't
+mean you must use the net_rx_packets array however; you're free to use any
+buffer you wish.
+
+The **stop** function should turn off / disable the hardware and place it back
+in its reset state.  It can be called at any time (before any call to the
+related start() function), so make sure it can handle this sort of thing.
+
+The (optional) **write_hwaddr** function should program the MAC address stored
+in pdata->enetaddr into the Ethernet controller.
+
+So the call graph at this stage would look something like:
+
+.. code-block:: c
+
+       (some net operation (ping / tftp / whatever...))
+       eth_init()
+               ops->start()
+       eth_send()
+               ops->send()
+       eth_rx()
+               ops->recv()
+               (process packet)
+               if (ops->free_pkt)
+                       ops->free_pkt()
+       eth_halt()
+               ops->stop()
+
+
+CONFIG_PHYLIB / CONFIG_CMD_MII
+--------------------------------
+
+If your device supports banging arbitrary values on the MII bus (pretty much
+every device does), you should add support for the mii command.  Doing so is
+fairly trivial and makes debugging mii issues a lot easier at runtime.
+
+In your driver's ``probe()`` function, add a call to mdio_alloc() and
+mdio_register() like so:
+
+.. code-block:: c
+
+       bus = mdio_alloc();
+       if (!bus) {
+               ...
+               return -ENOMEM;
+       }
+
+       bus->read = ape_mii_read;
+       bus->write = ape_mii_write;
+       mdio_register(bus);
+
+And then define the mii_read and mii_write functions if you haven't already.
+Their syntax is straightforward::
+
+       int mii_read(struct mii_dev *bus, int addr, int devad, int reg);
+       int mii_write(struct mii_dev *bus, int addr, int devad, int reg,
+                     u16 val);
+
+The read function should read the register 'reg' from the phy at address 'addr'
+and return the result to its caller.  The implementation for the write function
+should logically follow.
+
+................................................................
+
+Legacy network drivers
+------------------------
+
+!!! WARNING !!!
+
+This section below describes the old way of doing things. No new Ethernet
+drivers should be implemented this way. All new drivers should be written
+against the U-Boot core driver model, as described above.
+
+The actual callback functions are fairly similar, the differences are:
+
+- ``start()`` is called ``init()``
+- ``stop()`` is called ``halt()``
+- The ``recv()`` function must loop until all packets have been received, for
+  each packet it must call the net_process_received_packet() function,
+  handing it over the pointer and the length. Afterwards it should free
+  the packet, before checking for new data.
+
+For porting an old driver to the new driver model, split the existing recv()
+function into the actual new recv() function, just fetching **one** packet,
+remove the call to net_process_received_packet(), then move the packet
+cleanup into the ``free_pkt()`` function.
+
+Registering the driver and probing a device is handled very differently,
+follow the recommendations in the driver model design documentation for
+instructions on how to port this over. For the records, the old way of
+initialising a network driver is as follows:
+
+Old network driver registration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When U-Boot initializes, it will call the common function eth_initialize().
+This will in turn call the board-specific board_eth_init() (or if that fails,
+the cpu-specific cpu_eth_init()).  These board-specific functions can do random
+system handling, but ultimately they will call the driver-specific register
+function which in turn takes care of initializing that particular instance.
+
+Keep in mind that you should code the driver to avoid storing state in global
+data as someone might want to hook up two of the same devices to one board.
+Any such information that is specific to an interface should be stored in a
+private, driver-defined data structure and pointed to by eth->priv (see below).
+
+So the call graph at this stage would look something like:
+
+.. code-block:: c
+
+       board_init()
+               eth_initialize()
+                       board_eth_init() / cpu_eth_init()
+                               driver_register()
+                                       initialize eth_device
+                                       eth_register()
+
+At this point in time, the only thing you need to worry about is the driver's
+register function.  The pseudo code would look something like:
+
+.. code-block:: c
+
+       int ape_register(struct bd_info *bis, int iobase)
+       {
+               struct ape_priv *priv;
+               struct eth_device *dev;
+               struct mii_dev *bus;
+
+               priv = malloc(sizeof(*priv));
+               if (priv == NULL)
+                       return -ENOMEM;
+
+               dev = malloc(sizeof(*dev));
+               if (dev == NULL) {
+                       free(priv);
+                       return -ENOMEM;
+               }
+
+               /* setup whatever private state you need */
+
+               memset(dev, 0, sizeof(*dev));
+               sprintf(dev->name, "APE");
+
+               /*
+                * if your device has dedicated hardware storage for the
+                * MAC, read it and initialize dev->enetaddr with it
+                */
+               ape_mac_read(dev->enetaddr);
+
+               dev->iobase = iobase;
+               dev->priv = priv;
+               dev->init = ape_init;
+               dev->halt = ape_halt;
+               dev->send = ape_send;
+               dev->recv = ape_recv;
+               dev->write_hwaddr = ape_write_hwaddr;
+
+               eth_register(dev);
+
+       #ifdef CONFIG_PHYLIB
+               bus = mdio_alloc();
+               if (!bus) {
+                       free(priv);
+                       free(dev);
+                       return -ENOMEM;
+               }
+
+               bus->read = ape_mii_read;
+               bus->write = ape_mii_write;
+               mdio_register(bus);
+       #endif
+
+               return 1;
+       }
+
+The exact arguments needed to initialize your device are up to you.  If you
+need to pass more/less arguments, that's fine.  You should also add the
+prototype for your new register function to include/netdev.h.
+
+The return value for this function should be as follows:
+< 0 - failure (hardware failure, not probe failure)
+>=0 - number of interfaces detected
+
+You might notice that many drivers seem to use xxx_initialize() rather than
+xxx_register().  This is the old naming convention and should be avoided as it
+causes confusion with the driver-specific init function.
+
+Other than locating the MAC address in dedicated hardware storage, you should
+not touch the hardware in anyway.  That step is handled in the driver-specific
+init function.  Remember that we are only registering the device here, we are
+not checking its state or doing random probing.
diff --git a/doc/develop/driver-model/fdt-fixup.rst b/doc/develop/driver-model/fdt-fixup.rst
new file mode 100644 (file)
index 0000000..974c090
--- /dev/null
@@ -0,0 +1,132 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. 2017-01-06, Mario Six <[email protected]>
+
+Pre-relocation device tree manipulation
+=======================================
+
+Purpose
+-------
+
+In certain markets, it is beneficial for manufacturers of embedded devices to
+offer certain ranges of products, where the functionality of the devices within
+one series either don't differ greatly from another, or can be thought of as
+"extensions" of each other, where one device only differs from another in the
+addition of a small number of features (e.g. an additional output connector).
+
+To realize this in hardware, one method is to have a motherboard, and several
+possible daughter boards that can be attached to this mother board. Different
+daughter boards then either offer the slightly different functionality, or the
+addition of the daughter board to the device realizes the "extension" of
+functionality to the device described previously.
+
+For the software, we obviously want to reuse components for all these
+variations of the device. This means that the software somehow needs to cope
+with the situation that certain ICs may or may not be present on any given
+system, depending on which daughter boards are connected to the motherboard.
+
+In the Linux kernel, one possible solution to this problem is to employ the
+device tree overlay mechanism: There exists one "base" device tree, which
+features only the components guaranteed to exist in all varieties of the
+device. At the start of the kernel, the presence and type of the daughter
+boards is then detected, and the corresponding device tree overlays are applied
+to support the components on the daughter boards.
+
+Note that the components present on every variety of the board must, of course,
+provide a way to find out if and which daughter boards are installed for this
+mechanism to work.
+
+In the U-Boot boot loader, support for device tree overlays has recently been
+integrated, and is used on some boards to alter the device tree that is later
+passed to Linux. But since U-Boot's driver model, which is device tree-based as
+well, is being used in more and more drivers, the same problem of altering the
+device tree starts cropping up in U-Boot itself as well.
+
+An additional problem with the device tree in U-Boot is that it is read-only,
+and the current mechanisms don't allow easy manipulation of the device tree
+after the driver model has been initialized. While migrating to a live device
+tree (at least after the relocation) would greatly simplify the solution of
+this problem, it is a non-negligible task to implement it, an a interim
+solution is needed to address the problem at least in the medium-term.
+
+Hence, we propose a solution to this problem by offering a board-specific
+call-back function, which is passed a writeable pointer to the device tree.
+This function is called before the device tree is relocated, and specifically
+before the main U-Boot's driver model is instantiated, hence the main U-Boot
+"sees" all modifications to the device tree made in this function. Furthermore,
+we have the pre-relocation driver model at our disposal at this stage, which
+means that we can query the hardware for the existence and variety of the
+components easily.
+
+Implementation
+--------------
+
+To take advantage of the pre-relocation device tree manipulation mechanism,
+boards have to implement the function board_fix_fdt, which has the following
+signature:
+
+.. code-block:: c
+
+   int board_fix_fdt (void *rw_fdt_blob)
+
+The passed-in void pointer is a writeable pointer to the device tree, which can
+be used to manipulate the device tree using e.g. functions from
+include/fdt_support.h. The return value should either be 0 in case of
+successful execution of the device tree manipulation or something else for a
+failure. Note that returning a non-null value from the function will
+unrecoverably halt the boot process, as with any function from init_sequence_f
+(in common/board_f.c).
+
+Furthermore, the Kconfig option OF_BOARD_FIXUP has to be set for the function
+to be called::
+
+   Device Tree Control
+   -> [*] Board-specific manipulation of Device Tree
+
++----------------------------------------------------------+
+| WARNING: The actual manipulation of the device tree has  |
+| to be the _last_ set of operations in board_fix_fdt!     |
+| Since the pre-relocation driver model does not adapt to  |
+| changes made to the device tree either, its references   |
+| into the device tree will be invalid after manipulating  |
+| it, and unpredictable behavior might occur when          |
+| functions that rely on them are executed!                |
++----------------------------------------------------------+
+
+Hence, the recommended layout of the board_fixup_fdt call-back function is the
+following:
+
+.. code-block:: c
+
+       int board_fix_fdt(void *rw_fdt_blob)
+       {
+               /*
+                * Collect information about device's hardware and store
+                * them in e.g. local variables
+                */
+
+               /* Do device tree manipulation using the values previously collected */
+
+               /* Return 0 on successful manipulation and non-zero otherwise */
+       }
+
+If this convention is kept, both an "additive" approach, meaning that nodes for
+detected components are added to the device tree, as well as a "subtractive"
+approach, meaning that nodes for absent components are removed from the tree,
+as well as a combination of both approaches should work.
+
+Example
+-------
+
+The controlcenterdc board (board/gdsys/a38x/controlcenterdc.c) features a
+board_fix_fdt function, in which six GPIO expanders (which might be present or
+not, since they are on daughter boards) on a I2C bus are queried for, and
+subsequently deactivated in the device tree if they are not present.
+
+Note that the dm_i2c_simple_probe function does not use the device tree, hence
+it is safe to call it after the tree has already been manipulated.
+
+Work to be done
+---------------
+
+* The application of device tree overlay should be possible in board_fixup_fdt,
+  but has not been tested at this stage.
diff --git a/doc/develop/driver-model/fs_firmware_loader.rst b/doc/develop/driver-model/fs_firmware_loader.rst
new file mode 100644 (file)
index 0000000..a44708c
--- /dev/null
@@ -0,0 +1,154 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright (C) 2018-2019 Intel Corporation <www.intel.com>
+
+File System Firmware Loader
+===========================
+
+This is file system firmware loader for U-Boot framework, which has very close
+to some Linux Firmware API. For the details of Linux Firmware API, you can refer
+to https://01.org/linuxgraphics/gfx-docs/drm/driver-api/firmware/index.html.
+
+File system firmware loader can be used to load whatever(firmware, image,
+and binary) from the storage device in file system format into target location
+such as memory, then consumer driver such as FPGA driver can program FPGA image
+from the target location into FPGA.
+
+To enable firmware loader, CONFIG_FS_LOADER need to be set at
+<board_name>_defconfig such as "CONFIG_FS_LOADER=y".
+
+Firmware Loader API core features
+---------------------------------
+
+Firmware storage device described in device tree source
+-------------------------------------------------------
+For passing data like storage device phandle and partition where the
+firmware loading from to the firmware loader driver, those data could be
+defined in fs-loader node as shown in below:
+
+Example for block device::
+
+       fs_loader0: fs-loader {
+               u-boot,dm-pre-reloc;
+               compatible = "u-boot,fs-loader";
+               phandlepart = <&mmc 1>;
+       };
+
+<&mmc 1> means block storage device pointer and its partition.
+
+Above example is a description for block storage, but for UBI storage
+device, it can be described in FDT as shown in below:
+
+Example for ubi::
+
+       fs_loader1: fs-loader {
+               u-boot,dm-pre-reloc;
+               compatible = "u-boot,fs-loader";
+               mtdpart = "UBI",
+               ubivol = "ubi0";
+       };
+
+Then, firmware-loader property can be added with any device node, which
+driver would use the firmware loader for loading.
+
+The value of the firmware-loader property should be set with phandle
+of the fs-loader node. For example::
+
+       firmware-loader = <&fs_loader0>;
+
+If there are majority of devices using the same fs-loader node, then
+firmware-loader property can be added under /chosen node instead of
+adding to each of device node.
+
+For example::
+
+       /{
+               chosen {
+                       firmware-loader = <&fs_loader0>;
+               };
+       };
+
+In each respective driver of devices using firmware loader, the firmware
+loaded instance        should be created by DT phandle.
+
+For example of getting DT phandle from /chosen and creating instance:
+
+.. code-block:: c
+
+       chosen_node = ofnode_path("/chosen");
+       if (!ofnode_valid(chosen_node)) {
+               debug("/chosen node was not found.\n");
+               return -ENOENT;
+       }
+
+       phandle_p = ofnode_get_property(chosen_node, "firmware-loader", &size);
+       if (!phandle_p) {
+               debug("firmware-loader property was not found.\n");
+               return -ENOENT;
+       }
+
+       phandle = fdt32_to_cpu(*phandle_p);
+       ret = uclass_get_device_by_phandle_id(UCLASS_FS_FIRMWARE_LOADER,
+                                            phandle, &dev);
+       if (ret)
+               return ret;
+
+Firmware loader driver is also designed to support U-boot environment
+variables, so all these data from FDT can be overwritten
+through the U-boot environment variable during run time.
+
+For examples:
+
+storage_interface:
+  Storage interface, it can be "mmc", "usb", "sata" or "ubi".
+fw_dev_part:
+  Block device number and its partition, it can be "0:1".
+fw_ubi_mtdpart:
+  UBI device mtd partition, it can be "UBI".
+fw_ubi_volume:
+  UBI volume, it can be "ubi0".
+
+When above environment variables are set, environment values would be
+used instead of data from FDT.
+The benefit of this design allows user to change storage attribute data
+at run time through U-boot console and saving the setting as default
+environment values in the storage for the next power cycle, so no
+compilation is required for both driver and FDT.
+
+File system firmware Loader API
+-------------------------------
+
+.. code-block:: c
+
+       int request_firmware_into_buf(struct udevice *dev,
+                                     const char *name,
+                                     void *buf, size_t size, u32 offset)
+
+Load firmware into a previously allocated buffer
+
+Parameters:
+
+* struct udevice \*dev: An instance of a driver
+* const char \*name: name of firmware file
+* void \*buf: address of buffer to load firmware into
+* size_t size: size of buffer
+* u32 offset: offset of a file for start reading into buffer
+
+Returns:
+       size of total read
+       -ve when error
+
+Description:
+       The firmware is loaded directly into the buffer pointed to by buf
+
+Example of calling request_firmware_into_buf API after creating firmware loader
+instance:
+
+.. code-block:: c
+
+       ret = uclass_get_device_by_phandle_id(UCLASS_FS_FIRMWARE_LOADER,
+                                            phandle, &dev);
+       if (ret)
+               return ret;
+
+       request_firmware_into_buf(dev, filename, buffer_location, buffer_size,
+                                offset_ofreading);
diff --git a/doc/develop/driver-model/i2c-howto.rst b/doc/develop/driver-model/i2c-howto.rst
new file mode 100644 (file)
index 0000000..27e7440
--- /dev/null
@@ -0,0 +1,56 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+How to port an I2C driver to driver model
+=========================================
+
+Over half of the I2C drivers have been converted as at November 2016. These
+ones remain:
+
+   * adi_i2c
+   * davinci_i2c
+   * fti2c010
+   * ihs_i2c
+   * kona_i2c
+   * lpc32xx_i2c
+   * pca9564_i2c
+   * ppc4xx_i2c
+   * rcar_i2c
+   * sh_i2c
+   * soft_i2c
+   * zynq_i2c
+
+The deadline for this work is the end of June 2017. If no one steps
+forward to convert these, at some point there may come a patch to remove them!
+
+Here is a suggested approach for converting your I2C driver over to driver
+model. Please feel free to update this file with your ideas and suggestions.
+
+- #ifdef out all your own I2C driver code (#if !CONFIG_IS_ENABLED(DM_I2C))
+- Define CONFIG_DM_I2C for your board, vendor or architecture
+- If the board does not already use driver model, you need CONFIG_DM also
+- Your board should then build, but will not work fully since there will be
+  no I2C driver
+- Add the U_BOOT_DRIVER piece at the end (e.g. copy tegra_i2c.c for example)
+- Add a private struct for the driver data - avoid using static variables
+- Implement each of the driver methods, perhaps by calling your old methods
+- You may need to adjust the function parameters so that the old and new
+  implementations can share most of the existing code
+- If you convert all existing users of the driver, remove the pre-driver-model
+  code
+
+In terms of patches a conversion series typically has these patches:
+- clean up / prepare the driver for conversion
+- add driver model code
+- convert at least one existing board to use driver model serial
+- (if no boards remain that don't use driver model) remove the old code
+
+This may be a good time to move your board to use device tree also. Mostly
+this involves these steps:
+
+- define CONFIG_OF_CONTROL and CONFIG_OF_SEPARATE
+- add your device tree files to arch/<arch>/dts
+- update the Makefile there
+- Add stdout-path to your /chosen device tree node if it is not already there
+- build and get u-boot-dtb.bin so you can test it
+- Your drivers can now use device tree
+- For device tree in SPL, define CONFIG_SPL_OF_CONTROL
diff --git a/doc/develop/driver-model/index.rst b/doc/develop/driver-model/index.rst
new file mode 100644 (file)
index 0000000..fd4575d
--- /dev/null
@@ -0,0 +1,29 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Driver Model
+============
+
+The following holds information on the U-Boot device driver framework:
+driver-model, including the design details of itself and several driver
+subsystems
+
+.. toctree::
+   :maxdepth: 2
+
+   bind
+   debugging
+   design
+   ethernet
+   fdt-fixup
+   fs_firmware_loader
+   i2c-howto
+   livetree
+   migration
+   of-plat
+   pci-info
+   pmic-framework
+   remoteproc-framework
+   serial-howto
+   soc-framework
+   spi-howto
+   usb-info
diff --git a/doc/develop/driver-model/livetree.rst b/doc/develop/driver-model/livetree.rst
new file mode 100644 (file)
index 0000000..9f654f3
--- /dev/null
@@ -0,0 +1,286 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. sectionauthor:: Simon Glass <[email protected]>
+
+Live Device Tree
+================
+
+
+Introduction
+------------
+
+Traditionally U-Boot has used a 'flat' device tree. This means that it
+reads directly from the device tree binary structure. It is called a flat
+device tree because nodes are listed one after the other, with the
+hierarchy detected by tags in the format.
+
+This document describes U-Boot's support for a 'live' device tree, meaning
+that the tree is loaded into a hierarchical data structure within U-Boot.
+
+
+Motivation
+----------
+
+The flat device tree has several advantages:
+
+- it is the format produced by the device tree compiler, so no translation
+  is needed
+
+- it is fairly compact (e.g. there is no need for pointers)
+
+- it is accessed by the libfdt library, which is well tested and stable
+
+
+However the flat device tree does have some limitations. Adding new
+properties can involve copying large amounts of data around to make room.
+The overall tree has a fixed maximum size so sometimes the tree must be
+rebuilt in a new location to create more space. Even if not adding new
+properties or nodes, scanning the tree can be slow. For example, finding
+the parent of a node is a slow process. Reading from nodes involves a
+small amount parsing which takes a little time.
+
+Driver model scans the entire device tree sequentially on start-up which
+avoids the worst of the flat tree's limitations. But if the tree is to be
+modified at run-time, a live tree is much faster. Even if no modification
+is necessary, parsing the tree once and using a live tree from then on
+seems to save a little time.
+
+
+Implementation
+--------------
+
+In U-Boot a live device tree ('livetree') is currently supported only
+after relocation. Therefore we need a mechanism to specify a device
+tree node regardless of whether it is in the flat tree or livetree.
+
+The 'ofnode' type provides this. An ofnode can point to either a flat tree
+node (when the live tree node is not yet set up) or a livetree node. The
+caller of an ofnode function does not need to worry about these details.
+
+The main users of the information in a device tree are drivers. These have
+a 'struct udevice \*' which is attached to a device tree node. Therefore it
+makes sense to be able to read device tree  properties using the
+'struct udevice \*', rather than having to obtain the ofnode first.
+
+The 'dev_read\_...()' interface provides this. It allows properties to be
+easily read from the device tree using only a device pointer. Under the
+hood it uses ofnode so it works with both flat and live device trees.
+
+
+Enabling livetree
+-----------------
+
+CONFIG_OF_LIVE enables livetree. When this option is enabled, the flat
+tree will be used in SPL and before relocation in U-Boot proper. Just
+before relocation a livetree is built, and this is used for U-Boot proper
+after relocation.
+
+Most checks for livetree use CONFIG_IS_ENABLED(OF_LIVE). This means that
+for SPL, the CONFIG_SPL_OF_LIVE option is checked. At present this does
+not exist, since SPL does not support livetree.
+
+
+Porting drivers
+---------------
+
+Many existing drivers use the fdtdec interface to read device tree
+properties. This only works with a flat device tree. The drivers should be
+converted to use the dev_read_() interface.
+
+For example, the old code may be like this:
+
+.. code-block:: c
+
+    struct udevice *bus;
+    const void *blob = gd->fdt_blob;
+    int node = dev_of_offset(bus);
+
+    i2c_bus->regs = (struct i2c_ctlr *)devfdt_get_addr(dev);
+    plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", 500000);
+
+The new code is:
+
+.. code-block:: c
+
+    struct udevice *bus;
+
+    i2c_bus->regs = (struct i2c_ctlr *)dev_read_addr(dev);
+    plat->frequency = dev_read_u32_default(bus, "spi-max-frequency", 500000);
+
+The dev_read\_...() interface is more convenient and works with both the
+flat and live device trees. See include/dm/read.h for a list of functions.
+
+Where properties must be read from sub-nodes or other nodes, you must fall
+back to using ofnode. For example, for old code like this:
+
+.. code-block:: c
+
+    const void *blob = gd->fdt_blob;
+    int subnode;
+
+    fdt_for_each_subnode(subnode, blob, dev_of_offset(dev)) {
+        freq = fdtdec_get_int(blob, node, "spi-max-frequency", 500000);
+        ...
+    }
+
+you should use:
+
+.. code-block:: c
+
+    ofnode subnode;
+
+    ofnode_for_each_subnode(subnode, dev_ofnode(dev)) {
+        freq = ofnode_read_u32(node, "spi-max-frequency", 500000);
+        ...
+    }
+
+
+Useful ofnode functions
+-----------------------
+
+The internal data structures of the livetree are defined in include/dm/of.h :
+
+   :struct device_node: holds information about a device tree node
+   :struct property: holds information about a property within a node
+
+Nodes have pointers to their first property, their parent, their first child
+and their sibling. This allows nodes to be linked together in a hierarchical
+tree.
+
+Properties have pointers to the next property. This allows all properties of
+a node to be linked together in a chain.
+
+It should not be necessary to use these data structures in normal code. In
+particular, you should refrain from using functions which access the livetree
+directly, such as of_read_u32(). Use ofnode functions instead, to allow your
+code to work with a flat tree also.
+
+Some conversion functions are used internally. Generally these are not needed
+for driver code. Note that they will not work if called in the wrong context.
+For example it is invalid to call ofnode_to_no() when a flat tree is being
+used. Similarly it is not possible to call ofnode_to_offset() on a livetree
+node.
+
+ofnode_to_np():
+   converts ofnode to struct device_node *
+ofnode_to_offset():
+   converts ofnode to offset
+
+no_to_ofnode():
+   converts node pointer to ofnode
+offset_to_ofnode():
+   converts offset to ofnode
+
+
+Other useful functions:
+
+of_live_active():
+   returns true if livetree is in use, false if flat tree
+ofnode_valid():
+   return true if a given node is valid
+ofnode_is_np():
+   returns true if a given node is a livetree node
+ofnode_equal():
+   compares two ofnodes
+ofnode_null():
+   returns a null ofnode (for which ofnode_valid() returns false)
+
+
+Phandles
+--------
+
+There is full phandle support for live tree. All functions make use of
+struct ofnode_phandle_args, which has an ofnode within it. This supports both
+livetree and flat tree transparently. See for example
+ofnode_parse_phandle_with_args().
+
+
+Reading addresses
+-----------------
+
+You should use dev_read_addr() and friends to read addresses from device-tree
+nodes.
+
+
+fdtdec
+------
+
+The existing fdtdec interface will eventually be retired. Please try to avoid
+using it in new code.
+
+
+Modifying the livetree
+----------------------
+
+This is not currently supported. Once implemented it should provide a much
+more efficient implementation for modification of the device tree than using
+the flat tree.
+
+
+Internal implementation
+-----------------------
+
+The dev_read\_...() functions have two implementations. When
+CONFIG_DM_DEV_READ_INLINE is enabled, these functions simply call the ofnode
+functions directly. This is useful when livetree is not enabled. The ofnode
+functions call ofnode_is_np(node) which will always return false if livetree
+is disabled, just falling back to flat tree code.
+
+This optimisation means that without livetree enabled, the dev_read\_...() and
+ofnode interfaces do not noticeably add to code size.
+
+The CONFIG_DM_DEV_READ_INLINE option defaults to enabled when livetree is
+disabled.
+
+Most livetree code comes directly from Linux and is modified as little as
+possible. This is deliberate since this code is fairly stable and does what
+we want. Some features (such as get/put) are not supported. Internal macros
+take care of removing these features silently.
+
+Within the of_access.c file there are pointers to the alias node, the chosen
+node and the stdout-path alias.
+
+
+Errors
+------
+
+With a flat device tree, libfdt errors are returned (e.g. -FDT_ERR_NOTFOUND).
+For livetree normal 'errno' errors are returned (e.g. -ENOTFOUND). At present
+the ofnode and dev_read\_...() functions return either one or other type of
+error. This is clearly not desirable. Once tests are added for all the
+functions this can be tidied up.
+
+
+Adding new access functions
+---------------------------
+
+Adding a new function for device-tree access involves the following steps:
+
+   - Add two dev_read() functions:
+      - inline version in the read.h header file, which calls an ofnode function
+      - standard version in the read.c file (or perhaps another file), which
+        also calls an ofnode function
+
+        The implementations of these functions can be the same. The purpose
+        of the inline version is purely to reduce code size impact.
+
+   - Add an ofnode function. This should call ofnode_is_np() to work out
+     whether a livetree or flat tree is used. For the livetree it should
+     call an of\_...() function. For the flat tree it should call an
+     fdt\_...() function. The livetree version will be optimised out at
+     compile time if livetree is not enabled.
+
+   - Add an of\_...() function for the livetree implementation. If a similar
+     function is available in Linux, the implementation should be taken
+     from there and modified as little as possible (generally not at all).
+
+
+Future work
+-----------
+
+Live tree support was introduced in U-Boot 2017.07. There is still quite a bit
+of work to do to flesh this out:
+
+- tests for all access functions
+- support for livetree modification
+- addition of more access functions as needed
+- support for livetree in SPL and before relocation (if desired)
diff --git a/doc/develop/driver-model/migration.rst b/doc/develop/driver-model/migration.rst
new file mode 100644 (file)
index 0000000..2284e8a
--- /dev/null
@@ -0,0 +1,101 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Migration Schedule
+==================
+
+U-Boot has been migrating to a new driver model since its introduction in
+2014. This file describes the schedule for deprecation of pre-driver-model
+features.
+
+CONFIG_DM
+---------
+
+* Status: In progress
+* Deadline: 2020.01
+
+Starting with the 2010.01 release CONFIG_DM will be enabled for all boards.
+This does not concern CONFIG_DM_SPL and CONFIG_DM_TPL. The conversion date for
+these configuration items still needs to be defined.
+
+CONFIG_DM_MMC
+-------------
+
+* Status: In progress
+* Deadline: 2019.04
+
+The subsystem itself has been converted and maintainers should submit patches
+switching over to using CONFIG_DM_MMC and other base driver model options in
+time for inclusion in the 2019.04 rerelease.
+
+CONFIG_DM_USB
+-------------
+
+* Status: In progress
+* Deadline: 2019.07
+
+The subsystem itself has been converted along with many of the host controller
+and maintainers should submit patches switching over to using CONFIG_DM_USB and
+other base driver model options in time for inclusion in the 2019.07 rerelease.
+
+CONFIG_SATA
+-----------
+
+* Status: In progress
+* Deadline: 2019.07
+
+The subsystem itself has been converted along with many of the host controller
+and maintainers should submit patches switching over to using CONFIG_AHCI and
+other base driver model options in time for inclusion in the 2019.07 rerelease.
+
+CONFIG_BLK
+----------
+
+* Status: In progress
+* Deadline: 2019.07
+
+In concert with maintainers migrating their block device usage to the
+appropriate DM driver, CONFIG_BLK needs to be set as well.  The final deadline
+here coincides with the final deadline for migration of the various block
+subsystems.  At this point we will be able to audit and correct the logic in
+Kconfig around using CONFIG_PARTITIONS and CONFIG_HAVE_BLOCK_DEVICE and make
+use of CONFIG_BLK / CONFIG_SPL_BLK as needed.
+
+CONFIG_DM_SPI / CONFIG_DM_SPI_FLASH
+-----------------------------------
+
+Board Maintainers should submit the patches for enabling DM_SPI and DM_SPI_FLASH
+to move the migration with in the deadline.
+
+Partially converted::
+
+       drivers/spi/fsl_espi.c
+       drivers/spi/mxc_spi.c
+       drivers/spi/sh_qspi.c
+
+* Status: In progress
+* Deadline: 2019.07
+
+CONFIG_DM_PCI
+-------------
+Deadline: 2019.07
+
+The PCI subsystem has supported driver model since mid 2015. Maintainers should
+submit patches switching over to using CONFIG_DM_PCI and other base driver
+model options in time for inclusion in the 2019.07 release.
+
+
+CONFIG_DM_VIDEO
+---------------
+Deadline: 2019.07
+
+The video subsystem has supported driver model since early 2016. Maintainers
+should submit patches switching over to using CONFIG_DM_VIDEO and other base
+driver model options in time for inclusion in the 2019.07 release.
+
+CONFIG_DM_ETH
+-------------
+Deadline: 2020.07
+
+The network subsystem has supported the driver model since early 2015.
+Maintainers should submit patches switching over to using CONFIG_DM_ETH and
+other base driver model options in time for inclusion in the 2020.07 release.
diff --git a/doc/develop/driver-model/of-plat.rst b/doc/develop/driver-model/of-plat.rst
new file mode 100644 (file)
index 0000000..74f1932
--- /dev/null
@@ -0,0 +1,913 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Compiled-in Device Tree / Platform Data
+=======================================
+
+
+Introduction
+------------
+
+Device tree is the standard configuration method in U-Boot. It is used to
+define what devices are in the system and provide configuration information
+to these devices.
+
+The overhead of adding devicetree access to U-Boot is fairly modest,
+approximately 3KB on Thumb 2 (plus the size of the DT itself). This means
+that in most cases it is best to use devicetree for configuration.
+
+However there are some very constrained environments where U-Boot needs to
+work. These include SPL with severe memory limitations. For example, some
+SoCs require a 16KB SPL image which must include a full MMC stack. In this
+case the overhead of devicetree access may be too great.
+
+It is possible to create platform data manually by defining C structures
+for it, and reference that data in a `U_BOOT_DRVINFO()` declaration. This
+bypasses the use of devicetree completely, effectively creating a parallel
+configuration mechanism. But it is an available option for SPL.
+
+As an alternative, the 'of-platdata' feature is provided. This converts the
+devicetree contents into C code which can be compiled into the SPL binary.
+This saves the 3KB of code overhead and perhaps a few hundred more bytes due
+to more efficient storage of the data.
+
+
+How it works
+------------
+
+The feature is enabled by CONFIG OF_PLATDATA. This is only available in
+SPL/TPL and should be tested with:
+
+.. code-block:: c
+
+    #if CONFIG_IS_ENABLED(OF_PLATDATA)
+
+A tool called 'dtoc' converts a devicetree file either into a set of
+struct declarations, one for each compatible node, and a set of
+`U_BOOT_DRVINFO()` declarations along with the actual platform data for each
+device. As an example, consider this MMC node:
+
+.. code-block:: none
+
+    sdmmc: dwmmc@ff0c0000 {
+            compatible = "rockchip,rk3288-dw-mshc";
+            clock-freq-min-max = <400000 150000000>;
+            clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
+                     <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
+            clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+            fifo-depth = <0x100>;
+            interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+            reg = <0xff0c0000 0x4000>;
+            bus-width = <4>;
+            cap-mmc-highspeed;
+            cap-sd-highspeed;
+            card-detect-delay = <200>;
+            disable-wp;
+            num-slots = <1>;
+            pinctrl-names = "default";
+            pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>;
+                vmmc-supply = <&vcc_sd>;
+                status = "okay";
+                u-boot,dm-pre-reloc;
+        };
+
+
+Some of these properties are dropped by U-Boot under control of the
+CONFIG_OF_SPL_REMOVE_PROPS option. The rest are processed. This will produce
+the following C struct declaration:
+
+.. code-block:: c
+
+    struct dtd_rockchip_rk3288_dw_mshc {
+            fdt32_t         bus_width;
+            bool            cap_mmc_highspeed;
+            bool            cap_sd_highspeed;
+            fdt32_t         card_detect_delay;
+            fdt32_t         clock_freq_min_max[2];
+            struct phandle_1_arg clocks[4];
+            bool            disable_wp;
+            fdt32_t         fifo_depth;
+            fdt32_t         interrupts[3];
+            fdt32_t         num_slots;
+            fdt32_t         reg[2];
+            fdt32_t         vmmc_supply;
+    };
+
+and the following device declarations:
+
+.. code-block:: c
+
+    /* Node /clock-controller@ff760000 index 0 */
+    ...
+
+    /* Node /dwmmc@ff0c0000 index 2 */
+    static struct dtd_rockchip_rk3288_dw_mshc dtv_dwmmc_at_ff0c0000 = {
+            .fifo_depth             = 0x100,
+            .cap_sd_highspeed       = true,
+            .interrupts             = {0x0, 0x20, 0x4},
+            .clock_freq_min_max     = {0x61a80, 0x8f0d180},
+            .vmmc_supply            = 0xb,
+            .num_slots              = 0x1,
+            .clocks                 = {{0, 456},
+                                       {0, 68},
+                                       {0, 114},
+                                       {0, 118}},
+            .cap_mmc_highspeed      = true,
+            .disable_wp             = true,
+            .bus_width              = 0x4,
+            .u_boot_dm_pre_reloc    = true,
+            .reg                    = {0xff0c0000, 0x4000},
+            .card_detect_delay      = 0xc8,
+    };
+
+    U_BOOT_DRVINFO(dwmmc_at_ff0c0000) = {
+            .name           = "rockchip_rk3288_dw_mshc",
+            .plat       = &dtv_dwmmc_at_ff0c0000,
+            .plat_size  = sizeof(dtv_dwmmc_at_ff0c0000),
+            .parent_idx     = -1,
+    };
+
+The device is then instantiated at run-time and the platform data can be
+accessed using:
+
+.. code-block:: c
+
+    struct udevice *dev;
+    struct dtd_rockchip_rk3288_dw_mshc *plat = dev_get_plat(dev);
+
+This avoids the code overhead of converting the devicetree data to
+platform data in the driver. The `of_to_plat()` method should
+therefore do nothing in such a driver.
+
+Note that for the platform data to be matched with a driver, the 'name'
+property of the `U_BOOT_DRVINFO()` declaration has to match a driver declared
+via `U_BOOT_DRIVER()`. This effectively means that a `U_BOOT_DRIVER()` with a
+'name' corresponding to the devicetree 'compatible' string (after converting
+it to a valid name for C) is needed, so a dedicated driver is required for
+each 'compatible' string.
+
+In order to make this a bit more flexible, the `DM_DRIVER_ALIAS()` macro can be
+used to declare an alias for a driver name, typically a 'compatible' string.
+This macro produces no code, but is used by dtoc tool. It must be located in the
+same file as its associated driver, ideally just after it.
+
+The parent_idx is the index of the parent `driver_info` structure within its
+linker list (instantiated by the `U_BOOT_DRVINFO()` macro). This is used to
+support `dev_get_parent()`.
+
+During the build process dtoc parses both `U_BOOT_DRIVER()` and
+`DM_DRIVER_ALIAS()` to build a list of valid driver names and driver aliases.
+If the 'compatible' string used for a device does not not match a valid driver
+name, it will be checked against the list of driver aliases in order to get the
+right driver name to use. If in this step there is no match found a warning is
+issued to avoid run-time failures.
+
+Where a node has multiple compatible strings, dtoc generates a `#define` to
+make them equivalent, e.g.:
+
+.. code-block:: c
+
+    #define dtd_rockchip_rk3299_dw_mshc dtd_rockchip_rk3288_dw_mshc
+
+
+Converting of-platdata to a useful form
+---------------------------------------
+
+Of course it would be possible to use the of-platdata directly in your driver
+whenever configuration information is required. However this means that the
+driver will not be able to support devicetree, since the of-platdata
+structure is not available when devicetree is used. It would make no sense
+to use this structure if devicetree were available, since the structure has
+all the limitations metioned in caveats below.
+
+Therefore it is recommended that the of-platdata structure should be used
+only in the `probe()` method of your driver. It cannot be used in the
+`of_to_plat()` method since this is not called when platform data is
+already present.
+
+
+How to structure your driver
+----------------------------
+
+Drivers should always support devicetree as an option. The of-platdata
+feature is intended as a add-on to existing drivers.
+
+Your driver should convert the plat struct in its `probe()` method. The
+existing devicetree decoding logic should be kept in the
+`of_to_plat()` method and wrapped with `#if`.
+
+For example:
+
+.. code-block:: c
+
+    #include <dt-structs.h>
+
+    struct mmc_plat {
+    #if CONFIG_IS_ENABLED(OF_PLATDATA)
+            /* Put this first since driver model will copy the data here */
+            struct dtd_mmc dtplat;
+    #endif
+            /*
+             * Other fields can go here, to be filled in by decoding from
+             * the devicetree (or the C structures when of-platdata is used).
+             */
+            int fifo_depth;
+    };
+
+    static int mmc_of_to_plat(struct udevice *dev)
+    {
+    #if !CONFIG_IS_ENABLED(OF_PLATDATA)
+            /* Decode the devicetree data */
+            struct mmc_plat *plat = dev_get_plat(dev);
+            const void *blob = gd->fdt_blob;
+            int node = dev_of_offset(dev);
+
+            plat->fifo_depth = fdtdec_get_int(blob, node, "fifo-depth", 0);
+    #endif
+
+            return 0;
+    }
+
+    static int mmc_probe(struct udevice *dev)
+    {
+            struct mmc_plat *plat = dev_get_plat(dev);
+
+    #if CONFIG_IS_ENABLED(OF_PLATDATA)
+            /* Decode the of-platdata from the C structures */
+            struct dtd_mmc *dtplat = &plat->dtplat;
+
+            plat->fifo_depth = dtplat->fifo_depth;
+    #endif
+            /* Set up the device from the plat data */
+            writel(plat->fifo_depth, ...)
+    }
+
+    static const struct udevice_id mmc_ids[] = {
+            { .compatible = "vendor,mmc" },
+            { }
+    };
+
+    U_BOOT_DRIVER(mmc_drv) = {
+            .name           = "mmc_drv",
+            .id             = UCLASS_MMC,
+            .of_match       = mmc_ids,
+            .of_to_plat = mmc_of_to_plat,
+            .probe          = mmc_probe,
+            .priv_auto = sizeof(struct mmc_priv),
+            .plat_auto = sizeof(struct mmc_plat),
+    };
+
+    DM_DRIVER_ALIAS(mmc_drv, vendor_mmc) /* matches compatible string */
+
+Note that `struct mmc_plat` is defined in the C file, not in a header. This
+is to avoid needing to include dt-structs.h in a header file. The idea is to
+keep the use of each of-platdata struct to the smallest possible code area.
+There is just one driver C file for each struct, that can convert from the
+of-platdata struct to the standard one used by the driver.
+
+In the case where SPL_OF_PLATDATA is enabled, `plat_auto` is
+still used to allocate space for the platform data. This is different from
+the normal behaviour and is triggered by the use of of-platdata (strictly
+speaking it is a non-zero `plat_size` which triggers this).
+
+The of-platdata struct contents is copied from the C structure data to the
+start of the newly allocated area. In the case where devicetree is used,
+the platform data is allocated, and starts zeroed. In this case the
+`of_to_plat()` method should still set up the platform data (and the
+of-platdata struct will not be present).
+
+SPL must use either of-platdata or devicetree. Drivers cannot use both at
+the same time, but they must support devicetree. Supporting of-platdata is
+optional.
+
+The devicetree becomes inaccessible when CONFIG_SPL_OF_PLATDATA is enabled,
+since the devicetree access code is not compiled in. A corollary is that
+a board can only move to using of-platdata if all the drivers it uses support
+it. There would be little point in having some drivers require the device
+tree data, since then libfdt would still be needed for those drivers and
+there would be no code-size benefit.
+
+
+Build-time instantiation
+------------------------
+
+Even with of-platdata there is a fair amount of code required in driver model.
+It is possible to have U-Boot handle the instantiation of devices at build-time,
+so avoiding the need for the `device_bind()` code and some parts of
+`device_probe()`.
+
+The feature is enabled by CONFIG_OF_PLATDATA_INST.
+
+Here is an example device, as generated by dtoc::
+
+   /*
+    * Node /serial index 6
+    * driver sandbox_serial parent root_driver
+   */
+
+   #include <asm/serial.h>
+   struct sandbox_serial_plat __attribute__ ((section (".priv_data")))
+      _sandbox_serial_plat_serial = {
+      .dtplat = {
+         .sandbox_text_colour   = "cyan",
+      },
+   };
+   #include <asm/serial.h>
+   u8 _sandbox_serial_priv_serial[sizeof(struct sandbox_serial_priv)]
+      __attribute__ ((section (".priv_data")));
+   #include <serial.h>
+   u8 _sandbox_serial_uc_priv_serial[sizeof(struct serial_dev_priv)]
+      __attribute__ ((section (".priv_data")));
+
+   DM_DEVICE_INST(serial) = {
+      .driver     = DM_DRIVER_REF(sandbox_serial),
+      .name       = "sandbox_serial",
+      .plat_      = &_sandbox_serial_plat_serial,
+      .priv_      = _sandbox_serial_priv_serial,
+      .uclass     = DM_UCLASS_REF(serial),
+      .uclass_priv_ = _sandbox_serial_uc_priv_serial,
+      .uclass_node   = {
+         .prev = &DM_UCLASS_REF(serial)->dev_head,
+         .next = &DM_UCLASS_REF(serial)->dev_head,
+      },
+      .child_head   = {
+         .prev = &DM_DEVICE_REF(serial)->child_head,
+         .next = &DM_DEVICE_REF(serial)->child_head,
+      },
+      .sibling_node   = {
+         .prev = &DM_DEVICE_REF(i2c_at_0)->sibling_node,
+         .next = &DM_DEVICE_REF(spl_test)->sibling_node,
+      },
+      .seq_ = 0,
+   };
+
+Here is part of the driver, for reference::
+
+   static const struct udevice_id sandbox_serial_ids[] = {
+      { .compatible = "sandbox,serial" },
+      { }
+   };
+
+   U_BOOT_DRIVER(sandbox_serial) = {
+      .name   = "sandbox_serial",
+      .id   = UCLASS_SERIAL,
+      .of_match    = sandbox_serial_ids,
+      .of_to_plat  = sandbox_serial_of_to_plat,
+      .plat_auto   = sizeof(struct sandbox_serial_plat),
+      .priv_auto   = sizeof(struct sandbox_serial_priv),
+      .probe = sandbox_serial_probe,
+      .remove = sandbox_serial_remove,
+      .ops   = &sandbox_serial_ops,
+      .flags = DM_FLAG_PRE_RELOC,
+   };
+
+
+The `DM_DEVICE_INST()` macro declares a struct udevice so you can see that the
+members are from that struct. The private data is declared immediately above,
+as `_sandbox_serial_priv_serial`, so there is no need for run-time memory
+allocation. The #include lines are generated as well, since dtoc searches the
+U-Boot source code for the definition of `struct sandbox_serial_priv` and adds
+the relevant header so that the code will compile without errors.
+
+The `plat_` member is set to the dtv data which is declared immediately above
+the device. This is similar to how it would look without of-platdata-inst, but
+node that the `dtplat` member inside is part of the wider
+`_sandbox_serial_plat_serial` struct. This is because the driver declares its
+own platform data, and the part generated by dtoc can only be a portion of it.
+The `dtplat` part is always first in the struct. If the device has no
+`.plat_auto` field, then a simple dtv struct can be used as with this example::
+
+   static struct dtd_sandbox_clk dtv_clk_sbox = {
+      .assigned_clock_rates   = 0x141,
+      .assigned_clocks   = {0x7, 0x3},
+   };
+
+   #include <asm/clk.h>
+   u8 _sandbox_clk_priv_clk_sbox[sizeof(struct sandbox_clk_priv)]
+      __attribute__ ((section (".priv_data")));
+
+   DM_DEVICE_INST(clk_sbox) = {
+      .driver    = DM_DRIVER_REF(sandbox_clk),
+      .name      = "sandbox_clk",
+      .plat_     = &dtv_clk_sbox,
+
+Here is part of the driver, for reference::
+
+   static const struct udevice_id sandbox_clk_ids[] = {
+      { .compatible = "sandbox,clk" },
+      { }
+   };
+
+   U_BOOT_DRIVER(sandbox_clk) = {
+      .name       = "sandbox_clk",
+      .id         = UCLASS_CLK,
+      .of_match   = sandbox_clk_ids,
+      .ops        = &sandbox_clk_ops,
+      .probe      = sandbox_clk_probe,
+      .priv_auto  = sizeof(struct sandbox_clk_priv),
+   };
+
+
+You can see that `dtv_clk_sbox` just has the devicetree contents and there is
+no need for the `dtplat` separation, since the driver has no platform data of
+its own, besides that provided by the devicetree (i.e. no `.plat_auto` field).
+
+The doubly linked lists are handled by explicitly declaring the value of each
+node, as you can see with the `.prev` and `.next` values in the example above.
+Since dtoc knows the order of devices it can link them into the appropriate
+lists correctly.
+
+One of the features of driver model is the ability for a uclass to have a
+small amount of private data for each device in that uclass. This is used to
+provide a generic data structure that the uclass can use for all devices, thus
+allowing generic features to be implemented in common code. An example is I2C,
+which stores the bus speed there.
+
+Similarly, parent devices can have data associated with each of their children.
+This is used to provide information common to all children of a particular bus.
+For an I2C bus, this is used to store the I2C address of each child on the bus.
+
+This is all handled automatically by dtoc::
+
+   #include <asm/i2c.h>
+   u8 _sandbox_i2c_priv_i2c_at_0[sizeof(struct sandbox_i2c_priv)]
+      __attribute__ ((section (".priv_data")));
+   #include <i2c.h>
+   u8 _sandbox_i2c_uc_priv_i2c_at_0[sizeof(struct dm_i2c_bus)]
+      __attribute__ ((section (".priv_data")));
+
+   DM_DEVICE_INST(i2c_at_0) = {
+      .driver      = DM_DRIVER_REF(sandbox_i2c),
+      .name      = "sandbox_i2c",
+      .plat_   = &dtv_i2c_at_0,
+      .priv_      = _sandbox_i2c_priv_i2c_at_0,
+      .uclass   = DM_UCLASS_REF(i2c),
+      .uclass_priv_ = _sandbox_i2c_uc_priv_i2c_at_0,
+     ...
+
+Part of driver, for reference::
+
+   static const struct udevice_id sandbox_i2c_ids[] = {
+      { .compatible = "sandbox,i2c" },
+      { }
+   };
+
+   U_BOOT_DRIVER(sandbox_i2c) = {
+      .name   = "sandbox_i2c",
+      .id   = UCLASS_I2C,
+      .of_match = sandbox_i2c_ids,
+      .ops   = &sandbox_i2c_ops,
+      .priv_auto   = sizeof(struct sandbox_i2c_priv),
+   };
+
+Part of I2C uclass, for reference::
+
+   UCLASS_DRIVER(i2c) = {
+      .id         = UCLASS_I2C,
+      .name       = "i2c",
+      .flags      = DM_UC_FLAG_SEQ_ALIAS,
+      .post_bind  = i2c_post_bind,
+      .pre_probe  = i2c_pre_probe,
+      .post_probe = i2c_post_probe,
+      .per_device_auto   = sizeof(struct dm_i2c_bus),
+      .per_child_plat_auto   = sizeof(struct dm_i2c_chip),
+      .child_post_bind = i2c_child_post_bind,
+   };
+
+Here, `_sandbox_i2c_uc_priv_i2c_at_0` is required by the uclass but is declared
+in the device, as required by driver model. The required header file is included
+so that the code will compile without errors. A similar mechanism is used for
+child devices, but is not shown by this example.
+
+It would not be that useful to avoid binding devices but still need to allocate
+uclasses at runtime. So dtoc generates uclass instances as well::
+
+   struct list_head uclass_head = {
+      .prev = &DM_UCLASS_REF(serial)->sibling_node,
+      .next = &DM_UCLASS_REF(clk)->sibling_node,
+   };
+
+   DM_UCLASS_INST(clk) = {
+      .uc_drv      = DM_UCLASS_DRIVER_REF(clk),
+      .sibling_node   = {
+         .prev = &uclass_head,
+         .next = &DM_UCLASS_REF(i2c)->sibling_node,
+      },
+      .dev_head   = {
+         .prev = &DM_DEVICE_REF(clk_sbox)->uclass_node,
+         .next = &DM_DEVICE_REF(clk_fixed)->uclass_node,
+      },
+   };
+
+At the top is the list head. Driver model uses this on start-up, instead of
+creating its own.
+
+Below that are a set of `DM_UCLASS_INST()` macros, each declaring a
+`struct uclass`. The doubly linked lists work as for devices.
+
+All private data is placed into a `.priv_data` section so that it is contiguous
+in the resulting output binary.
+
+
+Indexes
+-------
+
+U-Boot stores drivers, devices and many other things in linker_list structures.
+These are sorted by name, so dtoc knows the order that they will appear when
+the linker runs. Each driver_info / udevice is referenced by its index in the
+linker_list array, called 'idx' in the code.
+
+When CONFIG_OF_PLATDATA_INST is enabled, idx is the udevice index, otherwise it
+is the driver_info index. In either case, indexes are used to reference devices
+using device_get_by_ofplat_idx(). This allows phandles to work as expected.
+
+
+Phases
+------
+
+U-Boot operates in several phases, typically TPL, SPL and U-Boot proper.
+The latter does not use dtoc.
+
+In some rare cases different drivers are used for two phases. For example,
+in TPL it may not be necessary to use the full PCI subsystem, so a simple
+driver can be used instead.
+
+This works in the build system simply by compiling in one driver or the
+other (e.g. PCI driver + uclass for SPL; simple_bus for TPL). But dtoc has
+no way of knowing which code is compiled in for which phase, since it does
+not inspect Makefiles or dependency graphs.
+
+So to make this work for dtoc, we need to be able to explicitly mark
+drivers with their phase. This is done by adding a macro to the driver::
+
+   /* code in tpl.c only compiled into TPL */
+   U_BOOT_DRIVER(pci_x86) = {
+      .name   = "pci_x86",
+      .id   = UCLASS_SIMPLE_BUS,
+      .of_match = of_match_ptr(tpl_fake_pci_ids),
+      DM_PHASE(tpl)
+   };
+
+
+   /* code in pci_x86.c compiled into SPL and U-Boot proper */
+   U_BOOT_DRIVER(pci_x86) = {
+      .name   = "pci_x86",
+      .id   = UCLASS_PCI,
+      .of_match = pci_x86_ids,
+      .ops   = &pci_x86_ops,
+   };
+
+
+Notice that the second driver has the same name but no DM_PHASE(), so it will be
+used for SPL and U-Boot.
+
+Note also that this only affects the code generated by dtoc. You still need to
+make sure that only the required driver is build into each phase.
+
+
+Header files
+------------
+
+With OF_PLATDATA_INST, dtoc must include the correct header file in the
+generated code for any structs that are used, so that the code will compile.
+For example, if `struct ns16550_plat` is used, the code must include the
+`ns16550.h` header file.
+
+Typically dtoc can detect the header file needed for a driver by looking
+for the structs that it uses. For example, if a driver as a `.priv_auto`
+that uses `struct ns16550_plat`, then dtoc can search header files for the
+definition of that struct and use the file.
+
+In some cases, enums are used in drivers, typically with the `.data` field
+of `struct udevice_id`. Since dtoc does not support searching for these,
+you must use the `DM_HDR()` macro to tell dtoc which header to use. This works
+as a macro included in the driver definition::
+
+   static const struct udevice_id apl_syscon_ids[] = {
+      { .compatible = "intel,apl-punit", .data = X86_SYSCON_PUNIT },
+      { }
+   };
+
+   U_BOOT_DRIVER(intel_apl_punit) = {
+      .name       = "intel_apl_punit",
+      .id         = UCLASS_SYSCON,
+      .of_match   = apl_syscon_ids,
+      .probe      = apl_punit_probe,
+      DM_HEADER(<asm/cpu.h>)    /* for X86_SYSCON_PUNIT */
+   };
+
+
+
+Caveats
+-------
+
+There are various complications with this feature which mean it should only
+be used when strictly necessary, i.e. in SPL with limited memory. Notable
+caveats include:
+
+   - Device tree does not describe data types. But the C code must define a
+     type for each property. These are guessed using heuristics which
+     are wrong in several fairly common cases. For example an 8-byte value
+     is considered to be a 2-item integer array, and is byte-swapped. A
+     boolean value that is not present means 'false', but cannot be
+     included in the structures since there is generally no mention of it
+     in the devicetree file.
+
+   - Naming of nodes and properties is automatic. This means that they follow
+     the naming in the devicetree, which may result in C identifiers that
+     look a bit strange.
+
+   - It is not possible to find a value given a property name. Code must use
+     the associated C member variable directly in the code. This makes
+     the code less robust in the face of devicetree changes. To avoid having
+     a second struct with similar members and names you need to explicitly
+     declare it as an alias with `DM_DRIVER_ALIAS()`.
+
+   - The platform data is provided to drivers as a C structure. The driver
+     must use the same structure to access the data. Since a driver
+     normally also supports devicetree it must use `#ifdef` to separate
+     out this code, since the structures are only available in SPL. This could
+     be fixed fairly easily by making the structs available outside SPL, so
+     that `IS_ENABLED()` could be used.
+
+   - With CONFIG_OF_PLATDATA_INST all binding happens at build-time, meaning
+     that (by default) it is not possible to call `device_bind()` from C code.
+     This means that all devices must have an associated devicetree node and
+     compatible string. For example if a GPIO device currently creates child
+     devices in its `bind()` method, it will not work with
+     CONFIG_OF_PLATDATA_INST. Arguably this is bad practice anyway and the
+     devicetree binding should be updated to declare compatible strings for
+     the child devices. It is possible to disable OF_PLATDATA_NO_BIND but this
+     is not recommended since it increases code size.
+
+
+Internals
+---------
+
+Generated files
+```````````````
+
+When enabled, dtoc generates the following five files:
+
+include/generated/dt-decl.h (OF_PLATDATA_INST only)
+   Contains declarations for all drivers, devices and uclasses. This allows
+   any `struct udevice`, `struct driver` or `struct uclass` to be located by its
+   name
+
+include/generated/dt-structs-gen.h
+   Contains the struct definitions for the devicetree nodes that are used. This
+   is the same as without OF_PLATDATA_INST
+
+spl/dts/dt-plat.c (only with !OF_PLATDATA_INST)
+   Contains the `U_BOOT_DRVINFO()` declarations that U-Boot uses to bind devices
+   at start-up. See above for an example
+
+spl/dts/dt-device.c (only with OF_PLATDATA_INST)
+   Contains `DM_DEVICE_INST()` declarations for each device that can be used at
+   run-time. These are declared in the file along with any private/platform data
+   that they use. Every device has an idx, as above. Since each device must be
+   part of a double-linked list, the nodes are declared in the code as well.
+
+spl/dts/dt-uclass.c (only with OF_PLATDATA_INST)
+   Contains `DM_UCLASS_INST()` declarations for each uclass that can be used at
+   run-time. These are declared in the file along with any private data
+   associated with the uclass itself (the `.priv_auto` member). Since each
+   uclass must be part of a double-linked list, the nodes are declared in the
+   code as well.
+
+The dt-structs.h file includes the generated file
+`(include/generated/dt-structs.h`) if CONFIG_SPL_OF_PLATDATA is enabled.
+Otherwise (such as in U-Boot proper) these structs are not available. This
+prevents them being used inadvertently. All usage must be bracketed with
+`#if CONFIG_IS_ENABLED(OF_PLATDATA)`.
+
+The dt-plat.c file contains the device declarations and is is built in
+spl/dt-plat.c.
+
+
+CONFIG options
+``````````````
+
+Several CONFIG options are used to control the behaviour of of-platdata, all
+available for both SPL and TPL:
+
+OF_PLATDATA
+   This is the main option which enables the of-platdata feature
+
+OF_PLATDATA_PARENT
+   This allows `device_get_parent()` to work. Without this, all devices exist as
+   direct children of the root node. This option is highly desirable (if not
+   always absolutely essential) for buses such as I2C.
+
+OF_PLATDATA_INST
+   This controls the instantiation of devices at build time. With it disabled,
+   only `U_BOOT_DRVINFO()` records are created, with U-Boot handling the binding
+   in `device_bind()` on start-up. With it enabled, only `DM_DEVICE_INST()` and
+   `DM_UCLASS_INST()` records are created, and `device_bind()` is not needed at
+   runtime.
+
+OF_PLATDATA_NO_BIND
+   This controls whether `device_bind()` is supported. It is enabled by default
+   with OF_PLATDATA_INST since code-size reduction is really the main point of
+   the feature. It can be disabled if needed but is not likely to be supported
+   in the long term.
+
+OF_PLATDATA_DRIVER_RT
+   This controls whether the `struct driver_rt` records are used by U-Boot.
+   Normally when a device is bound, U-Boot stores the device pointer in one of
+   these records. There is one for every `struct driver_info` in the system,
+   i.e. one for every device that is bound from those records. It provides a
+   way to locate a device in the code and is used by
+   `device_get_by_ofplat_idx()`. This option is always enabled with of-platdata,
+   provided OF_PLATDATA_INST is not. In that case the records are useless since
+   we don't have any `struct driver_info` records.
+
+OF_PLATDATA_RT
+   This controls whether the `struct udevice_rt` records are used by U-Boot.
+   It moves the updatable fields from `struct udevice` (currently only `flags`)
+   into a separate structure, allowing the records to be kept in read-only
+   memory. It is generally enabled if OF_PLATDATA_INST is enabled. This option
+   also controls whether the private data is used in situ, or first copied into
+   an allocated region. Again this is to allow the private data declared by
+   dtoc-generated code to be in read-only memory. Note that access to private
+   data must be done via accessor functions, such as `dev_get_priv()`, so that
+   the relocation is handled.
+
+READ_ONLY
+   This indicates that the data generated by dtoc should not be modified. Only
+   a few fields actually do get changed in U-Boot, such as device flags. This
+   option causes those to move into an allocated space (see OF_PLATDATA_RT).
+   Also, since updating doubly linked lists is generally impossible when some of
+   the nodes cannot be updated, OF_PLATDATA_NO_BIND is enabled.
+
+Data structures
+```````````````
+
+A few extra data structures are used with of-platdata:
+
+`struct udevice_rt`
+   Run-time information for devices. When OF_PLATDATA_RT is enabled, this holds
+   the flags for each device, so that `struct udevice` can remain unchanged by
+   U-Boot, and potentially reside in read-only memory. Access to flags is then
+   via functions like `dev_get_flags()` and `dev_or_flags()`. This data
+   structure is allocated on start-up, where the private data is also copied.
+   All flags values start at 0 and any changes are handled by `dev_or_flags()`
+   and `dev_bic_flags()`. It would be more correct for the flags to be set to
+   `DM_FLAG_BOUND`, or perhaps `DM_FLAG_BOUND | DM_FLAG_ALLOC_PDATA`, but since
+   there is no code to bind/unbind devices and no code to allocate/free
+   private data / platform data, it doesn't matter.
+
+`struct driver_rt`
+   Run-time information for `struct driver_info` records. When
+   OF_PLATDATA_DRIVER_RT is enabled, this holds a pointer to the device
+   created by each record. This is needed so that is it possible to locate a
+   device from C code. Specifically, the code can use `DM_DRVINFO_GET(name)` to
+   get a reference to a particular `struct driver_info`, with `name` being the
+   name of the devicetree node. This is very convenient. It is also fast, since
+   no    searching or string comparison is needed. This data structure is
+   allocated    on start-up, filled out by `device_bind()` and used by
+   `device_get_by_ofplat_idx()`.
+
+Other changes
+`````````````
+
+Some other changes are made with of-platdata:
+
+Accessor functions
+   Accessing private / platform data via functions such as `dev_get_priv()` has
+   always been encouraged. With OF_PLATDATA_RT this is essential, since the
+   `priv_` and `plat_`  (etc.) values point to the data generated by dtoc, not
+   the read-write copy that is sometimes made on start-up. Changing the
+   private / platform data  pointers has always been discouraged (the API is
+   marked internal) but with OF_PLATDATA_RT this is not currently supported in
+   general, since it assumes that all such pointers point to the relocated data.
+   Note also that the renaming of struct members to have a trailing underscore
+   was partly done to make people aware that they should not be accessed
+   directly.
+
+`gd->uclass_root_s`
+   Normally U-Boot sets up the head of the uclass list here and makes
+   `gd->uclass_root` point to it. With OF_PLATDATA_INST, dtoc generates a
+   declaration of `uclass_head` in `dt-uclass.c` since it needs to link the
+   head node into the list. In that case, `gd->uclass_root_s` is not used and
+   U-Boot just makes `gd->uclass_root` point to `uclass_head`.
+
+`gd->dm_driver_rt`
+   This holds a pointer to a list of `struct driver_rt` records, one for each
+   `struct driver_info`. The list is in alphabetical order by the name used
+   in `U_BOOT_DRVINFO(name)` and indexed by idx, with the first record having
+   an index of 0. It is only used if OF_PLATDATA_INST is not enabled. This is
+   accessed via macros so that it can be used inside IS_ENABLED(), rather than
+   requiring #ifdefs in the C code when it is not present.
+
+`gd->dm_udevice_rt`
+   This holds a pointer to a list of `struct udevice_rt` records, one for each
+   `struct udevice`. The list is in alphabetical order by the name used
+   in `DM_DEVICE_INST(name)` (a C version of the devicetree node) and indexed by
+   idx, with the first record having an index of 0. It is only used if
+   OF_PLATDATA_INST is enabled. This is accessed via macros so that it can be
+   used inside `IS_ENABLED()`, rather than requiring #ifdefs in the C code when
+   it is not present.
+
+`gd->dm_priv_base`
+   When OF_PLATDATA_RT is enabled, the private/platform data for each device is
+   copied into an allocated region by U-Boot on start-up. This points to that
+   region. All calls to accessor functions (e.g. `dev_get_priv()`) then
+   translate from the pointer provided by the caller (assumed to lie between
+   `__priv_data_start` and `__priv_data_end`) to the new allocated region. This
+   member is accessed via macros so that it can be used inside IS_ENABLED(),
+   rather than required #ifdefs in the C code when it is not present.
+
+`struct udevice->flags_`
+   When OF_PLATDATA_RT is enabled, device flags are no-longer part of
+   `struct udevice`, but are instead kept in `struct udevice_rt`, as described
+   above. Flags are accessed via functions, such as `dev_get_flags()` and
+   `dev_or_flags()`.
+
+`struct udevice->node_`
+   When OF_PLATDATA is enabled, there is no devicetree at runtime, so no need
+   for this field. It is removed, just to save space.
+
+`DM_PHASE`
+   This macro is used to indicate which phase of U-Boot a driver is intended
+   for. See above for details.
+
+`DM_HDR`
+   This macro is used to indicate which header file dtoc should use to allow
+   a driver declaration to compile correctly. See above for details.
+
+`device_get_by_ofplat_idx()`
+   There used to be a function called `device_get_by_driver_info()` which
+   looked up a `struct driver_info` pointer and returned the `struct udevice`
+   that was created from it. It was only available for use with of-platdata.
+   This has been removed in favour of `device_get_by_ofplat_idx()` which uses
+   `idx`, the index of the `struct driver_info` or `struct udevice` in the
+   linker_list. Similarly, the `struct phandle_0_arg` (etc.) structs have been
+   updated to use this index instead of a pointer to `struct driver_info`.
+
+`DM_DRVINFO_GET`
+   This has been removed since we now use indexes to obtain a driver from
+   `struct phandle_0_arg` and the like.
+
+Two-pass binding
+   The original of-platdata tried to order `U_BOOT_DRVINFO()` in the generated
+   files so as to have parents declared ahead of children. This was convenient
+   as it avoided any special code in U-Boot. With OF_PLATDATA_INST this does
+   not work as the idx value relies on using alphabetical order for everything,
+   so that dtoc and U-Boot's linker_lists agree on the idx value. Devices are
+   then bound in order of idx, having no regard to parent/child relationships.
+   For this reason, device binding now hapens in multiple passes, with parents
+   being bound before their children. This is important so that children can
+   find their parents in the bind() method if needed.
+
+Root device
+   The root device is generally bound by U-Boot but with OF_PLATDATA_INST it
+   cannot be, since binding needs to be done at build time. So in this case
+   dtoc sets up a root device using `DM_DEVICE_INST()` in `dt-device.c` and
+   U-Boot makes use of that. When OF_PLATDATA_INST is not enabled, U-Boot
+   generally ignores the root node and does not create a `U_BOOT_DRVINFO()`
+   record for it. This means that the idx numbers used by `struct driver_info`
+   (when OF_PLATDATA_INST is disabled) and the idx numbers used by
+   `struct udevice` (when OF_PLATDATA_INST is enabled) differ, since one has a
+   root node and the other does not. This does not actually matter, since only
+   one of them is actually used for any particular build, but it is worth
+   keeping in mind if comparing index values and switching OF_PLATDATA_INST on
+   and off.
+
+`__priv_data_start` and `__priv_data_end`
+   The private/platform data declared by dtoc is all collected together in
+   a linker section and these symbols mark the start and end of it. This allows
+   U-Boot to relocate the area to a new location if needed (with
+   OF_PLATDATA_RT)
+
+`dm_priv_to_rw()`
+   This function converts a private- or platform-data pointer value generated by
+   dtoc into one that can be used by U-Boot. It is a NOP unless OF_PLATDATA_RT
+   is enabled, in which case it translates the address to the relocated
+   region. See above for more information.
+
+The dm_populate_phandle_data() function that was previous needed has now been
+removed, since dtoc can address the drivers directly from dt-plat.c and does
+not need to fix up things at runtime.
+
+The pylibfdt Python module is used to access the devicetree.
+
+
+Credits
+-------
+
+This is an implementation of an idea by Tom Rini <[email protected]>.
+
+
+Future work
+-----------
+- Consider programmatically reading binding files instead of devicetree
+  contents
+- Allow IS_ENABLED() to be used in the C code instead of #if
+
+
+.. Simon Glass <[email protected]>
+.. Google, Inc
+.. 6/6/16
+.. Updated Independence Day 2016
+.. Updated 1st October 2020
+.. Updated 5th February 2021
diff --git a/doc/develop/driver-model/pci-info.rst b/doc/develop/driver-model/pci-info.rst
new file mode 100644 (file)
index 0000000..251601a
--- /dev/null
@@ -0,0 +1,172 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+PCI with Driver Model
+=====================
+
+How busses are scanned
+----------------------
+
+Any config read will end up at pci_read_config(). This uses
+uclass_get_device_by_seq() to get the PCI bus for a particular bus number.
+Bus number 0 will need to be requested first, and the alias in the device
+tree file will point to the correct device::
+
+       aliases {
+               pci0 = &pcic;
+       };
+
+       pcic: pci@0 {
+               compatible = "sandbox,pci";
+               ...
+       };
+
+
+If there is no alias the devices will be numbered sequentially in the device
+tree.
+
+The call to uclass_get_device() will cause the PCI bus to be probed.
+This does a scan of the bus to locate available devices. These devices are
+bound to their appropriate driver if available. If there is no driver, then
+they are bound to a generic PCI driver which does nothing.
+
+After probing a bus, the available devices will appear in the device tree
+under that bus.
+
+Note that this is all done on a lazy basis, as needed, so until something is
+touched on PCI (eg: a call to pci_find_devices()) it will not be probed.
+
+PCI devices can appear in the flattened device tree. If they do, their node
+often contains extra information which cannot be derived from the PCI IDs or
+PCI class of the device. Each PCI device node must have a <reg> property, as
+defined by the IEEE Std 1275-1994 PCI bus binding document v2.1. Compatible
+string list is optional and generally not needed, since PCI is discoverable
+bus, albeit there are justified exceptions. If the compatible string is
+present, matching on it takes precedence over PCI IDs and PCI classes.
+
+Note we must describe PCI devices with the same bus hierarchy as the
+hardware, otherwise driver model cannot detect the correct parent/children
+relationship during PCI bus enumeration thus PCI devices won't be bound to
+their drivers accordingly. A working example like below::
+
+       pci {
+               #address-cells = <3>;
+               #size-cells = <2>;
+               compatible = "pci-x86";
+               u-boot,dm-pre-reloc;
+               ranges = <0x02000000 0x0 0x40000000 0x40000000 0 0x80000000
+                         0x42000000 0x0 0xc0000000 0xc0000000 0 0x20000000
+                         0x01000000 0x0 0x2000 0x2000 0 0xe000>;
+
+               pcie@17,0 {
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       compatible = "pci-bridge";
+                       u-boot,dm-pre-reloc;
+                       reg = <0x0000b800 0x0 0x0 0x0 0x0>;
+
+                       topcliff@0,0 {
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               compatible = "pci-bridge";
+                               u-boot,dm-pre-reloc;
+                               reg = <0x00010000 0x0 0x0 0x0 0x0>;
+
+                               pciuart0: uart@a,1 {
+                                       compatible = "pci8086,8811.00",
+                                                       "pci8086,8811",
+                                                       "pciclass,070002",
+                                                       "pciclass,0700",
+                                                       "x86-uart";
+                                       u-boot,dm-pre-reloc;
+                                       reg = <0x00025100 0x0 0x0 0x0 0x0
+                                              0x01025110 0x0 0x0 0x0 0x0>;
+                                       ......
+                               };
+
+                               ......
+                       };
+               };
+
+               ......
+       };
+
+In this example, the root PCI bus node is the "/pci" which matches "pci-x86"
+driver. It has a subnode "pcie@17,0" with driver "pci-bridge". "pcie@17,0"
+also has subnode "topcliff@0,0" which is a "pci-bridge" too. Under that bridge,
+a PCI UART device "uart@a,1" is described. This exactly reflects the hardware
+bus hierarchy: on the root PCI bus, there is a PCIe root port which connects
+to a downstream device Topcliff chipset. Inside Topcliff chipset, it has a
+PCIe-to-PCI bridge and all the chipset integrated devices like the PCI UART
+device are on the PCI bus. Like other devices in the device tree, if we want
+to bind PCI devices before relocation, "u-boot,dm-pre-reloc" must be declared
+in each of these nodes.
+
+If PCI devices are not listed in the device tree, U_BOOT_PCI_DEVICE can be used
+to specify the driver to use for the device. The device tree takes precedence
+over U_BOOT_PCI_DEVICE. Please note with U_BOOT_PCI_DEVICE, only drivers with
+DM_FLAG_PRE_RELOC will be bound before relocation. If neither device tree nor
+U_BOOT_PCI_DEVICE is provided, the built-in driver (either pci_bridge_drv or
+pci_generic_drv) will be used.
+
+
+Sandbox
+-------
+
+With sandbox we need a device emulator for each device on the bus since there
+is no real PCI bus. This works by looking in the device tree node for an
+emulator driver. For example::
+
+       pci@1f,0 {
+               compatible = "pci-generic";
+               reg = <0xf800 0 0 0 0>;
+               sandbox,emul = <&emul_1f>;
+       };
+       pci-emul {
+               compatible = "sandbox,pci-emul-parent";
+               emul_1f: emul@1f,0 {
+                       compatible = "sandbox,swap-case";
+                       #emul-cells = <0>;
+               };
+       };
+
+This means that there is a 'sandbox,swap-case' driver at that bus position.
+Note that the first cell in the 'reg' value is the bus/device/function. See
+PCI_BDF() for the encoding (it is also specified in the IEEE Std 1275-1994
+PCI bus binding document, v2.1)
+
+The pci-emul node should go outside the pci bus node, since otherwise it will
+be scanned as a PCI device, causing confusion.
+
+When this bus is scanned we will end up with something like this::
+
+   `- * pci@0 @ 05c660c8, 0
+    `-   pci@1f,0 @ 05c661c8, 63488
+   `-   emul@1f,0 @ 05c662c8
+
+When accesses go to the pci@1f,0 device they are forwarded to its emulator.
+
+The sandbox PCI drivers also support dynamic driver binding, allowing device
+driver to declare the driver binding information via U_BOOT_PCI_DEVICE(),
+eliminating the need to provide any device tree node under the host controller
+node. It is required a "sandbox,dev-info" property must be provided in the
+host controller node for this functionality to work.
+
+.. code-block:: none
+
+       pci1: pci@1 {
+               compatible = "sandbox,pci";
+               ...
+               sandbox,dev-info = <0x08 0x00 0x1234 0x5678
+                                   0x0c 0x00 0x1234 0x5678>;
+       };
+
+The "sandbox,dev-info" property specifies all dynamic PCI devices on this bus.
+Each dynamic PCI device is encoded as 4 cells a group. The first and second
+cells are PCI device number and function number respectively. The third and
+fourth cells are PCI vendor ID and device ID respectively.
+
+When this bus is scanned we will end up with something like this::
+
+ pci        [ + ]   pci_sandbo  |-- pci1
+ pci_emul   [   ]   sandbox_sw  |   |-- sandbox_swap_case_emul
+ pci_emul   [   ]   sandbox_sw  |   `-- sandbox_swap_case_emul
diff --git a/doc/develop/driver-model/pmic-framework.rst b/doc/develop/driver-model/pmic-framework.rst
new file mode 100644 (file)
index 0000000..d24a1ba
--- /dev/null
@@ -0,0 +1,143 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. (C) Copyright 2014-2015 Samsung Electronics
+.. sectionauthor:: Przemyslaw Marczak <[email protected]>
+
+PMIC framework based on Driver Model
+====================================
+
+Introduction
+------------
+This is an introduction to driver-model multi uclass PMIC IC's support.
+At present it's based on two uclass types:
+
+UCLASS_PMIC:
+  basic uclass type for PMIC I/O, which provides common
+  read/write interface.
+UCLASS_REGULATOR:
+  additional uclass type for specific PMIC features, which are
+  Voltage/Current regulators.
+
+New files:
+
+UCLASS_PMIC:
+  - drivers/power/pmic/pmic-uclass.c
+  - include/power/pmic.h
+UCLASS_REGULATOR:
+  - drivers/power/regulator/regulator-uclass.c
+  - include/power/regulator.h
+
+Commands:
+- common/cmd_pmic.c
+- common/cmd_regulator.c
+
+How doees it work
+-----------------
+The Power Management Integrated Circuits (PMIC) are used in embedded systems
+to provide stable, precise and specific voltage power source with over-voltage
+and thermal protection circuits.
+
+The single PMIC can provide various functions by single or multiple interfaces,
+like in the example below::
+
+   -- SoC
+    |
+    |            ______________________________________
+    | BUS 0     |       Multi interface PMIC IC        |--> LDO out 1
+    | e.g.I2C0  |                                      |--> LDO out N
+    |-----------|---- PMIC device 0 (READ/WRITE ops)   |
+    | or SPI0   |    |_ REGULATOR device (ldo/... ops) |--> BUCK out 1
+    |           |    |_ CHARGER device (charger ops)   |--> BUCK out M
+    |           |    |_ MUIC device (microUSB con ops) |
+    | BUS 1     |    |_ ...                            |---> BATTERY
+    | e.g.I2C1  |                                      |
+    |-----------|---- PMIC device 1 (READ/WRITE ops)   |---> USB in 1
+    . or SPI1   |    |_ RTC device (rtc ops)           |---> USB in 2
+    .           |______________________________________|---> USB out
+    .
+
+Since U-Boot provides driver model features for I2C and SPI bus drivers,
+the PMIC devices should also support this. By the pmic and regulator API's,
+PMIC drivers can simply provide a common functions, for multi-interface and
+and multi-instance device support.
+
+Basic design assumptions:
+
+- Common I/O API:
+    UCLASS_PMIC. For the multi-function PMIC devices, this can be used as
+    parent I/O device for each IC's interface. Then, each children uses the
+    same dev for read/write.
+
+- Common regulator API:
+    UCLASS_REGULATOR. For driving the regulator attributes, auto setting
+    function or command line interface, based on kernel-style regulator device
+    tree constraints.
+
+For simple implementations, regulator drivers are not required, so the code can
+use pmic read/write directly.
+
+Pmic uclass
+-----------
+The basic information:
+
+* Uclass:   'UCLASS_PMIC'
+* Header:   'include/power/pmic.h'
+* Core:     'drivers/power/pmic/pmic-uclass.c' (config 'CONFIG_DM_PMIC')
+* Command:  'common/cmd_pmic.c' (config 'CONFIG_CMD_PMIC')
+* Example:  'drivers/power/pmic/max77686.c'
+
+For detailed API description, please refer to the header file.
+
+As an example of the pmic driver, please refer to the MAX77686 driver.
+
+Please pay attention for the driver's bind() method. Exactly the function call:
+'pmic_bind_children()', which is used to bind the regulators by using the array
+of regulator's node, compatible prefixes.
+
+The 'pmic; command also supports the new API. So the pmic command can be enabled
+by adding CONFIG_CMD_PMIC.
+The new pmic command allows to:
+- list pmic devices
+- choose the current device (like the mmc command)
+- read or write the pmic register
+- dump all pmic registers
+
+This command can use only UCLASS_PMIC devices, since this uclass is designed
+for pmic I/O operations only.
+
+For more information, please refer to the core file.
+
+Regulator uclass
+----------------
+The basic information:
+
+* Uclass: 'UCLASS_REGULATOR'
+
+* Header: 'include/power/regulator.h'
+
+* Core: 'drivers/power/regulator/regulator-uclass.c'
+  (config 'CONFIG_DM_REGULATOR')
+
+* Binding: 'doc/device-tree-bindings/regulator/regulator.txt'
+
+* Command: 'common/cmd_regulator.c' (config 'CONFIG_CMD_REGULATOR')
+
+* Example: 'drivers/power/regulator/max77686.c'
+  'drivers/power/pmic/max77686.c' (required I/O driver for the above)
+
+* Example: 'drivers/power/regulator/fixed.c'
+  (config 'CONFIG_DM_REGULATOR_FIXED')
+
+For detailed API description, please refer to the header file.
+
+For the example regulator driver, please refer to the MAX77686 regulator driver,
+but this driver can't operate without pmic's example driver, which provides an
+I/O interface for MAX77686 regulator.
+
+The second example is a fixed Voltage/Current regulator for a common use.
+
+The 'regulator' command also supports the new API. The command allow:
+- list regulator devices
+- choose the current device (like the mmc command)
+- do all regulator-specific operations
+
+For more information, please refer to the command file.
diff --git a/doc/develop/driver-model/remoteproc-framework.rst b/doc/develop/driver-model/remoteproc-framework.rst
new file mode 100644 (file)
index 0000000..566495a
--- /dev/null
@@ -0,0 +1,169 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. (C) Copyright 2015
+.. Texas Instruments Incorporated - http://www.ti.com/
+
+Remote Processor Framework
+==========================
+
+Introduction
+------------
+
+This is an introduction to driver-model for Remote Processors found
+on various System on Chip(SoCs). The term remote processor is used to
+indicate that this is not the processor on which U-Boot is operating
+on, instead is yet another processing entity that may be controlled by
+the processor on which we are functional.
+
+The simplified model depends on a single UCLASS - UCLASS_REMOTEPROC
+
+UCLASS_REMOTEPROC:
+  - drivers/remoteproc/rproc-uclass.c
+  - include/remoteproc.h
+
+Commands:
+  - common/cmd_remoteproc.c
+
+Configuration:
+  - CONFIG_REMOTEPROC is selected by drivers as needed
+  - CONFIG_CMD_REMOTEPROC for the commands if required.
+
+How does it work - The driver
+-----------------------------
+
+Overall, the driver statemachine transitions are typically as follows::
+
+           (entry)
+           +-------+
+       +---+ init  |
+       |   |       | <---------------------+
+       |   +-------+                       |
+       |                                   |
+       |                                   |
+       |   +--------+                      |
+   Load|   |  reset |                      |
+       |   |        | <----------+         |
+       |   +--------+            |         |
+       |        |Load            |         |
+       |        |                |         |
+       |   +----v----+   reset   |         |
+       +-> |         |    (opt)  |         |
+           |  Loaded +-----------+         |
+           |         |                     |
+           +----+----+                     |
+                | Start                    |
+            +---v-----+        (opt)       |
+         +->| Running |        Stop        |
+   Ping  +- |         +--------------------+
+   (opt)    +---------+
+
+(is_running does not change state)
+opt: Optional state transition implemented by driver.
+
+NOTE: It depends on the remote processor as to the exact behavior
+of the statemachine, remoteproc core does not intent to implement
+statemachine logic. Certain processors may allow start/stop without
+reloading the image in the middle, certain other processors may only
+allow us to start the processor(image from a EEPROM/OTP) etc.
+
+It is hence the responsibility of the driver to handle the requisite
+state transitions of the device as necessary.
+
+Basic design assumptions:
+
+Remote processor can operate on a certain firmware that maybe loaded
+and released from reset.
+
+The driver follows a standard UCLASS DM.
+
+in the bare minimum form:
+
+.. code-block:: c
+
+       static const struct dm_rproc_ops sandbox_testproc_ops = {
+               .load = sandbox_testproc_load,
+               .start = sandbox_testproc_start,
+       };
+
+       static const struct udevice_id sandbox_ids[] = {
+               {.compatible = "sandbox,test-processor"},
+               {}
+       };
+
+       U_BOOT_DRIVER(sandbox_testproc) = {
+               .name = "sandbox_test_proc",
+               .of_match = sandbox_ids,
+               .id = UCLASS_REMOTEPROC,
+               .ops = &sandbox_testproc_ops,
+               .probe = sandbox_testproc_probe,
+       };
+
+This allows for the device to be probed as part of the "init" command
+or invocation of 'rproc_init()' function as the system dependencies define.
+
+The driver is expected to maintain it's own statemachine which is
+appropriate for the device it maintains. It must, at the very least
+provide a load and start function. We assume here that the device
+needs to be loaded and started, else, there is no real purpose of
+using the remoteproc framework.
+
+Describing the device using platform data
+-----------------------------------------
+
+*IMPORTANT* NOTE: THIS SUPPORT IS NOT MEANT FOR USE WITH NEWER PLATFORM
+SUPPORT. THIS IS ONLY FOR LEGACY DEVICES. THIS MODE OF INITIALIZATION
+*WILL* BE EVENTUALLY REMOVED ONCE ALL NECESSARY PLATFORMS HAVE MOVED
+TO DM/FDT.
+
+Considering that many platforms are yet to move to device-tree model,
+a simplified definition of a device is as follows:
+
+.. code-block:: c
+
+       struct dm_rproc_uclass_pdata proc_3_test = {
+               .name = "proc_3_legacy",
+               .mem_type = RPROC_INTERNAL_MEMORY_MAPPED,
+               .driver_plat_data = &mydriver_data;
+       };
+
+       U_BOOT_DRVINFO(proc_3_demo) = {
+               .name = "sandbox_test_proc",
+               .plat = &proc_3_test,
+       };
+
+There can be additional data that may be desired depending on the
+remoteproc driver specific needs (for example: SoC integration
+details such as clock handle or something similar). See appropriate
+documentation for specific remoteproc driver for further details.
+These are passed via driver_plat_data.
+
+Describing the device using device tree
+---------------------------------------
+
+.. code-block: none
+
+       / {
+               ...
+               aliases {
+                       ...
+                       remoteproc0 = &rproc_1;
+                       remoteproc1 = &rproc_2;
+
+               };
+               ...
+
+               rproc_1: rproc@1 {
+                       compatible = "sandbox,test-processor";
+                       remoteproc-name = "remoteproc-test-dev1";
+               };
+
+               rproc_2: rproc@2 {
+                       compatible = "sandbox,test-processor";
+                       internal-memory-mapped;
+                       remoteproc-name = "remoteproc-test-dev2";
+               };
+               ...
+       };
+
+aliases usage is optional, but it is usually recommended to ensure the
+users have a consistent usage model for a platform.
+the compatible string used here is specific to the remoteproc driver involved.
diff --git a/doc/develop/driver-model/serial-howto.rst b/doc/develop/driver-model/serial-howto.rst
new file mode 100644 (file)
index 0000000..1469131
--- /dev/null
@@ -0,0 +1,46 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+How to port a serial driver to driver model
+===========================================
+
+Almost all of the serial drivers have been converted as at January 2016. These
+ones remain:
+
+   * serial_bfin.c
+   * serial_pxa.c
+
+The deadline for this work was the end of January 2016. If no one steps
+forward to convert these, at some point there may come a patch to remove them!
+
+Here is a suggested approach for converting your serial driver over to driver
+model. Please feel free to update this file with your ideas and suggestions.
+
+- #ifdef out all your own serial driver code (#ifndef CONFIG_DM_SERIAL)
+- Define CONFIG_DM_SERIAL for your board, vendor or architecture
+- If the board does not already use driver model, you need CONFIG_DM also
+- Your board should then build, but will not boot since there will be no serial
+  driver
+- Add the U_BOOT_DRIVER piece at the end (e.g. copy serial_s5p.c for example)
+- Add a private struct for the driver data - avoid using static variables
+- Implement each of the driver methods, perhaps by calling your old methods
+- You may need to adjust the function parameters so that the old and new
+  implementations can share most of the existing code
+- If you convert all existing users of the driver, remove the pre-driver-model
+  code
+
+In terms of patches a conversion series typically has these patches:
+- clean up / prepare the driver for conversion
+- add driver model code
+- convert at least one existing board to use driver model serial
+- (if no boards remain that don't use driver model) remove the old code
+
+This may be a good time to move your board to use device tree also. Mostly
+this involves these steps:
+
+- define CONFIG_OF_CONTROL and CONFIG_OF_SEPARATE
+- add your device tree files to arch/<arch>/dts
+- update the Makefile there
+- Add stdout-path to your /chosen device tree node if it is not already there
+- build and get u-boot-dtb.bin so you can test it
+- Your drivers can now use device tree
+- For device tree in SPL, define CONFIG_SPL_OF_CONTROL
diff --git a/doc/develop/driver-model/soc-framework.rst b/doc/develop/driver-model/soc-framework.rst
new file mode 100644 (file)
index 0000000..2609fda
--- /dev/null
@@ -0,0 +1,68 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. (C) Copyright 2020
+.. Texas Instruments Incorporated - http://www.ti.com/
+
+SOC ID Framework
+================
+
+Introduction
+------------
+
+The driver-model SOC ID framework is able to provide identification
+information about a specific SoC in use at runtime, and also provide matching
+from a set of identification information from an array. This can be useful for
+enabling small quirks in drivers that exist between SoC variants that are
+impractical to implement using device tree flags. It is based on UCLASS_SOC.
+
+UCLASS_SOC:
+  - drivers/soc/soc-uclass.c
+  - include/soc.h
+
+Configuration:
+  - CONFIG_SOC_DEVICE is selected by drivers as needed.
+
+Implementing a UCLASS_SOC provider
+----------------------------------
+
+The purpose of this framework is to allow UCLASS_SOC provider drivers to supply
+identification information about the SoC in use at runtime. The framework
+allows drivers to define soc_ops that return identification strings.  All
+soc_ops need not be defined and can be left as NULL, in which case the
+framework will return -ENOSYS and not consider the value when doing an
+soc_device_match.
+
+It is left to the driver implementor to decide how the information returned is
+determined, but in general the same SOC should always return the same set of
+identifying information. Information returned must be in the form of a NULL
+terminated string.
+
+See include/soc.h for documentation of the available soc_ops and the intended
+meaning of the values that can be returned. See drivers/soc/soc_sandbox.c for
+an example UCLASS_SOC provider driver.
+
+Using a UCLASS_SOC driver
+-------------------------
+
+The framework provides the ability to retrieve and use the identification
+strings directly. It also has the ability to return a match from a list of
+different sets of SoC data using soc_device_match.
+
+An array of 'struct soc_attr' can be defined, each containing ID information
+for a specific SoC, and when passed to soc_device_match, the identifier values
+for each entry in the list will be compared against the values provided by the
+UCLASS_SOC driver that is in use. The first entry in the list that matches all
+non-null values will be returned by soc_device_match.
+
+An example of various uses of the framework can be found at test/dm/soc.c.
+
+Describing the device using device tree
+---------------------------------------
+
+.. code-block:: none
+
+   chipid: chipid {
+        compatible = "sandbox,soc";
+   };
+
+All that is required in a DT node is a compatible for a corresponding
+UCLASS_SOC driver.
diff --git a/doc/develop/driver-model/spi-howto.rst b/doc/develop/driver-model/spi-howto.rst
new file mode 100644 (file)
index 0000000..97fbf75
--- /dev/null
@@ -0,0 +1,692 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+How to port a SPI driver to driver model
+========================================
+
+Here is a rough step-by-step guide. It is based around converting the
+exynos SPI driver to driver model (DM) and the example code is based
+around U-Boot v2014.10-rc2 (commit be9f643). This has been updated for
+v2015.04.
+
+It is quite long since it includes actual code examples.
+
+Before driver model, SPI drivers have their own private structure which
+contains 'struct spi_slave'. With driver model, 'struct spi_slave' still
+exists, but now it is 'per-child data' for the SPI bus. Each child of the
+SPI bus is a SPI slave. The information that was stored in the
+driver-specific slave structure can now be port in private data for the
+SPI bus.
+
+For example, struct tegra_spi_slave looks like this:
+
+.. code-block:: c
+
+       struct tegra_spi_slave {
+               struct spi_slave slave;
+               struct tegra_spi_ctrl *ctrl;
+       };
+
+In this case 'slave' will be in per-child data, and 'ctrl' will be in the
+SPI's buses private data.
+
+
+How long does this take?
+------------------------
+
+You should be able to complete this within 2 hours, including testing but
+excluding preparing the patches. The API is basically the same as before
+with only minor changes:
+
+- methods to set speed and mode are separated out
+- cs_info is used to get information on a chip select
+
+
+Enable driver mode for SPI and SPI flash
+----------------------------------------
+
+Add these to your board config:
+
+* CONFIG_DM_SPI
+* CONFIG_DM_SPI_FLASH
+
+
+Add the skeleton
+----------------
+
+Put this code at the bottom of your existing driver file:
+
+.. code-block:: c
+
+       struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs,
+                                         unsigned int max_hz, unsigned int mode)
+       {
+               return NULL;
+       }
+
+       struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
+                                             int spi_node)
+       {
+               return NULL;
+       }
+
+       static int exynos_spi_of_to_plat(struct udevice *dev)
+       {
+               return -ENODEV;
+       }
+
+       static int exynos_spi_probe(struct udevice *dev)
+       {
+               return -ENODEV;
+       }
+
+       static int exynos_spi_remove(struct udevice *dev)
+       {
+               return -ENODEV;
+       }
+
+       static int exynos_spi_claim_bus(struct udevice *dev)
+       {
+
+               return -ENODEV;
+       }
+
+       static int exynos_spi_release_bus(struct udevice *dev)
+       {
+
+               return -ENODEV;
+       }
+
+       static int exynos_spi_xfer(struct udevice *dev, unsigned int bitlen,
+                                  const void *dout, void *din, unsigned long flags)
+       {
+
+               return -ENODEV;
+       }
+
+       static int exynos_spi_set_speed(struct udevice *dev, uint speed)
+       {
+               return -ENODEV;
+       }
+
+       static int exynos_spi_set_mode(struct udevice *dev, uint mode)
+       {
+               return -ENODEV;
+       }
+
+       static int exynos_cs_info(struct udevice *bus, uint cs,
+                                 struct spi_cs_info *info)
+       {
+               return -EINVAL;
+       }
+
+       static const struct dm_spi_ops exynos_spi_ops = {
+               .claim_bus      = exynos_spi_claim_bus,
+               .release_bus    = exynos_spi_release_bus,
+               .xfer           = exynos_spi_xfer,
+               .set_speed      = exynos_spi_set_speed,
+               .set_mode       = exynos_spi_set_mode,
+               .cs_info        = exynos_cs_info,
+       };
+
+       static const struct udevice_id exynos_spi_ids[] = {
+               { .compatible = "samsung,exynos-spi" },
+               { }
+       };
+
+       U_BOOT_DRIVER(exynos_spi) = {
+               .name   = "exynos_spi",
+               .id     = UCLASS_SPI,
+               .of_match = exynos_spi_ids,
+               .ops    = &exynos_spi_ops,
+               .of_to_plat = exynos_spi_of_to_plat,
+               .probe  = exynos_spi_probe,
+               .remove = exynos_spi_remove,
+       };
+
+
+Replace 'exynos' in the above code with your driver name
+--------------------------------------------------------
+
+
+#ifdef out all of the code in your driver except for the above
+--------------------------------------------------------------
+
+This will allow you to get it building, which means you can work
+incrementally. Since all the methods return an error initially, there is
+less chance that you will accidentally leave something in.
+
+Also, even though your conversion is basically a rewrite, it might help
+reviewers if you leave functions in the same place in the file,
+particularly for large drivers.
+
+
+Add some includes
+-----------------
+
+Add these includes to your driver:
+
+.. code-block:: c
+
+       #include <dm.h>
+       #include <errno.h>
+
+
+Build
+-----
+
+At this point you should be able to build U-Boot for your board with the
+empty SPI driver. You still have empty methods in your driver, but we will
+write these one by one.
+
+Set up your platform data structure
+-----------------------------------
+
+This will hold the information your driver to operate, like its hardware
+address or maximum frequency.
+
+You may already have a struct like this, or you may need to create one
+from some of the #defines or global variables in the driver.
+
+Note that this information is not the run-time information. It should not
+include state that changes. It should be fixed throughout the live of
+U-Boot. Run-time information comes later.
+
+Here is what was in the exynos spi driver:
+
+.. code-block:: c
+
+       struct spi_bus {
+               enum periph_id periph_id;
+               s32 frequency;          /* Default clock frequency, -1 for none */
+               struct exynos_spi *regs;
+               int inited;             /* 1 if this bus is ready for use */
+               int node;
+               uint deactivate_delay_us;       /* Delay to wait after deactivate */
+       };
+
+Of these, inited is handled by DM and node is the device tree node, which
+DM tells you. The name is not quite right. So in this case we would use:
+
+.. code-block:: c
+
+       struct exynos_spi_plat {
+               enum periph_id periph_id;
+               s32 frequency;          /* Default clock frequency, -1 for none */
+               struct exynos_spi *regs;
+               uint deactivate_delay_us;       /* Delay to wait after deactivate */
+       };
+
+
+Write of_to_plat() [for device tree only]
+-------------------------------------------------
+
+This method will convert information in the device tree node into a C
+structure in your driver (called platform data). If you are not using
+device tree, go to 8b.
+
+DM will automatically allocate the struct for us when we are using device
+tree, but we need to tell it the size:
+
+.. code-block:: c
+
+       U_BOOT_DRIVER(spi_exynos) = {
+       ...
+               .plat_auto = sizeof(struct exynos_spi_plat),
+
+
+Here is a sample function. It gets a pointer to the platform data and
+fills in the fields from device tree.
+
+.. code-block:: c
+
+       static int exynos_spi_of_to_plat(struct udevice *bus)
+       {
+               struct exynos_spi_plat *plat = bus->plat;
+               const void *blob = gd->fdt_blob;
+               int node = dev_of_offset(bus);
+
+               plat->regs = (struct exynos_spi *)fdtdec_get_addr(blob, node, "reg");
+               plat->periph_id = pinmux_decode_periph_id(blob, node);
+
+               if (plat->periph_id == PERIPH_ID_NONE) {
+                       debug("%s: Invalid peripheral ID %d\n", __func__,
+                               plat->periph_id);
+                       return -FDT_ERR_NOTFOUND;
+               }
+
+               /* Use 500KHz as a suitable default */
+               plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
+                                               500000);
+               plat->deactivate_delay_us = fdtdec_get_int(blob, node,
+                                               "spi-deactivate-delay", 0);
+               debug("%s: regs=%p, periph_id=%d, max-frequency=%d, deactivate_delay=%d\n",
+                     __func__, plat->regs, plat->periph_id, plat->frequency,
+                     plat->deactivate_delay_us);
+
+               return 0;
+       }
+
+
+Add the platform data [non-device-tree only]
+--------------------------------------------
+
+Specify this data in a U_BOOT_DRVINFO() declaration in your board file:
+
+.. code-block:: c
+
+       struct exynos_spi_plat platdata_spi0 = {
+               .periph_id = ...
+               .frequency = ...
+               .regs = ...
+               .deactivate_delay_us = ...
+       };
+
+       U_BOOT_DRVINFO(board_spi0) = {
+               .name = "exynos_spi",
+               .plat = &platdata_spi0,
+       };
+
+You will unfortunately need to put the struct definition into a header file
+in this case so that your board file can use it.
+
+
+Add the device private data
+---------------------------
+
+Most devices have some private data which they use to keep track of things
+while active. This is the run-time information and needs to be stored in
+a structure. There is probably a structure in the driver that includes a
+'struct spi_slave', so you can use that.
+
+.. code-block:: c
+
+       struct exynos_spi_slave {
+               struct spi_slave slave;
+               struct exynos_spi *regs;
+               unsigned int freq;              /* Default frequency */
+               unsigned int mode;
+               enum periph_id periph_id;       /* Peripheral ID for this device */
+               unsigned int fifo_size;
+               int skip_preamble;
+               struct spi_bus *bus;            /* Pointer to our SPI bus info */
+               ulong last_transaction_us;      /* Time of last transaction end */
+       };
+
+
+We should rename this to make its purpose more obvious, and get rid of
+the slave structure, so we have:
+
+.. code-block:: c
+
+       struct exynos_spi_priv {
+               struct exynos_spi *regs;
+               unsigned int freq;              /* Default frequency */
+               unsigned int mode;
+               enum periph_id periph_id;       /* Peripheral ID for this device */
+               unsigned int fifo_size;
+               int skip_preamble;
+               ulong last_transaction_us;      /* Time of last transaction end */
+       };
+
+
+DM can auto-allocate this also:
+
+.. code-block:: c
+
+       U_BOOT_DRIVER(spi_exynos) = {
+       ...
+               .priv_auto = sizeof(struct exynos_spi_priv),
+
+
+Note that this is created before the probe method is called, and destroyed
+after the remove method is called. It will be zeroed when the probe
+method is called.
+
+
+Add the probe() and remove() methods
+------------------------------------
+
+Note: It's a good idea to build repeatedly as you are working, to avoid a
+huge amount of work getting things compiling at the end.
+
+The probe method is supposed to set up the hardware. U-Boot used to use
+spi_setup_slave() to do this. So take a look at this function and see
+what you can copy out to set things up.
+
+.. code-block:: c
+
+       static int exynos_spi_probe(struct udevice *bus)
+       {
+               struct exynos_spi_plat *plat = dev_get_plat(bus);
+               struct exynos_spi_priv *priv = dev_get_priv(bus);
+
+               priv->regs = plat->regs;
+               if (plat->periph_id == PERIPH_ID_SPI1 ||
+                   plat->periph_id == PERIPH_ID_SPI2)
+                       priv->fifo_size = 64;
+               else
+                       priv->fifo_size = 256;
+
+               priv->skip_preamble = 0;
+               priv->last_transaction_us = timer_get_us();
+               priv->freq = plat->frequency;
+               priv->periph_id = plat->periph_id;
+
+               return 0;
+       }
+
+This implementation doesn't actually touch the hardware, which is somewhat
+unusual for a driver. In this case we will do that when the device is
+claimed by something that wants to use the SPI bus.
+
+For remove we could shut down the clocks, but in this case there is
+nothing to do. DM frees any memory that it allocated, so we can just
+remove exynos_spi_remove() and its reference in U_BOOT_DRIVER.
+
+
+Implement set_speed()
+---------------------
+
+This should set up clocks so that the SPI bus is running at the right
+speed. With the old API spi_claim_bus() would normally do this and several
+of the following functions, so let's look at that function:
+
+.. code-block:: c
+
+       int spi_claim_bus(struct spi_slave *slave)
+       {
+               struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+               struct exynos_spi *regs = spi_slave->regs;
+               u32 reg = 0;
+               int ret;
+
+               ret = set_spi_clk(spi_slave->periph_id,
+                                               spi_slave->freq);
+               if (ret < 0) {
+                       debug("%s: Failed to setup spi clock\n", __func__);
+                       return ret;
+               }
+
+               exynos_pinmux_config(spi_slave->periph_id, PINMUX_FLAG_NONE);
+
+               spi_flush_fifo(slave);
+
+               reg = readl(&regs->ch_cfg);
+               reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L);
+
+               if (spi_slave->mode & SPI_CPHA)
+                       reg |= SPI_CH_CPHA_B;
+
+               if (spi_slave->mode & SPI_CPOL)
+                       reg |= SPI_CH_CPOL_L;
+
+               writel(reg, &regs->ch_cfg);
+               writel(SPI_FB_DELAY_180, &regs->fb_clk);
+
+               return 0;
+       }
+
+
+It sets up the speed, mode, pinmux, feedback delay and clears the FIFOs.
+With DM these will happen in separate methods.
+
+
+Here is an example for the speed part:
+
+.. code-block:: c
+
+       static int exynos_spi_set_speed(struct udevice *bus, uint speed)
+       {
+               struct exynos_spi_plat *plat = bus->plat;
+               struct exynos_spi_priv *priv = dev_get_priv(bus);
+               int ret;
+
+               if (speed > plat->frequency)
+                       speed = plat->frequency;
+               ret = set_spi_clk(priv->periph_id, speed);
+               if (ret)
+                       return ret;
+               priv->freq = speed;
+               debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq);
+
+               return 0;
+       }
+
+
+Implement set_mode()
+--------------------
+
+This should adjust the SPI mode (polarity, etc.). Again this code probably
+comes from the old spi_claim_bus(). Here is an example:
+
+.. code-block:: c
+
+       static int exynos_spi_set_mode(struct udevice *bus, uint mode)
+       {
+               struct exynos_spi_priv *priv = dev_get_priv(bus);
+               uint32_t reg;
+
+               reg = readl(&priv->regs->ch_cfg);
+               reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L);
+
+               if (mode & SPI_CPHA)
+                       reg |= SPI_CH_CPHA_B;
+
+               if (mode & SPI_CPOL)
+                       reg |= SPI_CH_CPOL_L;
+
+               writel(reg, &priv->regs->ch_cfg);
+               priv->mode = mode;
+               debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
+
+               return 0;
+       }
+
+
+Implement claim_bus()
+---------------------
+
+This is where a client wants to make use of the bus, so claims it first.
+At this point we need to make sure everything is set up ready for data
+transfer. Note that this function is wholly internal to the driver - at
+present the SPI uclass never calls it.
+
+Here again we look at the old claim function and see some code that is
+needed. It is anything unrelated to speed and mode:
+
+.. code-block:: c
+
+       static int exynos_spi_claim_bus(struct udevice *bus)
+       {
+               struct exynos_spi_priv *priv = dev_get_priv(bus);
+
+               exynos_pinmux_config(priv->periph_id, PINMUX_FLAG_NONE);
+               spi_flush_fifo(priv->regs);
+
+               writel(SPI_FB_DELAY_180, &priv->regs->fb_clk);
+
+               return 0;
+       }
+
+The spi_flush_fifo() function is in the removed part of the code, so we
+need to expose it again (perhaps with an #endif before it and '#if 0'
+after it). It only needs access to priv->regs which is why we have
+passed that in:
+
+.. code-block:: c
+
+       /**
+        * Flush spi tx, rx fifos and reset the SPI controller
+        *
+        * @param regs  Pointer to SPI registers
+        */
+       static void spi_flush_fifo(struct exynos_spi *regs)
+       {
+               clrsetbits_le32(&regs->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST);
+               clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
+               setbits_le32(&regs->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON);
+       }
+
+
+Implement release_bus()
+-----------------------
+
+This releases the bus - in our example the old code in spi_release_bus()
+is a call to spi_flush_fifo, so we add:
+
+.. code-block:: c
+
+       static int exynos_spi_release_bus(struct udevice *bus)
+       {
+               struct exynos_spi_priv *priv = dev_get_priv(bus);
+
+               spi_flush_fifo(priv->regs);
+
+               return 0;
+       }
+
+
+Implement xfer()
+----------------
+
+This is the final method that we need to create, and it is where all the
+work happens. The method parameters are the same as the old spi_xfer() with
+the addition of a 'struct udevice' so conversion is pretty easy. Start
+by copying the contents of spi_xfer() to your new xfer() method and proceed
+from there.
+
+If (flags & SPI_XFER_BEGIN) is non-zero then xfer() normally calls an
+activate function, something like this:
+
+.. code-block:: c
+
+       void spi_cs_activate(struct spi_slave *slave)
+       {
+               struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+
+               /* If it's too soon to do another transaction, wait */
+               if (spi_slave->bus->deactivate_delay_us &&
+                   spi_slave->last_transaction_us) {
+                       ulong delay_us;         /* The delay completed so far */
+                       delay_us = timer_get_us() - spi_slave->last_transaction_us;
+                       if (delay_us < spi_slave->bus->deactivate_delay_us)
+                               udelay(spi_slave->bus->deactivate_delay_us - delay_us);
+               }
+
+               clrbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
+               debug("Activate CS, bus %d\n", spi_slave->slave.bus);
+               spi_slave->skip_preamble = spi_slave->mode & SPI_PREAMBLE;
+       }
+
+The new version looks like this:
+
+.. code-block:: c
+
+       static void spi_cs_activate(struct udevice *dev)
+       {
+               struct udevice *bus = dev->parent;
+               struct exynos_spi_plat *pdata = dev_get_plat(bus);
+               struct exynos_spi_priv *priv = dev_get_priv(bus);
+
+               /* If it's too soon to do another transaction, wait */
+               if (pdata->deactivate_delay_us &&
+                   priv->last_transaction_us) {
+                       ulong delay_us;         /* The delay completed so far */
+                       delay_us = timer_get_us() - priv->last_transaction_us;
+                       if (delay_us < pdata->deactivate_delay_us)
+                               udelay(pdata->deactivate_delay_us - delay_us);
+               }
+
+               clrbits_le32(&priv->regs->cs_reg, SPI_SLAVE_SIG_INACT);
+               debug("Activate CS, bus '%s'\n", bus->name);
+               priv->skip_preamble = priv->mode & SPI_PREAMBLE;
+       }
+
+All we have really done here is change the pointers and print the device name
+instead of the bus number. Other local static functions can be treated in
+the same way.
+
+
+Set up the per-child data and child pre-probe function
+------------------------------------------------------
+
+To minimise the pain and complexity of the SPI subsystem while the driver
+model change-over is in place, struct spi_slave is used to reference a
+SPI bus slave, even though that slave is actually a struct udevice. In fact
+struct spi_slave is the device's child data. We need to make sure this space
+is available. It is possible to allocate more space that struct spi_slave
+needs, but this is the minimum.
+
+.. code-block:: c
+
+       U_BOOT_DRIVER(exynos_spi) = {
+       ...
+               .per_child_auto = sizeof(struct spi_slave),
+       }
+
+
+Optional: Set up cs_info() if you want it
+-----------------------------------------
+
+Sometimes it is useful to know whether a SPI chip select is valid, but this
+is not obvious from outside the driver. In this case you can provide a
+method for cs_info() to deal with this. If you don't provide it, then the
+device tree will be used to determine what chip selects are valid.
+
+Return -EINVAL if the supplied chip select is invalid, or 0 if it is valid.
+If you don't provide the cs_info() method, 0 is assumed for all chip selects
+that do not appear in the device tree.
+
+
+Test it
+-------
+
+Now that you have the code written and it compiles, try testing it using
+the 'sf test' command. You may need to enable CONFIG_CMD_SF_TEST for your
+board.
+
+
+Prepare patches and send them to the mailing lists
+--------------------------------------------------
+
+You can use 'tools/patman/patman' to prepare, check and send patches for
+your work. See tools/patman/README for details.
+
+A little note about SPI uclass features
+---------------------------------------
+
+The SPI uclass keeps some information about each device 'dev' on the bus:
+
+   struct dm_spi_slave_plat:
+     This is device_get_parent_plat(dev).
+     This is where the chip select number is stored, along with
+     the default bus speed and mode. It is automatically read
+     from the device tree in spi_child_post_bind(). It must not
+     be changed at run-time after being set up because platform
+     data is supposed to be immutable at run-time.
+   struct spi_slave:
+     This is device_get_parentdata(dev).
+     Already mentioned above. It holds run-time information about
+     the device.
+
+There are also some SPI uclass methods that get called behind the scenes:
+
+   spi_post_bind():
+     Called when a new bus is bound.
+     This scans the device tree for devices on the bus, and binds
+     each one. This in turn causes spi_child_post_bind() to be
+     called for each, which reads the device tree information
+     into the parent (per-child) platform data.
+   spi_child_post_bind():
+     Called when a new child is bound.
+     As mentioned above this reads the device tree information
+     into the per-child platform data
+   spi_child_pre_probe():
+     Called before a new child is probed.
+     This sets up the mode and speed in struct spi_slave by
+     copying it from the parent's platform data for this child.
+     It also sets the 'dev' pointer, needed to permit passing
+     'struct spi_slave' around the place without needing a
+     separate 'struct udevice' pointer.
+
+The above housekeeping makes it easier to write your SPI driver.
diff --git a/doc/develop/driver-model/usb-info.rst b/doc/develop/driver-model/usb-info.rst
new file mode 100644 (file)
index 0000000..24d1e81
--- /dev/null
@@ -0,0 +1,423 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+How USB works with driver model
+===============================
+
+Introduction
+------------
+
+Driver model USB support makes use of existing features but changes how
+drivers are found. This document provides some information intended to help
+understand how things work with USB in U-Boot when driver model is enabled.
+
+
+Enabling driver model for USB
+-----------------------------
+
+A new CONFIG_DM_USB option is provided to enable driver model for USB. This
+causes the USB uclass to be included, and drops the equivalent code in
+usb.c. In particular the usb_init() function is then implemented by the
+uclass.
+
+
+Support for EHCI and XHCI
+-------------------------
+
+So far OHCI is not supported. Both EHCI and XHCI drivers should be declared
+as drivers in the USB uclass. For example:
+
+.. code-block:: c
+
+       static const struct udevice_id ehci_usb_ids[] = {
+               { .compatible = "nvidia,tegra20-ehci", .data = USB_CTLR_T20 },
+               { .compatible = "nvidia,tegra30-ehci", .data = USB_CTLR_T30 },
+               { .compatible = "nvidia,tegra114-ehci", .data = USB_CTLR_T114 },
+               { }
+       };
+
+       U_BOOT_DRIVER(usb_ehci) = {
+               .name   = "ehci_tegra",
+               .id     = UCLASS_USB,
+               .of_match = ehci_usb_ids,
+               .of_to_plat = ehci_usb_of_to_plat,
+               .probe = tegra_ehci_usb_probe,
+               .remove = tegra_ehci_usb_remove,
+               .ops    = &ehci_usb_ops,
+               .plat_auto = sizeof(struct usb_plat),
+               .priv_auto = sizeof(struct fdt_usb),
+               .flags  = DM_FLAG_ALLOC_PRIV_DMA,
+       };
+
+Here ehci_usb_ids is used to list the controllers that the driver supports.
+Each has its own data value. Controllers must be in the UCLASS_USB uclass.
+
+The of_to_plat() method allows the controller driver to grab any
+necessary settings from the device tree.
+
+The ops here are ehci_usb_ops. All EHCI drivers will use these same ops in
+most cases, since they are all EHCI-compatible. For EHCI there are also some
+special operations that can be overridden when calling ehci_register().
+
+The driver can use priv_auto to set the size of its private data.
+This can hold run-time information needed by the driver for operation. It
+exists when the device is probed (not when it is bound) and is removed when
+the driver is removed.
+
+Note that usb_plat is currently only used to deal with setting up a bus
+in USB device mode (OTG operation). It can be omitted if that is not
+supported.
+
+The driver's probe() method should do the basic controller init and then
+call ehci_register() to register itself as an EHCI device. It should call
+ehci_deregister() in the remove() method. Registering a new EHCI device
+does not by itself cause the bus to be scanned.
+
+The old ehci_hcd_init() function is no-longer used. Nor is it necessary to
+set up the USB controllers from board init code. When 'usb start' is used,
+each controller will be probed and its bus scanned.
+
+XHCI works in a similar way.
+
+
+Data structures
+---------------
+
+The following primary data structures are in use:
+
+- struct usb_device:
+       This holds information about a device on the bus. All devices have
+       this structure, even the root hub. The controller itself does not
+       have this structure. You can access it for a device 'dev' with
+       dev_get_parent_priv(dev). It matches the old structure except that the
+       parent and child information is not present (since driver model
+       handles that). Once the device is set up, you can find the device
+       descriptor and current configuration descriptor in this structure.
+
+- struct usb_plat:
+       This holds platform data for a controller. So far this is only used
+       as a work-around for controllers which can act as USB devices in OTG
+       mode, since the gadget framework does not use driver model.
+
+- struct usb_dev_plat:
+       This holds platform data for a device. You can access it for a
+       device 'dev' with dev_get_parent_plat(dev). It holds the device
+       address and speed - anything that can be determined before the device
+       driver is actually set up. When probing the bus this structure is
+       used to provide essential information to the device driver.
+
+- struct usb_bus_priv:
+       This is private information for each controller, maintained by the
+       controller uclass. It is mostly used to keep track of the next
+       device address to use.
+
+Of these, only struct usb_device was used prior to driver model.
+
+
+USB buses
+---------
+
+Given a controller, you know the bus - it is the one attached to the
+controller. Each controller handles exactly one bus. Every controller has a
+root hub attached to it. This hub, which is itself a USB device, can provide
+one or more 'ports' to which additional devices can be attached. It is
+possible to power up a hub and find out which of its ports have devices
+attached.
+
+Devices are given addresses starting at 1. The root hub is always address 1,
+and from there the devices are numbered in sequence. The USB uclass takes
+care of this numbering automatically during enumeration.
+
+USB devices are enumerated by finding a device on a particular hub, and
+setting its address to the next available address. The USB bus stretches out
+in a tree structure, potentially with multiple hubs each with several ports
+and perhaps other hubs. Some hubs will have their own power since otherwise
+the 5V 500mA power supplied by the controller will not be sufficient to run
+very many devices.
+
+Enumeration in U-Boot takes a long time since devices are probed one at a
+time, and each is given sufficient time to wake up and announce itself. The
+timeouts are set for the slowest device.
+
+Up to 127 devices can be on each bus. USB has four bus speeds: low
+(1.5Mbps), full (12Mbps), high (480Mbps) which is only available with USB2
+and newer (EHCI), and super (5Gbps) which is only available with USB3 and
+newer (XHCI). If you connect a super-speed device to a high-speed hub, you
+will only get high-speed.
+
+
+USB operations
+--------------
+
+As before driver model, messages can be sent using submit_bulk_msg() and the
+like. These are now implemented by the USB uclass and route through the
+controller drivers. Note that messages are not sent to the driver of the
+device itself - i.e. they don't pass down the stack to the controller.
+U-Boot simply finds the controller to which the device is attached, and sends
+the message there with an appropriate 'pipe' value so it can be addressed
+properly. Having said that, the USB device which should receive the message
+is passed in to the driver methods, for use by sandbox. This design decision
+is open for review and the code impact of changing it is small since the
+methods are typically implemented by the EHCI and XHCI stacks.
+
+Controller drivers (in UCLASS_USB) themselves provide methods for sending
+each message type. For XHCI an additional alloc_device() method is provided
+since XHCI needs to allocate a device context before it can even read the
+device's descriptor.
+
+These methods use a 'pipe' which is a collection of bit fields used to
+describe the type of message, direction of transfer and the intended
+recipient (device number).
+
+
+USB Devices
+-----------
+
+USB devices are found using a simple algorithm which works through the
+available hubs in a depth-first search. Devices can be in any uclass, but
+are attached to a parent hub (or controller in the case of the root hub) and
+so have parent data attached to them (this is struct usb_device).
+
+By the time the device's probe() method is called, it is enumerated and is
+ready to talk to the host.
+
+The enumeration process needs to work out which driver to attach to each USB
+device. It does this by examining the device class, interface class, vendor
+ID, product ID, etc. See struct usb_driver_entry for how drivers are matched
+with USB devices - you can use the USB_DEVICE() macro to declare a USB
+driver. For example, usb_storage.c defines a USB_DEVICE() to handle storage
+devices, and it will be used for all USB devices which match.
+
+
+
+Technical details on enumeration flow
+-------------------------------------
+
+It is useful to understand precisely how a USB bus is enumerating to avoid
+confusion when dealing with USB devices.
+
+Device initialisation happens roughly like this:
+
+- At some point the 'usb start' command is run
+- This calls usb_init() which works through each controller in turn
+- The controller is probed(). This does no enumeration.
+- Then usb_scan_bus() is called. This calls usb_scan_device() to scan the
+  (only) device that is attached to the controller - a root hub
+- usb_scan_device() sets up a fake struct usb_device and calls
+  usb_setup_device(), passing the port number to be scanned, in this case
+  port 0
+- usb_setup_device() first calls usb_prepare_device() to set the device
+  address, then usb_select_config() to select the first configuration
+- at this point the device is enumerated but we do not have a real struct
+  udevice for it. But we do have the descriptor in struct usb_device so we can
+  use this to figure out what driver to use
+- back in usb_scan_device(), we call usb_find_child() to try to find an
+  existing device which matches the one we just found on the bus. This can
+  happen if the device is mentioned in the device tree, or if we previously
+  scanned the bus and so the device was created before
+- if usb_find_child() does not find an existing device, we call
+  usb_find_and_bind_driver() which tries to bind one
+- usb_find_and_bind_driver() searches all available USB drivers (declared
+  with USB_DEVICE()). If it finds a match it binds that driver to create a
+  new device.
+- If it does not, it binds a generic driver. A generic driver is good enough
+  to allow access to the device (sending it packets, etc.) but all
+  functionality will need to be implemented outside the driver model.
+- in any case, when usb_find_child() and/or usb_find_and_bind_driver() are
+  done, we have a device with the correct uclass. At this point we want to
+  probe the device
+- first we store basic information about the new device (address, port,
+  speed) in its parent platform data. We cannot store it its private data
+  since that will not exist until the device is probed.
+- then we call device_probe() which probes the device
+- the first probe step is actually the USB controller's (or USB hubs's)
+  child_pre_probe() method. This gets called before anything else and is
+  intended to set up a child device ready to be used with its parent bus. For
+  USB this calls usb_child_pre_probe() which grabs the information that was
+  stored in the parent platform data and stores it in the parent private data
+  (which is struct usb_device, a real one this time). It then calls
+  usb_select_config() again to make sure that everything about the device is
+  set up
+- note that we have called usb_select_config() twice. This is inefficient
+  but the alternative is to store additional information in the platform data.
+  The time taken is minimal and this way is simpler
+- at this point the device is set up and ready for use so far as the USB
+  subsystem is concerned
+- the device's probe() method is then called. It can send messages and do
+  whatever else it wants to make the device work.
+
+Note that the first device is always a root hub, and this must be scanned to
+find any devices. The above steps will have created a hub (UCLASS_USB_HUB),
+given it address 1 and set the configuration.
+
+For hubs, the hub uclass has a post_probe() method. This means that after
+any hub is probed, the uclass gets to do some processing. In this case
+usb_hub_post_probe() is called, and the following steps take place:
+
+- usb_hub_post_probe() calls usb_hub_scan() to scan the hub, which in turn
+  calls usb_hub_configure()
+- hub power is enabled
+- we loop through each port on the hub, performing the same steps for each
+- first, check if there is a device present. This happens in
+  usb_hub_port_connect_change(). If so, then usb_scan_device() is called to
+  scan the device, passing the appropriate port number.
+- you will recognise usb_scan_device() from the steps above. It sets up the
+  device ready for use. If it is a hub, it will scan that hub before it
+  continues here (recursively, depth-first)
+- once all hub ports are scanned in this way, the hub is ready for use and
+  all of its downstream devices also
+- additional controllers are scanned in the same way
+
+The above method has some nice properties:
+
+- the bus enumeration happens by virtue of driver model's natural device flow
+- most logic is in the USB controller and hub uclasses; the actual device
+  drivers do not need to know they are on a USB bus, at least so far as
+  enumeration goes
+- hub scanning happens automatically after a hub is probed
+
+
+Hubs
+----
+
+USB hubs are scanned as in the section above. While hubs have their own
+uclass, they share some common elements with controllers:
+
+- they both attach private data to their children (struct usb_device,
+  accessible for a child with dev_get_parent_priv(child))
+- they both use usb_child_pre_probe() to set up their children as proper USB
+  devices
+
+
+Example - Mass Storage
+----------------------
+
+As an example of a USB device driver, see usb_storage.c. It uses its own
+uclass and declares itself as follows:
+
+.. code-block:: c
+
+       U_BOOT_DRIVER(usb_mass_storage) = {
+               .name   = "usb_mass_storage",
+               .id     = UCLASS_MASS_STORAGE,
+               .of_match = usb_mass_storage_ids,
+               .probe = usb_mass_storage_probe,
+       };
+
+       static const struct usb_device_id mass_storage_id_table[] = {
+               { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
+                 .bInterfaceClass = USB_CLASS_MASS_STORAGE},
+               { }     /* Terminating entry */
+       };
+
+       USB_DEVICE(usb_mass_storage, mass_storage_id_table);
+
+The USB_DEVICE() macro attaches the given table of matching information to
+the given driver. Note that the driver is declared in U_BOOT_DRIVER() as
+'usb_mass_storage' and this must match the first parameter of USB_DEVICE.
+
+When usb_find_and_bind_driver() is called on a USB device with the
+bInterfaceClass value of USB_CLASS_MASS_STORAGE, it will automatically find
+this driver and use it.
+
+
+Counter-example: USB Ethernet
+-----------------------------
+
+As an example of the old way of doing things, see usb_ether.c. When the bus
+is scanned, all Ethernet devices will be created as generic USB devices (in
+uclass UCLASS_USB_DEV_GENERIC). Then, when the scan is completed,
+usb_host_eth_scan() will be called. This looks through all the devices on
+each bus and manually figures out which are Ethernet devices in the ways of
+yore.
+
+In fact, usb_ether should be moved to driver model. Each USB Ethernet driver
+(e.g drivers/usb/eth/asix.c) should include a USB_DEVICE() declaration, so
+that it will be found as part of normal USB enumeration. Then, instead of a
+generic USB driver, a real (driver-model-aware) driver will be used. Since
+Ethernet now supports driver model, this should be fairly easy to achieve,
+and then usb_ether.c and the usb_host_eth_scan() will melt away.
+
+
+Sandbox
+-------
+
+All driver model uclasses must have tests and USB is no exception. To
+achieve this, a sandbox USB controller is provided. This can make use of
+emulation drivers which pretend to be USB devices. Emulations are provided
+for a hub and a flash stick. These are enough to create a pretend USB bus
+(defined by the sandbox device tree sandbox.dts) which can be scanned and
+used.
+
+Tests in test/dm/usb.c make use of this feature. It allows much of the USB
+stack to be tested without real hardware being needed.
+
+Here is an example device tree fragment:
+
+.. code-block:: none
+
+       usb@1 {
+               compatible = "sandbox,usb";
+               hub {
+                       compatible = "usb-hub";
+                       usb,device-class = <USB_CLASS_HUB>;
+                       hub-emul {
+                               compatible = "sandbox,usb-hub";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               flash-stick {
+                                       reg = <0>;
+                                       compatible = "sandbox,usb-flash";
+                                       sandbox,filepath = "flash.bin";
+                               };
+                       };
+               };
+       };
+
+This defines a single controller, containing a root hub (which is required).
+The hub is emulated by a hub emulator, and the emulated hub has a single
+flash stick to emulate on one of its ports.
+
+When 'usb start' is used, the following 'dm tree' output will be available::
+
+   usb         [ + ]    `-- usb@1
+   usb_hub     [ + ]        `-- hub
+   usb_emul    [ + ]            |-- hub-emul
+   usb_emul    [ + ]            |   `-- flash-stick
+   usb_mass_st [ + ]            `-- usb_mass_storage
+
+
+This may look confusing. Most of it mirrors the device tree, but the
+'usb_mass_storage' device is not in the device tree. This is created by
+usb_find_and_bind_driver() based on the USB_DRIVER in usb_storage.c. While
+'flash-stick' is the emulation device, 'usb_mass_storage' is the real U-Boot
+USB device driver that talks to it.
+
+
+Future work
+-----------
+
+It is pretty uncommon to have a large USB bus with lots of hubs on an
+embedded system. In fact anything other than a root hub is uncommon. Still
+it would be possible to speed up enumeration in two ways:
+
+- breadth-first search would allow devices to be reset and probed in
+  parallel to some extent
+- enumeration could be lazy, in the sense that we could enumerate just the
+  root hub at first, then only progress to the next 'level' when a device is
+  used that we cannot find. This could be made easier if the devices were
+  statically declared in the device tree (which is acceptable for production
+  boards where the same, known, things are on each bus).
+
+But in common cases the current algorithm is sufficient.
+
+Other things that need doing:
+- Convert usb_ether to use driver model as described above
+- Test that keyboards work (and convert to driver model)
+- Move the USB gadget framework to driver model
+- Implement OHCI in driver model
+- Implement USB PHYs in driver model
+- Work out a clever way to provide lazy init for USB devices
+
+
+.. Simon Glass <[email protected]>
+.. 23-Mar-15
index 84914bb47bfc42a8d59983a5c8e488f429429b58..444df679578d017f67e7f78511f527f665004613 100644 (file)
@@ -10,6 +10,7 @@ Implementation
    :maxdepth: 1
 
    commands
+   driver-model/index
    global_data
    logging
    menus
diff --git a/doc/driver-model/bind.rst b/doc/driver-model/bind.rst
deleted file mode 100644 (file)
index b19661b..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-.. sectionauthor:: Patrice Chotard <[email protected]>
-
-Binding/unbinding a driver
-==========================
-
-This document aims to describe the bind and unbind commands.
-
-For debugging purpose, it should be useful to bind or unbind a driver from
-the U-boot command line.
-
-The unbind command calls the remove device driver callback and unbind the
-device from its driver.
-
-The bind command binds a device to its driver.
-
-In some cases it can be useful to be able to bind a device to a driver from
-the command line.
-The obvious example is for versatile devices such as USB gadget.
-Another use case is when the devices are not yet ready at startup and
-require some setup before the drivers are bound (ex: FPGA which bitsream is
-fetched from a mass storage or ethernet)
-
-usage:
-
-bind <node path> <driver>
-bind <class> <index> <driver>
-
-unbind <node path>
-unbind <class> <index>
-unbind <class> <index> <driver>
-
-Where:
- - <node path> is the node's device tree path
- - <class> is one of the class available in the list given by the "dm uclass"
-   command or first column of "dm tree" command.
- - <index> is the index of the parent's node (second column of "dm tree" output).
- - <driver> is the driver name to bind given by the "dm drivers" command or the by
-   the fourth column of "dm tree" output.
-
-example:
-
-bind usb_dev_generic 0 usb_ether
-unbind usb_dev_generic 0 usb_ether
-or
-unbind eth 1
-
-bind /ocp/omap_dwc3@48380000/usb@48390000 usb_ether
-unbind /ocp/omap_dwc3@48380000/usb@48390000
diff --git a/doc/driver-model/debugging.rst b/doc/driver-model/debugging.rst
deleted file mode 100644 (file)
index bbb2794..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-.. sectionauthor:: Simon Glass <[email protected]>
-
-Debugging driver model
-======================
-
-This document aims to provide help when you cannot work out why driver model is
-not doing what you expect.
-
-
-Useful techniques in general
-----------------------------
-
-Here are some useful debugging features generally.
-
-   - If you are writing a new feature, consider doing it in sandbox instead of
-     on your board. Sandbox has no limits, allows easy debugging (e.g. gdb) and
-     you can write emulators for most common devices.
-   - Put '#define DEBUG' at the top of a file, to activate all the debug() and
-     log_debug() statements in that file.
-   - Where logging is used, change the logging level, e.g. in SPL with
-     CONFIG_SPL_LOG_MAX_LEVEL=7 (which is LOGL_DEBUG) and
-     CONFIG_LOG_DEFAULT_LEVEL=7
-   - Where logging of return values is implemented with log_msg_ret(), set
-     CONFIG_LOG_ERROR_RETURN=y to see exactly where the error is happening
-   - Make sure you have a debug UART enabled - see CONFIG_DEBUG_UART. With this
-     you can get serial output (printf(), etc.) before the serial driver is
-     running.
-   - Use a JTAG emulator to set breakpoints and single-step through code
-
-Not that most of these increase code/data size somewhat when enabled.
-
-
-Failure to locate a device
---------------------------
-
-Let's say you have uclass_first_device_err() and it is not finding anything.
-
-If it is returning an error, then that gives you a clue. Look up linux/errno.h
-to see errors. Common ones are:
-
-   - -ENOMEM which indicates that memory is short. If it happens in SPL or
-     before relocation in U-Boot, check CONFIG_SPL_SYS_MALLOC_F_LEN and
-     CONFIG_SYS_MALLOC_F_LEN as they may need to be larger. Add '#define DEBUG'
-     at the very top of malloc_simple.c to get an idea of where your memory is
-     going.
-   - -EINVAL which typically indicates that something was missing or wrong in
-     the device tree node. Check that everything is correct and look at the
-     of_to_plat() method in the driver.
-
-If there is no error, you should check if the device is actually bound. Call
-dm_dump_all() just before you locate the device to make sure it exists.
-
-If it does not exist, check your device tree compatible strings match up with
-what the driver expects (in the struct udevice_id array).
-
-If you are using of-platdata (e.g. CONFIG_SPL_OF_PLATDATA), check that the
-driver name is the same as the first compatible string in the device tree (with
-invalid-variable characters converted to underscore).
-
-If you are really stuck, putting '#define LOG_DEBUG' at the top of
-drivers/core/lists.c should show you what is going on.
diff --git a/doc/driver-model/design.rst b/doc/driver-model/design.rst
deleted file mode 100644 (file)
index 4e5cecb..0000000
+++ /dev/null
@@ -1,1016 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-.. sectionauthor:: Simon Glass <[email protected]>
-
-Design Details
-==============
-
-This README contains high-level information about driver model, a unified
-way of declaring and accessing drivers in U-Boot. The original work was done
-by:
-
-   * Marek Vasut <[email protected]>
-   * Pavel Herrmann <[email protected]>
-   * Viktor Křivák <[email protected]>
-   * Tomas Hlavacek <[email protected]>
-
-This has been both simplified and extended into the current implementation
-by:
-
-   * Simon Glass <[email protected]>
-
-
-Terminology
------------
-
-Uclass
-  a group of devices which operate in the same way. A uclass provides
-  a way of accessing individual devices within the group, but always
-  using the same interface. For example a GPIO uclass provides
-  operations for get/set value. An I2C uclass may have 10 I2C ports,
-  4 with one driver, and 6 with another.
-
-Driver
-  some code which talks to a peripheral and presents a higher-level
-  interface to it.
-
-Device
-  an instance of a driver, tied to a particular port or peripheral.
-
-
-How to try it
--------------
-
-Build U-Boot sandbox and run it::
-
-   make sandbox_defconfig
-   make
-   ./u-boot -d u-boot.dtb
-
-   (type 'reset' to exit U-Boot)
-
-
-There is a uclass called 'demo'. This uclass handles
-saying hello, and reporting its status. There are two drivers in this
-uclass:
-
-   - simple: Just prints a message for hello, doesn't implement status
-   - shape: Prints shapes and reports number of characters printed as status
-
-The demo class is pretty simple, but not trivial. The intention is that it
-can be used for testing, so it will implement all driver model features and
-provide good code coverage of them. It does have multiple drivers, it
-handles parameter data and plat (data which tells the driver how
-to operate on a particular platform) and it uses private driver data.
-
-To try it, see the example session below::
-
-   =>demo hello 1
-   Hello '@' from 07981110: red 4
-   =>demo status 2
-   Status: 0
-   =>demo hello 2
-   g
-   r@
-   e@@
-   e@@@
-   n@@@@
-   g@@@@@
-   =>demo status 2
-   Status: 21
-   =>demo hello 4 ^
-     y^^^
-    e^^^^^
-   l^^^^^^^
-   l^^^^^^^
-    o^^^^^
-     w^^^
-   =>demo status 4
-   Status: 36
-   =>
-
-
-Running the tests
------------------
-
-The intent with driver model is that the core portion has 100% test coverage
-in sandbox, and every uclass has its own test. As a move towards this, tests
-are provided in test/dm. To run them, try::
-
-   ./test/py/test.py --bd sandbox --build -k ut_dm -v
-
-You should see something like this::
-
-   (venv)$ ./test/py/test.py --bd sandbox --build -k ut_dm -v
-   +make O=/root/u-boot/build-sandbox -s sandbox_defconfig
-   +make O=/root/u-boot/build-sandbox -s -j8
-   ============================= test session starts ==============================
-   platform linux2 -- Python 2.7.5, pytest-2.9.0, py-1.4.31, pluggy-0.3.1 -- /root/u-boot/venv/bin/python
-   cachedir: .cache
-   rootdir: /root/u-boot, inifile:
-   collected 199 items
-
-   test/py/tests/test_ut.py::test_ut_dm_init PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_adc_bind] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_adc_multi_channel_conversion] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_adc_multi_channel_shot] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_adc_single_channel_conversion] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_adc_single_channel_shot] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_adc_supply] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_adc_wrong_channel_selection] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_autobind] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_autobind_uclass_pdata_alloc] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_autobind_uclass_pdata_valid] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_autoprobe] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_bus_child_post_bind] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_bus_child_post_bind_uclass] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_bus_child_pre_probe_uclass] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_bus_children] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_bus_children_funcs] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_bus_children_iterators] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_bus_parent_data] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_bus_parent_data_uclass] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_bus_parent_ops] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_bus_parent_platdata] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_bus_parent_platdata_uclass] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_children] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_clk_base] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_clk_periph] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_device_get_uclass_id] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_eth] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_eth_act] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_eth_alias] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_eth_prime] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_eth_rotate] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_fdt] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_fdt_offset] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_fdt_pre_reloc] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_fdt_uclass_seq] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_gpio] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_gpio_anon] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_gpio_copy] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_gpio_leak] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_gpio_phandles] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_gpio_requestf] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_i2c_bytewise] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_i2c_find] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_i2c_offset] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_i2c_offset_len] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_i2c_probe_empty] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_i2c_read_write] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_i2c_speed] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_leak] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_led_base] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_led_gpio] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_led_label] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_lifecycle] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_mmc_base] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_net_retry] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_operations] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_ordering] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_pci_base] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_pci_busnum] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_pci_swapcase] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_platdata] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_power_pmic_get] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_power_pmic_io] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_power_regulator_autoset] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_power_regulator_autoset_list] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_power_regulator_get] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_power_regulator_set_get_current] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_power_regulator_set_get_enable] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_power_regulator_set_get_mode] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_power_regulator_set_get_voltage] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_pre_reloc] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_ram_base] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_regmap_base] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_regmap_syscon] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_remoteproc_base] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_remove] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_reset_base] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_reset_walk] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_rtc_base] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_rtc_dual] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_rtc_reset] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_rtc_set_get] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_spi_find] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_spi_flash] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_spi_xfer] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_syscon_base] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_syscon_by_driver_data] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_timer_base] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_uclass] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_uclass_before_ready] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_uclass_devices_find] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_uclass_devices_find_by_name] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_uclass_devices_get] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_uclass_devices_get_by_name] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_usb_base] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_usb_flash] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_usb_keyb] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_usb_multi] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_usb_remove] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_usb_tree] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_usb_tree_remove] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_usb_tree_reorder] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_video_base] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_video_bmp] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_video_bmp_comp] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_video_chars] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_video_context] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_video_rotation1] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_video_rotation2] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_video_rotation3] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_video_text] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_video_truetype] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_video_truetype_bs] PASSED
-   test/py/tests/test_ut.py::test_ut[ut_dm_video_truetype_scroll] PASSED
-
-   ======================= 84 tests deselected by '-kut_dm' =======================
-   ================== 115 passed, 84 deselected in 3.77 seconds ===================
-
-What is going on?
------------------
-
-Let's start at the top. The demo command is in cmd/demo.c. It does
-the usual command processing and then:
-
-.. code-block:: c
-
-       struct udevice *demo_dev;
-
-       ret = uclass_get_device(UCLASS_DEMO, devnum, &demo_dev);
-
-UCLASS_DEMO means the class of devices which implement 'demo'. Other
-classes might be MMC, or GPIO, hashing or serial. The idea is that the
-devices in the class all share a particular way of working. The class
-presents a unified view of all these devices to U-Boot.
-
-This function looks up a device for the demo uclass. Given a device
-number we can find the device because all devices have registered with
-the UCLASS_DEMO uclass.
-
-The device is automatically activated ready for use by uclass_get_device().
-
-Now that we have the device we can do things like:
-
-.. code-block:: c
-
-       return demo_hello(demo_dev, ch);
-
-This function is in the demo uclass. It takes care of calling the 'hello'
-method of the relevant driver. Bearing in mind that there are two drivers,
-this particular device may use one or other of them.
-
-The code for demo_hello() is in drivers/demo/demo-uclass.c:
-
-.. code-block:: c
-
-       int demo_hello(struct udevice *dev, int ch)
-       {
-               const struct demo_ops *ops = device_get_ops(dev);
-
-               if (!ops->hello)
-                       return -ENOSYS;
-
-               return ops->hello(dev, ch);
-       }
-
-As you can see it just calls the relevant driver method. One of these is
-in drivers/demo/demo-simple.c:
-
-.. code-block:: c
-
-       static int simple_hello(struct udevice *dev, int ch)
-       {
-               const struct dm_demo_pdata *pdata = dev_get_plat(dev);
-
-               printf("Hello from %08x: %s %d\n", map_to_sysmem(dev),
-                      pdata->colour, pdata->sides);
-
-               return 0;
-       }
-
-
-So that is a trip from top (command execution) to bottom (driver action)
-but it leaves a lot of topics to address.
-
-
-Declaring Drivers
------------------
-
-A driver declaration looks something like this (see
-drivers/demo/demo-shape.c):
-
-.. code-block:: c
-
-       static const struct demo_ops shape_ops = {
-               .hello = shape_hello,
-               .status = shape_status,
-       };
-
-       U_BOOT_DRIVER(demo_shape_drv) = {
-               .name   = "demo_shape_drv",
-               .id     = UCLASS_DEMO,
-               .ops    = &shape_ops,
-               .priv_data_size = sizeof(struct shape_data),
-       };
-
-
-This driver has two methods (hello and status) and requires a bit of
-private data (accessible through dev_get_priv(dev) once the driver has
-been probed). It is a member of UCLASS_DEMO so will register itself
-there.
-
-In U_BOOT_DRIVER it is also possible to specify special methods for bind
-and unbind, and these are called at appropriate times. For many drivers
-it is hoped that only 'probe' and 'remove' will be needed.
-
-The U_BOOT_DRIVER macro creates a data structure accessible from C,
-so driver model can find the drivers that are available.
-
-The methods a device can provide are documented in the device.h header.
-Briefly, they are:
-
-   * bind - make the driver model aware of a device (bind it to its driver)
-   * unbind - make the driver model forget the device
-   * of_to_plat - convert device tree data to plat - see later
-   * probe - make a device ready for use
-   * remove - remove a device so it cannot be used until probed again
-
-The sequence to get a device to work is bind, of_to_plat (if using
-device tree) and probe.
-
-
-Platform Data
--------------
-
-Note: platform data is the old way of doing things. It is
-basically a C structure which is passed to drivers to tell them about
-platform-specific settings like the address of its registers, bus
-speed, etc. Device tree is now the preferred way of handling this.
-Unless you have a good reason not to use device tree (the main one
-being you need serial support in SPL and don't have enough SRAM for
-the cut-down device tree and libfdt libraries) you should stay away
-from platform data.
-
-Platform data is like Linux platform data, if you are familiar with that.
-It provides the board-specific information to start up a device.
-
-Why is this information not just stored in the device driver itself? The
-idea is that the device driver is generic, and can in principle operate on
-any board that has that type of device. For example, with modern
-highly-complex SoCs it is common for the IP to come from an IP vendor, and
-therefore (for example) the MMC controller may be the same on chips from
-different vendors. It makes no sense to write independent drivers for the
-MMC controller on each vendor's SoC, when they are all almost the same.
-Similarly, we may have 6 UARTs in an SoC, all of which are mostly the same,
-but lie at different addresses in the address space.
-
-Using the UART example, we have a single driver and it is instantiated 6
-times by supplying 6 lots of platform data. Each lot of platform data
-gives the driver name and a pointer to a structure containing information
-about this instance - e.g. the address of the register space. It may be that
-one of the UARTS supports RS-485 operation - this can be added as a flag in
-the platform data, which is set for this one port and clear for the rest.
-
-Think of your driver as a generic piece of code which knows how to talk to
-a device, but needs to know where it is, any variant/option information and
-so on. Platform data provides this link between the generic piece of code
-and the specific way it is bound on a particular board.
-
-Examples of platform data include:
-
-   - The base address of the IP block's register space
-   - Configuration options, like:
-      - the SPI polarity and maximum speed for a SPI controller
-      - the I2C speed to use for an I2C device
-      - the number of GPIOs available in a GPIO device
-
-Where does the platform data come from? It is either held in a structure
-which is compiled into U-Boot, or it can be parsed from the Device Tree
-(see 'Device Tree' below).
-
-For an example of how it can be compiled in, see demo-pdata.c which
-sets up a table of driver names and their associated platform data.
-The data can be interpreted by the drivers however they like - it is
-basically a communication scheme between the board-specific code and
-the generic drivers, which are intended to work on any board.
-
-Drivers can access their data via dev->info->plat. Here is
-the declaration for the platform data, which would normally appear
-in the board file.
-
-.. code-block:: c
-
-       static const struct dm_demo_pdata red_square = {
-               .colour = "red",
-               .sides = 4.
-       };
-
-       static const struct driver_info info[] = {
-               {
-                       .name = "demo_shape_drv",
-                       .plat = &red_square,
-               },
-       };
-
-       demo1 = driver_bind(root, &info[0]);
-
-
-Device Tree
------------
-
-While plat is useful, a more flexible way of providing device data is
-by using device tree. In U-Boot you should use this where possible. Avoid
-sending patches which make use of the U_BOOT_DRVINFO() macro unless strictly
-necessary.
-
-With device tree we replace the above code with the following device tree
-fragment:
-
-.. code-block:: c
-
-       red-square {
-               compatible = "demo-shape";
-               colour = "red";
-               sides = <4>;
-       };
-
-This means that instead of having lots of U_BOOT_DRVINFO() declarations in
-the board file, we put these in the device tree. This approach allows a lot
-more generality, since the same board file can support many types of boards
-(e,g. with the same SoC) just by using different device trees. An added
-benefit is that the Linux device tree can be used, thus further simplifying
-the task of board-bring up either for U-Boot or Linux devs (whoever gets to
-the board first!).
-
-The easiest way to make this work it to add a few members to the driver:
-
-.. code-block:: c
-
-       .plat_auto = sizeof(struct dm_test_pdata),
-       .of_to_plat = testfdt_of_to_plat,
-
-The 'auto' feature allowed space for the plat to be allocated
-and zeroed before the driver's of_to_plat() method is called. The
-of_to_plat() method, which the driver write supplies, should parse
-the device tree node for this device and place it in dev->plat. Thus
-when the probe method is called later (to set up the device ready for use)
-the platform data will be present.
-
-Note that both methods are optional. If you provide an of_to_plat
-method then it will be called first (during activation). If you provide a
-probe method it will be called next. See Driver Lifecycle below for more
-details.
-
-If you don't want to have the plat automatically allocated then you
-can leave out plat_auto. In this case you can use malloc
-in your of_to_plat (or probe) method to allocate the required memory,
-and you should free it in the remove method.
-
-The driver model tree is intended to mirror that of the device tree. The
-root driver is at device tree offset 0 (the root node, '/'), and its
-children are the children of the root node.
-
-In order for a device tree to be valid, the content must be correct with
-respect to either device tree specification
-(https://www.devicetree.org/specifications/) or the device tree bindings that
-are found in the doc/device-tree-bindings directory.  When not U-Boot specific
-the bindings in this directory tend to come from the Linux Kernel.  As such
-certain design decisions may have been made already for us in terms of how
-specific devices are described and bound.  In most circumstances we wish to
-retain compatibility without additional changes being made to the device tree
-source files.
-
-Declaring Uclasses
-------------------
-
-The demo uclass is declared like this:
-
-.. code-block:: c
-
-       UCLASS_DRIVER(demo) = {
-               .id             = UCLASS_DEMO,
-       };
-
-It is also possible to specify special methods for probe, etc. The uclass
-numbering comes from include/dm/uclass-id.h. To add a new uclass, add to the
-end of the enum there, then declare your uclass as above.
-
-
-Device Sequence Numbers
------------------------
-
-U-Boot numbers devices from 0 in many situations, such as in the command
-line for I2C and SPI buses, and the device names for serial ports (serial0,
-serial1, ...). Driver model supports this numbering and permits devices
-to be locating by their 'sequence'. This numbering uniquely identifies a
-device in its uclass, so no two devices within a particular uclass can have
-the same sequence number.
-
-Sequence numbers start from 0 but gaps are permitted. For example, a board
-may have I2C buses 1, 4, 5 but no 0, 2 or 3. The choice of how devices are
-numbered is up to a particular board, and may be set by the SoC in some
-cases. While it might be tempting to automatically renumber the devices
-where there are gaps in the sequence, this can lead to confusion and is
-not the way that U-Boot works.
-
-Where a device gets its sequence number is controlled by the DM_SEQ_ALIAS
-Kconfig option, which can have a different value in U-Boot proper and SPL.
-If this option is not set, aliases are ignored.
-
-Even if CONFIG_DM_SEQ_ALIAS is enabled, the uclass must still have the
-DM_UC_FLAG_SEQ_ALIAS flag set, for its devices to be sequenced by aliases.
-
-With those options set, devices with an alias (e.g. "serial2") will get that
-sequence number (e.g. 2). Other devices get the next available number after all
-aliases and all existing numbers. This means that if there is just a single
-alias "serial2", unaliased serial devices will be assigned 3 or more, with 0 and
-1 being unused.
-
-If CONFIG_DM_SEQ_ALIAS or DM_UC_FLAG_SEQ_ALIAS are not set, all devices will get
-sequence numbers in a simple ordering starting from 0. To find the next number
-to allocate, driver model scans through to find the maximum existing number,
-then uses the next one. It does not attempt to fill in gaps.
-
-.. code-block:: none
-
-       aliases {
-               serial2 = "/serial@22230000";
-       };
-
-This indicates that in the uclass called "serial", the named node
-("/serial@22230000") will be given sequence number 2. Any command or driver
-which requests serial device 2 will obtain this device.
-
-More commonly you can use node references, which expand to the full path:
-
-.. code-block:: none
-
-       aliases {
-               serial2 = &serial_2;
-       };
-       ...
-       serial_2: serial@22230000 {
-       ...
-       };
-
-The alias resolves to the same string in this case, but this version is
-easier to read.
-
-Device sequence numbers are resolved when a device is bound and the number does
-not change for the life of the device.
-
-There are some situations where the uclass must allocate sequence numbers,
-since a strictly increase sequence (with devicetree nodes bound first) is not
-suitable. An example of this is the PCI bus. In this case, you can set the
-uclass DM_UC_FLAG_NO_AUTO_SEQ flag. With this flag set, only devices with an
-alias will be assigned a number by driver model. The rest is left to the uclass
-to sort out, e.g. when enumerating the bus.
-
-Note that changing the sequence number for a device (e.g. in a driver) is not
-permitted. If it is felt to be necessary, ask on the mailing list.
-
-Bus Drivers
------------
-
-A common use of driver model is to implement a bus, a device which provides
-access to other devices. Example of buses include SPI and I2C. Typically
-the bus provides some sort of transport or translation that makes it
-possible to talk to the devices on the bus.
-
-Driver model provides some useful features to help with implementing buses.
-Firstly, a bus can request that its children store some 'parent data' which
-can be used to keep track of child state. Secondly, the bus can define
-methods which are called when a child is probed or removed. This is similar
-to the methods the uclass driver provides. Thirdly, per-child platform data
-can be provided to specify things like the child's address on the bus. This
-persists across child probe()/remove() cycles.
-
-For consistency and ease of implementation, the bus uclass can specify the
-per-child platform data, so that it can be the same for all children of buses
-in that uclass. There are also uclass methods which can be called when
-children are bound and probed.
-
-Here an explanation of how a bus fits with a uclass may be useful. Consider
-a USB bus with several devices attached to it, each from a different (made
-up) uclass::
-
-   xhci_usb (UCLASS_USB)
-      eth (UCLASS_ETH)
-      camera (UCLASS_CAMERA)
-      flash (UCLASS_FLASH_STORAGE)
-
-Each of the devices is connected to a different address on the USB bus.
-The bus device wants to store this address and some other information such
-as the bus speed for each device.
-
-To achieve this, the bus device can use dev->parent_plat in each of its
-three children. This can be auto-allocated if the bus driver (or bus uclass)
-has a non-zero value for per_child_plat_auto. If not, then
-the bus device or uclass can allocate the space itself before the child
-device is probed.
-
-Also the bus driver can define the child_pre_probe() and child_post_remove()
-methods to allow it to do some processing before the child is activated or
-after it is deactivated.
-
-Similarly the bus uclass can define the child_post_bind() method to obtain
-the per-child platform data from the device tree and set it up for the child.
-The bus uclass can also provide a child_pre_probe() method. Very often it is
-the bus uclass that controls these features, since it avoids each driver
-having to do the same processing. Of course the driver can still tweak and
-override these activities.
-
-Note that the information that controls this behaviour is in the bus's
-driver, not the child's. In fact it is possible that child has no knowledge
-that it is connected to a bus. The same child device may even be used on two
-different bus types. As an example. the 'flash' device shown above may also
-be connected on a SATA bus or standalone with no bus::
-
-   xhci_usb (UCLASS_USB)
-      flash (UCLASS_FLASH_STORAGE)  - parent data/methods defined by USB bus
-
-   sata (UCLASS_AHCI)
-      flash (UCLASS_FLASH_STORAGE)  - parent data/methods defined by SATA bus
-
-   flash (UCLASS_FLASH_STORAGE)  - no parent data/methods (not on a bus)
-
-Above you can see that the driver for xhci_usb/sata controls the child's
-bus methods. In the third example the device is not on a bus, and therefore
-will not have these methods at all. Consider the case where the flash
-device defines child methods. These would be used for *its* children, and
-would be quite separate from the methods defined by the driver for the bus
-that the flash device is connetced to. The act of attaching a device to a
-parent device which is a bus, causes the device to start behaving like a
-bus device, regardless of its own views on the matter.
-
-The uclass for the device can also contain data private to that uclass.
-But note that each device on the bus may be a member of a different
-uclass, and this data has nothing to do with the child data for each child
-on the bus. It is the bus' uclass that controls the child with respect to
-the bus.
-
-
-Driver Lifecycle
-----------------
-
-Here are the stages that a device goes through in driver model. Note that all
-methods mentioned here are optional - e.g. if there is no probe() method for
-a device then it will not be called. A simple device may have very few
-methods actually defined.
-
-Bind stage
-^^^^^^^^^^
-
-U-Boot discovers devices using one of these two methods:
-
-- Scan the U_BOOT_DRVINFO() definitions. U-Boot looks up the name specified
-  by each, to find the appropriate U_BOOT_DRIVER() definition. In this case,
-  there is no path by which driver_data may be provided, but the U_BOOT_DRVINFO()
-  may provide plat.
-
-- Scan through the device tree definitions. U-Boot looks at top-level
-  nodes in the the device tree. It looks at the compatible string in each node
-  and uses the of_match table of the U_BOOT_DRIVER() structure to find the
-  right driver for each node. In this case, the of_match table may provide a
-  driver_data value, but plat cannot be provided until later.
-
-For each device that is discovered, U-Boot then calls device_bind() to create a
-new device, initializes various core fields of the device object such as name,
-uclass & driver, initializes any optional fields of the device object that are
-applicable such as of_offset, driver_data & plat, and finally calls the
-driver's bind() method if one is defined.
-
-At this point all the devices are known, and bound to their drivers. There
-is a 'struct udevice' allocated for all devices. However, nothing has been
-activated (except for the root device). Each bound device that was created
-from a U_BOOT_DRVINFO() declaration will hold the plat pointer specified
-in that declaration. For a bound device created from the device tree,
-plat will be NULL, but of_offset will be the offset of the device tree
-node that caused the device to be created. The uclass is set correctly for
-the device.
-
-The device's sequence number is assigned, either the requested one or the next
-available one (after all aliases are processed) if nothing particular is
-requested.
-
-The device's bind() method is permitted to perform simple actions, but
-should not scan the device tree node, not initialise hardware, nor set up
-structures or allocate memory. All of these tasks should be left for
-the probe() method.
-
-Note that compared to Linux, U-Boot's driver model has a separate step of
-probe/remove which is independent of bind/unbind. This is partly because in
-U-Boot it may be expensive to probe devices and we don't want to do it until
-they are needed, or perhaps until after relocation.
-
-Reading ofdata
-^^^^^^^^^^^^^^
-
-Most devices have data in the device tree which they can read to find out the
-base address of hardware registers and parameters relating to driver
-operation. This is called 'ofdata' (Open-Firmware data).
-
-The device's of_to_plat() implemnents allocation and reading of
-plat. A parent's ofdata is always read before a child.
-
-The steps are:
-
-   1. If priv_auto is non-zero, then the device-private space
-   is allocated for the device and zeroed. It will be accessible as
-   dev->priv. The driver can put anything it likes in there, but should use
-   it for run-time information, not platform data (which should be static
-   and known before the device is probed).
-
-   2. If plat_auto is non-zero, then the platform data space
-   is allocated. This is only useful for device tree operation, since
-   otherwise you would have to specify the platform data in the
-   U_BOOT_DRVINFO() declaration. The space is allocated for the device and
-   zeroed. It will be accessible as dev->plat.
-
-   3. If the device's uclass specifies a non-zero per_device_auto,
-   then this space is allocated and zeroed also. It is allocated for and
-   stored in the device, but it is uclass data. owned by the uclass driver.
-   It is possible for the device to access it.
-
-   4. If the device's immediate parent specifies a per_child_auto
-   then this space is allocated. This is intended for use by the parent
-   device to keep track of things related to the child. For example a USB
-   flash stick attached to a USB host controller would likely use this
-   space. The controller can hold information about the USB state of each
-   of its children.
-
-   5. If the driver provides an of_to_plat() method, then this is
-   called to convert the device tree data into platform data. This should
-   do various calls like dev_read_u32(dev, ...) to access the node and store
-   the resulting information into dev->plat. After this point, the device
-   works the same way whether it was bound using a device tree node or
-   U_BOOT_DRVINFO() structure. In either case, the platform data is now stored
-   in the plat structure. Typically you will use the
-   plat_auto feature to specify the size of the platform data
-   structure, and U-Boot will automatically allocate and zero it for you before
-   entry to of_to_plat(). But if not, you can allocate it yourself in
-   of_to_plat(). Note that it is preferable to do all the device tree
-   decoding in of_to_plat() rather than in probe(). (Apart from the
-   ugliness of mixing configuration and run-time data, one day it is possible
-   that U-Boot will cache platform data for devices which are regularly
-   de/activated).
-
-   6. The device is marked 'plat valid'.
-
-Note that ofdata reading is always done (for a child and all its parents)
-before probing starts. Thus devices go through two distinct states when
-probing: reading platform data and actually touching the hardware to bring
-the device up.
-
-Having probing separate from ofdata-reading helps deal with of-platdata, where
-the probe() method is common to both DT/of-platdata operation, but the
-of_to_plat() method is implemented differently.
-
-Another case has come up where this separate is useful. Generation of ACPI
-tables uses the of-platdata but does not want to probe the device. Probing
-would cause U-Boot to violate one of its design principles, viz that it
-should only probe devices that are used. For ACPI we want to generate a
-table for each device, even if U-Boot does not use it. In fact it may not
-even be possible to probe the device - e.g. an SD card which is not
-present will cause an error on probe, yet we still must tell Linux about
-the SD card connector in case it is used while Linux is running.
-
-It is important that the of_to_plat() method does not actually probe
-the device itself. However there are cases where other devices must be probed
-in the of_to_plat() method. An example is where a device requires a
-GPIO for it to operate. To select a GPIO obviously requires that the GPIO
-device is probed. This is OK when used by common, core devices such as GPIO,
-clock, interrupts, reset and the like.
-
-If your device relies on its parent setting up a suitable address space, so
-that dev_read_addr() works correctly, then make sure that the parent device
-has its setup code in of_to_plat(). If it has it in the probe method,
-then you cannot call dev_read_addr() from the child device's
-of_to_plat() method. Move it to probe() instead. Buses like PCI can
-fall afoul of this rule.
-
-Activation/probe
-^^^^^^^^^^^^^^^^
-
-When a device needs to be used, U-Boot activates it, by first reading ofdata
-as above and then following these steps (see device_probe()):
-
-   1. All parent devices are probed. It is not possible to activate a device
-   unless its predecessors (all the way up to the root device) are activated.
-   This means (for example) that an I2C driver will require that its bus
-   be activated.
-
-   2. The device's probe() method is called. This should do anything that
-   is required by the device to get it going. This could include checking
-   that the hardware is actually present, setting up clocks for the
-   hardware and setting up hardware registers to initial values. The code
-   in probe() can access:
-
-      - platform data in dev->plat (for configuration)
-      - private data in dev->priv (for run-time state)
-      - uclass data in dev->uclass_priv (for things the uclass stores
-        about this device)
-
-   Note: If you don't use priv_auto then you will need to
-   allocate the priv space here yourself. The same applies also to
-   plat_auto. Remember to free them in the remove() method.
-
-   3. The device is marked 'activated'
-
-   4. The uclass's post_probe() method is called, if one exists. This may
-   cause the uclass to do some housekeeping to record the device as
-   activated and 'known' by the uclass.
-
-Running stage
-^^^^^^^^^^^^^
-
-The device is now activated and can be used. From now until it is removed
-all of the above structures are accessible. The device appears in the
-uclass's list of devices (so if the device is in UCLASS_GPIO it will appear
-as a device in the GPIO uclass). This is the 'running' state of the device.
-
-Removal stage
-^^^^^^^^^^^^^
-
-When the device is no-longer required, you can call device_remove() to
-remove it. This performs the probe steps in reverse:
-
-   1. The uclass's pre_remove() method is called, if one exists. This may
-   cause the uclass to do some housekeeping to record the device as
-   deactivated and no-longer 'known' by the uclass.
-
-   2. All the device's children are removed. It is not permitted to have
-   an active child device with a non-active parent. This means that
-   device_remove() is called for all the children recursively at this point.
-
-   3. The device's remove() method is called. At this stage nothing has been
-   deallocated so platform data, private data and the uclass data will all
-   still be present. This is where the hardware can be shut down. It is
-   intended that the device be completely inactive at this point, For U-Boot
-   to be sure that no hardware is running, it should be enough to remove
-   all devices.
-
-   4. The device memory is freed (platform data, private data, uclass data,
-   parent data).
-
-   Note: Because the platform data for a U_BOOT_DRVINFO() is defined with a
-   static pointer, it is not de-allocated during the remove() method. For
-   a device instantiated using the device tree data, the platform data will
-   be dynamically allocated, and thus needs to be deallocated during the
-   remove() method, either:
-
-      - if the plat_auto is non-zero, the deallocation happens automatically
-        within the driver model core in the unbind stage; or
-
-      - when plat_auto is 0, both the allocation (in probe()
-        or preferably of_to_plat()) and the deallocation in remove()
-        are the responsibility of the driver author.
-
-   5. The device is marked inactive. Note that it is still bound, so the
-   device structure itself is not freed at this point. Should the device be
-   activated again, then the cycle starts again at step 2 above.
-
-Unbind stage
-^^^^^^^^^^^^
-
-The device is unbound. This is the step that actually destroys the device.
-If a parent has children these will be destroyed first. After this point
-the device does not exist and its memory has be deallocated.
-
-
-Special cases for removal
--------------------------
-
-Some devices need to do clean-up before the OS is called. For example, a USB
-driver may want to stop the bus. This can be done in the remove() method.
-Some special flags are used to determine whether to remove the device:
-
-   DM_FLAG_OS_PREPARE - indicates that the device needs to get ready for OS
-          boot. The device will be removed just before the OS is booted
-   DM_REMOVE_ACTIVE_DMA - indicates that the device uses DMA. This is
-          effectively the same as DM_FLAG_OS_PREPARE, so the device is removed
-          before the OS is booted
-   DM_FLAG_VITAL - indicates that the device is 'vital' to the operation of
-          other devices. It is possible to remove this device after all regular
-          devices are removed. This is useful e.g. for a clock, which need to
-          be active during the device-removal phase.
-
-The dm_remove_devices_flags() function can be used to remove devices based on
-their driver flags.
-
-Data Structures
----------------
-
-Driver model uses a doubly-linked list as the basic data structure. Some
-nodes have several lists running through them. Creating a more efficient
-data structure might be worthwhile in some rare cases, once we understand
-what the bottlenecks are.
-
-
-Changes since v1
-----------------
-
-For the record, this implementation uses a very similar approach to the
-original patches, but makes at least the following changes:
-
-- Tried to aggressively remove boilerplate, so that for most drivers there
-  is little or no 'driver model' code to write.
-- Moved some data from code into data structure - e.g. store a pointer to
-  the driver operations structure in the driver, rather than passing it
-  to the driver bind function.
-- Rename some structures to make them more similar to Linux (struct udevice
-  instead of struct instance, struct plat, etc.)
-- Change the name 'core' to 'uclass', meaning U-Boot class. It seems that
-  this concept relates to a class of drivers (or a subsystem). We shouldn't
-  use 'class' since it is a C++ reserved word, so U-Boot class (uclass) seems
-  better than 'core'.
-- Remove 'struct driver_instance' and just use a single 'struct udevice'.
-  This removes a level of indirection that doesn't seem necessary.
-- Built in device tree support, to avoid the need for plat
-- Removed the concept of driver relocation, and just make it possible for
-  the new driver (created after relocation) to access the old driver data.
-  I feel that relocation is a very special case and will only apply to a few
-  drivers, many of which can/will just re-init anyway. So the overhead of
-  dealing with this might not be worth it.
-- Implemented a GPIO system, trying to keep it simple
-
-
-Pre-Relocation Support
-----------------------
-
-For pre-relocation we simply call the driver model init function. Only
-drivers marked with DM_FLAG_PRE_RELOC or the device tree 'u-boot,dm-pre-reloc'
-property are initialised prior to relocation. This helps to reduce the driver
-model overhead. This flag applies to SPL and TPL as well, if device tree is
-enabled (CONFIG_OF_CONTROL) there.
-
-Note when device tree is enabled, the device tree 'u-boot,dm-pre-reloc'
-property can provide better control granularity on which device is bound
-before relocation. While with DM_FLAG_PRE_RELOC flag of the driver all
-devices with the same driver are bound, which requires allocation a large
-amount of memory. When device tree is not used, DM_FLAG_PRE_RELOC is the
-only way for statically declared devices via U_BOOT_DRVINFO() to be bound
-prior to relocation.
-
-It is possible to limit this to specific relocation steps, by using
-the more specialized 'u-boot,dm-spl' and 'u-boot,dm-tpl' flags
-in the device tree node. For U-Boot proper you can use 'u-boot,dm-pre-proper'
-which means that it will be processed (and a driver bound) in U-Boot proper
-prior to relocation, but will not be available in SPL or TPL.
-
-To reduce the size of SPL and TPL, only the nodes with pre-relocation properties
-('u-boot,dm-pre-reloc', 'u-boot,dm-spl' or 'u-boot,dm-tpl') are keept in their
-device trees (see README.SPL for details); the remaining nodes are always bound.
-
-Then post relocation we throw that away and re-init driver model again.
-For drivers which require some sort of continuity between pre- and
-post-relocation devices, we can provide access to the pre-relocation
-device pointers, but this is not currently implemented (the root device
-pointer is saved but not made available through the driver model API).
-
-
-SPL Support
------------
-
-Driver model can operate in SPL. Its efficient implementation and small code
-size provide for a small overhead which is acceptable for all but the most
-constrained systems.
-
-To enable driver model in SPL, define CONFIG_SPL_DM. You might want to
-consider the following option also. See the main README for more details.
-
-   - CONFIG_SYS_MALLOC_SIMPLE
-   - CONFIG_DM_WARN
-   - CONFIG_DM_DEVICE_REMOVE
-   - CONFIG_DM_STDIO
-
-
-Enabling Driver Model
----------------------
-
-Driver model is being brought into U-Boot gradually. As each subsystems gets
-support, a uclass is created and a CONFIG to enable use of driver model for
-that subsystem.
-
-For example CONFIG_DM_SERIAL enables driver model for serial. With that
-defined, the old serial support is not enabled, and your serial driver must
-conform to driver model. With that undefined, the old serial support is
-enabled and driver model is not available for serial. This means that when
-you convert a driver, you must either convert all its boards, or provide for
-the driver to be compiled both with and without driver model (generally this
-is not very hard).
-
-See the main README for full details of the available driver model CONFIG
-options.
-
-
-Things to punt for later
-------------------------
-
-Uclasses are statically numbered at compile time. It would be possible to
-change this to dynamic numbering, but then we would require some sort of
-lookup service, perhaps searching by name. This is slightly less efficient
-so has been left out for now. One small advantage of dynamic numbering might
-be fewer merge conflicts in uclass-id.h.
diff --git a/doc/driver-model/ethernet.rst b/doc/driver-model/ethernet.rst
deleted file mode 100644 (file)
index cdbccca..0000000
+++ /dev/null
@@ -1,321 +0,0 @@
-Ethernet Driver Guide
-=======================
-
-The networking stack in Das U-Boot is designed for multiple network devices
-to be easily added and controlled at runtime.  This guide is meant for people
-who wish to review the net driver stack with an eye towards implementing your
-own ethernet device driver.  Here we will describe a new pseudo 'APE' driver.
-
-Most existing drivers do already - and new network driver MUST - use the
-U-Boot core driver model. Generic information about this can be found in
-doc/driver-model/design.rst, this document will thus focus on the network
-specific code parts.
-Some drivers are still using the old Ethernet interface, differences between
-the two and hints about porting will be handled at the end.
-
-Driver framework
-------------------
-
-A network driver following the driver model must declare itself using
-the UCLASS_ETH .id field in the U-Boot driver struct:
-
-.. code-block:: c
-
-       U_BOOT_DRIVER(eth_ape) = {
-               .name                   = "eth_ape",
-               .id                     = UCLASS_ETH,
-               .of_match               = eth_ape_ids,
-               .of_to_plat     = eth_ape_of_to_plat,
-               .probe                  = eth_ape_probe,
-               .ops                    = &eth_ape_ops,
-               .priv_auto      = sizeof(struct eth_ape_priv),
-               .plat_auto = sizeof(struct eth_ape_pdata),
-               .flags                  = DM_FLAG_ALLOC_PRIV_DMA,
-       };
-
-struct eth_ape_priv contains runtime per-instance data, like buffers, pointers
-to current descriptors, current speed settings, pointers to PHY related data
-(like struct mii_dev) and so on. Declaring its size in .priv_auto
-will let the driver framework allocate it at the right time.
-It can be retrieved using a dev_get_priv(dev) call.
-
-struct eth_ape_pdata contains static platform data, like the MMIO base address,
-a hardware variant, the MAC address. ``struct eth_pdata eth_pdata``
-as the first member of this struct helps to avoid duplicated code.
-If you don't need any more platform data beside the standard member,
-just use sizeof(struct eth_pdata) for the plat_auto.
-
-PCI devices add a line pointing to supported vendor/device ID pairs:
-
-.. code-block:: c
-
-       static struct pci_device_id supported[] = {
-               { PCI_DEVICE(PCI_VENDOR_ID_APE, 0x4223) },
-               {}
-       };
-
-       U_BOOT_PCI_DEVICE(eth_ape, supported);
-
-It is also possible to declare support for a whole class of PCI devices::
-
-       { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_SDHCI << 8, 0xffff00) },
-
-Device probing and instantiation will be handled by the driver model framework,
-so follow the guidelines there. The probe() function would initialise the
-platform specific parts of the hardware, like clocks, resets, GPIOs, the MDIO
-bus. Also it would take care of any special PHY setup (power rails, enable
-bits for internal PHYs, etc.).
-
-Driver methods
-----------------
-
-The real work will be done in the driver method functions the driver provides
-by defining the members of struct eth_ops:
-
-.. code-block:: c
-
-       struct eth_ops {
-               int (*start)(struct udevice *dev);
-               int (*send)(struct udevice *dev, void *packet, int length);
-               int (*recv)(struct udevice *dev, int flags, uchar **packetp);
-               int (*free_pkt)(struct udevice *dev, uchar *packet, int length);
-               void (*stop)(struct udevice *dev);
-               int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
-               int (*write_hwaddr)(struct udevice *dev);
-               int (*read_rom_hwaddr)(struct udevice *dev);
-       };
-
-An up-to-date version of this struct together with more information can be
-found in include/net.h.
-
-Only start, stop, send and recv are required, the rest are optional and are
-handled by generic code or ignored if not provided.
-
-The **start** function initialises the hardware and gets it ready for send/recv
-operations.  You often do things here such as resetting the MAC
-and/or PHY, and waiting for the link to autonegotiate.  You should also take
-the opportunity to program the device's MAC address with the enetaddr member
-of the generic struct eth_pdata (which would be the first member of your
-own plat struct). This allows the rest of U-Boot to dynamically change
-the MAC address and have the new settings be respected.
-
-The **send** function does what you think -- transmit the specified packet
-whose size is specified by length (in bytes). The packet buffer can (and
-will!) be reused for subsequent calls to send(), so it must be no longer
-used when the send() function returns. The easiest way to achieve this is
-to wait until the transmission is complete. Alternatively, if supported by
-the hardware, just waiting for the buffer to be consumed (by some DMA engine)
-might be an option as well.
-Another way of consuming the buffer could be to copy the data to be send,
-then just queue the copied packet (for instance handing it over to a DMA
-engine), and return immediately afterwards.
-In any case you should leave the state such that the send function can be
-called multiple times in a row.
-
-The **recv** function polls for availability of a new packet. If none is
-available, it must return with -EAGAIN.
-If a packet has been received, make sure it is accessible to the CPU
-(invalidate caches if needed), then write its address to the packetp pointer,
-and return the length. If there is an error (receive error, too short or too
-long packet), return 0 if you require the packet to be cleaned up normally,
-or a negative error code otherwise (cleanup not necessary or already done).
-The U-Boot network stack will then process the packet.
-
-If **free_pkt** is defined, U-Boot will call it after a received packet has
-been processed, so the packet buffer can be freed or recycled. Typically you
-would hand it back to the hardware to acquire another packet. free_pkt() will
-be called after recv(), for the same packet, so you don't necessarily need
-to infer the buffer to free from the ``packet`` pointer, but can rely on that
-being the last packet that recv() handled.
-The common code sets up packet buffers for you already in the .bss
-(net_rx_packets), so there should be no need to allocate your own. This doesn't
-mean you must use the net_rx_packets array however; you're free to use any
-buffer you wish.
-
-The **stop** function should turn off / disable the hardware and place it back
-in its reset state.  It can be called at any time (before any call to the
-related start() function), so make sure it can handle this sort of thing.
-
-The (optional) **write_hwaddr** function should program the MAC address stored
-in pdata->enetaddr into the Ethernet controller.
-
-So the call graph at this stage would look something like:
-
-.. code-block:: c
-
-       (some net operation (ping / tftp / whatever...))
-       eth_init()
-               ops->start()
-       eth_send()
-               ops->send()
-       eth_rx()
-               ops->recv()
-               (process packet)
-               if (ops->free_pkt)
-                       ops->free_pkt()
-       eth_halt()
-               ops->stop()
-
-
-CONFIG_PHYLIB / CONFIG_CMD_MII
---------------------------------
-
-If your device supports banging arbitrary values on the MII bus (pretty much
-every device does), you should add support for the mii command.  Doing so is
-fairly trivial and makes debugging mii issues a lot easier at runtime.
-
-In your driver's ``probe()`` function, add a call to mdio_alloc() and
-mdio_register() like so:
-
-.. code-block:: c
-
-       bus = mdio_alloc();
-       if (!bus) {
-               ...
-               return -ENOMEM;
-       }
-
-       bus->read = ape_mii_read;
-       bus->write = ape_mii_write;
-       mdio_register(bus);
-
-And then define the mii_read and mii_write functions if you haven't already.
-Their syntax is straightforward::
-
-       int mii_read(struct mii_dev *bus, int addr, int devad, int reg);
-       int mii_write(struct mii_dev *bus, int addr, int devad, int reg,
-                     u16 val);
-
-The read function should read the register 'reg' from the phy at address 'addr'
-and return the result to its caller.  The implementation for the write function
-should logically follow.
-
-................................................................
-
-Legacy network drivers
-------------------------
-
-!!! WARNING !!!
-
-This section below describes the old way of doing things. No new Ethernet
-drivers should be implemented this way. All new drivers should be written
-against the U-Boot core driver model, as described above.
-
-The actual callback functions are fairly similar, the differences are:
-
-- ``start()`` is called ``init()``
-- ``stop()`` is called ``halt()``
-- The ``recv()`` function must loop until all packets have been received, for
-  each packet it must call the net_process_received_packet() function,
-  handing it over the pointer and the length. Afterwards it should free
-  the packet, before checking for new data.
-
-For porting an old driver to the new driver model, split the existing recv()
-function into the actual new recv() function, just fetching **one** packet,
-remove the call to net_process_received_packet(), then move the packet
-cleanup into the ``free_pkt()`` function.
-
-Registering the driver and probing a device is handled very differently,
-follow the recommendations in the driver model design documentation for
-instructions on how to port this over. For the records, the old way of
-initialising a network driver is as follows:
-
-Old network driver registration
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When U-Boot initializes, it will call the common function eth_initialize().
-This will in turn call the board-specific board_eth_init() (or if that fails,
-the cpu-specific cpu_eth_init()).  These board-specific functions can do random
-system handling, but ultimately they will call the driver-specific register
-function which in turn takes care of initializing that particular instance.
-
-Keep in mind that you should code the driver to avoid storing state in global
-data as someone might want to hook up two of the same devices to one board.
-Any such information that is specific to an interface should be stored in a
-private, driver-defined data structure and pointed to by eth->priv (see below).
-
-So the call graph at this stage would look something like:
-
-.. code-block:: c
-
-       board_init()
-               eth_initialize()
-                       board_eth_init() / cpu_eth_init()
-                               driver_register()
-                                       initialize eth_device
-                                       eth_register()
-
-At this point in time, the only thing you need to worry about is the driver's
-register function.  The pseudo code would look something like:
-
-.. code-block:: c
-
-       int ape_register(struct bd_info *bis, int iobase)
-       {
-               struct ape_priv *priv;
-               struct eth_device *dev;
-               struct mii_dev *bus;
-
-               priv = malloc(sizeof(*priv));
-               if (priv == NULL)
-                       return -ENOMEM;
-
-               dev = malloc(sizeof(*dev));
-               if (dev == NULL) {
-                       free(priv);
-                       return -ENOMEM;
-               }
-
-               /* setup whatever private state you need */
-
-               memset(dev, 0, sizeof(*dev));
-               sprintf(dev->name, "APE");
-
-               /*
-                * if your device has dedicated hardware storage for the
-                * MAC, read it and initialize dev->enetaddr with it
-                */
-               ape_mac_read(dev->enetaddr);
-
-               dev->iobase = iobase;
-               dev->priv = priv;
-               dev->init = ape_init;
-               dev->halt = ape_halt;
-               dev->send = ape_send;
-               dev->recv = ape_recv;
-               dev->write_hwaddr = ape_write_hwaddr;
-
-               eth_register(dev);
-
-       #ifdef CONFIG_PHYLIB
-               bus = mdio_alloc();
-               if (!bus) {
-                       free(priv);
-                       free(dev);
-                       return -ENOMEM;
-               }
-
-               bus->read = ape_mii_read;
-               bus->write = ape_mii_write;
-               mdio_register(bus);
-       #endif
-
-               return 1;
-       }
-
-The exact arguments needed to initialize your device are up to you.  If you
-need to pass more/less arguments, that's fine.  You should also add the
-prototype for your new register function to include/netdev.h.
-
-The return value for this function should be as follows:
-< 0 - failure (hardware failure, not probe failure)
->=0 - number of interfaces detected
-
-You might notice that many drivers seem to use xxx_initialize() rather than
-xxx_register().  This is the old naming convention and should be avoided as it
-causes confusion with the driver-specific init function.
-
-Other than locating the MAC address in dedicated hardware storage, you should
-not touch the hardware in anyway.  That step is handled in the driver-specific
-init function.  Remember that we are only registering the device here, we are
-not checking its state or doing random probing.
diff --git a/doc/driver-model/fdt-fixup.rst b/doc/driver-model/fdt-fixup.rst
deleted file mode 100644 (file)
index 974c090..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-.. 2017-01-06, Mario Six <[email protected]>
-
-Pre-relocation device tree manipulation
-=======================================
-
-Purpose
--------
-
-In certain markets, it is beneficial for manufacturers of embedded devices to
-offer certain ranges of products, where the functionality of the devices within
-one series either don't differ greatly from another, or can be thought of as
-"extensions" of each other, where one device only differs from another in the
-addition of a small number of features (e.g. an additional output connector).
-
-To realize this in hardware, one method is to have a motherboard, and several
-possible daughter boards that can be attached to this mother board. Different
-daughter boards then either offer the slightly different functionality, or the
-addition of the daughter board to the device realizes the "extension" of
-functionality to the device described previously.
-
-For the software, we obviously want to reuse components for all these
-variations of the device. This means that the software somehow needs to cope
-with the situation that certain ICs may or may not be present on any given
-system, depending on which daughter boards are connected to the motherboard.
-
-In the Linux kernel, one possible solution to this problem is to employ the
-device tree overlay mechanism: There exists one "base" device tree, which
-features only the components guaranteed to exist in all varieties of the
-device. At the start of the kernel, the presence and type of the daughter
-boards is then detected, and the corresponding device tree overlays are applied
-to support the components on the daughter boards.
-
-Note that the components present on every variety of the board must, of course,
-provide a way to find out if and which daughter boards are installed for this
-mechanism to work.
-
-In the U-Boot boot loader, support for device tree overlays has recently been
-integrated, and is used on some boards to alter the device tree that is later
-passed to Linux. But since U-Boot's driver model, which is device tree-based as
-well, is being used in more and more drivers, the same problem of altering the
-device tree starts cropping up in U-Boot itself as well.
-
-An additional problem with the device tree in U-Boot is that it is read-only,
-and the current mechanisms don't allow easy manipulation of the device tree
-after the driver model has been initialized. While migrating to a live device
-tree (at least after the relocation) would greatly simplify the solution of
-this problem, it is a non-negligible task to implement it, an a interim
-solution is needed to address the problem at least in the medium-term.
-
-Hence, we propose a solution to this problem by offering a board-specific
-call-back function, which is passed a writeable pointer to the device tree.
-This function is called before the device tree is relocated, and specifically
-before the main U-Boot's driver model is instantiated, hence the main U-Boot
-"sees" all modifications to the device tree made in this function. Furthermore,
-we have the pre-relocation driver model at our disposal at this stage, which
-means that we can query the hardware for the existence and variety of the
-components easily.
-
-Implementation
---------------
-
-To take advantage of the pre-relocation device tree manipulation mechanism,
-boards have to implement the function board_fix_fdt, which has the following
-signature:
-
-.. code-block:: c
-
-   int board_fix_fdt (void *rw_fdt_blob)
-
-The passed-in void pointer is a writeable pointer to the device tree, which can
-be used to manipulate the device tree using e.g. functions from
-include/fdt_support.h. The return value should either be 0 in case of
-successful execution of the device tree manipulation or something else for a
-failure. Note that returning a non-null value from the function will
-unrecoverably halt the boot process, as with any function from init_sequence_f
-(in common/board_f.c).
-
-Furthermore, the Kconfig option OF_BOARD_FIXUP has to be set for the function
-to be called::
-
-   Device Tree Control
-   -> [*] Board-specific manipulation of Device Tree
-
-+----------------------------------------------------------+
-| WARNING: The actual manipulation of the device tree has  |
-| to be the _last_ set of operations in board_fix_fdt!     |
-| Since the pre-relocation driver model does not adapt to  |
-| changes made to the device tree either, its references   |
-| into the device tree will be invalid after manipulating  |
-| it, and unpredictable behavior might occur when          |
-| functions that rely on them are executed!                |
-+----------------------------------------------------------+
-
-Hence, the recommended layout of the board_fixup_fdt call-back function is the
-following:
-
-.. code-block:: c
-
-       int board_fix_fdt(void *rw_fdt_blob)
-       {
-               /*
-                * Collect information about device's hardware and store
-                * them in e.g. local variables
-                */
-
-               /* Do device tree manipulation using the values previously collected */
-
-               /* Return 0 on successful manipulation and non-zero otherwise */
-       }
-
-If this convention is kept, both an "additive" approach, meaning that nodes for
-detected components are added to the device tree, as well as a "subtractive"
-approach, meaning that nodes for absent components are removed from the tree,
-as well as a combination of both approaches should work.
-
-Example
--------
-
-The controlcenterdc board (board/gdsys/a38x/controlcenterdc.c) features a
-board_fix_fdt function, in which six GPIO expanders (which might be present or
-not, since they are on daughter boards) on a I2C bus are queried for, and
-subsequently deactivated in the device tree if they are not present.
-
-Note that the dm_i2c_simple_probe function does not use the device tree, hence
-it is safe to call it after the tree has already been manipulated.
-
-Work to be done
----------------
-
-* The application of device tree overlay should be possible in board_fixup_fdt,
-  but has not been tested at this stage.
diff --git a/doc/driver-model/fs_firmware_loader.rst b/doc/driver-model/fs_firmware_loader.rst
deleted file mode 100644 (file)
index a44708c..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-.. Copyright (C) 2018-2019 Intel Corporation <www.intel.com>
-
-File System Firmware Loader
-===========================
-
-This is file system firmware loader for U-Boot framework, which has very close
-to some Linux Firmware API. For the details of Linux Firmware API, you can refer
-to https://01.org/linuxgraphics/gfx-docs/drm/driver-api/firmware/index.html.
-
-File system firmware loader can be used to load whatever(firmware, image,
-and binary) from the storage device in file system format into target location
-such as memory, then consumer driver such as FPGA driver can program FPGA image
-from the target location into FPGA.
-
-To enable firmware loader, CONFIG_FS_LOADER need to be set at
-<board_name>_defconfig such as "CONFIG_FS_LOADER=y".
-
-Firmware Loader API core features
----------------------------------
-
-Firmware storage device described in device tree source
--------------------------------------------------------
-For passing data like storage device phandle and partition where the
-firmware loading from to the firmware loader driver, those data could be
-defined in fs-loader node as shown in below:
-
-Example for block device::
-
-       fs_loader0: fs-loader {
-               u-boot,dm-pre-reloc;
-               compatible = "u-boot,fs-loader";
-               phandlepart = <&mmc 1>;
-       };
-
-<&mmc 1> means block storage device pointer and its partition.
-
-Above example is a description for block storage, but for UBI storage
-device, it can be described in FDT as shown in below:
-
-Example for ubi::
-
-       fs_loader1: fs-loader {
-               u-boot,dm-pre-reloc;
-               compatible = "u-boot,fs-loader";
-               mtdpart = "UBI",
-               ubivol = "ubi0";
-       };
-
-Then, firmware-loader property can be added with any device node, which
-driver would use the firmware loader for loading.
-
-The value of the firmware-loader property should be set with phandle
-of the fs-loader node. For example::
-
-       firmware-loader = <&fs_loader0>;
-
-If there are majority of devices using the same fs-loader node, then
-firmware-loader property can be added under /chosen node instead of
-adding to each of device node.
-
-For example::
-
-       /{
-               chosen {
-                       firmware-loader = <&fs_loader0>;
-               };
-       };
-
-In each respective driver of devices using firmware loader, the firmware
-loaded instance        should be created by DT phandle.
-
-For example of getting DT phandle from /chosen and creating instance:
-
-.. code-block:: c
-
-       chosen_node = ofnode_path("/chosen");
-       if (!ofnode_valid(chosen_node)) {
-               debug("/chosen node was not found.\n");
-               return -ENOENT;
-       }
-
-       phandle_p = ofnode_get_property(chosen_node, "firmware-loader", &size);
-       if (!phandle_p) {
-               debug("firmware-loader property was not found.\n");
-               return -ENOENT;
-       }
-
-       phandle = fdt32_to_cpu(*phandle_p);
-       ret = uclass_get_device_by_phandle_id(UCLASS_FS_FIRMWARE_LOADER,
-                                            phandle, &dev);
-       if (ret)
-               return ret;
-
-Firmware loader driver is also designed to support U-boot environment
-variables, so all these data from FDT can be overwritten
-through the U-boot environment variable during run time.
-
-For examples:
-
-storage_interface:
-  Storage interface, it can be "mmc", "usb", "sata" or "ubi".
-fw_dev_part:
-  Block device number and its partition, it can be "0:1".
-fw_ubi_mtdpart:
-  UBI device mtd partition, it can be "UBI".
-fw_ubi_volume:
-  UBI volume, it can be "ubi0".
-
-When above environment variables are set, environment values would be
-used instead of data from FDT.
-The benefit of this design allows user to change storage attribute data
-at run time through U-boot console and saving the setting as default
-environment values in the storage for the next power cycle, so no
-compilation is required for both driver and FDT.
-
-File system firmware Loader API
--------------------------------
-
-.. code-block:: c
-
-       int request_firmware_into_buf(struct udevice *dev,
-                                     const char *name,
-                                     void *buf, size_t size, u32 offset)
-
-Load firmware into a previously allocated buffer
-
-Parameters:
-
-* struct udevice \*dev: An instance of a driver
-* const char \*name: name of firmware file
-* void \*buf: address of buffer to load firmware into
-* size_t size: size of buffer
-* u32 offset: offset of a file for start reading into buffer
-
-Returns:
-       size of total read
-       -ve when error
-
-Description:
-       The firmware is loaded directly into the buffer pointed to by buf
-
-Example of calling request_firmware_into_buf API after creating firmware loader
-instance:
-
-.. code-block:: c
-
-       ret = uclass_get_device_by_phandle_id(UCLASS_FS_FIRMWARE_LOADER,
-                                            phandle, &dev);
-       if (ret)
-               return ret;
-
-       request_firmware_into_buf(dev, filename, buffer_location, buffer_size,
-                                offset_ofreading);
diff --git a/doc/driver-model/i2c-howto.rst b/doc/driver-model/i2c-howto.rst
deleted file mode 100644 (file)
index 27e7440..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-
-How to port an I2C driver to driver model
-=========================================
-
-Over half of the I2C drivers have been converted as at November 2016. These
-ones remain:
-
-   * adi_i2c
-   * davinci_i2c
-   * fti2c010
-   * ihs_i2c
-   * kona_i2c
-   * lpc32xx_i2c
-   * pca9564_i2c
-   * ppc4xx_i2c
-   * rcar_i2c
-   * sh_i2c
-   * soft_i2c
-   * zynq_i2c
-
-The deadline for this work is the end of June 2017. If no one steps
-forward to convert these, at some point there may come a patch to remove them!
-
-Here is a suggested approach for converting your I2C driver over to driver
-model. Please feel free to update this file with your ideas and suggestions.
-
-- #ifdef out all your own I2C driver code (#if !CONFIG_IS_ENABLED(DM_I2C))
-- Define CONFIG_DM_I2C for your board, vendor or architecture
-- If the board does not already use driver model, you need CONFIG_DM also
-- Your board should then build, but will not work fully since there will be
-  no I2C driver
-- Add the U_BOOT_DRIVER piece at the end (e.g. copy tegra_i2c.c for example)
-- Add a private struct for the driver data - avoid using static variables
-- Implement each of the driver methods, perhaps by calling your old methods
-- You may need to adjust the function parameters so that the old and new
-  implementations can share most of the existing code
-- If you convert all existing users of the driver, remove the pre-driver-model
-  code
-
-In terms of patches a conversion series typically has these patches:
-- clean up / prepare the driver for conversion
-- add driver model code
-- convert at least one existing board to use driver model serial
-- (if no boards remain that don't use driver model) remove the old code
-
-This may be a good time to move your board to use device tree also. Mostly
-this involves these steps:
-
-- define CONFIG_OF_CONTROL and CONFIG_OF_SEPARATE
-- add your device tree files to arch/<arch>/dts
-- update the Makefile there
-- Add stdout-path to your /chosen device tree node if it is not already there
-- build and get u-boot-dtb.bin so you can test it
-- Your drivers can now use device tree
-- For device tree in SPL, define CONFIG_SPL_OF_CONTROL
diff --git a/doc/driver-model/index.rst b/doc/driver-model/index.rst
deleted file mode 100644 (file)
index c9faf0a..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-
-Driver Model
-============
-
-.. toctree::
-   :maxdepth: 2
-
-   bind
-   debugging
-   design
-   ethernet
-   fdt-fixup
-   fs_firmware_loader
-   i2c-howto
-   livetree
-   migration
-   of-plat
-   pci-info
-   pmic-framework
-   remoteproc-framework
-   serial-howto
-   soc-framework
-   spi-howto
-   usb-info
diff --git a/doc/driver-model/livetree.rst b/doc/driver-model/livetree.rst
deleted file mode 100644 (file)
index 9f654f3..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-.. sectionauthor:: Simon Glass <[email protected]>
-
-Live Device Tree
-================
-
-
-Introduction
-------------
-
-Traditionally U-Boot has used a 'flat' device tree. This means that it
-reads directly from the device tree binary structure. It is called a flat
-device tree because nodes are listed one after the other, with the
-hierarchy detected by tags in the format.
-
-This document describes U-Boot's support for a 'live' device tree, meaning
-that the tree is loaded into a hierarchical data structure within U-Boot.
-
-
-Motivation
-----------
-
-The flat device tree has several advantages:
-
-- it is the format produced by the device tree compiler, so no translation
-  is needed
-
-- it is fairly compact (e.g. there is no need for pointers)
-
-- it is accessed by the libfdt library, which is well tested and stable
-
-
-However the flat device tree does have some limitations. Adding new
-properties can involve copying large amounts of data around to make room.
-The overall tree has a fixed maximum size so sometimes the tree must be
-rebuilt in a new location to create more space. Even if not adding new
-properties or nodes, scanning the tree can be slow. For example, finding
-the parent of a node is a slow process. Reading from nodes involves a
-small amount parsing which takes a little time.
-
-Driver model scans the entire device tree sequentially on start-up which
-avoids the worst of the flat tree's limitations. But if the tree is to be
-modified at run-time, a live tree is much faster. Even if no modification
-is necessary, parsing the tree once and using a live tree from then on
-seems to save a little time.
-
-
-Implementation
---------------
-
-In U-Boot a live device tree ('livetree') is currently supported only
-after relocation. Therefore we need a mechanism to specify a device
-tree node regardless of whether it is in the flat tree or livetree.
-
-The 'ofnode' type provides this. An ofnode can point to either a flat tree
-node (when the live tree node is not yet set up) or a livetree node. The
-caller of an ofnode function does not need to worry about these details.
-
-The main users of the information in a device tree are drivers. These have
-a 'struct udevice \*' which is attached to a device tree node. Therefore it
-makes sense to be able to read device tree  properties using the
-'struct udevice \*', rather than having to obtain the ofnode first.
-
-The 'dev_read\_...()' interface provides this. It allows properties to be
-easily read from the device tree using only a device pointer. Under the
-hood it uses ofnode so it works with both flat and live device trees.
-
-
-Enabling livetree
------------------
-
-CONFIG_OF_LIVE enables livetree. When this option is enabled, the flat
-tree will be used in SPL and before relocation in U-Boot proper. Just
-before relocation a livetree is built, and this is used for U-Boot proper
-after relocation.
-
-Most checks for livetree use CONFIG_IS_ENABLED(OF_LIVE). This means that
-for SPL, the CONFIG_SPL_OF_LIVE option is checked. At present this does
-not exist, since SPL does not support livetree.
-
-
-Porting drivers
----------------
-
-Many existing drivers use the fdtdec interface to read device tree
-properties. This only works with a flat device tree. The drivers should be
-converted to use the dev_read_() interface.
-
-For example, the old code may be like this:
-
-.. code-block:: c
-
-    struct udevice *bus;
-    const void *blob = gd->fdt_blob;
-    int node = dev_of_offset(bus);
-
-    i2c_bus->regs = (struct i2c_ctlr *)devfdt_get_addr(dev);
-    plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", 500000);
-
-The new code is:
-
-.. code-block:: c
-
-    struct udevice *bus;
-
-    i2c_bus->regs = (struct i2c_ctlr *)dev_read_addr(dev);
-    plat->frequency = dev_read_u32_default(bus, "spi-max-frequency", 500000);
-
-The dev_read\_...() interface is more convenient and works with both the
-flat and live device trees. See include/dm/read.h for a list of functions.
-
-Where properties must be read from sub-nodes or other nodes, you must fall
-back to using ofnode. For example, for old code like this:
-
-.. code-block:: c
-
-    const void *blob = gd->fdt_blob;
-    int subnode;
-
-    fdt_for_each_subnode(subnode, blob, dev_of_offset(dev)) {
-        freq = fdtdec_get_int(blob, node, "spi-max-frequency", 500000);
-        ...
-    }
-
-you should use:
-
-.. code-block:: c
-
-    ofnode subnode;
-
-    ofnode_for_each_subnode(subnode, dev_ofnode(dev)) {
-        freq = ofnode_read_u32(node, "spi-max-frequency", 500000);
-        ...
-    }
-
-
-Useful ofnode functions
------------------------
-
-The internal data structures of the livetree are defined in include/dm/of.h :
-
-   :struct device_node: holds information about a device tree node
-   :struct property: holds information about a property within a node
-
-Nodes have pointers to their first property, their parent, their first child
-and their sibling. This allows nodes to be linked together in a hierarchical
-tree.
-
-Properties have pointers to the next property. This allows all properties of
-a node to be linked together in a chain.
-
-It should not be necessary to use these data structures in normal code. In
-particular, you should refrain from using functions which access the livetree
-directly, such as of_read_u32(). Use ofnode functions instead, to allow your
-code to work with a flat tree also.
-
-Some conversion functions are used internally. Generally these are not needed
-for driver code. Note that they will not work if called in the wrong context.
-For example it is invalid to call ofnode_to_no() when a flat tree is being
-used. Similarly it is not possible to call ofnode_to_offset() on a livetree
-node.
-
-ofnode_to_np():
-   converts ofnode to struct device_node *
-ofnode_to_offset():
-   converts ofnode to offset
-
-no_to_ofnode():
-   converts node pointer to ofnode
-offset_to_ofnode():
-   converts offset to ofnode
-
-
-Other useful functions:
-
-of_live_active():
-   returns true if livetree is in use, false if flat tree
-ofnode_valid():
-   return true if a given node is valid
-ofnode_is_np():
-   returns true if a given node is a livetree node
-ofnode_equal():
-   compares two ofnodes
-ofnode_null():
-   returns a null ofnode (for which ofnode_valid() returns false)
-
-
-Phandles
---------
-
-There is full phandle support for live tree. All functions make use of
-struct ofnode_phandle_args, which has an ofnode within it. This supports both
-livetree and flat tree transparently. See for example
-ofnode_parse_phandle_with_args().
-
-
-Reading addresses
------------------
-
-You should use dev_read_addr() and friends to read addresses from device-tree
-nodes.
-
-
-fdtdec
-------
-
-The existing fdtdec interface will eventually be retired. Please try to avoid
-using it in new code.
-
-
-Modifying the livetree
-----------------------
-
-This is not currently supported. Once implemented it should provide a much
-more efficient implementation for modification of the device tree than using
-the flat tree.
-
-
-Internal implementation
------------------------
-
-The dev_read\_...() functions have two implementations. When
-CONFIG_DM_DEV_READ_INLINE is enabled, these functions simply call the ofnode
-functions directly. This is useful when livetree is not enabled. The ofnode
-functions call ofnode_is_np(node) which will always return false if livetree
-is disabled, just falling back to flat tree code.
-
-This optimisation means that without livetree enabled, the dev_read\_...() and
-ofnode interfaces do not noticeably add to code size.
-
-The CONFIG_DM_DEV_READ_INLINE option defaults to enabled when livetree is
-disabled.
-
-Most livetree code comes directly from Linux and is modified as little as
-possible. This is deliberate since this code is fairly stable and does what
-we want. Some features (such as get/put) are not supported. Internal macros
-take care of removing these features silently.
-
-Within the of_access.c file there are pointers to the alias node, the chosen
-node and the stdout-path alias.
-
-
-Errors
-------
-
-With a flat device tree, libfdt errors are returned (e.g. -FDT_ERR_NOTFOUND).
-For livetree normal 'errno' errors are returned (e.g. -ENOTFOUND). At present
-the ofnode and dev_read\_...() functions return either one or other type of
-error. This is clearly not desirable. Once tests are added for all the
-functions this can be tidied up.
-
-
-Adding new access functions
----------------------------
-
-Adding a new function for device-tree access involves the following steps:
-
-   - Add two dev_read() functions:
-      - inline version in the read.h header file, which calls an ofnode function
-      - standard version in the read.c file (or perhaps another file), which
-        also calls an ofnode function
-
-        The implementations of these functions can be the same. The purpose
-        of the inline version is purely to reduce code size impact.
-
-   - Add an ofnode function. This should call ofnode_is_np() to work out
-     whether a livetree or flat tree is used. For the livetree it should
-     call an of\_...() function. For the flat tree it should call an
-     fdt\_...() function. The livetree version will be optimised out at
-     compile time if livetree is not enabled.
-
-   - Add an of\_...() function for the livetree implementation. If a similar
-     function is available in Linux, the implementation should be taken
-     from there and modified as little as possible (generally not at all).
-
-
-Future work
------------
-
-Live tree support was introduced in U-Boot 2017.07. There is still quite a bit
-of work to do to flesh this out:
-
-- tests for all access functions
-- support for livetree modification
-- addition of more access functions as needed
-- support for livetree in SPL and before relocation (if desired)
diff --git a/doc/driver-model/migration.rst b/doc/driver-model/migration.rst
deleted file mode 100644 (file)
index 2284e8a..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-
-Migration Schedule
-==================
-
-U-Boot has been migrating to a new driver model since its introduction in
-2014. This file describes the schedule for deprecation of pre-driver-model
-features.
-
-CONFIG_DM
----------
-
-* Status: In progress
-* Deadline: 2020.01
-
-Starting with the 2010.01 release CONFIG_DM will be enabled for all boards.
-This does not concern CONFIG_DM_SPL and CONFIG_DM_TPL. The conversion date for
-these configuration items still needs to be defined.
-
-CONFIG_DM_MMC
--------------
-
-* Status: In progress
-* Deadline: 2019.04
-
-The subsystem itself has been converted and maintainers should submit patches
-switching over to using CONFIG_DM_MMC and other base driver model options in
-time for inclusion in the 2019.04 rerelease.
-
-CONFIG_DM_USB
--------------
-
-* Status: In progress
-* Deadline: 2019.07
-
-The subsystem itself has been converted along with many of the host controller
-and maintainers should submit patches switching over to using CONFIG_DM_USB and
-other base driver model options in time for inclusion in the 2019.07 rerelease.
-
-CONFIG_SATA
------------
-
-* Status: In progress
-* Deadline: 2019.07
-
-The subsystem itself has been converted along with many of the host controller
-and maintainers should submit patches switching over to using CONFIG_AHCI and
-other base driver model options in time for inclusion in the 2019.07 rerelease.
-
-CONFIG_BLK
-----------
-
-* Status: In progress
-* Deadline: 2019.07
-
-In concert with maintainers migrating their block device usage to the
-appropriate DM driver, CONFIG_BLK needs to be set as well.  The final deadline
-here coincides with the final deadline for migration of the various block
-subsystems.  At this point we will be able to audit and correct the logic in
-Kconfig around using CONFIG_PARTITIONS and CONFIG_HAVE_BLOCK_DEVICE and make
-use of CONFIG_BLK / CONFIG_SPL_BLK as needed.
-
-CONFIG_DM_SPI / CONFIG_DM_SPI_FLASH
------------------------------------
-
-Board Maintainers should submit the patches for enabling DM_SPI and DM_SPI_FLASH
-to move the migration with in the deadline.
-
-Partially converted::
-
-       drivers/spi/fsl_espi.c
-       drivers/spi/mxc_spi.c
-       drivers/spi/sh_qspi.c
-
-* Status: In progress
-* Deadline: 2019.07
-
-CONFIG_DM_PCI
--------------
-Deadline: 2019.07
-
-The PCI subsystem has supported driver model since mid 2015. Maintainers should
-submit patches switching over to using CONFIG_DM_PCI and other base driver
-model options in time for inclusion in the 2019.07 release.
-
-
-CONFIG_DM_VIDEO
----------------
-Deadline: 2019.07
-
-The video subsystem has supported driver model since early 2016. Maintainers
-should submit patches switching over to using CONFIG_DM_VIDEO and other base
-driver model options in time for inclusion in the 2019.07 release.
-
-CONFIG_DM_ETH
--------------
-Deadline: 2020.07
-
-The network subsystem has supported the driver model since early 2015.
-Maintainers should submit patches switching over to using CONFIG_DM_ETH and
-other base driver model options in time for inclusion in the 2020.07 release.
diff --git a/doc/driver-model/of-plat.rst b/doc/driver-model/of-plat.rst
deleted file mode 100644 (file)
index 74f1932..0000000
+++ /dev/null
@@ -1,913 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-
-Compiled-in Device Tree / Platform Data
-=======================================
-
-
-Introduction
-------------
-
-Device tree is the standard configuration method in U-Boot. It is used to
-define what devices are in the system and provide configuration information
-to these devices.
-
-The overhead of adding devicetree access to U-Boot is fairly modest,
-approximately 3KB on Thumb 2 (plus the size of the DT itself). This means
-that in most cases it is best to use devicetree for configuration.
-
-However there are some very constrained environments where U-Boot needs to
-work. These include SPL with severe memory limitations. For example, some
-SoCs require a 16KB SPL image which must include a full MMC stack. In this
-case the overhead of devicetree access may be too great.
-
-It is possible to create platform data manually by defining C structures
-for it, and reference that data in a `U_BOOT_DRVINFO()` declaration. This
-bypasses the use of devicetree completely, effectively creating a parallel
-configuration mechanism. But it is an available option for SPL.
-
-As an alternative, the 'of-platdata' feature is provided. This converts the
-devicetree contents into C code which can be compiled into the SPL binary.
-This saves the 3KB of code overhead and perhaps a few hundred more bytes due
-to more efficient storage of the data.
-
-
-How it works
-------------
-
-The feature is enabled by CONFIG OF_PLATDATA. This is only available in
-SPL/TPL and should be tested with:
-
-.. code-block:: c
-
-    #if CONFIG_IS_ENABLED(OF_PLATDATA)
-
-A tool called 'dtoc' converts a devicetree file either into a set of
-struct declarations, one for each compatible node, and a set of
-`U_BOOT_DRVINFO()` declarations along with the actual platform data for each
-device. As an example, consider this MMC node:
-
-.. code-block:: none
-
-    sdmmc: dwmmc@ff0c0000 {
-            compatible = "rockchip,rk3288-dw-mshc";
-            clock-freq-min-max = <400000 150000000>;
-            clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
-                     <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
-            clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
-            fifo-depth = <0x100>;
-            interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
-            reg = <0xff0c0000 0x4000>;
-            bus-width = <4>;
-            cap-mmc-highspeed;
-            cap-sd-highspeed;
-            card-detect-delay = <200>;
-            disable-wp;
-            num-slots = <1>;
-            pinctrl-names = "default";
-            pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>;
-                vmmc-supply = <&vcc_sd>;
-                status = "okay";
-                u-boot,dm-pre-reloc;
-        };
-
-
-Some of these properties are dropped by U-Boot under control of the
-CONFIG_OF_SPL_REMOVE_PROPS option. The rest are processed. This will produce
-the following C struct declaration:
-
-.. code-block:: c
-
-    struct dtd_rockchip_rk3288_dw_mshc {
-            fdt32_t         bus_width;
-            bool            cap_mmc_highspeed;
-            bool            cap_sd_highspeed;
-            fdt32_t         card_detect_delay;
-            fdt32_t         clock_freq_min_max[2];
-            struct phandle_1_arg clocks[4];
-            bool            disable_wp;
-            fdt32_t         fifo_depth;
-            fdt32_t         interrupts[3];
-            fdt32_t         num_slots;
-            fdt32_t         reg[2];
-            fdt32_t         vmmc_supply;
-    };
-
-and the following device declarations:
-
-.. code-block:: c
-
-    /* Node /clock-controller@ff760000 index 0 */
-    ...
-
-    /* Node /dwmmc@ff0c0000 index 2 */
-    static struct dtd_rockchip_rk3288_dw_mshc dtv_dwmmc_at_ff0c0000 = {
-            .fifo_depth             = 0x100,
-            .cap_sd_highspeed       = true,
-            .interrupts             = {0x0, 0x20, 0x4},
-            .clock_freq_min_max     = {0x61a80, 0x8f0d180},
-            .vmmc_supply            = 0xb,
-            .num_slots              = 0x1,
-            .clocks                 = {{0, 456},
-                                       {0, 68},
-                                       {0, 114},
-                                       {0, 118}},
-            .cap_mmc_highspeed      = true,
-            .disable_wp             = true,
-            .bus_width              = 0x4,
-            .u_boot_dm_pre_reloc    = true,
-            .reg                    = {0xff0c0000, 0x4000},
-            .card_detect_delay      = 0xc8,
-    };
-
-    U_BOOT_DRVINFO(dwmmc_at_ff0c0000) = {
-            .name           = "rockchip_rk3288_dw_mshc",
-            .plat       = &dtv_dwmmc_at_ff0c0000,
-            .plat_size  = sizeof(dtv_dwmmc_at_ff0c0000),
-            .parent_idx     = -1,
-    };
-
-The device is then instantiated at run-time and the platform data can be
-accessed using:
-
-.. code-block:: c
-
-    struct udevice *dev;
-    struct dtd_rockchip_rk3288_dw_mshc *plat = dev_get_plat(dev);
-
-This avoids the code overhead of converting the devicetree data to
-platform data in the driver. The `of_to_plat()` method should
-therefore do nothing in such a driver.
-
-Note that for the platform data to be matched with a driver, the 'name'
-property of the `U_BOOT_DRVINFO()` declaration has to match a driver declared
-via `U_BOOT_DRIVER()`. This effectively means that a `U_BOOT_DRIVER()` with a
-'name' corresponding to the devicetree 'compatible' string (after converting
-it to a valid name for C) is needed, so a dedicated driver is required for
-each 'compatible' string.
-
-In order to make this a bit more flexible, the `DM_DRIVER_ALIAS()` macro can be
-used to declare an alias for a driver name, typically a 'compatible' string.
-This macro produces no code, but is used by dtoc tool. It must be located in the
-same file as its associated driver, ideally just after it.
-
-The parent_idx is the index of the parent `driver_info` structure within its
-linker list (instantiated by the `U_BOOT_DRVINFO()` macro). This is used to
-support `dev_get_parent()`.
-
-During the build process dtoc parses both `U_BOOT_DRIVER()` and
-`DM_DRIVER_ALIAS()` to build a list of valid driver names and driver aliases.
-If the 'compatible' string used for a device does not not match a valid driver
-name, it will be checked against the list of driver aliases in order to get the
-right driver name to use. If in this step there is no match found a warning is
-issued to avoid run-time failures.
-
-Where a node has multiple compatible strings, dtoc generates a `#define` to
-make them equivalent, e.g.:
-
-.. code-block:: c
-
-    #define dtd_rockchip_rk3299_dw_mshc dtd_rockchip_rk3288_dw_mshc
-
-
-Converting of-platdata to a useful form
----------------------------------------
-
-Of course it would be possible to use the of-platdata directly in your driver
-whenever configuration information is required. However this means that the
-driver will not be able to support devicetree, since the of-platdata
-structure is not available when devicetree is used. It would make no sense
-to use this structure if devicetree were available, since the structure has
-all the limitations metioned in caveats below.
-
-Therefore it is recommended that the of-platdata structure should be used
-only in the `probe()` method of your driver. It cannot be used in the
-`of_to_plat()` method since this is not called when platform data is
-already present.
-
-
-How to structure your driver
-----------------------------
-
-Drivers should always support devicetree as an option. The of-platdata
-feature is intended as a add-on to existing drivers.
-
-Your driver should convert the plat struct in its `probe()` method. The
-existing devicetree decoding logic should be kept in the
-`of_to_plat()` method and wrapped with `#if`.
-
-For example:
-
-.. code-block:: c
-
-    #include <dt-structs.h>
-
-    struct mmc_plat {
-    #if CONFIG_IS_ENABLED(OF_PLATDATA)
-            /* Put this first since driver model will copy the data here */
-            struct dtd_mmc dtplat;
-    #endif
-            /*
-             * Other fields can go here, to be filled in by decoding from
-             * the devicetree (or the C structures when of-platdata is used).
-             */
-            int fifo_depth;
-    };
-
-    static int mmc_of_to_plat(struct udevice *dev)
-    {
-    #if !CONFIG_IS_ENABLED(OF_PLATDATA)
-            /* Decode the devicetree data */
-            struct mmc_plat *plat = dev_get_plat(dev);
-            const void *blob = gd->fdt_blob;
-            int node = dev_of_offset(dev);
-
-            plat->fifo_depth = fdtdec_get_int(blob, node, "fifo-depth", 0);
-    #endif
-
-            return 0;
-    }
-
-    static int mmc_probe(struct udevice *dev)
-    {
-            struct mmc_plat *plat = dev_get_plat(dev);
-
-    #if CONFIG_IS_ENABLED(OF_PLATDATA)
-            /* Decode the of-platdata from the C structures */
-            struct dtd_mmc *dtplat = &plat->dtplat;
-
-            plat->fifo_depth = dtplat->fifo_depth;
-    #endif
-            /* Set up the device from the plat data */
-            writel(plat->fifo_depth, ...)
-    }
-
-    static const struct udevice_id mmc_ids[] = {
-            { .compatible = "vendor,mmc" },
-            { }
-    };
-
-    U_BOOT_DRIVER(mmc_drv) = {
-            .name           = "mmc_drv",
-            .id             = UCLASS_MMC,
-            .of_match       = mmc_ids,
-            .of_to_plat = mmc_of_to_plat,
-            .probe          = mmc_probe,
-            .priv_auto = sizeof(struct mmc_priv),
-            .plat_auto = sizeof(struct mmc_plat),
-    };
-
-    DM_DRIVER_ALIAS(mmc_drv, vendor_mmc) /* matches compatible string */
-
-Note that `struct mmc_plat` is defined in the C file, not in a header. This
-is to avoid needing to include dt-structs.h in a header file. The idea is to
-keep the use of each of-platdata struct to the smallest possible code area.
-There is just one driver C file for each struct, that can convert from the
-of-platdata struct to the standard one used by the driver.
-
-In the case where SPL_OF_PLATDATA is enabled, `plat_auto` is
-still used to allocate space for the platform data. This is different from
-the normal behaviour and is triggered by the use of of-platdata (strictly
-speaking it is a non-zero `plat_size` which triggers this).
-
-The of-platdata struct contents is copied from the C structure data to the
-start of the newly allocated area. In the case where devicetree is used,
-the platform data is allocated, and starts zeroed. In this case the
-`of_to_plat()` method should still set up the platform data (and the
-of-platdata struct will not be present).
-
-SPL must use either of-platdata or devicetree. Drivers cannot use both at
-the same time, but they must support devicetree. Supporting of-platdata is
-optional.
-
-The devicetree becomes inaccessible when CONFIG_SPL_OF_PLATDATA is enabled,
-since the devicetree access code is not compiled in. A corollary is that
-a board can only move to using of-platdata if all the drivers it uses support
-it. There would be little point in having some drivers require the device
-tree data, since then libfdt would still be needed for those drivers and
-there would be no code-size benefit.
-
-
-Build-time instantiation
-------------------------
-
-Even with of-platdata there is a fair amount of code required in driver model.
-It is possible to have U-Boot handle the instantiation of devices at build-time,
-so avoiding the need for the `device_bind()` code and some parts of
-`device_probe()`.
-
-The feature is enabled by CONFIG_OF_PLATDATA_INST.
-
-Here is an example device, as generated by dtoc::
-
-   /*
-    * Node /serial index 6
-    * driver sandbox_serial parent root_driver
-   */
-
-   #include <asm/serial.h>
-   struct sandbox_serial_plat __attribute__ ((section (".priv_data")))
-      _sandbox_serial_plat_serial = {
-      .dtplat = {
-         .sandbox_text_colour   = "cyan",
-      },
-   };
-   #include <asm/serial.h>
-   u8 _sandbox_serial_priv_serial[sizeof(struct sandbox_serial_priv)]
-      __attribute__ ((section (".priv_data")));
-   #include <serial.h>
-   u8 _sandbox_serial_uc_priv_serial[sizeof(struct serial_dev_priv)]
-      __attribute__ ((section (".priv_data")));
-
-   DM_DEVICE_INST(serial) = {
-      .driver     = DM_DRIVER_REF(sandbox_serial),
-      .name       = "sandbox_serial",
-      .plat_      = &_sandbox_serial_plat_serial,
-      .priv_      = _sandbox_serial_priv_serial,
-      .uclass     = DM_UCLASS_REF(serial),
-      .uclass_priv_ = _sandbox_serial_uc_priv_serial,
-      .uclass_node   = {
-         .prev = &DM_UCLASS_REF(serial)->dev_head,
-         .next = &DM_UCLASS_REF(serial)->dev_head,
-      },
-      .child_head   = {
-         .prev = &DM_DEVICE_REF(serial)->child_head,
-         .next = &DM_DEVICE_REF(serial)->child_head,
-      },
-      .sibling_node   = {
-         .prev = &DM_DEVICE_REF(i2c_at_0)->sibling_node,
-         .next = &DM_DEVICE_REF(spl_test)->sibling_node,
-      },
-      .seq_ = 0,
-   };
-
-Here is part of the driver, for reference::
-
-   static const struct udevice_id sandbox_serial_ids[] = {
-      { .compatible = "sandbox,serial" },
-      { }
-   };
-
-   U_BOOT_DRIVER(sandbox_serial) = {
-      .name   = "sandbox_serial",
-      .id   = UCLASS_SERIAL,
-      .of_match    = sandbox_serial_ids,
-      .of_to_plat  = sandbox_serial_of_to_plat,
-      .plat_auto   = sizeof(struct sandbox_serial_plat),
-      .priv_auto   = sizeof(struct sandbox_serial_priv),
-      .probe = sandbox_serial_probe,
-      .remove = sandbox_serial_remove,
-      .ops   = &sandbox_serial_ops,
-      .flags = DM_FLAG_PRE_RELOC,
-   };
-
-
-The `DM_DEVICE_INST()` macro declares a struct udevice so you can see that the
-members are from that struct. The private data is declared immediately above,
-as `_sandbox_serial_priv_serial`, so there is no need for run-time memory
-allocation. The #include lines are generated as well, since dtoc searches the
-U-Boot source code for the definition of `struct sandbox_serial_priv` and adds
-the relevant header so that the code will compile without errors.
-
-The `plat_` member is set to the dtv data which is declared immediately above
-the device. This is similar to how it would look without of-platdata-inst, but
-node that the `dtplat` member inside is part of the wider
-`_sandbox_serial_plat_serial` struct. This is because the driver declares its
-own platform data, and the part generated by dtoc can only be a portion of it.
-The `dtplat` part is always first in the struct. If the device has no
-`.plat_auto` field, then a simple dtv struct can be used as with this example::
-
-   static struct dtd_sandbox_clk dtv_clk_sbox = {
-      .assigned_clock_rates   = 0x141,
-      .assigned_clocks   = {0x7, 0x3},
-   };
-
-   #include <asm/clk.h>
-   u8 _sandbox_clk_priv_clk_sbox[sizeof(struct sandbox_clk_priv)]
-      __attribute__ ((section (".priv_data")));
-
-   DM_DEVICE_INST(clk_sbox) = {
-      .driver    = DM_DRIVER_REF(sandbox_clk),
-      .name      = "sandbox_clk",
-      .plat_     = &dtv_clk_sbox,
-
-Here is part of the driver, for reference::
-
-   static const struct udevice_id sandbox_clk_ids[] = {
-      { .compatible = "sandbox,clk" },
-      { }
-   };
-
-   U_BOOT_DRIVER(sandbox_clk) = {
-      .name       = "sandbox_clk",
-      .id         = UCLASS_CLK,
-      .of_match   = sandbox_clk_ids,
-      .ops        = &sandbox_clk_ops,
-      .probe      = sandbox_clk_probe,
-      .priv_auto  = sizeof(struct sandbox_clk_priv),
-   };
-
-
-You can see that `dtv_clk_sbox` just has the devicetree contents and there is
-no need for the `dtplat` separation, since the driver has no platform data of
-its own, besides that provided by the devicetree (i.e. no `.plat_auto` field).
-
-The doubly linked lists are handled by explicitly declaring the value of each
-node, as you can see with the `.prev` and `.next` values in the example above.
-Since dtoc knows the order of devices it can link them into the appropriate
-lists correctly.
-
-One of the features of driver model is the ability for a uclass to have a
-small amount of private data for each device in that uclass. This is used to
-provide a generic data structure that the uclass can use for all devices, thus
-allowing generic features to be implemented in common code. An example is I2C,
-which stores the bus speed there.
-
-Similarly, parent devices can have data associated with each of their children.
-This is used to provide information common to all children of a particular bus.
-For an I2C bus, this is used to store the I2C address of each child on the bus.
-
-This is all handled automatically by dtoc::
-
-   #include <asm/i2c.h>
-   u8 _sandbox_i2c_priv_i2c_at_0[sizeof(struct sandbox_i2c_priv)]
-      __attribute__ ((section (".priv_data")));
-   #include <i2c.h>
-   u8 _sandbox_i2c_uc_priv_i2c_at_0[sizeof(struct dm_i2c_bus)]
-      __attribute__ ((section (".priv_data")));
-
-   DM_DEVICE_INST(i2c_at_0) = {
-      .driver      = DM_DRIVER_REF(sandbox_i2c),
-      .name      = "sandbox_i2c",
-      .plat_   = &dtv_i2c_at_0,
-      .priv_      = _sandbox_i2c_priv_i2c_at_0,
-      .uclass   = DM_UCLASS_REF(i2c),
-      .uclass_priv_ = _sandbox_i2c_uc_priv_i2c_at_0,
-     ...
-
-Part of driver, for reference::
-
-   static const struct udevice_id sandbox_i2c_ids[] = {
-      { .compatible = "sandbox,i2c" },
-      { }
-   };
-
-   U_BOOT_DRIVER(sandbox_i2c) = {
-      .name   = "sandbox_i2c",
-      .id   = UCLASS_I2C,
-      .of_match = sandbox_i2c_ids,
-      .ops   = &sandbox_i2c_ops,
-      .priv_auto   = sizeof(struct sandbox_i2c_priv),
-   };
-
-Part of I2C uclass, for reference::
-
-   UCLASS_DRIVER(i2c) = {
-      .id         = UCLASS_I2C,
-      .name       = "i2c",
-      .flags      = DM_UC_FLAG_SEQ_ALIAS,
-      .post_bind  = i2c_post_bind,
-      .pre_probe  = i2c_pre_probe,
-      .post_probe = i2c_post_probe,
-      .per_device_auto   = sizeof(struct dm_i2c_bus),
-      .per_child_plat_auto   = sizeof(struct dm_i2c_chip),
-      .child_post_bind = i2c_child_post_bind,
-   };
-
-Here, `_sandbox_i2c_uc_priv_i2c_at_0` is required by the uclass but is declared
-in the device, as required by driver model. The required header file is included
-so that the code will compile without errors. A similar mechanism is used for
-child devices, but is not shown by this example.
-
-It would not be that useful to avoid binding devices but still need to allocate
-uclasses at runtime. So dtoc generates uclass instances as well::
-
-   struct list_head uclass_head = {
-      .prev = &DM_UCLASS_REF(serial)->sibling_node,
-      .next = &DM_UCLASS_REF(clk)->sibling_node,
-   };
-
-   DM_UCLASS_INST(clk) = {
-      .uc_drv      = DM_UCLASS_DRIVER_REF(clk),
-      .sibling_node   = {
-         .prev = &uclass_head,
-         .next = &DM_UCLASS_REF(i2c)->sibling_node,
-      },
-      .dev_head   = {
-         .prev = &DM_DEVICE_REF(clk_sbox)->uclass_node,
-         .next = &DM_DEVICE_REF(clk_fixed)->uclass_node,
-      },
-   };
-
-At the top is the list head. Driver model uses this on start-up, instead of
-creating its own.
-
-Below that are a set of `DM_UCLASS_INST()` macros, each declaring a
-`struct uclass`. The doubly linked lists work as for devices.
-
-All private data is placed into a `.priv_data` section so that it is contiguous
-in the resulting output binary.
-
-
-Indexes
--------
-
-U-Boot stores drivers, devices and many other things in linker_list structures.
-These are sorted by name, so dtoc knows the order that they will appear when
-the linker runs. Each driver_info / udevice is referenced by its index in the
-linker_list array, called 'idx' in the code.
-
-When CONFIG_OF_PLATDATA_INST is enabled, idx is the udevice index, otherwise it
-is the driver_info index. In either case, indexes are used to reference devices
-using device_get_by_ofplat_idx(). This allows phandles to work as expected.
-
-
-Phases
-------
-
-U-Boot operates in several phases, typically TPL, SPL and U-Boot proper.
-The latter does not use dtoc.
-
-In some rare cases different drivers are used for two phases. For example,
-in TPL it may not be necessary to use the full PCI subsystem, so a simple
-driver can be used instead.
-
-This works in the build system simply by compiling in one driver or the
-other (e.g. PCI driver + uclass for SPL; simple_bus for TPL). But dtoc has
-no way of knowing which code is compiled in for which phase, since it does
-not inspect Makefiles or dependency graphs.
-
-So to make this work for dtoc, we need to be able to explicitly mark
-drivers with their phase. This is done by adding a macro to the driver::
-
-   /* code in tpl.c only compiled into TPL */
-   U_BOOT_DRIVER(pci_x86) = {
-      .name   = "pci_x86",
-      .id   = UCLASS_SIMPLE_BUS,
-      .of_match = of_match_ptr(tpl_fake_pci_ids),
-      DM_PHASE(tpl)
-   };
-
-
-   /* code in pci_x86.c compiled into SPL and U-Boot proper */
-   U_BOOT_DRIVER(pci_x86) = {
-      .name   = "pci_x86",
-      .id   = UCLASS_PCI,
-      .of_match = pci_x86_ids,
-      .ops   = &pci_x86_ops,
-   };
-
-
-Notice that the second driver has the same name but no DM_PHASE(), so it will be
-used for SPL and U-Boot.
-
-Note also that this only affects the code generated by dtoc. You still need to
-make sure that only the required driver is build into each phase.
-
-
-Header files
-------------
-
-With OF_PLATDATA_INST, dtoc must include the correct header file in the
-generated code for any structs that are used, so that the code will compile.
-For example, if `struct ns16550_plat` is used, the code must include the
-`ns16550.h` header file.
-
-Typically dtoc can detect the header file needed for a driver by looking
-for the structs that it uses. For example, if a driver as a `.priv_auto`
-that uses `struct ns16550_plat`, then dtoc can search header files for the
-definition of that struct and use the file.
-
-In some cases, enums are used in drivers, typically with the `.data` field
-of `struct udevice_id`. Since dtoc does not support searching for these,
-you must use the `DM_HDR()` macro to tell dtoc which header to use. This works
-as a macro included in the driver definition::
-
-   static const struct udevice_id apl_syscon_ids[] = {
-      { .compatible = "intel,apl-punit", .data = X86_SYSCON_PUNIT },
-      { }
-   };
-
-   U_BOOT_DRIVER(intel_apl_punit) = {
-      .name       = "intel_apl_punit",
-      .id         = UCLASS_SYSCON,
-      .of_match   = apl_syscon_ids,
-      .probe      = apl_punit_probe,
-      DM_HEADER(<asm/cpu.h>)    /* for X86_SYSCON_PUNIT */
-   };
-
-
-
-Caveats
--------
-
-There are various complications with this feature which mean it should only
-be used when strictly necessary, i.e. in SPL with limited memory. Notable
-caveats include:
-
-   - Device tree does not describe data types. But the C code must define a
-     type for each property. These are guessed using heuristics which
-     are wrong in several fairly common cases. For example an 8-byte value
-     is considered to be a 2-item integer array, and is byte-swapped. A
-     boolean value that is not present means 'false', but cannot be
-     included in the structures since there is generally no mention of it
-     in the devicetree file.
-
-   - Naming of nodes and properties is automatic. This means that they follow
-     the naming in the devicetree, which may result in C identifiers that
-     look a bit strange.
-
-   - It is not possible to find a value given a property name. Code must use
-     the associated C member variable directly in the code. This makes
-     the code less robust in the face of devicetree changes. To avoid having
-     a second struct with similar members and names you need to explicitly
-     declare it as an alias with `DM_DRIVER_ALIAS()`.
-
-   - The platform data is provided to drivers as a C structure. The driver
-     must use the same structure to access the data. Since a driver
-     normally also supports devicetree it must use `#ifdef` to separate
-     out this code, since the structures are only available in SPL. This could
-     be fixed fairly easily by making the structs available outside SPL, so
-     that `IS_ENABLED()` could be used.
-
-   - With CONFIG_OF_PLATDATA_INST all binding happens at build-time, meaning
-     that (by default) it is not possible to call `device_bind()` from C code.
-     This means that all devices must have an associated devicetree node and
-     compatible string. For example if a GPIO device currently creates child
-     devices in its `bind()` method, it will not work with
-     CONFIG_OF_PLATDATA_INST. Arguably this is bad practice anyway and the
-     devicetree binding should be updated to declare compatible strings for
-     the child devices. It is possible to disable OF_PLATDATA_NO_BIND but this
-     is not recommended since it increases code size.
-
-
-Internals
----------
-
-Generated files
-```````````````
-
-When enabled, dtoc generates the following five files:
-
-include/generated/dt-decl.h (OF_PLATDATA_INST only)
-   Contains declarations for all drivers, devices and uclasses. This allows
-   any `struct udevice`, `struct driver` or `struct uclass` to be located by its
-   name
-
-include/generated/dt-structs-gen.h
-   Contains the struct definitions for the devicetree nodes that are used. This
-   is the same as without OF_PLATDATA_INST
-
-spl/dts/dt-plat.c (only with !OF_PLATDATA_INST)
-   Contains the `U_BOOT_DRVINFO()` declarations that U-Boot uses to bind devices
-   at start-up. See above for an example
-
-spl/dts/dt-device.c (only with OF_PLATDATA_INST)
-   Contains `DM_DEVICE_INST()` declarations for each device that can be used at
-   run-time. These are declared in the file along with any private/platform data
-   that they use. Every device has an idx, as above. Since each device must be
-   part of a double-linked list, the nodes are declared in the code as well.
-
-spl/dts/dt-uclass.c (only with OF_PLATDATA_INST)
-   Contains `DM_UCLASS_INST()` declarations for each uclass that can be used at
-   run-time. These are declared in the file along with any private data
-   associated with the uclass itself (the `.priv_auto` member). Since each
-   uclass must be part of a double-linked list, the nodes are declared in the
-   code as well.
-
-The dt-structs.h file includes the generated file
-`(include/generated/dt-structs.h`) if CONFIG_SPL_OF_PLATDATA is enabled.
-Otherwise (such as in U-Boot proper) these structs are not available. This
-prevents them being used inadvertently. All usage must be bracketed with
-`#if CONFIG_IS_ENABLED(OF_PLATDATA)`.
-
-The dt-plat.c file contains the device declarations and is is built in
-spl/dt-plat.c.
-
-
-CONFIG options
-``````````````
-
-Several CONFIG options are used to control the behaviour of of-platdata, all
-available for both SPL and TPL:
-
-OF_PLATDATA
-   This is the main option which enables the of-platdata feature
-
-OF_PLATDATA_PARENT
-   This allows `device_get_parent()` to work. Without this, all devices exist as
-   direct children of the root node. This option is highly desirable (if not
-   always absolutely essential) for buses such as I2C.
-
-OF_PLATDATA_INST
-   This controls the instantiation of devices at build time. With it disabled,
-   only `U_BOOT_DRVINFO()` records are created, with U-Boot handling the binding
-   in `device_bind()` on start-up. With it enabled, only `DM_DEVICE_INST()` and
-   `DM_UCLASS_INST()` records are created, and `device_bind()` is not needed at
-   runtime.
-
-OF_PLATDATA_NO_BIND
-   This controls whether `device_bind()` is supported. It is enabled by default
-   with OF_PLATDATA_INST since code-size reduction is really the main point of
-   the feature. It can be disabled if needed but is not likely to be supported
-   in the long term.
-
-OF_PLATDATA_DRIVER_RT
-   This controls whether the `struct driver_rt` records are used by U-Boot.
-   Normally when a device is bound, U-Boot stores the device pointer in one of
-   these records. There is one for every `struct driver_info` in the system,
-   i.e. one for every device that is bound from those records. It provides a
-   way to locate a device in the code and is used by
-   `device_get_by_ofplat_idx()`. This option is always enabled with of-platdata,
-   provided OF_PLATDATA_INST is not. In that case the records are useless since
-   we don't have any `struct driver_info` records.
-
-OF_PLATDATA_RT
-   This controls whether the `struct udevice_rt` records are used by U-Boot.
-   It moves the updatable fields from `struct udevice` (currently only `flags`)
-   into a separate structure, allowing the records to be kept in read-only
-   memory. It is generally enabled if OF_PLATDATA_INST is enabled. This option
-   also controls whether the private data is used in situ, or first copied into
-   an allocated region. Again this is to allow the private data declared by
-   dtoc-generated code to be in read-only memory. Note that access to private
-   data must be done via accessor functions, such as `dev_get_priv()`, so that
-   the relocation is handled.
-
-READ_ONLY
-   This indicates that the data generated by dtoc should not be modified. Only
-   a few fields actually do get changed in U-Boot, such as device flags. This
-   option causes those to move into an allocated space (see OF_PLATDATA_RT).
-   Also, since updating doubly linked lists is generally impossible when some of
-   the nodes cannot be updated, OF_PLATDATA_NO_BIND is enabled.
-
-Data structures
-```````````````
-
-A few extra data structures are used with of-platdata:
-
-`struct udevice_rt`
-   Run-time information for devices. When OF_PLATDATA_RT is enabled, this holds
-   the flags for each device, so that `struct udevice` can remain unchanged by
-   U-Boot, and potentially reside in read-only memory. Access to flags is then
-   via functions like `dev_get_flags()` and `dev_or_flags()`. This data
-   structure is allocated on start-up, where the private data is also copied.
-   All flags values start at 0 and any changes are handled by `dev_or_flags()`
-   and `dev_bic_flags()`. It would be more correct for the flags to be set to
-   `DM_FLAG_BOUND`, or perhaps `DM_FLAG_BOUND | DM_FLAG_ALLOC_PDATA`, but since
-   there is no code to bind/unbind devices and no code to allocate/free
-   private data / platform data, it doesn't matter.
-
-`struct driver_rt`
-   Run-time information for `struct driver_info` records. When
-   OF_PLATDATA_DRIVER_RT is enabled, this holds a pointer to the device
-   created by each record. This is needed so that is it possible to locate a
-   device from C code. Specifically, the code can use `DM_DRVINFO_GET(name)` to
-   get a reference to a particular `struct driver_info`, with `name` being the
-   name of the devicetree node. This is very convenient. It is also fast, since
-   no    searching or string comparison is needed. This data structure is
-   allocated    on start-up, filled out by `device_bind()` and used by
-   `device_get_by_ofplat_idx()`.
-
-Other changes
-`````````````
-
-Some other changes are made with of-platdata:
-
-Accessor functions
-   Accessing private / platform data via functions such as `dev_get_priv()` has
-   always been encouraged. With OF_PLATDATA_RT this is essential, since the
-   `priv_` and `plat_`  (etc.) values point to the data generated by dtoc, not
-   the read-write copy that is sometimes made on start-up. Changing the
-   private / platform data  pointers has always been discouraged (the API is
-   marked internal) but with OF_PLATDATA_RT this is not currently supported in
-   general, since it assumes that all such pointers point to the relocated data.
-   Note also that the renaming of struct members to have a trailing underscore
-   was partly done to make people aware that they should not be accessed
-   directly.
-
-`gd->uclass_root_s`
-   Normally U-Boot sets up the head of the uclass list here and makes
-   `gd->uclass_root` point to it. With OF_PLATDATA_INST, dtoc generates a
-   declaration of `uclass_head` in `dt-uclass.c` since it needs to link the
-   head node into the list. In that case, `gd->uclass_root_s` is not used and
-   U-Boot just makes `gd->uclass_root` point to `uclass_head`.
-
-`gd->dm_driver_rt`
-   This holds a pointer to a list of `struct driver_rt` records, one for each
-   `struct driver_info`. The list is in alphabetical order by the name used
-   in `U_BOOT_DRVINFO(name)` and indexed by idx, with the first record having
-   an index of 0. It is only used if OF_PLATDATA_INST is not enabled. This is
-   accessed via macros so that it can be used inside IS_ENABLED(), rather than
-   requiring #ifdefs in the C code when it is not present.
-
-`gd->dm_udevice_rt`
-   This holds a pointer to a list of `struct udevice_rt` records, one for each
-   `struct udevice`. The list is in alphabetical order by the name used
-   in `DM_DEVICE_INST(name)` (a C version of the devicetree node) and indexed by
-   idx, with the first record having an index of 0. It is only used if
-   OF_PLATDATA_INST is enabled. This is accessed via macros so that it can be
-   used inside `IS_ENABLED()`, rather than requiring #ifdefs in the C code when
-   it is not present.
-
-`gd->dm_priv_base`
-   When OF_PLATDATA_RT is enabled, the private/platform data for each device is
-   copied into an allocated region by U-Boot on start-up. This points to that
-   region. All calls to accessor functions (e.g. `dev_get_priv()`) then
-   translate from the pointer provided by the caller (assumed to lie between
-   `__priv_data_start` and `__priv_data_end`) to the new allocated region. This
-   member is accessed via macros so that it can be used inside IS_ENABLED(),
-   rather than required #ifdefs in the C code when it is not present.
-
-`struct udevice->flags_`
-   When OF_PLATDATA_RT is enabled, device flags are no-longer part of
-   `struct udevice`, but are instead kept in `struct udevice_rt`, as described
-   above. Flags are accessed via functions, such as `dev_get_flags()` and
-   `dev_or_flags()`.
-
-`struct udevice->node_`
-   When OF_PLATDATA is enabled, there is no devicetree at runtime, so no need
-   for this field. It is removed, just to save space.
-
-`DM_PHASE`
-   This macro is used to indicate which phase of U-Boot a driver is intended
-   for. See above for details.
-
-`DM_HDR`
-   This macro is used to indicate which header file dtoc should use to allow
-   a driver declaration to compile correctly. See above for details.
-
-`device_get_by_ofplat_idx()`
-   There used to be a function called `device_get_by_driver_info()` which
-   looked up a `struct driver_info` pointer and returned the `struct udevice`
-   that was created from it. It was only available for use with of-platdata.
-   This has been removed in favour of `device_get_by_ofplat_idx()` which uses
-   `idx`, the index of the `struct driver_info` or `struct udevice` in the
-   linker_list. Similarly, the `struct phandle_0_arg` (etc.) structs have been
-   updated to use this index instead of a pointer to `struct driver_info`.
-
-`DM_DRVINFO_GET`
-   This has been removed since we now use indexes to obtain a driver from
-   `struct phandle_0_arg` and the like.
-
-Two-pass binding
-   The original of-platdata tried to order `U_BOOT_DRVINFO()` in the generated
-   files so as to have parents declared ahead of children. This was convenient
-   as it avoided any special code in U-Boot. With OF_PLATDATA_INST this does
-   not work as the idx value relies on using alphabetical order for everything,
-   so that dtoc and U-Boot's linker_lists agree on the idx value. Devices are
-   then bound in order of idx, having no regard to parent/child relationships.
-   For this reason, device binding now hapens in multiple passes, with parents
-   being bound before their children. This is important so that children can
-   find their parents in the bind() method if needed.
-
-Root device
-   The root device is generally bound by U-Boot but with OF_PLATDATA_INST it
-   cannot be, since binding needs to be done at build time. So in this case
-   dtoc sets up a root device using `DM_DEVICE_INST()` in `dt-device.c` and
-   U-Boot makes use of that. When OF_PLATDATA_INST is not enabled, U-Boot
-   generally ignores the root node and does not create a `U_BOOT_DRVINFO()`
-   record for it. This means that the idx numbers used by `struct driver_info`
-   (when OF_PLATDATA_INST is disabled) and the idx numbers used by
-   `struct udevice` (when OF_PLATDATA_INST is enabled) differ, since one has a
-   root node and the other does not. This does not actually matter, since only
-   one of them is actually used for any particular build, but it is worth
-   keeping in mind if comparing index values and switching OF_PLATDATA_INST on
-   and off.
-
-`__priv_data_start` and `__priv_data_end`
-   The private/platform data declared by dtoc is all collected together in
-   a linker section and these symbols mark the start and end of it. This allows
-   U-Boot to relocate the area to a new location if needed (with
-   OF_PLATDATA_RT)
-
-`dm_priv_to_rw()`
-   This function converts a private- or platform-data pointer value generated by
-   dtoc into one that can be used by U-Boot. It is a NOP unless OF_PLATDATA_RT
-   is enabled, in which case it translates the address to the relocated
-   region. See above for more information.
-
-The dm_populate_phandle_data() function that was previous needed has now been
-removed, since dtoc can address the drivers directly from dt-plat.c and does
-not need to fix up things at runtime.
-
-The pylibfdt Python module is used to access the devicetree.
-
-
-Credits
--------
-
-This is an implementation of an idea by Tom Rini <[email protected]>.
-
-
-Future work
------------
-- Consider programmatically reading binding files instead of devicetree
-  contents
-- Allow IS_ENABLED() to be used in the C code instead of #if
-
-
-.. Simon Glass <[email protected]>
-.. Google, Inc
-.. 6/6/16
-.. Updated Independence Day 2016
-.. Updated 1st October 2020
-.. Updated 5th February 2021
diff --git a/doc/driver-model/pci-info.rst b/doc/driver-model/pci-info.rst
deleted file mode 100644 (file)
index 251601a..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-
-PCI with Driver Model
-=====================
-
-How busses are scanned
-----------------------
-
-Any config read will end up at pci_read_config(). This uses
-uclass_get_device_by_seq() to get the PCI bus for a particular bus number.
-Bus number 0 will need to be requested first, and the alias in the device
-tree file will point to the correct device::
-
-       aliases {
-               pci0 = &pcic;
-       };
-
-       pcic: pci@0 {
-               compatible = "sandbox,pci";
-               ...
-       };
-
-
-If there is no alias the devices will be numbered sequentially in the device
-tree.
-
-The call to uclass_get_device() will cause the PCI bus to be probed.
-This does a scan of the bus to locate available devices. These devices are
-bound to their appropriate driver if available. If there is no driver, then
-they are bound to a generic PCI driver which does nothing.
-
-After probing a bus, the available devices will appear in the device tree
-under that bus.
-
-Note that this is all done on a lazy basis, as needed, so until something is
-touched on PCI (eg: a call to pci_find_devices()) it will not be probed.
-
-PCI devices can appear in the flattened device tree. If they do, their node
-often contains extra information which cannot be derived from the PCI IDs or
-PCI class of the device. Each PCI device node must have a <reg> property, as
-defined by the IEEE Std 1275-1994 PCI bus binding document v2.1. Compatible
-string list is optional and generally not needed, since PCI is discoverable
-bus, albeit there are justified exceptions. If the compatible string is
-present, matching on it takes precedence over PCI IDs and PCI classes.
-
-Note we must describe PCI devices with the same bus hierarchy as the
-hardware, otherwise driver model cannot detect the correct parent/children
-relationship during PCI bus enumeration thus PCI devices won't be bound to
-their drivers accordingly. A working example like below::
-
-       pci {
-               #address-cells = <3>;
-               #size-cells = <2>;
-               compatible = "pci-x86";
-               u-boot,dm-pre-reloc;
-               ranges = <0x02000000 0x0 0x40000000 0x40000000 0 0x80000000
-                         0x42000000 0x0 0xc0000000 0xc0000000 0 0x20000000
-                         0x01000000 0x0 0x2000 0x2000 0 0xe000>;
-
-               pcie@17,0 {
-                       #address-cells = <3>;
-                       #size-cells = <2>;
-                       compatible = "pci-bridge";
-                       u-boot,dm-pre-reloc;
-                       reg = <0x0000b800 0x0 0x0 0x0 0x0>;
-
-                       topcliff@0,0 {
-                               #address-cells = <3>;
-                               #size-cells = <2>;
-                               compatible = "pci-bridge";
-                               u-boot,dm-pre-reloc;
-                               reg = <0x00010000 0x0 0x0 0x0 0x0>;
-
-                               pciuart0: uart@a,1 {
-                                       compatible = "pci8086,8811.00",
-                                                       "pci8086,8811",
-                                                       "pciclass,070002",
-                                                       "pciclass,0700",
-                                                       "x86-uart";
-                                       u-boot,dm-pre-reloc;
-                                       reg = <0x00025100 0x0 0x0 0x0 0x0
-                                              0x01025110 0x0 0x0 0x0 0x0>;
-                                       ......
-                               };
-
-                               ......
-                       };
-               };
-
-               ......
-       };
-
-In this example, the root PCI bus node is the "/pci" which matches "pci-x86"
-driver. It has a subnode "pcie@17,0" with driver "pci-bridge". "pcie@17,0"
-also has subnode "topcliff@0,0" which is a "pci-bridge" too. Under that bridge,
-a PCI UART device "uart@a,1" is described. This exactly reflects the hardware
-bus hierarchy: on the root PCI bus, there is a PCIe root port which connects
-to a downstream device Topcliff chipset. Inside Topcliff chipset, it has a
-PCIe-to-PCI bridge and all the chipset integrated devices like the PCI UART
-device are on the PCI bus. Like other devices in the device tree, if we want
-to bind PCI devices before relocation, "u-boot,dm-pre-reloc" must be declared
-in each of these nodes.
-
-If PCI devices are not listed in the device tree, U_BOOT_PCI_DEVICE can be used
-to specify the driver to use for the device. The device tree takes precedence
-over U_BOOT_PCI_DEVICE. Please note with U_BOOT_PCI_DEVICE, only drivers with
-DM_FLAG_PRE_RELOC will be bound before relocation. If neither device tree nor
-U_BOOT_PCI_DEVICE is provided, the built-in driver (either pci_bridge_drv or
-pci_generic_drv) will be used.
-
-
-Sandbox
--------
-
-With sandbox we need a device emulator for each device on the bus since there
-is no real PCI bus. This works by looking in the device tree node for an
-emulator driver. For example::
-
-       pci@1f,0 {
-               compatible = "pci-generic";
-               reg = <0xf800 0 0 0 0>;
-               sandbox,emul = <&emul_1f>;
-       };
-       pci-emul {
-               compatible = "sandbox,pci-emul-parent";
-               emul_1f: emul@1f,0 {
-                       compatible = "sandbox,swap-case";
-                       #emul-cells = <0>;
-               };
-       };
-
-This means that there is a 'sandbox,swap-case' driver at that bus position.
-Note that the first cell in the 'reg' value is the bus/device/function. See
-PCI_BDF() for the encoding (it is also specified in the IEEE Std 1275-1994
-PCI bus binding document, v2.1)
-
-The pci-emul node should go outside the pci bus node, since otherwise it will
-be scanned as a PCI device, causing confusion.
-
-When this bus is scanned we will end up with something like this::
-
-   `- * pci@0 @ 05c660c8, 0
-    `-   pci@1f,0 @ 05c661c8, 63488
-   `-   emul@1f,0 @ 05c662c8
-
-When accesses go to the pci@1f,0 device they are forwarded to its emulator.
-
-The sandbox PCI drivers also support dynamic driver binding, allowing device
-driver to declare the driver binding information via U_BOOT_PCI_DEVICE(),
-eliminating the need to provide any device tree node under the host controller
-node. It is required a "sandbox,dev-info" property must be provided in the
-host controller node for this functionality to work.
-
-.. code-block:: none
-
-       pci1: pci@1 {
-               compatible = "sandbox,pci";
-               ...
-               sandbox,dev-info = <0x08 0x00 0x1234 0x5678
-                                   0x0c 0x00 0x1234 0x5678>;
-       };
-
-The "sandbox,dev-info" property specifies all dynamic PCI devices on this bus.
-Each dynamic PCI device is encoded as 4 cells a group. The first and second
-cells are PCI device number and function number respectively. The third and
-fourth cells are PCI vendor ID and device ID respectively.
-
-When this bus is scanned we will end up with something like this::
-
- pci        [ + ]   pci_sandbo  |-- pci1
- pci_emul   [   ]   sandbox_sw  |   |-- sandbox_swap_case_emul
- pci_emul   [   ]   sandbox_sw  |   `-- sandbox_swap_case_emul
diff --git a/doc/driver-model/pmic-framework.rst b/doc/driver-model/pmic-framework.rst
deleted file mode 100644 (file)
index d24a1ba..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-.. (C) Copyright 2014-2015 Samsung Electronics
-.. sectionauthor:: Przemyslaw Marczak <[email protected]>
-
-PMIC framework based on Driver Model
-====================================
-
-Introduction
-------------
-This is an introduction to driver-model multi uclass PMIC IC's support.
-At present it's based on two uclass types:
-
-UCLASS_PMIC:
-  basic uclass type for PMIC I/O, which provides common
-  read/write interface.
-UCLASS_REGULATOR:
-  additional uclass type for specific PMIC features, which are
-  Voltage/Current regulators.
-
-New files:
-
-UCLASS_PMIC:
-  - drivers/power/pmic/pmic-uclass.c
-  - include/power/pmic.h
-UCLASS_REGULATOR:
-  - drivers/power/regulator/regulator-uclass.c
-  - include/power/regulator.h
-
-Commands:
-- common/cmd_pmic.c
-- common/cmd_regulator.c
-
-How doees it work
------------------
-The Power Management Integrated Circuits (PMIC) are used in embedded systems
-to provide stable, precise and specific voltage power source with over-voltage
-and thermal protection circuits.
-
-The single PMIC can provide various functions by single or multiple interfaces,
-like in the example below::
-
-   -- SoC
-    |
-    |            ______________________________________
-    | BUS 0     |       Multi interface PMIC IC        |--> LDO out 1
-    | e.g.I2C0  |                                      |--> LDO out N
-    |-----------|---- PMIC device 0 (READ/WRITE ops)   |
-    | or SPI0   |    |_ REGULATOR device (ldo/... ops) |--> BUCK out 1
-    |           |    |_ CHARGER device (charger ops)   |--> BUCK out M
-    |           |    |_ MUIC device (microUSB con ops) |
-    | BUS 1     |    |_ ...                            |---> BATTERY
-    | e.g.I2C1  |                                      |
-    |-----------|---- PMIC device 1 (READ/WRITE ops)   |---> USB in 1
-    . or SPI1   |    |_ RTC device (rtc ops)           |---> USB in 2
-    .           |______________________________________|---> USB out
-    .
-
-Since U-Boot provides driver model features for I2C and SPI bus drivers,
-the PMIC devices should also support this. By the pmic and regulator API's,
-PMIC drivers can simply provide a common functions, for multi-interface and
-and multi-instance device support.
-
-Basic design assumptions:
-
-- Common I/O API:
-    UCLASS_PMIC. For the multi-function PMIC devices, this can be used as
-    parent I/O device for each IC's interface. Then, each children uses the
-    same dev for read/write.
-
-- Common regulator API:
-    UCLASS_REGULATOR. For driving the regulator attributes, auto setting
-    function or command line interface, based on kernel-style regulator device
-    tree constraints.
-
-For simple implementations, regulator drivers are not required, so the code can
-use pmic read/write directly.
-
-Pmic uclass
------------
-The basic information:
-
-* Uclass:   'UCLASS_PMIC'
-* Header:   'include/power/pmic.h'
-* Core:     'drivers/power/pmic/pmic-uclass.c' (config 'CONFIG_DM_PMIC')
-* Command:  'common/cmd_pmic.c' (config 'CONFIG_CMD_PMIC')
-* Example:  'drivers/power/pmic/max77686.c'
-
-For detailed API description, please refer to the header file.
-
-As an example of the pmic driver, please refer to the MAX77686 driver.
-
-Please pay attention for the driver's bind() method. Exactly the function call:
-'pmic_bind_children()', which is used to bind the regulators by using the array
-of regulator's node, compatible prefixes.
-
-The 'pmic; command also supports the new API. So the pmic command can be enabled
-by adding CONFIG_CMD_PMIC.
-The new pmic command allows to:
-- list pmic devices
-- choose the current device (like the mmc command)
-- read or write the pmic register
-- dump all pmic registers
-
-This command can use only UCLASS_PMIC devices, since this uclass is designed
-for pmic I/O operations only.
-
-For more information, please refer to the core file.
-
-Regulator uclass
-----------------
-The basic information:
-
-* Uclass: 'UCLASS_REGULATOR'
-
-* Header: 'include/power/regulator.h'
-
-* Core: 'drivers/power/regulator/regulator-uclass.c'
-  (config 'CONFIG_DM_REGULATOR')
-
-* Binding: 'doc/device-tree-bindings/regulator/regulator.txt'
-
-* Command: 'common/cmd_regulator.c' (config 'CONFIG_CMD_REGULATOR')
-
-* Example: 'drivers/power/regulator/max77686.c'
-  'drivers/power/pmic/max77686.c' (required I/O driver for the above)
-
-* Example: 'drivers/power/regulator/fixed.c'
-  (config 'CONFIG_DM_REGULATOR_FIXED')
-
-For detailed API description, please refer to the header file.
-
-For the example regulator driver, please refer to the MAX77686 regulator driver,
-but this driver can't operate without pmic's example driver, which provides an
-I/O interface for MAX77686 regulator.
-
-The second example is a fixed Voltage/Current regulator for a common use.
-
-The 'regulator' command also supports the new API. The command allow:
-- list regulator devices
-- choose the current device (like the mmc command)
-- do all regulator-specific operations
-
-For more information, please refer to the command file.
diff --git a/doc/driver-model/remoteproc-framework.rst b/doc/driver-model/remoteproc-framework.rst
deleted file mode 100644 (file)
index 566495a..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-.. (C) Copyright 2015
-.. Texas Instruments Incorporated - http://www.ti.com/
-
-Remote Processor Framework
-==========================
-
-Introduction
-------------
-
-This is an introduction to driver-model for Remote Processors found
-on various System on Chip(SoCs). The term remote processor is used to
-indicate that this is not the processor on which U-Boot is operating
-on, instead is yet another processing entity that may be controlled by
-the processor on which we are functional.
-
-The simplified model depends on a single UCLASS - UCLASS_REMOTEPROC
-
-UCLASS_REMOTEPROC:
-  - drivers/remoteproc/rproc-uclass.c
-  - include/remoteproc.h
-
-Commands:
-  - common/cmd_remoteproc.c
-
-Configuration:
-  - CONFIG_REMOTEPROC is selected by drivers as needed
-  - CONFIG_CMD_REMOTEPROC for the commands if required.
-
-How does it work - The driver
------------------------------
-
-Overall, the driver statemachine transitions are typically as follows::
-
-           (entry)
-           +-------+
-       +---+ init  |
-       |   |       | <---------------------+
-       |   +-------+                       |
-       |                                   |
-       |                                   |
-       |   +--------+                      |
-   Load|   |  reset |                      |
-       |   |        | <----------+         |
-       |   +--------+            |         |
-       |        |Load            |         |
-       |        |                |         |
-       |   +----v----+   reset   |         |
-       +-> |         |    (opt)  |         |
-           |  Loaded +-----------+         |
-           |         |                     |
-           +----+----+                     |
-                | Start                    |
-            +---v-----+        (opt)       |
-         +->| Running |        Stop        |
-   Ping  +- |         +--------------------+
-   (opt)    +---------+
-
-(is_running does not change state)
-opt: Optional state transition implemented by driver.
-
-NOTE: It depends on the remote processor as to the exact behavior
-of the statemachine, remoteproc core does not intent to implement
-statemachine logic. Certain processors may allow start/stop without
-reloading the image in the middle, certain other processors may only
-allow us to start the processor(image from a EEPROM/OTP) etc.
-
-It is hence the responsibility of the driver to handle the requisite
-state transitions of the device as necessary.
-
-Basic design assumptions:
-
-Remote processor can operate on a certain firmware that maybe loaded
-and released from reset.
-
-The driver follows a standard UCLASS DM.
-
-in the bare minimum form:
-
-.. code-block:: c
-
-       static const struct dm_rproc_ops sandbox_testproc_ops = {
-               .load = sandbox_testproc_load,
-               .start = sandbox_testproc_start,
-       };
-
-       static const struct udevice_id sandbox_ids[] = {
-               {.compatible = "sandbox,test-processor"},
-               {}
-       };
-
-       U_BOOT_DRIVER(sandbox_testproc) = {
-               .name = "sandbox_test_proc",
-               .of_match = sandbox_ids,
-               .id = UCLASS_REMOTEPROC,
-               .ops = &sandbox_testproc_ops,
-               .probe = sandbox_testproc_probe,
-       };
-
-This allows for the device to be probed as part of the "init" command
-or invocation of 'rproc_init()' function as the system dependencies define.
-
-The driver is expected to maintain it's own statemachine which is
-appropriate for the device it maintains. It must, at the very least
-provide a load and start function. We assume here that the device
-needs to be loaded and started, else, there is no real purpose of
-using the remoteproc framework.
-
-Describing the device using platform data
------------------------------------------
-
-*IMPORTANT* NOTE: THIS SUPPORT IS NOT MEANT FOR USE WITH NEWER PLATFORM
-SUPPORT. THIS IS ONLY FOR LEGACY DEVICES. THIS MODE OF INITIALIZATION
-*WILL* BE EVENTUALLY REMOVED ONCE ALL NECESSARY PLATFORMS HAVE MOVED
-TO DM/FDT.
-
-Considering that many platforms are yet to move to device-tree model,
-a simplified definition of a device is as follows:
-
-.. code-block:: c
-
-       struct dm_rproc_uclass_pdata proc_3_test = {
-               .name = "proc_3_legacy",
-               .mem_type = RPROC_INTERNAL_MEMORY_MAPPED,
-               .driver_plat_data = &mydriver_data;
-       };
-
-       U_BOOT_DRVINFO(proc_3_demo) = {
-               .name = "sandbox_test_proc",
-               .plat = &proc_3_test,
-       };
-
-There can be additional data that may be desired depending on the
-remoteproc driver specific needs (for example: SoC integration
-details such as clock handle or something similar). See appropriate
-documentation for specific remoteproc driver for further details.
-These are passed via driver_plat_data.
-
-Describing the device using device tree
----------------------------------------
-
-.. code-block: none
-
-       / {
-               ...
-               aliases {
-                       ...
-                       remoteproc0 = &rproc_1;
-                       remoteproc1 = &rproc_2;
-
-               };
-               ...
-
-               rproc_1: rproc@1 {
-                       compatible = "sandbox,test-processor";
-                       remoteproc-name = "remoteproc-test-dev1";
-               };
-
-               rproc_2: rproc@2 {
-                       compatible = "sandbox,test-processor";
-                       internal-memory-mapped;
-                       remoteproc-name = "remoteproc-test-dev2";
-               };
-               ...
-       };
-
-aliases usage is optional, but it is usually recommended to ensure the
-users have a consistent usage model for a platform.
-the compatible string used here is specific to the remoteproc driver involved.
diff --git a/doc/driver-model/serial-howto.rst b/doc/driver-model/serial-howto.rst
deleted file mode 100644 (file)
index 1469131..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-
-How to port a serial driver to driver model
-===========================================
-
-Almost all of the serial drivers have been converted as at January 2016. These
-ones remain:
-
-   * serial_bfin.c
-   * serial_pxa.c
-
-The deadline for this work was the end of January 2016. If no one steps
-forward to convert these, at some point there may come a patch to remove them!
-
-Here is a suggested approach for converting your serial driver over to driver
-model. Please feel free to update this file with your ideas and suggestions.
-
-- #ifdef out all your own serial driver code (#ifndef CONFIG_DM_SERIAL)
-- Define CONFIG_DM_SERIAL for your board, vendor or architecture
-- If the board does not already use driver model, you need CONFIG_DM also
-- Your board should then build, but will not boot since there will be no serial
-  driver
-- Add the U_BOOT_DRIVER piece at the end (e.g. copy serial_s5p.c for example)
-- Add a private struct for the driver data - avoid using static variables
-- Implement each of the driver methods, perhaps by calling your old methods
-- You may need to adjust the function parameters so that the old and new
-  implementations can share most of the existing code
-- If you convert all existing users of the driver, remove the pre-driver-model
-  code
-
-In terms of patches a conversion series typically has these patches:
-- clean up / prepare the driver for conversion
-- add driver model code
-- convert at least one existing board to use driver model serial
-- (if no boards remain that don't use driver model) remove the old code
-
-This may be a good time to move your board to use device tree also. Mostly
-this involves these steps:
-
-- define CONFIG_OF_CONTROL and CONFIG_OF_SEPARATE
-- add your device tree files to arch/<arch>/dts
-- update the Makefile there
-- Add stdout-path to your /chosen device tree node if it is not already there
-- build and get u-boot-dtb.bin so you can test it
-- Your drivers can now use device tree
-- For device tree in SPL, define CONFIG_SPL_OF_CONTROL
diff --git a/doc/driver-model/soc-framework.rst b/doc/driver-model/soc-framework.rst
deleted file mode 100644 (file)
index 2609fda..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-.. (C) Copyright 2020
-.. Texas Instruments Incorporated - http://www.ti.com/
-
-SOC ID Framework
-================
-
-Introduction
-------------
-
-The driver-model SOC ID framework is able to provide identification
-information about a specific SoC in use at runtime, and also provide matching
-from a set of identification information from an array. This can be useful for
-enabling small quirks in drivers that exist between SoC variants that are
-impractical to implement using device tree flags. It is based on UCLASS_SOC.
-
-UCLASS_SOC:
-  - drivers/soc/soc-uclass.c
-  - include/soc.h
-
-Configuration:
-  - CONFIG_SOC_DEVICE is selected by drivers as needed.
-
-Implementing a UCLASS_SOC provider
-----------------------------------
-
-The purpose of this framework is to allow UCLASS_SOC provider drivers to supply
-identification information about the SoC in use at runtime. The framework
-allows drivers to define soc_ops that return identification strings.  All
-soc_ops need not be defined and can be left as NULL, in which case the
-framework will return -ENOSYS and not consider the value when doing an
-soc_device_match.
-
-It is left to the driver implementor to decide how the information returned is
-determined, but in general the same SOC should always return the same set of
-identifying information. Information returned must be in the form of a NULL
-terminated string.
-
-See include/soc.h for documentation of the available soc_ops and the intended
-meaning of the values that can be returned. See drivers/soc/soc_sandbox.c for
-an example UCLASS_SOC provider driver.
-
-Using a UCLASS_SOC driver
--------------------------
-
-The framework provides the ability to retrieve and use the identification
-strings directly. It also has the ability to return a match from a list of
-different sets of SoC data using soc_device_match.
-
-An array of 'struct soc_attr' can be defined, each containing ID information
-for a specific SoC, and when passed to soc_device_match, the identifier values
-for each entry in the list will be compared against the values provided by the
-UCLASS_SOC driver that is in use. The first entry in the list that matches all
-non-null values will be returned by soc_device_match.
-
-An example of various uses of the framework can be found at test/dm/soc.c.
-
-Describing the device using device tree
----------------------------------------
-
-.. code-block:: none
-
-   chipid: chipid {
-        compatible = "sandbox,soc";
-   };
-
-All that is required in a DT node is a compatible for a corresponding
-UCLASS_SOC driver.
diff --git a/doc/driver-model/spi-howto.rst b/doc/driver-model/spi-howto.rst
deleted file mode 100644 (file)
index 97fbf75..0000000
+++ /dev/null
@@ -1,692 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-
-How to port a SPI driver to driver model
-========================================
-
-Here is a rough step-by-step guide. It is based around converting the
-exynos SPI driver to driver model (DM) and the example code is based
-around U-Boot v2014.10-rc2 (commit be9f643). This has been updated for
-v2015.04.
-
-It is quite long since it includes actual code examples.
-
-Before driver model, SPI drivers have their own private structure which
-contains 'struct spi_slave'. With driver model, 'struct spi_slave' still
-exists, but now it is 'per-child data' for the SPI bus. Each child of the
-SPI bus is a SPI slave. The information that was stored in the
-driver-specific slave structure can now be port in private data for the
-SPI bus.
-
-For example, struct tegra_spi_slave looks like this:
-
-.. code-block:: c
-
-       struct tegra_spi_slave {
-               struct spi_slave slave;
-               struct tegra_spi_ctrl *ctrl;
-       };
-
-In this case 'slave' will be in per-child data, and 'ctrl' will be in the
-SPI's buses private data.
-
-
-How long does this take?
-------------------------
-
-You should be able to complete this within 2 hours, including testing but
-excluding preparing the patches. The API is basically the same as before
-with only minor changes:
-
-- methods to set speed and mode are separated out
-- cs_info is used to get information on a chip select
-
-
-Enable driver mode for SPI and SPI flash
-----------------------------------------
-
-Add these to your board config:
-
-* CONFIG_DM_SPI
-* CONFIG_DM_SPI_FLASH
-
-
-Add the skeleton
-----------------
-
-Put this code at the bottom of your existing driver file:
-
-.. code-block:: c
-
-       struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs,
-                                         unsigned int max_hz, unsigned int mode)
-       {
-               return NULL;
-       }
-
-       struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
-                                             int spi_node)
-       {
-               return NULL;
-       }
-
-       static int exynos_spi_of_to_plat(struct udevice *dev)
-       {
-               return -ENODEV;
-       }
-
-       static int exynos_spi_probe(struct udevice *dev)
-       {
-               return -ENODEV;
-       }
-
-       static int exynos_spi_remove(struct udevice *dev)
-       {
-               return -ENODEV;
-       }
-
-       static int exynos_spi_claim_bus(struct udevice *dev)
-       {
-
-               return -ENODEV;
-       }
-
-       static int exynos_spi_release_bus(struct udevice *dev)
-       {
-
-               return -ENODEV;
-       }
-
-       static int exynos_spi_xfer(struct udevice *dev, unsigned int bitlen,
-                                  const void *dout, void *din, unsigned long flags)
-       {
-
-               return -ENODEV;
-       }
-
-       static int exynos_spi_set_speed(struct udevice *dev, uint speed)
-       {
-               return -ENODEV;
-       }
-
-       static int exynos_spi_set_mode(struct udevice *dev, uint mode)
-       {
-               return -ENODEV;
-       }
-
-       static int exynos_cs_info(struct udevice *bus, uint cs,
-                                 struct spi_cs_info *info)
-       {
-               return -EINVAL;
-       }
-
-       static const struct dm_spi_ops exynos_spi_ops = {
-               .claim_bus      = exynos_spi_claim_bus,
-               .release_bus    = exynos_spi_release_bus,
-               .xfer           = exynos_spi_xfer,
-               .set_speed      = exynos_spi_set_speed,
-               .set_mode       = exynos_spi_set_mode,
-               .cs_info        = exynos_cs_info,
-       };
-
-       static const struct udevice_id exynos_spi_ids[] = {
-               { .compatible = "samsung,exynos-spi" },
-               { }
-       };
-
-       U_BOOT_DRIVER(exynos_spi) = {
-               .name   = "exynos_spi",
-               .id     = UCLASS_SPI,
-               .of_match = exynos_spi_ids,
-               .ops    = &exynos_spi_ops,
-               .of_to_plat = exynos_spi_of_to_plat,
-               .probe  = exynos_spi_probe,
-               .remove = exynos_spi_remove,
-       };
-
-
-Replace 'exynos' in the above code with your driver name
---------------------------------------------------------
-
-
-#ifdef out all of the code in your driver except for the above
---------------------------------------------------------------
-
-This will allow you to get it building, which means you can work
-incrementally. Since all the methods return an error initially, there is
-less chance that you will accidentally leave something in.
-
-Also, even though your conversion is basically a rewrite, it might help
-reviewers if you leave functions in the same place in the file,
-particularly for large drivers.
-
-
-Add some includes
------------------
-
-Add these includes to your driver:
-
-.. code-block:: c
-
-       #include <dm.h>
-       #include <errno.h>
-
-
-Build
------
-
-At this point you should be able to build U-Boot for your board with the
-empty SPI driver. You still have empty methods in your driver, but we will
-write these one by one.
-
-Set up your platform data structure
------------------------------------
-
-This will hold the information your driver to operate, like its hardware
-address or maximum frequency.
-
-You may already have a struct like this, or you may need to create one
-from some of the #defines or global variables in the driver.
-
-Note that this information is not the run-time information. It should not
-include state that changes. It should be fixed throughout the live of
-U-Boot. Run-time information comes later.
-
-Here is what was in the exynos spi driver:
-
-.. code-block:: c
-
-       struct spi_bus {
-               enum periph_id periph_id;
-               s32 frequency;          /* Default clock frequency, -1 for none */
-               struct exynos_spi *regs;
-               int inited;             /* 1 if this bus is ready for use */
-               int node;
-               uint deactivate_delay_us;       /* Delay to wait after deactivate */
-       };
-
-Of these, inited is handled by DM and node is the device tree node, which
-DM tells you. The name is not quite right. So in this case we would use:
-
-.. code-block:: c
-
-       struct exynos_spi_plat {
-               enum periph_id periph_id;
-               s32 frequency;          /* Default clock frequency, -1 for none */
-               struct exynos_spi *regs;
-               uint deactivate_delay_us;       /* Delay to wait after deactivate */
-       };
-
-
-Write of_to_plat() [for device tree only]
--------------------------------------------------
-
-This method will convert information in the device tree node into a C
-structure in your driver (called platform data). If you are not using
-device tree, go to 8b.
-
-DM will automatically allocate the struct for us when we are using device
-tree, but we need to tell it the size:
-
-.. code-block:: c
-
-       U_BOOT_DRIVER(spi_exynos) = {
-       ...
-               .plat_auto = sizeof(struct exynos_spi_plat),
-
-
-Here is a sample function. It gets a pointer to the platform data and
-fills in the fields from device tree.
-
-.. code-block:: c
-
-       static int exynos_spi_of_to_plat(struct udevice *bus)
-       {
-               struct exynos_spi_plat *plat = bus->plat;
-               const void *blob = gd->fdt_blob;
-               int node = dev_of_offset(bus);
-
-               plat->regs = (struct exynos_spi *)fdtdec_get_addr(blob, node, "reg");
-               plat->periph_id = pinmux_decode_periph_id(blob, node);
-
-               if (plat->periph_id == PERIPH_ID_NONE) {
-                       debug("%s: Invalid peripheral ID %d\n", __func__,
-                               plat->periph_id);
-                       return -FDT_ERR_NOTFOUND;
-               }
-
-               /* Use 500KHz as a suitable default */
-               plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
-                                               500000);
-               plat->deactivate_delay_us = fdtdec_get_int(blob, node,
-                                               "spi-deactivate-delay", 0);
-               debug("%s: regs=%p, periph_id=%d, max-frequency=%d, deactivate_delay=%d\n",
-                     __func__, plat->regs, plat->periph_id, plat->frequency,
-                     plat->deactivate_delay_us);
-
-               return 0;
-       }
-
-
-Add the platform data [non-device-tree only]
---------------------------------------------
-
-Specify this data in a U_BOOT_DRVINFO() declaration in your board file:
-
-.. code-block:: c
-
-       struct exynos_spi_plat platdata_spi0 = {
-               .periph_id = ...
-               .frequency = ...
-               .regs = ...
-               .deactivate_delay_us = ...
-       };
-
-       U_BOOT_DRVINFO(board_spi0) = {
-               .name = "exynos_spi",
-               .plat = &platdata_spi0,
-       };
-
-You will unfortunately need to put the struct definition into a header file
-in this case so that your board file can use it.
-
-
-Add the device private data
----------------------------
-
-Most devices have some private data which they use to keep track of things
-while active. This is the run-time information and needs to be stored in
-a structure. There is probably a structure in the driver that includes a
-'struct spi_slave', so you can use that.
-
-.. code-block:: c
-
-       struct exynos_spi_slave {
-               struct spi_slave slave;
-               struct exynos_spi *regs;
-               unsigned int freq;              /* Default frequency */
-               unsigned int mode;
-               enum periph_id periph_id;       /* Peripheral ID for this device */
-               unsigned int fifo_size;
-               int skip_preamble;
-               struct spi_bus *bus;            /* Pointer to our SPI bus info */
-               ulong last_transaction_us;      /* Time of last transaction end */
-       };
-
-
-We should rename this to make its purpose more obvious, and get rid of
-the slave structure, so we have:
-
-.. code-block:: c
-
-       struct exynos_spi_priv {
-               struct exynos_spi *regs;
-               unsigned int freq;              /* Default frequency */
-               unsigned int mode;
-               enum periph_id periph_id;       /* Peripheral ID for this device */
-               unsigned int fifo_size;
-               int skip_preamble;
-               ulong last_transaction_us;      /* Time of last transaction end */
-       };
-
-
-DM can auto-allocate this also:
-
-.. code-block:: c
-
-       U_BOOT_DRIVER(spi_exynos) = {
-       ...
-               .priv_auto = sizeof(struct exynos_spi_priv),
-
-
-Note that this is created before the probe method is called, and destroyed
-after the remove method is called. It will be zeroed when the probe
-method is called.
-
-
-Add the probe() and remove() methods
-------------------------------------
-
-Note: It's a good idea to build repeatedly as you are working, to avoid a
-huge amount of work getting things compiling at the end.
-
-The probe method is supposed to set up the hardware. U-Boot used to use
-spi_setup_slave() to do this. So take a look at this function and see
-what you can copy out to set things up.
-
-.. code-block:: c
-
-       static int exynos_spi_probe(struct udevice *bus)
-       {
-               struct exynos_spi_plat *plat = dev_get_plat(bus);
-               struct exynos_spi_priv *priv = dev_get_priv(bus);
-
-               priv->regs = plat->regs;
-               if (plat->periph_id == PERIPH_ID_SPI1 ||
-                   plat->periph_id == PERIPH_ID_SPI2)
-                       priv->fifo_size = 64;
-               else
-                       priv->fifo_size = 256;
-
-               priv->skip_preamble = 0;
-               priv->last_transaction_us = timer_get_us();
-               priv->freq = plat->frequency;
-               priv->periph_id = plat->periph_id;
-
-               return 0;
-       }
-
-This implementation doesn't actually touch the hardware, which is somewhat
-unusual for a driver. In this case we will do that when the device is
-claimed by something that wants to use the SPI bus.
-
-For remove we could shut down the clocks, but in this case there is
-nothing to do. DM frees any memory that it allocated, so we can just
-remove exynos_spi_remove() and its reference in U_BOOT_DRIVER.
-
-
-Implement set_speed()
----------------------
-
-This should set up clocks so that the SPI bus is running at the right
-speed. With the old API spi_claim_bus() would normally do this and several
-of the following functions, so let's look at that function:
-
-.. code-block:: c
-
-       int spi_claim_bus(struct spi_slave *slave)
-       {
-               struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
-               struct exynos_spi *regs = spi_slave->regs;
-               u32 reg = 0;
-               int ret;
-
-               ret = set_spi_clk(spi_slave->periph_id,
-                                               spi_slave->freq);
-               if (ret < 0) {
-                       debug("%s: Failed to setup spi clock\n", __func__);
-                       return ret;
-               }
-
-               exynos_pinmux_config(spi_slave->periph_id, PINMUX_FLAG_NONE);
-
-               spi_flush_fifo(slave);
-
-               reg = readl(&regs->ch_cfg);
-               reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L);
-
-               if (spi_slave->mode & SPI_CPHA)
-                       reg |= SPI_CH_CPHA_B;
-
-               if (spi_slave->mode & SPI_CPOL)
-                       reg |= SPI_CH_CPOL_L;
-
-               writel(reg, &regs->ch_cfg);
-               writel(SPI_FB_DELAY_180, &regs->fb_clk);
-
-               return 0;
-       }
-
-
-It sets up the speed, mode, pinmux, feedback delay and clears the FIFOs.
-With DM these will happen in separate methods.
-
-
-Here is an example for the speed part:
-
-.. code-block:: c
-
-       static int exynos_spi_set_speed(struct udevice *bus, uint speed)
-       {
-               struct exynos_spi_plat *plat = bus->plat;
-               struct exynos_spi_priv *priv = dev_get_priv(bus);
-               int ret;
-
-               if (speed > plat->frequency)
-                       speed = plat->frequency;
-               ret = set_spi_clk(priv->periph_id, speed);
-               if (ret)
-                       return ret;
-               priv->freq = speed;
-               debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq);
-
-               return 0;
-       }
-
-
-Implement set_mode()
---------------------
-
-This should adjust the SPI mode (polarity, etc.). Again this code probably
-comes from the old spi_claim_bus(). Here is an example:
-
-.. code-block:: c
-
-       static int exynos_spi_set_mode(struct udevice *bus, uint mode)
-       {
-               struct exynos_spi_priv *priv = dev_get_priv(bus);
-               uint32_t reg;
-
-               reg = readl(&priv->regs->ch_cfg);
-               reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L);
-
-               if (mode & SPI_CPHA)
-                       reg |= SPI_CH_CPHA_B;
-
-               if (mode & SPI_CPOL)
-                       reg |= SPI_CH_CPOL_L;
-
-               writel(reg, &priv->regs->ch_cfg);
-               priv->mode = mode;
-               debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
-
-               return 0;
-       }
-
-
-Implement claim_bus()
----------------------
-
-This is where a client wants to make use of the bus, so claims it first.
-At this point we need to make sure everything is set up ready for data
-transfer. Note that this function is wholly internal to the driver - at
-present the SPI uclass never calls it.
-
-Here again we look at the old claim function and see some code that is
-needed. It is anything unrelated to speed and mode:
-
-.. code-block:: c
-
-       static int exynos_spi_claim_bus(struct udevice *bus)
-       {
-               struct exynos_spi_priv *priv = dev_get_priv(bus);
-
-               exynos_pinmux_config(priv->periph_id, PINMUX_FLAG_NONE);
-               spi_flush_fifo(priv->regs);
-
-               writel(SPI_FB_DELAY_180, &priv->regs->fb_clk);
-
-               return 0;
-       }
-
-The spi_flush_fifo() function is in the removed part of the code, so we
-need to expose it again (perhaps with an #endif before it and '#if 0'
-after it). It only needs access to priv->regs which is why we have
-passed that in:
-
-.. code-block:: c
-
-       /**
-        * Flush spi tx, rx fifos and reset the SPI controller
-        *
-        * @param regs  Pointer to SPI registers
-        */
-       static void spi_flush_fifo(struct exynos_spi *regs)
-       {
-               clrsetbits_le32(&regs->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST);
-               clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
-               setbits_le32(&regs->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON);
-       }
-
-
-Implement release_bus()
------------------------
-
-This releases the bus - in our example the old code in spi_release_bus()
-is a call to spi_flush_fifo, so we add:
-
-.. code-block:: c
-
-       static int exynos_spi_release_bus(struct udevice *bus)
-       {
-               struct exynos_spi_priv *priv = dev_get_priv(bus);
-
-               spi_flush_fifo(priv->regs);
-
-               return 0;
-       }
-
-
-Implement xfer()
-----------------
-
-This is the final method that we need to create, and it is where all the
-work happens. The method parameters are the same as the old spi_xfer() with
-the addition of a 'struct udevice' so conversion is pretty easy. Start
-by copying the contents of spi_xfer() to your new xfer() method and proceed
-from there.
-
-If (flags & SPI_XFER_BEGIN) is non-zero then xfer() normally calls an
-activate function, something like this:
-
-.. code-block:: c
-
-       void spi_cs_activate(struct spi_slave *slave)
-       {
-               struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
-
-               /* If it's too soon to do another transaction, wait */
-               if (spi_slave->bus->deactivate_delay_us &&
-                   spi_slave->last_transaction_us) {
-                       ulong delay_us;         /* The delay completed so far */
-                       delay_us = timer_get_us() - spi_slave->last_transaction_us;
-                       if (delay_us < spi_slave->bus->deactivate_delay_us)
-                               udelay(spi_slave->bus->deactivate_delay_us - delay_us);
-               }
-
-               clrbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
-               debug("Activate CS, bus %d\n", spi_slave->slave.bus);
-               spi_slave->skip_preamble = spi_slave->mode & SPI_PREAMBLE;
-       }
-
-The new version looks like this:
-
-.. code-block:: c
-
-       static void spi_cs_activate(struct udevice *dev)
-       {
-               struct udevice *bus = dev->parent;
-               struct exynos_spi_plat *pdata = dev_get_plat(bus);
-               struct exynos_spi_priv *priv = dev_get_priv(bus);
-
-               /* If it's too soon to do another transaction, wait */
-               if (pdata->deactivate_delay_us &&
-                   priv->last_transaction_us) {
-                       ulong delay_us;         /* The delay completed so far */
-                       delay_us = timer_get_us() - priv->last_transaction_us;
-                       if (delay_us < pdata->deactivate_delay_us)
-                               udelay(pdata->deactivate_delay_us - delay_us);
-               }
-
-               clrbits_le32(&priv->regs->cs_reg, SPI_SLAVE_SIG_INACT);
-               debug("Activate CS, bus '%s'\n", bus->name);
-               priv->skip_preamble = priv->mode & SPI_PREAMBLE;
-       }
-
-All we have really done here is change the pointers and print the device name
-instead of the bus number. Other local static functions can be treated in
-the same way.
-
-
-Set up the per-child data and child pre-probe function
-------------------------------------------------------
-
-To minimise the pain and complexity of the SPI subsystem while the driver
-model change-over is in place, struct spi_slave is used to reference a
-SPI bus slave, even though that slave is actually a struct udevice. In fact
-struct spi_slave is the device's child data. We need to make sure this space
-is available. It is possible to allocate more space that struct spi_slave
-needs, but this is the minimum.
-
-.. code-block:: c
-
-       U_BOOT_DRIVER(exynos_spi) = {
-       ...
-               .per_child_auto = sizeof(struct spi_slave),
-       }
-
-
-Optional: Set up cs_info() if you want it
------------------------------------------
-
-Sometimes it is useful to know whether a SPI chip select is valid, but this
-is not obvious from outside the driver. In this case you can provide a
-method for cs_info() to deal with this. If you don't provide it, then the
-device tree will be used to determine what chip selects are valid.
-
-Return -EINVAL if the supplied chip select is invalid, or 0 if it is valid.
-If you don't provide the cs_info() method, 0 is assumed for all chip selects
-that do not appear in the device tree.
-
-
-Test it
--------
-
-Now that you have the code written and it compiles, try testing it using
-the 'sf test' command. You may need to enable CONFIG_CMD_SF_TEST for your
-board.
-
-
-Prepare patches and send them to the mailing lists
---------------------------------------------------
-
-You can use 'tools/patman/patman' to prepare, check and send patches for
-your work. See tools/patman/README for details.
-
-A little note about SPI uclass features
----------------------------------------
-
-The SPI uclass keeps some information about each device 'dev' on the bus:
-
-   struct dm_spi_slave_plat:
-     This is device_get_parent_plat(dev).
-     This is where the chip select number is stored, along with
-     the default bus speed and mode. It is automatically read
-     from the device tree in spi_child_post_bind(). It must not
-     be changed at run-time after being set up because platform
-     data is supposed to be immutable at run-time.
-   struct spi_slave:
-     This is device_get_parentdata(dev).
-     Already mentioned above. It holds run-time information about
-     the device.
-
-There are also some SPI uclass methods that get called behind the scenes:
-
-   spi_post_bind():
-     Called when a new bus is bound.
-     This scans the device tree for devices on the bus, and binds
-     each one. This in turn causes spi_child_post_bind() to be
-     called for each, which reads the device tree information
-     into the parent (per-child) platform data.
-   spi_child_post_bind():
-     Called when a new child is bound.
-     As mentioned above this reads the device tree information
-     into the per-child platform data
-   spi_child_pre_probe():
-     Called before a new child is probed.
-     This sets up the mode and speed in struct spi_slave by
-     copying it from the parent's platform data for this child.
-     It also sets the 'dev' pointer, needed to permit passing
-     'struct spi_slave' around the place without needing a
-     separate 'struct udevice' pointer.
-
-The above housekeeping makes it easier to write your SPI driver.
diff --git a/doc/driver-model/usb-info.rst b/doc/driver-model/usb-info.rst
deleted file mode 100644 (file)
index 24d1e81..0000000
+++ /dev/null
@@ -1,423 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0+
-
-How USB works with driver model
-===============================
-
-Introduction
-------------
-
-Driver model USB support makes use of existing features but changes how
-drivers are found. This document provides some information intended to help
-understand how things work with USB in U-Boot when driver model is enabled.
-
-
-Enabling driver model for USB
------------------------------
-
-A new CONFIG_DM_USB option is provided to enable driver model for USB. This
-causes the USB uclass to be included, and drops the equivalent code in
-usb.c. In particular the usb_init() function is then implemented by the
-uclass.
-
-
-Support for EHCI and XHCI
--------------------------
-
-So far OHCI is not supported. Both EHCI and XHCI drivers should be declared
-as drivers in the USB uclass. For example:
-
-.. code-block:: c
-
-       static const struct udevice_id ehci_usb_ids[] = {
-               { .compatible = "nvidia,tegra20-ehci", .data = USB_CTLR_T20 },
-               { .compatible = "nvidia,tegra30-ehci", .data = USB_CTLR_T30 },
-               { .compatible = "nvidia,tegra114-ehci", .data = USB_CTLR_T114 },
-               { }
-       };
-
-       U_BOOT_DRIVER(usb_ehci) = {
-               .name   = "ehci_tegra",
-               .id     = UCLASS_USB,
-               .of_match = ehci_usb_ids,
-               .of_to_plat = ehci_usb_of_to_plat,
-               .probe = tegra_ehci_usb_probe,
-               .remove = tegra_ehci_usb_remove,
-               .ops    = &ehci_usb_ops,
-               .plat_auto = sizeof(struct usb_plat),
-               .priv_auto = sizeof(struct fdt_usb),
-               .flags  = DM_FLAG_ALLOC_PRIV_DMA,
-       };
-
-Here ehci_usb_ids is used to list the controllers that the driver supports.
-Each has its own data value. Controllers must be in the UCLASS_USB uclass.
-
-The of_to_plat() method allows the controller driver to grab any
-necessary settings from the device tree.
-
-The ops here are ehci_usb_ops. All EHCI drivers will use these same ops in
-most cases, since they are all EHCI-compatible. For EHCI there are also some
-special operations that can be overridden when calling ehci_register().
-
-The driver can use priv_auto to set the size of its private data.
-This can hold run-time information needed by the driver for operation. It
-exists when the device is probed (not when it is bound) and is removed when
-the driver is removed.
-
-Note that usb_plat is currently only used to deal with setting up a bus
-in USB device mode (OTG operation). It can be omitted if that is not
-supported.
-
-The driver's probe() method should do the basic controller init and then
-call ehci_register() to register itself as an EHCI device. It should call
-ehci_deregister() in the remove() method. Registering a new EHCI device
-does not by itself cause the bus to be scanned.
-
-The old ehci_hcd_init() function is no-longer used. Nor is it necessary to
-set up the USB controllers from board init code. When 'usb start' is used,
-each controller will be probed and its bus scanned.
-
-XHCI works in a similar way.
-
-
-Data structures
----------------
-
-The following primary data structures are in use:
-
-- struct usb_device:
-       This holds information about a device on the bus. All devices have
-       this structure, even the root hub. The controller itself does not
-       have this structure. You can access it for a device 'dev' with
-       dev_get_parent_priv(dev). It matches the old structure except that the
-       parent and child information is not present (since driver model
-       handles that). Once the device is set up, you can find the device
-       descriptor and current configuration descriptor in this structure.
-
-- struct usb_plat:
-       This holds platform data for a controller. So far this is only used
-       as a work-around for controllers which can act as USB devices in OTG
-       mode, since the gadget framework does not use driver model.
-
-- struct usb_dev_plat:
-       This holds platform data for a device. You can access it for a
-       device 'dev' with dev_get_parent_plat(dev). It holds the device
-       address and speed - anything that can be determined before the device
-       driver is actually set up. When probing the bus this structure is
-       used to provide essential information to the device driver.
-
-- struct usb_bus_priv:
-       This is private information for each controller, maintained by the
-       controller uclass. It is mostly used to keep track of the next
-       device address to use.
-
-Of these, only struct usb_device was used prior to driver model.
-
-
-USB buses
----------
-
-Given a controller, you know the bus - it is the one attached to the
-controller. Each controller handles exactly one bus. Every controller has a
-root hub attached to it. This hub, which is itself a USB device, can provide
-one or more 'ports' to which additional devices can be attached. It is
-possible to power up a hub and find out which of its ports have devices
-attached.
-
-Devices are given addresses starting at 1. The root hub is always address 1,
-and from there the devices are numbered in sequence. The USB uclass takes
-care of this numbering automatically during enumeration.
-
-USB devices are enumerated by finding a device on a particular hub, and
-setting its address to the next available address. The USB bus stretches out
-in a tree structure, potentially with multiple hubs each with several ports
-and perhaps other hubs. Some hubs will have their own power since otherwise
-the 5V 500mA power supplied by the controller will not be sufficient to run
-very many devices.
-
-Enumeration in U-Boot takes a long time since devices are probed one at a
-time, and each is given sufficient time to wake up and announce itself. The
-timeouts are set for the slowest device.
-
-Up to 127 devices can be on each bus. USB has four bus speeds: low
-(1.5Mbps), full (12Mbps), high (480Mbps) which is only available with USB2
-and newer (EHCI), and super (5Gbps) which is only available with USB3 and
-newer (XHCI). If you connect a super-speed device to a high-speed hub, you
-will only get high-speed.
-
-
-USB operations
---------------
-
-As before driver model, messages can be sent using submit_bulk_msg() and the
-like. These are now implemented by the USB uclass and route through the
-controller drivers. Note that messages are not sent to the driver of the
-device itself - i.e. they don't pass down the stack to the controller.
-U-Boot simply finds the controller to which the device is attached, and sends
-the message there with an appropriate 'pipe' value so it can be addressed
-properly. Having said that, the USB device which should receive the message
-is passed in to the driver methods, for use by sandbox. This design decision
-is open for review and the code impact of changing it is small since the
-methods are typically implemented by the EHCI and XHCI stacks.
-
-Controller drivers (in UCLASS_USB) themselves provide methods for sending
-each message type. For XHCI an additional alloc_device() method is provided
-since XHCI needs to allocate a device context before it can even read the
-device's descriptor.
-
-These methods use a 'pipe' which is a collection of bit fields used to
-describe the type of message, direction of transfer and the intended
-recipient (device number).
-
-
-USB Devices
------------
-
-USB devices are found using a simple algorithm which works through the
-available hubs in a depth-first search. Devices can be in any uclass, but
-are attached to a parent hub (or controller in the case of the root hub) and
-so have parent data attached to them (this is struct usb_device).
-
-By the time the device's probe() method is called, it is enumerated and is
-ready to talk to the host.
-
-The enumeration process needs to work out which driver to attach to each USB
-device. It does this by examining the device class, interface class, vendor
-ID, product ID, etc. See struct usb_driver_entry for how drivers are matched
-with USB devices - you can use the USB_DEVICE() macro to declare a USB
-driver. For example, usb_storage.c defines a USB_DEVICE() to handle storage
-devices, and it will be used for all USB devices which match.
-
-
-
-Technical details on enumeration flow
--------------------------------------
-
-It is useful to understand precisely how a USB bus is enumerating to avoid
-confusion when dealing with USB devices.
-
-Device initialisation happens roughly like this:
-
-- At some point the 'usb start' command is run
-- This calls usb_init() which works through each controller in turn
-- The controller is probed(). This does no enumeration.
-- Then usb_scan_bus() is called. This calls usb_scan_device() to scan the
-  (only) device that is attached to the controller - a root hub
-- usb_scan_device() sets up a fake struct usb_device and calls
-  usb_setup_device(), passing the port number to be scanned, in this case
-  port 0
-- usb_setup_device() first calls usb_prepare_device() to set the device
-  address, then usb_select_config() to select the first configuration
-- at this point the device is enumerated but we do not have a real struct
-  udevice for it. But we do have the descriptor in struct usb_device so we can
-  use this to figure out what driver to use
-- back in usb_scan_device(), we call usb_find_child() to try to find an
-  existing device which matches the one we just found on the bus. This can
-  happen if the device is mentioned in the device tree, or if we previously
-  scanned the bus and so the device was created before
-- if usb_find_child() does not find an existing device, we call
-  usb_find_and_bind_driver() which tries to bind one
-- usb_find_and_bind_driver() searches all available USB drivers (declared
-  with USB_DEVICE()). If it finds a match it binds that driver to create a
-  new device.
-- If it does not, it binds a generic driver. A generic driver is good enough
-  to allow access to the device (sending it packets, etc.) but all
-  functionality will need to be implemented outside the driver model.
-- in any case, when usb_find_child() and/or usb_find_and_bind_driver() are
-  done, we have a device with the correct uclass. At this point we want to
-  probe the device
-- first we store basic information about the new device (address, port,
-  speed) in its parent platform data. We cannot store it its private data
-  since that will not exist until the device is probed.
-- then we call device_probe() which probes the device
-- the first probe step is actually the USB controller's (or USB hubs's)
-  child_pre_probe() method. This gets called before anything else and is
-  intended to set up a child device ready to be used with its parent bus. For
-  USB this calls usb_child_pre_probe() which grabs the information that was
-  stored in the parent platform data and stores it in the parent private data
-  (which is struct usb_device, a real one this time). It then calls
-  usb_select_config() again to make sure that everything about the device is
-  set up
-- note that we have called usb_select_config() twice. This is inefficient
-  but the alternative is to store additional information in the platform data.
-  The time taken is minimal and this way is simpler
-- at this point the device is set up and ready for use so far as the USB
-  subsystem is concerned
-- the device's probe() method is then called. It can send messages and do
-  whatever else it wants to make the device work.
-
-Note that the first device is always a root hub, and this must be scanned to
-find any devices. The above steps will have created a hub (UCLASS_USB_HUB),
-given it address 1 and set the configuration.
-
-For hubs, the hub uclass has a post_probe() method. This means that after
-any hub is probed, the uclass gets to do some processing. In this case
-usb_hub_post_probe() is called, and the following steps take place:
-
-- usb_hub_post_probe() calls usb_hub_scan() to scan the hub, which in turn
-  calls usb_hub_configure()
-- hub power is enabled
-- we loop through each port on the hub, performing the same steps for each
-- first, check if there is a device present. This happens in
-  usb_hub_port_connect_change(). If so, then usb_scan_device() is called to
-  scan the device, passing the appropriate port number.
-- you will recognise usb_scan_device() from the steps above. It sets up the
-  device ready for use. If it is a hub, it will scan that hub before it
-  continues here (recursively, depth-first)
-- once all hub ports are scanned in this way, the hub is ready for use and
-  all of its downstream devices also
-- additional controllers are scanned in the same way
-
-The above method has some nice properties:
-
-- the bus enumeration happens by virtue of driver model's natural device flow
-- most logic is in the USB controller and hub uclasses; the actual device
-  drivers do not need to know they are on a USB bus, at least so far as
-  enumeration goes
-- hub scanning happens automatically after a hub is probed
-
-
-Hubs
-----
-
-USB hubs are scanned as in the section above. While hubs have their own
-uclass, they share some common elements with controllers:
-
-- they both attach private data to their children (struct usb_device,
-  accessible for a child with dev_get_parent_priv(child))
-- they both use usb_child_pre_probe() to set up their children as proper USB
-  devices
-
-
-Example - Mass Storage
-----------------------
-
-As an example of a USB device driver, see usb_storage.c. It uses its own
-uclass and declares itself as follows:
-
-.. code-block:: c
-
-       U_BOOT_DRIVER(usb_mass_storage) = {
-               .name   = "usb_mass_storage",
-               .id     = UCLASS_MASS_STORAGE,
-               .of_match = usb_mass_storage_ids,
-               .probe = usb_mass_storage_probe,
-       };
-
-       static const struct usb_device_id mass_storage_id_table[] = {
-               { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
-                 .bInterfaceClass = USB_CLASS_MASS_STORAGE},
-               { }     /* Terminating entry */
-       };
-
-       USB_DEVICE(usb_mass_storage, mass_storage_id_table);
-
-The USB_DEVICE() macro attaches the given table of matching information to
-the given driver. Note that the driver is declared in U_BOOT_DRIVER() as
-'usb_mass_storage' and this must match the first parameter of USB_DEVICE.
-
-When usb_find_and_bind_driver() is called on a USB device with the
-bInterfaceClass value of USB_CLASS_MASS_STORAGE, it will automatically find
-this driver and use it.
-
-
-Counter-example: USB Ethernet
------------------------------
-
-As an example of the old way of doing things, see usb_ether.c. When the bus
-is scanned, all Ethernet devices will be created as generic USB devices (in
-uclass UCLASS_USB_DEV_GENERIC). Then, when the scan is completed,
-usb_host_eth_scan() will be called. This looks through all the devices on
-each bus and manually figures out which are Ethernet devices in the ways of
-yore.
-
-In fact, usb_ether should be moved to driver model. Each USB Ethernet driver
-(e.g drivers/usb/eth/asix.c) should include a USB_DEVICE() declaration, so
-that it will be found as part of normal USB enumeration. Then, instead of a
-generic USB driver, a real (driver-model-aware) driver will be used. Since
-Ethernet now supports driver model, this should be fairly easy to achieve,
-and then usb_ether.c and the usb_host_eth_scan() will melt away.
-
-
-Sandbox
--------
-
-All driver model uclasses must have tests and USB is no exception. To
-achieve this, a sandbox USB controller is provided. This can make use of
-emulation drivers which pretend to be USB devices. Emulations are provided
-for a hub and a flash stick. These are enough to create a pretend USB bus
-(defined by the sandbox device tree sandbox.dts) which can be scanned and
-used.
-
-Tests in test/dm/usb.c make use of this feature. It allows much of the USB
-stack to be tested without real hardware being needed.
-
-Here is an example device tree fragment:
-
-.. code-block:: none
-
-       usb@1 {
-               compatible = "sandbox,usb";
-               hub {
-                       compatible = "usb-hub";
-                       usb,device-class = <USB_CLASS_HUB>;
-                       hub-emul {
-                               compatible = "sandbox,usb-hub";
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               flash-stick {
-                                       reg = <0>;
-                                       compatible = "sandbox,usb-flash";
-                                       sandbox,filepath = "flash.bin";
-                               };
-                       };
-               };
-       };
-
-This defines a single controller, containing a root hub (which is required).
-The hub is emulated by a hub emulator, and the emulated hub has a single
-flash stick to emulate on one of its ports.
-
-When 'usb start' is used, the following 'dm tree' output will be available::
-
-   usb         [ + ]    `-- usb@1
-   usb_hub     [ + ]        `-- hub
-   usb_emul    [ + ]            |-- hub-emul
-   usb_emul    [ + ]            |   `-- flash-stick
-   usb_mass_st [ + ]            `-- usb_mass_storage
-
-
-This may look confusing. Most of it mirrors the device tree, but the
-'usb_mass_storage' device is not in the device tree. This is created by
-usb_find_and_bind_driver() based on the USB_DRIVER in usb_storage.c. While
-'flash-stick' is the emulation device, 'usb_mass_storage' is the real U-Boot
-USB device driver that talks to it.
-
-
-Future work
------------
-
-It is pretty uncommon to have a large USB bus with lots of hubs on an
-embedded system. In fact anything other than a root hub is uncommon. Still
-it would be possible to speed up enumeration in two ways:
-
-- breadth-first search would allow devices to be reset and probed in
-  parallel to some extent
-- enumeration could be lazy, in the sense that we could enumerate just the
-  root hub at first, then only progress to the next 'level' when a device is
-  used that we cannot find. This could be made easier if the devices were
-  statically declared in the device tree (which is acceptable for production
-  boards where the same, known, things are on each bus).
-
-But in common cases the current algorithm is sufficient.
-
-Other things that need doing:
-- Convert usb_ether to use driver model as described above
-- Test that keyboards work (and convert to driver model)
-- Move the USB gadget framework to driver model
-- Implement OHCI in driver model
-- Implement USB PHYs in driver model
-- Work out a clever way to provide lazy init for USB devices
-
-
-.. Simon Glass <[email protected]>
-.. 23-Mar-15
index 366963813ace21bd65e4f04c668cd0c5ec8d0092..f7aada966b02d4031b59b430eab095bba195b914 100644 (file)
@@ -38,17 +38,6 @@ want to contribute to U-Boot.
 
    develop/index
 
-Driver-Model documentation
---------------------------
-
-The following holds information on the U-Boot device driver framework:
-driver-model, including the design details of itself and several driver
-subsystems.
-
-.. toctree::
-   :maxdepth: 2
-
-   driver-model/index
 
 U-Boot API documentation
 ------------------------
This page took 0.28009 seconds and 4 git commands to generate.