Driver Model in U-Boot
Introduction
Driver model in U-Boot is to provide a consistent model for U-Boot drivers and the platform data / device tree information used by the drivers to instantiate devices.
The model is arranged by three concepts:
- 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.
- 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 peripheral port or peripheral, created from some platform-specific information bound to a driver.
Configure U-Boot
To use U-Boot with driver model and device tree supported, you should to do,
- First enable the driver model support, then enable the drivers after enabling the driver model for the corresponding sub-system.
- Provide the run-time configuration of U-Boot via a flat device tree (fdt), and enables the FDT library as well.
Note: In the following configuration, we take sama5d2 Xplained boards for example.
Firstly, use your default kernel configuration:
make ARCH=arm sama5d2_xplained_spiflash_defconfig
You can configure the options by using U-Boot configuration interface.
make ARCH=arm menuconfig
First, you enable the device tree support by enabling the symbols
CONFIG_OF_CONTROL
You should select the separate DTB for DT control (
CONFIG_OF_SEPARATE
), which is recommended for the production devices.
Then specify the default filename of the device tree source
CONFIG_DEFAULT_DEVICE_TREE="at91-sama5d2_xplained"
Device Tree Control --->
[*] Run-time configuration via Device Tree
[*] Enable run-time configuration via Device Tree in SPL
Provider of DTB for DT control (Separate DTB for DT control) --->
(at91-sama5d2_xplained) Default Device Tree for DT control
(pinctrl-0 pinctrl-names interrupt-parent) List of device tree properties to drop for SPL
Of course, the FDT library is required.
Make the FDT library available by enabling the symbols
CONFIG_OF_LIBFDT
,
CONFIG_SPL_OF_LIBFDT
.
Library routines --->
[*] Enable the FDT library
[ ] Enable the FDT library overlay support
[*] Enable the FDT library for SPL
The FDT library provides functions for accessing binary device tree images in memory, such as adding and removing nodes and properties, scanning through the tree and finding particular compatible nodes.
Enable the Driver Model
First of all, you can enable the driver model by enabling the symbol
CONFIG_DM
,
CONFIG_SPL_DM
.
Device Drivers --->
Generic Driver Options --->
[*] Enable Driver Model
[*] Enable Driver Model for SPL
[*] Enable warnings in driver model
[*] Support device removal
[*] Support stdio registration
[*] Support numbered aliases in device tree
Enable the Individual Driver
Before enabling the driver with driver model support, you should enable the common clock framework and pinctrl framework.
Support the Clock Framework
Enable the clock framework by enabling the symbols
CONFIG_CLK
,
CONFIG_SPL_CLK
,
CONFIG_CLK_AT91
.
Device Drivers --->
Clock --->
[*] Enable clock driver support
[*] Enable clock support in SPL
[*] AT91 clock drivers
[*] Support UTMI PLL Clock
[*] Support H32MX 32-bit Matrix Clock
[*] Support Generic Clock
Support the Pinctrl Framework
Enable the pinctrl framework by enabling the symbols,
CONFIG_PINCTRL
,
CONFIG_PINCTRL_AT91PIO4
.
Device Drivers --->
Pin controllers --->
[*] Support pin controllers
[*] Support full pin controllers
[*] Support generic pin controllers
[*] Support pin multiplexing controllers
[*] AT91 PIO4 pinctrl driver
Enable the Individual Driver with Driver Model
To enable the driver with driver model support, firstly, enable the driver model for the corresponding sub-system, i.e. enabling the symbol like
CONFIG_DM_<subsys>
.
Take the Atmel SPI driver for example to configure.
Enable the Atmel SPI driver with driver model by enabling the symbols,
CONFIG_DM_SPI
,
CONFIG_ATMEL_SPI
.
Device Drivers --->
SPI Support --->
[*] Enable Driver Model for SPI drivers
[*] Atmel SPI driver
Build U-Boot
After the configuration is done, built U-Boot with driver model and fdt supported in two ways,
1. Build with the default DTS which is defined from CONFIG_DEFAULT_DEVICE_TREE.
make ARCH=arm CROSS_COMPILE=<path_to_cross-compiler/cross-compiler-prefix->
2. Build with the user specified dts file.
make ARCH=arm CROSS_COMPILE=<path_to_cross-compiler/cross-compiler-prefix-> DEVICE_TREE=<dts-file-name>
path_to_cross-compiler is only needed if the path of the cross-compiler is not in your PATH.
cross-compiler-prefix- looks like
arm-linux- ,
arm-elf- ,
arm-linux-gnueabihf- , or
arm-none-linux-gnueabi- .
dts-file-name is the filename of the device tree source for the board, as
at91-sama5d2_xplained
After the built is done, you can see the generated files like,
$ ls -l u-boot*.bin
-rw-rw-r-- 1 wyang wyang 381857 Nov 3 15:45 u-boot.bin
-rw-rw-r-- 1 wyang wyang 381857 Nov 3 15:45 u-boot-dtb.bin
-rwxrwxr-x 1 wyang wyang 369264 Nov 3 15:45 u-boot-nodtb.bin
$ ls -l u-boot*.dtb
-rw-rw-r-- 1 wyang wyang 12593 Nov 3 15:45 u-boot.dtb
u-boot.dtb is the compact binary file produced by
dtc tool from the device tree source file.
u-boot-nodtb.bin is the raw binary file of U-Boot without DT stuff.
u-boot-dtb.bin is the binary file generated by joining the above two file.
cat u-boot-nodtb.bin u-boot.dtb > u-boot-dtb.bin
u-boot.bin is identical to
u-boot-dtb.bin.
u-boot.bin single file is pretty different as the one without the DM/DT but it's
use is the same.
Nothing needs to change for the first bootloader.
U-Boot dm Command usage
Flash the
u-boot.bin image to the target board.
After U-Boot boot up successfully, you can check the driver model tree using the
dm command. It is very helpful for the developer to check the device binding.
=> dm help
dm - Driver model low level access
Usage:
dm tree Dump driver model tree ('*' = activated)
dm uclass Dump list of instances for each uclass
dm devres Dump list of device resources for each device
=> dm tree
Class Probed Name
----------------------------------------
root [ + ] root_driver
video [ + ] |-- hlcdc@f0000000
vidconsole0 [ + ] | `-- hlcdc@f0000000.vidconsole0
simple_bus [ + ] `-- ahb
usb [ ] |-- ehci@00500000
mmc [ + ] |-- sdio-host@a0000000
mmc [ + ] |-- sdio-host@b0000000
simple_bus [ + ] `-- apb
clk [ + ] |-- pmc@f0014000
clk [ + ] | |-- mainck
clk [ + ] | |-- pllack
clk [ + ] | |-- utmick
clk [ + ] | |-- masterck
clk [ + ] | |-- h32mxck
clk [ ] | |-- systemck
clk [ ] | | |-- ddrck
clk [ ] | | |-- lcdck
clk [ ] | | |-- uhpck
clk [ ] | | |-- udpck
clk [ ] | | |-- pck0
clk [ ] | | |-- pck1
clk [ ] | | |-- pck2
clk [ ] | | `-- iscck
clk [ + ] | |-- periph32ck
clk [ + ] | | |-- macb0_clk
clk [ ] | | |-- tdes_clk
clk [ ] | | |-- matrix1_clk
clk [ ] | | |-- hsmc_clk
clk [ + ] | | |-- pioA_clk
clk [ ] | | |-- flx0_clk
clk [ ] | | |-- flx1_clk
clk [ ] | | |-- flx2_clk
clk [ ] | | |-- flx3_clk
clk [ ] | | |-- flx4_clk
clk [ ] | | |-- uart0_clk
clk [ ] | | |-- uart1_clk
clk [ ] | | |-- uart2_clk
clk [ ] | | |-- uart3_clk
clk [ ] | | |-- uart4_clk
clk [ ] | | |-- twi0_clk
clk [ + ] | | |-- twi1_clk
clk [ + ] | | |-- spi0_clk
clk [ ] | | |-- spi1_clk
clk [ ] | | |-- tcb0_clk
clk [ ] | | |-- tcb1_clk
clk [ ] | | |-- pwm_clk
clk [ ] | | |-- adc_clk
clk [ ] | | |-- uhphs_clk
clk [ ] | | |-- udphs_clk
clk [ ] | | |-- ssc0_clk
clk [ ] | | |-- ssc1_clk
clk [ ] | | |-- trng_clk
clk [ ] | | |-- pdmic_clk
clk [ ] | | |-- i2s0_clk
clk [ ] | | |-- i2s1_clk
clk [ ] | | |-- can0_clk
clk [ ] | | |-- can1_clk
clk [ ] | | `-- classd_clk
clk [ + ] | |-- periph64ck
clk [ ] | | |-- dma0_clk
clk [ ] | | |-- dma1_clk
clk [ ] | | |-- aes_clk
clk [ ] | | |-- aesb_clk
clk [ ] | | |-- sha_clk
clk [ ] | | |-- mpddr_clk
clk [ ] | | |-- matrix0_clk
clk [ + ] | | |-- sdmmc0_hclk
clk [ + ] | | |-- sdmmc1_hclk
clk [ + ] | | |-- lcdc_clk
clk [ ] | | |-- isc_clk
clk [ ] | | |-- qspi0_clk
clk [ ] | | `-- qspi1_clk
clk [ + ] | `-- gck
clk [ + ] | |-- sdmmc0_gclk
clk [ + ] | |-- sdmmc1_gclk
clk [ ] | |-- tcb0_gclk
clk [ ] | |-- tcb1_gclk
clk [ ] | |-- pwm_gclk
clk [ ] | |-- pdmic_gclk
clk [ ] | |-- i2s0_gclk
clk [ ] | |-- i2s1_gclk
clk [ ] | |-- can0_gclk
clk [ ] | |-- can1_gclk
clk [ ] | `-- classd_gclk
spi [ + ] |-- spi@f8000000
spi_flash [ ] | `-- spi_flash@0
eth [ + ] |-- ethernet@f8008000
serial [ + ] |-- serial@f8020000
clk [ ] |-- sckc@f8048050
clk [ ] | `-- slowck
i2c [ + ] |-- i2c@fc028000
i2c_generic [ + ] | `-- generic_5c
gpio [ + ] `-- gpio@fc038000
pinctrl [ + ] `-- pinctrl
pinconfig [ + ] |-- i2c1_default
pinconfig [ + ] |-- pinctrl_lcd_base
pinconfig [ + ] |-- pinctrl_lcd_pwm
pinconfig [ + ] |-- pinctrl_lcd_rgb666
pinconfig [ + ] |-- macb0_phy_irq
pinconfig [ + ] |-- macb0_rmii
pinconfig [ ] |-- qspi0_default
pinconfig [ + ] |-- sdmmc0_cmd_dat_default
pinconfig [ + ] |-- sdmmc0_ck_cd_default
pinconfig [ + ] |-- sdmmc1_cmd_dat_default
pinconfig [ + ] |-- sdmmc1_ck_cd_default
pinconfig [ + ] |-- spi0_default
pinconfig [ + ] |-- uart1_default
pinconfig [ ] |-- usb_default
pinconfig [ ] `-- usba_vbus
=> dm uclass
uclass 0: root
- * root_driver @ 3f981028, seq 0, (req -1)
uclass 9: simple_bus
- * ahb @ 3f981138, seq 0, (req -1)
- * apb @ 3f981308, seq 1, (req -1)
uclass 11: clk
- * pmc@f0014000 @ 3f981390, seq 0, (req -1)
- * mainck @ 3f9813e8, seq 7, (req -1)
- * pllack @ 3f981450, seq 8, (req -1)
- * utmick @ 3f9814b8, seq 9, (req -1)
- * masterck @ 3f981520, seq 10, (req -1)
- * h32mxck @ 3f981578, seq 14, (req -1)
- systemck @ 3f9815e0
- ddrck @ 3f981648
- lcdck @ 3f9816a0
- uhpck @ 3f9816f8
- udpck @ 3f981750
- pck0 @ 3f9817a8
- pck1 @ 3f981800
- pck2 @ 3f981858
- iscck @ 3f9818b0
- * periph32ck @ 3f981908, seq 1, (req -1)
- * macb0_clk @ 3f981970, seq 17, (req -1)
- tdes_clk @ 3f9819c8
- matrix1_clk @ 3f981a20
- hsmc_clk @ 3f981a78
- * pioA_clk @ 3f981ad0, seq 2, (req -1)
- flx0_clk @ 3f981b28
- flx1_clk @ 3f981b80
- flx2_clk @ 3f981bd8
- flx3_clk @ 3f981c30
- flx4_clk @ 3f981c88
- uart0_clk @ 3f981ce0
- uart1_clk @ 3f981d38
- uart2_clk @ 3f981d90
- uart3_clk @ 3f981de8
- uart4_clk @ 3f981e40
- twi0_clk @ 3f981e98
- * twi1_clk @ 3f981ef0, seq 16, (req -1)
- * spi0_clk @ 3f981f48, seq 13, (req -1)
- spi1_clk @ 3f981fa0
- tcb0_clk @ 3f981ff8
- tcb1_clk @ 3f982050
- pwm_clk @ 3f9820a8
- adc_clk @ 3f982100
- uhphs_clk @ 3f982158
- udphs_clk @ 3f9821b0
- ssc0_clk @ 3f982208
- ssc1_clk @ 3f982260
- trng_clk @ 3f9822b8
- pdmic_clk @ 3f982310
- i2s0_clk @ 3f982368
- i2s1_clk @ 3f9823c0
- can0_clk @ 3f982418
- can1_clk @ 3f982470
- classd_clk @ 3f9824c8
- * periph64ck @ 3f982520, seq 3, (req -1)
- dma0_clk @ 3f982588
- dma1_clk @ 3f9825e0
- aes_clk @ 3f982638
- aesb_clk @ 3f982690
- sha_clk @ 3f9826e8
- mpddr_clk @ 3f982740
- matrix0_clk @ 3f982798
- * sdmmc0_hclk @ 3f9827f0, seq 4, (req -1)
- * sdmmc1_hclk @ 3f982848, seq 11, (req -1)
- * lcdc_clk @ 3f9828a0, seq 15, (req -1)
- isc_clk @ 3f9828f8
- qspi0_clk @ 3f982950
- qspi1_clk @ 3f9829a8
- * gck @ 3f982a00, seq 5, (req -1)
- * sdmmc0_gclk @ 3f982a68, seq 6, (req -1)
- * sdmmc1_gclk @ 3f982ac0, seq 12, (req -1)
- tcb0_gclk @ 3f982b18
- tcb1_gclk @ 3f982b70
- pwm_gclk @ 3f982bc8
- pdmic_gclk @ 3f982c20
- i2s0_gclk @ 3f982c78
- i2s1_gclk @ 3f982cd0
- can0_gclk @ 3f982d28
- can1_gclk @ 3f982d80
- classd_gclk @ 3f982dd8
- sckc@f8048050 @ 3f983070
- slowck @ 3f9830c8
uclass 14: disk
uclass 18: eth
- * ethernet@f8008000 @ 3f982f78, seq 0, (req -1)
uclass 19: gpio
- * gpio@fc038000 @ 3f9831b8, seq 0, (req -1)
uclass 20: i2c
- * i2c@fc028000 @ 3f983140, seq 1, (req 1)
uclass 22: i2c_generic
- * generic_5c @ 3f984350, seq 0, (req -1)
uclass 28: usb_mass_storage
uclass 30: mmc
- * sdio-host@a0000000 @ 3f981258, seq 0, (req -1)
- * sdio-host@b0000000 @ 3f9812b0, seq 1, (req -1)
uclass 34: panel
uclass 35: backlight
uclass 39: pinctrl
- * pinctrl @ 3f983240, seq 0, (req -1)
uclass 40: pinconfig
- * i2c1_default @ 3f9832c8, seq 9, (req -1)
- * pinctrl_lcd_base @ 3f983320, seq 6, (req -1)
- * pinctrl_lcd_pwm @ 3f983378, seq 7, (req -1)
- * pinctrl_lcd_rgb666 @ 3f9833d0, seq 8, (req -1)
- * macb0_phy_irq @ 3f983428, seq 11, (req -1)
- * macb0_rmii @ 3f983480, seq 10, (req -1)
- qspi0_default @ 3f9834d8
- * sdmmc0_cmd_dat_default @ 3f983530, seq 1, (req -1)
- * sdmmc0_ck_cd_default @ 3f983588, seq 2, (req -1)
- * sdmmc1_cmd_dat_default @ 3f9835e0, seq 3, (req -1)
- * sdmmc1_ck_cd_default @ 3f983638, seq 4, (req -1)
- * spi0_default @ 3f983690, seq 5, (req -1)
- * uart1_default @ 3f9836e8, seq 0, (req -1)
- usb_default @ 3f983740
- usba_vbus @ 3f983798
uclass 44: regulator
uclass 48: serial
- * serial@f8020000 @ 3f983008, seq 0, (req -1)
uclass 49: spi
- * spi@f8000000 @ 3f982e50, seq 0, (req 0)
uclass 50: spi_flash
- * spi_flash@0 @ 3f982ed8, seq 0, (req -1)
uclass 51: spi_generic
uclass 56: usb
- ehci@00500000 @ 3f9811d0
uclass 57: usb_dev_generic
uclass 58: usb_hub
uclass 59: video
- * hlcdc@f0000000 @ 3f9810b0, seq 0, (req -1)
uclass 61: vidconsole0
- * hlcdc@f0000000.vidconsole0 @ 3f984088, seq 0, (req -1)
Reference Documents
- doc/driver-model/README
- doc/README.fdt-control
- U-Boot Driver Model
Other useful slides:
- Order at Last, The New U-Boot Driver Model Architecture by Simon Glass, ELEC 2015, Dublin.
- Driver Model in U-Boot by Simon Glass, U-Boot Mini-Summit 2014.