Merge branch 'master' of git://git.denx.de/u-boot-mips
authorTom Rini <trini@ti.com>
Tue, 4 Mar 2014 23:13:06 +0000 (18:13 -0500)
committerTom Rini <trini@ti.com>
Tue, 4 Mar 2014 23:13:06 +0000 (18:13 -0500)
186 files changed:
Makefile
README
arch/arc/config.mk
arch/arm/config.mk
arch/arm/cpu/armv7/kona-common/hwinit-common.c
arch/arm/cpu/armv7/omap-common/hwinit-common.c
arch/arm/cpu/armv7/omap4/hwinit.c
arch/arm/cpu/armv7/omap5/hwinit.c
arch/arm/cpu/at91-common/phy.c
arch/arm/include/asm/arch-davinci/hardware.h
arch/arm/include/asm/arch-mb86r0x/hardware.h
arch/arm/include/asm/arch-tnetv107x/hardware.h
arch/arm/include/asm/arch-zynq/sys_proto.h
arch/arm/include/asm/sizes.h [deleted file]
arch/avr32/config.mk
arch/blackfin/config.mk
arch/m68k/config.mk
arch/m68k/cpu/mcf5227x/config.mk
arch/m68k/cpu/mcf523x/config.mk
arch/m68k/cpu/mcf52x2/config.mk
arch/m68k/cpu/mcf532x/config.mk
arch/m68k/cpu/mcf5445x/config.mk
arch/m68k/cpu/mcf547x_8x/config.mk
arch/microblaze/config.mk
arch/mips/config.mk
arch/nds32/config.mk
arch/nios2/config.mk
arch/openrisc/config.mk
arch/powerpc/config.mk
arch/sandbox/config.mk
arch/sandbox/dts/Makefile [new file with mode: 0644]
arch/sandbox/dts/sandbox.dts [new file with mode: 0644]
arch/sandbox/include/asm/gpio.h
arch/sh/config.mk
arch/sh/cpu/sh2/config.mk
arch/sh/cpu/sh3/config.mk
arch/sh/cpu/sh4/config.mk
arch/sparc/config.mk
arch/x86/config.mk
board/BuS/vl_ma2sc/vl_ma2sc.c
board/atmel/at91sam9263ek/at91sam9263ek.c
board/compulab/cm_t335/spl.c
board/cray/L1/.gitignore [new file with mode: 0644]
board/freescale/m54418twr/config.mk
board/freescale/mx6slevk/mx6slevk.c
board/gaisler/gr_cpci_ax2000/config.mk
board/gaisler/gr_ep2s60/config.mk
board/gaisler/gr_xc3s_1500/config.mk
board/gaisler/grsim/config.mk
board/gaisler/grsim_leon2/config.mk
board/highbank/highbank.c
board/matrix_vision/mvblm7/.gitignore [new file with mode: 0644]
board/matrix_vision/mvsmr/.gitignore [new file with mode: 0644]
board/micronas/vct/config.mk
board/ronetix/pm9261/pm9261.c
board/ronetix/pm9263/pm9263.c
board/ronetix/pm9g45/pm9g45.c
board/samsung/common/misc.c
board/sandbox/sandbox/sandbox.c
board/synopsys/arcangel4/Makefile [deleted file]
board/wandboard/wandboard.c
board/xilinx/zynq/board.c
boards.cfg
common/Makefile
common/board_r.c
common/cmd_demo.c [new file with mode: 0644]
common/cmd_gpio.c
common/cmd_mem.c
common/command.c
config.mk
doc/driver-model/README.txt [new file with mode: 0644]
doc/driver-model/UDM-block.txt [deleted file]
doc/driver-model/UDM-cores.txt [deleted file]
doc/driver-model/UDM-design.txt [deleted file]
doc/driver-model/UDM-fpga.txt [deleted file]
doc/driver-model/UDM-gpio.txt [deleted file]
doc/driver-model/UDM-hwmon.txt [deleted file]
doc/driver-model/UDM-keyboard.txt [deleted file]
doc/driver-model/UDM-mmc.txt [deleted file]
doc/driver-model/UDM-net.txt [deleted file]
doc/driver-model/UDM-pci.txt [deleted file]
doc/driver-model/UDM-pcmcia.txt [deleted file]
doc/driver-model/UDM-power.txt [deleted file]
doc/driver-model/UDM-rtc.txt [deleted file]
doc/driver-model/UDM-serial.txt [deleted file]
doc/driver-model/UDM-spi.txt [deleted file]
doc/driver-model/UDM-stdio.txt [deleted file]
doc/driver-model/UDM-tpm.txt [deleted file]
doc/driver-model/UDM-twserial.txt [deleted file]
doc/driver-model/UDM-usb.txt [deleted file]
doc/driver-model/UDM-video.txt [deleted file]
doc/driver-model/UDM-watchdog.txt [deleted file]
drivers/core/Makefile [new file with mode: 0644]
drivers/core/device.c [new file with mode: 0644]
drivers/core/lists.c [new file with mode: 0644]
drivers/core/root.c [new file with mode: 0644]
drivers/core/uclass.c [new file with mode: 0644]
drivers/core/util.c [new file with mode: 0644]
drivers/demo/Makefile [new file with mode: 0644]
drivers/demo/demo-pdata.c [new file with mode: 0644]
drivers/demo/demo-shape.c [new file with mode: 0644]
drivers/demo/demo-simple.c [new file with mode: 0644]
drivers/demo/demo-uclass.c [new file with mode: 0644]
drivers/fpga/zynqpl.c
drivers/gpio/Makefile
drivers/gpio/at91_gpio.c
drivers/gpio/gpio-uclass.c [new file with mode: 0644]
drivers/gpio/sandbox.c
drivers/mmc/zynq_sdhci.c
drivers/net/xilinx_emaclite.c
drivers/net/zynq_gem.c
drivers/pci/pcie_imx.c
drivers/serial/serial_zynq.c
drivers/usb/gadget/f_thor.h
fs/yaffs2/yaffs_list.h [deleted file]
fs/yaffs2/ydirectenv.h
include/asm-generic/global_data.h
include/asm-generic/gpio.h
include/command.h
include/common.h
include/configs/at91rm9200ek.h
include/configs/bcm28155_ap.h
include/configs/beaver.h
include/configs/cardhu.h
include/configs/cpuat91.h
include/configs/dalmore.h
include/configs/devkit3250.h
include/configs/harmony.h
include/configs/hummingboard.h
include/configs/mx6sabre_common.h
include/configs/mx6slevk.h
include/configs/omap1510.h
include/configs/omap3_sdp3430.h
include/configs/paz00.h
include/configs/rpi_b.h
include/configs/sandbox.h
include/configs/sbc35_a9g20.h
include/configs/seaboard.h
include/configs/snapper9260.h
include/configs/tegra-common.h
include/configs/tnetv107x_evm.h
include/configs/trats.h
include/configs/trats2.h
include/configs/trimslice.h
include/configs/udoo.h
include/configs/venice2.h
include/configs/ventana.h
include/configs/wandboard.h
include/configs/whistler.h
include/configs/zynq-common.h
include/dm-demo.h [new file with mode: 0644]
include/dm.h [new file with mode: 0644]
include/dm/device-internal.h [new file with mode: 0644]
include/dm/device.h [new file with mode: 0644]
include/dm/lists.h [new file with mode: 0644]
include/dm/platdata.h [new file with mode: 0644]
include/dm/root.h [new file with mode: 0644]
include/dm/test.h [new file with mode: 0644]
include/dm/uclass-id.h [new file with mode: 0644]
include/dm/uclass-internal.h [new file with mode: 0644]
include/dm/uclass.h [new file with mode: 0644]
include/dm/ut.h [new file with mode: 0644]
include/dm/util.h [new file with mode: 0644]
include/linux/sizes.h [new file with mode: 0644]
include/netdev.h
include/usb/s3c_udc.h
lib/display_options.c
mkconfig
nand_spl/board/sheldon/simpc8313/Makefile
nand_spl/board/sheldon/simpc8313/config.mk [moved from board/sheldon/simpc8313/config.mk with 100% similarity]
post/lib_powerpc/fpu/Makefile
scripts/checkpatch.pl
spl/Makefile
test/dm/.gitignore [new file with mode: 0644]
test/dm/Makefile [new file with mode: 0644]
test/dm/cmd_dm.c [new file with mode: 0644]
test/dm/core.c [new file with mode: 0644]
test/dm/gpio.c [new file with mode: 0644]
test/dm/test-dm.sh [new file with mode: 0755]
test/dm/test-driver.c [new file with mode: 0644]
test/dm/test-fdt.c [new file with mode: 0644]
test/dm/test-main.c [new file with mode: 0644]
test/dm/test-uclass.c [new file with mode: 0644]
test/dm/test.dts [new file with mode: 0644]
test/dm/ut.c [new file with mode: 0644]
tools/Makefile

index 0281171..ecac292 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -489,8 +489,6 @@ endif
 # that (or fail if absent).  Otherwise, search for a linker script in a
 # standard location.
 
-LDSCRIPT_MAKEFILE_DIR = $(dir $(LDSCRIPT))
-
 ifndef LDSCRIPT
        #LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds.debug
        ifdef CONFIG_SYS_LDSCRIPT
@@ -515,8 +513,6 @@ ifndef LDSCRIPT
        endif
        ifeq ($(wildcard $(LDSCRIPT)),)
                LDSCRIPT := $(TOPDIR)/arch/$(ARCH)/cpu/u-boot.lds
-               # We don't expect a Makefile here
-               LDSCRIPT_MAKEFILE_DIR =
        endif
 endif
 
@@ -595,6 +591,7 @@ libs-y += fs/
 libs-y += net/
 libs-y += disk/
 libs-y += drivers/
+libs-$(CONFIG_DM) += drivers/core/
 libs-y += drivers/dma/
 libs-y += drivers/gpio/
 libs-y += drivers/i2c/
@@ -629,6 +626,8 @@ libs-y += lib/libfdt/
 libs-$(CONFIG_API) += api/
 libs-$(CONFIG_HAS_POST) += post/
 libs-y += test/
+libs-y += test/dm/
+libs-$(CONFIG_DM_DEMO) += drivers/demo/
 
 ifneq (,$(filter $(SOC), mx25 mx27 mx5 mx6 mx31 mx35 mxs vf610))
 libs-y += arch/$(ARCH)/imx-common/
@@ -637,7 +636,7 @@ endif
 libs-$(CONFIG_ARM) += arch/arm/cpu/
 libs-$(CONFIG_PPC) += arch/powerpc/cpu/
 
-libs-y += board/$(BOARDDIR)/
+libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/)
 
 libs-y := $(sort $(libs-y))
 
@@ -654,7 +653,7 @@ u-boot-main := $(libs-y)
 # Add GCC lib
 ifdef USE_PRIVATE_LIBGCC
 ifeq ("$(USE_PRIVATE_LIBGCC)", "yes")
-PLATFORM_LIBGCC = $(OBJTREE)/arch/$(ARCH)/lib/lib.a
+PLATFORM_LIBGCC = arch/$(ARCH)/lib/lib.a
 else
 PLATFORM_LIBGCC = -L $(USE_PRIVATE_LIBGCC) -lgcc
 endif
@@ -712,6 +711,7 @@ ALL-$(CONFIG_SPL) += spl/u-boot-spl.bin
 ALL-$(CONFIG_SPL_FRAMEWORK) += u-boot.img
 ALL-$(CONFIG_TPL) += tpl/u-boot-tpl.bin
 ALL-$(CONFIG_OF_SEPARATE) += u-boot.dtb u-boot-dtb.bin
+ALL-$(CONFIG_OF_HOSTFILE) += u-boot.dtb
 ifneq ($(CONFIG_SPL_TARGET),)
 ALL-$(CONFIG_SPL) += $(CONFIG_SPL_TARGET:"%"=%)
 endif
@@ -1067,6 +1067,13 @@ u-boot.lds: $(LDSCRIPT) prepare FORCE
 PHONY += nand_spl
 nand_spl: prepare
        $(Q)$(MAKE) $(build)=nand_spl/board/$(BOARDDIR) all
+       @echo >&2
+       @echo >&2 "==================== WARNING ====================="
+       @echo >&2 "nand_spl will not be included in v2014.07 release."
+       @echo >&2 "Please switch over to SPL."
+       @echo >&2 "Otherwise, this board will be removed."
+       @echo >&2 "=================================================="
+       @echo >&2
 
 nand_spl/u-boot-spl-16k.bin: nand_spl
        @:
@@ -1145,9 +1152,12 @@ checkarmreloc: u-boot
 env: scripts_basic
        $(Q)$(MAKE) $(build)=tools/$@
 
-tools-all: HOST_TOOLS_ALL=y
+tools-all: export HOST_TOOLS_ALL=y
 tools-all: env tools ;
 
+cross_tools: export CROSS_BUILD_TOOLS=y
+cross_tools: tools ;
+
 .PHONY : CHANGELOG
 CHANGELOG:
        git log --no-merges U-Boot-1_1_5.. | \
diff --git a/README b/README
index ff49260..216f0c7 100644 (file)
--- a/README
+++ b/README
@@ -3470,6 +3470,9 @@ typically in board_init_f() and board_init_r().
 Configuration Settings:
 -----------------------
 
+- CONFIG_SYS_SUPPORT_64BIT_DATA: Defined automatically if compiled as 64-bit.
+               Optionally it can be defined to support 64-bit memory commands.
+
 - CONFIG_SYS_LONGHELP: Defined when you want long help messages included;
                undefine this when you're short of memory.
 
index 76f4f7c..d9f5d9d 100644 (file)
@@ -9,14 +9,18 @@ CONFIG_SYS_LITTLE_ENDIAN = 1
 endif
 
 ifdef CONFIG_SYS_LITTLE_ENDIAN
-CROSS_COMPILE ?= arc-buildroot-linux-uclibc-
+ARC_CROSS_COMPILE := arc-buildroot-linux-uclibc-
 endif
 
 ifdef CONFIG_SYS_BIG_ENDIAN
-CROSS_COMPILE ?= arceb-buildroot-linux-uclibc-
+ARC_CROSS_COMPILE := arceb-buildroot-linux-uclibc-
 PLATFORM_LDFLAGS += -EB
 endif
 
+ifeq ($(CROSS_COMPILE),)
+CROSS_COMPILE := $(ARC_CROSS_COMPILE)
+endif
+
 PLATFORM_CPPFLAGS += -ffixed-r25 -D__ARC__ -DCONFIG_ARC -gdwarf-2
 
 LDSCRIPT := $(SRCTREE)/$(CPUDIR)/u-boot.lds
index 17b7408..792cb43 100644 (file)
@@ -5,7 +5,9 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-CROSS_COMPILE ?= arm-linux-
+ifeq ($(CROSS_COMPILE),)
+CROSS_COMPILE := arm-linux-
+endif
 
 ifndef CONFIG_STANDALONE_LOAD_ADDR
 ifneq ($(CONFIG_OMAP_COMMON),)
@@ -67,13 +69,8 @@ ifneq (,$(findstring -mabi=aapcs-linux,$(PLATFORM_CPPFLAGS)))
 # times. Also, the prefix needs to be different based on whether
 # CONFIG_SPL_BUILD is defined or not. 'filter-out' the existing entry
 # before adding the correct one.
-ifdef CONFIG_SPL_BUILD
-PLATFORM_LIBS := $(SPLTREE)/arch/arm/lib/eabi_compat.o \
-       $(filter-out %/arch/arm/lib/eabi_compat.o, $(PLATFORM_LIBS))
-else
-PLATFORM_LIBS := $(OBJTREE)/arch/arm/lib/eabi_compat.o \
-       $(filter-out %/arch/arm/lib/eabi_compat.o, $(PLATFORM_LIBS))
-endif
+PLATFORM_LIBS := arch/arm/lib/eabi_compat.o \
+       $(filter-out arch/arm/lib/eabi_compat.o, $(PLATFORM_LIBS))
 endif
 
 # needed for relocation
index f8b1e06..2b3a840 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #include <common.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #ifndef CONFIG_SYS_DCACHE_OFF
 void enable_caches(void)
index ade744e..8ebc0ce 100644 (file)
@@ -14,7 +14,7 @@
 #include <common.h>
 #include <spl.h>
 #include <asm/arch/sys_proto.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/emif.h>
 #include <asm/omap_common.h>
 #include <linux/compiler.h>
index b0598a0..db16548 100644 (file)
@@ -15,7 +15,7 @@
 #include <asm/armv7.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/sys_proto.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/emif.h>
 #include <asm/arch/gpio.h>
 #include <asm/omap_common.h>
index 737d23c..93feb16 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/arch/cpu.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/clock.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/utils.h>
 #include <asm/arch/gpio.h>
 #include <asm/emif.h>
index 3b6c60c..2cba716 100644 (file)
@@ -14,7 +14,7 @@
 
 #include <common.h>
 #include <asm/io.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/arch/at91_pmc.h>
 #include <asm/arch/at91_rstc.h>
 #include <watchdog.h>
index 27b1844..98fe56e 100644 (file)
@@ -15,7 +15,7 @@
 #define __ASM_ARCH_HARDWARE_H
 
 #include <config.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #define        REG(addr)       (*(volatile unsigned int *)(addr))
 #define REG_P(addr)    ((volatile unsigned int *)(addr))
index c0e3f20..42a52bc 100644 (file)
@@ -9,7 +9,7 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/arch/mb86r0x.h>
 
 #endif
index aed6c46..2a7ca4e 100644 (file)
@@ -9,7 +9,7 @@
 
 #ifndef __ASSEMBLY__
 
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #define ASYNC_EMIF_NUM_CS              4
 #define ASYNC_EMIF_MODE_NOR            0
index 0a2ba05..a68e1b3 100644 (file)
@@ -19,5 +19,6 @@ extern void zynq_ddrc_init(void);
 
 /* Driver extern functions */
 extern int zynq_sdhci_init(u32 regbase);
+extern int zynq_sdhci_of_init(const void *blob);
 
 #endif /* _SYS_PROTO_H_ */
diff --git a/arch/arm/include/asm/sizes.h b/arch/arm/include/asm/sizes.h
deleted file mode 100644 (file)
index 28cf5ea..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * SPDX-License-Identifier:    GPL-2.0+
- */
-/*  Size defintions
- *  Copyright (C) ARM Limited 1998. All rights reserved.
- */
-
-#ifndef __sizes_h
-#define __sizes_h                       1
-
-/* handy sizes */
-#define SZ_1K                           0x00000400
-#define SZ_4K                           0x00001000
-#define SZ_8K                           0x00002000
-#define SZ_16K                          0x00004000
-#define SZ_32K                          0x00008000
-#define SZ_64K                          0x00010000
-#define SZ_128K                         0x00020000
-#define SZ_256K                         0x00040000
-#define SZ_512K                         0x00080000
-
-#define SZ_1M                           0x00100000
-#define SZ_2M                           0x00200000
-#define SZ_4M                           0x00400000
-#define SZ_8M                           0x00800000
-#define SZ_16M                          0x01000000
-#define SZ_31M                          0x01F00000
-#define SZ_32M                          0x02000000
-#define SZ_64M                          0x04000000
-#define SZ_128M                         0x08000000
-#define SZ_256M                         0x10000000
-#define SZ_512M                         0x20000000
-
-#define SZ_1G                           0x40000000
-#define SZ_2G                           0x80000000
-
-#endif
-
-/*         END */
index b9b9631..28a371c 100644 (file)
@@ -5,7 +5,10 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-CROSS_COMPILE ?= avr32-linux-
+ifeq ($(CROSS_COMPILE),)
+CROSS_COMPILE := avr32-linux-
+endif
+
 PLATFORM_CPPFLAGS += -DCONFIG_AVR32
 CONFIG_STANDALONE_LOAD_ADDR ?= 0x00000000
 
index c752025..adc9712 100644 (file)
@@ -5,7 +5,9 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-CROSS_COMPILE ?= bfin-uclinux-
+ifeq ($(CROSS_COMPILE),)
+CROSS_COMPILE := bfin-uclinux-
+endif
 
 CONFIG_STANDALONE_LOAD_ADDR ?= 0x1000 -m elf32bfin
 
index 9c3e24f..33b3d51 100644 (file)
@@ -5,11 +5,14 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-CROSS_COMPILE ?= m68k-elf-
+ifeq ($(CROSS_COMPILE),)
+CROSS_COMPILE := m68k-elf-
+endif
 
 CONFIG_STANDALONE_LOAD_ADDR ?= 0x20000
 
 PLATFORM_CPPFLAGS += -DCONFIG_M68K -D__M68K__
 PLATFORM_LDFLAGS  += -n
-PLATFORM_RELFLAGS              += -ffunction-sections -fdata-sections
+PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections
+PLATFORM_RELFLAGS += -ffixed-d7 -msep-data
 LDFLAGS_FINAL                  += --gc-sections
index 2681171..b5c26e4 100644 (file)
@@ -7,5 +7,4 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-PLATFORM_RELFLAGS += -ffixed-d7 -msep-data
 PLATFORM_CPPFLAGS += -mcpu=52277 -fPIC
index 620769f..c9435ab 100644 (file)
@@ -7,5 +7,4 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-PLATFORM_RELFLAGS += -ffixed-d7 -msep-data
 PLATFORM_CPPFLAGS += -mcpu=5235 -fPIC
index d0be46f..25f98de 100644 (file)
@@ -7,8 +7,6 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-PLATFORM_RELFLAGS += -ffixed-d7 -msep-data
-
 cfg=$(shell grep configs $(OBJTREE)/include/config.h | sed 's/.*<\(configs.*\)>/\1/')
 is5208:=$(shell grep CONFIG_M5208 $(TOPDIR)/include/$(cfg))
 is5249:=$(shell grep CONFIG_M5249 $(TOPDIR)/include/$(cfg))
index be12203..0604ab0 100644 (file)
@@ -7,8 +7,6 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-PLATFORM_RELFLAGS += -ffixed-d7 -msep-data
-
 cfg=$(shell grep configs $(OBJTREE)/include/config.h | sed 's/.*<\(configs.*\)>/\1/')
 is5301x:=$(shell grep CONFIG_MCF5301x $(TOPDIR)/include/$(cfg))
 is532x:=$(shell grep CONFIG_MCF532x $(TOPDIR)/include/$(cfg))
index d546b22..6da08d5 100644 (file)
@@ -9,8 +9,6 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-PLATFORM_RELFLAGS += -ffixed-d7 -msep-data
-
 cfg=$(shell grep configs $(OBJTREE)/include/config.h | sed 's/.*<\(configs.*\)>/\1/')
 is5441x:=$(shell grep CONFIG_MCF5441x $(TOPDIR)/include/$(cfg))
 
index 345f584..825f6cc 100644 (file)
@@ -7,7 +7,6 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-PLATFORM_RELFLAGS += -ffixed-d7 -msep-data
 PLATFORM_CPPFLAGS += -mcpu=5485 -fPIC
 
 ifneq (,$(findstring -linux-,$(shell $(CC) --version)))
index fc545a9..cdb321a 100644 (file)
@@ -8,7 +8,9 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-CROSS_COMPILE ?= mb-
+ifeq ($(CROSS_COMPILE),)
+CROSS_COMPILE := mb-
+endif
 
 CONFIG_STANDALONE_LOAD_ADDR ?= 0x80F00000
 
index 2abdebb..1899f51 100644 (file)
@@ -5,7 +5,9 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-CROSS_COMPILE ?= mips_4KC-
+ifeq ($(CROSS_COMPILE),)
+CROSS_COMPILE := mips_4KC-
+endif
 
 # Handle special prefix in ELDK 4.0 toolchain
 ifneq (,$(findstring 4KCle,$(CROSS_COMPILE)))
index 550f8a4..0cbc4ad 100644 (file)
@@ -8,7 +8,9 @@
 #
 # SPDX-License-Identifier:     GPL-2.0+
 
-CROSS_COMPILE ?= nds32le-linux-
+ifeq ($(CROSS_COMPILE),)
+CROSS_COMPILE := nds32le-linux-
+endif
 
 CONFIG_STANDALONE_LOAD_ADDR = 0x300000 -T $(srctree)/$(src)/nds32.lds
 
index 7d546ef..65a5a40 100644 (file)
@@ -6,7 +6,9 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-CROSS_COMPILE ?= nios2-elf-
+ifeq ($(CROSS_COMPILE),)
+CROSS_COMPILE := nios2-elf-
+endif
 
 CONFIG_STANDALONE_LOAD_ADDR ?= 0x02000000
 
index 13015eb..981edff 100644 (file)
@@ -5,7 +5,9 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-CROSS_COMPILE ?= or32-elf-
+ifeq ($(CROSS_COMPILE),)
+CROSS_COMPILE := or32-elf-
+endif
 
 # r10 used for global object pointer, already set in OR32 GCC but just to be
 # clear
index f75c3bf..e398f97 100644 (file)
@@ -5,7 +5,9 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-CROSS_COMPILE ?= ppc_8xx-
+ifeq ($(CROSS_COMPILE),)
+CROSS_COMPILE := ppc_8xx-
+endif
 
 CONFIG_STANDALONE_LOAD_ADDR ?= 0x40000
 LDFLAGS_FINAL += --gc-sections
index 23b057e..668aa71 100644 (file)
@@ -11,3 +11,5 @@ __HAVE_ARCH_GENERIC_BOARD := y
 cmd_u-boot__ = $(CC) -o $@ -T u-boot.lds \
        -Wl,--start-group $(u-boot-main) -Wl,--end-group \
        $(PLATFORM_LIBS) -Wl,-Map -Wl,u-boot.map
+
+CONFIG_ARCH_DEVICE_TREE := sandbox
diff --git a/arch/sandbox/dts/Makefile b/arch/sandbox/dts/Makefile
new file mode 100644 (file)
index 0000000..a4c980b
--- /dev/null
@@ -0,0 +1,11 @@
+dtb-$(CONFIG_SANDBOX) += sandbox.dtb
+
+targets += $(dtb-y)
+
+DTC_FLAGS += -R 4 -p 0x1000
+
+PHONY += dtbs
+dtbs: $(addprefix $(obj)/, $(dtb-y))
+       @:
+
+clean-files := *.dtb
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
new file mode 100644 (file)
index 0000000..96a4438
--- /dev/null
@@ -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>;
+       };
+};
index afb9c78..95b59da 100644 (file)
@@ -29,7 +29,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)
@@ -38,7 +38,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)
@@ -46,7 +46,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)
@@ -55,11 +55,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
index 758c070..0578fa3 100644 (file)
@@ -5,7 +5,9 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-CROSS_COMPILE ?= sh4-linux-
+ifeq ($(CROSS_COMPILE),)
+CROSS_COMPILE := sh4-linux-
+endif
 
 CONFIG_STANDALONE_LOAD_ADDR ?= 0x8C000000
 ifeq ($(CPU),sh2)
@@ -15,3 +17,4 @@ endif
 PLATFORM_CPPFLAGS += -DCONFIG_SH -D__SH__
 PLATFORM_LDFLAGS += -e $(CONFIG_SYS_TEXT_BASE) --defsym reloc_dst=$(CONFIG_SYS_TEXT_BASE)
 LDFLAGS_FINAL = --gc-sections
+PLATFORM_RELFLAGS += -ffixed-r13
index 69273b4..4904d76 100644 (file)
@@ -8,11 +8,10 @@
 ENDIANNESS += -EB
 
 ifdef CONFIG_SH2A
-PLATFORM_CPPFLAGS += -m2a -m2a-nofpu -mb -ffreestanding
+PLATFORM_CPPFLAGS += -m2a -m2a-nofpu -mb
 else # SH2
 PLATFORM_CPPFLAGS += -m3e -mb
 endif
 PLATFORM_CPPFLAGS += -DCONFIG_SH2 $(call cc-option,-mno-fdpic)
 
-PLATFORM_RELFLAGS += -ffixed-r13
 PLATFORM_LDFLAGS += $(ENDIANNESS)
index abd4b8d..24b5c47 100644 (file)
@@ -12,4 +12,3 @@
 #
 #
 PLATFORM_CPPFLAGS += -DCONFIG_SH3 -m3
-PLATFORM_RELFLAGS += -ffixed-r13
index 753580b..5773d4f 100644 (file)
@@ -9,4 +9,3 @@
 #
 #
 PLATFORM_CPPFLAGS += -DCONFIG_SH4 -m4-nofpu
-PLATFORM_RELFLAGS += -ffixed-r13
index 9bb3724..e2327ec 100644 (file)
@@ -5,7 +5,9 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-CROSS_COMPILE ?= sparc-elf-
+ifeq ($(CROSS_COMPILE),)
+CROSS_COMPILE := sparc-elf-
+endif
 
 CONFIG_STANDALONE_LOAD_ADDR ?= 0x00000000 -L $(gcclibdir) \
                        -T $(srctree)/$(src)/sparc.lds
index 4a4ad80..58dff14 100644 (file)
@@ -8,13 +8,10 @@
 CONFIG_STANDALONE_LOAD_ADDR ?= 0x40000
 
 PLATFORM_CPPFLAGS += -fno-strict-aliasing
-PLATFORM_CPPFLAGS += -Wstrict-prototypes
 PLATFORM_CPPFLAGS += -mregparm=3
 PLATFORM_CPPFLAGS += -fomit-frame-pointer
-PF_CPPFLAGS_X86   := $(call cc-option, -ffreestanding) \
-                    $(call cc-option, -fno-toplevel-reorder, \
+PF_CPPFLAGS_X86   := $(call cc-option, -fno-toplevel-reorder, \
                       $(call cc-option, -fno-unit-at-a-time)) \
-                    $(call cc-option, -fno-stack-protector) \
                     $(call cc-option, -mpreferred-stack-boundary=2)
 PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_X86)
 PLATFORM_CPPFLAGS += -fno-dwarf2-cfi-asm
index 63f7ad9..da39c86 100644 (file)
@@ -8,7 +8,7 @@
 
 #include <config.h>
 #include <common.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <asm/arch/hardware.h>
index d42a173..7784cd7 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <common.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/arch/at91sam9263.h>
 #include <asm/arch/at91sam9_smc.h>
 #include <asm/arch/at91_common.h>
index b3b150a..d574364 100644 (file)
@@ -18,7 +18,7 @@
 #include <asm/arch/clocks_am33xx.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/hardware_am33xx.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 const struct ctrl_ioregs ioregs = {
        .cm0ioctl               = MT41J128MJT125_IOCTRL_VALUE,
diff --git a/board/cray/L1/.gitignore b/board/cray/L1/.gitignore
new file mode 100644 (file)
index 0000000..cd76d66
--- /dev/null
@@ -0,0 +1,2 @@
+bootscript.c
+bootscript.image
index b306d03..07f52e0 100644 (file)
@@ -4,6 +4,4 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp
-
 PLATFORM_CPPFLAGS += -DTEXT_BASE=$(CONFIG_SYS_TEXT_BASE)
index c496254..aadad32 100644 (file)
@@ -14,7 +14,7 @@
 #include <asm/gpio.h>
 #include <asm/imx-common/iomux-v3.h>
 #include <asm/io.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <common.h>
 #include <fsl_esdhc.h>
 #include <mmc.h>
index 309c879..731a539 100644 (file)
@@ -17,5 +17,3 @@ CONFIG_SYS_TEXT_BASE = 0x00000000
 
 # U-BOOT IN SDRAM
 #CONFIG_SYS_TEXT_BASE = 0x60000000
-
-PLATFORM_CPPFLAGS += -I$(TOPDIR)/board
index d57efae..6e01f07 100644 (file)
@@ -15,5 +15,3 @@ CONFIG_SYS_TEXT_BASE = 0x00000000
 
 # U-BOOT IN SDRAM
 #CONFIG_SYS_TEXT_BASE = 0x40000000
-
-PLATFORM_CPPFLAGS += -I$(TOPDIR)/board
index e87320b..e4a66cb 100644 (file)
@@ -14,5 +14,3 @@ CONFIG_SYS_TEXT_BASE = 0x00000000
 
 # U-BOOT IN RAM
 #CONFIG_SYS_TEXT_BASE = 0x40000000
-
-PLATFORM_CPPFLAGS += -I$(TOPDIR)/board
index df26f82..d1f61da 100644 (file)
@@ -14,5 +14,3 @@ CONFIG_SYS_TEXT_BASE = 0x00000000
 
 # U-BOOT IN RAM
 #CONFIG_SYS_TEXT_BASE = 0x40000000
-
-PLATFORM_CPPFLAGS += -I$(TOPDIR)/board
index 99f9a68..f98b23b 100644 (file)
@@ -14,5 +14,3 @@ CONFIG_SYS_TEXT_BASE = 0x00000000
 
 # RUN U-BOOT FROM RAM
 #CONFIG_SYS_TEXT_BASE = 0x40000000
-
-PLATFORM_CPPFLAGS += -I$(TOPDIR)/board
index 4b272c7..371b0a2 100644 (file)
@@ -9,7 +9,7 @@
 #include <netdev.h>
 #include <scsi.h>
 
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/io.h>
 
 #define HB_AHCI_BASE                   0xffe08000
diff --git a/board/matrix_vision/mvblm7/.gitignore b/board/matrix_vision/mvblm7/.gitignore
new file mode 100644 (file)
index 0000000..469f1bc
--- /dev/null
@@ -0,0 +1 @@
+bootscript.img
diff --git a/board/matrix_vision/mvsmr/.gitignore b/board/matrix_vision/mvsmr/.gitignore
new file mode 100644 (file)
index 0000000..469f1bc
--- /dev/null
@@ -0,0 +1 @@
+bootscript.img
index 0f004e0..354d918 100644 (file)
@@ -8,8 +8,6 @@
 # vct_xxx boards with MIPS 4Kc CPU core
 #
 
-sinclude $(TOPDIR)/board/$(BOARDDIR)/config.tmp
-
 ifndef CONFIG_SYS_TEXT_BASE
 CONFIG_SYS_TEXT_BASE = 0x87000000
 endif
index a634383..ec3ac89 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 #include <common.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <asm/arch/at91sam9_smc.h>
index 3cedeef..3aaffa8 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 #include <common.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <asm/arch/at91sam9_smc.h>
index c9f2747..15aa4ac 100644 (file)
@@ -12,7 +12,7 @@
  */
 
 #include <common.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <asm/arch/at91sam9_smc.h>
index eb15739..3ff4289 100644 (file)
@@ -11,7 +11,7 @@
 #include <samsung/misc.h>
 #include <errno.h>
 #include <version.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/gpio.h>
 #include <asm/gpio.h>
index 95efaff..2f90df5 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 #include <common.h>
-
+#include <dm.h>
 #include <os.h>
 
 /*
  */
 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)
 {
 }
diff --git a/board/synopsys/arcangel4/Makefile b/board/synopsys/arcangel4/Makefile
deleted file mode 100644 (file)
index 575e58f..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
-#
-# SPDX-License-Identifier:     GPL-2.0+
-#
-
-# This board is mostly used for debugging U-Boot in simulation (ISS).
-# The only peripheral which is used on this board is a serial port which
-# requires no initialization except those in "include/configs/arcangel4.h".
-# And now there's no specific initializations for this board.
-# So this Makefile is only required for satisfaction of U-Boot build system.
index 72e9bb2..0508457 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/imx-common/iomux-v3.h>
 #include <asm/imx-common/boot_mode.h>
 #include <asm/io.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <common.h>
 #include <fsl_esdhc.h>
 #include <ipu_pixfmt.h>
index 82f2345..485a5e4 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <fdtdec.h>
 #include <netdev.h>
 #include <zynqpl.h>
 #include <asm/arch/hardware.h>
@@ -134,8 +135,27 @@ int board_mmc_init(bd_t *bd)
 
 int dram_init(void)
 {
+#ifdef CONFIG_OF_CONTROL
+       int node;
+       fdt_addr_t addr;
+       fdt_size_t size;
+       const void *blob = gd->fdt_blob;
+
+       node = fdt_node_offset_by_prop_value(blob, -1, "device_type",
+                                            "memory", 7);
+       if (node == -FDT_ERR_NOTFOUND) {
+               debug("ZYNQ DRAM: Can't get memory node\n");
+               return -1;
+       }
+       addr = fdtdec_get_addr_size(blob, node, "reg", &size);
+       if (addr == FDT_ADDR_T_NONE || size == 0) {
+               debug("ZYNQ DRAM: Can't get base address or size\n");
+               return -1;
+       }
+       gd->ram_size = size;
+#else
        gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
-
+#endif
        zynq_ddrc_init();
 
        return 0;
index d28e09b..14cd151 100644 (file)
@@ -44,9 +44,9 @@
 ###########################################################################################################
 
 Active  aarch64     armv8          -           armltd          vexpress64          vexpress_aemv8a                      vexpress_aemv8a:ARM64                                                                                                             David Feng <fenghua@phytium.com.cn>
-Active  arc         arc700         -           synopsys        -                   arcangel4                            -                                                                                                                                 Alexey Brodkin <abrodkin@synopsys.com>
+Active  arc         arc700         -           synopsys        <none>              arcangel4                            -                                                                                                                                 Alexey Brodkin <abrodkin@synopsys.com>
 Active  arc         arc700         -           synopsys        -                   axs101                               -                                                                                                                                 Alexey Brodkin <abrodkin@synopsys.com>
-Active  arc         arc700         -           synopsys        arcangel4           arcangel4-be                         -                                                                                                                                 Alexey Brodkin <abrodkin@synopsys.com>
+Active  arc         arc700         -           synopsys        <none>              arcangel4-be                         -                                                                                                                                 Alexey Brodkin <abrodkin@synopsys.com>
 Active  arm         arm1136        -           armltd          integrator          integratorcp_cm1136                  integratorcp:CM1136                                                                                                               Linus Walleij <linus.walleij@linaro.org>
 Active  arm         arm1136        mx31        -               -                   imx31_phycore                        -                                                                                                                                 -
 Active  arm         arm1136        mx31        davedenx        -                   qong                                 -                                                                                                                                 Wolfgang Denk <wd@denx.de>
index ca9af13..04e9cdd 100644 (file)
@@ -64,6 +64,7 @@ obj-$(CONFIG_CMD_CONSOLE) += cmd_console.o
 obj-$(CONFIG_CMD_CPLBINFO) += cmd_cplbinfo.o
 obj-$(CONFIG_DATAFLASH_MMC_SELECT) += cmd_dataflash_mmc_mux.o
 obj-$(CONFIG_CMD_DATE) += cmd_date.o
+obj-$(CONFIG_CMD_DEMO) += cmd_demo.o
 obj-$(CONFIG_CMD_SOUND) += cmd_sound.o
 ifdef CONFIG_4xx
 obj-$(CONFIG_CMD_SETGETDCR) += cmd_dcr.o
index 899f377..8629a65 100644 (file)
@@ -18,6 +18,7 @@
 #ifdef CONFIG_HAS_DATAFLASH
 #include <dataflash.h>
 #endif
+#include <dm.h>
 #include <environment.h>
 #include <fdtdec.h>
 #if defined(CONFIG_CMD_IDE)
@@ -51,7 +52,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;
 
@@ -263,6 +266,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_platdata();
+       if (ret) {
+               debug("dm_scan_platdata() 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;
@@ -761,6 +791,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
diff --git a/common/cmd_demo.c b/common/cmd_demo.c
new file mode 100644 (file)
index 0000000..a3bba7f
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm-demo.h>
+#include <asm/io.h>
+
+struct device *demo_dev;
+
+static int do_demo_hello(cmd_tbl_t *cmdtp, int flag, int argc,
+                        char * const argv[])
+{
+       int ch = 0;
+
+       if (argc)
+               ch = *argv[0];
+
+       return demo_hello(demo_dev, ch);
+}
+
+static int do_demo_status(cmd_tbl_t *cmdtp, int flag, int argc,
+                         char * const argv[])
+{
+       int status;
+       int ret;
+
+       ret = demo_status(demo_dev, &status);
+       if (ret)
+               return ret;
+
+       printf("Status: %d\n", status);
+
+       return 0;
+}
+
+int do_demo_list(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       struct device *dev;
+       int i, ret;
+
+       puts("Demo uclass entries:\n");
+
+       for (i = 0, ret = uclass_first_device(UCLASS_DEMO, &dev);
+            dev;
+            ret = uclass_next_device(&dev)) {
+               printf("entry %d - instance %08x, ops %08x, platdata %08x\n",
+                      i++, map_to_sysmem(dev),
+                      map_to_sysmem(dev->driver->ops),
+                      map_to_sysmem(dev_get_platdata(dev)));
+       }
+
+       return cmd_process_error(cmdtp, ret);
+}
+
+static cmd_tbl_t demo_commands[] = {
+       U_BOOT_CMD_MKENT(list, 0, 1, do_demo_list, "", ""),
+       U_BOOT_CMD_MKENT(hello, 2, 1, do_demo_hello, "", ""),
+       U_BOOT_CMD_MKENT(status, 1, 1, do_demo_status, "", ""),
+};
+
+static int do_demo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       cmd_tbl_t *demo_cmd;
+       int devnum = 0;
+       int ret;
+
+       if (argc < 2)
+               return CMD_RET_USAGE;
+       demo_cmd = find_cmd_tbl(argv[1], demo_commands,
+                               ARRAY_SIZE(demo_commands));
+       argc -= 2;
+       argv += 2;
+       if (!demo_cmd || argc > demo_cmd->maxargs)
+               return CMD_RET_USAGE;
+
+       if (argc) {
+               devnum = simple_strtoul(argv[0], NULL, 10);
+               ret = uclass_get_device(UCLASS_DEMO, devnum, &demo_dev);
+               if (ret)
+                       return cmd_process_error(cmdtp, ret);
+               argc--;
+               argv++;
+       }
+
+       ret = demo_cmd->cmd(demo_cmd, flag, argc, argv);
+
+       return cmd_process_error(demo_cmd, ret);
+}
+
+U_BOOT_CMD(
+       demo,   4,      1,      do_demo,
+       "Driver model (dm) demo operations",
+       "list                     List available demo devices\n"
+       "demo hello <num> [<char>]     Say hello\n"
+       "demo status <num>             Get demo device status"
+);
index 47eee89..778aa5f 100644 (file)
@@ -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,23 @@ 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@chromium.org): For now we must fit into the existing GPIO
+        * framework, so we look up the name here and convert it to a GPIO number.
+        * Once all GPIO drivers are converted to driver model, we can change the
+        * code here 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 +186,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>]");
index 6d75d02..5b03c2d 100644 (file)
@@ -41,7 +41,7 @@ static        ulong   base_address = 0;
 /* Memory Display
  *
  * Syntax:
- *     md{.b, .w, .l} {addr} {len}
+ *     md{.b, .w, .l, .q} {addr} {len}
  */
 #define DISP_LINE_LEN  16
 static int do_mem_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
@@ -155,7 +155,12 @@ static int do_mem_nm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-       ulong   addr, writeval, count;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       u64 writeval;
+#else
+       ulong writeval;
+#endif
+       ulong   addr, count;
        int     size;
        void *buf;
        ulong bytes;
@@ -175,7 +180,11 @@ static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
        /* Get the value to write.
        */
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       writeval = simple_strtoull(argv[2], NULL, 16);
+#else
        writeval = simple_strtoul(argv[2], NULL, 16);
+#endif
 
        /* Count ? */
        if (argc == 4) {
@@ -189,6 +198,10 @@ static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        while (count-- > 0) {
                if (size == 4)
                        *((u32 *)buf) = (u32)writeval;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+               else if (size == 8)
+                       *((u64 *)buf) = (u64)writeval;
+#endif
                else if (size == 2)
                        *((u16 *)buf) = (u16)writeval;
                else
@@ -262,6 +275,11 @@ static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        int     rcode = 0;
        const char *type;
        const void *buf1, *buf2, *base;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       u64 word1, word2;
+#else
+       ulong word1, word2;
+#endif
 
        if (argc != 4)
                return CMD_RET_USAGE;
@@ -270,7 +288,9 @@ static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        */
        if ((size = cmd_get_data_size(argv[0], 4)) < 0)
                return 1;
-       type = size == 4 ? "word" : size == 2 ? "halfword" : "byte";
+       type = size == 8 ? "double word" :
+              size == 4 ? "word" :
+              size == 2 ? "halfword" : "byte";
 
        addr1 = simple_strtoul(argv[1], NULL, 16);
        addr1 += base_address;
@@ -298,10 +318,14 @@ static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        base = buf1 = map_sysmem(addr1, bytes);
        buf2 = map_sysmem(addr2, bytes);
        for (ngood = 0; ngood < count; ++ngood) {
-               ulong word1, word2;
                if (size == 4) {
                        word1 = *(u32 *)buf1;
                        word2 = *(u32 *)buf2;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+               } else if (size == 8) {
+                       word1 = *(u64 *)buf1;
+                       word2 = *(u64 *)buf2;
+#endif
                } else if (size == 2) {
                        word1 = *(u16 *)buf1;
                        word2 = *(u16 *)buf2;
@@ -311,10 +335,15 @@ static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                }
                if (word1 != word2) {
                        ulong offset = buf1 - base;
-
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+                       printf("%s at 0x%p (%#0*llx) != %s at 0x%p (%#0*llx)\n",
+                              type, (void *)(addr1 + offset), size, word1,
+                              type, (void *)(addr2 + offset), size, word2);
+#else
                        printf("%s at 0x%08lx (%#0*lx) != %s at 0x%08lx (%#0*lx)\n",
                                type, (ulong)(addr1 + offset), size, word1,
                                type, (ulong)(addr2 + offset), size, word2);
+#endif
                        rcode = 1;
                        break;
                }
@@ -434,6 +463,10 @@ static int do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        while (count-- > 0) {
                if (size == 4)
                        *((u32 *)buf) = *((u32  *)src);
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+               else if (size == 8)
+                       *((u64 *)buf) = *((u64 *)src);
+#endif
                else if (size == 2)
                        *((u16 *)buf) = *((u16 *)src);
                else
@@ -467,6 +500,9 @@ static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
 {
        ulong   addr, length, i, bytes;
        int     size;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       volatile u64 *llp;
+#endif
        volatile u32 *longp;
        volatile u16 *shortp;
        volatile u8 *cp;
@@ -497,6 +533,13 @@ static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
         * If we have only one object, just run infinite loops.
         */
        if (length == 1) {
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+               if (size == 8) {
+                       llp = (u64 *)buf;
+                       for (;;)
+                               i = *llp;
+               }
+#endif
                if (size == 4) {
                        longp = (u32 *)buf;
                        for (;;)
@@ -512,6 +555,16 @@ static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
                        i = *cp;
        }
 
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       if (size == 8) {
+               for (;;) {
+                       llp = (u64 *)buf;
+                       i = length;
+                       while (i-- > 0)
+                               *llp++;
+               }
+       }
+#endif
        if (size == 4) {
                for (;;) {
                        longp = (u32 *)buf;
@@ -542,8 +595,14 @@ static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
 #ifdef CONFIG_LOOPW
 int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-       ulong   addr, length, i, data, bytes;
+       ulong   addr, length, i, bytes;
        int     size;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       volatile u64 *llp;
+       u64 data;
+#else
+       ulong   data;
+#endif
        volatile u32 *longp;
        volatile u16 *shortp;
        volatile u8 *cp;
@@ -568,7 +627,11 @@ int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        length = simple_strtoul(argv[2], NULL, 16);
 
        /* data to write */
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       data = simple_strtoull(argv[3], NULL, 16);
+#else
        data = simple_strtoul(argv[3], NULL, 16);
+#endif
 
        bytes = size * length;
        buf = map_sysmem(addr, bytes);
@@ -577,11 +640,18 @@ int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
         * If we have only one object, just run infinite loops.
         */
        if (length == 1) {
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+               if (size == 8) {
+                       llp = (u64 *)buf;
+                       for (;;)
+                               *llp = data;
+               }
+#endif
                if (size == 4) {
                        longp = (u32 *)buf;
                        for (;;)
                                *longp = data;
-                                       }
+               }
                if (size == 2) {
                        shortp = (u16 *)buf;
                        for (;;)
@@ -592,6 +662,16 @@ int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                        *cp = data;
        }
 
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       if (size == 8) {
+               for (;;) {
+                       llp = (u64 *)buf;
+                       i = length;
+                       while (i-- > 0)
+                               *llp++ = data;
+               }
+       }
+#endif
        if (size == 4) {
                for (;;) {
                        longp = (u32 *)buf;
@@ -998,13 +1078,18 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc,
 /* Modify memory.
  *
  * Syntax:
- *     mm{.b, .w, .l} {addr}
- *     nm{.b, .w, .l} {addr}
+ *     mm{.b, .w, .l, .q} {addr}
+ *     nm{.b, .w, .l, .q} {addr}
  */
 static int
 mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
 {
-       ulong   addr, i;
+       ulong   addr;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       u64 i;
+#else
+       ulong i;
+#endif
        int     nbytes, size;
        void *ptr = NULL;
 
@@ -1055,6 +1140,10 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
                printf("%08lx:", addr);
                if (size == 4)
                        printf(" %08x", *((u32 *)ptr));
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+               else if (size == 8)
+                       printf(" %016llx", *((u64 *)ptr));
+#endif
                else if (size == 2)
                        printf(" %04x", *((u16 *)ptr));
                else
@@ -1079,7 +1168,11 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
 #endif
                else {
                        char *endp;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+                       i = simple_strtoull(console_buffer, &endp, 16);
+#else
                        i = simple_strtoul(console_buffer, &endp, 16);
+#endif
                        nbytes = endp - console_buffer;
                        if (nbytes) {
 #ifdef CONFIG_BOOT_RETRY_TIME
@@ -1089,6 +1182,10 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
 #endif
                                if (size == 4)
                                        *((u32 *)ptr) = i;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+                               else if (size == 8)
+                                       *((u64 *)ptr) = i;
+#endif
                                else if (size == 2)
                                        *((u16 *)ptr) = i;
                                else
@@ -1136,39 +1233,63 @@ static int do_mem_crc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 U_BOOT_CMD(
        md,     3,      1,      do_mem_md,
        "memory display",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       "[.b, .w, .l, .q] address [# of objects]"
+#else
        "[.b, .w, .l] address [# of objects]"
+#endif
 );
 
 
 U_BOOT_CMD(
        mm,     2,      1,      do_mem_mm,
        "memory modify (auto-incrementing address)",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       "[.b, .w, .l, .q] address"
+#else
        "[.b, .w, .l] address"
+#endif
 );
 
 
 U_BOOT_CMD(
        nm,     2,      1,      do_mem_nm,
        "memory modify (constant address)",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       "[.b, .w, .l, .q] address"
+#else
        "[.b, .w, .l] address"
+#endif
 );
 
 U_BOOT_CMD(
        mw,     4,      1,      do_mem_mw,
        "memory write (fill)",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       "[.b, .w, .l, .q] address value [count]"
+#else
        "[.b, .w, .l] address value [count]"
+#endif
 );
 
 U_BOOT_CMD(
        cp,     4,      1,      do_mem_cp,
        "memory copy",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       "[.b, .w, .l, .q] source target count"
+#else
        "[.b, .w, .l] source target count"
+#endif
 );
 
 U_BOOT_CMD(
        cmp,    4,      1,      do_mem_cmp,
        "memory compare",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       "[.b, .w, .l, .q] addr1 addr2 count"
+#else
        "[.b, .w, .l] addr1 addr2 count"
+#endif
 );
 
 #ifdef CONFIG_CMD_CRC32
@@ -1220,14 +1341,22 @@ U_BOOT_CMD(
 U_BOOT_CMD(
        loop,   3,      1,      do_mem_loop,
        "infinite loop on address range",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       "[.b, .w, .l, .q] address number_of_objects"
+#else
        "[.b, .w, .l] address number_of_objects"
+#endif
 );
 
 #ifdef CONFIG_LOOPW
 U_BOOT_CMD(
        loopw,  4,      1,      do_mem_loopw,
        "infinite write loop on address range",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       "[.b, .w, .l, .q] address number_of_objects data_to_write"
+#else
        "[.b, .w, .l] address number_of_objects data_to_write"
+#endif
 );
 #endif /* CONFIG_LOOPW */
 
@@ -1243,13 +1372,21 @@ U_BOOT_CMD(
 U_BOOT_CMD(
        mdc,    4,      1,      do_mem_mdc,
        "memory display cyclic",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       "[.b, .w, .l, .q] address count delay(ms)"
+#else
        "[.b, .w, .l] address count delay(ms)"
+#endif
 );
 
 U_BOOT_CMD(
        mwc,    4,      1,      do_mem_mwc,
        "memory write cyclic",
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+       "[.b, .w, .l, .q] address value delay(ms)"
+#else
        "[.b, .w, .l] address value delay(ms)"
+#endif
 );
 #endif /* CONFIG_MX_CYCLIC */
 
index 597ab4c..746b7e3 100644 (file)
@@ -421,6 +421,10 @@ int cmd_get_data_size(char* arg, int default_size)
                        return 2;
                case 'l':
                        return 4;
+#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA
+               case 'q':
+                       return 8;
+#endif
                case 's':
                        return -2;
                default:
@@ -538,3 +542,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;
+}
index 9897f20..af25c11 100644 (file)
--- a/config.mk
+++ b/config.mk
@@ -28,11 +28,13 @@ sinclude $(TOPDIR)/$(CPUDIR)/config.mk              # include  CPU  specific rules
 ifdef  SOC
 sinclude $(TOPDIR)/$(CPUDIR)/$(SOC)/config.mk  # include  SoC  specific rules
 endif
+ifneq ($(BOARD),)
 ifdef  VENDOR
 BOARDDIR = $(VENDOR)/$(BOARD)
 else
 BOARDDIR = $(BOARD)
 endif
+endif
 ifdef  BOARD
 sinclude $(TOPDIR)/board/$(BOARDDIR)/config.mk # include board specific rules
 endif
@@ -46,7 +48,5 @@ OBJCOPYFLAGS += --gap-fill=0xff
 CPPFLAGS = $(RELFLAGS)
 CPPFLAGS += -pipe $(PLATFORM_CPPFLAGS)
 
-BCURDIR = $(subst $(SRCTREE)/,,$(CURDIR:$(obj)%=%))
-
 LDFLAGS += $(PLATFORM_LDFLAGS)
 LDFLAGS_FINAL += -Bstatic
diff --git a/doc/driver-model/README.txt b/doc/driver-model/README.txt
new file mode 100644 (file)
index 0000000..e0b395a
--- /dev/null
@@ -0,0 +1,368 @@
+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 <marex@denx.de>
+   Pavel Herrmann <morpheus.ibis@gmail.com>
+   Viktor Křivák <viktor.krivak@gmail.com>
+   Tomas Hlavacek <tmshlvck@gmail.com>
+
+This has been both simplified and extended into the current implementation
+by:
+
+   Simon Glass <sjg@chromium.org>
+
+
+Terminology
+-----------
+
+Uclass - a group of devices 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 good code coverage of them. It does have multiple drivers, it
+handles parameter data and platdata (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
+
+You should see something like this:
+
+    <...U-Boot banner...>
+    Running 12 driver model tests
+    Test: dm_test_autobind
+    Test: dm_test_autoprobe
+    Test: dm_test_children
+    Test: dm_test_fdt
+    Test: dm_test_gpio
+    sandbox_gpio: sb_gpio_get_value: error: offset 4 not reserved
+    Test: dm_test_leak
+    Warning: Please add '#define DEBUG' to the top of common/dlmalloc.c
+    Warning: Please add '#define DEBUG' to the top of common/dlmalloc.c
+    Test: dm_test_lifecycle
+    Test: dm_test_operations
+    Test: dm_test_ordering
+    Test: dm_test_platdata
+    Test: dm_test_remove
+    Test: dm_test_uclass
+    Failures: 0
+
+(You can add '#define DEBUG' as suggested to check for memory leaks)
+
+
+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, devnum, &demo_dev);
+
+UCLASS_DEMO means the class of devices which implement 'demo'. Other
+classes might be MMC, or GPIO, hashing or serial. The idea is that the
+devices in the class all share a particular way of working. The class
+presents a unified view of all these devices to U-Boot.
+
+This function looks up a device for the demo uclass. Given a device
+number we can find the device because all devices have registered with
+the UCLASS_DEMO uclass.
+
+The device is automatically activated ready for use by uclass_get_device().
+
+Now that we have the device we can do things like:
+
+       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_get_platdata(dev);
+
+       printf("Hello from %08x: %s %d\n", map_to_sysmem(dev),
+              pdata->colour, pdata->sides);
+
+       return 0;
+}
+
+
+So that is a trip from top (command execution) to bottom (driver action)
+but it leaves a lot of topics to address.
+
+
+Declaring Drivers
+-----------------
+
+A driver declaration looks something like this (see
+drivers/demo/demo-shape.c):
+
+static const struct demo_ops shape_ops = {
+       .hello = shape_hello,
+       .status = shape_status,
+};
+
+U_BOOT_DRIVER(demo_shape_drv) = {
+       .name   = "demo_shape_drv",
+       .id     = UCLASS_DEMO,
+       .ops    = &shape_ops,
+       .priv_data_size = sizeof(struct shape_data),
+};
+
+
+This driver has two methods (hello and status) and requires a bit of
+private data (accessible through dev_get_priv(dev) once the driver has
+been probed). It is a member of UCLASS_DEMO so will register itself
+there.
+
+In U_BOOT_DRIVER it is also possible to specify special methods for bind
+and unbind, and these are called at appropriate times. For many drivers
+it is hoped that only 'probe' and 'remove' will be needed.
+
+The U_BOOT_DRIVER macro creates a data structure accessible from C,
+so driver model can find the drivers that are available.
+
+The methods a device can provide are documented in the device.h header.
+Briefly, they are:
+
+    bind - make the driver model aware of a device (bind it to its driver)
+    unbind - make the driver model forget the device
+    ofdata_to_platdata - convert device tree data to platdata - see later
+    probe - make a device ready for use
+    remove - remove a device so it cannot be used until probed again
+
+The sequence to get a device to work is bind, ofdata_to_platdata (if using
+device tree) and probe.
+
+
+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->platdata. 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",
+                       .platdata = &red_square,
+               },
+       };
+
+       demo1 = driver_bind(root, &info[0]);
+
+
+Device Tree
+-----------
+
+While platdata 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 tree fragment:
+
+       red-square {
+               compatible = "demo-shape";
+               colour = "red";
+               sides = <4>;
+       };
+
+
+The easiest way to make this work it to add a few members to the driver:
+
+       .platdata_auto_alloc_size = sizeof(struct dm_test_pdata),
+       .ofdata_to_platdata = testfdt_ofdata_to_platdata,
+       .probe  = testfdt_drv_probe,
+
+The 'auto_alloc' feature allowed space for the platdata to be allocated
+and zeroed before the driver's ofdata_to_platdata method is called. This
+method reads the information out of the device tree and puts it in
+dev->platdata. Then the probe method is called to set up the device.
+
+Note that both methods are optional. If you provide an ofdata_to_platdata
+method then it wlil be called first (after bind). If you provide a probe
+method it will be called next.
+
+If you don't want to have the platdata automatically allocated then you
+can leave out platdata_auto_alloc_size. In this case you can use malloc
+in your ofdata_to_platdata (or probe) method to allocate the required memory,
+and you should free it in the remove method.
+
+
+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 platdata, 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 platdata
+- 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-relocation device pointers.
+
+Uclasses are statically numbered at compile time. It would be possible to
+change this to dynamic numbering, but then we would require some sort of
+lookup service, perhaps searching by name. This is slightly less efficient
+so has been left out for now. One small advantage of dynamic numbering might
+be fewer merge conflicts in uclass-id.h.
+
+
+Simon Glass
+sjg@chromium.org
+April 2013
+Updated 7-May-13
+Updated 14-Jun-13
+Updated 18-Oct-13
+Updated 5-Nov-13
diff --git a/doc/driver-model/UDM-block.txt b/doc/driver-model/UDM-block.txt
deleted file mode 100644 (file)
index 0437d9b..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-Block device subsystem analysis
-===============================
-
-Pavel Herrmann <morpheus.ibis@gmail.com>
-2012-03-08
-
-I) Overview
------------
-
-  U-Boot currently implements several distinct APIs for block devices - some
-  drivers use the SATA API, some drivers use the IDE API, sym53c8xx and
-  AHCI use the SCSI API, mg_disk has a separate API, and systemace also has a
-  separate API. There are also MMC and USB APIs used outside of drivers/block,
-  those will be detailed in their specific documents.
-
-  Block devices are described by block_dev_desc structure, that holds, among
-  other things, the read/write/erase callbacks. Block device structures are
-  stored in any way depending on the API, but can be accessed by
-
-    block_dev_desc_t * $api_get_dev(int dev)
-
-  function, as seen in disk/part.c.
-
-  1) SATA interface
-  -----------------
-
-    The SATA interface drivers implement the following functions:
-
-      int   init_sata(int dev)
-      int   scan_sata(int dev)
-      ulong sata_read(int dev, ulong blknr, ulong blkcnt, void *buffer)
-      ulong sata_write(int dev, ulong blknr, ulong blkcnt, const void *buffer)
-
-    Block devices are kept in sata_dev_desc[], which is prefilled with values
-    common to all SATA devices in cmd_sata.c, and then modified in init_sata
-    function in the drivers. Callbacks of the block device use SATA API
-    directly. The sata_get_dev function is defined in cmd_sata.c.
-
-  2) SCSI interface
-  -----------------
-
-    The SCSI interface drivers implement the following functions:
-
-      void scsi_print_error(ccb *pccb)
-      int  scsi_exec(ccb *pccb)
-      void scsi_bus_reset(void)
-      void scsi_low_level_init(int busdevfunc)
-
-    The SCSI API works through the scsi_exec function, the actual operation
-    requested is found in the ccb structure.
-
-    Block devices are kept in scsi_dev_desc[], which lives only in cmd_scsi.c.
-    Callbacks of the block device use functions from cmd_scsi.c, which in turn
-    call scsi_exec of the controller. The scsi_get_dev function is also defined
-    in cmd_scsi.c.
-
-  3) mg_disk interface
-  --------------------
-
-    The mg_disk interface drivers implement the following functions:
-
-      struct mg_drv_data* mg_get_drv_data (void)
-      uint   mg_disk_init (void)
-      uint   mg_disk_read (u32 addr, u8 *buff, u32 len)
-      uint   mg_disk_write(u32 addr, u8 *buff, u32 len)
-      uint   mg_disk_write_sects(void *buff, u32 sect_num, u32 sect_cnt)
-      uint   mg_disk_read_sects(void *buff, u32 sect_num, u32 sect_cnt)
-
-    The mg_get_drv_data function is to be overridden per-board, but there are no
-    board in-tree that do this.
-
-    Only one driver for this API exists, and it only supports one block device.
-    Callbacks for this device are implemented in mg_disk.c and call the mg_disk
-    API. The mg_disk_get_dev function is defined in mg_disk.c and ignores the
-    device number, always returning the same device.
-
-  4) systemace interface
-  ----------------------
-
-    The systemace interface does not define any driver API, and has no command
-    itself. The single defined function is systemace_get_devs() from
-    systemace.c, which returns a single static structure for the only supported
-    block device. Callbacks for this device are also implemented in systemace.c.
-
-  5) IDE interface
-  ----------------
-
-    The IDE interface drivers implement the following functions, but only if
-    CONFIG_IDE_AHB is set:
-
-      uchar ide_read_register(int dev, unsigned int port);
-      void  ide_write_register(int dev, unsigned int port, unsigned char val);
-      void  ide_read_data(int dev, ulong *sect_buf, int words);
-      void  ide_write_data(int dev, const ulong *sect_buf, int words);
-
-    The first two functions are called from ide_inb()/ide_outb(), and will
-    default to direct memory access if CONFIG_IDE_AHB is not set, or
-    ide_inb()/ide_outb() functions will get overridden by the board altogether.
-
-    The second two functions are called from input_data()/output_data()
-    functions, and also default to direct memory access, but cannot be
-    overridden by the board.
-
-    One function shared by IDE drivers (but not defined in ide.h) is
-      int ide_preinit(void)
-    This function gets called from ide_init in cmd_ide.c if CONFIG_IDE_PREINIT
-    is defined, and will do the driver-specific initialization of the device.
-
-    Block devices are kept in ide_dev_desc[], which is filled in cmd_ide.c.
-    Callbacks of the block device are defined in cmd_ide.c, and use the
-    ide_inb()/ide_outb()/input_data()/output_data() functions mentioned above.
-    The ide_get_dev function is defined in cmd_ide.c.
-
-II) Approach
-------------
-
-  A new block controller core and an associated API will be created to mimic the
-  current SATA API, its drivers will have the following ops:
-
-  struct block_ctrl_ops {
-    int scan(instance *i);
-    int reset(instance *i, int port);
-    lbaint_t read(instance *i, int port, lbaint_t start, lbatin_t length,
-                 void *buffer);
-    lbaint_t write(instance *i, int port, lbaint_t start, lbatin_t length,
-                  void*buffer);
-  }
-
-  The current sata_init() function will be changed into the driver probe()
-  function. The read() and write() functions should never be called directly,
-  instead they should be called by block device driver for disks.
-
-  Other block APIs would either be transformed into this API, or be kept as
-  legacy for old drivers, or be dropped altogether.
-
-  Legacy driver APIs will each have its own driver core that will contain the
-  shared logic, which is currently located mostly in cmd_* files. Callbacks for
-  block device drivers will then probably be implemented as a part of the core
-  logic, and will use the driver ops (which will copy current state of
-  respective APIs) to do the work.
-
-  All drivers will be cleaned up, most ifdefs should be converted into
-  platform_data, to enable support for multiple devices with different settings.
-
-  A new block device core will also be created, and will keep track of all
-  block devices on all interfaces.
-
-  Current block_dev_desc structure will be changed to fit the driver model, all
-  identification and configuration will be placed in private data, and
-  a single accessor and modifier will be defined, to accommodate the need for
-  different sets of options for different interfaces, while keeping the
-  structure small. The new block device drivers will have the following ops
-  structure (lbaint_t is either 32bit or 64bit unsigned, depending on
-  CONFIG_LBA48):
-
-  struct blockdev_ops {
-    lbaint_t (*block_read)(struct instance *i, lbaint_t start, lbaint_t blkcnt,
-                          void *buffer);
-    lbaint_t (*block_write)(struct instance *i, lbaint_t start, lbaint_t blkcnt,
-                           void *buffer);
-    lbaint_t (*block_erase)(struct instance *i, lbaint_t start, lbaint_t blkcnt
-                           );
-    int             (*get_option)(struct instance *i, enum blockdev_option_code op,
-                          struct option *res);
-    int             (*set_option)(struct instance *i, enum blockdev_option_code op,
-                          struct option *val);
-  }
-
-  struct option {
-    uint32_t flags
-    union data {
-      uint64_t data_u;
-      char*    data_s;
-      void*    data_p;
-    }
-  }
-
-  enum blockdev_option_code {
-    BLKD_OPT_IFTYPE=0,
-    BLKD_OPT_TYPE,
-    BLKD_OPT_BLOCKSIZE,
-    BLKD_OPT_BLOCKCOUNT,
-    BLKD_OPT_REMOVABLE,
-    BLKD_OPT_LBA48,
-    BLKD_OPT_VENDOR,
-    BLKD_OPT_PRODICT,
-    BLKD_OPT_REVISION,
-    BLKD_OPT_SCSILUN,
-    BLKD_OPT_SCSITARGET,
-    BLKD_OPT_OFFSET
-  }
-
-  Flags in option above will contain the type of returned data (which should be
-  checked against what is expected, even though the option requested should
-  specify it), and a flag to indicate whether the returned pointer needs to be
-  free()'d.
-
-  The block device core will contain the logic now located in disk/part.c and
-  related files, and will be used to forward requests to block devices. The API
-  for the block device core will copy the ops of a block device (with a string
-  identifier instead of instance pointer). This means that partitions will also
-  be handled by the block device core, and exported as block devices, making
-  them transparent to the rest of the code.
-
-  Sadly, this will change how file systems can access the devices, and thus will
-  affect a lot of places. However, these changes should be localized and easy to
-  implement.
-
-  AHCI driver will be rewritten to fit the new unified block controller API,
-  making SCSI API easy to merge with sym53c8xx, or remove it once the device
-  driver has died.
-
-  Optionally, IDE core may be changed into one driver with unified block
-  controller API, as most of it is already in one place and device drivers are
-  just sets of hooks. Additionally, mg_disk driver is unused and may be removed
-  in near future.
-
-
-III) Analysis of in-tree drivers
---------------------------------
-
-  ahci.c
-  ------
-    SCSI API, will be rewritten for a different API.
-
-  ata_piix.c
-  ----------
-    SATA API, easy to port.
-
-  fsl_sata.c
-  ----------
-    SATA API, few CONFIG macros, easy to port.
-
-  ftide020.c
-  ----------
-    IDE API, defines CONFIG_IDE_AHB and ide_preinit hook functions.
-
-  mg_disk.c
-  ---------
-    Single driver with mg_disk API, not much to change, easy to port.
-
-  mvsata_ide.c
-  ------------
-    IDE API, only defines ide_preinit hook function.
-
-  mxc_ata.c
-  ---------
-    IDE API, only defines ide_preinit hook function.
-
-  pata_bfin.c
-  -----------
-    SATA API, easy to port.
-
-  sata_dwc.c
-  ----------
-    SATA API, easy to port.
-
-  sata_sil3114.c
-  --------------
-    SATA API, easy to port.
-
-  sata_sil.c
-  ----------
-    SATA API, easy to port.
-
-  sil680.c
-  --------
-    IDE API, only defines ide_preinit hook function.
-
-  sym53c8xx.c
-  -----------
-    SCSI API, may be merged with code from cmd_scsi.
-
-  systemace.c
-  -----------
-    Single driver with systemace API, not much to change, easy to port.
diff --git a/doc/driver-model/UDM-cores.txt b/doc/driver-model/UDM-cores.txt
deleted file mode 100644 (file)
index 6032333..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-Driver cores API document
-=========================
-
-Pavel Herrmann <morpheus.ibis@gmail.com>
-
-1) Overview
------------
-  Driver cores will be used as a wrapper for devices of the same type, and as
-  an abstraction for device driver APIs. For each driver API (which roughly
-  correspond to device types), there will be one driver core. Each driver core
-  will implement three APIs - a driver API (which will be the same as API of
-  drivers the core wraps around), a core API (which will be implemented by all
-  cores) and a command API (core-specific API which will be exposed to
-  commands).
-
-  A) Command API
-    The command API will provide access to shared functionality for a specific
-    device, which is currently located mostly in commands. Commands will be
-    rewritten to be more lightweight by using this API. As this API will be
-    different for each core, it is out of scope of this document.
-
-  B) Driver API
-    The driver API will act as a wrapper around actual device drivers,
-    providing a single entrypoint for device access. All functions in this API
-    have an instance* argument (probably called "this" or "i"), which will be
-    examined by the core, and a correct function for the specified driver will
-    get called.
-
-    If the core gets called with a group instance pointer (as discussed in
-    design), it will automatically select the instance that is associated
-    with this core, and use it as target of the call. if the group contains
-    multiple instances of a single type, the caller must explicitly use an
-    accessor to select the correct instance.
-
-    This accessor will look like:
-      struct instance *get_instance_from_group(struct instance *group, int i)
-
-    When called with a non-group instance, it will simply return the instance.
-
-  C) Core API
-    The core API will be implemented by all cores, and will provide
-    functionality for getting driver instances from non-driver code. This API
-    will consist of following functions:
-
-      int get_count(struct instance *core);
-      struct instance* get_instance(struct instance *core, int index);
-      int init(struct instance *core);
-      int bind(struct instance *core, struct instance *dev, void *ops,
-              void *hint);
-      int unbind(struct instance *core, instance *dev);
-      int replace(struct instance *core, struct_instance *new_dev,
-                 struct instance *old_dev);
-      int destroy(struct instance *core);
-      int reloc(struct instance *new_core, struct instance *old_core);
-
-      The 'hint' parameter of bind() serves for additional data a driver can
-      pass to the core, to help it create the correct internal state for this
-      instance. the replace() function will get called during instance
-      relocation, and will replace the old instance with the new one, keeping
-      the internal state untouched.
-
-
-2) Lifetime of a driver core
-----------------------------
-  Driver cores will be initialized at runtime, to limit memory footprint in
-  early-init stage, when we have to fit into ~1KB of memory. All active cores
-  will be stored in a tree structure (referenced as "Core tree") in global data,
-  which provides good tradeoff between size and access time.
-  Every core will have a number constant associated with it, which will be used
-  to find the instance in Core tree, and to refer to the core in all calls
-  working with the Core tree.
-  The Core Tree should be implemented using B-tree (or a similar structure)
-  to guarantee acceptable time overhead in all cases.
-
-  Code for working with the core (i2c in this example) follows:
-
-    core_init(CORE_I2C);
-      This will check whether we already have a i2c core, and if not it creates
-      a new instance and adds it into the Core tree. This will not be exported,
-      all code should depend on get_core_instance to init the core when
-      necessary.
-
-    get_core_instance(CORE_I2C);
-      This is an accessor into the Core tree, which will return the instance
-      of i2c core, creating it if necessary
-
-    core_bind(CORE_I2C, instance, driver_ops);
-      This will get called in bind() function of a driver, and will add the
-      instance into cores internal list of devices. If the core is not found, it
-      will get created.
-
-    driver_activate(instance *inst);
-      This call will recursively activate all devices necessary for using the
-      specified device. the code could be simplified as:
-       {
-       if (is_activated(inst))
-         return;
-       driver_activate(inst->bus);
-       get_driver(inst)->probe(inst);
-       }
-
-      The case with multiple parents will need to be handled here as well.
-      get_driver is an accessor to available drivers, which will get struct
-      driver based on a name in the instance.
-
-    i2c_write(instance *inst, ...);
-      An actual call to some method of the driver. This code will look like:
-       {
-       driver_activate(inst);
-       struct instance *core = get_core_instance(CORE_I2C);
-       device_ops = get_ops(inst);
-       device_ops->write(...);
-       }
-
-      get_ops will not be an exported function, it will be internal and specific
-      to the core, as it needs to know how are the ops stored, and what type
-      they are.
-
-  Please note that above examples represent the algorithm, not the actual code,
-  as they are missing checks for validity of return values.
-
-  core_init() function will get called the first time the core is requested,
-  either by core_link() or core_get_instance(). This way, the cores will get
-  created only when they are necessary, which will reduce our memory footprint.
diff --git a/doc/driver-model/UDM-design.txt b/doc/driver-model/UDM-design.txt
deleted file mode 100644 (file)
index 9f03bba..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-Design document
-===============
-Marek Vasut <marek.vasut@gmail.com>
-Pavel Herrmann <morpheus.ibis@gmail.com>
-2012-05-17
-
-I) The modular concept
-----------------------
-
-The driver core design is done with modularity in mind. The long-term plan is to
-extend this modularity to allow loading not only drivers, but various other
-objects into U-Boot at runtime -- like commands, support for other boards etc.
-
-II) Driver core initialization stages
--------------------------------------
-
-The drivers have to be initialized in two stages, since the U-Boot bootloader
-runs in two stages itself. The first stage is the one which is executed before
-the bootloader itself is relocated. The second stage then happens after
-relocation.
-
-  1) First stage
-  --------------
-
-  The first stage runs after the bootloader did very basic hardware init. This
-  means the stack pointer was configured, caches disabled and that's about it.
-  The problem with this part is the memory management isn't running at all. To
-  make things even worse, at this point, the RAM is still likely uninitialized
-  and therefore unavailable.
-
-  2) Second stage
-  ---------------
-
-  At this stage, the bootloader has initialized RAM and is running from it's
-  final location. Dynamic memory allocations are working at this point. Most of
-  the driver initialization is executed here.
-
-III) The drivers
-----------------
-
-  1) The structure of a driver
-  ----------------------------
-
-  The driver will contain a structure located in a separate section, which
-  will allow linker to create a list of compiled-in drivers at compile time.
-  Let's call this list "driver_list".
-
-  struct driver __attribute__((section(driver_list))) {
-    /* The name of the driver */
-    char               name[STATIC_CONFIG_DRIVER_NAME_LENGTH];
-
-    /*
-     * This function should connect this driver with cores it depends on and
-     * with other drivers, likely bus drivers
-     */
-    int                        (*bind)(struct instance *i);
-
-    /* This function actually initializes the hardware. */
-    int                        (*probe)(struct instance *i);
-
-    /*
-     * The function of the driver called when U-Boot finished relocation.
-     * This is particularly important to eg. move pointers to DMA buffers
-     * and such from the location before relocation to their final location.
-     */
-    int                        (*reloc)(struct instance *i);
-
-    /*
-     * This is called when the driver is shuting down, to deinitialize the
-     * hardware.
-     */
-    int                        (*remove)(struct instance *i);
-
-    /* This is called to remove the driver from the driver tree */
-    int                        (*unbind)(struct instance *i);
-
-    /* This is a list of cores this driver depends on */
-    struct driver      *cores[];
-  };
-
-  The cores[] array in here is very important. It allows u-boot to figure out,
-  in compile-time, which possible cores can be activated at runtime. Therefore
-  if there are cores that won't be ever activated, GCC LTO might remove them
-  from the final binary. Actually, this information might be used to drive build
-  of the cores.
-
-  FIXME: Should *cores[] be really struct driver, pointing to drivers that
-        represent the cores? Shouldn't it be core instance pointer?
-
-  2) Instantiation of a driver
-  ----------------------------
-
-  The driver is instantiated by calling:
-
-    driver_bind(struct instance *bus, const struct driver_info *di)
-
-  The "struct instance *bus" is a pointer to a bus with which this driver should
-  be registered with. The "root" bus pointer is supplied to the board init
-  functions.
-
-  FIXME: We need some functions that will return list of busses of certain type
-        registered with the system so the user can find proper instance even if
-        he has no bus pointer (this will come handy if the user isn't
-        registering the driver from board init function, but somewhere else).
-
-  The "const struct driver_info *di" pointer points to a structure defining the
-  driver to be registered. The structure is defined as follows:
-
-  struct driver_info {
-       char                    name[STATIC_CONFIG_DRIVER_NAME_LENGTH];
-       void                    *platform_data;
-  }
-
-  The instantiation of a driver by calling driver_bind() creates an instance
-  of the driver by allocating "struct driver_instance". Note that only struct
-  instance is passed to the driver. The wrapping struct driver_instance is there
-  for purposes of the driver core:
-
-  struct driver_instance {
-    uint32_t          flags;
-    struct instance   i;
-  };
-
-  struct instance {
-       /* Pointer to a driver information passed by driver_register() */
-       const struct driver_info        *info;
-       /* Pointer to a bus this driver is bound with */
-       struct instance                 *bus;
-       /* Pointer to this driver's own private data */
-       void                            *private_data;
-       /* Pointer to the first block of successor nodes (optional) */
-       struct successor_block          *succ;
-  }
-
-  The instantiation of a driver does not mean the hardware is initialized. The
-  driver_bind() call only creates the instance of the driver, fills in the "bus"
-  pointer and calls the drivers' .bind() function. The .bind() function of the
-  driver should hook the driver with the remaining cores and/or drivers it
-  depends on.
-
-  It's important to note here, that in case the driver instance has multiple
-  parents, such parent can be connected with this instance by calling:
-
-    driver_link(struct instance *parent, struct instance *dev);
-
-  This will connect the other parent driver with the newly instantiated driver.
-  Note that this must be called after driver_bind() and before driver_acticate()
-  (driver_activate() will be explained below). To allow struct instance to have
-  multiple parent pointer, the struct instance *bus will utilize it's last bit
-  to indicate if this is a pointer to struct instance or to an array if
-  instances, struct successor block. The approach is similar as the approach to
-  *succ in struct instance, described in the following paragraph.
-
-  The last pointer of the struct instance, the pointer to successor nodes, is
-  used only in case of a bus driver. Otherwise the pointer contains NULL value.
-  The last bit of this field indicates if this is a bus having a single child
-  node (so the last bit is 0) or if this bus has multiple child nodes (the last
-  bit is 1). In the former case, the driver core should clear the last bit and
-  this pointer points directly to the child node. In the later case of a bus
-  driver, the pointer points to an instance of structure:
-
-  struct successor_block {
-    /* Array of pointers to instances of devices attached to this bus */
-    struct instance                     *dev[BLOCKING_FACTOR];
-    /* Pointer to next block of successors */
-    struct successor_block              *next;
-  }
-
-  Some of the *dev[] array members might be NULL in case there are no more
-  devices attached. The *next is NULL in case the list of attached devices
-  doesn't continue anymore. The BLOCKING_FACTOR is used to allocate multiple
-  slots for successor devices at once to avoid fragmentation of memory.
-
-  3) The bind() function of a driver
-  ----------------------------------
-
-  The bind function of a driver connects the driver with various cores the
-  driver provides functions for. The driver model related part will look like
-  the following example for a bus driver:
-
-  int driver_bind(struct instance *in)
-  {
-       ...
-       core_bind(&core_i2c_static_instance, in, i2c_bus_funcs);
-       ...
-  }
-
-  FIXME: What if we need to run-time determine, depending on some hardware
-        register, what kind of i2c_bus_funcs to pass?
-
-  This makes the i2c core aware of a new bus. The i2c_bus_funcs is a constant
-  structure of functions any i2c bus driver must provide to work. This will
-  allow the i2c command operate with the bus. The core_i2c_static_instance is
-  the pointer to the instance of a core this driver provides function to.
-
-  FIXME: Maybe replace "core-i2c" with CORE_I2C global pointer to an instance of
-        the core?
-
-  4) The instantiation of a core driver
-  -------------------------------------
-
-  The core driver is special in the way that it's single-instance driver. It is
-  always present in the system, though it might not be activated. The fact that
-  it's single instance allows it to be instantiated at compile time.
-
-  Therefore, all possible structures of this driver can be in read-only memory,
-  especially struct driver and struct driver_instance. But the successor list,
-  which needs special treatment.
-
-  To solve the problem with a successor list and the core driver flags, a new
-  entry in struct gd (global data) will be introduced. This entry will point to
-  runtime allocated array of struct driver_instance. It will be possible to
-  allocate the exact amount of struct driver_instance necessary, as the number
-  of cores that might be activated will be known at compile time. The cores will
-  then behave like any usual driver.
-
-  Pointers to the struct instance of cores can be computed at compile time,
-  therefore allowing the resulting u-boot binary to save some overhead.
-
-  5) The probe() function of a driver
-  -----------------------------------
-
-  The probe function of a driver allocates necessary resources and does required
-  initialization of the hardware itself. This is usually called only when the
-  driver is needed, as a part of the defered probe mechanism.
-
-  The driver core should implement a function called
-
-    int driver_activate(struct instance *in);
-
-  which should call the .probe() function of the driver and then configure the
-  state of the driver instance to "ACTIVATED". This state of a driver instance
-  should be stored in a wrap-around structure for the structure instance, the
-  struct driver_instance.
-
-  6) The command side interface to a driver
-  -----------------------------------------
-
-  The U-Boot command shall communicate only with the specific driver core. The
-  driver core in turn exports necessary API towards the command.
-
-  7) Demonstration imaginary board
-  --------------------------------
-
-  Consider the following computer:
-
-  *
-  |
-  +-- System power management logic
-  |
-  +-- CPU clock controlling logc
-  |
-  +-- NAND controller
-  |   |
-  |   +-- NAND flash chip
-  |
-  +-- 128MB of DDR DRAM
-  |
-  +-- I2C bus #0
-  |   |
-  |   +-- RTC
-  |   |
-  |   +-- EEPROM #0
-  |   |
-  |   +-- EEPROM #1
-  |
-  +-- USB host-only IP core
-  |   |
-  |   +-- USB storage device
-  |
-  +-- USB OTG-capable IP core
-  |   |
-  |   +-- connection to the host PC
-  |
-  +-- GPIO
-  |   |
-  |   +-- User LED #0
-  |   |
-  |   +-- User LED #1
-  |
-  +-- UART0
-  |
-  +-- UART1
-  |
-  +-- Ethernet controller #0
-  |
-  +-- Ethernet controller #1
-  |
-  +-- Audio codec
-  |
-  +-- PCI bridge
-  |   |
-  |   +-- Ethernet controller #2
-  |   |
-  |   +-- SPI host card
-  |   |   |
-  |   |   +-- Audio amplifier (must be operational before codec)
-  |   |
-  |   +-- GPIO host card
-  |       |
-  |       +-- User LED #2
-  |
-  +-- LCD controller
-  |
-  +-- PWM controller (must be enabled after LCD controller)
-  |
-  +-- SPI host controller
-  |   |
-  |   +-- SD/MMC connected via SPI
-  |   |
-  |   +-- SPI flash
-  |
-  +-- CPLD/FPGA with stored configuration of the board
diff --git a/doc/driver-model/UDM-fpga.txt b/doc/driver-model/UDM-fpga.txt
deleted file mode 100644 (file)
index 4f9df94..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-I/O system analysis
-===================
-Marek Vasut <marek.vasut@gmail.com>
-2012-02-21
-
-I) Overview
------------
-
-The current FPGA implementation is handled by command "fpga". This command in
-turn calls the following functions:
-
-fpga_info()
-fpga_load()
-fpga_dump()
-
-These functions are implemented by what appears to be FPGA multiplexer, located
-in drivers/fpga/fpga.c . This code determines which device to operate with
-depending on the device ID.
-
-The fpga_info() function is multiplexer of the functions providing information
-about the particular FPGA device. These functions are implemented in the drivers
-for the particular FPGA device:
-
-xilinx_info()
-altera_info()
-lattice_info()
-
-Similar approach is used for fpga_load(), which multiplexes "xilinx_load()",
-"altera_load()" and "lattice_load()" and is used to load firmware into the FPGA
-device.
-
-The fpga_dump() function, which prints the contents of the FPGA device, is no
-different either, by multiplexing "xilinx_dump()", "altera_dump()" and
-"lattice_dump()" functions.
-
-Finally, each new FPGA device is registered by calling "fpga_add()" function.
-This function takes two arguments, the second one being particularly important,
-because it's basically what will become platform_data. Currently, it's data that
-are passed to the driver from the board/platform code.
-
-II) Approach
-------------
-
-The path to conversion of the FPGA subsystem will be very straightforward, since
-the FPGA subsystem is already quite dynamic. Multiple things will need to be
-modified though.
-
-First is the registration of the new FPGA device towards the FPGA core. This
-will be achieved by calling:
-
-  fpga_device_register(struct instance *i, const struct fpga_ops *ops);
-
-The particularly interesting part is the struct fpga_ops, which contains
-operations supported by the FPGA device. These are basically the already used
-calls in the current implementation:
-
-struct fpga_ops {
-  int info(struct instance *i);
-  int load(struct instance *i, const char *buf, size_t size);
-  int dump(struct instance *i, const char *buf, size_t size);
-}
-
-The other piece that'll have to be modified is how the devices are tracked.
-It'll be necessary to introduce a linked list of devices within the FPGA core
-instead of tracking them by ID number.
-
-Next, the "Xilinx_desc", "Lattice_desc" and "Altera_desc" structures will have
-to be moved to driver's private_data. Finally, structures passed from the board
-and/or platform files, like "Xilinx_Virtex2_Slave_SelectMap_fns" would be passed
-via platform_data to the driver.
-
-III) Analysis of in-tree drivers
---------------------------------
-
-  1) Altera driver
-  ----------------
-  The driver is realized using the following files:
-
-    drivers/fpga/altera.c
-    drivers/fpga/ACEX1K.c
-    drivers/fpga/cyclon2.c
-    drivers/fpga/stratixII.c
-
-  All of the sub-drivers implement basically the same info-load-dump interface
-  and there's no expected problem during the conversion. The driver itself will
-  be realised by altera.c and all the sub-drivers will be linked in. The
-  distinction will be done by passing different platform data.
-
-  2) Lattice driver
-  -----------------
-  The driver is realized using the following files:
-
-    drivers/fpga/lattice.c
-    drivers/fpga/ivm_core.c
-
-  This driver also implements the standard interface, but to realise the
-  operations with the FPGA device, uses functions from "ivm_core.c" file. This
-  file implements the main communications logic and has to be linked in together
-  with "lattice.c". No problem converting is expected here.
-
-  3) Xilinx driver
-  ----------------
-  The driver is realized using the following files:
-
-    drivers/fpga/xilinx.c
-    drivers/fpga/spartan2.c
-    drivers/fpga/spartan3.c
-    drivers/fpga/virtex2.c
-
-  This set of sub-drivers is special by defining a big set of macros in
-  "include/spartan3.h" and similar files. These macros would need to be either
-  rewritten or replaced. Otherwise, there are no problems expected during the
-  conversion process.
diff --git a/doc/driver-model/UDM-gpio.txt b/doc/driver-model/UDM-gpio.txt
deleted file mode 100644 (file)
index 585d458..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-GPIO analysis
-=============
-Viktor Krivak <viktor.krivak@gmail.com>
-2012-02-24
-
-I) Overview
------------
-
-  At this moment U-Boot provides standard API that consists of 7 functions.
-
-    int  gpio_request(unsigned gpio, const char *label)
-    int  gpio_free(unsigned gpio)
-    int  gpio_direction_input(unsigned gpio)
-    int  gpio_direction_output(unsigned gpio, int value)
-    int  gpio_get_value(unsigned gpio)
-    void gpio_set_value(unsigned gpio, int value)
-
-  Methods "gpio_request()" and "gpio_free()" are used for claiming and releasing
-  GPIOs. First one should check if the desired pin exists and if the pin wasn't
-  requested already elsewhere. The method also has a label argument that can be
-  used for debug purposes. The label argument should be copied into the internal
-  memory, but only if the DEBUG macro is set. The "gpio_free()" is the exact
-  opposite. It releases the particular pin. Other methods are used for setting
-  input or output direction and obtaining or setting values of the pins.
-
-II) Approach
-------------
-
-  1) Request and free GPIO
-  ------------------------
-
-    The "gpio_request()" implementation is basically the same for all boards.
-    The function checks if the particular GPIO is correct and checks if the
-    GPIO pin is still free. If the conditions are met, the method marks the
-    GPIO claimed in it's internal structure. If macro DEBUG is defined, the
-    function also copies the label argument to the structure. If the pin is
-    already locked, the function returns -1 and if DEBUG is defined, certain
-    debug output is generated, including the contents of the label argument.
-    The "gpio_free()" function releases the lock and eventually deallocates
-    data used by the copied label argument.
-
-  2) Internal data
-  ----------------
-
-  Internal data are driver specific. They have to contain some mechanism to
-  realise the locking though. This can be done for example using a bit field.
-
-  3) Operations provided by the driver
-  ------------------------------------
-
-  The driver operations basically meet API that is already defined and used.
-  Except for "gpio_request()" and "gpio_free()", all methods can be converted in
-  a simple manner. The driver provides the following structure:
-
-  struct gpio_driver_ops {
-    int  (*gpio_request)(struct instance *i, unsigned gpio,
-                        const char *label);
-    int  (*gpio_free)(struct instance *i, unsigned gpio);
-    int  (*gpio_direction_input)(struct instance *i, unsigned gpio);
-    int  (*gpio_direction_output)(struct instance *i, unsigned gpio,
-                                 int value);
-    int  (*gpio_get_value)(struct instance *i, unsigned gpio);
-    void (*gpio_set_value)(struct instance *i, unsigned gpio, int value);
-  }
-
-III) Analysis of in-tree drivers
---------------------------------
-
-  altera_pio.c
-  ------------
-  Meets standard API. Implements gpio_request() properly. Simple conversion
-  possible.
-
-  at91_gpio.c
-  -----------
-  Don't meet standard API. Need some other methods to implement.
-
-  da8xx_gpio.c
-  ------------
-  Meets standard API. Implements gpio_request() properly. Simple conversion
-  possible.
-
-  kw_gpio.c
-  ---------
-  Doesn't meet standard API. Needs some other methods to implement and move some
-  methods to another file.
-
-  mpc83xx_gpio.c
-  --------------
-  Meets standard API. Doesn't implement gpio_request() properly (only checks
-  if the pin is valid). Simple conversion possible.
-
-  mvgpio.c
-  --------
-  Meets standard API. Doesn't implement gpio_request() properly (only checks
-  if the pin is valid). Simple conversion possible.
-
-  mvgpio.h
-  --------
-  Wrong placement. Will be moved to another location.
-
-  mvmfp.c
-  -------
-  Wrong placement. Will be moved to another location.
diff --git a/doc/driver-model/UDM-hwmon.txt b/doc/driver-model/UDM-hwmon.txt
deleted file mode 100644 (file)
index 03a96a0..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-Hwmon device subsystem analysis
-===============================
-
-Tomas Hlavacek <tmshlvck@gmail.com>
-2012-03-02
-
-I) Overview
------------
-
-U-Boot currently implements one API for HW monitoring devices. The
-interface is defined in include/dtt.h and comprises of functions:
-
-    void dtt_init(void);
-    int dtt_init_one(int);
-    int dtt_read(int sensor, int reg);
-    int dtt_write(int sensor, int reg, int val);
-    int dtt_get_temp(int sensor);
-
-The functions are implemented by a proper device driver in drivers/hwmon
-directory and the driver to be compiled in is selected in a Makefile.
-Drivers are mutually exclusive.
-
-Drivers depends on I2O code and naturally on board specific data. There are
-few ad-hoc constants put in dtt.h file and driver headers and code. This
-has to be consolidated into board specific data or driver headers if those
-constants makes sense globally.
-
-
-II) Approach
-------------
-
-  1) New API
-  ----------
-  In the UDM each hwmon driver would register itself by a function
-
-    int hwmon_device_register(struct instance *i,
-                             struct hwmon_device_ops *o);
-
-  The structure being defined as follows:
-
-    struct hwmon_device_ops {
-       int  (*read)(struct instance *i, int sensor, int reg);
-       int  (*write)(struct instance *i, int sensor, int reg,
-                     int val);
-       int  (*get_temp)(struct instance *i, int sensor);
-    };
-
-
-  2) Conversion thougths
-  ----------------------
-  U-Boot hwmon drivers exports virtually the same functions (with exceptions)
-  and we are considering low number of drivers and code anyway. The interface
-  is already similar and unified by the interface defined in dtt.h.
-  Current initialization functions dtt_init() and dtt_init_one() will be
-  converted into probe() and hwmon_device_register(), so the funcionality will
-  be kept in more proper places. Besides implementing core registration and
-  initialization we need to do code cleanup, especially separate
-  driver-specific and HW specific constants.
-
-  3) Special consideration due to early initialization
-  ----------------------------------------------------
-  The dtt_init() function call is used during early initialization in
-  board/gdsys/405ex/io64.c for starting up fans. The dtt code is perfectly
-  usable in the early stage because it uses only local variables and no heap
-  memory is required at this level. However the underlying code of I2C has to
-  keep the same properties with regard to possibility of running in early
-  initialization stage.
-
-III) Analysis of in-tree drivers
---------------------------------
-
-  drivers/hwmon/lm81.c
-  --------------------
-  The driver is standard dtt. Simple conversion is possible.
-
-
-  drivers/hwmon/ds1722.c
-  ----------------------
-  The driver is not standard dtt, but interface is similar to dtt.
-  The interface has to be changed in order to comply to above mentioned
-  specification.
-
-
-  drivers/hwmon/ds1775.c
-  ----------------------
-  The driver is standard dtt. Simple conversion is possible.
-
-
-  drivers/hwmon/lm73.c
-  --------------------
-  The driver is standard dtt. Simple conversion is possible.
-
-
-  drivers/hwmon/lm63.c
-  --------------------
-  The driver is standard dtt. Simple conversion is possible.
-
-
-  drivers/hwmon/adt7460.c
-  -----------------------
-  The driver is standard dtt. Simple conversion is possible.
-
-
-  drivers/hwmon/lm75.c
-  --------------------
-  The driver is standard dtt. Simple conversion is possible.
-
-
-  drivers/hwmon/ds1621.c
-  ----------------------
-  The driver is standard dtt. Simple conversion is possible.
-
-
-  drivers/hwmon/adm1021.c
-  -----------------------
-  The driver is standard dtt. Simple conversion is possible.
diff --git a/doc/driver-model/UDM-keyboard.txt b/doc/driver-model/UDM-keyboard.txt
deleted file mode 100644 (file)
index 5babfc5..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-Keyboard input analysis
-=======================
-Marek Vasut <marek.vasut@gmail.com>
-2012-02-20
-
-I) Overview
------------
-
-The keyboard drivers are most often registered with STDIO subsystem. There are
-components of the keyboard drivers though, which operate in severe ad-hoc
-manner, often being related to interrupt-driven keypress reception. This
-components will require the most sanitization of all parts of keyboard input
-subsystem.
-
-Otherwise, the keyboard is no different from other standard input but with the
-necessity to decode scancodes. These are decoded using tables provided by
-keyboard drivers. These tables are often driver specific.
-
-II) Approach
-------------
-
-The most problematic part is the interrupt driven keypress reception. For this,
-the buffers that are currently shared throughout the whole U-Boot would need to
-be converted into driver's private data.
-
-III) Analysis of in-tree drivers
---------------------------------
-
-  board/mpl/common/kbd.c
-  ----------------------
-  This driver is a classic STDIO driver, no problem with conversion is expected.
-  Only necessary change will be to move this driver to a proper location.
-
-  board/rbc823/kbd.c
-  ------------------
-  This driver is a classic STDIO driver, no problem with conversion is expected.
-  Only necessary change will be to move this driver to a proper location.
-
-  drivers/input/keyboard.c
-  ------------------------
-  This driver is special in many ways. Firstly because this is a universal stub
-  driver for converting scancodes from i8042 and the likes. Secondly because the
-  buffer is filled by various other ad-hoc implementations of keyboard input by
-  using this buffer as an extern. This will need to be fixed by allowing drivers
-  to pass certain routines to this driver via platform data.
diff --git a/doc/driver-model/UDM-mmc.txt b/doc/driver-model/UDM-mmc.txt
deleted file mode 100644 (file)
index 97f83a7..0000000
+++ /dev/null
@@ -1,319 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-MMC system analysis
-===================
-Marek Vasut <marek.vasut@gmail.com>
-2012-02-25
-
-I) Overview
------------
-
-The MMC subsystem is already quite dynamic in it's nature. It's only necessary
-to flip the subsystem to properly defined API.
-
-The probing process of MMC drivers start by calling "mmc_initialize()",
-implemented by MMC framework, from the architecture initialization file. The
-"mmc_initialize()" function in turn calls "board_mmc_init()" function and if
-this doesn't succeed, "cpu_mmc_init()" function is called. It is important to
-note that both of the "*_mmc_init()" functions have weak aliases to functions
-which automatically fail.
-
-Both of the "*_mmc_init()" functions though serve only one purpose. To call
-driver specific probe function, which in turn actually registers the driver with
-MMC subsystem. Each of the driver specific probe functions is currently done in
-very ad-hoc manner.
-
-The registration with the MMC subsystem is done by calling "mmc_register()",
-whose argument is a runtime configured structure of information about the MMC
-driver. Currently, the information structure is intermixed with driver's internal
-data. The description of the structure follows:
-
-struct mmc {
- /*
-  * API: Allows this driver to be a member of the linked list of all MMC drivers
-  *      registered with MMC subsystem
-  */
-  struct list_head link;
-
-  /* DRIVER: Name of the registered driver */
-  char name[32];
-
-  /* DRIVER: Driver's private data */
-  void *priv;
-
-  /* DRIVER: Voltages the host bus can provide */
-  uint voltages;
-
-  /* API: Version of the card */
-  uint version;
-
-  /* API: Test if the driver was already initialized */
-  uint has_init;
-
-  /* DRIVER: Minimum frequency the host bus can provide */
-  uint f_min;
-
-  /* DRIVER: Maximum frequency the host bus can provide */
-  uint f_max;
-
-  /* API: Is the card SDHC */
-  int high_capacity;
-
-  /* API: Actual width of the bus used by the current card */
-  uint bus_width;
-
-  /*
-   * DRIVER: Clock frequency to be configured on the host bus, this is read-only
-   *         for the driver.
-   */
-  uint clock;
-
-  /* API: Capabilities of the card */
-  uint card_caps;
-
-  /* DRIVER: MMC bus capabilities */
-  uint host_caps;
-
-  /* API: Configuration and ID data retrieved from the card */
-  uint ocr;
-  uint scr[2];
-  uint csd[4];
-  uint cid[4];
-  ushort rca;
-
-  /* API: Partition configuration */
-  char part_config;
-
-  /* API: Number of partitions */
-  char part_num;
-
-  /* API: Transmission speed */
-  uint tran_speed;
-
-  /* API: Read block length */
-  uint read_bl_len;
-
-  /* API: Write block length */
-  uint write_bl_len;
-
-  /* API: Erase group size */
-  uint erase_grp_size;
-
-  /* API: Capacity of the card */
-  u64 capacity;
-
-  /* API: Descriptor of this block device */
-  block_dev_desc_t block_dev;
-
-  /* DRIVER: Function used to submit command to the card */
-  int (*send_cmd)(struct mmc *mmc,
-                 struct mmc_cmd *cmd, struct mmc_data *data);
-
-  /* DRIVER: Function used to configure the host */
-  void (*set_ios)(struct mmc *mmc);
-
-  /* DRIVER: Function used to initialize the host */
-  int (*init)(struct mmc *mmc);
-
-  /* DRIVER: Function used to report the status of Card Detect pin */
-  int (*getcd)(struct mmc *mmc);
-
-  /*
-   * DRIVER: Maximum amount of blocks sent during multiblock xfer,
-   *         set to 0 to autodetect.
-   */
-  uint b_max;
-};
-
-The API above is the new API used by most of the drivers. There're still drivers
-in the tree that use old, legacy API though.
-
-2) Approach
------------
-
-To convert the MMC subsystem to a proper driver model, the "struct mmc"
-structure will have to be properly split in the first place. The result will
-consist of multiple parts, first will be the structure defining operations
-provided by the MMC driver:
-
-struct mmc_driver_ops {
-  /* Function used to submit command to the card */
-  int  (*send_cmd)(struct mmc *mmc,
-                 struct mmc_cmd *cmd, struct mmc_data *data);
-  /* DRIVER: Function used to configure the host */
-  void (*set_ios)(struct mmc *mmc);
-  /* Function used to initialize the host */
-  int  (*init)(struct mmc *mmc);
-  /* Function used to report the status of Card Detect pin */
-  int  (*getcd)(struct mmc *mmc);
-}
-
-The second part will define the parameters of the MMC driver:
-
-struct mmc_driver_params {
-  /* Voltages the host bus can provide */
-  uint32_t voltages;
-  /* Minimum frequency the host bus can provide */
-  uint32_t f_min;
-  /* Maximum frequency the host bus can provide */
-  uint32_t f_max;
-  /* MMC bus capabilities */
-  uint32_t host_caps;
-  /*
-   * Maximum amount of blocks sent during multiblock xfer,
-   * set to 0 to autodetect.
-   */
-  uint32_t b_max;
-}
-
-And finally, the internal per-card data of the MMC subsystem core:
-
-struct mmc_card_props {
-  /* Version of the card */
-  uint32_t version;
-  /* Test if the driver was already initializes */
-  bool     has_init;
-  /* Is the card SDHC */
-  bool     high_capacity;
-  /* Actual width of the bus used by the current card */
-  uint8_t  bus_width;
-  /* Capabilities of the card */
-  uint32_t card_caps;
-  /* Configuration and ID data retrieved from the card */
-  uint32_t ocr;
-  uint32_t scr[2];
-  uint32_t csd[4];
-  uint32_t cid[4];
-  uint16_t rca;
-  /* Partition configuration */
-  uint8_t  part_config;
-  /* Number of partitions */
-  uint8_t  part_num;
-  /* Transmission speed */
-  uint32_t tran_speed;
-  /* Read block length */
-  uint32_t read_bl_len;
-  /* Write block length */
-  uint32_t write_bl_len;
-  /* Erase group size */
-  uint32_t erase_grp_size;
-  /* Capacity of the card */
-  uint64_t capacity;
-  /* Descriptor of this block device */
-  block_dev_desc_t block_dev;
-}
-
-The probe() function will then register the MMC driver by calling:
-
-  mmc_device_register(struct instance *i, struct mmc_driver_ops *o,
-                                         struct mmc_driver_params *p);
-
-The struct mmc_driver_params will have to be dynamic in some cases, but the
-driver shouldn't modify it's contents elsewhere than in probe() call.
-
-Next, since the MMC drivers will now be consistently registered into the driver
-tree from board file, the functions "board_mmc_init()" and "cpu_mmc_init()" will
-disappear altogether.
-
-As for the legacy drivers, these will either be converted or removed altogether.
-
-III) Analysis of in-tree drivers
---------------------------------
-
-  arm_pl180_mmci.c
-  ----------------
-  Follows the new API and also has a good encapsulation of the whole driver. The
-  conversion here will be simple.
-
-  atmel_mci.c
-  -----------
-  This driver uses the legacy API and should be removed unless converted. It is
-  probably possbible to replace this driver with gen_atmel_mci.c . No conversion
-  will be done on this driver.
-
-  bfin_sdh.c
-  ----------
-  Follows the new API and also has a good encapsulation of the whole driver. The
-  conversion here will be simple.
-
-  davinci_mmc.c
-  -------------
-  Follows the new API and also has a good encapsulation of the whole driver. The
-  conversion here will be simple.
-
-  fsl_esdhc.c
-  -----------
-  Follows the new API and also has a good encapsulation of the whole driver. The
-  conversion here will be simple, unless some problem appears due to the FDT
-  component of the driver.
-
-  ftsdc010_esdhc.c
-  ----------------
-  Follows the new API and also has a good encapsulation of the whole driver. The
-  conversion here will be simple.
-
-  gen_atmel_mci.c
-  ---------------
-  Follows the new API and also has a good encapsulation of the whole driver. The
-  conversion here will be simple.
-
-  mmc_spi.c
-  ---------
-  Follows the new API and also has a good encapsulation of the whole driver. The
-  conversion here will be simple.
-
-  mv_sdhci.c
-  ----------
-  This is a component of the SDHCI support, allowing it to run on Marvell
-  Kirkwood chip. It is probable the SDHCI support will have to be modified to
-  allow calling functions from this file based on information passed via
-  platform_data.
-
-  mxcmmc.c
-  --------
-  Follows the new API and also has a good encapsulation of the whole driver. The
-  conversion here will be simple.
-
-  mxsmmc.c
-  --------
-  Follows the new API and also has a good encapsulation of the whole driver. The
-  conversion here will be simple.
-
-  omap_hsmmc.c
-  ------------
-  Follows the new API and also has a good encapsulation of the whole driver. The
-  conversion here will be simple.
-
-  pxa_mmc.c
-  ---------
-  This driver uses the legacy API and is written in a severely ad-hoc manner.
-  This driver will be removed in favor of pxa_mmc_gen.c, which is proved to work
-  better and is already well tested. No conversion will be done on this driver
-  anymore.
-
-  pxa_mmc_gen.c
-  -------------
-  Follows the new API and also has a good encapsulation of the whole driver. The
-  conversion here will be simple.
-
-  s5p_mmc.c
-  ---------
-  Follows the new API and also has a good encapsulation of the whole driver. The
-  conversion here will be simple.
-
-  sdhci.c
-  -------
-  Follows the new API and also has a good encapsulation of the whole driver. The
-  conversion here will be simple, though it'd be necessary to modify this driver
-  to also support the Kirkwood series and probably also Tegra series of CPUs.
-  See the respective parts of this section for details.
-
-  sh_mmcif.c
-  ----------
-  Follows the new API and also has a good encapsulation of the whole driver. The
-  conversion here will be simple.
-
-  tegra2_mmc.c
-  ------------
-  Follows the new API and also has a good encapsulation of the whole driver. The
-  conversion here will be simple.
diff --git a/doc/driver-model/UDM-net.txt b/doc/driver-model/UDM-net.txt
deleted file mode 100644 (file)
index 097ed69..0000000
+++ /dev/null
@@ -1,428 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-Net system analysis
-===================
-Marek Vasut <marek.vasut@gmail.com>
-2012-03-03
-
-I) Overview
------------
-
-The networking subsystem already supports multiple devices. Therefore the
-conversion shall not be very hard.
-
-The network subsystem is operated from net/eth.c, which tracks all registered
-ethernet interfaces and calls their particular functions registered via
-eth_register().
-
-The eth_register() is called from the network driver initialization function,
-which in turn is called most often either from "board_net_init()" or
-"cpu_net_init()". This function has one important argument, which is the
-"struct eth_device", defined at include/net.h:
-
-struct eth_device {
-  /* DRIVER: Name of the device */
-  char name[NAMESIZE];
-  /* DRIVER: MAC address */
-  unsigned char enetaddr[6];
-  /* DRIVER: Register base address */
-  int iobase;
-  /* CORE: state of the device */
-  int state;
-
-  /* DRIVER: Device initialization function */
-  int  (*init) (struct eth_device*, bd_t*);
-  /* DRIVER: Function for sending packets */
-  int  (*send) (struct eth_device*, volatile void* packet, int length);
-  /* DRIVER: Function for receiving packets */
-  int  (*recv) (struct eth_device*);
-  /* DRIVER: Function to cease operation of the device */
-  void (*halt) (struct eth_device*);
-  /* DRIVER: Function to send multicast packet (OPTIONAL) */
-  int (*mcast) (struct eth_device*, u32 ip, u8 set);
-  /* DRIVER: Function to change ethernet MAC address */
-  int  (*write_hwaddr) (struct eth_device*);
-  /* CORE: Next device in the linked list of devices managed by net core */
-  struct eth_device *next;
-  /* CORE: Device index */
-  int index;
-  /* DRIVER: Driver's private data */
-  void *priv;
-};
-
-This structure defines the particular driver, though also contains elements that
-should not be exposed to the driver, like core state.
-
-Small, but important part of the networking subsystem is the PHY management
-layer, whose drivers are contained in drivers/net/phy. These drivers register in
-a very similar manner to network drivers, by calling "phy_register()" with the
-argument of "struct phy_driver":
-
-struct phy_driver {
-  /* DRIVER: Name of the PHY driver */
-  char *name;
-  /* DRIVER: UID of the PHY driver */
-  unsigned int uid;
-  /* DRIVER: Mask for UID of the PHY driver */
-  unsigned int mask;
-  /* DRIVER: MMDS of the PHY driver */
-  unsigned int mmds;
-  /* DRIVER: Features the PHY driver supports */
-  u32 features;
-  /* DRIVER: Initialize the PHY hardware */
-  int (*probe)(struct phy_device *phydev);
-  /* DRIVER: Reconfigure the PHY hardware */
-  int (*config)(struct phy_device *phydev);
-  /* DRIVER: Turn on the PHY hardware, allow it to send/receive */
-  int (*startup)(struct phy_device *phydev);
-  /* DRIVER: Turn off the PHY hardware */
-  int (*shutdown)(struct phy_device *phydev);
-  /* CORE: Allows this driver to be part of list of drivers */
-  struct list_head list;
-};
-
-II) Approach
-------------
-
-To convert the elements of network subsystem to proper driver model method, the
-"struct eth_device" will have to be split into multiple components. The first
-will be a structure defining the driver operations:
-
-struct eth_driver_ops {
-  int  (*init)(struct instance*, bd_t*);
-  int  (*send)(struct instance*, void *packet, int length);
-  int  (*recv)(struct instance*);
-  void (*halt)(struct instance*);
-  int  (*mcast)(struct instance*, u32 ip, u8 set);
-  int  (*write_hwaddr)(struct instance*);
-};
-
-Next, there'll be platform data which will be per-driver and will replace the
-"priv" part of "struct eth_device". Last part will be the per-device core state.
-
-With regards to the PHY part of the API, the "struct phy_driver" is almost ready
-to be used with the new driver model approach. The only change will be the
-replacement of per-driver initialization functions and removal of
-"phy_register()" function in favor or driver model approach.
-
-III) Analysis of in-tree drivers
---------------------------------
-
-  drivers/net/4xx_enet.c
-  ----------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/altera_tse.c
-  ------------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/armada100_fec.c
-  ---------------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/at91_emac.c
-  -----------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/ax88180.c
-  ---------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/ax88796.c
-  ---------------------
-
-  This file contains a components of the NE2000 driver, implementing only
-  different parts on the NE2000 clone AX88796. This being no standalone driver,
-  no conversion will be done here.
-
-  drivers/net/bfin_mac.c
-  ----------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/calxedaxgmac.c
-  --------------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/cs8900.c
-  --------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/davinci_emac.c
-  --------------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/dc2114x.c
-  ---------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/designware.c
-  ------------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/dm9000x.c
-  ---------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/dnet.c
-  ------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/e1000.c
-  -------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/e1000_spi.c
-  -----------------------
-
-  Driver for the SPI bus integrated on the Intel E1000. This is not part of the
-  network stack.
-
-  drivers/net/eepro100.c
-  ----------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/enc28j60.c
-  ----------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/ep93xx_eth.c
-  ------------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/ethoc.c
-  -------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/fec_mxc.c
-  ---------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/fsl_mcdmafec.c
-  --------------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/fsl_mdio.c
-  ----------------------
-
-  This file contains driver for FSL MDIO interface, which is not part of the
-  networking stack.
-
-  drivers/net/ftgmac100.c
-  -----------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/ftmac100.c
-  ----------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/greth.c
-  -------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/inca-ip_sw.c
-  ------------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/ks8695eth.c
-  -----------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/lan91c96.c
-  ----------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/macb.c
-  ------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/mcffec.c
-  --------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/mcfmii.c
-  --------------------
-
-  This file contains MII interface driver for MCF FEC.
-
-  drivers/net/mpc512x_fec.c
-  -------------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/mpc5xxx_fec.c
-  -------------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/mvgbe.c
-  -------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/natsemi.c
-  ---------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/ne2000_base.c
-  -------------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process. This driver contains the core
-  implementation of NE2000, which needs a few external functions, implemented by
-  AX88796, NE2000 etc.
-
-  drivers/net/ne2000.c
-  --------------------
-
-  This file implements external functions necessary for native NE2000 compatible
-  networking card to work.
-
-  drivers/net/netconsole.c
-  ------------------------
-
-  This is actually an STDIO driver.
-
-  drivers/net/ns8382x.c
-  ---------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/pcnet.c
-  -------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/plb2800_eth.c
-  -------------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/rtl8139.c
-  ---------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/rtl8169.c
-  ---------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/sh_eth.c
-  --------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/smc91111.c
-  ----------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/smc911x.c
-  ---------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/tsec.c
-  ------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/tsi108_eth.c
-  ------------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/uli526x.c
-  ---------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/vsc7385.c
-  ---------------------
-
-  This is a driver that only uploads firmware to a switch. This is not subject
-  of conversion.
-
-  drivers/net/xilinx_axi_emac.c
-  -----------------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
-
-  drivers/net/xilinx_emaclite.c
-  -----------------------------
-
-  This driver uses the standard new networking API, therefore there should be no
-  obstacles throughout the conversion process.
diff --git a/doc/driver-model/UDM-pci.txt b/doc/driver-model/UDM-pci.txt
deleted file mode 100644 (file)
index 1dce99d..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-PCI subsystem analysis
-======================
-
-Pavel Herrmann <morpheus.ibis@gmail.com>
-2012-03-17
-
-I) Overview
------------
-
-  U-Boot already supports multiple PCI busses, stored in a linked-list of
-  pci_controller structures. This structure contains generic driver data, bus
-  interface operations and private data for the driver.
-
-  Bus interface operations for PCI are (names are self-explanatory):
-
-    read_byte()
-    read_word()
-    read_dword()
-    write_byte()
-    write_word()
-    write_dword()
-
-  Each driver has to implement dword operations, and either implement word and
-  byte operations, or use shared $operation_config_$type_via_dword (eg.
-  read_config_byte_via_dword and similar) function. These functions are used
-  for config space I/O (read_config_dword and similar functions of the PCI
-  subsystem), which is used to configure the connected devices for standard MMIO
-  operations. All data transfers by respective device drivers are then done by
-  MMIO
-
-  Each driver also defines a separate init function, which has unique symbol
-  name, and thus more drivers can be compiled in without colliding. This init
-  function is typically called from pci_init_board(), different for each
-  particular board.
-
-  Some boards also define a function called fixup_irq, which gets called after
-  scanning the PCI bus for devices, and should dismiss any interrupts.
-
-  Several drivers are also located in arch/ and should be moved to drivers/pci.
-
-II) Approach
-------------
-
-  The pci_controller structure needs to be broken down to fit the new driver
-  model. Due to a large number of members, this will be done through three
-  distinct accessors, one for memory regions, one for config table and one for
-  everything else. That will make the pci_ops structure look like this:
-
-    struct pci_ops {
-      int (*read_byte)(struct instance *bus, pci_dev_t *dev, int addr,
-                      u8 *buf);
-      int (*read_word)(struct instance *bus, pci_dev_t *dev, int addr,
-                      u16 *buf);
-      int (*read_dword)(struct instance *bus, pci_dev_t *dev, int addr,
-                       u32 *buf);
-      int (*write_byte)(struct instance *bus, pci_dev_t *dev, int addr,
-                       u8 val);
-      int (*write_byte)(struct instance *bus, pci_dev_t *dev, int addr,
-                       u8 val);
-      int (*write_dword)(struct instance *bus, pci_dev_t *dev, int addr,
-                        u32 val);
-      void (*fixup_irq)(struct instance *bus, pci_dev_t *dev);
-      struct pci_region* (*get_region)(struct instance *, uint num);
-      struct pci_config_table* (*get_cfg_table)(struct instance *bus);
-      uint (*get_option)(struct instance * bus, enum pci_option_code op);
-    }
-
-    enum pci_option_code {
-      PCI_OPT_BUS_NUMBER=0,
-      PCI_OPT_REGION_COUNT,
-      PCI_OPT_INDIRECT_TYPE,
-      PCI_OPT_AUTO_MEM,
-      PCI_OPT_AUTO_IO,
-      PCI_OPT_AUTO_PREFETCH,
-      PCI_OPT_AUTO_FB,
-      PCI_OPT_CURRENT_BUS,
-      PCI_OPT_CFG_ADDR,
-    }
-
-  The return value for get_option will be an unsigned integer value for any
-  option code. If the option currently is a pointer to pci_region, it will
-  return an index for get_region function. Special case has to be made for
-  PCI_OPT_CFG_ADDR, which should be interpreted as a pointer, but it is only
-  used for equality in find_hose_by_cfg_addr, and thus can be returned as an
-  uint. Other function using cfg_addr value are read/write functions for
-  specific drivers (especially ops for indirect bridges), and thus have access
-  to private_data of the driver instance.
-
-  The config table accessor will return a pointer to a NULL-terminated array of
-  pci_config_table, which is supplied by the board in platform_data, or NULL if
-  the board didn't specify one. This table is used to override PnP
-  auto-initialization, or to specific initialization functions for non-PNP
-  devices.
-
-  Transparent PCI-PCI bridges will get their own driver, and will forward all
-  operations to operations of their parent bus. This however makes it
-  impossible to use instances to identify devices, as not all devices will be
-  directly visible to the respective bus driver.
-
-  Init functions of controller drivers will be moved to their respective
-  probe() functions, in accordance to the driver model.
-
-  The PCI core will handle all mapping functions currently found in pci.c, as
-  well as proxy functions for read/write operations of the drivers. The PCI
-  core will also handle bus scanning and device configuration.
-
-  The PnP helper functions currently in pci_auto.c will also be a part of PCI
-  core, but they will be exposed only to PCI controller drivers, not to other
-  device drivers.
-
-  The PCI API for device drivers will remain largely unchanged, most drivers
-  will require no changes at all, and all modifications will be limited to
-  changing the pci_controlle into instance*.
-
-III) Analysis of in-tree drivers
---------------------------------
-
-  A) drivers in drivers/pci/
-  --------------------------
-
-    pci_indirect.c
-    --------------
-      Shared driver for indirect PCI bridges, several CONFIG macros - will
-      require significant cleanup.
-
-    pci_sh4.c
-    ---------
-      Shared init function for SH4 drivers, uses dword for read/write ops.
-
-    pci_sh7751.c
-    ------------
-      Standard driver, uses SH4 shared init.
-
-    pci_sh7780.c
-    ------------
-      Standard driver, uses SH4 shared init.
-
-    tsi108_pci.c
-    ------------
-      Standard driver, uses dword for read/write ops.
-
-    fsl_pci_init.c
-    --------------
-      Driver for PCI and PCI-e, uses indirect functions.
-
-    pci_ftpci100.c
-    --------------
-      Standard driver, uses indirect functions, has separate scan/setup
-      functions.
-
-  B) driver in arch/
-  ------------------
-
-    x86/lib/pci_type1.c
-    -------------------
-      Standard driver, specifies all read/write functions separately.
-
-    m68k/cpu/mcf5445x/pci.c
-    -----------------------
-      Standard driver, specifies all read/write functions separately.
-
-    m68k/cpu/mcf547x_8x/pci.c
-    -------------------------
-      Standard driver, specifies all read/write functions separately.
-
-    powerpc/cpu/mpc824x/pci.c
-    -------------------------
-      Standard driver, uses indirect functions, does not setup HW.
-
-    powerpc/cpu/mpc8260/pci.c
-    -------------------------
-      Standard driver, uses indirect functions.
-
-    powerpc/cpu/ppc4xx/4xx_pci.c
-    ----------------------------
-      Standard driver, uses indirect functions.
-
-    powerpc/cpu/ppc4xx/4xx_pcie.c
-    -----------------------------
-      PCI-e driver, specifies all read/write functions separately.
-
-    powerpc/cpu/mpc83xx/pci.c
-    -------------------------
-      Standard driver, uses indirect functions.
-
-    powerpc/cpu/mpc83xx/pcie.c
-    --------------------------
-      PCI-e driver, specifies all read/write functions separately.
-
-    powerpc/cpu/mpc5xxx/pci_mpc5200.c
-    ---------------------------------
-      Standard driver, uses dword for read/write ops.
-
-    powerpc/cpu/mpc512x/pci.c
-    -------------------------
-      Standard driver, uses indirect functions.
-
-    powerpc/cpu/mpc85xx/pci.c
-    -------------------------
-      Standard driver, uses indirect functions, has two busses.
-
-  C) drivers in board/
-  --------------------
-
-    eltec/elppc/pci.c
-    -----------------
-      Standard driver, uses indirect functions.
-
-    amirix/ap1000/pci.c
-    -------------------
-      Standard driver, specifies all read/write functions separately.
-
-    prodrive/p3mx/pci.c
-    -------------------
-      Standard driver, uses dword for read/write ops, has two busses.
-
-    esd/cpci750/pci.c
-    -----------------
-      Standard driver, uses dword for read/write ops, has two busses.
-
-    esd/common/pci.c
-    ----------------
-      Standard driver, uses dword for read/write ops.
-
-    dave/common/pci.c
-    -----------------
-      Standard driver, uses dword for read/write ops.
-
-    ppmc7xx/pci.c
-    -------------
-      Standard driver, uses indirect functions.
-
-    Marvell/db64360/pci.c
-    ---------------------
-      Standard driver, uses dword for read/write ops, has two busses.
-
-    Marvell/db64460/pci.c
-    ---------------------
-      Standard driver, uses dword for read/write ops, has two busses.
-
-    evb64260/pci.c
-    --------------
-      Standard driver, uses dword for read/write ops, has two busses.
-
-    armltd/integrator/pci.c
-    -----------------------
-      Standard driver, specifies all read/write functions separately.
-
-  All drivers will be moved to drivers/pci. Several drivers seem
-  similar/identical, especially those located under board, and may be merged
-  into one.
diff --git a/doc/driver-model/UDM-pcmcia.txt b/doc/driver-model/UDM-pcmcia.txt
deleted file mode 100644 (file)
index d55e89d..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-PCMCIA analysis
-===============
-Viktor Krivak <viktor.krivak@gmail.com>
-2012-03-17
-
-I) Overview
------------
-
-  U-boot implements only 2 methods to interoperate with pcmcia. One to turn
-  device on and other to turn device off. Names of these methods are usually
-  pcmcia_on() and pcmcia_off() without any parameters. Some files in driver
-  directory implements only internal API. These methods aren't used outside
-  driver directory and they are not converted to new driver model.
-
-II) Approach
------------
-
-  1) New API
-  ----------
-
-    Current API is preserved and all internal methods are hiden.
-
-    struct ops {
-      void (*pcmcia_on)(struct instance *i);
-      void (*pcmcia_off)(struct instance *i);
-    }
-
-  2) Conversion
-  -------------
-
-    In header file pcmcia.h are some other variables which are used for
-    additional configuration. But all have to be moved to platform data or to
-    specific driver implementation.
-
-  3) Platform data
-  ----------------
-
-    Many boards have custom implementation of internal API. Pointers to these
-    methods are stored in platform_data. But the most implementations for Intel
-    82365 and compatible PC Card controllers and Yenta-compatible
-    PCI-to-CardBus controllers implement whole API per board. In these cases
-    pcmcia_on() and pcmcia_off() behave only as wrappers and call specific
-    board methods.
-
-III) Analysis of in-tree drivers
---------------------------------
-
-  i82365.c
-  --------
-    Driver methods have different name i82365_init() and i82365_exit but
-    all functionality is the same. Board files board/atc/ti113x.c and
-    board/cpc45/pd67290.c use their own implementation of these method.
-    In this case all methods in driver behave only as wrappers.
-
-  marubun_pcmcia.c
-  ----------------
-    Meets standard API behaviour. Simple conversion.
-
-  mpc8xx_pcmcia.c
-  ---------------
-    Meets standard API behaviour. Simple conversion.
-
-  rpx_pcmcia.c
-  ------------
-    Implements only internal API used in other drivers. Non of methods
-    implemented here are used outside driver model.
-
-  ti_pci1410a.c
-  -------------
-    Has different API but methods in this file are never called. Probably
-    dead code.
-
-  tqm8xx_pcmcia.c
-  ---------------
-    Implements only internal API used in other drivers. Non of methods
-    implemented here are used outside driver model.
diff --git a/doc/driver-model/UDM-power.txt b/doc/driver-model/UDM-power.txt
deleted file mode 100644 (file)
index 666d553..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-POWER analysis
-==============
-Viktor Krivak <viktor.krivak@gmail.com>
-2012-03-09
-
-I) Overview
------------
-
-  1) Actual state
-  ---------------
-
-  At this moment power doesn't contain API. There are many methods for
-  initialization of some board specific functions but only few does what is
-  expected. Basically only one file contains something meaningful for this
-  driver.
-
-  2) Current implementation
-  -------------------------
-
-  In file twl6030.c are methods twl6030_stop_usb_charging() and
-  twl6030_start_usb_charging() for start and stop charging from USB. There are
-  also methods to get information about battery state and initialization of
-  battery charging. Only these methods are used in converted API.
-
-
-II) Approach
-------------
-
-  1) New API
-  ----------
-
-  New API implements only functions specific for managing power. All board
-  specific init methods are moved to other files. Name of methods are
-  self-explanatory.
-
-  struct ops {
-    void (*start_usb_charging)(struct instance *i);
-    void (*stop_usb_charging)(struct instance *i);
-    int  (*get_battery_current)(struct instance *i);
-    int  (*get_battery_voltage)(struct instance *i);
-    void (*init_battery_charging)(struct instance *i);
-  }
-
-  2) Conversions of other methods
-  -------------------------------
-
-  Methods that can't be converted to new API are moved to board file or to
-  special file for board hacks.
-
-III) Analysis of in-tree drivers
---------------------------------
-
-  ftpmu010.c
-  ----------
-  All methods of this file are moved to another location.
-    void ftpmu010_32768osc_enable(void): Move to boards hacks
-    void ftpmu010_mfpsr_select_dev(unsigned int dev): Move to board file
-                                                     arch/nds32/lib/board.c
-    void ftpmu010_mfpsr_diselect_dev(unsigned int dev): Dead code
-    void ftpmu010_dlldis_disable(void): Dead code
-    void ftpmu010_sdram_clk_disable(unsigned int cr0): Move to board file
-                                                      arch/nds32/lib/board.c
-    void ftpmu010_sdramhtc_set(unsigned int val): Move to board file
-                                                 arch/nds32/lib/board.c
-
-  twl4030.c
-  ---------
-  All methods of this file are moved to another location.
-    void twl4030_power_reset_init(void): Move to board hacks
-    void twl4030_pmrecv_vsel_cfg(u8 vsel_reg, u8 vsel_val, u8 dev_grp,
-                                u8 dev_grp_sel): Move to board hacks
-    void twl4030_power_init(void): Move to board hacks
-    void twl4030_power_mmc_init(void): Move to board hacks
-
-  twl6030.c
-  ---------
-  Some methods are converted to new API and rest are moved to another location.
-    void twl6030_stop_usb_charging(void): Convert to new API
-    void twl6030_start_usb_charging(void): Convert to new API
-    int twl6030_get_battery_current(void): Convert to new API
-    int twl6030_get_battery_voltage(void): Convert to new API
-    void twl6030_init_battery_charging(void): Convert to new API
-    void twl6030_power_mmc_init(): Move to board file
-                                  drivers/mmc/omap_hsmmc.c
-    void twl6030_usb_device_settings(): Move to board file
-                                       drivers/usb/musb/omap3.c
diff --git a/doc/driver-model/UDM-rtc.txt b/doc/driver-model/UDM-rtc.txt
deleted file mode 100644 (file)
index 3640d24..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-=============================
-RTC device subsystem analysis
-=============================
-
-Tomas Hlavacek <tmshlvck@gmail.com>
-2012-03-10
-
-I) Overview
------------
-
-U-Boot currently implements one common API for RTC devices. The interface
-is defined in include/rtc.h and comprises of functions and structures:
-
-    struct rtc_time {
-       int tm_sec;
-       int tm_min;
-       int tm_hour;
-       int tm_mday;
-       int tm_mon;
-       int tm_year;
-       int tm_wday;
-       int tm_yday;
-       int tm_isdst;
-    };
-
-    int rtc_get (struct rtc_time *);
-    int rtc_set (struct rtc_time *);
-    void rtc_reset (void);
-
-The functions are implemented by a proper device driver in drivers/rtc
-directory and the driver to be compiled in is selected in a Makefile.
-Drivers are mutually exclusive.
-
-Drivers depends on date code in drivers/rtc/date.c and naturally on board
-specific data.
-
-II) Approach
-------------
-
-  1) New API
-  ----------
-  In the UDM each rtc driver would register itself by a function
-
-    int rtc_device_register(struct instance *i,
-                           struct rtc_device_ops *o);
-
-  The structure being defined as follows:
-
-    struct rtc_device_ops {
-       int  (*get_time)(struct instance *i, struct rtc_time *t);
-       int  (*set_time)(struct instance *i, struct rtc_time *t);
-       int  (*reset)(struct instance *i);
-    };
-
-
-  2) Conversion thougths
-  ----------------------
-  U-Boot RTC drivers exports the same functions and therefore the conversion
-  of the drivers is straight-forward. There is no initialization needed.
-
-
-III) Analysis of in-tree drivers
---------------------------------
-
-  drivers/rtc/rv3029.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/s3c24x0_rtc.c
-  -------------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/pt7c4338.c
-  ----------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/mvrtc.c
-  -------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/ftrtc010.c
-  ----------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/mpc5xxx.c
-  ---------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/ds164x.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/rs5c372.c
-  ---------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/m41t94.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/mc13xxx-rtc.c
-  -------------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/mcfrtc.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/davinci.c
-  ---------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/rx8025.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/bfin_rtc.c
-  ----------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/m41t62.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/ds1306.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/mpc8xx.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/ds3231.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/ds12887.c
-  ---------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/ds1302.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/ds1374.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/ds174x.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/m41t60.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/m48t35ax.c
-  ----------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/pl031.c
-  -------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/x1205.c
-  -------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/m41t11.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/pcf8563.c
-  ---------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/mk48t59.c
-  ---------------------
-  Macros needs cleanup. Besides that the driver is standard rtc.
-  Simple conversion is possible.
-
-
-  drivers/rtc/mxsrtc.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/ds1307.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/ds1556.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/rtc4543.c
-  ---------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/ds1337.c
-  --------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/isl1208.c
-  ---------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/max6900.c
-  ---------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/mc146818.c
-  ----------------------
-  The driver is standard rtc. Simple conversion is possible.
-
-
-  drivers/rtc/at91sam9_rtt.c
-  --------------------------
-  The driver is standard rtc. Simple conversion is possible.
diff --git a/doc/driver-model/UDM-serial.txt b/doc/driver-model/UDM-serial.txt
deleted file mode 100644 (file)
index ed804a8..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-Serial I/O analysis
-===================
-Marek Vasut <marek.vasut@gmail.com>
-2012-02-20
-
-I) Overview
------------
-
-The serial port support currently requires the driver to export the following
-functions:
-
-  serial_putc() ...... Output a character
-  serial_puts() ...... Output string, often done using serial_putc()
-  serial_tstc() ...... Test if incoming character is in a buffer
-  serial_getc() ...... Retrieve incoming character
-  serial_setbrg() .... Configure port options
-  serial_init() ...... Initialize the hardware
-
-The simpliest implementation, supporting only one port, simply defines these six
-functions and calls them. Such calls are scattered all around U-Boot, especiall
-serial_putc(), serial_puts(), serial_tstc() and serial_getc(). The serial_init()
-and serial_setbrg() are often called from platform-dependent places.
-
-It's important to consider current implementation of CONFIG_SERIAL_MULTI though.
-This resides in common/serial.c and behaves as a multiplexer for serial ports.
-This, by calling serial_assign(), allows user to switch I/O from one serial port
-to another. Though the environmental variables "stdin", "stdout", "stderr"
-remain set to "serial".
-
-These variables are managed by the IOMUX. This resides in common/iomux.c and
-manages all console input/output from U-Boot. For serial port, only one IOMUX is
-always registered, called "serial" and the switching of different serial ports
-is done by code in common/serial.c.
-
-On a final note, it's important to mention function default_serial_console(),
-which is platform specific and reports the default serial console for the
-platform, unless proper environment variable overrides this.
-
-II) Approach
-------------
-
-Drivers not using CONFIG_SERIAL_MULTI already will have to be converted to
-similar approach. The probe() function of a driver will call a function
-registering the driver with a STDIO subsystem core, stdio_device_register().
-
-The serial_init() function will now be replaced by probe() function of the
-driver, the rest of the components of the driver will be converted to standard
-STDIO driver calls. See [ UDM-stdio.txt ] for details.
-
-The serial_setbrg() function depends on global data pointer. This is wrong,
-since there is likely to be user willing to configure different baudrate on two
-different serial ports. The function will be replaced with STDIO's "conf()"
-call, with STDIO_CONFIG_SERIAL_BAUDRATE argument.
-
-III) Analysis of in-tree drivers
---------------------------------
-
-  altera_jtag_uart.c
-  ------------------
-  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
-
-  altera_uart.c
-  -------------
-  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
-
-  arm_dcc.c
-  ---------
-  No support for CONFIG_SERIAL_MULTI. Simple conversion possible, unless used
-  with CONFIG_ARM_DCC_MULTI. Then it registers another separate IOMUX.
-
-  atmel_usart.c
-  -------------
-  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
-
-  mcfuart.c
-  ---------
-  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
-
-  ns16550.c
-  ---------
-  This driver seems complicated and certain consideration will need to be made
-  during conversion. This driver is implemented in very universal manner,
-  therefore it'll be necessary to properly design it's platform_data.
-
-  opencores_yanu.c
-  ----------------
-  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
-
-  sandbox.c
-  ---------
-  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
-
-  serial.c
-  --------
-  This is a complementary part of NS16550 UART driver, see above.
-
-  serial_imx.c
-  ------------
-  No support for CONFIG_SERIAL_MULTI. Simple conversion possible. This driver
-  might be removed in favor of serial_mxc.c .
-
-  serial_ks8695.c
-  ---------------
-  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
-
-  serial_max3100.c
-  ----------------
-  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
-
-  serial_mxc.c
-  ------------
-  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
-
-  serial_pl01x.c
-  --------------
-  No support for CONFIG_SERIAL_MULTI. Simple conversion possible, though this
-  driver in fact contains two drivers in total.
-
-  serial_pxa.c
-  ------------
-  This driver is a bit complicated, but due to clean support for
-  CONFIG_SERIAL_MULTI, there are no expected obstructions throughout the
-  conversion process.
-
-  serial_s3c24x0.c
-  ----------------
-  This driver, being quite ad-hoc might need some work to bring back to shape.
-
-  serial_s5p.c
-  ------------
-  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
-
-  serial_sa1100.c
-  ---------------
-  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
-
-  serial_sh.c
-  -----------
-  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
-
-  serial_xuartlite.c
-  ------------------
-  No support for CONFIG_SERIAL_MULTI. Simple conversion possible.
-
-  usbtty.c
-  --------
-  This driver seems very complicated and entangled with USB framework. The
-  conversion might be complicated here.
-
-  arch/powerpc/cpu/mpc512x/serial.c
-  ---------------------------------
-  This driver supports CONFIG_SERIAL_MULTI. This driver will need to be moved to
-  proper place.
diff --git a/doc/driver-model/UDM-spi.txt b/doc/driver-model/UDM-spi.txt
deleted file mode 100644 (file)
index 9ba0f84..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-SPI analysis
-============
-Viktor Krivak <viktor.krivak@gmail.com>
-2012-03-03
-
-I) Overview
------------
-
-  1) The SPI driver
-  -----------------
-
-  At this moment U-Boot provides standard API that consist of 7 functions:
-
-  void spi_init(void);
-  struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-                                   unsigned int max_hz, unsigned int mode);
-  void spi_free_slave(struct spi_slave *slave);
-  int  spi_claim_bus(struct spi_slave *slave);
-  void spi_release_bus(struct spi_slave *slave);
-  int  spi_xfer(struct spi_slave *slave, unsigned int bitlen,
-               const void *dout, void *din, unsigned long flags);
-  int  spi_cs_is_valid(unsigned int bus, unsigned int cs);
-  void spi_cs_activate(struct spi_slave *slave);
-  void spi_cs_deactivate(struct spi_slave *slave);
-  void spi_set_speed(struct spi_slave *slave, uint hz);
-
-  Method spi_init() is usually empty. All necessary configuration are sets by
-  spi_setup_slave(). But this configuration is usually stored only in memory.
-  No real hardware sets are made. All hardware settings are provided by method
-  spi_claim_bus(). This method claims the bus and it can't be claimed again
-  until it's release. That's mean all calls of method spi_claim_bus() will
-  fail. But lots of cpu implementation don't meet this behaviour.
-  Method spi_release_bus() does exact opposite. It release bus directly by
-  some hardware sets. spi_free_slave() only free memory allocated by
-  spi_setup_slave(). Method spi_xfer() do actually read and write operation
-  throw specified bus and cs. Other methods are self explanatory.
-
-  2) Current limitations
-  ----------------------
-
-  Theoretically at this moment api allows use more then one bus per device at
-  the time. But in real this can be achieved only when all buses have their
-  own base addresses in memory.
-
-
-II) Approach
-------------
-
-  1) Claiming bus
-  ---------------
-
-  The current api cannot be used because struct spi_slave have to be in
-  private data. In that case user are prohibited to use different bus on one
-  device at same time. But when base memory address for bus are different.
-  It's possible make more instance of this driver. Otherwise it can't can be
-  done because of hardware limitation.
-
-  2) API change
-  -------------
-
-  Method spi_init() is moved to probe. Methods spi_setup_slave() and
-  spi_claim_bus() are joined to one method. This method checks if desired bus
-  exists and is available then configure necessary hardware and claims bus.
-  Method spi_release_bus() and spi_free_slave() are also joined to meet this
-  new approach. Other function remain same. Only struct spi_slave was change
-  to instance.
-
-  struct ops {
-    int  (*spi_request_bus)(struct instance *i, unsigned int bus,
-                           unsigned int cs, unsigned int max_hz,
-                           unsigned int mode);
-    void (*spi_release_bus)(struct instance *i);
-    int  (*spi_xfer) (struct instance *i, unsigned int bitlen,
-                     const void *dout, void *din, unsigned long flags);
-    int  (*spi_cs_is_valid)(struct instance *i, unsigned int bus,
-                           unsigned int cs);
-    void (*spi_cs_activate)(struct instance *i);
-    void (*spi_cs_deactivate)(struct instance *i);
-    void (*spi_set_speed)(struct instance *i, uint hz);
-  }
-
-  3) Legacy API
-  -------------
-
-  To easy conversion of the whole driver. Original and new api can exist next
-  to each other. New API is designed to be only a wrapper that extracts
-  necessary information from private_data and use old api. When driver can
-  use more than one bus at the time. New API require multiple instance. One
-  for each bus. In this case spi_slave have to be copied in each instance.
-
-  4) Conversion TIME-LINE
-  -----------------------
-
-  To prevent build corruption api conversion have to be processed in several
-  independent steps. In first step all old API methods are renamed. After that
-  new API and core function are implemented. Next step is conversion of all
-  board init methods to set platform data. After all these steps it is possible
-  to start conversion of all remaining calls. This procedure guarantees that
-  build procedure and binaries are never broken.
-
-III) Analysis of in-tree drivers
---------------------------------
-
-  altera_spi.c
-  ------------
-  All methods have designated structure. Simple conversion possible.
-
-  andes_spi.c
-  -----------
-  All methods have designated structure. Simple conversion possible.
-
-  andes_spi.h
-  -----------
-  Support file for andes_spi.c. No conversion is needed.
-
-  armada100_spi.c
-  ---------------
-  All methods have designated structure. Simple conversion possible.
-
-  atmel_dataflash_spi.c
-  ---------------------
-  Wrong placement. Will be moved to another location.
-
-  atmel_spi.c
-  -----------
-  Supports more than one bus. Need some minor change.
-
-  atmel_spi.h
-  -----------
-  Support file for andes_spi.c. No conversion is needed.
-
-  bfin_spi.c
-  ----------
-  Supports more than one bus. Need some minor change.
-
-  cf_spi.c
-  --------
-  Cooperate with some cpu specific methods from other files. Hard conversion.
-
-  davinci_spi.c
-  -------------
-  All methods have designated structure. Simple conversion possible.
-
-  davinci_spi.h
-  -------------
-  Support file for davinci_spi.h. No conversion is needed.
-
-  fsl_espi.c
-  ----------
-  All methods have designated structure. Simple conversion possible.
-
-  kirkwood_spi.c
-  --------------
-  All methods have designated structure. Simple conversion possible.
-
-  mpc8xxx_spi.c
-  -------------
-  All methods have designated structure. Simple conversion possible.
-
-  mpc52xx_spi.c
-  -------------
-  All methods have designated structure. Simple conversion possible.
-
-  mxc_spi.c
-  ---------
-  All methods have designated structure. Simple conversion possible.
-
-  mxs_spi.c
-  ---------
-  All methods have designated structure. Simple conversion possible.
-
-  oc_tiny_spi.c
-  -------------
-  Supports more than one bus. Need some minor change.
-
-  omap3_spi.c
-  -----------
-  Supports more than one bus. Need some minor change.
-
-  omap3_spi.h
-  -----------
-  Support file for omap3_spi.c. No conversion is needed.
-
-  sh_spi.c
-  --------
-  All methods have designated structure. Simple conversion possible.
-
-  sh_spi.h
-  --------
-  Support file for sh_spi.h. No conversion is needed.
-
-  soft_spi.c
-  ----------
-  Use many board specific method linked from other files. Need careful debugging.
-
-  tegra2_spi.c
-  ------------
-  Some hardware specific problem when releasing bus.
diff --git a/doc/driver-model/UDM-stdio.txt b/doc/driver-model/UDM-stdio.txt
deleted file mode 100644 (file)
index 156627b..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-I/O system analysis
-===================
-Marek Vasut <marek.vasut@gmail.com>
-2012-02-20
-
-I) Overview
------------
-
-The console input and output is currently done using the STDIO subsystem in
-U-Boot. The design of this subsystem is already flexible enough to be easily
-converted to new driver model approach. Minor changes will need to be done
-though.
-
-Each device that wants to register with STDIO subsystem has to define struct
-stdio_dev, defined in include/stdio_dev.h and containing the following fields:
-
-struct stdio_dev {
-       int     flags;                  /* Device flags: input/output/system */
-       int     ext;                    /* Supported extensions              */
-       char    name[16];               /* Device name                       */
-
-/* GENERAL functions */
-
-       int (*start) (void);            /* To start the device               */
-       int (*stop) (void);             /* To stop the device                */
-
-/* OUTPUT functions */
-
-       void (*putc) (const char c);    /* To put a char                     */
-       void (*puts) (const char *s);   /* To put a string (accelerator)     */
-
-/* INPUT functions */
-
-       int (*tstc) (void);             /* To test if a char is ready...     */
-       int (*getc) (void);             /* To get that char                  */
-
-/* Other functions */
-
-       void *priv;                     /* Private extensions                */
-       struct list_head list;
-};
-
-Currently used flags are DEV_FLAGS_INPUT, DEV_FLAGS_OUTPUT and DEV_FLAGS_SYSTEM,
-extensions being only one, the DEV_EXT_VIDEO.
-
-The private extensions are now used as a per-device carrier of private data and
-finally list allows this structure to be a member of linked list of STDIO
-devices.
-
-The STDIN, STDOUT and STDERR routing is handled by environment variables
-"stdin", "stdout" and "stderr". By configuring the variable to the name of a
-driver, functions of such driver are called to execute that particular
-operation.
-
-II) Approach
-------------
-
-  1) Similarity of serial, video and keyboard drivers
-  ---------------------------------------------------
-
-  All of these drivers can be unified under the STDIO subsystem if modified
-  slightly. The serial drivers basically define both input and output functions
-  and need function to configure baudrate. The keyboard drivers provide only
-  input. On the other hand, video drivers provide output, but need to be
-  configured in certain way. This configuration might be dynamic, therefore the
-  STDIO has to be modified to provide such flexibility.
-
-  2) Unification of serial, video and keyboard drivers
-  ----------------------------------------------------
-
-  Every STDIO device would register a structure containing operation it supports
-  with the STDIO core by calling:
-
-    int stdio_device_register(struct instance *i, struct stdio_device_ops *o);
-
-  The structure being defined as follows:
-
-  struct stdio_device_ops {
-    void (*putc)(struct instance *i, const char c);
-    void (*puts)(struct instance *i, const char *s);    /* OPTIONAL */
-
-    int  (*tstc)(struct instance *i);
-    int  (*getc)(struct instance *i);
-
-    int  (*init)(struct instance *i);
-    int  (*exit)(struct instance *i);
-    int  (*conf)(struct instance *i, enum stdio_config c, const void *data);
-  };
-
-  The "putc()" function will emit a character, the "puts()" function will emit a
-  string. If both of these are set to NULL, the device is considered STDIN only,
-  aka input only device.
-
-  The "getc()" retrieves a character from a STDIN device, while "tstc()" tests
-  if there is a character in the buffer of STDIN device. In case these two are
-  set to NULL, this device is STDOUT / STDERR device.
-
-  Setting all "putc()", "puts()", "getc()" and "tstc()" calls to NULL isn't an
-  error condition, though such device does nothing. By instroducing tests for
-  these functions being NULL, the "flags" and "ext" fields from original struct
-  stdio_dev can be eliminated.
-
-  The "init()" and "exit()" calls are replacement for "start()" and "exit()"
-  calls in the old approach. The "priv" part of the old struct stdio_dev will be
-  replaced by common private data in the driver model and the struct list_head
-  list will be eliminated by introducing common STDIO core, that tracks all the
-  STDIO devices.
-
-  Lastly, the "conf()" call will allow the user to configure various options of
-  the driver. The enum stdio_config contains all possible configuration options
-  available to the STDIO devices, const void *data being the argument to be
-  configured. Currently, the enum stdio_config will contain at least the
-  following options:
-
-  enum stdio_config {
-    STDIO_CONFIG_SERIAL_BAUDRATE,
-  };
-
-  3) Transformation of stdio routing
-  ----------------------------------
-
-  By allowing multiple instances of drivers, the environment variables "stdin",
-  "stdout" and "stderr" can no longer be set to the name of the driver.
-  Therefore the STDIO core, tracking all of the STDIO devices in the system will
-  need to have a small amount of internal data for each device:
-
-  struct stdio_device_node {
-    struct instance          *i;
-    struct stdio_device_ops  *ops;
-    uint8_t                  id;
-    uint8_t                  flags;
-    struct list_head         list;
-  }
-
-  The "id" is the order of the instance of the same driver. The "flags" variable
-  allows multiple drivers to be used at the same time and even for different
-  purpose. The following flags will be defined:
-
-    STDIO_FLG_STDIN ..... This device will be used as an input device. All input
-                         from all devices with this flag set will be received
-                         and passed to the upper layers.
-    STDIO_FLG_STDOUT .... This device will be used as an output device. All
-                         output sent to stdout will be routed to all devices
-                         with this flag set.
-    STDIO_FLG_STDERR .... This device will be used as an standard error output
-                         device. All output sent to stderr will be routed to
-                         all devices with this flag set.
-
-  The "list" member of this structure allows to have a linked list of all
-  registered STDIO devices.
-
-III) Analysis of in-tree drivers
---------------------------------
-
-For in-depth analysis of serial port drivers, refer to [ UDM-serial.txt ].
-For in-depth analysis of keyboard drivers, refer to [ UDM-keyboard.txt ].
-For in-depth analysis of video drivers, refer to [ UDM-video.txt ].
-
-  arch/blackfin/cpu/jtag-console.c
-  --------------------------------
-  This driver is a classic STDIO driver, no problem with conversion is expected.
-
-  board/mpl/pati/pati.c
-  ---------------------
-  This driver registers with the STDIO framework, though it uses a lot of ad-hoc
-  stuff which will need to be sorted out.
-
-  board/netphone/phone_console.c
-  ------------------------------
-  This driver is a classic STDIO driver, no problem with conversion is expected.
-
-  drivers/net/netconsole.c
-  ------------------------
-  This driver is a classic STDIO driver, no problem with conversion is expected.
-
-IV) Other involved files (To be removed)
-----------------------------------------
-
-common/cmd_console.c
-common/cmd_log.c
-common/cmd_terminal.c
-common/console.c
-common/fdt_support.c
-common/iomux.c
-common/lcd.c
-common/serial.c
-common/stdio.c
-common/usb_kbd.c
-doc/README.iomux
diff --git a/doc/driver-model/UDM-tpm.txt b/doc/driver-model/UDM-tpm.txt
deleted file mode 100644 (file)
index 0beff4a..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-TPM system analysis
-===================
-Marek Vasut <marek.vasut@gmail.com>
-2012-02-23
-
-I) Overview
------------
-
-There is currently only one TPM chip driver available and therefore the API
-controlling it is very much based on this. The API is very simple:
-
-  int tis_open(void);
-  int tis_close(void);
-  int tis_sendrecv(const u8 *sendbuf, size_t send_size,
-                        u8 *recvbuf, size_t *recv_len);
-
-The command operating the TPM chip only provides operations to send and receive
-bytes from the chip.
-
-II) Approach
-------------
-
-The API can't be generalised too much considering there's only one TPM chip
-supported. But it's a good idea to split the tis_sendrecv() function in two
-functions. Therefore the new API will use register the TPM chip by calling:
-
-  tpm_device_register(struct instance *i, const struct tpm_ops *ops);
-
-And the struct tpm_ops will contain the following members:
-
-  struct tpm_ops {
-    int (*tpm_open)(struct instance *i);
-    int (*tpm_close)(struct instance *i);
-    int (*tpm_send)(const uint8_t *buf, const size_t size);
-    int (*tpm_recv)(uint8_t *buf, size_t *size);
-  };
-
-The behaviour of "tpm_open()" and "tpm_close()" will basically copy the
-behaviour of "tis_open()" and "tis_close()". The "tpm_send()" will be based on
-the "tis_senddata()" and "tis_recv()" will be based on "tis_readresponse()".
-
-III) Analysis of in-tree drivers
---------------------------------
-
-There is only one in-tree driver present, the "drivers/tpm/generic_lpc_tpm.c",
-which will be simply converted as outlined in previous chapter.
diff --git a/doc/driver-model/UDM-twserial.txt b/doc/driver-model/UDM-twserial.txt
deleted file mode 100644 (file)
index 5f2c5a3..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-==================================
-TWserial device subsystem analysis
-==================================
-
-Tomas Hlavacek<tmshlvck@gmail.com>
-2012-03-21
-
-I) Overview
------------
-
-U-Boot currently implements one common API for TWSerial devices. The interface
-is defined in include/tws.h and comprises of functions:
-
-    int tws_read(uchar *buffer, int len);
-    int tws_write(uchar *buffer, int len);
-
-The functions are implemented by a proper device driver in drivers/twserial
-directory and the driver to be compiled in is selected in a Makefile. There is
-only one driver present now.
-
-The driver depends on ad-hoc code in board specific data, namely functions:
-
-    void tws_ce(unsigned bit);
-    void tws_wr(unsigned bit);
-    void tws_clk(unsigned bit);
-    void tws_data(unsigned bit);
-    unsigned tws_data_read(void);
-    void tws_data_config_output(unsigned output);
-
-implemented in include/configs/inka4x0.h .
-
-II) Approach
-------------
-
-  U-Boot TWserial drivers exports two simple functions and therefore the conversion
-  of the driver and creating a core for it is not needed. It should be consolidated
-  with include/configs/inka4x0.h and taken to the misc/ dir.
-
-
-III) Analysis of in-tree drivers
---------------------------------
-
-  drivers/twserial/soft_tws.c
-  ---------------------------
-  The driver is the only TWserial driver. The ad-hoc part in
-  include/configs/inka4x0.h and the core soft_tws driver should be consolidated
-  to one compact driver and moved to misc/ .
diff --git a/doc/driver-model/UDM-usb.txt b/doc/driver-model/UDM-usb.txt
deleted file mode 100644 (file)
index 5ce85b5..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-USB analysis
-============
-Marek Vasut <marek.vasut@gmail.com>
-2012-02-16
-
-I) Overview
------------
-
-  1) The USB Host driver
-  ----------------------
-  There are basically four or five USB host drivers. All such drivers currently
-  provide at least the following fuctions:
-
-    usb_lowlevel_init() ... Do the initialization of the USB controller hardware
-    usb_lowlevel_stop() ... Do the shutdown of the USB controller hardware
-
-    usb_event_poll() ...... Poll interrupt from USB device, often used by KBD
-
-    submit_control_msg() .. Submit message via Control endpoint
-    submit_int_msg() ...... Submit message via Interrupt endpoint
-    submit_bulk_msg() ..... Submit message via Bulk endpoint
-
-
-    This allows for the host driver to be easily abstracted.
-
-  2) The USB hierarchy
-  --------------------
-
-  In the current implementation, the USB Host driver provides operations to
-  communicate via the USB bus. This is realised by providing access to a USB
-  root port to which an USB root hub is attached. The USB bus is scanned and for
-  each newly found device, a struct usb_device is allocated. See common/usb.c
-  and include/usb.h for details.
-
-II) Approach
-------------
-
-  1) The USB Host driver
-  ----------------------
-
-  Converting the host driver will follow the classic driver model consideration.
-  Though, the host driver will have to call a function that registers a root
-  port with the USB core in it's probe() function, let's call this function
-
-    usb_register_root_port(&ops);
-
-  This will allow the USB core to track all available root ports. The ops
-  parameter will contain structure describing operations supported by the root
-  port:
-
-  struct usb_port_ops {
-    void   (*usb_event_poll)();
-    int    (*submit_control_msg)();
-    int    (*submit_int_msg)();
-    int    (*submit_bulk_msg)();
-  }
-
-  2) The USB hierarchy and hub drivers
-  ------------------------------------
-
-  Converting the USB heirarchy should be fairy simple, considering the already
-  dynamic nature of the implementation. The current usb_hub_device structure
-  will have to be converted to a struct instance. Every such instance will
-  contain components of struct usb_device and struct usb_hub_device in it's
-  private data, providing only accessors in order to properly encapsulate the
-  driver.
-
-  By registering the root port, the USB framework will instantiate a USB hub
-  driver, which is always present, the root hub. The root hub and any subsequent
-  hub instance is represented by struct instance and it's private data contain
-  amongst others common bits from struct usb_device.
-
-  Note the USB hub driver is partly defying the usual method of registering a
-  set of callbacks to a particular core driver. Instead, a static set of
-  functions is defined and the USB hub instance is passed to those. This creates
-  certain restrictions as of how the USB hub driver looks, but considering the
-  specification for USB hub is given and a different type of USB hub won't ever
-  exist, this approach is ok:
-
-  - Report how many ports does this hub have:
-      uint get_nr_ports(struct instance *hub);
-  - Get pointer to device connected to a port:
-      struct instance *(*get_child)(struct instance *hub, int port);
-  - Instantiate and configure device on port:
-      struct instance *(*enum_dev_on_port)(struct instance *hub, int port);
-
-  3) USB device drivers
-  ---------------------
-
-  The USB device driver, in turn, will have to register various ops structures
-  with certain cores. For example, USB disc driver will have to register it's
-  ops with core handling USB discs etc.
diff --git a/doc/driver-model/UDM-video.txt b/doc/driver-model/UDM-video.txt
deleted file mode 100644 (file)
index e67e9e4..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-Video output analysis
-=====================
-Marek Vasut <marek.vasut@gmail.com>
-2012-02-20
-
-I) Overview
------------
-
-The video drivers are most often registered with video subsystem. This subsystem
-often expects to be allowed access to framebuffer of certain parameters. This
-subsystem also provides calls for STDIO subsystem to allow it to output
-characters on the screen. For this part, see [ UDM-stdio.txt ].
-
-Therefore the API has two parts, the video driver part and the part where the
-video driver core registers with STDIO API.
-
-The video driver part will follow the current cfb_console approach, though
-allowing it to be more dynamic.
-
-II) Approach
-------------
-
-Registering the video driver into the video driver core is done by calling the
-following function from the driver probe() function:
-
-  video_device_register(struct instance *i, GraphicDevice *gd);
-
-Because the video driver core is in charge or rendering characters as well as
-bitmaps on the screen, it will in turn call stdio_device_register(i, so), where
-"i" is the same instance as the video driver's one. But "so" will be special
-static struct stdio_device_ops handling the character output.
-
-
-III) Analysis of in-tree drivers
---------------------------------
-
-  arch/powerpc/cpu/mpc8xx/video.c
-  -------------------------------
-  This driver copies the cfb_console [ see drivers/video/cfb_console.c ]
-  approach and acts only as a STDIO device. Therefore there are currently two
-  possible approaches, first being the conversion of this driver to usual STDIO
-  device and second, long-term one, being conversion of this driver to video
-  driver that provides console.
-
-  arch/x86/lib/video.c
-  --------------------
-  This driver registers two separate STDIO devices and should be therefore
-  converted as such.
-
-  board/bf527-ezkit/video.c
-  -------------------------
-  This driver seems bogus as it behaves as STDIO device, but provides no input
-  or output capabilities. It relies on DEV_EXT_VIDEO, which is no longer in use
-  or present otherwise than as a dead code/define.
-
-  board/bf533-stamp/video.c
-  -------------------------
-  This driver seems bogus as it behaves as STDIO device, but provides no input
-  or output capabilities. It relies on DEV_EXT_VIDEO, which is no longer in use
-  or present otherwise than as a dead code/define.
-
-  board/bf548-ezkit/video.c
-  -------------------------
-  This driver seems bogus as it behaves as STDIO device, but provides no input
-  or output capabilities. It relies on DEV_EXT_VIDEO, which is no longer in use
-  or present otherwise than as a dead code/define.
-
-  board/cm-bf548/video.c
-  ----------------------
-  This driver seems bogus as it behaves as STDIO device, but provides no input
-  or output capabilities. It relies on DEV_EXT_VIDEO, which is no longer in use
-  or present otherwise than as a dead code/define.
diff --git a/doc/driver-model/UDM-watchdog.txt b/doc/driver-model/UDM-watchdog.txt
deleted file mode 100644 (file)
index 3f13063..0000000
+++ /dev/null
@@ -1,329 +0,0 @@
-The U-Boot Driver Model Project
-===============================
-Watchdog device subsystem analysis
-==================================
-
-Tomas Hlavacek <tmshlvck@gmail.com>
-2012-03-09
-
-I) Overview
------------
-
-U-Boot currently implements an API for HW watchdog devices as explicit drivers
-in drivers/watchdog directory. There are also drivers for both hardware and
-software watchdog on particular CPUs implemented in arch/*/cpu/*/cpu.c. There
-are macros in include/watchdog.h that selects between SW and HW watchdog and
-assembly SW implementation.
-
-The current common interface comprises of one set out of these two possible
-variants:
-
-    1)
-    void watchdog_reset(void);
-    int watchdog_disable(void);
-    int watchdog_init(void);
-
-    2)
-    void hw_watchdog_reset(void);
-    void hw_watchdog_init(void);
-
-The watchdog implementations are also spread through board/*/*.c that in
-some cases. The API and semantics is in most cases same as the above
-mentioned common functions.
-
-
-II) Approach
-------------
-
-  1) New API
-  ----------
-
-  In the UDM each watchdog driver would register itself by a function
-
-    int watchdog_device_register(struct instance *i,
-                                const struct watchdog_device_ops *o);
-
-  The structure being defined as follows:
-
-    struct watchdog_device_ops {
-       int (*disable)(struct instance *i);
-       void (*reset)(struct instance *i);
-    };
-
-  The watchdog_init() function will be dissolved into probe() function.
-
-  2) Conversion thougths
-  ----------------------
-
-  Conversion of watchdog implementations to a new API could be divided
-  to three subsections: a) HW implementations, which are mostly compliant
-  to the above mentioned API; b) SW implementations, which are compliant
-  to the above mentioned API and c) SW implementations that are not compliant
-  to the API and has to be rectified or partially rewritten.
-
-III) Analysis of in-tree drivers
---------------------------------
-
-  drivers/watchdog/at91sam9_wdt.c
-  -------------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  drivers/watchdog/ftwdt010_wdt.c
-  -------------------------------
-  The driver is ad-hoc HW watchdog. Conversion has to take into account
-  driver parts spread in include/faraday/*. Restructuring the driver and
-  code cleanup has to be considered.
-
-
-  arch/arm/cpu/arm1136/mx31/timer.c
-  ---------------------------------
-  The driver is semi-standard ad-hoc HW watchdog. Conversion has to take
-  into account driver parts spread in the timer.c file.
-
-
-  arch/arm/cpu/arm926ejs/davinci/timer.c
-  --------------------------------------
-  The driver is ad-hoc semi-standard HW watchdog. Conversion has to take
-  into account driver parts spread in the timer.c file.
-
-
-  arch/arm/cpu/armv7/omap-common/hwinit-common.c
-  ----------------------------------------------
-  The driver is non-standard ad-hoc HW watchdog. Conversion is possible
-  but functions has to be renamed and constants moved to another places.
-
-
-  arch/arm/cpu/armv7/omap3/board.c
-  --------------------------------
-  The driver is non-standard ad-hoc HW watchdog. Conversion is possible
-  but functions has to be renamed and constants moved to another places.
-
-
-  arch/blackfin/cpu/watchdog.c
-  ----------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  arch/m68k/cpu/mcf523x/cpu.c
-  ---------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  arch/m68k/cpu/mcf52x2/cpu.c
-  ---------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  arch/m68k/cpu/mcf532x/cpu.c
-  ---------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  arch/m68k/cpu/mcf547x_8x/cpu.c
-  ------------------------------
-  The driver is standard HW watchdog (there is slight naming convention
-  violation that has to be rectified). Simple conversion is possible.
-
-
-  arch/powerpc/cpu/74xx_7xx/cpu.c
-  -------------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  arch/powerpc/cpu/mpc512x/cpu.c
-  ------------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  arch/powerpc/cpu/mpc5xx/cpu.c
-  -----------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  arch/powerpc/cpu/mpc5xxx/cpu.c
-  ------------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  arch/powerpc/cpu/mpc8260/cpu.c
-  ------------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  arch/powerpc/cpu/mpc83xx/cpu.c
-  ------------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  arch/powerpc/cpu/mpc85xx/cpu.c
-  ------------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  arch/powerpc/cpu/mpc86xx/cpu.c
-  ------------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  arch/powerpc/cpu/mpc8xx/cpu.c
-  -----------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  arch/powerpc/cpu/ppc4xx/cpu.c
-  -----------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  arch/sh/cpu/sh2/watchdog.c
-  --------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  arch/sh/cpu/sh3/watchdog.c
-  --------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  arch/sh/cpu/sh4/watchdog.c
-  --------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/amcc/luan/luan.c
-  ----------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/amcc/yosemite/yosemite.c
-  ------------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/apollon/apollon.c
-  -----------------------
-  The driver is standard HW watchdog however the watchdog_init()
-  function is called in early initialization. Simple conversion is possible.
-
-
-  board/bmw/m48t59y.c
-  -------------------
-  Special watchdog driver. Dead code. To be removed.
-
-
-  board/davedenx/qong/qong.c
-  --------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/dvlhost/watchdog.c
-  ------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/eNET/eNET.c
-  -----------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/eltec/elppc/elppc.c
-  -------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/enbw/enbw_cmc/enbw_cmc.c
-  ------------------------------
-  Only function proxy call. Code cleanup needed.
-
-
-  board/freescale/mx31pdk/mx31pdk.c
-  ---------------------------------
-  Only function proxy call. Code cleanup needed.
-
-
-  board/gth2/gth2.c
-  -----------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/lwmon5/lwmon5.c
-  ---------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/manroland/mucmc52/mucmc52.c
-  ---------------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/manroland/uc101/uc101.c
-  -----------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/mousse/m48t59y.c
-  ----------------------
-  Special watchdog driver. Dead code. To be removed.
-
-
-  board/mvblue/mvblue.c
-  ---------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/netphone/netphone.c
-  -------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/netta/netta.c
-  -------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/netta2/netta2.c
-  ---------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/omicron/calimain/calimain.c
-  ---------------------------------
-  Only function proxy call. Code cleanup needed.
-
-
-  board/pcs440ep/pcs440ep.c
-  -------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/stx/stxxtc/stxxtc.c
-  -------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/ti/omap2420h4/omap2420h4.c
-  --------------------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/ttcontrol/vision2/vision2.c
-  ---------------------------------
-  The driver is standard HW watchdog but namespace is polluted by
-  non-standard macros. Simple conversion is possible, code cleanup
-  needed.
-
-
-  board/v38b/v38b.c
-  -----------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/ve8313/ve8313.c
-  ---------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
-
-
-  board/w7o/watchdog.c
-  --------------------
-  The driver is standard HW watchdog. Simple conversion is possible.
diff --git a/drivers/core/Makefile b/drivers/core/Makefile
new file mode 100644 (file)
index 0000000..90b2a7f
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2013 Google, Inc
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-$(CONFIG_DM)       := device.o lists.o root.o uclass.o util.o
diff --git a/drivers/core/device.c b/drivers/core/device.c
new file mode 100644 (file)
index 0000000..55ba281
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * Device manager
+ *
+ * Copyright (c) 2013 Google, Inc
+ *
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <dm/device.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/platdata.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
+ *
+ * On error, the function continues to unbind all children, and reports the
+ * first error.
+ *
+ * @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, saved_ret = 0;
+
+       assert(dev);
+
+       list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
+               ret = device_unbind(pos);
+               if (ret && !saved_ret)
+                       saved_ret = ret;
+       }
+
+       return saved_ret;
+}
+
+/**
+ * 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;
+}
+
+int device_bind(struct device *parent, struct driver *drv, const char *name,
+               void *platdata, int of_offset, struct device **devp)
+{
+       struct device *dev;
+       struct uclass *uc;
+       int ret = 0;
+
+       *devp = NULL;
+       if (!name)
+               return -EINVAL;
+
+       ret = uclass_get(drv->id, &uc);
+       if (ret)
+               return ret;
+
+       dev = calloc(1, sizeof(struct device));
+       if (!dev)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&dev->sibling_node);
+       INIT_LIST_HEAD(&dev->child_head);
+       INIT_LIST_HEAD(&dev->uclass_node);
+       dev->platdata = platdata;
+       dev->name = name;
+       dev->of_offset = of_offset;
+       dev->parent = parent;
+       dev->driver = drv;
+       dev->uclass = uc;
+       if (!dev->platdata && drv->platdata_auto_alloc_size)
+               dev->flags |= DM_FLAG_ALLOC_PDATA;
+
+       /* put dev into parent's successor list */
+       if (parent)
+               list_add_tail(&dev->sibling_node, &parent->child_head);
+
+       ret = uclass_bind_device(dev);
+       if (ret)
+               goto fail_bind;
+
+       /* if we fail to bind we remove device from successors and free it */
+       if (drv->bind) {
+               ret = drv->bind(dev);
+               if (ret) {
+                       if (uclass_unbind_device(dev)) {
+                               dm_warn("Failed to unbind dev '%s' on error path\n",
+                                       dev->name);
+                       }
+                       goto fail_bind;
+               }
+       }
+       if (parent)
+               dm_dbg("Bound device %s to %s\n", dev->name, parent->name);
+       *devp = dev;
+
+       return 0;
+
+fail_bind:
+       list_del(&dev->sibling_node);
+       free(dev);
+       return ret;
+}
+
+int device_bind_by_name(struct device *parent, const struct driver_info *info,
+                       struct device **devp)
+{
+       struct driver *drv;
+
+       drv = lists_driver_lookup_name(info->name);
+       if (!drv)
+               return -ENOENT;
+
+       return device_bind(parent, drv, info->name, (void *)info->platdata,
+                          -1, devp);
+}
+
+int device_unbind(struct device *dev)
+{
+       struct driver *drv;
+       int ret;
+
+       if (!dev)
+               return -EINVAL;
+
+       if (dev->flags & DM_FLAG_ACTIVATED)
+               return -EINVAL;
+
+       drv = dev->driver;
+       assert(drv);
+
+       if (drv->unbind) {
+               ret = drv->unbind(dev);
+               if (ret)
+                       return ret;
+       }
+
+       ret = device_chld_unbind(dev);
+       if (ret)
+               return ret;
+
+       ret = uclass_unbind_device(dev);
+       if (ret)
+               return ret;
+
+       if (dev->parent)
+               list_del(&dev->sibling_node);
+       free(dev);
+
+       return 0;
+}
+
+/**
+ * device_free() - Free memory buffers allocated by a device
+ * @dev:       Device that is to be started
+ */
+static void device_free(struct device *dev)
+{
+       int size;
+
+       if (dev->driver->priv_auto_alloc_size) {
+               free(dev->priv);
+               dev->priv = NULL;
+       }
+       if (dev->flags & DM_FLAG_ALLOC_PDATA) {
+               free(dev->platdata);
+               dev->platdata = NULL;
+       }
+       size = dev->uclass->uc_drv->per_device_auto_alloc_size;
+       if (size) {
+               free(dev->uclass_priv);
+               dev->uclass_priv = NULL;
+       }
+}
+
+int device_probe(struct device *dev)
+{
+       struct driver *drv;
+       int size = 0;
+       int ret;
+
+       if (!dev)
+               return -EINVAL;
+
+       if (dev->flags & DM_FLAG_ACTIVATED)
+               return 0;
+
+       drv = dev->driver;
+       assert(drv);
+
+       /* Allocate private data and platdata if requested */
+       if (drv->priv_auto_alloc_size) {
+               dev->priv = calloc(1, drv->priv_auto_alloc_size);
+               if (!dev->priv) {
+                       ret = -ENOMEM;
+                       goto fail;
+               }
+       }
+       /* Allocate private data if requested */
+       if (dev->flags & DM_FLAG_ALLOC_PDATA) {
+               dev->platdata = calloc(1, drv->platdata_auto_alloc_size);
+               if (!dev->platdata) {
+                       ret = -ENOMEM;
+                       goto fail;
+               }
+       }
+       size = dev->uclass->uc_drv->per_device_auto_alloc_size;
+       if (size) {
+               dev->uclass_priv = calloc(1, size);
+               if (!dev->uclass_priv) {
+                       ret = -ENOMEM;
+                       goto fail;
+               }
+       }
+
+       /* Ensure all parents are probed */
+       if (dev->parent) {
+               ret = device_probe(dev->parent);
+               if (ret)
+                       goto fail;
+       }
+
+       if (drv->ofdata_to_platdata && dev->of_offset >= 0) {
+               ret = drv->ofdata_to_platdata(dev);
+               if (ret)
+                       goto fail;
+       }
+
+       if (drv->probe) {
+               ret = drv->probe(dev);
+               if (ret)
+                       goto fail;
+       }
+
+       dev->flags |= DM_FLAG_ACTIVATED;
+
+       ret = uclass_post_probe_device(dev);
+       if (ret) {
+               dev->flags &= ~DM_FLAG_ACTIVATED;
+               goto fail_uclass;
+       }
+
+       return 0;
+fail_uclass:
+       if (device_remove(dev)) {
+               dm_warn("%s: Device '%s' failed to remove on error path\n",
+                       __func__, dev->name);
+       }
+fail:
+       device_free(dev);
+
+       return ret;
+}
+
+int device_remove(struct device *dev)
+{
+       struct driver *drv;
+       int ret;
+
+       if (!dev)
+               return -EINVAL;
+
+       if (!(dev->flags & DM_FLAG_ACTIVATED))
+               return 0;
+
+       drv = dev->driver;
+       assert(drv);
+
+       ret = uclass_pre_remove_device(dev);
+       if (ret)
+               return ret;
+
+       ret = device_chld_remove(dev);
+       if (ret)
+               goto err;
+
+       if (drv->remove) {
+               ret = drv->remove(dev);
+               if (ret)
+                       goto err_remove;
+       }
+
+       device_free(dev);
+
+       dev->flags &= ~DM_FLAG_ACTIVATED;
+
+       return 0;
+
+err_remove:
+       /* We can't put the children back */
+       dm_warn("%s: Device '%s' failed to remove, but children are gone\n",
+               __func__, dev->name);
+err:
+       ret = uclass_post_probe_device(dev);
+       if (ret) {
+               dm_warn("%s: Device '%s' failed to post_probe on error path\n",
+                       __func__, dev->name);
+       }
+
+       return ret;
+}
+
+void *dev_get_platdata(struct device *dev)
+{
+       if (!dev) {
+               dm_warn("%s: null device", __func__);
+               return NULL;
+       }
+
+       return dev->platdata;
+}
+
+void *dev_get_priv(struct device *dev)
+{
+       if (!dev) {
+               dm_warn("%s: null device", __func__);
+               return NULL;
+       }
+
+       return dev->priv;
+}
diff --git a/drivers/core/lists.c b/drivers/core/lists.c
new file mode 100644 (file)
index 0000000..4f2c126
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * (C) Copyright 2012
+ * Marek Vasut <marex@denx.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <dm/device.h>
+#include <dm/device-internal.h>
+#include <dm/platdata.h>
+#include <dm/uclass.h>
+#include <dm/util.h>
+#include <linux/compiler.h>
+
+struct driver *lists_driver_lookup_name(const char *name)
+{
+       struct driver *drv =
+               ll_entry_start(struct driver, driver);
+       const int n_ents = ll_entry_count(struct driver, driver);
+       struct driver *entry;
+       int len;
+
+       if (!drv || !n_ents)
+               return NULL;
+
+       len = strlen(name);
+
+       for (entry = drv; entry != drv + n_ents; entry++) {
+               if (strncmp(name, entry->name, len))
+                       continue;
+
+               /* Full match */
+               if (len == strlen(entry->name))
+                       return entry;
+       }
+
+       /* Not found */
+       return NULL;
+}
+
+struct uclass_driver *lists_uclass_lookup(enum uclass_id id)
+{
+       struct uclass_driver *uclass =
+               ll_entry_start(struct uclass_driver, uclass);
+       const int n_ents = ll_entry_count(struct uclass_driver, uclass);
+       struct uclass_driver *entry;
+
+       if ((id == UCLASS_INVALID) || !uclass)
+               return NULL;
+
+       for (entry = uclass; entry != uclass + n_ents; entry++) {
+               if (entry->id == id)
+                       return entry;
+       }
+
+       return NULL;
+}
+
+int lists_bind_drivers(struct device *parent)
+{
+       struct driver_info *info =
+               ll_entry_start(struct driver_info, driver_info);
+       const int n_ents = ll_entry_count(struct driver_info, driver_info);
+       struct driver_info *entry;
+       struct device *dev;
+       int result = 0;
+       int ret;
+
+       for (entry = info; entry != info + n_ents; entry++) {
+               ret = device_bind_by_name(parent, entry, &dev);
+               if (ret) {
+                       dm_warn("No match for driver '%s'\n", entry->name);
+                       if (!result || ret != -ENOENT)
+                               result = ret;
+               }
+       }
+
+       return result;
+}
+
+#ifdef CONFIG_OF_CONTROL
+/**
+ * driver_check_compatible() - Check if a driver is compatible with this node
+ *
+ * @param blob:                Device tree pointer
+ * @param offset:      Offset of node in device tree
+ * @param of_matchL    List of compatible strings to match
+ * @return 0 if there is a match, -ENOENT if no match, -ENODEV if the node
+ * does not have a compatible string, other error <0 if there is a device
+ * tree error
+ */
+static int driver_check_compatible(const void *blob, int offset,
+                                  const struct device_id *of_match)
+{
+       int ret;
+
+       if (!of_match)
+               return -ENOENT;
+
+       while (of_match->compatible) {
+               ret = fdt_node_check_compatible(blob, offset,
+                                               of_match->compatible);
+               if (!ret)
+                       return 0;
+               else if (ret == -FDT_ERR_NOTFOUND)
+                       return -ENODEV;
+               else if (ret < 0)
+                       return -EINVAL;
+               of_match++;
+       }
+
+       return -ENOENT;
+}
+
+int lists_bind_fdt(struct device *parent, const void *blob, int offset)
+{
+       struct driver *driver = ll_entry_start(struct driver, driver);
+       const int n_ents = ll_entry_count(struct driver, driver);
+       struct driver *entry;
+       struct device *dev;
+       const char *name;
+       int result = 0;
+       int ret;
+
+       dm_dbg("bind node %s\n", fdt_get_name(blob, offset, NULL));
+       for (entry = driver; entry != driver + n_ents; entry++) {
+               ret = driver_check_compatible(blob, offset, entry->of_match);
+               if (ret == -ENOENT) {
+                       continue;
+               } else if (ret == -ENODEV) {
+                       break;
+               } else if (ret) {
+                       dm_warn("Device tree error at offset %d\n", offset);
+                       if (!result || ret != -ENOENT)
+                               result = ret;
+                       break;
+               }
+
+               name = fdt_get_name(blob, offset, NULL);
+               dm_dbg("   - found match at '%s'\n", entry->name);
+               ret = device_bind(parent, entry, name, NULL, offset, &dev);
+               if (ret) {
+                       dm_warn("No match for driver '%s'\n", entry->name);
+                       if (!result || ret != -ENOENT)
+                               result = ret;
+               }
+       }
+
+       return result;
+}
+#endif
diff --git a/drivers/core/root.c b/drivers/core/root.c
new file mode 100644 (file)
index 0000000..407bc0d
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <malloc.h>
+#include <dm/device.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/platdata.h>
+#include <dm/uclass.h>
+#include <dm/util.h>
+#include <linux/list.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct driver_info root_info = {
+       .name           = "root_driver",
+};
+
+struct device *dm_root(void)
+{
+       if (!gd->dm_root) {
+               dm_warn("Virtual root driver does not exist!\n");
+               return NULL;
+       }
+
+       return gd->dm_root;
+}
+
+int dm_init(void)
+{
+       int ret;
+
+       if (gd->dm_root) {
+               dm_warn("Virtual root driver already exists!\n");
+               return -EINVAL;
+       }
+       INIT_LIST_HEAD(&gd->uclass_root);
+
+       ret = device_bind_by_name(NULL, &root_info, &gd->dm_root);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+int dm_scan_platdata(void)
+{
+       int ret;
+
+       ret = lists_bind_drivers(gd->dm_root);
+       if (ret == -ENOENT) {
+               dm_warn("Some drivers were not found\n");
+               ret = 0;
+       }
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+#ifdef CONFIG_OF_CONTROL
+int dm_scan_fdt(const void *blob)
+{
+       int offset = 0;
+       int ret = 0, err;
+       int depth = 0;
+
+       do {
+               offset = fdt_next_node(blob, offset, &depth);
+               if (offset > 0 && depth == 1) {
+                       err = lists_bind_fdt(gd->dm_root, blob, offset);
+                       if (err && !ret)
+                               ret = err;
+               }
+       } while (offset > 0);
+
+       if (ret)
+               dm_warn("Some drivers failed to bind\n");
+
+       return ret;
+}
+#endif
+
+/* This is the root driver - all drivers are children of this */
+U_BOOT_DRIVER(root_driver) = {
+       .name   = "root_driver",
+       .id     = UCLASS_ROOT,
+};
+
+/* This is the root uclass */
+UCLASS_DRIVER(root) = {
+       .name   = "root",
+       .id     = UCLASS_ROOT,
+};
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
new file mode 100644 (file)
index 0000000..4df5a8b
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <malloc.h>
+#include <dm/device.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/uclass.h>
+#include <dm/uclass-internal.h>
+#include <dm/util.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct uclass *uclass_find(enum uclass_id key)
+{
+       struct uclass *uc;
+
+       /*
+        * TODO(sjg@chromium.org): Optimise this, perhaps moving the found
+        * node to the start of the list, or creating a linear array mapping
+        * id to node.
+        */
+       list_for_each_entry(uc, &gd->uclass_root, sibling_node) {
+               if (uc->uc_drv->id == key)
+                       return uc;
+       }
+
+       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
+ * each id.
+ */
+static int uclass_add(enum uclass_id id, struct uclass **ucp)
+{
+       struct uclass_driver *uc_drv;
+       struct uclass *uc;
+       int ret;
+
+       *ucp = NULL;
+       uc_drv = lists_uclass_lookup(id);
+       if (!uc_drv) {
+               dm_warn("Cannot find uclass for id %d: please add the UCLASS_DRIVER() declaration for this UCLASS_... id\n",
+                       id);
+               return -ENOENT;
+       }
+       if (uc_drv->ops) {
+               dm_warn("No ops for uclass id %d\n", id);
+               return -EINVAL;
+       }
+       uc = calloc(1, sizeof(*uc));
+       if (!uc)
+               return -ENOMEM;
+       if (uc_drv->priv_auto_alloc_size) {
+               uc->priv = calloc(1, uc_drv->priv_auto_alloc_size);
+               if (!uc->priv) {
+                       ret = -ENOMEM;
+                       goto fail_mem;
+               }
+       }
+       uc->uc_drv = uc_drv;
+       INIT_LIST_HEAD(&uc->sibling_node);
+       INIT_LIST_HEAD(&uc->dev_head);
+       list_add(&uc->sibling_node, &gd->uclass_root);
+
+       if (uc_drv->init) {
+               ret = uc_drv->init(uc);
+               if (ret)
+                       goto fail;
+       }
+
+       *ucp = uc;
+
+       return 0;
+fail:
+       if (uc_drv->priv_auto_alloc_size) {
+               free(uc->priv);
+               uc->priv = NULL;
+       }
+       list_del(&uc->sibling_node);
+fail_mem:
+       free(uc);
+
+       return ret;
+}
+
+int uclass_destroy(struct uclass *uc)
+{
+       struct uclass_driver *uc_drv;
+       struct device *dev, *tmp;
+       int ret;
+
+       list_for_each_entry_safe(dev, tmp, &uc->dev_head, uclass_node) {
+               ret = device_remove(dev);
+               if (ret)
+                       return ret;
+               ret = device_unbind(dev);
+               if (ret)
+                       return ret;
+       }
+
+       uc_drv = uc->uc_drv;
+       if (uc_drv->destroy)
+               uc_drv->destroy(uc);
+       list_del(&uc->sibling_node);
+       if (uc_drv->priv_auto_alloc_size)
+               free(uc->priv);
+       free(uc);
+
+       return 0;
+}
+
+int uclass_get(enum uclass_id id, struct uclass **ucp)
+{
+       struct uclass *uc;
+
+       *ucp = NULL;
+       uc = uclass_find(id);
+       if (!uc)
+               return uclass_add(id, ucp);
+       *ucp = uc;
+
+       return 0;
+}
+
+int uclass_find_device(enum uclass_id id, int index, struct device **devp)
+{
+       struct uclass *uc;
+       struct device *dev;
+       int ret;
+
+       *devp = NULL;
+       ret = uclass_get(id, &uc);
+       if (ret)
+               return ret;
+
+       list_for_each_entry(dev, &uc->dev_head, uclass_node) {
+               if (!index--) {
+                       *devp = dev;
+                       return 0;
+               }
+       }
+
+       return -ENODEV;
+}
+
+int uclass_get_device(enum uclass_id id, int index, struct device **devp)
+{
+       struct device *dev;
+       int ret;
+
+       *devp = NULL;
+       ret = uclass_find_device(id, index, &dev);
+       if (ret)
+               return ret;
+
+       ret = device_probe(dev);
+       if (ret)
+               return ret;
+
+       *devp = dev;
+
+       return 0;
+}
+
+int uclass_first_device(enum uclass_id id, struct device **devp)
+{
+       struct uclass *uc;
+       struct device *dev;
+       int ret;
+
+       *devp = NULL;
+       ret = uclass_get(id, &uc);
+       if (ret)
+               return ret;
+       if (list_empty(&uc->dev_head))
+               return 0;
+
+       dev = list_first_entry(&uc->dev_head, struct device, uclass_node);
+       ret = device_probe(dev);
+       if (ret)
+               return ret;
+       *devp = dev;
+
+       return 0;
+}
+
+int uclass_next_device(struct device **devp)
+{
+       struct device *dev = *devp;
+       int ret;
+
+       *devp = NULL;
+       if (list_is_last(&dev->uclass_node, &dev->uclass->dev_head))
+               return 0;
+
+       dev = list_entry(dev->uclass_node.next, struct device, uclass_node);
+       ret = device_probe(dev);
+       if (ret)
+               return ret;
+       *devp = dev;
+
+       return 0;
+}
+
+int uclass_bind_device(struct device *dev)
+{
+       struct uclass *uc;
+       int ret;
+
+       uc = dev->uclass;
+
+       list_add_tail(&dev->uclass_node, &uc->dev_head);
+
+       if (uc->uc_drv->post_bind) {
+               ret = uc->uc_drv->post_bind(dev);
+               if (ret) {
+                       list_del(&dev->uclass_node);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+int uclass_unbind_device(struct device *dev)
+{
+       struct uclass *uc;
+       int ret;
+
+       uc = dev->uclass;
+       if (uc->uc_drv->pre_unbind) {
+               ret = uc->uc_drv->pre_unbind(dev);
+               if (ret)
+                       return ret;
+       }
+
+       list_del(&dev->uclass_node);
+       return 0;
+}
+
+int uclass_post_probe_device(struct device *dev)
+{
+       struct uclass_driver *uc_drv = dev->uclass->uc_drv;
+
+       if (uc_drv->post_probe)
+               return uc_drv->post_probe(dev);
+
+       return 0;
+}
+
+int uclass_pre_remove_device(struct device *dev)
+{
+       struct uclass_driver *uc_drv;
+       struct uclass *uc;
+       int ret;
+
+       uc = dev->uclass;
+       uc_drv = uc->uc_drv;
+       if (uc->uc_drv->pre_remove) {
+               ret = uc->uc_drv->pre_remove(dev);
+               if (ret)
+                       return ret;
+       }
+       if (uc_drv->per_device_auto_alloc_size) {
+               free(dev->uclass_priv);
+               dev->uclass_priv = NULL;
+       }
+
+       return 0;
+}
diff --git a/drivers/core/util.c b/drivers/core/util.c
new file mode 100644 (file)
index 0000000..e01dd06
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <vsprintf.h>
+
+void dm_warn(const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       vprintf(fmt, args);
+       va_end(args);
+}
+
+void dm_dbg(const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       vprintf(fmt, args);
+       va_end(args);
+}
+
+int list_count_items(struct list_head *head)
+{
+       struct list_head *node;
+       int count = 0;
+
+       list_for_each(node, head)
+               count++;
+
+       return count;
+}
diff --git a/drivers/demo/Makefile b/drivers/demo/Makefile
new file mode 100644 (file)
index 0000000..baaa2ba
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Copyright (c) 2013 Google, Inc
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-$(CONFIG_DM_DEMO) += demo-uclass.o demo-pdata.o
+obj-$(CONFIG_DM_DEMO_SIMPLE) += demo-simple.o
+obj-$(CONFIG_DM_DEMO_SHAPE) += demo-shape.o
diff --git a/drivers/demo/demo-pdata.c b/drivers/demo/demo-pdata.c
new file mode 100644 (file)
index 0000000..e92841d
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm-demo.h>
+
+static const struct dm_demo_pdata red_square = {
+       .colour = "red",
+       .sides = 4.
+};
+static const struct dm_demo_pdata green_triangle = {
+       .colour = "green",
+       .sides = 3.
+};
+static const struct dm_demo_pdata yellow_hexagon = {
+       .colour = "yellow",
+       .sides = 6.
+};
+
+U_BOOT_DEVICE(demo0) = {
+       .name = "demo_shape_drv",
+       .platdata = &red_square,
+};
+
+U_BOOT_DEVICE(demo1) = {
+       .name = "demo_simple_drv",
+       .platdata = &red_square,
+};
+
+U_BOOT_DEVICE(demo2) = {
+       .name = "demo_shape_drv",
+       .platdata = &green_triangle,
+};
+
+U_BOOT_DEVICE(demo3) = {
+       .name = "demo_simple_drv",
+       .platdata = &yellow_hexagon,
+};
+
+U_BOOT_DEVICE(demo4) = {
+       .name = "demo_shape_drv",
+       .platdata = &yellow_hexagon,
+};
diff --git a/drivers/demo/demo-shape.c b/drivers/demo/demo-shape.c
new file mode 100644 (file)
index 0000000..2f0eb96
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <dm-demo.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Shape size */
+#define WIDTH  8
+#define HEIGHT 6
+
+struct shape_data {
+       int num_chars;  /* Number of non-space characters output so far */
+};
+
+/* Crazy little function to draw shapes on the console */
+static int shape_hello(struct device *dev, int ch)
+{
+       const struct dm_demo_pdata *pdata = dev_get_platdata(dev);
+       struct shape_data *data = dev_get_priv(dev);
+       static const struct shape {
+               int start;
+               int end;
+               int dstart;
+               int dend;
+       } shapes[3] = {
+               { 0, 1, 0, 1 },
+               { 0, WIDTH, 0, 0 },
+               { HEIGHT / 2 - 1, WIDTH - HEIGHT / 2 + 1, -1, 1},
+       };
+       struct shape shape;
+       unsigned int index;
+       int line, pos, inside;
+       const char *colour = pdata->colour;
+       int first = 0;
+
+       if (!ch)
+               ch = pdata->default_char;
+       if (!ch)
+               ch = '@';
+
+       index = (pdata->sides / 2) - 1;
+       if (index >= ARRAY_SIZE(shapes))
+               return -EIO;
+       shape = shapes[index];
+
+       for (line = 0; line < HEIGHT; line++) {
+               first = 1;
+               for (pos = 0; pos < WIDTH; pos++) {
+                       inside = pos >= shape.start && pos < shape.end;
+                       if (inside) {
+                               putc(first ? *colour++ : ch);
+                               data->num_chars++;
+                               first = 0;
+                               if (!*colour)
+                                       colour = pdata->colour;
+                       } else {
+                               putc(' ');
+                       }
+               }
+               putc('\n');
+               shape.start += shape.dstart;
+               shape.end += shape.dend;
+               if (shape.start < 0) {
+                       shape.dstart = -shape.dstart;
+                       shape.dend = -shape.dend;
+                       shape.start += shape.dstart;
+                       shape.end += shape.dend;
+               }
+       }
+
+       return 0;
+}
+
+static int shape_status(struct device *dev, int *status)
+{
+       struct shape_data *data = dev_get_priv(dev);
+
+       *status = data->num_chars;
+       return 0;
+}
+
+static const struct demo_ops shape_ops = {
+       .hello = shape_hello,
+       .status = shape_status,
+};
+
+static int shape_ofdata_to_platdata(struct device *dev)
+{
+       struct dm_demo_pdata *pdata = dev_get_platdata(dev);
+       int ret;
+
+       /* Parse the data that is common with all demo devices */
+       ret = demo_parse_dt(dev);
+       if (ret)
+               return ret;
+
+       /* Parse the data that only we need */
+       pdata->default_char = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+                                            "character", '@');
+
+       return 0;
+}
+
+static const struct device_id demo_shape_id[] = {
+       { "demo-shape", 0 },
+       { },
+};
+
+U_BOOT_DRIVER(demo_shape_drv) = {
+       .name   = "demo_shape_drv",
+       .of_match = demo_shape_id,
+       .id     = UCLASS_DEMO,
+       .ofdata_to_platdata = shape_ofdata_to_platdata,
+       .ops    = &shape_ops,
+       .priv_auto_alloc_size = sizeof(struct shape_data),
+       .platdata_auto_alloc_size = sizeof(struct dm_demo_pdata),
+};
diff --git a/drivers/demo/demo-simple.c b/drivers/demo/demo-simple.c
new file mode 100644 (file)
index 0000000..6ba8131
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm-demo.h>
+#include <asm/io.h>
+
+static int simple_hello(struct device *dev, int ch)
+{
+       const struct dm_demo_pdata *pdata = dev_get_platdata(dev);
+
+       printf("Hello from %08x: %s %d\n", map_to_sysmem(dev), pdata->colour,
+              pdata->sides);
+
+       return 0;
+}
+
+static const struct demo_ops simple_ops = {
+       .hello = simple_hello,
+};
+
+static int demo_shape_ofdata_to_platdata(struct device *dev)
+{
+       /* Parse the data that is common with all demo devices */
+       return demo_parse_dt(dev);
+}
+
+static const struct device_id demo_shape_id[] = {
+       { "demo-simple", 0 },
+       { },
+};
+
+U_BOOT_DRIVER(demo_simple_drv) = {
+       .name   = "demo_simple_drv",
+       .of_match = demo_shape_id,
+       .id     = UCLASS_DEMO,
+       .ofdata_to_platdata = demo_shape_ofdata_to_platdata,
+       .ops    = &simple_ops,
+       .platdata_auto_alloc_size = sizeof(struct dm_demo_pdata),
+};
diff --git a/drivers/demo/demo-uclass.c b/drivers/demo/demo-uclass.c
new file mode 100644 (file)
index 0000000..48588be
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm-demo.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <linux/list.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+UCLASS_DRIVER(demo) = {
+       .id             = UCLASS_DEMO,
+};
+
+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);
+}
+
+int demo_status(struct device *dev, int *status)
+{
+       const struct demo_ops *ops = device_get_ops(dev);
+
+       if (!ops->status)
+               return -ENOSYS;
+
+       return ops->status(dev, status);
+}
+
+int demo_parse_dt(struct device *dev)
+{
+       struct dm_demo_pdata *pdata = dev_get_platdata(dev);
+       int dn = dev->of_offset;
+
+       pdata->sides = fdtdec_get_int(gd->fdt_blob, dn, "sides", 0);
+       pdata->colour = fdt_getprop(gd->fdt_blob, dn, "colour", NULL);
+       if (!pdata->sides || !pdata->colour) {
+               debug("%s: Invalid device tree data\n", __func__);
+               return -EINVAL;
+       }
+
+       return 0;
+}
index 15900c9..923a158 100644 (file)
@@ -10,7 +10,7 @@
 #include <common.h>
 #include <asm/io.h>
 #include <zynqpl.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/sys_proto.h>
 
index ed2c0c7..4e001e1 100644 (file)
@@ -5,6 +5,8 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
+obj-$(CONFIG_DM_GPIO)          += gpio-uclass.o
+
 obj-$(CONFIG_AT91_GPIO)        += at91_gpio.o
 obj-$(CONFIG_INTEL_ICH6_GPIO)  += intel_ich6_gpio.o
 obj-$(CONFIG_KIRKWOOD_GPIO)    += kw_gpio.o
index 8b76666..0b70071 100644 (file)
@@ -11,7 +11,7 @@
 #include <config.h>
 #include <common.h>
 #include <asm/io.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/at91_pio.h>
 #include <asm/arch/gpio.h>
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
new file mode 100644 (file)
index 0000000..56bfd11
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/gpio.h>
+
+/**
+ * gpio_to_device() - Convert global GPIO number to device, number
+ * gpio:       The numeric representation of the GPIO
+ *
+ * Convert the GPIO number to an entry in the list of GPIOs
+ * or GPIO blocks registered with the GPIO controller. Returns
+ * entry on success, NULL on error.
+ */
+static int gpio_to_device(unsigned int gpio, struct device **devp,
+                         unsigned int *offset)
+{
+       struct gpio_dev_priv *uc_priv;
+       struct device *dev;
+       int ret;
+
+       for (ret = uclass_first_device(UCLASS_GPIO, &dev);
+            dev;
+            ret = uclass_next_device(&dev)) {
+               uc_priv = dev->uclass_priv;
+               if (gpio >= uc_priv->gpio_base &&
+                   gpio < uc_priv->gpio_base + uc_priv->gpio_count) {
+                       *devp = dev;
+                       *offset = gpio - uc_priv->gpio_base;
+                       return 0;
+               }
+       }
+
+       /* No such GPIO */
+       return ret ? ret : -EINVAL;
+}
+
+int gpio_lookup_name(const char *name, struct device **devp,
+                    unsigned int *offsetp, unsigned int *gpiop)
+{
+       struct gpio_dev_priv *uc_priv;
+       struct device *dev;
+       int ret;
+
+       if (devp)
+               *devp = NULL;
+       for (ret = uclass_first_device(UCLASS_GPIO, &dev);
+            dev;
+            ret = uclass_next_device(&dev)) {
+               ulong offset;
+               int len;
+
+               uc_priv = dev->uclass_priv;
+               len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0;
+
+               if (!strncmp(name, uc_priv->bank_name, len)) {
+                       if (strict_strtoul(name + len, 10, &offset))
+                               continue;
+                       if (devp)
+                               *devp = dev;
+                       if (offsetp)
+                               *offsetp = offset;
+                       if (gpiop)
+                               *gpiop = uc_priv->gpio_base + offset;
+                       return 0;
+               }
+       }
+
+       return ret ? ret : -EINVAL;
+}
+
+/**
+ * gpio_request() - [COMPAT] Request GPIO
+ * gpio:       GPIO number
+ * label:      Name for the requested GPIO
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_request(unsigned gpio, const char *label)
+{
+       unsigned int offset;
+       struct device *dev;
+       int ret;
+
+       ret = gpio_to_device(gpio, &dev, &offset);
+       if (ret)
+               return ret;
+
+       if (!gpio_get_ops(dev)->request)
+               return 0;
+
+       return gpio_get_ops(dev)->request(dev, offset, label);
+}
+
+/**
+ * gpio_free() - [COMPAT] Relinquish GPIO
+ * gpio:       GPIO number
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_free(unsigned gpio)
+{
+       unsigned int offset;
+       struct device *dev;
+       int ret;
+
+       ret = gpio_to_device(gpio, &dev, &offset);
+       if (ret)
+               return ret;
+
+       if (!gpio_get_ops(dev)->free)
+               return 0;
+       return gpio_get_ops(dev)->free(dev, offset);
+}
+
+/**
+ * gpio_direction_input() - [COMPAT] Set GPIO direction to input
+ * gpio:       GPIO number
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_direction_input(unsigned gpio)
+{
+       unsigned int offset;
+       struct device *dev;
+       int ret;
+
+       ret = gpio_to_device(gpio, &dev, &offset);
+       if (ret)
+               return ret;
+
+       return gpio_get_ops(dev)->direction_input(dev, offset);
+}
+
+/**
+ * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value
+ * gpio:       GPIO number
+ * value:      Logical value to be set on the GPIO pin
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_direction_output(unsigned gpio, int value)
+{
+       unsigned int offset;
+       struct device *dev;
+       int ret;
+
+       ret = gpio_to_device(gpio, &dev, &offset);
+       if (ret)
+               return ret;
+
+       return gpio_get_ops(dev)->direction_output(dev, offset, value);
+}
+
+/**
+ * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value
+ * gpio:       GPIO number
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns the value of the GPIO pin, or negative value
+ * on error.
+ */
+int gpio_get_value(unsigned gpio)
+{
+       unsigned int offset;
+       struct device *dev;
+       int ret;
+
+       ret = gpio_to_device(gpio, &dev, &offset);
+       if (ret)
+               return ret;
+
+       return gpio_get_ops(dev)->get_value(dev, offset);
+}
+
+/**
+ * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin
+ * gpio:       GPIO number
+ * value:      Logical value to be set on the GPIO pin.
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_set_value(unsigned gpio, int value)
+{
+       unsigned int offset;
+       struct device *dev;
+       int ret;
+
+       ret = gpio_to_device(gpio, &dev, &offset);
+       if (ret)
+               return ret;
+
+       return gpio_get_ops(dev)->set_value(dev, offset, value);
+}
+
+const char *gpio_get_bank_info(struct device *dev, int *bit_count)
+{
+       struct gpio_dev_priv *priv;
+
+       /* Must be called on an active device */
+       priv = dev->uclass_priv;
+       assert(priv);
+
+       *bit_count = priv->gpio_count;
+       return priv->bank_name;
+}
+
+/* We need to renumber the GPIOs when any driver is probed/removed */
+static int gpio_renumber(void)
+{
+       struct gpio_dev_priv *uc_priv;
+       struct device *dev;
+       struct uclass *uc;
+       unsigned base;
+       int ret;
+
+       ret = uclass_get(UCLASS_GPIO, &uc);
+       if (ret)
+               return ret;
+
+       /* Ensure that we have a base for each bank */
+       base = 0;
+       uclass_foreach_dev(dev, uc) {
+               if (device_active(dev)) {
+                       uc_priv = dev->uclass_priv;
+                       uc_priv->gpio_base = base;
+                       base += uc_priv->gpio_count;
+               }
+       }
+
+       return 0;
+}
+
+static int gpio_post_probe(struct device *dev)
+{
+       return gpio_renumber();
+}
+
+static int gpio_pre_remove(struct device *dev)
+{
+       return gpio_renumber();
+}
+
+UCLASS_DRIVER(gpio) = {
+       .id             = UCLASS_GPIO,
+       .name           = "gpio",
+       .post_probe     = gpio_post_probe,
+       .pre_remove     = gpio_pre_remove,
+       .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv),
+};
index 3c6cfec..22b6a5f 100644 (file)
@@ -4,8 +4,13 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <malloc.h>
 #include <asm/gpio.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /* Flags for each GPIO */
 #define GPIOF_OUTPUT   (1 << 0)        /* Currently set as an output */
 #define GPIOF_HIGH     (1 << 1)        /* Currently set high */
@@ -16,34 +21,30 @@ struct gpio_state {
        u8 flags;               /* flags (GPIOF_...) */
 };
 
-/*
- * State of GPIOs
- * TODO: Put this into sandbox state
- */
-static struct gpio_state state[CONFIG_SANDBOX_GPIO_COUNT];
-
 /* Access routines for GPIO state */
-static u8 *get_gpio_flags(unsigned gp)
+static u8 *get_gpio_flags(struct device *dev, unsigned offset)
 {
-       /* assert()'s could be disabled, so make sure we handle that */
-       assert(gp < ARRAY_SIZE(state));
-       if (gp >= ARRAY_SIZE(state)) {
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+       struct gpio_state *state = dev_get_priv(dev);
+
+       if (offset >= uc_priv->gpio_count) {
                static u8 invalid_flags;
-               printf("sandbox_gpio: error: invalid gpio %u\n", gp);
+               printf("sandbox_gpio: error: invalid gpio %u\n", offset);
                return &invalid_flags;
        }
 
-       return &state[gp].flags;
+       return &state[offset].flags;
 }
 
-static int get_gpio_flag(unsigned gp, int flag)
+static int get_gpio_flag(struct device *dev, unsigned offset, int flag)
 {
-       return (*get_gpio_flags(gp) & flag) != 0;
+       return (*get_gpio_flags(dev, offset) & flag) != 0;
 }
 
-static int set_gpio_flag(unsigned gp, int flag, int value)
+static int set_gpio_flag(struct device *dev, unsigned offset, int flag,
+                        int value)
 {
-       u8 *gpio = get_gpio_flags(gp);
+       u8 *gpio = get_gpio_flags(dev, offset);
 
        if (value)
                *gpio |= flag;
@@ -53,11 +54,12 @@ static int set_gpio_flag(unsigned gp, int flag, int value)
        return 0;
 }
 
-static int check_reserved(unsigned gpio, const char *func)
+static int check_reserved(struct device *dev, unsigned offset,
+                         const char *func)
 {
-       if (!get_gpio_flag(gpio, GPIOF_RESERVED)) {
-               printf("sandbox_gpio: %s: error: gpio %u not reserved\n",
-                       func, gpio);
+       if (!get_gpio_flag(dev, offset, GPIOF_RESERVED)) {
+               printf("sandbox_gpio: %s: error: offset %u not reserved\n",
+                      func, offset);
                return -1;
        }
 
@@ -68,126 +70,185 @@ static int check_reserved(unsigned gpio, const char *func)
  * Back-channel sandbox-internal-only access to GPIO state
  */
 
-int sandbox_gpio_get_value(unsigned gp)
+int sandbox_gpio_get_value(struct device *dev, unsigned offset)
 {
-       if (get_gpio_flag(gp, GPIOF_OUTPUT))
-               debug("sandbox_gpio: get_value on output gpio %u\n", gp);
-       return get_gpio_flag(gp, GPIOF_HIGH);
+       if (get_gpio_flag(dev, offset, GPIOF_OUTPUT))
+               debug("sandbox_gpio: get_value on output gpio %u\n", offset);
+       return get_gpio_flag(dev, offset, GPIOF_HIGH);
 }
 
-int sandbox_gpio_set_value(unsigned gp, int value)
+int sandbox_gpio_set_value(struct device *dev, unsigned offset, int value)
 {
-       return set_gpio_flag(gp, GPIOF_HIGH, value);
+       return set_gpio_flag(dev, offset, GPIOF_HIGH, value);
 }
 
-int sandbox_gpio_get_direction(unsigned gp)
+int sandbox_gpio_get_direction(struct device *dev, unsigned offset)
 {
-       return get_gpio_flag(gp, GPIOF_OUTPUT);
+       return get_gpio_flag(dev, offset, GPIOF_OUTPUT);
 }
 
-int sandbox_gpio_set_direction(unsigned gp, int output)
+int sandbox_gpio_set_direction(struct device *dev, unsigned offset, int output)
 {
-       return set_gpio_flag(gp, GPIOF_OUTPUT, output);
+       return set_gpio_flag(dev, offset, GPIOF_OUTPUT, output);
 }
 
 /*
  * These functions implement the public interface within U-Boot
  */
 
-/* set GPIO port 'gp' as an input */
-int gpio_direction_input(unsigned gp)
+/* set GPIO port 'offset' as an input */
+static int sb_gpio_direction_input(struct device *dev, unsigned offset)
 {
-       debug("%s: gp:%u\n", __func__, gp);
+       debug("%s: offset:%u\n", __func__, offset);
 
-       if (check_reserved(gp, __func__))
+       if (check_reserved(dev, offset, __func__))
                return -1;
 
-       return sandbox_gpio_set_direction(gp, 0);
+       return sandbox_gpio_set_direction(dev, offset, 0);
 }
 
-/* set GPIO port 'gp' as an output, with polarity 'value' */
-int gpio_direction_output(unsigned gp, int value)
+/* set GPIO port 'offset' as an output, with polarity 'value' */
+static int sb_gpio_direction_output(struct device *dev, unsigned offset,
+                                   int value)
 {
-       debug("%s: gp:%u, value = %d\n", __func__, gp, value);
+       debug("%s: offset:%u, value = %d\n", __func__, offset, value);
 
-       if (check_reserved(gp, __func__))
+       if (check_reserved(dev, offset, __func__))
                return -1;
 
-       return sandbox_gpio_set_direction(gp, 1) |
-               sandbox_gpio_set_value(gp, value);
+       return sandbox_gpio_set_direction(dev, offset, 1) |
+               sandbox_gpio_set_value(dev, offset, value);
 }
 
-/* read GPIO IN value of port 'gp' */
-int gpio_get_value(unsigned gp)
+/* read GPIO IN value of port 'offset' */
+static int sb_gpio_get_value(struct device *dev, unsigned offset)
 {
-       debug("%s: gp:%u\n", __func__, gp);
+       debug("%s: offset:%u\n", __func__, offset);
 
-       if (check_reserved(gp, __func__))
+       if (check_reserved(dev, offset, __func__))
                return -1;
 
-       return sandbox_gpio_get_value(gp);
+       return sandbox_gpio_get_value(dev, offset);
 }
 
-/* write GPIO OUT value to port 'gp' */
-int gpio_set_value(unsigned gp, int value)
+/* write GPIO OUT value to port 'offset' */
+static int sb_gpio_set_value(struct device *dev, unsigned offset, int value)
 {
-       debug("%s: gp:%u, value = %d\n", __func__, gp, value);
+       debug("%s: offset:%u, value = %d\n", __func__, offset, value);
 
-       if (check_reserved(gp, __func__))
+       if (check_reserved(dev, offset, __func__))
                return -1;
 
-       if (!sandbox_gpio_get_direction(gp)) {
-               printf("sandbox_gpio: error: set_value on input gpio %u\n", gp);
+       if (!sandbox_gpio_get_direction(dev, offset)) {
+               printf("sandbox_gpio: error: set_value on input gpio %u\n",
+                      offset);
                return -1;
        }
 
-       return sandbox_gpio_set_value(gp, value);
+       return sandbox_gpio_set_value(dev, offset, value);
 }
 
-int gpio_request(unsigned gp, const char *label)
+static int sb_gpio_request(struct device *dev, unsigned offset,
+                          const char *label)
 {
-       debug("%s: gp:%u, label:%s\n", __func__, gp, label);
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+       struct gpio_state *state = dev_get_priv(dev);
+
+       debug("%s: offset:%u, label:%s\n", __func__, offset, label);
 
-       if (gp >= ARRAY_SIZE(state)) {
-               printf("sandbox_gpio: error: invalid gpio %u\n", gp);
+       if (offset >= uc_priv->gpio_count) {
+               printf("sandbox_gpio: error: invalid gpio %u\n", offset);
                return -1;
        }
 
-       if (get_gpio_flag(gp, GPIOF_RESERVED)) {
-               printf("sandbox_gpio: error: gpio %u already reserved\n", gp);
+       if (get_gpio_flag(dev, offset, GPIOF_RESERVED)) {
+               printf("sandbox_gpio: error: gpio %u already reserved\n",
+                      offset);
                return -1;
        }
 
-       state[gp].label = label;
-       return set_gpio_flag(gp, GPIOF_RESERVED, 1);
+       state[offset].label = label;
+       return set_gpio_flag(dev, offset, GPIOF_RESERVED, 1);
 }
 
-int gpio_free(unsigned gp)
+static int sb_gpio_free(struct device *dev, unsigned offset)
 {
-       debug("%s: gp:%u\n", __func__, gp);
+       struct gpio_state *state = dev_get_priv(dev);
+
+       debug("%s: offset:%u\n", __func__, offset);
 
-       if (check_reserved(gp, __func__))
+       if (check_reserved(dev, offset, __func__))
                return -1;
 
-       state[gp].label = NULL;
-       return set_gpio_flag(gp, GPIOF_RESERVED, 0);
+       state[offset].label = NULL;
+       return set_gpio_flag(dev, offset, GPIOF_RESERVED, 0);
 }
 
-/* Display GPIO information */
-void gpio_info(void)
+static int sb_gpio_get_state(struct device *dev, unsigned int offset,
+                            char *buf, int bufsize)
 {
-       unsigned gpio;
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+       struct gpio_state *state = dev_get_priv(dev);
+       const char *label;
+
+       label = state[offset].label;
+       snprintf(buf, bufsize, "%s%d: %s: %d [%c]%s%s",
+                uc_priv->bank_name ? uc_priv->bank_name : "", offset,
+                sandbox_gpio_get_direction(dev, offset) ? "out" : " in",
+                sandbox_gpio_get_value(dev, offset),
+                get_gpio_flag(dev, offset, GPIOF_RESERVED) ? 'x' : ' ',
+                label ? " " : "",
+                label ? label : "");
 
-       puts("Sandbox GPIOs\n");
+       return 0;
+}
+
+static const struct dm_gpio_ops gpio_sandbox_ops = {
+       .request                = sb_gpio_request,
+       .free                   = sb_gpio_free,
+       .direction_input        = sb_gpio_direction_input,
+       .direction_output       = sb_gpio_direction_output,
+       .get_value              = sb_gpio_get_value,
+       .set_value              = sb_gpio_set_value,
+       .get_state              = sb_gpio_get_state,
+};
+
+static int sandbox_gpio_ofdata_to_platdata(struct device *dev)
+{
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
 
-       for (gpio = 0; gpio < ARRAY_SIZE(state); ++gpio) {
-               const char *label = state[gpio].label;
+       uc_priv->gpio_count = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+                                            "num-gpios", 0);
+       uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev->of_offset,
+                                        "gpio-bank-name", NULL);
 
-               printf("%4d: %s: %d [%c] %s\n",
-                       gpio,
-                       sandbox_gpio_get_direction(gpio) ? "out" : " in",
-                       sandbox_gpio_get_value(gpio),
-                       get_gpio_flag(gpio, GPIOF_RESERVED) ? 'x' : ' ',
-                       label ? label : "");
+       return 0;
+}
+
+static int gpio_sandbox_probe(struct device *dev)
+{
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+       if (dev->of_offset == -1) {
+               /* Tell the uclass how many GPIOs we have */
+               uc_priv->gpio_count = CONFIG_SANDBOX_GPIO_COUNT;
        }
+
+       dev->priv = calloc(sizeof(struct gpio_state), uc_priv->gpio_count);
+
+       return 0;
 }
+
+static const struct device_id sandbox_gpio_ids[] = {
+       { .compatible = "sandbox,gpio" },
+       { }
+};
+
+U_BOOT_DRIVER(gpio_sandbox) = {
+       .name   = "gpio_sandbox",
+       .id     = UCLASS_GPIO,
+       .of_match = sandbox_gpio_ids,
+       .ofdata_to_platdata = sandbox_gpio_ofdata_to_platdata,
+       .probe  = gpio_sandbox_probe,
+       .ops    = &gpio_sandbox_ops,
+};
index 72a272f..fdce2c2 100644 (file)
@@ -7,6 +7,8 @@
  */
 
 #include <common.h>
+#include <fdtdec.h>
+#include <libfdt.h>
 #include <malloc.h>
 #include <sdhci.h>
 #include <asm/arch/sys_proto.h>
@@ -32,3 +34,30 @@ int zynq_sdhci_init(u32 regbase)
        add_sdhci(host, 52000000, 52000000 >> 9);
        return 0;
 }
+
+#ifdef CONFIG_OF_CONTROL
+int zynq_sdhci_of_init(const void *blob)
+{
+       int offset = 0;
+       u32 ret = 0;
+       u32 reg;
+
+       debug("ZYNQ SDHCI: Initialization\n");
+
+       do {
+               offset = fdt_node_offset_by_compatible(blob, offset,
+                                       "arasan,sdhci-8.9a");
+               if (offset != -1) {
+                       reg = fdtdec_get_addr(blob, offset, "reg");
+                       if (reg != FDT_ADDR_T_NONE) {
+                               ret |= zynq_sdhci_init(reg);
+                       } else {
+                               debug("ZYNQ SDHCI: Can't get base address\n");
+                               return -1;
+                       }
+               }
+       } while (offset != -1);
+
+       return ret;
+}
+#endif
index 0a5209d..2a5cc44 100644 (file)
@@ -14,8 +14,6 @@
 #include <asm/io.h>
 #include <fdtdec.h>
 
-DECLARE_GLOBAL_DATA_PTR;
-
 #undef DEBUG
 
 #define ENET_ADDR_LENGTH       6
@@ -364,24 +362,27 @@ int xilinx_emaclite_initialize(bd_t *bis, unsigned long base_addr,
 }
 
 #ifdef CONFIG_OF_CONTROL
-int xilinx_emaclite_init(bd_t *bis)
+int xilinx_emaclite_of_init(const void *blob)
 {
        int offset = 0;
        u32 ret = 0;
        u32 reg;
 
        do {
-               offset = fdt_node_offset_by_compatible(gd->fdt_blob, offset,
+               offset = fdt_node_offset_by_compatible(blob, offset,
                                        "xlnx,xps-ethernetlite-1.00.a");
                if (offset != -1) {
-                       reg = fdtdec_get_addr(gd->fdt_blob, offset, "reg");
+                       reg = fdtdec_get_addr(blob, offset, "reg");
                        if (reg != FDT_ADDR_T_NONE) {
-                               u32 rxpp = fdtdec_get_int(gd->fdt_blob, offset,
+                               u32 rxpp = fdtdec_get_int(blob, offset,
                                                        "xlnx,rx-ping-pong", 0);
-                               u32 txpp = fdtdec_get_int(gd->fdt_blob, offset,
+                               u32 txpp = fdtdec_get_int(blob, offset,
                                                        "xlnx,tx-ping-pong", 0);
-                               ret |= xilinx_emaclite_initialize(bis, reg,
+                               ret |= xilinx_emaclite_initialize(NULL, reg,
                                                                txpp, rxpp);
+                       } else {
+                               debug("EMACLITE: Can't get base address\n");
+                               return -1;
                        }
                }
        } while (offset != -1);