Driver model implementation, tests, demo and GPIO
Subsystems (4)
v3 cover Driver model implementation, tests, demo and GPIO
Note: If you are reviewing this code, but don't have a lot of time, please consider starting with the 'demo' driver (patch 'dm: Add a demonstration/example driver') since it clearly shows how devices and uclasses work. Much of this series consists of test code and plumbing, so is of less interest to driver authors.
This patch adds a driver model implementation. It is taken from the driver model code developed by:
Marek Vasut <[email protected]>
Pavel Herrmann <[email protected]>
Viktor K?iv?k <[email protected]>
Tomas Hlavacek <[email protected]>
Please see doc/driver-model/README.txt for details of how to run this and what to look for. So far the documentation in doc/driver-model has not been updated.
You can find a test version of the code used here in branch dm2 at:
http://git.denx.de/u-boot-x86.git
(Branch dm contains the original implementation)
Changes in v3:
- Add new patch to build a device tree file for sandbox
- Tidy up commenting of functions and structures
- Rename per_device_priv_size to per_device_auto_alloc_size, etc.
- Add a flag for tracking whether DM allocates/frees platform_data
- Add function/struct comments to tests
- Fix up demo command help
- Update demo driver to use device tree
- Update GPIO support to use new struct member names
- Tidy up comments/documentation in GPIO module
- Update sandbox GPIO header file comments
- Updated README.txt to cover changes since version 2
- Add new patch to move driver model documentation
Changes in v2:
- Removed pointer return values in favour of integer
- Use driver_bind() in dm_init() instead of writing new code
- Allow driver_bind() to support a NULL parent
- Add dm_warn() to warn about impending doom
- Standardise variable names (e.g. uclass instead of class)
- Remove relocation functions
- Add new header file for lists
- Add new util file to hold utility functions
- Allow a driver to bind to only one uclass
- Remove unneeded arguments to uclass_bind(), uclass_unbind()
- Rename struct device's 'bus' to 'parent'
- Rename data structures to hopefully be clearer
- Put platform_data definitions in their own header file
- Add U_BOOT_DEVICE to declare platform_data
- Add auto-probing feature for platform_data to avoid driver_bind() calls
- Add simple unit test functions
- Add test infrastructure for driver model
- Add integration tests for driver model
- Add device tree support in driver model
- Add automatic allocation of platform_data for FDT
- Add automatic allocation of priv data for devices
- Add automatic allocation of device-specific priv data for uclasses
- Add GPIO uclass and tests
- Add sandbox GPIO driver
- Update gpio command to use driver model
- Add tests for core code
- Add script to run tests
- Add a single include/dm.h to bring in driver model code
Pavel Herrmann (1):
dm: Add README for driver model
Simon Glass (15):
sandbox: Make map_to_sysmem() use a constant pointer
sandbox: Correct data sizes and printf() strings in fdtdec.c
sandbox: config: Don't use 64-bit physical memory
sandbox: Build a device tree file for sandbox
Add cmd_process_error() to report and process errors
sandbox: config: Enable driver model
dm: Add base driver model support
dm: Set up driver model after relocation
dm: Add basic tests
dm: Add a 'dm' command for testing
dm: Add a demonstration/example driver
dm: Add GPIO support and tests
sandbox: Convert GPIOs to use driver model
dm: Enable gpio command to support driver model
dm: Move old driver model documentation into an 'old-docs' directory
Makefile | 5 +
arch/sandbox/config.mk | 2 +
arch/sandbox/include/asm/gpio.h | 14 +-
arch/sandbox/include/asm/io.h | 2 +-
arch/sandbox/include/asm/types.h | 4 +-
board/sandbox/dts/sandbox.dts | 20 +
board/sandbox/sandbox/sandbox.c | 7 +-
common/Makefile | 1 +
common/board_r.c | 33 ++
common/cmd_demo.c | 115 +++++
common/cmd_gpio.c | 127 +++++-
common/command.c | 10 +
common/dm/Makefile | 43 ++
common/dm/device.c | 331 ++++++++++++++
common/dm/lists.c | 168 +++++++
common/dm/root.c | 115 +++++
common/dm/uclass.c | 298 ++++++++++++
common/dm/util.c | 50 ++
doc/driver-model/README.txt | 320 +++++++++++++
doc/driver-model/old-docs/README | 29 ++
doc/driver-model/{ => old-docs}/UDM-block.txt | 0
doc/driver-model/{ => old-docs}/UDM-cores.txt | 0
doc/driver-model/{ => old-docs}/UDM-design.txt | 0
doc/driver-model/{ => old-docs}/UDM-fpga.txt | 0
doc/driver-model/{ => old-docs}/UDM-gpio.txt | 0
doc/driver-model/{ => old-docs}/UDM-hwmon.txt | 0
doc/driver-model/{ => old-docs}/UDM-keyboard.txt | 0
doc/driver-model/{ => old-docs}/UDM-mmc.txt | 0
doc/driver-model/{ => old-docs}/UDM-net.txt | 0
doc/driver-model/{ => old-docs}/UDM-pci.txt | 0
doc/driver-model/{ => old-docs}/UDM-pcmcia.txt | 0
doc/driver-model/{ => old-docs}/UDM-power.txt | 0
doc/driver-model/{ => old-docs}/UDM-rtc.txt | 0
doc/driver-model/{ => old-docs}/UDM-serial.txt | 0
doc/driver-model/{ => old-docs}/UDM-spi.txt | 0
doc/driver-model/{ => old-docs}/UDM-stdio.txt | 0
doc/driver-model/{ => old-docs}/UDM-tpm.txt | 0
doc/driver-model/{ => old-docs}/UDM-twserial.txt | 0
doc/driver-model/{ => old-docs}/UDM-usb.txt | 0
doc/driver-model/{ => old-docs}/UDM-video.txt | 0
doc/driver-model/{ => old-docs}/UDM-watchdog.txt | 0
drivers/demo/Makefile | 44 ++
drivers/demo/demo-pdata.c | 60 +++
drivers/demo/demo-shape.c | 143 ++++++
drivers/demo/demo-simple.c | 61 +++
drivers/demo/demo-uclass.c | 73 +++
drivers/gpio/Makefile | 2 +
drivers/gpio/gpio-uclass.c | 279 ++++++++++++
drivers/gpio/sandbox.c | 210 +++++----
include/asm-generic/global_data.h | 8 +
include/asm-generic/gpio.h | 104 +++++
include/command.h | 9 +
include/common.h | 2 +-
include/configs/sandbox.h | 11 +-
include/dm-demo.h | 49 ++
include/dm.h | 27 ++
include/dm/device-internal.h | 100 ++++
include/dm/device.h | 149 ++++++
include/dm/lists.h | 52 +++
include/dm/platform_data.h | 35 ++
include/dm/root.h | 66 +++
include/dm/test.h | 180 ++++++++
include/dm/uclass-id.h | 41 ++
include/dm/uclass-internal.h | 98 ++++
include/dm/uclass.h | 155 +++++++
include/dm/ut.h | 108 +++++
include/dm/util.h | 42 ++
lib/fdtdec.c | 8 +-
test/dm/Makefile | 53 +++
test/dm/cmd_dm.c | 146 ++++++
test/dm/core.c | 557 +++++++++++++++++++++++
test/dm/gpio.c | 124 +++++
test/dm/test-driver.c | 159 +++++++
test/dm/test-fdt.c | 148 ++++++
test/dm/test-main.c | 120 +++++
test/dm/test-uclass.c | 117 +++++
test/dm/test.dts | 59 +++
test/dm/ut.c | 46 ++
78 files changed, 5229 insertions(+), 110 deletions(-)
create mode 100644 board/sandbox/dts/sandbox.dts
create mode 100644 common/cmd_demo.c
create mode 100644 common/dm/Makefile
create mode 100644 common/dm/device.c
create mode 100644 common/dm/lists.c
create mode 100644 common/dm/root.c
create mode 100644 common/dm/uclass.c
create mode 100644 common/dm/util.c
create mode 100644 doc/driver-model/README.txt
create mode 100644 doc/driver-model/old-docs/README
rename doc/driver-model/{ => old-docs}/UDM-block.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-cores.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-design.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-fpga.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-gpio.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-hwmon.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-keyboard.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-mmc.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-net.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-pci.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-pcmcia.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-power.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-rtc.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-serial.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-spi.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-stdio.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-tpm.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-twserial.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-usb.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-video.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-watchdog.txt (100%)
create mode 100644 drivers/demo/Makefile
create mode 100644 drivers/demo/demo-pdata.c
create mode 100644 drivers/demo/demo-shape.c
create mode 100644 drivers/demo/demo-simple.c
create mode 100644 drivers/demo/demo-uclass.c
create mode 100644 drivers/gpio/gpio-uclass.c
create mode 100644 include/dm-demo.h
create mode 100644 include/dm.h
create mode 100644 include/dm/device-internal.h
create mode 100644 include/dm/device.h
create mode 100644 include/dm/lists.h
create mode 100644 include/dm/platform_data.h
create mode 100644 include/dm/root.h
create mode 100644 include/dm/test.h
create mode 100644 include/dm/uclass-id.h
create mode 100644 include/dm/uclass-internal.h
create mode 100644 include/dm/uclass.h
create mode 100644 include/dm/ut.h
create mode 100644 include/dm/util.h
create mode 100644 test/dm/Makefile
create mode 100644 test/dm/cmd_dm.c
create mode 100644 test/dm/core.c
create mode 100644 test/dm/gpio.c
create mode 100644 test/dm/test-driver.c
create mode 100644 test/dm/test-fdt.c
create mode 100644 test/dm/test-main.c
create mode 100644 test/dm/test-uclass.c
create mode 100644 test/dm/test.dts
create mode 100644 test/dm/ut.cSignature · 1 line
1.8.3
PATCH v3 1/16 sandbox: Make map_to_sysmem() use a constant pointer
Very often a constant pointer is passed to this function, so we should declare this, since map_to_sysmem() does not change the pointer.
---
Changes in v3: None
Changes in v2: None
arch/sandbox/include/asm/io.h | 2 +- include/common.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
arch/sandbox/include/asm/io.h +1 -1
@@ -54,6 +54,6 @@ static inline void unmap_sysmem(const void *vaddr) }/* Map from a pointer to our RAM buffer */ -phys_addr_t map_to_sysmem (void *ptr); +phys_addr_t map_to_sysmem (const void *ptr);#endif
include/common.h +1 -1
@@ -926,7 +926,7 @@ static inline void unmap_sysmem(const void *vaddr) { } -static inline phys_addr_t map_to_sysmem (void *ptr) +static inline phys_addr_t map_to_sysmem (const void *ptr) {return (phys_addr_t )(uintptr_t )ptr; }
Signature · 1 line
1.8.3
PATCH v3 2/16 sandbox: Correct data sizes and printf() strings in fdtdec.c
In reply to Simon GlassThere are a few warnings in this file when building for sandbox. Addresses coming from the device tree need to be treated as ulong as elsewhere in U-Boot and we must use map_sysmem() to convert to a pointer when needed.
---
Changes in v3: None
Changes in v2: None
lib/fdtdec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
lib/fdtdec.c +4 -4
@@ -93,10 +93,10 @@ fdt_addr_t fdtdec_get_addr_size(const void *blob, int node, size = (fdt_size_t *)((char *)cell +sizeof (fdt_addr_t)); *sizep =fdt_size_to_cpu (*size); -debug ("addr=%p, size=%p\n" , (void *)addr, - (void *)*sizep); +debug ("addr=%08lx, size=%08x\n" , + (ulong )addr, *sizep); }else { -debug ("%p\n" , (void *)addr); +debug ("%08lx\n" , (ulong )addr); }return addr; }
@@ -618,7 +618,7 @@ int fdtdec_decode_region(const void *blob, int node,if (!cell || (len !=sizeof (fdt_addr_t) *2 ))return -1 ; - *ptrp = (void *)fdt_addr_to_cpu (*cell); + *ptrp =map_sysmem (fdt_addr_to_cpu (*cell), *size); *size =fdt_size_to_cpu (cell[1 ]);debug ("%s: size=%zx\n" , __func__, *size);return 0 ;
Signature · 1 line
1.8.3
PATCH v3 3/16 sandbox: config: Don't use 64-bit physical memory
In reply to Simon GlassSandbox uses an emulated memory map which is quite small. We don't need the CONFIG_PHYS_64BIT option since we can address memory with a 32-bit offset into our ram_buf.
Adjust the phys_addr_t and phys_size_t types accordingly.
---
Changes in v3: None
Changes in v2: None
arch/sandbox/include/asm/types.h | 4 ++-- include/configs/sandbox.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-)
arch/sandbox/include/asm/types.h +2 -2
@@ -64,8 +64,8 @@ typedef unsigned long long u64;#define BITS_PER_LONG CONFIG_SANDBOX_BITS_PER_LONGtypedef unsigned long dma_addr_t ; -typedef unsigned long phys_addr_t ; -typedef unsigned long phys_size_t ; +typedef u32 phys_addr_t ; +typedef u32 phys_size_t ;#endif /* __KERNEL__ */
include/configs/sandbox.h +0 -1
@@ -73,7 +73,6 @@#define CONFIG_SYS_LOAD_ADDR 0x00000000#define CONFIG_SYS_MEMTEST_START 0x00100000#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_MEMTEST_START + 0x1000) -#define CONFIG_PHYS_64BIT #define CONFIG_SYS_FDT_LOAD_ADDR 0x1000000/* Size of our emulated memory */
Signature · 1 line
1.8.3
PATCH v3 4/16 sandbox: Build a device tree file for sandbox
In reply to Simon GlassAdd support for building a device tree for sandbox's CONFIG_OF_HOSTFILE option to make it easier to use device tree with sandbox.
This adjusts the Makefile to build a u-boot.dtb file which can be passed to sandbox U-Boot with:
./u-boot -d u-boot.dtb
---
Changes in v3:
- Add new patch to build a device tree file for sandbox
Changes in v2: None
Makefile | 1 + arch/sandbox/config.mk | 2 ++ board/sandbox/dts/sandbox.dts | 20 ++++++++++++++++++++ include/configs/sandbox.h | 1 + 4 files changed, 24 insertions(+) create mode 100644 board/sandbox/dts/sandbox.dts
Makefile +1 -0
@@ -413,6 +413,7 @@ ALL-$(CONFIG_NAND_U_BOOT) += $(obj)u-boot-nand.bin ALL-$(CONFIG_ONENAND_U_BOOT) += $(obj)u-boot-onenand.bin ALL-$(CONFIG_SPL) += $(obj)spl/u-boot-spl.bin ALL-$(CONFIG_OF_SEPARATE) += $(obj)u-boot.dtb $(obj)u-boot-dtb.bin +ALL-$(CONFIG_OF_HOSTFILE) += $(obj)u-boot.dtb ifneq ($(CONFIG_SPL_TARGET),) ALL-$(CONFIG_SPL) += $(obj)$(subst ",,$(CONFIG_SPL_TARGET)) endif
arch/sandbox/config.mk +2 -0
@@ -23,3 +23,5 @@ PLATFORM_LIBS += -lrt # Support generic board on sandbox __HAVE_ARCH_GENERIC_BOARD := y + +CONFIG_ARCH_DEVICE_TREE := sandbox
board/sandbox/dts/sandbox.dts new file +20 -0
@@ -0,0 +1,20 @@ +/dts-v1/; + +/ { + triangle { + compatible = "demo-shape"; + colour = "cyan"; + sides = <3>; + character = <83>; + }; + square { + compatible = "demo-shape"; + colour = "blue"; + sides = <4>; + }; + hexagon { + compatible = "demo-simple"; + colour = "white"; + sides = <6>; + }; +};
include/configs/sandbox.h +1 -0
@@ -31,6 +31,7 @@#define CONFIG_LMB #define CONFIG_FIT #define CONFIG_CMD_FDT +#define CONFIG_DEFAULT_DEVICE_TREE sandbox#define CONFIG_FS_FAT #define CONFIG_FS_EXT4
Signature · 1 line
1.8.3
PATCH v3 5/16 Add cmd_process_error() to report and process errors
In reply to Simon GlassU-Boot now uses errors defined in include/errno.h which are negative integers. Commands which fail need to report the error and return 1 to indicate failure. Add this functionality in cmd_process_error().
For now this merely reports the error number. It would be possible also to produce a helpful error message by storing the error strings in U-Boot.
---
Changes in v3: None
Changes in v2: None
common/command.c | 10 ++++++++++ include/command.h | 9 +++++++++ 2 files changed, 19 insertions(+)
common/command.c +10 -0
@@ -554,3 +554,13 @@ enum command_ret_t cmd_process(int flag, int argc, char * const argv[], rc =cmd_usage (cmdtp);return rc; } + +int cmd_process_error (cmd_tbl_t *cmdtp,int err) +{ +if (err) { +printf ("Command '%s' failed: Error %d\n" , cmdtp->name, err); +return 1 ; + } + +return 0 ; +}
include/command.h +9 -0
@@ -80,6 +80,15 @@ extern int var_complete(int argc, char * const argv[], char last_char, int maxv,extern int cmd_auto_complete (const char *const prompt,char *buf,int *np,int *colp);#endif +/** +* cmd_process_error() - report and process a possible error +* +* @cmdtp: Command which caused the error +* @err: Error code (0 if none, -ve for error, like -EIO) +* @return 0 if there is not error, 1 (CMD_RET_FAILURE) if an error is found +*/ +int cmd_process_error (cmd_tbl_t *cmdtp,int err); +/* * Monitor Command *
Signature · 1 line
1.8.3
PATCH v3 6/16 sandbox: config: Enable driver model
In reply to Simon GlassUse driver model in sandbox to permit running of driver model unit test.
---
Changes in v3: None
Changes in v2: None
include/configs/sandbox.h | 2 ++ 1 file changed, 2 insertions(+)
include/configs/sandbox.h +2 -0
@@ -22,6 +22,8 @@#ifndef __CONFIG_H#define __CONFIG_H +#define CONFIG_DM +/* Number of bits in a C 'long' on this architecture */ #define CONFIG_SANDBOX_BITS_PER_LONG 64
Signature · 1 line
1.8.3
PATCH v3 7/16 dm: Add base driver model support
In reply to Simon GlassAdd driver model functionality for generic board.
This includes data structures and base code for registering devices and uclasses (groups of devices with the same purpose, e.g. all I2C ports will be in the same uclass).
The feature is enabled with CONFIG_DM.
---
Changes in v3:
- Tidy up commenting of functions and structures
- Rename per_device_priv_size to per_device_auto_alloc_size, etc.
- Add a flag for tracking whether DM allocates/frees platform_data
Changes in v2: None
Makefile | 2 + common/dm/Makefile | 43 +++++ common/dm/device.c | 331 ++++++++++++++++++++++++++++++++++++++ common/dm/lists.c | 168 +++++++++++++++++++ common/dm/root.c | 115 +++++++++++++ common/dm/uclass.c | 298 ++++++++++++++++++++++++++++++++++ common/dm/util.c | 50 ++++++ include/asm-generic/global_data.h | 8 + include/dm.h | 27 ++++ include/dm/device-internal.h | 100 ++++++++++++ include/dm/device.h | 149 +++++++++++++++++ include/dm/lists.h | 52 ++++++ include/dm/platform_data.h | 35 ++++ include/dm/root.h | 66 ++++++++ include/dm/uclass-id.h | 41 +++++ include/dm/uclass-internal.h | 98 +++++++++++ include/dm/uclass.h | 155 ++++++++++++++++++ include/dm/util.h | 42 +++++ 18 files changed, 1780 insertions(+) create mode 100644 common/dm/Makefile create mode 100644 common/dm/device.c create mode 100644 common/dm/lists.c create mode 100644 common/dm/root.c create mode 100644 common/dm/uclass.c create mode 100644 common/dm/util.c create mode 100644 include/dm.h create mode 100644 include/dm/device-internal.h create mode 100644 include/dm/device.h create mode 100644 include/dm/lists.h create mode 100644 include/dm/platform_data.h create mode 100644 include/dm/root.h create mode 100644 include/dm/uclass-id.h create mode 100644 include/dm/uclass-internal.h create mode 100644 include/dm/uclass.h create mode 100644 include/dm/util.h
Makefile +2 -0
@@ -337,6 +337,8 @@ LIBS-y += api/libapi.o LIBS-y += post/libpost.o LIBS-y += test/libtest.o +LIBS-$(CONFIG_DM) += common/dm/libdm.o + ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP34XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TI814X),) LIBS-y += $(CPUDIR)/omap-common/libomap-common.o endif
common/dm/Makefile new file +43 -0
43 lines not on this page · raw message
common/dm/device.c new file +331 -0
331 lines not on this page · raw message
common/dm/lists.c new file +168 -0
168 lines not on this page · raw message
common/dm/root.c new file +115 -0
115 lines not on this page · raw message
common/dm/uclass.c new file +298 -0
298 lines not on this page · raw message
common/dm/util.c new file +50 -0
50 lines not on this page · raw message
include/asm-generic/global_data.h +8 -0
@@ -37,6 +37,8 @@*/ #ifndef __ASSEMBLY__ +#include <linux/list.h> + typedef struct global_data { bd_t *bd; unsigned long flags;
@@ -77,6 +79,12 @@ typedef struct global_data {unsigned long start_addr_sp;/* start_addr_stackpointer */ unsigned long reloc_off;struct global_data *new_gd;/* relocated global data */ + +#ifdef CONFIG_DM +struct device *dm_root;/* Root instance for Driver Model */ +struct list_head uclass_root;/* Head of core tree */ +#endif +const void *fdt_blob;/* Our device tree, NULL if none */ void *new_fdt;/* Relocated FDT */ unsigned long fdt_size;/* Space reserved for relocated FDT */
include/dm.h new file +27 -0
@@ -0,0 +1,27 @@ +/* +* Copyright (c) 2013 Google, Inc +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, +* MA 02111-1307 USA +*/ + +#ifndef _DM_H_ +#define _DM_H + +#include <dm/device.h> +#include <dm/platform_data.h> +#include <dm/uclass.h> + +#endif
include/dm/device-internal.h new file +100 -0
100 lines not on this page · raw message
include/dm/device.h new file +149 -0
149 lines not on this page · raw message
include/dm/lists.h new file +52 -0
52 lines not on this page · raw message
include/dm/platform_data.h new file +35 -0
@@ -0,0 +1,35 @@ +/* +* Copyright (c) 2013 Google, Inc +* +* (C) Copyright 2012 +* Pavel Herrmann <[email protected]> +* Marek Vasut <[email protected]> +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, +* MA 02111-1307 USA +*/ + +#ifndef _DM_PLATFORM_DATA_H +#define _DM_PLATFORM_DATA_H + +struct driver_info { +const char *name; +const void *platform_data; +}; + +#define U_BOOT_DEVICE (__name) \ + ll_entry_declare(struct driver_info, __name, driver_info) + +#endif
include/dm/root.h new file +66 -0
66 lines not on this page · raw message
include/dm/uclass-id.h new file +41 -0
41 lines not on this page · raw message
include/dm/uclass-internal.h new file +98 -0
98 lines not on this page · raw message
include/dm/uclass.h new file +155 -0
155 lines not on this page · raw message
include/dm/util.h new file +42 -0
42 lines not on this page · raw message
Signature · 1 line
1.8.3
PATCH v3 7/16 dm: Add base driver model support
Dear Simon Glass,
Quoted 21 lines
Add driver model functionality for generic board.
This includes data structures and base code for registering devices and uclasses (groups of devices with the same purpose, e.g. all I2C ports will be in the same uclass).
The feature is enabled with
CONFIG_DM.Signed-off-by Simon Glass <[email protected]>Signed-off-by Marek Vasut <[email protected]>Signed-off-by Pavel Herrmann <[email protected]>Signed-off-by Viktor K?iv?k <[email protected]>Signed-off-by Tomas Hlavacek <[email protected]>---
Changes in v3:
- Tidy up commenting of functions and structures
- Renameper_device_priv_sizetoper_device_auto_alloc_size, etc.
- Add a flag for tracking whether DM allocates/freesplatform_dataChanges in v2: None
Quoted 8 lines
Makefile | 2 + common/dm/Makefile | 43 +++++ common/dm/device.c | 331 ++++++++++++++++++++++++++++++++++++++ common/dm/lists.c | 168 +++++++++++++++++++ common/dm/root.c | 115 +++++++++++++ common/dm/uclass.c | 298 ++++++++++++++++++++++++++++++++++ common/dm/util.c | 50 ++++++
Maybe we should move these into drivers/core like Linux has it ?
[...]
Quoted 19 lines
common/dm/device.c new file +19
-0+#include <common.h> +#include <malloc.h> +#include <dm/device.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dm/platform_data.h> +#include <dm/uclass.h> +#include <dm/uclass-internal.h> +#include <dm/util.h> +#include <linux/err.h> +#include <linux/list.h> + +/** +* device_chld_unbind() - Unbind all device's children from the device +* @dev: The device that is to be stripped of its children +* @return 0 on success, -ve on error +*/ +static int device_chld_unbind (struct device *dev) +{
common/dm/device.c line 53
Quoted 10 lines
common/dm/device.c new file +10
-0+struct device *pos, *n; +int ret; + +assert (dev); + +list_for_each_entry_safe (pos, n, &dev->child_head, sibling_node) { + ret =device_unbind (pos); +if (ret) +return ret; + }
This is used for stuff like destroying USB bus topology after running "usb rescan" for the second time, right? We might want to continue unbinding and only report the error instead of returning on the first error.
Quoted 13 lines
common/dm/device.c new file +13
-0+return 0 ; +} + +/** +* device_chld_remove() - Stop all device's children +* @dev: The device whose children are to be removed +* @return 0 on success, -ve on error +*/ +static int device_chld_remove (struct device *dev) +{ +struct device *pos, *n; +int ret; +
common/dm/device.c line 77
Quoted 10 lines
common/dm/device.c new file +10
-0+assert (dev); + +list_for_each_entry_safe (pos, n, &dev->child_head, sibling_node) { + ret =device_remove (pos); +if (ret) +return ret; + } + +return 0 ; +}
[...]
We might really want to document these.
Quoted 2 lines
+int device_bind_by_name(struct device *parent, const struct
driver_info
*info, + struct device **devp)
[...]
common/dm/uclass.c line 43
Quoted 9 lines
common/dm/uclass.c new file +9
-0+struct uclass *uclass_find (enum uclass_id key) +{ +struct uclass *uc; + +/* +* TODO(sjg at chromium.org): Optimise this, perhaps moving the found +* node to the start of the list, or creating a linear array mapping +* id to node. +*/
We better do this later, after it's all in place.
Quoted 9 lines
common/dm/uclass.c new file +9
-0+list_for_each_entry (uc, &gd->uclass_root, sibling_node) { +if (uc->uc_drv->id == key) +return uc; + } + +return NULL ; +} + +/**
common/dm/uclass.c line 62
Quoted 10 lines
common/dm/uclass.c new file +10
-0+* uclass_add() - Create new uclass in list +* @id: Id number to create +* @ucp: Returns pointer to uclass, or NULL on error +* @return 0 on success, -ve on error +* +* The new uclass is added to the list. There must be only one uclass for +* each id. +*/ +static int uclass_add (enum uclass_id id,struct uclass **ucp) +{
I might be a bit lost here. Do we now support adding uclass at runtime ?
Best regards,
PATCH v3 7/16 dm: Add base driver model support
Hi Marek,
Quoted 17 lines · Marek Vasut
Dear Simon Glass,
Quoted 4 lines
Add driver model functionality for generic board.
This includes data structures and base code for registering devices and uclasses (groups of devices with the same purpose, e.g. all I2C ports
will
Quoted 9 lines
be in the same uclass).
The feature is enabled with
CONFIG_DM.Signed-off-by Simon Glass <[email protected]>Signed-off-by Marek Vasut <[email protected]>Signed-off-by Pavel Herrmann <[email protected]>Signed-off-by Viktor K?iv?k <[email protected]>Signed-off-by Tomas Hlavacek <[email protected]>
I am going to tidy this up for a v4, in case you are wondering why I am only getting to this now.
Quoted 12 lines
Quoted 6 lines
---
Changes in v3:
- Tidy up commenting of functions and structures
- Renameper_device_priv_sizetoper_device_auto_alloc_size, etc.
- Add a flag for tracking whether DM allocates/freesplatform_dataQuoted 6 lines
Changes in v2: None
Makefile | 2 + common/dm/Makefile | 43 +++++ common/dm/device.c | 331++++++++++++++++++++++++++++++++++++++
common/dm/lists.c
Quoted 9 lines
|
Quoted 3 lines
168 +++++++++++++++++++
common/dm/root.c | 115 +++++++++++++ common/dm/uclass.c | 298++++++++++++++++++++++++++++++++++
Quoted 1 line
common/dm/util.c | 50 ++++++Maybe we should move these into
drivers/corelike Linux has it ?
Done
Quoted 29 lines
[...]
Quoted 26 lines
common/dm/device.c new file +26
-0+#include <common.h> +#include <malloc.h> +#include <dm/device.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dm/platform_data.h> +#include <dm/uclass.h> +#include <dm/uclass-internal.h> +#include <dm/util.h> +#include <linux/err.h> +#include <linux/list.h> + +/** +* device_chld_unbind() - Unbind all device's children from the device +* @dev: The device that is to be stripped of its children +* @return 0 on success, -ve on error +*/ +static int device_chld_unbind (struct device *dev) +{ +struct device *pos, *n; +int ret; + +assert (dev); + +list_for_each_entry_safe (pos, n, &dev->child_head, sibling_node) { + ret =device_unbind (pos);
Quoted 9 lines
common/dm/device.c line 53
Quoted 3 lines
common/dm/device.c new file +3
-0+if (ret) +return ret; + }This is used for stuff like destroying USB bus topology after running "usb rescan" for the second time, right? We might want to continue unbinding and only
report the error instead of returning on the first error.
Done
Quoted 27 lines
Quoted 24 lines
common/dm/device.c new file +23
-0+return 0 ; +} + +/** +* device_chld_remove() - Stop all device's children +* @dev: The device whose children are to be removed +* @return 0 on success, -ve on error +*/ +static int device_chld_remove (struct device *dev) +{ +struct device *pos, *n; +int ret; + +assert (dev); + +list_for_each_entry_safe (pos, n, &dev->child_head, sibling_node) { + ret =device_remove (pos); +if (ret) +return ret; + } + +return 0 ; +}[...]
Quoted 2 lines
We might really want to document these.
Yes - they are documented in the header file include/dm/device-internal.h
Quoted 14 lines
Quoted 3 lines
+int device_bind_by_name(struct device *parent, const struct
driver_info
*info, + struct device **devp)[...]
common/dm/uclass.c
Quoted 7 lines
common/dm/uclass.c new file +7
-0+struct uclass *uclass_find (enum uclass_id key) +{ +struct uclass *uc; + +/* +* TODO(sjg at chromium.org): Optimise this, perhaps moving the found +* node to the start of the list, or creating a linear array mapping
Quoted 5 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ * id to node. + */We better do this later, after it's all in place.
Yes, I'm not sure how important it is. We only have about 3 uclasses. This will be a nice problem to have when all the drivers are converted...
Quoted 17 lines
Quoted 6 lines
common/dm/uclass.c new file +5
-0+list_for_each_entry (uc, &gd->uclass_root, sibling_node) { +if (uc->uc_drv->id == key) +return uc; + } +common/dm/uclass.c
Quoted 10 lines
common/dm/uclass.c new file +10
-0+return NULL ; +} + +/** +* uclass_add() - Create new uclass in list +* @id: Id number to create +* @ucp: Returns pointer to uclass, or NULL on error +* @return 0 on success, -ve on error +* +* The new uclass is added to the list. There must be only one uclass for
Quoted 7 lines
Review
Quoted 4 lines
+ * each id.
+ */(quoted diff) +2
-0+static int uclass_add(enum uclass_id id, struct uclass **ucp) +{I might be a bit lost here. Do we now support adding uclass at runtime ?
Sort-of. The uclass_get() function is the only one exported, but it in turn calls uclass_add(). We could open this up later, but I don't see a lot of benefit, since we only want one uclass per ID.
Regards,
Simon
PATCH v3 8/16 dm: Set up driver model after relocation
In reply to Simon GlassMake driver model available after relocation, by setting up data structures and scanning for devices using compiled-in platform_data and (when available) the device tree.
---
Changes in v3: None
Changes in v2: None
common/board_r.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
common/board_r.c +33 -0
@@ -34,6 +34,7 @@#ifdef CONFIG_HAS_DATAFLASH #include <dataflash.h> #endif +#include <dm.h> #include <environment.h> #include <fdtdec.h> #if defined(CONFIG_CMD_IDE )
@@ -66,7 +67,9 @@#ifdef CONFIG_X86 #include <asm/init_helpers.h> #endif +#include <dm/root.h> #include <linux/compiler.h> +#include <linux/err.h> DECLARE_GLOBAL_DATA_PTR ;
@@ -269,6 +272,33 @@ static int initr_malloc(void)return 0 ; } +#ifdef CONFIG_DM +static int initr_dm (void ) +{ +int ret; + + ret =dm_init (); +if (ret) { +debug ("dm_init() failed: %d\n" , ret); +return ret; + } + ret =dm_scan_platform_data (); +if (ret) { +debug ("dm_scan_platform_data() failed: %d\n" , ret); +return ret; + } +#ifdef CONFIG_OF_CONTROL + ret =dm_scan_fdt (gd->fdt_blob); +if (ret) { +debug ("dm_scan_fdt() failed: %d\n" , ret); +return ret; + } +#endif + +return 0 ; +} +#endif +__weak int power_init_board (void ) {return 0 ;
@@ -766,6 +796,9 @@ init_fnc_t init_sequence_r[] = { initr_barrier, initr_malloc, bootstage_relocate, +#ifdef CONFIG_DM + initr_dm, +#endif #ifdef CONFIG_ARCH_EARLY_INIT_R arch_early_init_r, #endif
Signature · 1 line
1.8.3
PATCH v3 8/16 dm: Set up driver model after relocation
Dear Simon Glass,
Quoted 45 lines
Make driver model available after relocation, by setting up data structures and scanning for devices using compiled-in
platform_dataand (when available) the device tree.Signed-off-by Simon Glass <[email protected]>---
Changes in v3: None
Changes in v2: Nonecommon/board_r.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)common/board_r.c +10
-0@@ -34,6 +34,7 @@#ifdef CONFIG_HAS_DATAFLASH #include <dataflash.h> #endif +#include <dm.h> #include <environment.h> #include <fdtdec.h> #if defined(CONFIG_CMD_IDE )@@ -66,7 +67,9 @@#ifdef CONFIG_X86 #include <asm/init_helpers.h> #endif +#include <dm/root.h> #include <linux/compiler.h> +#include <linux/err.h> DECLARE_GLOBAL_DATA_PTR ;@@ -269,6 +272,33 @@ static int initr_malloc(void)return 0 ; } +#ifdef CONFIG_DM +static int initr_dm (void ) +{ +int ret; + + ret =dm_init (); +if (ret) {
common/board_r.c static int initr_malloc(void) · line 291
Quoted 10 lines
common/board_r.c +10
-0+debug ("dm_init() failed: %d\n" , ret); +return ret; + } + ret =dm_scan_platform_data (); +if (ret) { +debug ("dm_scan_platform_data() failed: %d\n" , ret); +return ret; + } +#ifdef CONFIG_OF_CONTROL + ret =dm_scan_fdt (gd->fdt_blob);
This part is _very_ nice!
Quoted 14 lines
common/board_r.c +10
-0+if (ret) { +debug ("dm_scan_fdt() failed: %d\n" , ret); +return ret; + } +#endif + + return 0; +} +#endif +__weak int power_init_board (void ) {return 0 ;
common/board_r.c init_fnc_t init_sequence_r[] = { · line 804
Quoted 9 lines
common/board_r.c +3
-0@@ -766,6 +796,9 @@ init_fnc_t init_sequence_r[] = { initr_barrier, initr_malloc, bootstage_relocate, +#ifdef CONFIG_DM + initr_dm, +#endif #ifdef CONFIG_ARCH_EARLY_INIT_R arch_early_init_r, #endif
Best regards,
Marek Vasut
PATCH v3 8/16 dm: Set up driver model after relocation
Hi Marek,
Quoted 52 lines · Marek Vasut
Dear Simon Glass,
Quoted 1 line
Make driver model available after relocation, by setting up data
structures
Quoted 48 lines
and scanning for devices using compiled-in
platform_dataand (when available) the device tree.Signed-off-by Simon Glass <[email protected]>---
Changes in v3: None
Changes in v2: Nonecommon/board_r.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)common/board_r.c +14
-0@@ -34,6 +34,7 @@#ifdef CONFIG_HAS_DATAFLASH #include <dataflash.h> #endif +#include <dm.h> #include <environment.h> #include <fdtdec.h> #if defined(CONFIG_CMD_IDE )@@ -66,7 +67,9 @@#ifdef CONFIG_X86 #include <asm/init_helpers.h> #endif +#include <dm/root.h> #include <linux/compiler.h> +#include <linux/err.h> DECLARE_GLOBAL_DATA_PTR ;@@ -269,6 +272,33 @@ static int initr_malloc(void)return 0 ; } +#ifdef CONFIG_DM +static int initr_dm (void ) +{ +int ret; + + ret =dm_init (); +if (ret) { +debug ("dm_init() failed: %d\n" , ret); +return ret; + } + ret =dm_scan_platform_data ();
Quoted 9 lines
common/board_r.c static int initr_malloc(void) · line 291
Quoted 6 lines
common/board_r.c +6
-0+if (ret) { +debug ("dm_scan_platform_data() failed: %d\n" , ret); +return ret; + } +#ifdef CONFIG_OF_CONTROL + ret =dm_scan_fdt (gd->fdt_blob);This part is _very_ nice!
Yes, it's great - it will provide automated availability of device instances just from the device tree.
Regards,
Simon
PATCH v3 8/16 dm: Set up driver model after relocation
Hi Simon,
Quoted 76 lines
Hi Marek,
Quoted 64 lines · Marek Vasut
Dear Simon Glass,
Quoted 1 line
Make driver model available after relocation, by setting up data
structures
Quoted 58 lines
and scanning for devices using compiled-in
platform_dataand (when available) the device tree.Signed-off-by Simon Glass <[email protected]>---
Changes in v3: None
Changes in v2: Nonecommon/board_r.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)common/board_r.c +1
-0@@ -34,6 +34,7 @@#ifdef CONFIG_HAS_DATAFLASH #include <dataflash.h> #endif +#include <dm.h> #include <
environment.h>
#include <fdtdec.h>
#ifdefined(CONFIG_CMD_IDE)common/board_r.c +13
-0@@ -66,7 +67,9 @@#ifdef CONFIG_X86 #include <asm/init_helpers.h> #endif +#include <dm/root.h> #include <linux/compiler.h> +#include <linux/err.h> DECLARE_GLOBAL_DATA_PTR ;@@ -269,6 +272,33 @@ static int initr_malloc(void)return 0 ; } +#ifdef CONFIG_DM +static int initr_dm (void ) +{ +int ret; + + ret =dm_init (); +if (ret) { +debug ("dm_init() failed: %d\n" , ret); +return ret; + } + ret =dm_scan_platform_data ();Quoted 8 lines
common/board_r.c static int initr_malloc(void) · line 291
Quoted 6 lines
common/board_r.c +6
-0+if (ret) { +debug ("dm_scan_platform_data() failed: %d\n" , ret); +return ret; + } +#ifdef CONFIG_OF_CONTROL + ret =dm_scan_fdt (gd->fdt_blob);This part is _very_ nice!
Quoted 2 lines
Yes, it's great - it will provide automated availability of device instances just from the device tree.
Let us meet at the ELCE and discuss this. I'll not be half-asleep this time.
PATCH v3 9/16 dm: Add basic tests
In reply to Simon GlassAdd some tests of driver model functionality. Coverage includes:
- basic init
- binding of drivers to devices using platform_data
- automatic probing of devices when referenced
- availability of platform data to devices
- lifecycle from bind to probe to remove to unbind
- renumbering within a uclass when devices are probed/removed
- calling driver-defined operations
- deactivation of drivers when removed
- memory leak across creation and destruction of drivers/uclasses
- uclass init/destroy methods
- automatic probe/remove of children/parents when needed
This function is enabled for sandbox, using CONFIG_DM_TEST.
---
Changes in v3:
- Add function/struct comments to tests
Changes in v2: None
Makefile | 1 + include/configs/sandbox.h | 1 + include/dm/test.h | 180 +++++++++++++++ include/dm/ut.h | 108 +++++++++ test/dm/Makefile | 52 +++++ test/dm/core.c | 557 ++++++++++++++++++++++++++++++++++++++++++++++ test/dm/test-driver.c | 159 +++++++++++++ test/dm/test-fdt.c | 148 ++++++++++++ test/dm/test-main.c | 120 ++++++++++ test/dm/test-uclass.c | 117 ++++++++++ test/dm/test.dts | 59 +++++ test/dm/ut.c | 46 ++++ 12 files changed, 1548 insertions(+) create mode 100644 include/dm/test.h create mode 100644 include/dm/ut.h create mode 100644 test/dm/Makefile create mode 100644 test/dm/core.c create mode 100644 test/dm/test-driver.c create mode 100644 test/dm/test-fdt.c create mode 100644 test/dm/test-main.c create mode 100644 test/dm/test-uclass.c create mode 100644 test/dm/test.dts create mode 100644 test/dm/ut.c
Makefile +1 -0
@@ -336,6 +336,7 @@ LIBS-y += lib/libfdt/libfdt.o LIBS-y += api/libapi.o LIBS-y += post/libpost.o LIBS-y += test/libtest.o +LIBS-y += test/dm/libtestdm.o LIBS-$(CONFIG_DM) += common/dm/libdm.o
include/configs/sandbox.h +1 -0
@@ -23,6 +23,7 @@#define __CONFIG_H#define CONFIG_DM +#define CONFIG_DM_TEST /* Number of bits in a C 'long' on this architecture */ #define CONFIG_SANDBOX_BITS_PER_LONG 64
include/dm/test.h new file +180 -0
180 lines not on this page · raw message
include/dm/ut.h new file +108 -0
108 lines not on this page · raw message
test/dm/Makefile new file +52 -0
52 lines not on this page · raw message
test/dm/core.c new file +557 -0
557 lines not on this page · raw message
test/dm/test-driver.c new file +159 -0
159 lines not on this page · raw message
test/dm/test-fdt.c new file +148 -0
148 lines not on this page · raw message
test/dm/test-main.c new file +120 -0
120 lines not on this page · raw message
test/dm/test-uclass.c new file +117 -0
117 lines not on this page · raw message
test/dm/test.dts new file +59 -0
59 lines not on this page · raw message
test/dm/ut.c new file +46 -0
46 lines not on this page · raw message
Signature · 1 line
1.8.3
PATCH v3 10/16 dm: Add a 'dm' command for testing
In reply to Simon GlassThis command is not required for driver model operation, but can be useful for testing. It provides simple dumps of internal data structures.
---
Changes in v3: None
Changes in v2: None
include/configs/sandbox.h | 1 + test/dm/Makefile | 1 + test/dm/cmd_dm.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 test/dm/cmd_dm.c
include/configs/sandbox.h +1 -0
@@ -23,6 +23,7 @@#define __CONFIG_H#define CONFIG_DM +#define CONFIG_CMD_DM #define CONFIG_DM_TEST /* Number of bits in a C 'long' on this architecture */
test/dm/Makefile +1 -0
@@ -21,6 +21,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)libtestdm.o +COBJS-$(CONFIG_CMD_DM) += cmd_dm.o COBJS-$(CONFIG_DM_TEST) += test-driver.o COBJS-$(CONFIG_DM_TEST) += test-fdt.o COBJS-$(CONFIG_DM_TEST) += test-main.o
test/dm/cmd_dm.c new file +146 -0
146 lines not on this page · raw message
Signature · 1 line
1.8.3
PATCH v3 10/16 dm: Add a 'dm' command for testing
Dear Simon Glass,
test/dm/cmd_dm.c line 146
Quoted 7 lines
test/dm/cmd_dm.c new file +7
-0+U_BOOT_CMD ( + dm,2 ,1 , do_dm, +"Driver model low level access" , +"dump Dump driver model tree\n" +"dm uclass Dump list of instances for each uclass\n" +"dm test Run tests" +);
Looking at this, remark comes to mind. We should really fix this inconsistency between the first "dump" and the rest of "dm uclass" and "dm test" etc. in the U_BOOT_CMD.
This is obviously out of scope of these patches.
Best regards,
Marek Vasut
PATCH v3 10/16 dm: Add a 'dm' command for testing
Hi Marek,
Quoted 16 lines · Marek Vasut
Dear Simon Glass,
test/dm/cmd_dm.c line 146
Quoted 7 lines
test/dm/cmd_dm.c new file +7
-0+U_BOOT_CMD ( + dm,2 ,1 , do_dm, +"Driver model low level access" , +"dump Dump driver model tree\n" +"dm uclass Dump list of instances for each uclass\n" +"dm test Run tests" +);Looking at this, remark comes to mind. We should really fix this inconsistency
between the first "dump" and the rest of "dm uclass" and "dm test" etc. in theU_BOOT_CMD.
I think I'll change this one to 'dm tree' instead of 'dm dump' since 'dump' is pretty vague.
Quoted 1 line
This is obviously out of scope of these patches.
Regards,
Simon
PATCH v3 11/16 dm: Add a demonstration/example driver
In reply to Simon GlassAs an example of how to write a uclass and a driver, provide a demo version of each, accessible through the 'demo' command.
To use these with driver model, define CONFIG_CMD_DEMO and CONFIG_DM_DEMO.
The two demo drivers are enabled with CONFIG_DM_DEMO_SIMPLE and CONFIG_DM_DEMO_SHAPE.
---
Changes in v3:
- Fix up demo command help
- Update demo driver to use device tree
Changes in v2: None
Makefile | 1 + common/Makefile | 1 + common/cmd_demo.c | 115 ++++++++++++++++++++++++++++++++++++ drivers/demo/Makefile | 44 ++++++++++++++ drivers/demo/demo-pdata.c | 60 +++++++++++++++++++ drivers/demo/demo-shape.c | 143 +++++++++++++++++++++++++++++++++++++++++++++ drivers/demo/demo-simple.c | 61 +++++++++++++++++++ drivers/demo/demo-uclass.c | 73 +++++++++++++++++++++++ include/configs/sandbox.h | 4 ++ include/dm-demo.h | 49 ++++++++++++++++ 10 files changed, 551 insertions(+) create mode 100644 common/cmd_demo.c create mode 100644 drivers/demo/Makefile create mode 100644 drivers/demo/demo-pdata.c create mode 100644 drivers/demo/demo-shape.c create mode 100644 drivers/demo/demo-simple.c create mode 100644 drivers/demo/demo-uclass.c create mode 100644 include/dm-demo.h
Makefile +1 -0
@@ -338,6 +338,7 @@ LIBS-y += post/libpost.o LIBS-y += test/libtest.o LIBS-y += test/dm/libtestdm.o +LIBS-$(CONFIG_DM_DEMO) += drivers/demo/libdemo.o LIBS-$(CONFIG_DM) += common/dm/libdm.o ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP34XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TI814X),)
common/Makefile +1 -0
@@ -85,6 +85,7 @@ COBJS-$(CONFIG_CMD_CONSOLE) += cmd_console.o COBJS-$(CONFIG_CMD_CPLBINFO) += cmd_cplbinfo.o COBJS-$(CONFIG_DATAFLASH_MMC_SELECT) += cmd_dataflash_mmc_mux.o COBJS-$(CONFIG_CMD_DATE) += cmd_date.o +COBJS-$(CONFIG_CMD_DEMO) += cmd_demo.o COBJS-$(CONFIG_CMD_SOUND) += cmd_sound.o ifdef CONFIG_4xx COBJS-$(CONFIG_CMD_SETGETDCR) += cmd_dcr.o
common/cmd_demo.c new file +115 -0
115 lines not on this page · raw message
drivers/demo/Makefile new file +44 -0
44 lines not on this page · raw message
drivers/demo/demo-pdata.c new file +60 -0
60 lines not on this page · raw message
drivers/demo/demo-shape.c new file +143 -0
143 lines not on this page · raw message
drivers/demo/demo-simple.c new file +61 -0
61 lines not on this page · raw message
drivers/demo/demo-uclass.c new file +73 -0
73 lines not on this page · raw message
include/configs/sandbox.h +4 -0
@@ -23,7 +23,11 @@#define __CONFIG_H#define CONFIG_DM +#define CONFIG_CMD_DEMO #define CONFIG_CMD_DM +#define CONFIG_DM_DEMO +#define CONFIG_DM_DEMO_SIMPLE +#define CONFIG_DM_DEMO_SHAPE #define CONFIG_DM_TEST /* Number of bits in a C 'long' on this architecture */
include/dm-demo.h new file +49 -0
49 lines not on this page · raw message
Signature · 1 line
1.8.3
PATCH v3 11/16 dm: Add a demonstration/example driver
Dear Simon Glass,
Quoted 19 lines
As an example of how to write a uclass and a driver, provide a demo version of each, accessible through the 'demo' command.
To use these with driver model, define
CONFIG_CMD_DEMOandCONFIG_DM_DEMO.The two demo drivers are enabled with
CONFIG_DM_DEMO_SIMPLEandCONFIG_DM_DEMO_SHAPE.Signed-off-by Simon Glass <[email protected]>Signed-off-by Marek Vasut <[email protected]>Signed-off-by Pavel Herrmann <[email protected]>Signed-off-by Viktor K?iv?k <[email protected]>Signed-off-by Tomas Hlavacek <[email protected]>---
Changes in v3:
- Fix up demo command help
- Update demo driver to use device treeChanges in v2: None
[...]
drivers/demo/demo-pdata.c line 60
Quoted 4 lines
drivers/demo/demo-pdata.c new file +4
-0+U_BOOT_DEVICE (demo4) = { + .name ="demo_shape_drv" , + .platform_data = &yellow_hexagon, +};
So this is static instantiation of the drivers?
[...]
drivers/demo/demo-simple.c line 59
Quoted 7 lines
drivers/demo/demo-simple.c new file +7
-0+U_BOOT_DRIVER (demo_simple_drv) = { + .name ="demo_simple_drv" , + .of_match = demo_shape_id, + .id =UCLASS_DEMO , + .probe = demo_shape_probe, + .ops = &simple_ops, + .ops = &simple_ops,
This .ops is here twice ;-)
Review
Quoted 2 lines
(quoted diff) +2
-0+ .platform_data_auto_alloc_size = sizeof(struct dm_demo_pdata), +};
[...]
Best regards,
Marek Vasut
PATCH v3 11/16 dm: Add a demonstration/example driver
Hi Marek,
Quoted 24 lines · Marek Vasut
Dear Simon Glass,
Quoted 1 line
As an example of how to write a uclass and a driver, provide a demo
version
Quoted 3 lines
of each, accessible through the 'demo' command.
To use these with driver model, define
CONFIG_CMD_DEMOand
CONFIG_DM_DEMO.Quoted 9 lines
The two demo drivers are enabled with
CONFIG_DM_DEMO_SIMPLEandCONFIG_DM_DEMO_SHAPE.Signed-off-by Simon Glass <[email protected]>Signed-off-by Marek Vasut <[email protected]>Signed-off-by Pavel Herrmann <[email protected]>Signed-off-by Viktor K?iv?k <[email protected]>Signed-off-by Tomas Hlavacek <[email protected]>Quoted 6 lines
---
Changes in v3:
- Fix up demo command help
- Update demo driver to use device treeChanges in v2: None
Quoted 9 lines
[...]
drivers/demo/demo-pdata.c line 60
Quoted 4 lines
drivers/demo/demo-pdata.c new file +4
-0+U_BOOT_DEVICE (demo4) = { + .name ="demo_shape_drv" , + .platform_data = &yellow_hexagon, +};So this is static instantiation of the drivers?
Yes, it is possible to set up a device either with statically-linked platform_data (as here) or with device tree.
Quoted 11 lines
[...]
drivers/demo/demo-simple.c line 59
Quoted 7 lines
drivers/demo/demo-simple.c new file +7
-0+U_BOOT_DRIVER (demo_simple_drv) = { + .name ="demo_simple_drv" , + .of_match = demo_shape_id, + .id =UCLASS_DEMO , + .probe = demo_shape_probe, + .ops = &simple_ops, + .ops = &simple_ops,
Quoted 2 lines
This .ops is here twice ;-)
Fixed.
Quoted 8 lines
Quoted 3 lines
(quoted diff) +2
-0+ .platform_data_auto_alloc_size = sizeof(struct dm_demo_pdata), +};[...]
Regards,
Simon
PATCH v3 12/16 dm: Add GPIO support and tests
In reply to Simon GlassAdd driver model support for GPIOs. Since existing GPIO drivers do not use driver model, this feature must be enabled by CONFIG_DM_GPIO. After all GPO drivers are converted over we can perhaps remove this config.
Tests are provided for the sandbox implementation, and are a sufficient sanity check for basic operation.
The GPIO uclass understands the concept of named banks of GPIOs, with each GPIO device providing a single bank. Within each bank the GPIOs are numbered using an offset from 0 to n-1. For example a bank named 'b' with 20 offsets will provide GPIOs named b0 to b19.
Anonymous GPIO banks are also supported, and are just numbered without any prefix.
Each time a GPIO driver is added to the uclass, the GPIOs are renumbered accordinging, so there is always a global GPIO numbering order.
---
Changes in v3:
- Update GPIO support to use new struct member names
- Tidy up comments/documentation in GPIO module
Changes in v2: None
drivers/gpio/Makefile | 2 + drivers/gpio/gpio-uclass.c | 279 +++++++++++++++++++++++++++++++++++++++++++++ include/asm-generic/gpio.h | 104 +++++++++++++++++ test/dm/gpio.c | 124 ++++++++++++++++++++ 4 files changed, 509 insertions(+) create mode 100644 drivers/gpio/gpio-uclass.c create mode 100644 test/dm/gpio.c
drivers/gpio/Makefile +2 -0
@@ -25,6 +25,8 @@ include $(TOPDIR)/config.mk LIB := $(obj)libgpio.o +COBJS-$(CONFIG_DM_GPIO) += gpio-uclass.o + COBJS-$(CONFIG_AT91_GPIO) += at91_gpio.o COBJS-$(CONFIG_INTEL_ICH6_GPIO) += intel_ich6_gpio.o COBJS-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o
drivers/gpio/gpio-uclass.c new file +279 -0
279 lines not on this page · raw message
include/asm-generic/gpio.h +104 -0
108 lines not on this page · raw message
test/dm/gpio.c new file +124 -0
124 lines not on this page · raw message
Signature · 1 line
1.8.3
PATCH v3 12/16 dm: Add GPIO support and tests
Dear Simon Glass,
Quoted 17 lines
Add driver model support for GPIOs. Since existing GPIO drivers do not use driver model, this feature must be enabled by
CONFIG_DM_GPIO. After all GPO drivers are converted over we can perhaps remove this config.Tests are provided for the sandbox implementation, and are a sufficient sanity check for basic operation.
The GPIO uclass understands the concept of named banks of GPIOs, with each GPIO device providing a single bank. Within each bank the GPIOs are numbered using an offset from 0 to n-1. For example a bank named 'b' with 20 offsets will provide GPIOs named b0 to b19.
Anonymous GPIO banks are also supported, and are just numbered without any prefix.
Each time a GPIO driver is added to the uclass, the GPIOs are renumbered accordinging, so there is always a global GPIO numbering order.
[...]
include/asm-generic/gpio.h int gpio_get_value(unsigned gpio); · line 142
Quoted 9 lines
include/asm-generic/gpio.h +9
-0+struct dm_gpio_ops { +int (*request)(struct device *dev,unsigned offset,const char *label); +int (*free)(struct device *dev,unsigned offset); +int (*direction_input)(struct device *dev,unsigned offset); +int (*direction_output)(struct device *dev,unsigned offset, +int value); +int (*get_value)(struct device *dev,unsigned offset); +int (*set_value)(struct device *dev,unsigned offset,int value); +int (*get_function)(struct device *dev,unsigned offset);
What's this "get_function()" call about? Is this to set GPIO AF ? If so, it's mixing pinmux and GPIO into one, that shouldn't happen.
include/asm-generic/gpio.h int gpio_get_value(unsigned gpio); · line 145
Quoted 3 lines
include/asm-generic/gpio.h +3
-0+int (*get_state)(struct device *dev,unsigned offset,char *state, +int maxlen); +};
[...]
Best regards,
Marek Vasut
PATCH v3 12/16 dm: Add GPIO support and tests
Hi Marek,
Quoted 36 lines · Marek Vasut
Dear Simon Glass,
Quoted 1 line
Add driver model support for GPIOs. Since existing GPIO drivers do not
use
Quoted 7 lines
driver model, this feature must be enabled by
CONFIG_DM_GPIO. After all GPO drivers are converted over we can perhaps remove this config.Tests are provided for the sandbox implementation, and are a sufficient sanity check for basic operation.
The GPIO uclass understands the concept of named banks of GPIOs, with
each
Quoted 5 lines
GPIO device providing a single bank. Within each bank the GPIOs are numbered using an offset from 0 to n-1. For example a bank named 'b' with 20 offsets will provide GPIOs named b0 to b19.
Anonymous GPIO banks are also supported, and are just numbered without
any
Quoted 4 lines
prefix.
Each time a GPIO driver is added to the uclass, the GPIOs are renumbered accordinging, so there is always a global GPIO numbering order.
[...]
Review
Quoted 2 lines
(quoted diff) +2
-0+struct dm_gpio_ops { + int (*request)(struct device *dev, unsigned offset, const char*label);
include/asm-generic/gpio.h int gpio_get_value(unsigned gpio); · line 142
Quoted 7 lines
include/asm-generic/gpio.h +7
-0+int (*free)(struct device *dev,unsigned offset); +int (*direction_input)(struct device *dev,unsigned offset); +int (*direction_output)(struct device *dev,unsigned offset, +int value); +int (*get_value)(struct device *dev,unsigned offset); +int (*set_value)(struct device *dev,unsigned offset,int value); +int (*get_function)(struct device *dev,unsigned offset);
Quoted 4 lines
What's this "
get_function()" call about? Is this to set GPIO AF ? If so, it's
mixing pinmux and GPIO into one, that shouldn't happen.
It's this:
static const char * const gpio_function[] = {
"input",
"output",
"unknown",
};
We need to know the whether the pin is in use for GPIO and if so, whether it is input or output.
I have not looked at pinmux, but consider this out of scope for this series.
Quoted 9 lines
include/asm-generic/gpio.h int gpio_get_value(unsigned gpio); · line 145
Quoted 4 lines
include/asm-generic/gpio.h +3
-0+int (*get_state)(struct device *dev,unsigned offset,char *state, +int maxlen); +};[...]
Regards,
Simon
PATCH v3 13/16 sandbox: Convert GPIOs to use driver model
In reply to Simon GlassConvert sandbox over to use driver model GPIOs.
---
Changes in v3:
- Update sandbox GPIO header file comments
Changes in v2: None
arch/sandbox/include/asm/gpio.h | 14 +-- board/sandbox/sandbox/sandbox.c | 7 +- drivers/gpio/sandbox.c | 210 +++++++++++++++++++++++++--------------- include/configs/sandbox.h | 1 + 4 files changed, 144 insertions(+), 88 deletions(-)
arch/sandbox/include/asm/gpio.h +5 -9
@@ -45,7 +45,7 @@* @param gp GPIO number * @return -1 on error, 0 if GPIO is low, >0 if high */ -int sandbox_gpio_get_value (unsigned gp); +int sandbox_gpio_get_value (struct device *dev,unsigned int offset);/** * Set the simulated value of a GPIO (used only in sandbox test code)
@@ -54,7 +54,7 @@ int sandbox_gpio_get_value(unsigned gp);* @param value value to set (0 for low, non-zero for high) * @return -1 on error, 0 if ok */ -int sandbox_gpio_set_value (unsigned gp,int value); +int sandbox_gpio_set_value (struct device *dev,unsigned int offset,int value);/** * Return the simulated direction of a GPIO (used only in sandbox test code)
@@ -62,7 +62,7 @@ int sandbox_gpio_set_value(unsigned gp, int value);* @param gp GPIO number * @return -1 on error, 0 if GPIO is input, >0 if output */ -int sandbox_gpio_get_direction (unsigned gp); +int sandbox_gpio_get_direction (struct device *dev,unsigned int offset);/** * Set the simulated direction of a GPIO (used only in sandbox test code)
@@ -71,11 +71,7 @@ int sandbox_gpio_get_direction(unsigned gp);* @param output 0 to set as input, 1 to set as output * @return -1 on error, 0 if ok */ -int sandbox_gpio_set_direction (unsigned gp,int output); - -/* Display information about each GPIO */ -void gpio_info (void ); - -#define gpio_status () gpio_info() +int sandbox_gpio_set_direction (struct device *dev,unsigned int offset, +int output);#endif
board/sandbox/sandbox/sandbox.c +6 -1
@@ -20,7 +20,7 @@*/ #include <common.h> - +#include <dm.h> #include <os.h> /*
@@ -30,6 +30,11 @@*/ gd_t *gd; +/* Add a simple GPIO device */ +U_BOOT_DEVICE (gpio_sandbox) = { + .name ="gpio_sandbox" , +}; +void flush_cache (unsigned long start,unsigned long size) { }
drivers/gpio/sandbox.c +132 -78
311 lines not on this page · raw message
include/configs/sandbox.h +1 -0
@@ -28,6 +28,7 @@#define CONFIG_DM_DEMO #define CONFIG_DM_DEMO_SIMPLE #define CONFIG_DM_DEMO_SHAPE +#define CONFIG_DM_GPIO #define CONFIG_DM_TEST /* Number of bits in a C 'long' on this architecture */
Signature · 1 line
1.8.3
PATCH v3 14/16 dm: Enable gpio command to support driver model
In reply to Simon GlassNow that named GPIO banks are supported, along with a way of obtaining the status of a GPIO (input or output), we can provide an enhanced GPIO command for driver model. Where the driver provides its own operation for obtaining the GPIO state, this is used, otherwise a generic version is sufficient.
---
Changes in v3: None
Changes in v2: None
common/cmd_gpio.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 114 insertions(+), 13 deletions(-)
common/cmd_gpio.c +114 -13
@@ -8,7 +8,7 @@#include <common.h> #include <command.h> - +#include <dm.h> #include <asm/gpio.h> #ifndef name_to_gpio
@@ -22,25 +22,115 @@ enum gpio_cmd { GPIO_TOGGLE, }; +#if defined(CONFIG_DM_GPIO ) && !defined(gpio_status) +static const char *const gpio_function[] = { +"input" , +"output" , +"unknown" , +}; + +static void show_gpio (struct device *dev,const char *bank_name,int offset) +{ +struct dm_gpio_ops *ops =gpio_get_ops (dev); +char buf[80 ]; +int ret; + + *buf ='\0' ; +if (ops->get_state) { + ret = ops->get_state (dev, offset, buf,sizeof (buf)); +if (ret) { +puts ("<unknown>" ); +return ; + } + }else { +int func =GPIOF_UNKNOWN ; +int ret; + +if (ops->get_function) { + ret = ops->get_function (dev, offset); +if (ret >=0 && ret <ARRAY_SIZE (gpio_function)) + func = ret; + } +sprintf (buf,"%s%u: %8s %d" , bank_name, offset, + gpio_function[func], ops->get_value (dev, offset)); + } + +puts (buf); +puts ("\n" ); +} + +static int do_gpio_status (const char *gpio_name) +{ +struct device *dev; +int newline =0 ; +int ret; + +if (gpio_name && !*gpio_name) + gpio_name =NULL ; +for (ret =uclass_first_device (UCLASS_GPIO , &dev); + dev; + ret =uclass_next_device (&dev)) { +const char *bank_name; +int num_bits; + + bank_name =gpio_get_bank_info (dev, &num_bits); + +if (!gpio_name || !bank_name || + !strncmp (gpio_name, bank_name,strlen (bank_name))) { +const char *p =NULL ; +int offset; + +if (bank_name) { +if (newline) +putc ('\n' ); +printf ("Bank %s:\n" , bank_name); + } + newline =1 ; +if (gpio_name && bank_name) { + p = gpio_name +strlen (bank_name); + offset =simple_strtoul (p,NULL ,10 ); +show_gpio (dev, bank_name, offset); + }else { +for (offset =0 ; offset < num_bits; offset++) +show_gpio (dev, bank_name, offset); + } + } + } + +return ret; +} +#endif +static int do_gpio (cmd_tbl_t *cmdtp,int flag,int argc,char *const argv[]) { -int gpio; +unsigned int gpio;enum gpio_cmd sub_cmd;ulong value; -const char *str_cmd, *str_gpio; +const char *str_cmd, *str_gpio =NULL ; +#ifdef CONFIG_DM_GPIO +int ret; +#endif +if (argc <2 ) + show_usage: +return CMD_RET_USAGE ; + str_cmd = argv[1 ]; +if (argc >2 ) + str_gpio = argv[2 ]; +if (!strcmp (str_cmd,"status" )) { +/* Support deprecated gpio_status() */ #ifdef gpio_status -if (argc ==2 && !strcmp (argv[1 ],"status" )) {gpio_status ();return 0 ; - } +#elif defined(CONFIG_DM_GPIO ) +return cmd_process_error (cmdtp,do_gpio_status (str_gpio)); +#else + goto show_usage;#endif + } -if (argc !=3 ) - show_usage: -return CMD_RET_USAGE ; - str_cmd = argv[1 ]; - str_gpio = argv[2 ]; +if (!str_gpio) + goto show_usage;/* parse the behavior */ switch (*str_cmd) {
@@ -51,11 +141,21 @@ static int do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])default : goto show_usage; } +#if defined(CONFIG_DM_GPIO ) +/* +* TODO(sjg at chromium.org): Convert this code over to use the GPIO +* uclass interface instead of the numbered GPIO compatibility +* layer. +*/ + ret =gpio_lookup_name (str_gpio,NULL ,NULL , &gpio); +if (ret) +return cmd_process_error (cmdtp, ret); +#else /* turn the gpio name into a gpio number */ gpio =name_to_gpio (str_gpio);if (gpio <0 ) goto show_usage; - +#endif /* grab the pin before we tweak it */ if (gpio_request (gpio,"cmd_gpio" )) {printf ("gpio: requesting pin %u failed\n" , gpio);
@@ -84,6 +184,7 @@ static int do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) }U_BOOT_CMD (gpio,3 ,0 , do_gpio, -"input/set/clear/toggle gpio pins" , +"query and control gpio pins" ,"<input|set|clear|toggle> <pin>\n" -" - input/set/clear/toggle the specified pin" ); +" - input/set/clear/toggle the specified pin\n" +"gpio status [<bank> | <pin>]" );
Signature · 1 line
1.8.3
PATCH v3 15/16 dm: Add README for driver model
In reply to Simon GlassFrom: Pavel Herrmann <[email protected]>
This adds a README to help with understanding of this series.
---
Changes in v3:
- Updated README.txt to cover changes since version 2
Changes in v2:
- Removed pointer return values in favour of integer
- Use driver_bind() in dm_init() instead of writing new code
- Allow driver_bind() to support a NULL parent
- Add dm_warn() to warn about impending doom
- Standardise variable names (e.g. uclass instead of class)
- Remove relocation functions
- Add new header file for lists
- Add new util file to hold utility functions
- Allow a driver to bind to only one uclass
- Remove unneeded arguments to uclass_bind(), uclass_unbind()
- Rename struct device's 'bus' to 'parent'
- Rename data structures to hopefully be clearer
- Put platform_data definitions in their own header file
- Add U_BOOT_DEVICE to declare platform_data
- Add auto-probing feature for platform_data to avoid driver_bind() calls
- Add simple unit test functions
- Add test infrastructure for driver model
- Add integration tests for driver model
- Add device tree support in driver model
- Add automatic allocation of platform_data for FDT
- Add automatic allocation of priv data for devices
- Add automatic allocation of device-specific priv data for uclasses
- Add GPIO uclass and tests
- Add sandbox GPIO driver
- Update gpio command to use driver model
- Add tests for core code
- Add script to run tests
- Add a single include/dm.h to bring in driver model code
doc/driver-model/README.txt | 320 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 320 insertions(+) create mode 100644 doc/driver-model/README.txt
doc/driver-model/README.txt new file +320 -0
@@ -0,0 +1,320 @@ +Driver Model +============ + +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 device which operate in the same way. A uclass provides + a way of accessing invidual 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_config + make + ./u-boot + + (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 100% code coverage of them. It does have multiple drivers, it +handles parameter data and platform_data (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/dm/test-dm.sh + + +What is going on? +----------------- + +Let's start at the top. The demo command is in common/cmd_demo.c. It does +the usual command procesing and then: + + struct device *demo_dev; + + ret = uclass_get_device(UCLASS_DEMO, &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 the device for the demo uclass. Given a device +number we can find the device because all devices have registered with +the UCLASS_DEMO uclass. + +Having found the device, we activate it with: + + ret = driver_activate(demo_dev); + +This is because all devices are inactive until used in U-Boot. The exact +mechanism of activating a driver will hopefully change. For example, i +may be possible to combine uclass_get_child() and driver_activate(). + +Now that we have the device we can do things like: + + 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: + +int demo_hello(struct device *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: + +static int simple_hello(struct device *dev, int ch) +{ + const struct dm_demo_pdata *pdata = dev->platform_data; + + printf("Hello from %08x: %s %d\n", map_to_sysmem(dev), + pdata->colour, pdata->sides); + + return 0; +} + + +So that is a trip from top to bottom but it leaves a lot of topics to +address. + + +Declaring Drivers +----------------- + +A driver declaration looks something like this (see +drivers/demo/demo-shape.c): + +static const struct demo_ops simple_ops = { + .hello = shape_hello, + .status = shape_status, +}; + +U_BOOT_DRIVER(demo_shape_drv) = { + .name = "demo_shape_drv", + .id = UCLASS_DEMO, + .ops = &simple_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->priv 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 probe, +and bind, 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. + + +Platform Data +------------- + +Where does the platform data come from? 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 acceess their data via dev->info->platform_data. Here is +the declaration for the platform data, which would normally appear +in the board file. + + static const struct dm_demo_cdata red_square = { + .colour = "red", + .sides = 4. + }; + static const struct driver_info info[] = { + { + .name = "demo_shape_drv", + .platform_data = &red_square, + }, + }; + + demo1 = driver_bind(root, &info[0]); + + +Device Tree +----------- + +While platform_data is useful, a more flexible way of providing device data is +by using device tree. With device tree we replace the above code with the +following device treefragment: + + red-square { + compatible = "demo-shape"; + colour = "red"; + sides = <4>; + }; + + +The easiest way to make this work it to add a platform_data_size member to +the driver: + + .platform_data_auto_alloc_size = sizeof(struct dm_test_pdata), + +This will be allocated and zeroed before the driver's probe method is called. +The driver can then read the information out of the device tree and put it +in dev->priv, typically using a ..._parse_dt() function. + + +Declaring Uclasses +------------------ + +The demo uclass is declared like this: + +U_BOOT_CLASS(demo) = { + .id = UCLASS_DEMO, +}; + +It is also possible to specify special methods for probe, etc. The uclass +numbering comes from include/dm/uclass.h. To add a new uclass, add to the +end of the enum there, then declare your uclass as above. + + +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 agressively 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 device +instead of struct instance, struct platform_data, 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 device'. +This removes a level of indirection that doesn't seem necessary. +- Built in device tree support, to avoid the need for platform_data +- 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 + + +Things to punt for later +------------------------ + +- SPL support - this will have to be present before many drivers can be +converted, but it seems like we can add it once we are happy with the +core implementation. +- Pre-relocation support - similar story + +That is not to say that no thinking has gone into these - in fact there +is quite a lot there. However, getting these right is non-trivial and +there is a high cost associated with going down the wrong path. + +For SPL, it may be possible to fit in a simplified driver model with only +bind and probe methods, to reduce size. + +For pre-relocation we can simply call the driver model init function. 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-relocatoin device pointers. + + +Simon Glass +sjg at chromium.org +April 2013 +Updated 7-May-13 +Updated 14-Jun-13
Signature · 1 line
1.8.3
PATCH v3 15/16 dm: Add README for driver model
Dear Simon Glass,
Quoted 30 lines
From: Pavel Herrmann <[email protected]>
This adds a README to help with understanding of this series.
Signed-off-by Simon Glass <[email protected]>---
Changes in v3:
- Updated README.txt to cover changes since version 2Changes in v2:
- Removed pointer return values in favour of integer
- Usedriver_bind()indm_init()instead of writing new code
- Allowdriver_bind()to support a NULL parent
- Adddm_warn()to warn about impending doom
- Standardise variable names (e.g. uclass instead of class)
- Remove relocation functions
- Add new header file for lists
- Add new util file to hold utility functions
- Allow a driver to bind to only one uclass
- Remove unneeded arguments touclass_bind(),uclass_unbind()
- Rename struct device's 'bus' to 'parent'
- Rename data structures to hopefully be clearer
- Putplatform_datadefinitions in their own header file
- AddU_BOOT_DEVICEto declareplatform_data
- Add auto-probing feature forplatform_datato avoiddriver_bind()calls
- Add simple unit test functions
- Add test infrastructure for driver model
- Add integration tests for driver model
- Add device tree support in driver model
- Add automatic allocation ofplatform_datafor FDT
Quoted 8 lines
- Add automatic allocation of priv data for devices
- Add automatic allocation of device-specific priv data for uclasses
- Add GPIO uclass and tests
- Add sandbox GPIO driver
- Update gpio command to use driver model
- Add tests for core code
- Add script to run tests
- Add a singleinclude/dm.hto bring in driver model code
You might _really_ want to reorder the readme in front of the actual DM patches.
Best regards,
Marek Vasut
PATCH v3 15/16 dm: Add README for driver model
Hi Marek,
Quoted 41 lines · Marek Vasut
Dear Simon Glass,
Quoted 30 lines
From: Pavel Herrmann <[email protected]>
This adds a README to help with understanding of this series.
Signed-off-by Simon Glass <[email protected]>---
Changes in v3:
- Updated README.txt to cover changes since version 2Changes in v2:
- Removed pointer return values in favour of integer
- Usedriver_bind()indm_init()instead of writing new code
- Allowdriver_bind()to support a NULL parent
- Adddm_warn()to warn about impending doom
- Standardise variable names (e.g. uclass instead of class)
- Remove relocation functions
- Add new header file for lists
- Add new util file to hold utility functions
- Allow a driver to bind to only one uclass
- Remove unneeded arguments touclass_bind(),uclass_unbind()
- Rename struct device's 'bus' to 'parent'
- Rename data structures to hopefully be clearer
- Putplatform_datadefinitions in their own header file
- AddU_BOOT_DEVICEto declareplatform_data
- Add auto-probing feature forplatform_datato avoiddriver_bind()calls
- Add simple unit test functions
- Add test infrastructure for driver model
- Add integration tests for driver model
- Add device tree support in driver model
- Add automatic allocation ofplatform_datafor FDTQuoted 8 lines
- Add automatic allocation of priv data for devices
- Add automatic allocation of device-specific priv data for uclasses
- Add GPIO uclass and tests
- Add sandbox GPIO driver
- Update gpio command to use driver model
- Add tests for core code
- Add script to run tests
- Add a singleinclude/dm.hto bring in driver model code
Quoted 3 lines
You might _really_ want to reorder the readme in front of the actual DM patches.
Will do.
Regards,
Simon
PATCH v3 16/16 dm: Move old driver model documentation into an 'old-docs' directory
In reply to Simon GlassThis documentation is still useful but is not fully correct with the API changes since the original driver model implementation. So move it into a separate directory, and create a README to describe what is going on.
This documentation pertains to the planned implementation of driver model in U-Boot for each subsystem. It is probably better to have this documentation in the source code for each subsystem where possible, so that docbook will pick it up. Where this does not make sense, new documentation can be placed in some suitable file in doc/driver-model.
---
Changes in v3:
- Add new patch to move driver model documentation
Changes in v2: None
doc/driver-model/old-docs/README | 29 ++++++++++++++++++++++++
doc/driver-model/{ => old-docs}/UDM-block.txt | 0
doc/driver-model/{ => old-docs}/UDM-cores.txt | 0
doc/driver-model/{ => old-docs}/UDM-design.txt | 0
doc/driver-model/{ => old-docs}/UDM-fpga.txt | 0
doc/driver-model/{ => old-docs}/UDM-gpio.txt | 0
doc/driver-model/{ => old-docs}/UDM-hwmon.txt | 0
doc/driver-model/{ => old-docs}/UDM-keyboard.txt | 0
doc/driver-model/{ => old-docs}/UDM-mmc.txt | 0
doc/driver-model/{ => old-docs}/UDM-net.txt | 0
doc/driver-model/{ => old-docs}/UDM-pci.txt | 0
doc/driver-model/{ => old-docs}/UDM-pcmcia.txt | 0
doc/driver-model/{ => old-docs}/UDM-power.txt | 0
doc/driver-model/{ => old-docs}/UDM-rtc.txt | 0
doc/driver-model/{ => old-docs}/UDM-serial.txt | 0
doc/driver-model/{ => old-docs}/UDM-spi.txt | 0
doc/driver-model/{ => old-docs}/UDM-stdio.txt | 0
doc/driver-model/{ => old-docs}/UDM-tpm.txt | 0
doc/driver-model/{ => old-docs}/UDM-twserial.txt | 0
doc/driver-model/{ => old-docs}/UDM-usb.txt | 0
doc/driver-model/{ => old-docs}/UDM-video.txt | 0
doc/driver-model/{ => old-docs}/UDM-watchdog.txt | 0
22 files changed, 29 insertions(+)
create mode 100644 doc/driver-model/old-docs/README
rename doc/driver-model/{ => old-docs}/UDM-block.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-cores.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-design.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-fpga.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-gpio.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-hwmon.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-keyboard.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-mmc.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-net.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-pci.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-pcmcia.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-power.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-rtc.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-serial.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-spi.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-stdio.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-tpm.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-twserial.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-usb.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-video.txt (100%)
rename doc/driver-model/{ => old-docs}/UDM-watchdog.txt (100%)doc/driver-model/old-docs/README new file +29 -0
@@ -0,0 +1,29 @@ +The U-Boot Driver Model Project +=============================== + +This directory contains the original driver model documents. The documents +are still useful and relevant, but some of the terminology has changed, +and some of the APIs are a little different. + +The changes (which are not reflected in the docs in this directory) are: + +- Tried to agressively 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 device +instead of struct instance, struct platform_data, 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 device'. +This removes a level of indirection that doesn't seem necessary. +- Built in device tree support, to avoid the need for platform_data +- 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
doc/driver-model/old-docs/UDM-block.txt renamed from doc/driver-model/UDM-block.txt +0 -0
doc/driver-model/old-docs/UDM-cores.txt renamed from doc/driver-model/UDM-cores.txt +0 -0
doc/driver-model/old-docs/UDM-design.txt renamed from doc/driver-model/UDM-design.txt +0 -0
doc/driver-model/old-docs/UDM-fpga.txt renamed from doc/driver-model/UDM-fpga.txt +0 -0
doc/driver-model/old-docs/UDM-gpio.txt renamed from doc/driver-model/UDM-gpio.txt +0 -0
doc/driver-model/old-docs/UDM-hwmon.txt renamed from doc/driver-model/UDM-hwmon.txt +0 -0
doc/driver-model/old-docs/UDM-keyboard.txt renamed from doc/driver-model/UDM-keyboard.txt +0 -0
doc/driver-model/old-docs/UDM-mmc.txt renamed from doc/driver-model/UDM-mmc.txt +0 -0
doc/driver-model/old-docs/UDM-net.txt renamed from doc/driver-model/UDM-net.txt +0 -0
doc/driver-model/old-docs/UDM-pci.txt renamed from doc/driver-model/UDM-pci.txt +0 -0
doc/driver-model/old-docs/UDM-pcmcia.txt renamed from doc/driver-model/UDM-pcmcia.txt +0 -0
doc/driver-model/old-docs/UDM-power.txt renamed from doc/driver-model/UDM-power.txt +0 -0
doc/driver-model/old-docs/UDM-rtc.txt renamed from doc/driver-model/UDM-rtc.txt +0 -0
doc/driver-model/old-docs/UDM-serial.txt renamed from doc/driver-model/UDM-serial.txt +0 -0
doc/driver-model/old-docs/UDM-spi.txt renamed from doc/driver-model/UDM-spi.txt +0 -0
doc/driver-model/old-docs/UDM-stdio.txt renamed from doc/driver-model/UDM-stdio.txt +0 -0
doc/driver-model/old-docs/UDM-tpm.txt renamed from doc/driver-model/UDM-tpm.txt +0 -0
doc/driver-model/old-docs/UDM-twserial.txt renamed from doc/driver-model/UDM-twserial.txt +0 -0
doc/driver-model/old-docs/UDM-usb.txt renamed from doc/driver-model/UDM-usb.txt +0 -0
doc/driver-model/old-docs/UDM-video.txt renamed from doc/driver-model/UDM-video.txt +0 -0
doc/driver-model/old-docs/UDM-watchdog.txt renamed from doc/driver-model/UDM-watchdog.txt +0 -0
Signature · 1 line
1.8.3