aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Rini2018-11-16 07:37:50 -0600
committerTom Rini2018-11-16 07:37:50 -0600
commit1d6edcbfed2af33c748f2beb399810a0441888da (patch)
treefe88d63e5ef1dbe1915f90e02429e8b6934859da
parentf6206f8587fc7ec82a57dbbeb5de0f94b3c2ef49 (diff)
parent4c6e27f63c88d065a98f438085dfc36af47d3a23 (diff)
downloadu-boot-master.tar.gz
u-boot-master.tar.xz
u-boot-master.zip
Merge tag 'pull-14nov18' of git://git.denx.de/u-boot-dmHEADupstream-mastermaster
- virtio implementation and supporting patches - DM_FLAG_PRE_RELOC fixes - regmap improvements - minor buildman and sandbox things
-rw-r--r--Documentation/devicetree/bindings/misc/gdsys,iocon_fpga.txt19
-rw-r--r--Documentation/devicetree/bindings/misc/gdsys,iocpu_fpga.txt19
-rw-r--r--Documentation/devicetree/bindings/misc/gdsys,soc.txt16
-rw-r--r--arch/Kconfig6
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/mach-stm32mp/bsec.c1
-rw-r--r--arch/mips/include/asm/io.h22
-rw-r--r--arch/riscv/lib/bootm.c11
-rw-r--r--arch/sandbox/cpu/os.c7
-rw-r--r--arch/sandbox/dts/test.dts17
-rw-r--r--arch/x86/cpu/baytrail/cpu.c1
-rw-r--r--arch/x86/cpu/broadwell/cpu.c1
-rw-r--r--arch/x86/cpu/cpu_x86.c1
-rw-r--r--arch/x86/cpu/ivybridge/model_206ax.c1
-rw-r--r--arch/x86/cpu/tangier/sysreset.c1
-rw-r--r--arch/x86/include/asm/io.h66
-rw-r--r--board/emulation/qemu-arm/Kconfig13
-rw-r--r--board/emulation/qemu-arm/qemu-arm.c10
-rw-r--r--board/emulation/qemu-riscv/Kconfig11
-rw-r--r--board/emulation/qemu-riscv/qemu-riscv.c9
-rw-r--r--board/emulation/qemu-x86/Kconfig3
-rw-r--r--cmd/Kconfig7
-rw-r--r--cmd/Makefile1
-rw-r--r--cmd/sata.c9
-rw-r--r--cmd/virtio.c38
-rw-r--r--common/board_f.c28
-rw-r--r--common/usb_storage.c4
-rw-r--r--configs/imx8qxp_mek_defconfig1
-rw-r--r--configs/qemu_arm64_defconfig1
-rw-r--r--configs/qemu_arm_defconfig1
-rw-r--r--configs/sandbox_noblk_defconfig1
-rw-r--r--disk/part.c6
-rw-r--r--doc/README.virtio253
-rw-r--r--doc/driver-model/README.txt16
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/block/blk-uclass.c25
-rw-r--r--drivers/block/ide.c2
-rw-r--r--drivers/block/sandbox.c17
-rw-r--r--drivers/clk/altera/clk-arria10.c1
-rw-r--r--drivers/clk/clk_pic32.c1
-rw-r--r--drivers/clk/clk_zynq.c1
-rw-r--r--drivers/clk/exynos/clk-exynos7420.c3
-rw-r--r--drivers/clk/owl/clk_s900.c1
-rw-r--r--drivers/core/device.c2
-rw-r--r--drivers/core/dump.c2
-rw-r--r--drivers/core/lists.c9
-rw-r--r--drivers/core/ofnode.c4
-rw-r--r--drivers/core/regmap.c316
-rw-r--r--drivers/core/root.c20
-rw-r--r--drivers/core/uclass.c31
-rw-r--r--drivers/core/util.c25
-rw-r--r--drivers/cpu/mpc83xx_cpu.c2
-rw-r--r--drivers/gpio/omap_gpio.c2
-rw-r--r--drivers/gpio/stm32f7_gpio.c2
-rw-r--r--drivers/gpio/tegra186_gpio.c1
-rw-r--r--drivers/gpio/tegra_gpio.c1
-rw-r--r--drivers/i2c/omap24xx_i2c.c2
-rw-r--r--drivers/misc/Kconfig17
-rw-r--r--drivers/misc/Makefile63
-rw-r--r--drivers/misc/gdsys_soc.c74
-rw-r--r--drivers/misc/gdsys_soc.h23
-rw-r--r--drivers/misc/ihs_fpga.c867
-rw-r--r--drivers/misc/ihs_fpga.h49
-rw-r--r--drivers/misc/imx8/scu.c4
-rw-r--r--drivers/misc/swap_case.c9
-rw-r--r--drivers/mmc/mmc.c3
-rw-r--r--drivers/mmc/omap_hsmmc.c2
-rw-r--r--drivers/nvme/nvme.c1
-rw-r--r--drivers/pci/pci-uclass.c51
-rw-r--r--drivers/pinctrl/broadcom/pinctrl-bcm283x.c2
-rw-r--r--drivers/pinctrl/exynos/pinctrl-exynos7420.c1
-rw-r--r--drivers/pinctrl/nxp/pinctrl-imx5.c2
-rw-r--r--drivers/pinctrl/nxp/pinctrl-imx6.c2
-rw-r--r--drivers/pinctrl/nxp/pinctrl-imx7.c2
-rw-r--r--drivers/pinctrl/nxp/pinctrl-imx7ulp.c2
-rw-r--r--drivers/pinctrl/pinctrl-single.c1
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c2
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c2
-rw-r--r--drivers/ram/bmips_ram.c1
-rw-r--r--drivers/scsi/scsi.c1
-rw-r--r--drivers/serial/altera_jtag_uart.c1
-rw-r--r--drivers/serial/altera_uart.c1
-rw-r--r--drivers/serial/arm_dcc.c1
-rw-r--r--drivers/serial/atmel_usart.c2
-rw-r--r--drivers/serial/ns16550.c20
-rw-r--r--drivers/serial/serial-uclass.c2
-rw-r--r--drivers/serial/serial_ar933x.c1
-rw-r--r--drivers/serial/serial_arc.c1
-rw-r--r--drivers/serial/serial_bcm283x_mu.c2
-rw-r--r--drivers/serial/serial_bcm283x_pl011.c2
-rw-r--r--drivers/serial/serial_bcm6345.c1
-rw-r--r--drivers/serial/serial_efi.c1
-rw-r--r--drivers/serial/serial_intel_mid.c1
-rw-r--r--drivers/serial/serial_lpuart.c1
-rw-r--r--drivers/serial/serial_meson.c1
-rw-r--r--drivers/serial/serial_mvebu_a3700.c1
-rw-r--r--drivers/serial/serial_mxc.c2
-rw-r--r--drivers/serial/serial_omap.c2
-rw-r--r--drivers/serial/serial_owl.c1
-rw-r--r--drivers/serial/serial_pic32.c1
-rw-r--r--drivers/serial/serial_pl01x.c2
-rw-r--r--drivers/serial/serial_s5p.c1
-rw-r--r--drivers/serial/serial_sh.c2
-rw-r--r--drivers/serial/serial_sti_asc.c1
-rw-r--r--drivers/serial/serial_stm32.c2
-rw-r--r--drivers/serial/serial_xuartlite.c1
-rw-r--r--drivers/serial/serial_zynq.c1
-rw-r--r--drivers/sysreset/sysreset_x86.c1
-rw-r--r--drivers/timer/Kconfig110
-rw-r--r--drivers/timer/ag101p_timer.c1
-rw-r--r--drivers/timer/altera_timer.c1
-rw-r--r--drivers/timer/arc_timer.c1
-rw-r--r--drivers/timer/ast_timer.c1
-rw-r--r--drivers/timer/atcpit100_timer.c1
-rw-r--r--drivers/timer/atmel_pit_timer.c1
-rw-r--r--drivers/timer/cadence-ttc.c1
-rw-r--r--drivers/timer/dw-apb-timer.c1
-rw-r--r--drivers/timer/mpc83xx_timer.c1
-rw-r--r--drivers/timer/omap-timer.c1
-rw-r--r--drivers/timer/rockchip_timer.c1
-rw-r--r--drivers/timer/sti-timer.c1
-rw-r--r--drivers/timer/stm32_timer.c1
-rw-r--r--drivers/timer/timer-uclass.c2
-rw-r--r--drivers/timer/tsc_timer.c1
-rw-r--r--drivers/video/simplefb.c1
-rw-r--r--drivers/virtio/Kconfig62
-rw-r--r--drivers/virtio/Makefile11
-rw-r--r--drivers/virtio/virtio-uclass.c369
-rw-r--r--drivers/virtio/virtio_blk.c137
-rw-r--r--drivers/virtio/virtio_blk.h129
-rw-r--r--drivers/virtio/virtio_mmio.c413
-rw-r--r--drivers/virtio/virtio_mmio.h129
-rw-r--r--drivers/virtio/virtio_net.c239
-rw-r--r--drivers/virtio/virtio_net.h268
-rw-r--r--drivers/virtio/virtio_pci.h173
-rw-r--r--drivers/virtio/virtio_pci_legacy.c421
-rw-r--r--drivers/virtio/virtio_pci_modern.c609
-rw-r--r--drivers/virtio/virtio_ring.c358
-rw-r--r--drivers/virtio/virtio_sandbox.c233
-rw-r--r--drivers/watchdog/ast_wdt.c1
-rw-r--r--include/blk.h22
-rw-r--r--include/dm/device-internal.h4
-rw-r--r--include/dm/lists.h9
-rw-r--r--include/dm/root.h17
-rw-r--r--include/dm/test.h1
-rw-r--r--include/dm/uclass-id.h1
-rw-r--r--include/dm/uclass.h4
-rw-r--r--include/dm/util.h27
-rw-r--r--include/init.h7
-rw-r--r--include/linux/io.h4
-rw-r--r--include/pci.h48
-rw-r--r--include/regmap.h232
-rw-r--r--include/virtio.h707
-rw-r--r--include/virtio_ring.h320
-rw-r--r--include/virtio_types.h24
-rw-r--r--lib/Kconfig6
-rw-r--r--lib/efi/efi_app.c1
-rw-r--r--lib/efi_driver/efi_block_device.c26
-rw-r--r--test/dm/Makefile1
-rw-r--r--test/dm/blk.c27
-rw-r--r--test/dm/bus.c47
-rw-r--r--test/dm/pci.c20
-rw-r--r--test/dm/regmap.c30
-rw-r--r--test/dm/test-fdt.c36
-rw-r--r--test/dm/virtio.c122
-rw-r--r--tools/buildman/README12
-rw-r--r--tools/buildman/board.py28
-rw-r--r--tools/buildman/cmdline.py4
-rw-r--r--tools/buildman/control.py20
-rw-r--r--tools/buildman/test.py31
171 files changed, 7486 insertions, 343 deletions
diff --git a/Documentation/devicetree/bindings/misc/gdsys,iocon_fpga.txt b/Documentation/devicetree/bindings/misc/gdsys,iocon_fpga.txt
new file mode 100644
index 0000000000..acd466fdc6
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/gdsys,iocon_fpga.txt
@@ -0,0 +1,19 @@
1gdsys IHS FPGA for CON devices
2
3The gdsys IHS FPGA is the main FPGA on gdsys CON devices. This driver provides
4support for enabling and starting the FPGA, as well as verifying working bus
5communication.
6
7Required properties:
8- compatible: must be "gdsys,iocon_fpga"
9- reset-gpios: List of GPIOs controlling the FPGA's reset
10- done-gpios: List of GPIOs notifying whether the FPGA's reconfiguration is
11 done
12
13Example:
14
15FPGA0 {
16 compatible = "gdsys,iocon_fpga";
17 reset-gpios = <&PPCPCA 26 0>;
18 done-gpios = <&GPIO_VB0 19 0>;
19};
diff --git a/Documentation/devicetree/bindings/misc/gdsys,iocpu_fpga.txt b/Documentation/devicetree/bindings/misc/gdsys,iocpu_fpga.txt
new file mode 100644
index 0000000000..819db22bf7
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/gdsys,iocpu_fpga.txt
@@ -0,0 +1,19 @@
1gdsys IHS FPGA for CPU devices
2
3The gdsys IHS FPGA is the main FPGA on gdsys CPU devices. This driver provides
4support for enabling and starting the FPGA, as well as verifying working bus
5communication.
6
7Required properties:
8- compatible: must be "gdsys,iocpu_fpga"
9- reset-gpios: List of GPIOs controlling the FPGA's reset
10- done-gpios: List of GPIOs notifying whether the FPGA's reconfiguration is
11 done
12
13Example:
14
15FPGA0 {
16 compatible = "gdsys,iocpu_fpga";
17 reset-gpios = <&PPCPCA 26 0>;
18 done-gpios = <&GPIO_VB0 19 0>;
19};
diff --git a/Documentation/devicetree/bindings/misc/gdsys,soc.txt b/Documentation/devicetree/bindings/misc/gdsys,soc.txt
new file mode 100644
index 0000000000..278e935b16
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/gdsys,soc.txt
@@ -0,0 +1,16 @@
1gdsys soc bus driver
2
3This driver provides a simple interface for the busses associated with gdsys
4IHS FPGAs. The bus itself contains devices whose register maps are contained
5within the FPGA's register space.
6
7Required properties:
8- fpga: A phandle to the controlling IHS FPGA
9
10Example:
11
12FPGA0BUS: fpga0bus {
13 compatible = "gdsys,soc";
14 ranges = <0x0 0xe0600000 0x00004000>;
15 fpga = <&FPGA0>;
16};
diff --git a/arch/Kconfig b/arch/Kconfig
index 1f2f407d64..9fdd2f7e66 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -110,6 +110,11 @@ config SANDBOX
110 imply LIBAVB 110 imply LIBAVB
111 imply CMD_AVB 111 imply CMD_AVB
112 imply UDP_FUNCTION_FASTBOOT 112 imply UDP_FUNCTION_FASTBOOT
113 imply VIRTIO_MMIO
114 imply VIRTIO_PCI
115 imply VIRTIO_SANDBOX
116 imply VIRTIO_BLK
117 imply VIRTIO_NET
113 118
114config SH 119config SH
115 bool "SuperH architecture" 120 bool "SuperH architecture"
@@ -120,6 +125,7 @@ config X86
120 select CREATE_ARCH_SYMLINK 125 select CREATE_ARCH_SYMLINK
121 select DM 126 select DM
122 select DM_PCI 127 select DM_PCI
128 select HAVE_ARCH_IOMAP
123 select HAVE_PRIVATE_LIBGCC 129 select HAVE_PRIVATE_LIBGCC
124 select OF_CONTROL 130 select OF_CONTROL
125 select PCI 131 select PCI
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2899a60793..f0e7fde137 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1496,6 +1496,7 @@ source "board/broadcom/bcmns2/Kconfig"
1496source "board/cavium/thunderx/Kconfig" 1496source "board/cavium/thunderx/Kconfig"
1497source "board/cirrus/edb93xx/Kconfig" 1497source "board/cirrus/edb93xx/Kconfig"
1498source "board/eets/pdu001/Kconfig" 1498source "board/eets/pdu001/Kconfig"
1499source "board/emulation/qemu-arm/Kconfig"
1499source "board/freescale/ls2080a/Kconfig" 1500source "board/freescale/ls2080a/Kconfig"
1500source "board/freescale/ls2080aqds/Kconfig" 1501source "board/freescale/ls2080aqds/Kconfig"
1501source "board/freescale/ls2080ardb/Kconfig" 1502source "board/freescale/ls2080ardb/Kconfig"
diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c
index 0e152efc04..d087a31389 100644
--- a/arch/arm/mach-stm32mp/bsec.c
+++ b/arch/arm/mach-stm32mp/bsec.c
@@ -417,7 +417,6 @@ U_BOOT_DRIVER(stm32mp_bsec) = {
417 .ofdata_to_platdata = stm32mp_bsec_ofdata_to_platdata, 417 .ofdata_to_platdata = stm32mp_bsec_ofdata_to_platdata,
418 .platdata_auto_alloc_size = sizeof(struct stm32mp_bsec_platdata), 418 .platdata_auto_alloc_size = sizeof(struct stm32mp_bsec_platdata),
419 .ops = &stm32mp_bsec_ops, 419 .ops = &stm32mp_bsec_ops,
420 .flags = DM_FLAG_PRE_RELOC,
421}; 420};
422 421
423/* bsec IP is not present in device tee, manage IP address by platdata */ 422/* bsec IP is not present in device tee, manage IP address by platdata */
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index 957442effd..7c40e415c7 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -547,6 +547,28 @@ __BUILD_CLRSETBITS(bwlq, sfx, end, type)
547#define __to_cpu(v) (v) 547#define __to_cpu(v) (v)
548#define cpu_to__(v) (v) 548#define cpu_to__(v) (v)
549 549
550#define out_arch(type, endian, a, v) __raw_write##type(cpu_to_##endian(v),a)
551#define in_arch(type, endian, a) endian##_to_cpu(__raw_read##type(a))
552
553#define out_le64(a, v) out_arch(q, le64, a, v)
554#define out_le32(a, v) out_arch(l, le32, a, v)
555#define out_le16(a, v) out_arch(w, le16, a, v)
556
557#define in_le64(a) in_arch(q, le64, a)
558#define in_le32(a) in_arch(l, le32, a)
559#define in_le16(a) in_arch(w, le16, a)
560
561#define out_be64(a, v) out_arch(q, be64, a, v)
562#define out_be32(a, v) out_arch(l, be32, a, v)
563#define out_be16(a, v) out_arch(w, be16, a, v)
564
565#define in_be64(a) in_arch(q, be64, a)
566#define in_be32(a) in_arch(l, be32, a)
567#define in_be16(a) in_arch(w, be16, a)
568
569#define out_8(a, v) __raw_writeb(v, a)
570#define in_8(a) __raw_readb(a)
571
550BUILD_CLRSETBITS(b, 8, _, u8) 572BUILD_CLRSETBITS(b, 8, _, u8)
551BUILD_CLRSETBITS(w, le16, le16, u16) 573BUILD_CLRSETBITS(w, le16, le16, u16)
552BUILD_CLRSETBITS(w, be16, be16, u16) 574BUILD_CLRSETBITS(w, be16, be16, u16)
diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c
index a7a9fb921b..2b5ccce933 100644
--- a/arch/riscv/lib/bootm.c
+++ b/arch/riscv/lib/bootm.c
@@ -9,9 +9,11 @@
9#include <common.h> 9#include <common.h>
10#include <command.h> 10#include <command.h>
11#include <image.h> 11#include <image.h>
12#include <u-boot/zlib.h>
13#include <asm/byteorder.h> 12#include <asm/byteorder.h>
14#include <asm/csr.h> 13#include <asm/csr.h>
14#include <dm/device.h>
15#include <dm/root.h>
16#include <u-boot/zlib.h>
15 17
16DECLARE_GLOBAL_DATA_PTR; 18DECLARE_GLOBAL_DATA_PTR;
17 19
@@ -57,6 +59,13 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
57 /* we assume that the kernel is in place */ 59 /* we assume that the kernel is in place */
58 printf("\nStarting kernel ...\n\n"); 60 printf("\nStarting kernel ...\n\n");
59 61
62 /*
63 * Call remove function of all devices with a removal flag set.
64 * This may be useful for last-stage operations, like cancelling
65 * of DMA operation or releasing device internal buffers.
66 */
67 dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
68
60 cleanup_before_linux(); 69 cleanup_before_linux();
61 70
62 if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) 71 if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 07e46471fe..325ded51d8 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -174,7 +174,12 @@ void *os_malloc(size_t length)
174 struct os_mem_hdr *hdr; 174 struct os_mem_hdr *hdr;
175 int page_size = getpagesize(); 175 int page_size = getpagesize();
176 176
177 hdr = mmap(NULL, length + page_size, 177 /*
178 * Use an address that is hopefully available to us so that pointers
179 * to this memory are fairly obvious. If we end up with a different
180 * address, that's fine too.
181 */
182 hdr = mmap((void *)0x10000000, length + page_size,
178 PROT_READ | PROT_WRITE | PROT_EXEC, 183 PROT_READ | PROT_WRITE | PROT_EXEC,
179 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 184 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
180 if (hdr == MAP_FAILED) 185 if (hdr == MAP_FAILED)
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 57e0dd7663..024aa7c512 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -186,6 +186,10 @@
186 compatible = "denx,u-boot-fdt-test"; 186 compatible = "denx,u-boot-fdt-test";
187 }; 187 };
188 188
189 h-test {
190 compatible = "denx,u-boot-fdt-test1";
191 };
192
189 clocks { 193 clocks {
190 clk_fixed: clk-fixed { 194 clk_fixed: clk-fixed {
191 compatible = "fixed-clock"; 195 compatible = "fixed-clock";
@@ -346,14 +350,17 @@
346 350
347 cpu-test1 { 351 cpu-test1 {
348 compatible = "sandbox,cpu_sandbox"; 352 compatible = "sandbox,cpu_sandbox";
353 u-boot,dm-pre-reloc;
349 }; 354 };
350 355
351 cpu-test2 { 356 cpu-test2 {
352 compatible = "sandbox,cpu_sandbox"; 357 compatible = "sandbox,cpu_sandbox";
358 u-boot,dm-pre-reloc;
353 }; 359 };
354 360
355 cpu-test3 { 361 cpu-test3 {
356 compatible = "sandbox,cpu_sandbox"; 362 compatible = "sandbox,cpu_sandbox";
363 u-boot,dm-pre-reloc;
357 }; 364 };
358 365
359 misc-test { 366 misc-test {
@@ -525,7 +532,7 @@
525 532
526 syscon@0 { 533 syscon@0 {
527 compatible = "sandbox,syscon0"; 534 compatible = "sandbox,syscon0";
528 reg = <0x10 4>; 535 reg = <0x10 16>;
529 }; 536 };
530 537
531 syscon@1 { 538 syscon@1 {
@@ -712,6 +719,14 @@
712 sandbox_tee { 719 sandbox_tee {
713 compatible = "sandbox,tee"; 720 compatible = "sandbox,tee";
714 }; 721 };
722
723 sandbox_virtio1 {
724 compatible = "sandbox,virtio1";
725 };
726
727 sandbox_virtio2 {
728 compatible = "sandbox,virtio2";
729 };
715}; 730};
716 731
717#include "sandbox_pmic.dtsi" 732#include "sandbox_pmic.dtsi"
diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c
index 56e98131d7..2eb917283b 100644
--- a/arch/x86/cpu/baytrail/cpu.c
+++ b/arch/x86/cpu/baytrail/cpu.c
@@ -203,4 +203,5 @@ U_BOOT_DRIVER(cpu_x86_baytrail_drv) = {
203 .bind = cpu_x86_bind, 203 .bind = cpu_x86_bind,
204 .probe = cpu_x86_baytrail_probe, 204 .probe = cpu_x86_baytrail_probe,
205 .ops = &cpu_x86_baytrail_ops, 205 .ops = &cpu_x86_baytrail_ops,
206 .flags = DM_FLAG_PRE_RELOC,
206}; 207};
diff --git a/arch/x86/cpu/broadwell/cpu.c b/arch/x86/cpu/broadwell/cpu.c
index 02b3169cf5..232fa40eb5 100644
--- a/arch/x86/cpu/broadwell/cpu.c
+++ b/arch/x86/cpu/broadwell/cpu.c
@@ -764,4 +764,5 @@ U_BOOT_DRIVER(cpu_x86_broadwell_drv) = {
764 .probe = cpu_x86_broadwell_probe, 764 .probe = cpu_x86_broadwell_probe,
765 .ops = &cpu_x86_broadwell_ops, 765 .ops = &cpu_x86_broadwell_ops,
766 .priv_auto_alloc_size = sizeof(struct cpu_broadwell_priv), 766 .priv_auto_alloc_size = sizeof(struct cpu_broadwell_priv),
767 .flags = DM_FLAG_PRE_RELOC,
767}; 768};
diff --git a/arch/x86/cpu/cpu_x86.c b/arch/x86/cpu/cpu_x86.c
index 2b6cc9f22d..1aaf851bb4 100644
--- a/arch/x86/cpu/cpu_x86.c
+++ b/arch/x86/cpu/cpu_x86.c
@@ -94,4 +94,5 @@ U_BOOT_DRIVER(cpu_x86_drv) = {
94 .of_match = cpu_x86_ids, 94 .of_match = cpu_x86_ids,
95 .bind = cpu_x86_bind, 95 .bind = cpu_x86_bind,
96 .ops = &cpu_x86_ops, 96 .ops = &cpu_x86_ops,
97 .flags = DM_FLAG_PRE_RELOC,
97}; 98};
diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c
index 33e5c6263d..6edc3e233c 100644
--- a/arch/x86/cpu/ivybridge/model_206ax.c
+++ b/arch/x86/cpu/ivybridge/model_206ax.c
@@ -478,4 +478,5 @@ U_BOOT_DRIVER(cpu_x86_model_206ax_drv) = {
478 .bind = cpu_x86_bind, 478 .bind = cpu_x86_bind,
479 .probe = cpu_x86_model_206ax_probe, 479 .probe = cpu_x86_model_206ax_probe,
480 .ops = &cpu_x86_model_206ax_ops, 480 .ops = &cpu_x86_model_206ax_ops,
481 .flags = DM_FLAG_PRE_RELOC,
481}; 482};
diff --git a/arch/x86/cpu/tangier/sysreset.c b/arch/x86/cpu/tangier/sysreset.c
index e762ee1b81..b03bc28f93 100644
--- a/arch/x86/cpu/tangier/sysreset.c
+++ b/arch/x86/cpu/tangier/sysreset.c
@@ -44,5 +44,4 @@ U_BOOT_DRIVER(tangier_sysreset) = {
44 .id = UCLASS_SYSRESET, 44 .id = UCLASS_SYSRESET,
45 .of_match = tangier_sysreset_ids, 45 .of_match = tangier_sysreset_ids,
46 .ops = &tangier_sysreset_ops, 46 .ops = &tangier_sysreset_ops,
47 .flags = DM_FLAG_PRE_RELOC,
48}; 47};
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index c05c6bf8a2..81def0afd3 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -241,6 +241,72 @@ static inline void sync(void)
241#define __iormb() dmb() 241#define __iormb() dmb()
242#define __iowmb() dmb() 242#define __iowmb() dmb()
243 243
244/*
245 * Read/write from/to an (offsettable) iomem cookie. It might be a PIO
246 * access or a MMIO access, these functions don't care. The info is
247 * encoded in the hardware mapping set up by the mapping functions
248 * (or the cookie itself, depending on implementation and hw).
249 *
250 * The generic routines don't assume any hardware mappings, and just
251 * encode the PIO/MMIO as part of the cookie. They coldly assume that
252 * the MMIO IO mappings are not in the low address range.
253 *
254 * Architectures for which this is not true can't use this generic
255 * implementation and should do their own copy.
256 */
257
258/*
259 * We assume that all the low physical PIO addresses (0-0xffff) always
260 * PIO. That means we can do some sanity checks on the low bits, and
261 * don't need to just take things for granted.
262 */
263#define PIO_RESERVED 0x10000UL
264
265/*
266 * Ugly macros are a way of life.
267 */
268#define IO_COND(addr, is_pio, is_mmio) do { \
269 unsigned long port = (unsigned long __force)addr; \
270 if (port >= PIO_RESERVED) { \
271 is_mmio; \
272 } else { \
273 is_pio; \
274 } \
275} while (0)
276
277static inline u8 ioread8(const volatile void __iomem *addr)
278{
279 IO_COND(addr, return inb(port), return readb(addr));
280 return 0xff;
281}
282
283static inline u16 ioread16(const volatile void __iomem *addr)
284{
285 IO_COND(addr, return inw(port), return readw(addr));
286 return 0xffff;
287}
288
289static inline u32 ioread32(const volatile void __iomem *addr)
290{
291 IO_COND(addr, return inl(port), return readl(addr));
292 return 0xffffffff;
293}
294
295static inline void iowrite8(u8 value, volatile void __iomem *addr)
296{
297 IO_COND(addr, outb(value, port), writeb(value, addr));
298}
299
300static inline void iowrite16(u16 value, volatile void __iomem *addr)
301{
302 IO_COND(addr, outw(value, port), writew(value, addr));
303}
304
305static inline void iowrite32(u32 value, volatile void __iomem *addr)
306{
307 IO_COND(addr, outl(value, port), writel(value, addr));
308}
309
244#include <asm-generic/io.h> 310#include <asm-generic/io.h>
245 311
246#endif /* _ASM_IO_H */ 312#endif /* _ASM_IO_H */
diff --git a/board/emulation/qemu-arm/Kconfig b/board/emulation/qemu-arm/Kconfig
new file mode 100644
index 0000000000..02ae4d9884
--- /dev/null
+++ b/board/emulation/qemu-arm/Kconfig
@@ -0,0 +1,13 @@
1if TARGET_QEMU_ARM_32BIT || TARGET_QEMU_ARM_64BIT
2
3config SYS_TEXT_BASE
4 default 0x00000000
5
6config BOARD_SPECIFIC_OPTIONS # dummy
7 def_bool y
8 imply VIRTIO_MMIO
9 imply VIRTIO_PCI
10 imply VIRTIO_NET
11 imply VIRTIO_BLK
12
13endif
diff --git a/board/emulation/qemu-arm/qemu-arm.c b/board/emulation/qemu-arm/qemu-arm.c
index 812c90636d..e1f4709c4c 100644
--- a/board/emulation/qemu-arm/qemu-arm.c
+++ b/board/emulation/qemu-arm/qemu-arm.c
@@ -2,8 +2,12 @@
2/* 2/*
3 * Copyright (c) 2017 Tuomas Tynkkynen 3 * Copyright (c) 2017 Tuomas Tynkkynen
4 */ 4 */
5
5#include <common.h> 6#include <common.h>
7#include <dm.h>
6#include <fdtdec.h> 8#include <fdtdec.h>
9#include <virtio_types.h>
10#include <virtio.h>
7 11
8#ifdef CONFIG_ARM64 12#ifdef CONFIG_ARM64
9#include <asm/armv8/mmu.h> 13#include <asm/armv8/mmu.h>
@@ -58,6 +62,12 @@ struct mm_region *mem_map = qemu_arm64_mem_map;
58 62
59int board_init(void) 63int board_init(void)
60{ 64{
65 /*
66 * Make sure virtio bus is enumerated so that peripherals
67 * on the virtio bus can be discovered by their drivers
68 */
69 virtio_init();
70
61 return 0; 71 return 0;
62} 72}
63 73
diff --git a/board/emulation/qemu-riscv/Kconfig b/board/emulation/qemu-riscv/Kconfig
index af23363fcf..37a80db6a9 100644
--- a/board/emulation/qemu-riscv/Kconfig
+++ b/board/emulation/qemu-riscv/Kconfig
@@ -18,5 +18,16 @@ config SYS_TEXT_BASE
18config BOARD_SPECIFIC_OPTIONS # dummy 18config BOARD_SPECIFIC_OPTIONS # dummy
19 def_bool y 19 def_bool y
20 imply SYS_NS16550 20 imply SYS_NS16550
21 imply VIRTIO_MMIO
22 imply VIRTIO_NET
23 imply VIRTIO_BLK
24 imply CMD_PING
25 imply CMD_FS_GENERIC
26 imply DOS_PARTITION
27 imply EFI_PARTITION
28 imply ISO_PARTITION
29 imply CMD_EXT2
30 imply CMD_EXT4
31 imply CMD_FAT
21 32
22endif 33endif
diff --git a/board/emulation/qemu-riscv/qemu-riscv.c b/board/emulation/qemu-riscv/qemu-riscv.c
index 041e716c9b..2730a288fb 100644
--- a/board/emulation/qemu-riscv/qemu-riscv.c
+++ b/board/emulation/qemu-riscv/qemu-riscv.c
@@ -4,12 +4,21 @@
4 */ 4 */
5 5
6#include <common.h> 6#include <common.h>
7#include <dm.h>
7#include <fdtdec.h> 8#include <fdtdec.h>
9#include <virtio_types.h>
10#include <virtio.h>
8 11
9#define MROM_FDT_ADDR 0x1020 12#define MROM_FDT_ADDR 0x1020
10 13
11int board_init(void) 14int board_init(void)
12{ 15{
16 /*
17 * Make sure virtio bus is enumerated so that peripherals
18 * on the virtio bus can be discovered by their drivers
19 */
20 virtio_init();
21
13 return 0; 22 return 0;
14} 23}
15 24
diff --git a/board/emulation/qemu-x86/Kconfig b/board/emulation/qemu-x86/Kconfig
index 41a27dd933..6d19299d8b 100644
--- a/board/emulation/qemu-x86/Kconfig
+++ b/board/emulation/qemu-x86/Kconfig
@@ -21,5 +21,8 @@ config BOARD_SPECIFIC_OPTIONS # dummy
21 select X86_RESET_VECTOR 21 select X86_RESET_VECTOR
22 select QEMU 22 select QEMU
23 select BOARD_ROMSIZE_KB_1024 23 select BOARD_ROMSIZE_KB_1024
24 imply VIRTIO_PCI
25 imply VIRTIO_NET
26 imply VIRTIO_BLK
24 27
25endif 28endif
diff --git a/cmd/Kconfig b/cmd/Kconfig
index ad14c9ce71..d609f9d1c9 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1065,6 +1065,13 @@ config CMD_USB_MASS_STORAGE
1065 help 1065 help
1066 USB mass storage support 1066 USB mass storage support
1067 1067
1068config CMD_VIRTIO
1069 bool "virtio"
1070 depends on VIRTIO
1071 default y if VIRTIO
1072 help
1073 VirtIO block device support
1074
1068config CMD_AXI 1075config CMD_AXI
1069 bool "axi" 1076 bool "axi"
1070 depends on AXI 1077 depends on AXI
diff --git a/cmd/Makefile b/cmd/Makefile
index ac4830a692..12a1330b06 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -135,6 +135,7 @@ obj-$(CONFIG_CMD_UBI) += ubi.o
135obj-$(CONFIG_CMD_UBIFS) += ubifs.o 135obj-$(CONFIG_CMD_UBIFS) += ubifs.o
136obj-$(CONFIG_CMD_UNIVERSE) += universe.o 136obj-$(CONFIG_CMD_UNIVERSE) += universe.o
137obj-$(CONFIG_CMD_UNZIP) += unzip.o 137obj-$(CONFIG_CMD_UNZIP) += unzip.o
138obj-$(CONFIG_CMD_VIRTIO) += virtio.o
138obj-$(CONFIG_CMD_LZMADEC) += lzmadec.o 139obj-$(CONFIG_CMD_LZMADEC) += lzmadec.o
139 140
140obj-$(CONFIG_CMD_USB) += usb.o disk.o 141obj-$(CONFIG_CMD_USB) += usb.o disk.o
diff --git a/cmd/sata.c b/cmd/sata.c
index 4f0c6e0137..6d62ba8f74 100644
--- a/cmd/sata.c
+++ b/cmd/sata.c
@@ -51,7 +51,6 @@ int sata_probe(int devnum)
51{ 51{
52#ifdef CONFIG_AHCI 52#ifdef CONFIG_AHCI
53 struct udevice *dev; 53 struct udevice *dev;
54 struct udevice *blk;
55 int rc; 54 int rc;
56 55
57 rc = uclass_get_device(UCLASS_AHCI, devnum, &dev); 56 rc = uclass_get_device(UCLASS_AHCI, devnum, &dev);
@@ -67,14 +66,6 @@ int sata_probe(int devnum)
67 return CMD_RET_FAILURE; 66 return CMD_RET_FAILURE;
68 } 67 }
69 68
70 rc = blk_get_from_parent(dev, &blk);
71 if (!rc) {
72 struct blk_desc *desc = dev_get_uclass_platdata(blk);
73
74 if (desc->lba > 0 && desc->blksz > 0)
75 part_init(desc);
76 }
77
78 return 0; 69 return 0;
79#else 70#else
80 return sata_initialize() < 0 ? CMD_RET_FAILURE : CMD_RET_SUCCESS; 71 return sata_initialize() < 0 ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
diff --git a/cmd/virtio.c b/cmd/virtio.c
new file mode 100644
index 0000000000..b7082bc63a
--- /dev/null
+++ b/cmd/virtio.c
@@ -0,0 +1,38 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2018, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
4 * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
5 */
6
7#include <common.h>
8#include <command.h>
9#include <dm.h>
10#include <virtio_types.h>
11#include <virtio.h>
12
13static int virtio_curr_dev;
14
15static int do_virtio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
16{
17 if (argc == 2 && !strcmp(argv[1], "scan")) {
18 /* make sure all virtio devices are enumerated */
19 virtio_init();
20
21 return CMD_RET_SUCCESS;
22 }
23
24 return blk_common_cmd(argc, argv, IF_TYPE_VIRTIO, &virtio_curr_dev);
25}
26
27U_BOOT_CMD(
28 virtio, 8, 1, do_virtio,
29 "virtio block devices sub-system",
30 "scan - initialize virtio bus\n"
31 "virtio info - show all available virtio block devices\n"
32 "virtio device [dev] - show or set current virtio block device\n"
33 "virtio part [dev] - print partition table of one or all virtio block devices\n"
34 "virtio read addr blk# cnt - read `cnt' blocks starting at block\n"
35 " `blk#' to memory address `addr'\n"
36 "virtio write addr blk# cnt - write `cnt' blocks starting at block\n"
37 " `blk#' from memory address `addr'"
38);
diff --git a/common/board_f.c b/common/board_f.c
index afafec5e4d..96503ff8d3 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -11,6 +11,7 @@
11 11
12#include <common.h> 12#include <common.h>
13#include <console.h> 13#include <console.h>
14#include <cpu.h>
14#include <dm.h> 15#include <dm.h>
15#include <environment.h> 16#include <environment.h>
16#include <fdtdec.h> 17#include <fdtdec.h>
@@ -165,6 +166,33 @@ static int print_resetinfo(void)
165} 166}
166#endif 167#endif
167 168
169#if defined(CONFIG_DISPLAY_CPUINFO) && CONFIG_IS_ENABLED(CPU)
170static int print_cpuinfo(void)
171{
172 struct udevice *dev;
173 char desc[512];
174 int ret;
175
176 ret = uclass_first_device_err(UCLASS_CPU, &dev);
177 if (ret) {
178 debug("%s: Could not get CPU device (err = %d)\n",
179 __func__, ret);
180 return ret;
181 }
182
183 ret = cpu_get_desc(dev, desc, sizeof(desc));
184 if (ret) {
185 debug("%s: Could not get CPU description (err = %d)\n",
186 dev->name, ret);
187 return ret;
188 }
189
190 printf("CPU: %s\n", desc);
191
192 return 0;
193}
194#endif
195
168static int announce_dram_init(void) 196static int announce_dram_init(void)
169{ 197{
170 puts("DRAM: "); 198 puts("DRAM: ");
diff --git a/common/usb_storage.c b/common/usb_storage.c
index d92ebb6eb1..560d60538b 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -226,9 +226,7 @@ static int usb_stor_probe_device(struct usb_device *udev)
226 blkdev->lun = lun; 226 blkdev->lun = lun;
227 227
228 ret = usb_stor_get_info(udev, data, blkdev); 228 ret = usb_stor_get_info(udev, data, blkdev);
229 if (ret == 1) 229 if (ret == 1) {
230 ret = blk_prepare_device(dev);
231 if (!ret) {
232 usb_max_devs++; 230 usb_max_devs++;
233 debug("%s: Found device %p\n", __func__, udev); 231 debug("%s: Found device %p\n", __func__, udev);
234 } else { 232 } else {
diff --git a/configs/imx8qxp_mek_defconfig b/configs/imx8qxp_mek_defconfig
index 518f7259f2..58b4ca0861 100644
--- a/configs/imx8qxp_mek_defconfig
+++ b/configs/imx8qxp_mek_defconfig
@@ -6,7 +6,6 @@ CONFIG_TARGET_IMX8QXP_MEK=y
6CONFIG_NR_DRAM_BANKS=3 6CONFIG_NR_DRAM_BANKS=3
7CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/imx8qxp_mek/imximage.cfg" 7CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/imx8qxp_mek/imximage.cfg"
8CONFIG_BOOTDELAY=3 8CONFIG_BOOTDELAY=3
9# CONFIG_DISPLAY_CPUINFO is not set
10CONFIG_CMD_CPU=y 9CONFIG_CMD_CPU=y
11# CONFIG_CMD_IMPORTENV is not set 10# CONFIG_CMD_IMPORTENV is not set
12CONFIG_CMD_CLK=y 11CONFIG_CMD_CLK=y
diff --git a/configs/qemu_arm64_defconfig b/configs/qemu_arm64_defconfig
index e9e2819272..f4502c9e9f 100644
--- a/configs/qemu_arm64_defconfig
+++ b/configs/qemu_arm64_defconfig
@@ -1,7 +1,6 @@
1CONFIG_ARM=y 1CONFIG_ARM=y
2CONFIG_ARM_SMCCC=y 2CONFIG_ARM_SMCCC=y
3CONFIG_ARCH_QEMU=y 3CONFIG_ARCH_QEMU=y
4CONFIG_SYS_TEXT_BASE=0x00000000
5CONFIG_TARGET_QEMU_ARM_64BIT=y 4CONFIG_TARGET_QEMU_ARM_64BIT=y
6CONFIG_AHCI=y 5CONFIG_AHCI=y
7CONFIG_DISTRO_DEFAULTS=y 6CONFIG_DISTRO_DEFAULTS=y
diff --git a/configs/qemu_arm_defconfig b/configs/qemu_arm_defconfig
index 04c9afdb02..acebdc5a4e 100644
--- a/configs/qemu_arm_defconfig
+++ b/configs/qemu_arm_defconfig
@@ -1,7 +1,6 @@
1CONFIG_ARM=y 1CONFIG_ARM=y
2CONFIG_ARM_SMCCC=y 2CONFIG_ARM_SMCCC=y
3CONFIG_ARCH_QEMU=y 3CONFIG_ARCH_QEMU=y
4CONFIG_SYS_TEXT_BASE=0x00000000
5CONFIG_TARGET_QEMU_ARM_32BIT=y 4CONFIG_TARGET_QEMU_ARM_32BIT=y
6CONFIG_AHCI=y 5CONFIG_AHCI=y
7CONFIG_DISTRO_DEFAULTS=y 6CONFIG_DISTRO_DEFAULTS=y
diff --git a/configs/sandbox_noblk_defconfig b/configs/sandbox_noblk_defconfig
index 93b2240185..e71e2d3860 100644
--- a/configs/sandbox_noblk_defconfig
+++ b/configs/sandbox_noblk_defconfig
@@ -171,6 +171,7 @@ CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y
171CONFIG_VIDEO_SANDBOX_SDL=y 171CONFIG_VIDEO_SANDBOX_SDL=y
172CONFIG_OSD=y 172CONFIG_OSD=y
173CONFIG_SANDBOX_OSD=y 173CONFIG_SANDBOX_OSD=y
174# CONFIG_VIRTIO_BLK is not set
174CONFIG_FS_CBFS=y 175CONFIG_FS_CBFS=y
175CONFIG_FS_CRAMFS=y 176CONFIG_FS_CRAMFS=y
176CONFIG_CMD_DHRYSTONE=y 177CONFIG_CMD_DHRYSTONE=y
diff --git a/disk/part.c b/disk/part.c
index 9e457a6e72..f30f9e9187 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -150,6 +150,9 @@ void dev_print (struct blk_desc *dev_desc)
150 dev_desc->revision, 150 dev_desc->revision,
151 dev_desc->product); 151 dev_desc->product);
152 break; 152 break;
153 case IF_TYPE_VIRTIO:
154 printf("%s VirtIO Block Device\n", dev_desc->vendor);
155 break;
153 case IF_TYPE_DOC: 156 case IF_TYPE_DOC:
154 puts("device type DOC\n"); 157 puts("device type DOC\n");
155 return; 158 return;
@@ -281,6 +284,9 @@ static void print_part_header(const char *type, struct blk_desc *dev_desc)
281 case IF_TYPE_NVME: 284 case IF_TYPE_NVME:
282 puts ("NVMe"); 285 puts ("NVMe");
283 break; 286 break;
287 case IF_TYPE_VIRTIO:
288 puts("VirtIO");
289 break;
284 default: 290 default:
285 puts ("UNKNOWN"); 291 puts ("UNKNOWN");
286 break; 292 break;
diff --git a/doc/README.virtio b/doc/README.virtio
new file mode 100644
index 0000000000..d3652f2e2f
--- /dev/null
+++ b/doc/README.virtio
@@ -0,0 +1,253 @@
1# SPDX-License-Identifier: GPL-2.0+
2#
3# Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
4
5VirtIO Support
6==============
7
8This document describes the information about U-Boot support for VirtIO [1]
9devices, including supported boards, build instructions, driver details etc.
10
11What's VirtIO?
12--------------
13VirtIO is a virtualization standard for network and disk device drivers where
14just the guest's device driver "knows" it is running in a virtual environment,
15and cooperates with the hypervisor. This enables guests to get high performance
16network and disk operations, and gives most of the performance benefits of
17paravirtualization. In the U-Boot case, the guest is U-Boot itself, while the
18virtual environment are normally QEMU [2] targets like ARM, RISC-V and x86.
19
20Status
21------
22VirtIO can use various different buses, aka transports as described in the
23spec. While VirtIO devices are commonly implemented as PCI devices on x86,
24embedded devices models like ARM/RISC-V, which does not normally come with
25PCI support might use simple memory mapped device (MMIO) instead of the PCI
26device. The memory mapped virtio device behaviour is based on the PCI device
27specification. Therefore most operations including device initialization,
28queues configuration and buffer transfers are nearly identical. Both MMIO
29and PCI transport options are supported in U-Boot.
30
31The VirtIO spec defines a lots of VirtIO device types, however at present only
32network and block device, the most two commonly used devices, are supported.
33
34The following QEMU targets are supported.
35
36 - qemu_arm_defconfig
37 - qemu_arm64_defconfig
38 - qemu-riscv32_defconfig
39 - qemu-riscv64_defconfig
40 - qemu-x86_defconfig
41 - qemu-x86_64_defconfig
42
43Note ARM and RISC-V targets are configured with VirtIO MMIO transport driver,
44and on x86 it's the PCI transport driver.
45
46Build Instructions
47------------------
48Building U-Boot for pre-configured QEMU targets is no different from others.
49For example, we can do the following with the CROSS_COMPILE environment
50variable being properly set to a working toolchain for ARM:
51
52 $ make qemu_arm_defconfig
53 $ make
54
55You can even create a QEMU ARM target with VirtIO devices showing up on both
56MMIO and PCI buses. In this case, you can enable the PCI transport driver
57from 'make menuconfig':
58
59Device Drivers --->
60 ...
61 VirtIO Drivers --->
62 ...
63 [*] PCI driver for virtio devices
64
65Other drivers are at the same location and can be tuned to suit the needs.
66
67Requirements
68------------
69It is required that QEMU v2.5.0+ should be used to test U-Boot VirtIO support
70on QEMU ARM and x86, and v2.12.0+ on QEMU RISC-V.
71
72Testing
73-------
74The following QEMU command line is used to get U-Boot up and running with
75VirtIO net and block devices on ARM.
76
77 $ qemu-system-arm -nographic -machine virt -bios u-boot.bin \
78 -netdev tap,ifname=tap0,id=net0 \
79 -device virtio-net-device,netdev=net0 \
80 -drive if=none,file=test.img,format=raw,id=hd0 \
81 -device virtio-blk-device,drive=hd0
82
83On x86, command is slightly different to create PCI VirtIO devices.
84
85 $ qemu-system-i386 -nographic -bios u-boot.rom \
86 -netdev tap,ifname=tap0,id=net0 \
87 -device virtio-net-pci,netdev=net0 \
88 -drive if=none,file=test.img,format=raw,id=hd0 \
89 -device virtio-blk-pci,drive=hd0
90
91Additional net and block devices can be created by appending more '-device'
92parameters. It is also possible to specify both MMIO and PCI VirtIO devices.
93For example, the following commnad creates 3 VirtIO devices, with 1 on MMIO
94and 2 on PCI bus.
95
96 $ qemu-system-arm -nographic -machine virt -bios u-boot.bin \
97 -netdev tap,ifname=tap0,id=net0 \
98 -device virtio-net-pci,netdev=net0 \
99 -drive if=none,file=test0.img,format=raw,id=hd0 \
100 -device virtio-blk-device,drive=hd0 \
101 -drive if=none,file=test1.img,format=raw,id=hd1 \
102 -device virtio-blk-pci,drive=hd1
103
104By default QEMU creates VirtIO legacy devices by default. To create non-legacy
105(aka modern) devices, pass additional device property/value pairs like below:
106
107 $ qemu-system-i386 -nographic -bios u-boot.rom \
108 -netdev tap,ifname=tap0,id=net0 \
109 -device virtio-net-pci,netdev=net0,disable-legacy=true,disable-modern=false \
110 -drive if=none,file=test.img,format=raw,id=hd0 \
111 -device virtio-blk-pci,drive=hd0,disable-legacy=true,disable-modern=false
112
113A 'virtio' command is provided in U-Boot shell.
114
115 => virtio
116 virtio - virtio block devices sub-system
117
118 Usage:
119 virtio scan - initialize virtio bus
120 virtio info - show all available virtio block devices
121 virtio device [dev] - show or set current virtio block device
122 virtio part [dev] - print partition table of one or all virtio block devices
123 virtio read addr blk# cnt - read `cnt' blocks starting at block
124 `blk#' to memory address `addr'
125 virtio write addr blk# cnt - write `cnt' blocks starting at block
126 `blk#' from memory address `addr'
127
128To probe all the VirtIO devices, type:
129
130 => virtio scan
131
132Then we can show the connected block device details by:
133
134 => virtio info
135 Device 0: QEMU VirtIO Block Device
136 Type: Hard Disk
137 Capacity: 4096.0 MB = 4.0 GB (8388608 x 512)
138
139And list the directories and files on the disk by:
140
141 => ls virtio 0 /
142 <DIR> 4096 .
143 <DIR> 4096 ..
144 <DIR> 16384 lost+found
145 <DIR> 4096 dev
146 <DIR> 4096 proc
147 <DIR> 4096 sys
148 <DIR> 4096 var
149 <DIR> 4096 etc
150 <DIR> 4096 usr
151 <SYM> 7 bin
152 <SYM> 8 sbin
153 <SYM> 7 lib
154 <SYM> 9 lib64
155 <DIR> 4096 run
156 <DIR> 4096 boot
157 <DIR> 4096 home
158 <DIR> 4096 media
159 <DIR> 4096 mnt
160 <DIR> 4096 opt
161 <DIR> 4096 root
162 <DIR> 4096 srv
163 <DIR> 4096 tmp
164 0 .autorelabel
165
166Driver Internals
167----------------
168There are 3 level of drivers in the VirtIO driver family.
169
170 +---------------------------------------+
171 | virtio device drivers |
172 | +-------------+ +------------+ |
173 | | virtio-net | | virtio-blk | |
174 | +-------------+ +------------+ |
175 +---------------------------------------+
176 +---------------------------------------+
177 | virtio transport drivers |
178 | +-------------+ +------------+ |
179 | | virtio-mmio | | virtio-pci | |
180 | +-------------+ +------------+ |
181 +---------------------------------------+
182 +----------------------+
183 | virtio uclass driver |
184 +----------------------+
185
186The root one is the virtio uclass driver (virtio-uclass.c), which does lots of
187common stuff for the transport drivers (virtio_mmio.c, virtio_pci.c). The real
188virtio device is discovered in the transport driver's probe() method, and its
189device ID is saved in the virtio uclass's private data of the transport device.
190Then in the virtio uclass's post_probe() method, the real virtio device driver
191(virtio_net.c, virtio_blk.c) is bound if there is a match on the device ID.
192
193The child_post_bind(), child_pre_probe() and child_post_probe() methods of the
194virtio uclass driver help bring the virtio device driver online. They do things
195like acknowledging device, feature negotiation, etc, which are really common
196for all virtio devices.
197
198The transport drivers provide a set of ops (struct dm_virtio_ops) for the real
199virtio device driver to call. These ops APIs's parameter is designed to remind
200the caller to pass the correct 'struct udevice' id of the virtio device, eg:
201
202int virtio_get_status(struct udevice *vdev, u8 *status)
203
204So the parameter 'vdev' indicates the device should be the real virtio device.
205But we also have an API like:
206
207struct virtqueue *vring_create_virtqueue(unsigned int index, unsigned int num,
208 unsigned int vring_align,
209 struct udevice *udev)
210
211Here the parameter 'udev' indicates the device should be the transport device.
212Similar naming is applied in other functions that are even not APIs, eg:
213
214static int virtio_uclass_post_probe(struct udevice *udev)
215static int virtio_uclass_child_pre_probe(struct udevice *vdev)
216
217So it's easy to tell which device these functions are operating on.
218
219Development Flow
220----------------
221At present only VirtIO network card (device ID 1) and block device (device
222ID 2) are supported. If you want to develop new driver for new devices,
223please follow the guideline below.
224
2251. add new device ID in virtio.h
226#define VIRTIO_ID_XXX X
227
2282. update VIRTIO_ID_MAX_NUM to be the largest device ID plus 1
229
2303. add new driver name string in virtio.h
231#define VIRTIO_XXX_DRV_NAME "virtio-xxx"
232
2334. create a new driver with name set to the name string above
234U_BOOT_DRIVER(virtio_xxx) = {
235 .name = VIRTIO_XXX_DRV_NAME,
236 ...
237 .remove = virtio_reset,
238 .flags = DM_FLAG_ACTIVE_DMA,
239}
240
241Note the driver needs to provide the remove method and normally this can be
242hooked to virtio_reset(). The driver flags should contain DM_FLAG_ACTIVE_DMA
243for the remove method to be called before jumping to OS.
244
2455. provide bind() method in the driver, where virtio_driver_features_init()
246 should be called for driver to negotiate feature support with the device.
247
2486. do funny stuff with the driver
249
250References
251----------
252[1] http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.pdf
253[2] https://www.qemu.org
diff --git a/doc/driver-model/README.txt b/doc/driver-model/README.txt
index 36541630a2..07b120d512 100644
--- a/doc/driver-model/README.txt
+++ b/doc/driver-model/README.txt
@@ -830,10 +830,18 @@ Pre-Relocation Support
830---------------------- 830----------------------
831 831
832For pre-relocation we simply call the driver model init function. Only 832For pre-relocation we simply call the driver model init function. Only
833drivers marked with DM_FLAG_PRE_RELOC or the device tree 833drivers marked with DM_FLAG_PRE_RELOC or the device tree 'u-boot,dm-pre-reloc'
834'u-boot,dm-pre-reloc' flag are initialised prior to relocation. This helps 834property are initialised prior to relocation. This helps to reduce the driver
835to reduce the driver model overhead. This flag applies to SPL and TPL as 835model overhead. This flag applies to SPL and TPL as well, if device tree is
836well, if device tree is enabled there. 836enabled (CONFIG_OF_CONTROL) there.
837
838Note when device tree is enabled, the device tree 'u-boot,dm-pre-reloc'
839property can provide better control granularity on which device is bound
840before relocation. While with DM_FLAG_PRE_RELOC flag of the driver all
841devices with the same driver are bound, which requires allocation a large
842amount of memory. When device tree is not used, DM_FLAG_PRE_RELOC is the
843only way for statically declared devices via U_BOOT_DEVICE() to be bound
844prior to relocation.
837 845
838It is possible to limit this to specific relocation steps, by using 846It is possible to limit this to specific relocation steps, by using
839the more specialized 'u-boot,dm-spl' and 'u-boot,dm-tpl' flags 847the more specialized 'u-boot,dm-spl' and 'u-boot,dm-tpl' flags
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 927a2b87f6..4ac823d962 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -112,6 +112,8 @@ source "drivers/usb/Kconfig"
112 112
113source "drivers/video/Kconfig" 113source "drivers/video/Kconfig"
114 114
115source "drivers/virtio/Kconfig"
116
115source "drivers/w1/Kconfig" 117source "drivers/w1/Kconfig"
116 118
117source "drivers/w1-eeprom/Kconfig" 119source "drivers/w1-eeprom/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index fb38b67541..4453c62ad3 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_$(SPL_TPL_)SERIAL_SUPPORT) += serial/
14obj-$(CONFIG_$(SPL_TPL_)SPI_FLASH_SUPPORT) += mtd/spi/ 14obj-$(CONFIG_$(SPL_TPL_)SPI_FLASH_SUPPORT) += mtd/spi/
15obj-$(CONFIG_$(SPL_TPL_)SPI_SUPPORT) += spi/ 15obj-$(CONFIG_$(SPL_TPL_)SPI_SUPPORT) += spi/
16obj-$(CONFIG_$(SPL_TPL_)TIMER) += timer/ 16obj-$(CONFIG_$(SPL_TPL_)TIMER) += timer/
17obj-$(CONFIG_$(SPL_TPL_)VIRTIO) += virtio/
17obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox/ 18obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox/
18obj-$(CONFIG_$(SPL_)REMOTEPROC) += remoteproc/ 19obj-$(CONFIG_$(SPL_)REMOTEPROC) += remoteproc/
19 20
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index facf52711c..65a766e586 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -23,6 +23,7 @@ static const char *if_typename_str[IF_TYPE_COUNT] = {
23 [IF_TYPE_HOST] = "host", 23 [IF_TYPE_HOST] = "host",
24 [IF_TYPE_NVME] = "nvme", 24 [IF_TYPE_NVME] = "nvme",
25 [IF_TYPE_EFI] = "efi", 25 [IF_TYPE_EFI] = "efi",
26 [IF_TYPE_VIRTIO] = "virtio",
26}; 27};
27 28
28static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = { 29static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = {
@@ -37,6 +38,7 @@ static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = {
37 [IF_TYPE_HOST] = UCLASS_ROOT, 38 [IF_TYPE_HOST] = UCLASS_ROOT,
38 [IF_TYPE_NVME] = UCLASS_NVME, 39 [IF_TYPE_NVME] = UCLASS_NVME,
39 [IF_TYPE_EFI] = UCLASS_EFI, 40 [IF_TYPE_EFI] = UCLASS_EFI,
41 [IF_TYPE_VIRTIO] = UCLASS_VIRTIO,
40}; 42};
41 43
42static enum if_type if_typename_to_iftype(const char *if_typename) 44static enum if_type if_typename_to_iftype(const char *if_typename)
@@ -471,15 +473,6 @@ unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start,
471 return ops->erase(dev, start, blkcnt); 473 return ops->erase(dev, start, blkcnt);
472} 474}
473 475
474int blk_prepare_device(struct udevice *dev)
475{
476 struct blk_desc *desc = dev_get_uclass_platdata(dev);
477
478 part_init(desc);
479
480 return 0;
481}
482
483int blk_get_from_parent(struct udevice *parent, struct udevice **devp) 476int blk_get_from_parent(struct udevice *parent, struct udevice **devp)
484{ 477{
485 struct udevice *dev; 478 struct udevice *dev;
@@ -526,7 +519,7 @@ int blk_find_max_devnum(enum if_type if_type)
526 return max_devnum; 519 return max_devnum;
527} 520}
528 521
529static int blk_next_free_devnum(enum if_type if_type) 522int blk_next_free_devnum(enum if_type if_type)
530{ 523{
531 int ret; 524 int ret;
532 525
@@ -644,8 +637,20 @@ int blk_unbind_all(int if_type)
644 return 0; 637 return 0;
645} 638}
646 639
640static int blk_post_probe(struct udevice *dev)
641{
642#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT)
643 struct blk_desc *desc = dev_get_uclass_platdata(dev);
644
645 part_init(desc);
646#endif
647
648 return 0;
649}
650
647UCLASS_DRIVER(blk) = { 651UCLASS_DRIVER(blk) = {
648 .id = UCLASS_BLK, 652 .id = UCLASS_BLK,
649 .name = "blk", 653 .name = "blk",
654 .post_probe = blk_post_probe,
650 .per_device_platdata_auto_alloc_size = sizeof(struct blk_desc), 655 .per_device_platdata_auto_alloc_size = sizeof(struct blk_desc),
651}; 656};
diff --git a/drivers/block/ide.c b/drivers/block/ide.c
index 38adb6a241..4b8a4eac17 100644
--- a/drivers/block/ide.c
+++ b/drivers/block/ide.c
@@ -1169,8 +1169,6 @@ static int ide_blk_probe(struct udevice *udev)
1169 BLK_REV_SIZE); 1169 BLK_REV_SIZE);
1170 desc->revision[BLK_REV_SIZE] = '\0'; 1170 desc->revision[BLK_REV_SIZE] = '\0';
1171 1171
1172 part_init(desc);
1173
1174 return 0; 1172 return 0;
1175} 1173}
1176 1174
diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c
index 0392437309..d3b1aaaba3 100644
--- a/drivers/block/sandbox.c
+++ b/drivers/block/sandbox.c
@@ -33,7 +33,7 @@ static unsigned long host_block_read(struct udevice *dev,
33 unsigned long start, lbaint_t blkcnt, 33 unsigned long start, lbaint_t blkcnt,
34 void *buffer) 34 void *buffer)
35{ 35{
36 struct host_block_dev *host_dev = dev_get_priv(dev); 36 struct host_block_dev *host_dev = dev_get_platdata(dev);
37 struct blk_desc *block_dev = dev_get_uclass_platdata(dev); 37 struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
38 38
39#else 39#else
@@ -64,7 +64,7 @@ static unsigned long host_block_write(struct udevice *dev,
64 unsigned long start, lbaint_t blkcnt, 64 unsigned long start, lbaint_t blkcnt,
65 const void *buffer) 65 const void *buffer)
66{ 66{
67 struct host_block_dev *host_dev = dev_get_priv(dev); 67 struct host_block_dev *host_dev = dev_get_platdata(dev);
68 struct blk_desc *block_dev = dev_get_uclass_platdata(dev); 68 struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
69#else 69#else
70static unsigned long host_block_write(struct blk_desc *block_dev, 70static unsigned long host_block_write(struct blk_desc *block_dev,
@@ -131,17 +131,18 @@ int host_dev_bind(int devnum, char *filename)
131 os_lseek(fd, 0, OS_SEEK_END) / 512, &dev); 131 os_lseek(fd, 0, OS_SEEK_END) / 512, &dev);
132 if (ret) 132 if (ret)
133 goto err_file; 133 goto err_file;
134
135 host_dev = dev_get_platdata(dev);
136 host_dev->fd = fd;
137 host_dev->filename = fname;
138
134 ret = device_probe(dev); 139 ret = device_probe(dev);
135 if (ret) { 140 if (ret) {
136 device_unbind(dev); 141 device_unbind(dev);
137 goto err_file; 142 goto err_file;
138 } 143 }
139 144
140 host_dev = dev_get_priv(dev); 145 return 0;
141 host_dev->fd = fd;
142 host_dev->filename = fname;
143
144 return blk_prepare_device(dev);
145err_file: 146err_file:
146 os_close(fd); 147 os_close(fd);
147err: 148err:
@@ -226,7 +227,7 @@ U_BOOT_DRIVER(sandbox_host_blk) = {
226 .name = "sandbox_host_blk", 227 .name = "sandbox_host_blk",
227 .id = UCLASS_BLK, 228 .id = UCLASS_BLK,
228 .ops = &sandbox_host_blk_ops, 229 .ops = &sandbox_host_blk_ops,
229 .priv_auto_alloc_size = sizeof(struct host_block_dev), 230 .platdata_auto_alloc_size = sizeof(struct host_block_dev),
230}; 231};
231#else 232#else
232U_BOOT_LEGACY_BLK(sandbox_host) = { 233U_BOOT_LEGACY_BLK(sandbox_host) = {
diff --git a/drivers/clk/altera/clk-arria10.c b/drivers/clk/altera/clk-arria10.c
index 78102c760d..612a1718dc 100644
--- a/drivers/clk/altera/clk-arria10.c
+++ b/drivers/clk/altera/clk-arria10.c
@@ -352,7 +352,6 @@ static const struct udevice_id socfpga_a10_clk_match[] = {
352U_BOOT_DRIVER(socfpga_a10_clk) = { 352U_BOOT_DRIVER(socfpga_a10_clk) = {
353 .name = "clk-a10", 353 .name = "clk-a10",
354 .id = UCLASS_CLK, 354 .id = UCLASS_CLK,
355 .flags = DM_FLAG_PRE_RELOC,
356 .of_match = socfpga_a10_clk_match, 355 .of_match = socfpga_a10_clk_match,
357 .ops = &socfpga_a10_clk_ops, 356 .ops = &socfpga_a10_clk_ops,
358 .bind = socfpga_a10_clk_bind, 357 .bind = socfpga_a10_clk_bind,
diff --git a/drivers/clk/clk_pic32.c b/drivers/clk/clk_pic32.c
index fdf95a12da..b3ac0d5a92 100644
--- a/drivers/clk/clk_pic32.c
+++ b/drivers/clk/clk_pic32.c
@@ -418,7 +418,6 @@ U_BOOT_DRIVER(pic32_clk) = {
418 .name = "pic32_clk", 418 .name = "pic32_clk",
419 .id = UCLASS_CLK, 419 .id = UCLASS_CLK,
420 .of_match = pic32_clk_ids, 420 .of_match = pic32_clk_ids,
421 .flags = DM_FLAG_PRE_RELOC,
422 .ops = &pic32_pic32_clk_ops, 421 .ops = &pic32_pic32_clk_ops,
423 .probe = pic32_clk_probe, 422 .probe = pic32_clk_probe,
424 .priv_auto_alloc_size = sizeof(struct pic32_clk_priv), 423 .priv_auto_alloc_size = sizeof(struct pic32_clk_priv),
diff --git a/drivers/clk/clk_zynq.c b/drivers/clk/clk_zynq.c
index d647e0a01e..482f0937cb 100644
--- a/drivers/clk/clk_zynq.c
+++ b/drivers/clk/clk_zynq.c
@@ -480,7 +480,6 @@ U_BOOT_DRIVER(zynq_clk) = {
480 .name = "zynq_clk", 480 .name = "zynq_clk",
481 .id = UCLASS_CLK, 481 .id = UCLASS_CLK,
482 .of_match = zynq_clk_ids, 482 .of_match = zynq_clk_ids,
483 .flags = DM_FLAG_PRE_RELOC,
484 .ops = &zynq_clk_ops, 483 .ops = &zynq_clk_ops,
485 .priv_auto_alloc_size = sizeof(struct zynq_clk_priv), 484 .priv_auto_alloc_size = sizeof(struct zynq_clk_priv),
486 .probe = zynq_clk_probe, 485 .probe = zynq_clk_probe,
diff --git a/drivers/clk/exynos/clk-exynos7420.c b/drivers/clk/exynos/clk-exynos7420.c
index 763567b17c..aa86c7ca44 100644
--- a/drivers/clk/exynos/clk-exynos7420.c
+++ b/drivers/clk/exynos/clk-exynos7420.c
@@ -201,7 +201,6 @@ U_BOOT_DRIVER(exynos7420_clk_topc) = {
201 .probe = exynos7420_clk_topc_probe, 201 .probe = exynos7420_clk_topc_probe,
202 .priv_auto_alloc_size = sizeof(struct exynos7420_clk_topc_priv), 202 .priv_auto_alloc_size = sizeof(struct exynos7420_clk_topc_priv),
203 .ops = &exynos7420_clk_topc_ops, 203 .ops = &exynos7420_clk_topc_ops,
204 .flags = DM_FLAG_PRE_RELOC,
205}; 204};
206 205
207static const struct udevice_id exynos7420_clk_top0_compat[] = { 206static const struct udevice_id exynos7420_clk_top0_compat[] = {
@@ -216,7 +215,6 @@ U_BOOT_DRIVER(exynos7420_clk_top0) = {
216 .probe = exynos7420_clk_top0_probe, 215 .probe = exynos7420_clk_top0_probe,
217 .priv_auto_alloc_size = sizeof(struct exynos7420_clk_top0_priv), 216 .priv_auto_alloc_size = sizeof(struct exynos7420_clk_top0_priv),
218 .ops = &exynos7420_clk_top0_ops, 217 .ops = &exynos7420_clk_top0_ops,
219 .flags = DM_FLAG_PRE_RELOC,
220}; 218};
221 219
222static const struct udevice_id exynos7420_clk_peric1_compat[] = { 220static const struct udevice_id exynos7420_clk_peric1_compat[] = {
@@ -229,5 +227,4 @@ U_BOOT_DRIVER(exynos7420_clk_peric1) = {
229 .id = UCLASS_CLK, 227 .id = UCLASS_CLK,
230 .of_match = exynos7420_clk_peric1_compat, 228 .of_match = exynos7420_clk_peric1_compat,
231 .ops = &exynos7420_clk_peric1_ops, 229 .ops = &exynos7420_clk_peric1_ops,
232 .flags = DM_FLAG_PRE_RELOC,
233}; 230};
diff --git a/drivers/clk/owl/clk_s900.c b/drivers/clk/owl/clk_s900.c
index 2b39bb99af..a7c15d2812 100644
--- a/drivers/clk/owl/clk_s900.c
+++ b/drivers/clk/owl/clk_s900.c
@@ -134,5 +134,4 @@ U_BOOT_DRIVER(clk_owl) = {
134 .ops = &owl_clk_ops, 134 .ops = &owl_clk_ops,
135 .priv_auto_alloc_size = sizeof(struct owl_clk_priv), 135 .priv_auto_alloc_size = sizeof(struct owl_clk_priv),
136 .probe = owl_clk_probe, 136 .probe = owl_clk_probe,
137 .flags = DM_FLAG_PRE_RELOC,
138}; 137};
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 5176aa3f86..47a697f3e5 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -834,5 +834,5 @@ int dev_enable_by_path(const char *path)
834 if (ret) 834 if (ret)
835 return ret; 835 return ret;
836 836
837 return lists_bind_fdt(parent, node, NULL); 837 return lists_bind_fdt(parent, node, NULL, false);
838} 838}
diff --git a/drivers/core/dump.c b/drivers/core/dump.c
index d7cdb1475d..9068084404 100644
--- a/drivers/core/dump.c
+++ b/drivers/core/dump.c
@@ -89,7 +89,7 @@ void dm_dump_uclass(void)
89 printf("uclass %d: %s\n", id, uc->uc_drv->name); 89 printf("uclass %d: %s\n", id, uc->uc_drv->name);
90 if (list_empty(&uc->dev_head)) 90 if (list_empty(&uc->dev_head))
91 continue; 91 continue;
92 list_for_each_entry(dev, &uc->dev_head, uclass_node) { 92 uclass_foreach_dev(dev, uc) {
93 dm_display_line(dev, i); 93 dm_display_line(dev, i);
94 i++; 94 i++;
95 } 95 }
diff --git a/drivers/core/lists.c b/drivers/core/lists.c
index a1677269d8..a1f828463e 100644
--- a/drivers/core/lists.c
+++ b/drivers/core/lists.c
@@ -122,7 +122,8 @@ static int driver_check_compatible(const struct udevice_id *of_match,
122 return -ENOENT; 122 return -ENOENT;
123} 123}
124 124
125int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp) 125int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp,
126 bool pre_reloc_only)
126{ 127{
127 struct driver *driver = ll_entry_start(struct driver, driver); 128 struct driver *driver = ll_entry_start(struct driver, driver);
128 const int n_ents = ll_entry_count(struct driver, driver); 129 const int n_ents = ll_entry_count(struct driver, driver);
@@ -171,6 +172,12 @@ int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp)
171 if (entry == driver + n_ents) 172 if (entry == driver + n_ents)
172 continue; 173 continue;
173 174
175 if (pre_reloc_only) {
176 if (!dm_ofnode_pre_reloc(node) &&
177 !(entry->flags & DM_FLAG_PRE_RELOC))
178 return 0;
179 }
180
174 pr_debug(" - found match at '%s'\n", entry->name); 181 pr_debug(" - found match at '%s'\n", entry->name);
175 ret = device_bind_with_driver_data(parent, entry, name, 182 ret = device_bind_with_driver_data(parent, entry, name,
176 id->data, node, &dev); 183 id->data, node, &dev);
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index b7b7ad3a62..d9b5280b2d 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -831,8 +831,10 @@ int ofnode_write_prop(ofnode node, const char *propname, int len,
831 return -ENOMEM; 831 return -ENOMEM;
832 832
833 new->name = strdup(propname); 833 new->name = strdup(propname);
834 if (!new->name) 834 if (!new->name) {
835 free(new);
835 return -ENOMEM; 836 return -ENOMEM;
837 }
836 838
837 new->value = (void *)value; 839 new->value = (void *)value;
838 new->length = len; 840 new->length = len;
diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index 8e5c3bcf61..5ef0f71c8b 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -17,6 +17,12 @@
17 17
18DECLARE_GLOBAL_DATA_PTR; 18DECLARE_GLOBAL_DATA_PTR;
19 19
20/**
21 * regmap_alloc() - Allocate a regmap with a given number of ranges.
22 *
23 * @count: Number of ranges to be allocated for the regmap.
24 * Return: A pointer to the newly allocated regmap, or NULL on error.
25 */
20static struct regmap *regmap_alloc(int count) 26static struct regmap *regmap_alloc(int count)
21{ 27{
22 struct regmap *map; 28 struct regmap *map;
@@ -50,6 +56,58 @@ int regmap_init_mem_platdata(struct udevice *dev, fdt_val_t *reg, int count,
50 return 0; 56 return 0;
51} 57}
52#else 58#else
59/**
60 * init_range() - Initialize a single range of a regmap
61 * @node: Device node that will use the map in question
62 * @range: Pointer to a regmap_range structure that will be initialized
63 * @addr_len: The length of the addr parts of the reg property
64 * @size_len: The length of the size parts of the reg property
65 * @index: The index of the range to initialize
66 *
67 * This function will read the necessary 'reg' information from the device tree
68 * (the 'addr' part, and the 'length' part), and initialize the range in
69 * quesion.
70 *
71 * Return: 0 if OK, -ve on error
72 */
73static int init_range(ofnode node, struct regmap_range *range, int addr_len,
74 int size_len, int index)
75{
76 fdt_size_t sz;
77 struct resource r;
78
79 if (of_live_active()) {
80 int ret;
81
82 ret = of_address_to_resource(ofnode_to_np(node),
83 index, &r);
84 if (ret) {
85 debug("%s: Could not read resource of range %d (ret = %d)\n",
86 ofnode_get_name(node), index, ret);
87 return ret;
88 }
89
90 range->start = r.start;
91 range->size = r.end - r.start + 1;
92 } else {
93 int offset = ofnode_to_offset(node);
94
95 range->start = fdtdec_get_addr_size_fixed(gd->fdt_blob, offset,
96 "reg", index,
97 addr_len, size_len,
98 &sz, true);
99 if (range->start == FDT_ADDR_T_NONE) {
100 debug("%s: Could not read start of range %d\n",
101 ofnode_get_name(node), index);
102 return -EINVAL;
103 }
104
105 range->size = sz;
106 }
107
108 return 0;
109}
110
53int regmap_init_mem(ofnode node, struct regmap **mapp) 111int regmap_init_mem(ofnode node, struct regmap **mapp)
54{ 112{
55 struct regmap_range *range; 113 struct regmap_range *range;
@@ -58,19 +116,41 @@ int regmap_init_mem(ofnode node, struct regmap **mapp)
58 int addr_len, size_len, both_len; 116 int addr_len, size_len, both_len;
59 int len; 117 int len;
60 int index; 118 int index;
61 struct resource r;
62 119
63 addr_len = ofnode_read_simple_addr_cells(ofnode_get_parent(node)); 120 addr_len = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
121 if (addr_len < 0) {
122 debug("%s: Error while reading the addr length (ret = %d)\n",
123 ofnode_get_name(node), addr_len);
124 return addr_len;
125 }
126
64 size_len = ofnode_read_simple_size_cells(ofnode_get_parent(node)); 127 size_len = ofnode_read_simple_size_cells(ofnode_get_parent(node));
128 if (size_len < 0) {
129 debug("%s: Error while reading the size length: (ret = %d)\n",
130 ofnode_get_name(node), size_len);
131 return size_len;
132 }
133
65 both_len = addr_len + size_len; 134 both_len = addr_len + size_len;
135 if (!both_len) {
136 debug("%s: Both addr and size length are zero\n",
137 ofnode_get_name(node));
138 return -EINVAL;
139 }
66 140
67 len = ofnode_read_size(node, "reg"); 141 len = ofnode_read_size(node, "reg");
68 if (len < 0) 142 if (len < 0) {
143 debug("%s: Error while reading reg size (ret = %d)\n",
144 ofnode_get_name(node), len);
69 return len; 145 return len;
146 }
70 len /= sizeof(fdt32_t); 147 len /= sizeof(fdt32_t);
71 count = len / both_len; 148 count = len / both_len;
72 if (!count) 149 if (!count) {
150 debug("%s: Not enough data in reg property\n",
151 ofnode_get_name(node));
73 return -EINVAL; 152 return -EINVAL;
153 }
74 154
75 map = regmap_alloc(count); 155 map = regmap_alloc(count);
76 if (!map) 156 if (!map)
@@ -78,19 +158,21 @@ int regmap_init_mem(ofnode node, struct regmap **mapp)
78 158
79 for (range = map->ranges, index = 0; count > 0; 159 for (range = map->ranges, index = 0; count > 0;
80 count--, range++, index++) { 160 count--, range++, index++) {
81 fdt_size_t sz; 161 int ret = init_range(node, range, addr_len, size_len, index);
82 if (of_live_active()) { 162
83 of_address_to_resource(ofnode_to_np(node), index, &r); 163 if (ret)
84 range->start = r.start; 164 return ret;
85 range->size = r.end - r.start + 1;
86 } else {
87 range->start = fdtdec_get_addr_size_fixed(gd->fdt_blob,
88 ofnode_to_offset(node), "reg", index,
89 addr_len, size_len, &sz, true);
90 range->size = sz;
91 }
92 } 165 }
93 166
167 if (ofnode_read_bool(node, "little-endian"))
168 map->endianness = REGMAP_LITTLE_ENDIAN;
169 else if (ofnode_read_bool(node, "big-endian"))
170 map->endianness = REGMAP_BIG_ENDIAN;
171 else if (ofnode_read_bool(node, "native-endian"))
172 map->endianness = REGMAP_NATIVE_ENDIAN;
173 else /* Default: native endianness */
174 map->endianness = REGMAP_NATIVE_ENDIAN;
175
94 *mapp = map; 176 *mapp = map;
95 177
96 return 0; 178 return 0;
@@ -115,24 +197,218 @@ int regmap_uninit(struct regmap *map)
115 return 0; 197 return 0;
116} 198}
117 199
118int regmap_read(struct regmap *map, uint offset, uint *valp) 200static inline u8 __read_8(u8 *addr, enum regmap_endianness_t endianness)
119{ 201{
120 u32 *ptr = map_physmem(map->ranges[0].start + offset, 4, MAP_NOCACHE); 202 return readb(addr);
203}
121 204
122 *valp = le32_to_cpu(readl(ptr)); 205static inline u16 __read_16(u16 *addr, enum regmap_endianness_t endianness)
206{
207 switch (endianness) {
208 case REGMAP_LITTLE_ENDIAN:
209 return in_le16(addr);
210 case REGMAP_BIG_ENDIAN:
211 return in_be16(addr);
212 case REGMAP_NATIVE_ENDIAN:
213 return readw(addr);
214 }
215
216 return readw(addr);
217}
218
219static inline u32 __read_32(u32 *addr, enum regmap_endianness_t endianness)
220{
221 switch (endianness) {
222 case REGMAP_LITTLE_ENDIAN:
223 return in_le32(addr);
224 case REGMAP_BIG_ENDIAN:
225 return in_be32(addr);
226 case REGMAP_NATIVE_ENDIAN:
227 return readl(addr);
228 }
229
230 return readl(addr);
231}
232
233#if defined(in_le64) && defined(in_be64) && defined(readq)
234static inline u64 __read_64(u64 *addr, enum regmap_endianness_t endianness)
235{
236 switch (endianness) {
237 case REGMAP_LITTLE_ENDIAN:
238 return in_le64(addr);
239 case REGMAP_BIG_ENDIAN:
240 return in_be64(addr);
241 case REGMAP_NATIVE_ENDIAN:
242 return readq(addr);
243 }
244
245 return readq(addr);
246}
247#endif
248
249int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset,
250 void *valp, size_t val_len)
251{
252 struct regmap_range *range;
253 void *ptr;
254
255 if (range_num >= map->range_count) {
256 debug("%s: range index %d larger than range count\n",
257 __func__, range_num);
258 return -ERANGE;
259 }
260 range = &map->ranges[range_num];
261
262 ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE);
263
264 if (offset + val_len > range->size) {
265 debug("%s: offset/size combination invalid\n", __func__);
266 return -ERANGE;
267 }
268
269 switch (val_len) {
270 case REGMAP_SIZE_8:
271 *((u8 *)valp) = __read_8(ptr, map->endianness);
272 break;
273 case REGMAP_SIZE_16:
274 *((u16 *)valp) = __read_16(ptr, map->endianness);
275 break;
276 case REGMAP_SIZE_32:
277 *((u32 *)valp) = __read_32(ptr, map->endianness);
278 break;
279#if defined(in_le64) && defined(in_be64) && defined(readq)
280 case REGMAP_SIZE_64:
281 *((u64 *)valp) = __read_64(ptr, map->endianness);
282 break;
283#endif
284 default:
285 debug("%s: regmap size %zu unknown\n", __func__, val_len);
286 return -EINVAL;
287 }
123 288
124 return 0; 289 return 0;
125} 290}
126 291
127int regmap_write(struct regmap *map, uint offset, uint val) 292int regmap_raw_read(struct regmap *map, uint offset, void *valp, size_t val_len)
128{ 293{
129 u32 *ptr = map_physmem(map->ranges[0].start + offset, 4, MAP_NOCACHE); 294 return regmap_raw_read_range(map, 0, offset, valp, val_len);
295}
130 296
131 writel(cpu_to_le32(val), ptr); 297int regmap_read(struct regmap *map, uint offset, uint *valp)
298{
299 return regmap_raw_read(map, offset, valp, REGMAP_SIZE_32);
300}
301
302static inline void __write_8(u8 *addr, const u8 *val,
303 enum regmap_endianness_t endianness)
304{
305 writeb(*val, addr);
306}
307
308static inline void __write_16(u16 *addr, const u16 *val,
309 enum regmap_endianness_t endianness)
310{
311 switch (endianness) {
312 case REGMAP_NATIVE_ENDIAN:
313 writew(*val, addr);
314 break;
315 case REGMAP_LITTLE_ENDIAN:
316 out_le16(addr, *val);
317 break;
318 case REGMAP_BIG_ENDIAN:
319 out_be16(addr, *val);
320 break;
321 }
322}
323
324static inline void __write_32(u32 *addr, const u32 *val,
325 enum regmap_endianness_t endianness)
326{
327 switch (endianness) {
328 case REGMAP_NATIVE_ENDIAN:
329 writel(*val, addr);
330 break;
331 case REGMAP_LITTLE_ENDIAN:
332 out_le32(addr, *val);
333 break;
334 case REGMAP_BIG_ENDIAN:
335 out_be32(addr, *val);
336 break;
337 }
338}
339
340#if defined(out_le64) && defined(out_be64) && defined(writeq)
341static inline void __write_64(u64 *addr, const u64 *val,
342 enum regmap_endianness_t endianness)
343{
344 switch (endianness) {
345 case REGMAP_NATIVE_ENDIAN:
346 writeq(*val, addr);
347 break;
348 case REGMAP_LITTLE_ENDIAN:
349 out_le64(addr, *val);
350 break;
351 case REGMAP_BIG_ENDIAN:
352 out_be64(addr, *val);
353 break;
354 }
355}
356#endif
357
358int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset,
359 const void *val, size_t val_len)
360{
361 struct regmap_range *range;
362 void *ptr;
363
364 if (range_num >= map->range_count) {
365 debug("%s: range index %d larger than range count\n",
366 __func__, range_num);
367 return -ERANGE;
368 }
369 range = &map->ranges[range_num];
370
371 ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE);
372
373 if (offset + val_len > range->size) {
374 debug("%s: offset/size combination invalid\n", __func__);
375 return -ERANGE;
376 }
377
378 switch (val_len) {
379 case REGMAP_SIZE_8:
380 __write_8(ptr, val, map->endianness);
381 break;
382 case REGMAP_SIZE_16:
383 __write_16(ptr, val, map->endianness);
384 break;
385 case REGMAP_SIZE_32:
386 __write_32(ptr, val, map->endianness);
387 break;
388#if defined(out_le64) && defined(out_be64) && defined(writeq)
389 case REGMAP_SIZE_64:
390 __write_64(ptr, val, map->endianness);
391 break;
392#endif
393 default:
394 debug("%s: regmap size %zu unknown\n", __func__, val_len);
395 return -EINVAL;
396 }
132 397
133 return 0; 398 return 0;
134} 399}
135 400
401int regmap_raw_write(struct regmap *map, uint offset, const void *val,
402 size_t val_len)
403{
404 return regmap_raw_write_range(map, 0, offset, val, val_len);
405}
406
407int regmap_write(struct regmap *map, uint offset, uint val)
408{
409 return regmap_raw_write(map, offset, &val, REGMAP_SIZE_32);
410}
411
136int regmap_update_bits(struct regmap *map, uint offset, uint mask, uint val) 412int regmap_update_bits(struct regmap *map, uint offset, uint mask, uint val)
137{ 413{
138 uint reg; 414 uint reg;
diff --git a/drivers/core/root.c b/drivers/core/root.c
index b54bf5bcdc..4ce55f9cc8 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -222,14 +222,22 @@ static int dm_scan_fdt_live(struct udevice *parent,
222 int ret = 0, err; 222 int ret = 0, err;
223 223
224 for (np = node_parent->child; np; np = np->sibling) { 224 for (np = node_parent->child; np; np = np->sibling) {
225 if (pre_reloc_only && 225 /* "chosen" node isn't a device itself but may contain some: */
226 !of_find_property(np, "u-boot,dm-pre-reloc", NULL)) 226 if (!strcmp(np->name, "chosen")) {
227 pr_debug("parsing subnodes of \"chosen\"\n");
228
229 err = dm_scan_fdt_live(parent, np, pre_reloc_only);
230 if (err && !ret)
231 ret = err;
227 continue; 232 continue;
233 }
234
228 if (!of_device_is_available(np)) { 235 if (!of_device_is_available(np)) {
229 pr_debug(" - ignoring disabled device\n"); 236 pr_debug(" - ignoring disabled device\n");
230 continue; 237 continue;
231 } 238 }
232 err = lists_bind_fdt(parent, np_to_ofnode(np), NULL); 239 err = lists_bind_fdt(parent, np_to_ofnode(np), NULL,
240 pre_reloc_only);
233 if (err && !ret) { 241 if (err && !ret) {
234 ret = err; 242 ret = err;
235 debug("%s: ret=%d\n", np->name, ret); 243 debug("%s: ret=%d\n", np->name, ret);
@@ -282,14 +290,12 @@ static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
282 continue; 290 continue;
283 } 291 }
284 292
285 if (pre_reloc_only &&
286 !dm_fdt_pre_reloc(blob, offset))
287 continue;
288 if (!fdtdec_get_is_enabled(blob, offset)) { 293 if (!fdtdec_get_is_enabled(blob, offset)) {
289 pr_debug(" - ignoring disabled device\n"); 294 pr_debug(" - ignoring disabled device\n");
290 continue; 295 continue;
291 } 296 }
292 err = lists_bind_fdt(parent, offset_to_ofnode(offset), NULL); 297 err = lists_bind_fdt(parent, offset_to_ofnode(offset), NULL,
298 pre_reloc_only);
293 if (err && !ret) { 299 if (err && !ret) {
294 ret = err; 300 ret = err;
295 debug("%s: ret=%d\n", node_name, ret); 301 debug("%s: ret=%d\n", node_name, ret);
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 3113d6a56b..6cfcde8918 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -180,7 +180,7 @@ int dev_get_uclass_index(struct udevice *dev, struct uclass **ucp)
180 if (list_empty(&uc->dev_head)) 180 if (list_empty(&uc->dev_head))
181 return -ENODEV; 181 return -ENODEV;
182 182
183 list_for_each_entry(iter, &uc->dev_head, uclass_node) { 183 uclass_foreach_dev(iter, uc) {
184 if (iter == dev) { 184 if (iter == dev) {
185 if (ucp) 185 if (ucp)
186 *ucp = uc; 186 *ucp = uc;
@@ -205,7 +205,7 @@ int uclass_find_device(enum uclass_id id, int index, struct udevice **devp)
205 if (list_empty(&uc->dev_head)) 205 if (list_empty(&uc->dev_head))
206 return -ENODEV; 206 return -ENODEV;
207 207
208 list_for_each_entry(dev, &uc->dev_head, uclass_node) { 208 uclass_foreach_dev(dev, uc) {
209 if (!index--) { 209 if (!index--) {
210 *devp = dev; 210 *devp = dev;
211 return 0; 211 return 0;
@@ -259,7 +259,7 @@ int uclass_find_device_by_name(enum uclass_id id, const char *name,
259 if (ret) 259 if (ret)
260 return ret; 260 return ret;
261 261
262 list_for_each_entry(dev, &uc->dev_head, uclass_node) { 262 uclass_foreach_dev(dev, uc) {
263 if (!strncmp(dev->name, name, strlen(name))) { 263 if (!strncmp(dev->name, name, strlen(name))) {
264 *devp = dev; 264 *devp = dev;
265 return 0; 265 return 0;
@@ -284,7 +284,7 @@ int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq,
284 if (ret) 284 if (ret)
285 return ret; 285 return ret;
286 286
287 list_for_each_entry(dev, &uc->dev_head, uclass_node) { 287 uclass_foreach_dev(dev, uc) {
288 debug(" - %d %d '%s'\n", dev->req_seq, dev->seq, dev->name); 288 debug(" - %d %d '%s'\n", dev->req_seq, dev->seq, dev->name);
289 if ((find_req_seq ? dev->req_seq : dev->seq) == 289 if ((find_req_seq ? dev->req_seq : dev->seq) ==
290 seq_or_req_seq) { 290 seq_or_req_seq) {
@@ -312,7 +312,7 @@ int uclass_find_device_by_of_offset(enum uclass_id id, int node,
312 if (ret) 312 if (ret)
313 return ret; 313 return ret;
314 314
315 list_for_each_entry(dev, &uc->dev_head, uclass_node) { 315 uclass_foreach_dev(dev, uc) {
316 if (dev_of_offset(dev) == node) { 316 if (dev_of_offset(dev) == node) {
317 *devp = dev; 317 *devp = dev;
318 return 0; 318 return 0;
@@ -337,7 +337,7 @@ int uclass_find_device_by_ofnode(enum uclass_id id, ofnode node,
337 if (ret) 337 if (ret)
338 return ret; 338 return ret;
339 339
340 list_for_each_entry(dev, &uc->dev_head, uclass_node) { 340 uclass_foreach_dev(dev, uc) {
341 log(LOGC_DM, LOGL_DEBUG_CONTENT, " - checking %s\n", 341 log(LOGC_DM, LOGL_DEBUG_CONTENT, " - checking %s\n",
342 dev->name); 342 dev->name);
343 if (ofnode_equal(dev_ofnode(dev), node)) { 343 if (ofnode_equal(dev_ofnode(dev), node)) {
@@ -372,7 +372,7 @@ static int uclass_find_device_by_phandle(enum uclass_id id,
372 if (ret) 372 if (ret)
373 return ret; 373 return ret;
374 374
375 list_for_each_entry(dev, &uc->dev_head, uclass_node) { 375 uclass_foreach_dev(dev, uc) {
376 uint phandle; 376 uint phandle;
377 377
378 phandle = dev_read_phandle(dev); 378 phandle = dev_read_phandle(dev);
@@ -399,7 +399,7 @@ int uclass_get_device_by_driver(enum uclass_id id,
399 if (ret) 399 if (ret)
400 return ret; 400 return ret;
401 401
402 list_for_each_entry(dev, &uc->dev_head, uclass_node) { 402 uclass_foreach_dev(dev, uc) {
403 if (dev->driver == find_drv) 403 if (dev->driver == find_drv)
404 return uclass_get_device_tail(dev, 0, devp); 404 return uclass_get_device_tail(dev, 0, devp);
405 } 405 }
@@ -499,7 +499,7 @@ int uclass_get_device_by_phandle_id(enum uclass_id id, uint phandle_id,
499 if (ret) 499 if (ret)
500 return ret; 500 return ret;
501 501
502 list_for_each_entry(dev, &uc->dev_head, uclass_node) { 502 uclass_foreach_dev(dev, uc) {
503 uint phandle; 503 uint phandle;
504 504
505 phandle = dev_read_phandle(dev); 505 phandle = dev_read_phandle(dev);
@@ -687,8 +687,19 @@ int uclass_pre_probe_device(struct udevice *dev)
687 687
688int uclass_post_probe_device(struct udevice *dev) 688int uclass_post_probe_device(struct udevice *dev)
689{ 689{
690 struct uclass_driver *uc_drv = dev->uclass->uc_drv; 690 struct uclass_driver *uc_drv;
691 int ret;
692
693 if (dev->parent) {
694 uc_drv = dev->parent->uclass->uc_drv;
695 if (uc_drv->child_post_probe) {
696 ret = uc_drv->child_post_probe(dev);
697 if (ret)
698 return ret;
699 }
700 }
691 701
702 uc_drv = dev->uclass->uc_drv;
692 if (uc_drv->post_probe) 703 if (uc_drv->post_probe)
693 return uc_drv->post_probe(dev); 704 return uc_drv->post_probe(dev);
694 705
diff --git a/drivers/core/util.c b/drivers/core/util.c
index 451d4766d0..27a6848703 100644
--- a/drivers/core/util.c
+++ b/drivers/core/util.c
@@ -4,6 +4,7 @@
4 */ 4 */
5 5
6#include <common.h> 6#include <common.h>
7#include <dm/ofnode.h>
7#include <dm/util.h> 8#include <dm/util.h>
8#include <linux/libfdt.h> 9#include <linux/libfdt.h>
9#include <vsprintf.h> 10#include <vsprintf.h>
@@ -53,3 +54,27 @@ bool dm_fdt_pre_reloc(const void *blob, int offset)
53 54
54 return false; 55 return false;
55} 56}
57
58bool dm_ofnode_pre_reloc(ofnode node)
59{
60 if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
61 return true;
62
63#ifdef CONFIG_TPL_BUILD
64 if (ofnode_read_bool(node, "u-boot,dm-tpl"))
65 return true;
66#elif defined(CONFIG_SPL_BUILD)
67 if (ofnode_read_bool(node, "u-boot,dm-spl"))
68 return true;
69#else
70 /*
71 * In regular builds individual spl and tpl handling both
72 * count as handled pre-relocation for later second init.
73 */
74 if (ofnode_read_bool(node, "u-boot,dm-spl") ||
75 ofnode_read_bool(node, "u-boot,dm-tpl"))
76 return true;
77#endif
78
79 return false;
80}
diff --git a/drivers/cpu/mpc83xx_cpu.c b/drivers/cpu/mpc83xx_cpu.c
index 31717afaec..7bc86bf9b2 100644
--- a/drivers/cpu/mpc83xx_cpu.c
+++ b/drivers/cpu/mpc83xx_cpu.c
@@ -262,7 +262,7 @@ static int mpc83xx_cpu_get_desc(struct udevice *dev, char *buf, int size)
262 determine_cpu_data(dev); 262 determine_cpu_data(dev);
263 263
264 snprintf(buf, size, 264 snprintf(buf, size,
265 "CPU: %s, MPC%s%s%s, Rev: %d.%d at %s MHz, CSB: %s MHz\n", 265 "%s, MPC%s%s%s, Rev: %d.%d at %s MHz, CSB: %s MHz",
266 e300_names[priv->e300_type], 266 e300_names[priv->e300_type],
267 cpu_type_names[priv->type], 267 cpu_type_names[priv->type],
268 priv->is_e_processor ? "E" : "", 268 priv->is_e_processor ? "E" : "",
diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c
index 555eba2662..0031415d03 100644
--- a/drivers/gpio/omap_gpio.c
+++ b/drivers/gpio/omap_gpio.c
@@ -372,7 +372,9 @@ U_BOOT_DRIVER(gpio_omap) = {
372 .ops = &gpio_omap_ops, 372 .ops = &gpio_omap_ops,
373 .probe = omap_gpio_probe, 373 .probe = omap_gpio_probe,
374 .priv_auto_alloc_size = sizeof(struct gpio_bank), 374 .priv_auto_alloc_size = sizeof(struct gpio_bank),
375#if !CONFIG_IS_ENABLED(OF_CONTROL)
375 .flags = DM_FLAG_PRE_RELOC, 376 .flags = DM_FLAG_PRE_RELOC,
377#endif
376}; 378};
377 379
378#endif /* CONFIG_DM_GPIO */ 380#endif /* CONFIG_DM_GPIO */
diff --git a/drivers/gpio/stm32f7_gpio.c b/drivers/gpio/stm32f7_gpio.c
index 4c0786fff8..b903dc46b3 100644
--- a/drivers/gpio/stm32f7_gpio.c
+++ b/drivers/gpio/stm32f7_gpio.c
@@ -123,6 +123,6 @@ U_BOOT_DRIVER(gpio_stm32) = {
123 .of_match = stm32_gpio_ids, 123 .of_match = stm32_gpio_ids,
124 .probe = gpio_stm32_probe, 124 .probe = gpio_stm32_probe,
125 .ops = &gpio_stm32_ops, 125 .ops = &gpio_stm32_ops,
126 .flags = DM_FLAG_PRE_RELOC | DM_UC_FLAG_SEQ_ALIAS, 126 .flags = DM_UC_FLAG_SEQ_ALIAS,
127 .priv_auto_alloc_size = sizeof(struct stm32_gpio_priv), 127 .priv_auto_alloc_size = sizeof(struct stm32_gpio_priv),
128}; 128};
diff --git a/drivers/gpio/tegra186_gpio.c b/drivers/gpio/tegra186_gpio.c
index 1f0e8d51da..6626b5415a 100644
--- a/drivers/gpio/tegra186_gpio.c
+++ b/drivers/gpio/tegra186_gpio.c
@@ -281,5 +281,4 @@ U_BOOT_DRIVER(tegra186_gpio) = {
281 .bind = tegra186_gpio_bind, 281 .bind = tegra186_gpio_bind,
282 .probe = tegra186_gpio_probe, 282 .probe = tegra186_gpio_probe,
283 .ops = &tegra186_gpio_ops, 283 .ops = &tegra186_gpio_ops,
284 .flags = DM_FLAG_PRE_RELOC,
285}; 284};
diff --git a/drivers/gpio/tegra_gpio.c b/drivers/gpio/tegra_gpio.c
index 302efddc27..a730f5c4fe 100644
--- a/drivers/gpio/tegra_gpio.c
+++ b/drivers/gpio/tegra_gpio.c
@@ -378,5 +378,4 @@ U_BOOT_DRIVER(gpio_tegra) = {
378 .probe = gpio_tegra_probe, 378 .probe = gpio_tegra_probe,
379 .priv_auto_alloc_size = sizeof(struct tegra_port_info), 379 .priv_auto_alloc_size = sizeof(struct tegra_port_info),
380 .ops = &gpio_tegra_ops, 380 .ops = &gpio_tegra_ops,
381 .flags = DM_FLAG_PRE_RELOC,
382}; 381};
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index 54bf35e552..51f923752c 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -925,7 +925,9 @@ U_BOOT_DRIVER(i2c_omap) = {
925 .probe = omap_i2c_probe, 925 .probe = omap_i2c_probe,
926 .priv_auto_alloc_size = sizeof(struct omap_i2c), 926 .priv_auto_alloc_size = sizeof(struct omap_i2c),
927 .ops = &omap_i2c_ops, 927 .ops = &omap_i2c_ops,
928#if !CONFIG_IS_ENABLED(OF_CONTROL)
928 .flags = DM_FLAG_PRE_RELOC, 929 .flags = DM_FLAG_PRE_RELOC,
930#endif
929}; 931};
930 932
931#endif /* CONFIG_DM_I2C */ 933#endif /* CONFIG_DM_I2C */
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index c5697011f2..48febc47d2 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -312,4 +312,21 @@ config FS_LOADER
312 The consumer driver would then use this loader to program whatever, 312 The consumer driver would then use this loader to program whatever,
313 ie. the FPGA device. 313 ie. the FPGA device.
314 314
315config GDSYS_SOC
316 bool "Enable gdsys SOC driver"
317 depends on MISC
318 help
319 Support for gdsys IHS SOC, a simple bus associated with each gdsys
320 IHS (Integrated Hardware Systems) FPGA, which holds all devices whose
321 register maps are contained within the FPGA's register map.
322
323config IHS_FPGA
324 bool "Enable IHS FPGA driver"
325 depends on MISC
326 help
327 Support IHS (Integrated Hardware Systems) FPGA, the main FPGAs on
328 gdsys devices, which supply the majority of the functionality offered
329 by the devices. This driver supports both CON and CPU variants of the
330 devices, depending on the device tree entry.
331
315endmenu 332endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 759d2c791b..302d441592 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -4,11 +4,6 @@
4# Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 5
6obj-$(CONFIG_MISC) += misc-uclass.o 6obj-$(CONFIG_MISC) += misc-uclass.o
7obj-$(CONFIG_ALI152X) += ali512x.o
8obj-$(CONFIG_ALTERA_SYSID) += altera_sysid.o
9obj-$(CONFIG_ATSHA204A) += atsha204a-i2c.o
10obj-$(CONFIG_DS4510) += ds4510.o
11obj-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o
12ifndef CONFIG_SPL_BUILD 7ifndef CONFIG_SPL_BUILD
13obj-$(CONFIG_CROS_EC) += cros_ec.o 8obj-$(CONFIG_CROS_EC) += cros_ec.o
14obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpc.o 9obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpc.o
@@ -16,46 +11,54 @@ obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
16obj-$(CONFIG_CROS_EC_SANDBOX) += cros_ec_sandbox.o 11obj-$(CONFIG_CROS_EC_SANDBOX) += cros_ec_sandbox.o
17obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o 12obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o
18endif 13endif
19obj-$(CONFIG_FSL_IIM) += fsl_iim.o 14
20obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o
21obj-$(CONFIG_$(SPL_)I2C_EEPROM) += i2c_eeprom.o
22obj-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o
23obj-$(CONFIG_IMX8) += imx8/
24obj-$(CONFIG_MXC_OCOTP) += mxc_ocotp.o
25obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o
26obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o
27obj-$(CONFIG_NS87308) += ns87308.o
28obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
29ifdef CONFIG_DM_I2C 15ifdef CONFIG_DM_I2C
30ifndef CONFIG_SPL_BUILD 16ifndef CONFIG_SPL_BUILD
31obj-$(CONFIG_SANDBOX) += i2c_eeprom_emul.o 17obj-$(CONFIG_SANDBOX) += i2c_eeprom_emul.o
32endif 18endif
33endif 19endif
34obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o
35obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o
36obj-$(CONFIG_LED_STATUS) += status_led.o
37obj-$(CONFIG_SANDBOX) += swap_case.o
38ifdef CONFIG_SPL_OF_PLATDATA 20ifdef CONFIG_SPL_OF_PLATDATA
39ifdef CONFIG_SPL_BUILD 21ifdef CONFIG_SPL_BUILD
40obj-$(CONFIG_SANDBOX) += spltest_sandbox.o 22obj-$(CONFIG_SANDBOX) += spltest_sandbox.o
41endif 23endif
42endif 24endif
43obj-$(CONFIG_SANDBOX) += syscon_sandbox.o misc_sandbox.o 25obj-$(CONFIG_ALI152X) += ali512x.o
44obj-$(CONFIG_TEGRA_CAR) += tegra_car.o 26obj-$(CONFIG_ALTERA_SYSID) += altera_sysid.o
45obj-$(CONFIG_TEGRA186_BPMP) += tegra186_bpmp.o 27obj-$(CONFIG_ATSHA204A) += atsha204a-i2c.o
46obj-$(CONFIG_TWL4030_LED) += twl4030_led.o 28obj-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o
29obj-$(CONFIG_DS4510) += ds4510.o
30obj-$(CONFIG_FSL_DEVICE_DISABLE) += fsl_devdis.o
47obj-$(CONFIG_FSL_IFC) += fsl_ifc.o 31obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
32obj-$(CONFIG_FSL_IIM) += fsl_iim.o
33obj-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o
48obj-$(CONFIG_FSL_SEC_MON) += fsl_sec_mon.o 34obj-$(CONFIG_FSL_SEC_MON) += fsl_sec_mon.o
35obj-$(CONFIG_FS_LOADER) += fs_loader.o
36obj-$(CONFIG_GDSYS_IOEP) += gdsys_ioep.o
37obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o
38obj-$(CONFIG_GDSYS_SOC) += gdsys_soc.o
39obj-$(CONFIG_$(SPL_)I2C_EEPROM) += i2c_eeprom.o
40obj-$(CONFIG_IHS_FPGA) += ihs_fpga.o
41obj-$(CONFIG_IMX8) += imx8/
42obj-$(CONFIG_LED_STATUS) += status_led.o
43obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o
44obj-$(CONFIG_MPC83XX_SERDES) += mpc83xx_serdes.o
45obj-$(CONFIG_MXC_OCOTP) += mxc_ocotp.o
46obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o
47obj-$(CONFIG_NS87308) += ns87308.o
48obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o
49obj-$(CONFIG_PCA9551_LED) += pca9551_led.o 49obj-$(CONFIG_PCA9551_LED) += pca9551_led.o
50obj-$(CONFIG_FSL_DEVICE_DISABLE) += fsl_devdis.o 50obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
51obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o
52obj-$(CONFIG_QFW) += qfw.o 51obj-$(CONFIG_QFW) += qfw.o
53obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o 52obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o
54obj-$(CONFIG_STM32_RCC) += stm32_rcc.o 53obj-$(CONFIG_SANDBOX) += swap_case.o
54obj-$(CONFIG_SANDBOX) += syscon_sandbox.o misc_sandbox.o
55obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o
56obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o
55obj-$(CONFIG_STM32MP_FUSE) += stm32mp_fuse.o 57obj-$(CONFIG_STM32MP_FUSE) += stm32mp_fuse.o
58obj-$(CONFIG_STM32_RCC) += stm32_rcc.o
56obj-$(CONFIG_SYS_DPAA_QBMAN) += fsl_portals.o 59obj-$(CONFIG_SYS_DPAA_QBMAN) += fsl_portals.o
57obj-$(CONFIG_GDSYS_IOEP) += gdsys_ioep.o 60obj-$(CONFIG_TEGRA186_BPMP) += tegra186_bpmp.o
58obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o 61obj-$(CONFIG_TEGRA_CAR) += tegra_car.o
62obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
59obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress_config.o 63obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress_config.o
60obj-$(CONFIG_MPC83XX_SERDES) += mpc83xx_serdes.o 64obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o
61obj-$(CONFIG_FS_LOADER) += fs_loader.o
diff --git a/drivers/misc/gdsys_soc.c b/drivers/misc/gdsys_soc.c
new file mode 100644
index 0000000000..94a21e08af
--- /dev/null
+++ b/drivers/misc/gdsys_soc.c
@@ -0,0 +1,74 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2017
4 * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
5 */
6
7#include <common.h>
8#include <dm.h>
9#include <dm/lists.h>
10
11#include "gdsys_soc.h"
12
13/**
14 * struct gdsys_soc_priv - Private data for gdsys soc bus
15 * @fpga: The gdsys IHS FPGA this bus is associated with
16 */
17struct gdsys_soc_priv {
18 struct udevice *fpga;
19};
20
21static const struct udevice_id gdsys_soc_ids[] = {
22 { .compatible = "gdsys,soc" },
23 { /* sentinel */ }
24};
25
26int gdsys_soc_get_fpga(struct udevice *child, struct udevice **fpga)
27{
28 struct gdsys_soc_priv *bus_priv;
29
30 if (!child->parent) {
31 debug("%s: Invalid parent\n", child->name);
32 return -EINVAL;
33 }
34
35 if (!device_is_compatible(child->parent, "gdsys,soc")) {
36 debug("%s: Not child of a gdsys soc\n", child->name);
37 return -EINVAL;
38 }
39
40 bus_priv = dev_get_priv(child->parent);
41
42 *fpga = bus_priv->fpga;
43
44 return 0;
45}
46
47static int gdsys_soc_probe(struct udevice *dev)
48{
49 struct gdsys_soc_priv *priv = dev_get_priv(dev);
50 struct udevice *fpga;
51 int res = uclass_get_device_by_phandle(UCLASS_MISC, dev, "fpga",
52 &fpga);
53 if (res == -ENOENT) {
54 debug("%s: Could not find 'fpga' phandle\n", dev->name);
55 return -EINVAL;
56 }
57
58 if (res == -ENODEV) {
59 debug("%s: Could not get FPGA device\n", dev->name);
60 return -EINVAL;
61 }
62
63 priv->fpga = fpga;
64
65 return 0;
66}
67
68U_BOOT_DRIVER(gdsys_soc_bus) = {
69 .name = "gdsys_soc_bus",
70 .id = UCLASS_SIMPLE_BUS,
71 .of_match = gdsys_soc_ids,
72 .probe = gdsys_soc_probe,
73 .priv_auto_alloc_size = sizeof(struct gdsys_soc_priv),
74};
diff --git a/drivers/misc/gdsys_soc.h b/drivers/misc/gdsys_soc.h
new file mode 100644
index 0000000000..088d3b6523
--- /dev/null
+++ b/drivers/misc/gdsys_soc.h
@@ -0,0 +1,23 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * (C) Copyright 2017
4 * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
5 */
6
7#ifndef _GDSYS_SOC_H_
8#define _GDSYS_SOC_H_
9
10/**
11 * gdsys_soc_get_fpga() - Retrieve pointer to parent bus' FPGA device
12 * @child: The child device on the FPGA bus needing access to the FPGA.
13 * @fpga: Pointer to the retrieved FPGA device.
14 *
15 * To access their register maps, devices on gdsys soc buses usually have
16 * facilitate the accessor function of the IHS FPGA their parent bus is
17 * attached to. To access the FPGA device from within the bus' children, this
18 * function returns a pointer to it.
19 *
20 * Return: 0 on success, -ve on failure
21 */
22int gdsys_soc_get_fpga(struct udevice *child, struct udevice **fpga);
23#endif /* _GDSYS_SOC_H_ */
diff --git a/drivers/misc/ihs_fpga.c b/drivers/misc/ihs_fpga.c
new file mode 100644
index 0000000000..f9e4b27a27
--- /dev/null
+++ b/drivers/misc/ihs_fpga.c
@@ -0,0 +1,867 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2017
4 * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
5 *
6 * based on the ioep-fpga driver, which is
7 *
8 * (C) Copyright 2014
9 * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de
10 */
11
12#include <common.h>
13#include <dm.h>
14#include <regmap.h>
15#include <asm/gpio.h>
16
17#include "ihs_fpga.h"
18
19/**
20 * struct ihs_fpga_priv - Private data structure for IHS FPGA driver
21 * @map: Register map for the FPGA's own register space
22 * @reset_gpio: GPIO to start FPGA reconfiguration
23 * @done_gpio: GPOI to read the 'ready' status of the FPGA
24 */
25struct ihs_fpga_priv {
26 struct regmap *map;
27 struct gpio_desc reset_gpio;
28 struct gpio_desc done_gpio;
29};
30
31/* Test pattern for reflection test */
32const u16 REFLECTION_TESTPATTERN = 0xdead;
33/* Delay (in ms) for each round in the reflection test */
34const uint REFLECTION_TEST_DELAY = 100;
35/* Maximum number of rounds in the reflection test */
36const uint REFLECTION_TEST_ROUNDS = 5;
37/* Delay (in ms) for each round waiting for the FPGA's done GPIO */
38const uint FPGA_DONE_WAIT_DELAY = 100;
39/* Maximum number of rounds for waiting for the FPGA's done GPIO */
40const uint FPGA_DONE_WAIT_ROUND = 5;
41
42/**
43 * enum pcb_video_type - Video type of the PCB
44 * @PCB_DVI_SL: Video type is DVI single-link
45 * @PCB_DP_165MPIX: Video type is DisplayPort (165Mpix)
46 * @PCB_DP_300MPIX: Video type is DisplayPort (300Mpix)
47 * @PCB_HDMI: Video type is HDMI
48 * @PCB_DP_1_2: Video type is DisplayPort 1.2
49 * @PCB_HDMI_2_0: Video type is HDMI 2.0
50 */
51enum pcb_video_type {
52 PCB_DVI_SL,
53 PCB_DP_165MPIX,
54 PCB_DP_300MPIX,
55 PCB_HDMI,
56 PCB_DP_1_2,
57 PCB_HDMI_2_0,
58};
59
60/**
61 * enum pcb_transmission_type - Transmission type of the PCB
62 * @PCB_CAT_1G: Transmission type is 1G Ethernet
63 * @PCB_FIBER_3G: Transmission type is 3G Fiber
64 * @PCB_CAT_10G: Transmission type is 10G Ethernet
65 * @PCB_FIBER_10G: Transmission type is 10G Fiber
66 */
67enum pcb_transmission_type {
68 PCB_CAT_1G,
69 PCB_FIBER_3G,
70 PCB_CAT_10G,
71 PCB_FIBER_10G,
72};
73
74/**
75 * enum carrier_speed - Speed of the FPGA's carrier
76 * @CARRIER_SPEED_1G: The carrier speed is 1G
77 * @CARRIER_SPEED_2_5G: The carrier speed is 2.5G
78 * @CARRIER_SPEED_3G: The carrier speed is 3G
79 * @CARRIER_SPEED_10G: The carrier speed is 10G
80 */
81enum carrier_speed {
82 CARRIER_SPEED_1G,
83 CARRIER_SPEED_3G,
84 CARRIER_SPEED_2_5G = CARRIER_SPEED_3G,
85 CARRIER_SPEED_10G,
86};
87
88/**
89 * enum ram_config - FPGA's RAM configuration
90 * @RAM_DDR2_32BIT_295MBPS: DDR2 32 bit at 295Mb/s
91 * @RAM_DDR3_32BIT_590MBPS: DDR3 32 bit at 590Mb/s
92 * @RAM_DDR3_48BIT_590MBPS: DDR3 48 bit at 590Mb/s
93 * @RAM_DDR3_64BIT_1800MBPS: DDR3 64 bit at 1800Mb/s
94 * @RAM_DDR3_48BIT_1800MBPS: DDR3 48 bit at 1800Mb/s
95 */
96enum ram_config {
97 RAM_DDR2_32BIT_295MBPS,
98 RAM_DDR3_32BIT_590MBPS,
99 RAM_DDR3_48BIT_590MBPS,
100 RAM_DDR3_64BIT_1800MBPS,
101 RAM_DDR3_48BIT_1800MBPS,
102};
103
104/**
105 * enum sysclock - Speed of the FPGA's system clock
106 * @SYSCLK_147456: System clock is 147.456 MHz
107 */
108enum sysclock {
109 SYSCLK_147456,
110};
111
112/**
113 * struct fpga_versions - Data read from the versions register
114 * @video_channel: Is the FPGA for a video channel (true) or main
115 * channel (false) device?
116 * @con_side: Is the FPGA for a CON (true) or a CPU (false) device?
117 * @pcb_video_type: Defines for whch video type the FPGA is configured
118 * @pcb_transmission_type: Defines for which transmission type the FPGA is
119 * configured
120 * @hw_version: Hardware version of the FPGA
121 */
122struct fpga_versions {
123 bool video_channel;
124 bool con_side;
125 enum pcb_video_type pcb_video_type;
126 enum pcb_transmission_type pcb_transmission_type;
127 unsigned int hw_version;
128};
129
130/**
131 * struct fpga_features - Data read from the features register
132 * @video_channels: Number of video channels supported
133 * @carriers: Number of carrier channels supported
134 * @carrier_speed: Speed of carriers
135 * @ram_config: RAM configuration of FPGA
136 * @sysclock: System clock speed of FPGA
137 * @pcm_tx: Support for PCM transmission
138 * @pcm_rx: Support for PCM reception
139 * @spdif_tx: Support for SPDIF audio transmission
140 * @spdif_rx: Support for SPDIF audio reception
141 * @usb2: Support for transparent USB2.0
142 * @rs232: Support for bidirectional RS232
143 * @compression_type1: Support for compression type 1
144 * @compression_type2: Support for compression type 2
145 * @compression_type3: Support for compression type 3
146 * @interlace: Support for interlace image formats
147 * @osd: Support for a OSD
148 * @compression_pipes: Number of compression pipes supported
149 */
150struct fpga_features {
151 u8 video_channels;
152 u8 carriers;
153 enum carrier_speed carrier_speed;
154 enum ram_config ram_config;
155 enum sysclock sysclock;
156 bool pcm_tx;
157 bool pcm_rx;
158 bool spdif_tx;
159 bool spdif_rx;
160 bool usb2;
161 bool rs232;
162 bool compression_type1;
163 bool compression_type2;
164 bool compression_type3;
165 bool interlace;
166 bool osd;
167 bool compression_pipes;
168};
169
170#ifdef CONFIG_SYS_FPGA_FLAVOR_GAZERBEAM
171
172/**
173 * get_versions() - Fill structure with info from version register.
174 * @dev: FPGA device to be queried for information
175 * @versions: Pointer to the structure to fill with information from the
176 * versions register
177 * Return: 0
178 */
179static int get_versions(struct udevice *dev, struct fpga_versions *versions)
180{
181 struct ihs_fpga_priv *priv = dev_get_priv(dev);
182 enum {
183 VERSIONS_FPGA_VIDEO_CHANNEL = BIT(12),
184 VERSIONS_FPGA_CON_SIDE = BIT(13),
185 VERSIONS_FPGA_SC = BIT(14),
186 VERSIONS_PCB_CON = BIT(9),
187 VERSIONS_PCB_SC = BIT(8),
188 VERSIONS_PCB_VIDEO_MASK = 0x3 << 6,
189 VERSIONS_PCB_VIDEO_DP_1_2 = 0x0 << 6,
190 VERSIONS_PCB_VIDEO_HDMI_2_0 = 0x1 << 6,
191 VERSIONS_PCB_TRANSMISSION_MASK = 0x3 << 4,
192 VERSIONS_PCB_TRANSMISSION_FIBER_10G = 0x0 << 4,
193 VERSIONS_PCB_TRANSMISSION_CAT_10G = 0x1 << 4,
194 VERSIONS_PCB_TRANSMISSION_FIBER_3G = 0x2 << 4,
195 VERSIONS_PCB_TRANSMISSION_CAT_1G = 0x3 << 4,
196 VERSIONS_HW_VER_MASK = 0xf << 0,
197 };
198 u16 raw_versions;
199
200 memset(versions, 0, sizeof(struct fpga_versions));
201
202 ihs_fpga_get(priv->map, versions, &raw_versions);
203
204 versions->video_channel = raw_versions & VERSIONS_FPGA_VIDEO_CHANNEL;
205 versions->con_side = raw_versions & VERSIONS_FPGA_CON_SIDE;
206
207 switch (raw_versions & VERSIONS_PCB_VIDEO_MASK) {
208 case VERSIONS_PCB_VIDEO_DP_1_2:
209 versions->pcb_video_type = PCB_DP_1_2;
210 break;
211
212 case VERSIONS_PCB_VIDEO_HDMI_2_0:
213 versions->pcb_video_type = PCB_HDMI_2_0;
214 break;
215 }
216
217 switch (raw_versions & VERSIONS_PCB_TRANSMISSION_MASK) {
218 case VERSIONS_PCB_TRANSMISSION_FIBER_10G:
219 versions->pcb_transmission_type = PCB_FIBER_10G;
220 break;
221
222 case VERSIONS_PCB_TRANSMISSION_CAT_10G:
223 versions->pcb_transmission_type = PCB_CAT_10G;
224 break;
225
226 case VERSIONS_PCB_TRANSMISSION_FIBER_3G:
227 versions->pcb_transmission_type = PCB_FIBER_3G;
228 break;
229
230 case VERSIONS_PCB_TRANSMISSION_CAT_1G:
231 versions->pcb_transmission_type = PCB_CAT_1G;
232 break;
233 }
234
235 versions->hw_version = raw_versions & VERSIONS_HW_VER_MASK;
236
237 return 0;
238}
239
240/**
241 * get_features() - Fill structure with info from features register.
242 * @dev: FPGA device to be queried for information
243 * @features: Pointer to the structure to fill with information from the
244 * features register
245 * Return: 0
246 */
247static int get_features(struct udevice *dev, struct fpga_features *features)
248{
249 struct ihs_fpga_priv *priv = dev_get_priv(dev);
250 enum {
251 FEATURE_SPDIF_RX = BIT(15),
252 FEATURE_SPDIF_TX = BIT(14),
253 FEATURE_PCM_RX = BIT(13),
254 FEATURE_PCM_TX = BIT(12),
255 FEATURE_RAM_MASK = GENMASK(11, 8),
256 FEATURE_RAM_DDR2_32BIT_295MBPS = 0x0 << 8,
257 FEATURE_RAM_DDR3_32BIT_590MBPS = 0x1 << 8,
258 FEATURE_RAM_DDR3_48BIT_590MBPS = 0x2 << 8,
259 FEATURE_RAM_DDR3_64BIT_1800MBPS = 0x3 << 8,
260 FEATURE_RAM_DDR3_48BIT_1800MBPS = 0x4 << 8,
261 FEATURE_CARRIER_SPEED_MASK = GENMASK(7, 6),
262 FEATURE_CARRIER_SPEED_1G = 0x0 << 6,
263 FEATURE_CARRIER_SPEED_2_5G = 0x1 << 6,
264 FEATURE_CARRIER_SPEED_10G = 0x2 << 6,
265 FEATURE_CARRIERS_MASK = GENMASK(5, 4),
266 FEATURE_CARRIERS_0 = 0x0 << 4,
267 FEATURE_CARRIERS_1 = 0x1 << 4,
268 FEATURE_CARRIERS_2 = 0x2 << 4,
269 FEATURE_CARRIERS_4 = 0x3 << 4,
270 FEATURE_USB2 = BIT(3),
271 FEATURE_VIDEOCHANNELS_MASK = GENMASK(2, 0),
272 FEATURE_VIDEOCHANNELS_0 = 0x0 << 0,
273 FEATURE_VIDEOCHANNELS_1 = 0x1 << 0,
274 FEATURE_VIDEOCHANNELS_1_1 = 0x2 << 0,
275 FEATURE_VIDEOCHANNELS_2 = 0x3 << 0,
276 };
277
278 enum {
279 EXT_FEATURE_OSD = BIT(15),
280 EXT_FEATURE_ETHERNET = BIT(9),
281 EXT_FEATURE_INTERLACE = BIT(8),
282 EXT_FEATURE_RS232 = BIT(7),
283 EXT_FEATURE_COMPRESSION_PERF_MASK = GENMASK(6, 4),
284 EXT_FEATURE_COMPRESSION_PERF_1X = 0x0 << 4,
285 EXT_FEATURE_COMPRESSION_PERF_2X = 0x1 << 4,
286 EXT_FEATURE_COMPRESSION_PERF_4X = 0x2 << 4,
287 EXT_FEATURE_COMPRESSION_TYPE1 = BIT(0),
288 EXT_FEATURE_COMPRESSION_TYPE2 = BIT(1),
289 EXT_FEATURE_COMPRESSION_TYPE3 = BIT(2),
290 };
291
292 u16 raw_features;
293 u16 raw_extended_features;
294
295 memset(features, 0, sizeof(struct fpga_features));
296
297 ihs_fpga_get(priv->map, features, &raw_features);
298 ihs_fpga_get(priv->map, extended_features, &raw_extended_features);
299
300 switch (raw_features & FEATURE_VIDEOCHANNELS_MASK) {
301 case FEATURE_VIDEOCHANNELS_0:
302 features->video_channels = 0;
303 break;
304
305 case FEATURE_VIDEOCHANNELS_1:
306 features->video_channels = 1;
307 break;
308
309 case FEATURE_VIDEOCHANNELS_1_1:
310 case FEATURE_VIDEOCHANNELS_2:
311 features->video_channels = 2;
312 break;
313 };
314
315 switch (raw_features & FEATURE_CARRIERS_MASK) {
316 case FEATURE_CARRIERS_0:
317 features->carriers = 0;
318 break;
319
320 case FEATURE_CARRIERS_1:
321 features->carriers = 1;
322 break;
323
324 case FEATURE_CARRIERS_2:
325 features->carriers = 2;
326 break;
327
328 case FEATURE_CARRIERS_4:
329 features->carriers = 4;
330 break;
331 }
332
333 switch (raw_features & FEATURE_CARRIER_SPEED_MASK) {
334 case FEATURE_CARRIER_SPEED_1G:
335 features->carrier_speed = CARRIER_SPEED_1G;
336 break;
337 case FEATURE_CARRIER_SPEED_2_5G:
338 features->carrier_speed = CARRIER_SPEED_2_5G;
339 break;
340 case FEATURE_CARRIER_SPEED_10G:
341 features->carrier_speed = CARRIER_SPEED_10G;
342 break;
343 }
344
345 switch (raw_features & FEATURE_RAM_MASK) {
346 case FEATURE_RAM_DDR2_32BIT_295MBPS:
347 features->ram_config = RAM_DDR2_32BIT_295MBPS;
348 break;
349
350 case FEATURE_RAM_DDR3_32BIT_590MBPS:
351 features->ram_config = RAM_DDR3_32BIT_590MBPS;
352 break;
353
354 case FEATURE_RAM_DDR3_48BIT_590MBPS:
355 features->ram_config = RAM_DDR3_48BIT_590MBPS;
356 break;
357
358 case FEATURE_RAM_DDR3_64BIT_1800MBPS:
359 features->ram_config = RAM_DDR3_64BIT_1800MBPS;
360 break;
361
362 case FEATURE_RAM_DDR3_48BIT_1800MBPS:
363 features->ram_config = RAM_DDR3_48BIT_1800MBPS;
364 break;
365 }
366
367 features->pcm_tx = raw_features & FEATURE_PCM_TX;
368 features->pcm_rx = raw_features & FEATURE_PCM_RX;
369 features->spdif_tx = raw_features & FEATURE_SPDIF_TX;
370 features->spdif_rx = raw_features & FEATURE_SPDIF_RX;
371 features->usb2 = raw_features & FEATURE_USB2;
372 features->rs232 = raw_extended_features & EXT_FEATURE_RS232;
373 features->compression_type1 = raw_extended_features &
374 EXT_FEATURE_COMPRESSION_TYPE1;
375 features->compression_type2 = raw_extended_features &
376 EXT_FEATURE_COMPRESSION_TYPE2;
377 features->compression_type3 = raw_extended_features &
378 EXT_FEATURE_COMPRESSION_TYPE3;
379 features->interlace = raw_extended_features & EXT_FEATURE_INTERLACE;
380 features->osd = raw_extended_features & EXT_FEATURE_OSD;
381 features->compression_pipes = raw_extended_features &
382 EXT_FEATURE_COMPRESSION_PERF_MASK;
383
384 return 0;
385}
386
387#else
388
389/**
390 * get_versions() - Fill structure with info from version register.
391 * @fpga: Identifier of the FPGA device to be queried for information
392 * @versions: Pointer to the structure to fill with information from the
393 * versions register
394 *
395 * This is the legacy version and should be considered deprecated for new
396 * devices.
397 *
398 * Return: 0
399 */
400static int get_versions(unsigned int fpga, struct fpga_versions *versions)
401{
402 enum {
403 /* HW version encoding is a mess, leave it for the moment */
404 VERSIONS_HW_VER_MASK = 0xf << 0,
405 VERSIONS_PIX_CLOCK_GEN_IDT8N3QV01 = BIT(4),
406 VERSIONS_SFP = BIT(5),
407 VERSIONS_VIDEO_MASK = 0x7 << 6,
408 VERSIONS_VIDEO_DVI = 0x0 << 6,
409 VERSIONS_VIDEO_DP_165 = 0x1 << 6,
410 VERSIONS_VIDEO_DP_300 = 0x2 << 6,
411 VERSIONS_VIDEO_HDMI = 0x3 << 6,
412 VERSIONS_UT_MASK = 0xf << 12,
413 VERSIONS_UT_MAIN_SERVER = 0x0 << 12,
414 VERSIONS_UT_MAIN_USER = 0x1 << 12,
415 VERSIONS_UT_VIDEO_SERVER = 0x2 << 12,
416 VERSIONS_UT_VIDEO_USER = 0x3 << 12,
417 };
418 u16 raw_versions;
419
420 memset(versions, 0, sizeof(struct fpga_versions));
421
422 FPGA_GET_REG(fpga, versions, &raw_versions);
423
424 switch (raw_versions & VERSIONS_UT_MASK) {
425 case VERSIONS_UT_MAIN_SERVER:
426 versions->video_channel = false;
427 versions->con_side = false;
428 break;
429
430 case VERSIONS_UT_MAIN_USER:
431 versions->video_channel = false;
432 versions->con_side = true;
433 break;
434
435 case VERSIONS_UT_VIDEO_SERVER:
436 versions->video_channel = true;
437 versions->con_side = false;
438 break;
439
440 case VERSIONS_UT_VIDEO_USER:
441 versions->video_channel = true;
442 versions->con_side = true;
443 break;
444 }
445
446 switch (raw_versions & VERSIONS_VIDEO_MASK) {
447 case VERSIONS_VIDEO_DVI:
448 versions->pcb_video_type = PCB_DVI_SL;
449 break;
450
451 case VERSIONS_VIDEO_DP_165:
452 versions->pcb_video_type = PCB_DP_165MPIX;
453 break;
454
455 case VERSIONS_VIDEO_DP_300:
456 versions->pcb_video_type = PCB_DP_300MPIX;
457 break;
458
459 case VERSIONS_VIDEO_HDMI:
460 versions->pcb_video_type = PCB_HDMI;
461 break;
462 }
463
464 versions->hw_version = raw_versions & VERSIONS_HW_VER_MASK;
465
466 if (raw_versions & VERSIONS_SFP)
467 versions->pcb_transmission_type = PCB_FIBER_3G;
468 else
469 versions->pcb_transmission_type = PCB_CAT_1G;
470
471 return 0;
472}
473
474/**
475 * get_features() - Fill structure with info from features register.
476 * @fpga: Identifier of the FPGA device to be queried for information
477 * @features: Pointer to the structure to fill with information from the
478 * features register
479 *
480 * This is the legacy version and should be considered deprecated for new
481 * devices.
482 *
483 * Return: 0
484 */
485static int get_features(unsigned int fpga, struct fpga_features *features)
486{
487 enum {
488 FEATURE_CARRIER_SPEED_2_5 = BIT(4),
489 FEATURE_RAM_MASK = 0x7 << 5,
490 FEATURE_RAM_DDR2_32BIT = 0x0 << 5,
491 FEATURE_RAM_DDR3_32BIT = 0x1 << 5,
492 FEATURE_RAM_DDR3_48BIT = 0x2 << 5,
493 FEATURE_PCM_AUDIO_TX = BIT(9),
494 FEATURE_PCM_AUDIO_RX = BIT(10),
495 FEATURE_OSD = BIT(11),
496 FEATURE_USB20 = BIT(12),
497 FEATURE_COMPRESSION_MASK = 7 << 13,
498 FEATURE_COMPRESSION_TYPE1 = 0x1 << 13,
499 FEATURE_COMPRESSION_TYPE1_TYPE2 = 0x3 << 13,
500 FEATURE_COMPRESSION_TYPE1_TYPE2_TYPE3 = 0x7 << 13,
501 };
502
503 enum {
504 EXTENDED_FEATURE_SPDIF_AUDIO_TX = BIT(0),
505 EXTENDED_FEATURE_SPDIF_AUDIO_RX = BIT(1),
506 EXTENDED_FEATURE_RS232 = BIT(2),
507 EXTENDED_FEATURE_COMPRESSION_PIPES = BIT(3),
508 EXTENDED_FEATURE_INTERLACE = BIT(4),
509 };
510
511 u16 raw_features;
512 u16 raw_extended_features;
513
514 memset(features, 0, sizeof(struct fpga_features));
515
516 FPGA_GET_REG(fpga, fpga_features, &raw_features);
517 FPGA_GET_REG(fpga, fpga_ext_features, &raw_extended_features);
518
519 features->video_channels = raw_features & 0x3;
520 features->carriers = (raw_features >> 2) & 0x3;
521
522 features->carrier_speed = (raw_features & FEATURE_CARRIER_SPEED_2_5)
523 ? CARRIER_SPEED_2_5G : CARRIER_SPEED_1G;
524
525 switch (raw_features & FEATURE_RAM_MASK) {
526 case FEATURE_RAM_DDR2_32BIT:
527 features->ram_config = RAM_DDR2_32BIT_295MBPS;
528 break;
529
530 case FEATURE_RAM_DDR3_32BIT:
531 features->ram_config = RAM_DDR3_32BIT_590MBPS;
532 break;
533
534 case FEATURE_RAM_DDR3_48BIT:
535 features->ram_config = RAM_DDR3_48BIT_590MBPS;
536 break;
537 }
538
539 features->pcm_tx = raw_features & FEATURE_PCM_AUDIO_TX;
540 features->pcm_rx = raw_features & FEATURE_PCM_AUDIO_RX;
541 features->spdif_tx = raw_extended_features &
542 EXTENDED_FEATURE_SPDIF_AUDIO_TX;
543 features->spdif_rx = raw_extended_features &
544 EXTENDED_FEATURE_SPDIF_AUDIO_RX;
545
546 features->usb2 = raw_features & FEATURE_USB20;
547 features->rs232 = raw_extended_features & EXTENDED_FEATURE_RS232;
548
549 features->compression_type1 = false;
550 features->compression_type2 = false;
551 features->compression_type3 = false;
552 switch (raw_features & FEATURE_COMPRESSION_MASK) {
553 case FEATURE_COMPRESSION_TYPE1_TYPE2_TYPE3:
554 features->compression_type3 = true;
555 /* fall-through */
556 case FEATURE_COMPRESSION_TYPE1_TYPE2:
557 features->compression_type2 = true;
558 /* fall-through */
559 case FEATURE_COMPRESSION_TYPE1:
560 features->compression_type1 = true;
561 break;
562 }
563
564 features->interlace = raw_extended_features &
565 EXTENDED_FEATURE_INTERLACE;
566 features->osd = raw_features & FEATURE_OSD;
567 features->compression_pipes = raw_extended_features &
568 EXTENDED_FEATURE_COMPRESSION_PIPES;
569
570 return 0;
571}
572
573#endif
574
575/**
576 * fpga_print_info() - Print information about FPGA device
577 * @dev: FPGA device to print information about
578 */
579static void fpga_print_info(struct udevice *dev)
580{
581 struct ihs_fpga_priv *priv = dev_get_priv(dev);
582 u16 fpga_version;
583 struct fpga_versions versions;
584 struct fpga_features features;
585
586 ihs_fpga_get(priv->map, fpga_version, &fpga_version);
587 get_versions(dev, &versions);
588 get_features(dev, &features);
589
590 if (versions.video_channel)
591 printf("Videochannel");
592 else
593 printf("Mainchannel");
594
595 if (versions.con_side)
596 printf(" User");
597 else
598 printf(" Server");
599
600 switch (versions.pcb_transmission_type) {
601 case PCB_CAT_1G:
602 case PCB_CAT_10G:
603 printf(" CAT");
604 break;
605 case PCB_FIBER_3G:
606 case PCB_FIBER_10G:
607 printf(" Fiber");
608 break;
609 };
610
611 switch (versions.pcb_video_type) {
612 case PCB_DVI_SL:
613 printf(" DVI,");
614 break;
615 case PCB_DP_165MPIX:
616 printf(" DP 165MPix/s,");
617 break;
618 case PCB_DP_300MPIX:
619 printf(" DP 300MPix/s,");
620 break;
621 case PCB_HDMI:
622 printf(" HDMI,");
623 break;
624 case PCB_DP_1_2:
625 printf(" DP 1.2,");
626 break;
627 case PCB_HDMI_2_0:
628 printf(" HDMI 2.0,");
629 break;
630 }
631
632 printf(" FPGA V %d.%02d\n features: ",
633 fpga_version / 100, fpga_version % 100);
634
635 if (!features.compression_type1 &&
636 !features.compression_type2 &&
637 !features.compression_type3)
638 printf("no compression, ");
639
640 if (features.compression_type1)
641 printf("type1, ");
642
643 if (features.compression_type2)
644 printf("type2, ");
645
646 if (features.compression_type3)
647 printf("type3, ");
648
649 printf("%sosd", features.osd ? "" : "no ");
650
651 if (features.pcm_rx && features.pcm_tx)
652 printf(", pcm rx+tx");
653 else if (features.pcm_rx)
654 printf(", pcm rx");
655 else if (features.pcm_tx)
656 printf(", pcm tx");
657
658 if (features.spdif_rx && features.spdif_tx)
659 printf(", spdif rx+tx");
660 else if (features.spdif_rx)
661 printf(", spdif rx");
662 else if (features.spdif_tx)
663 printf(", spdif tx");
664
665 puts(",\n ");
666
667 switch (features.sysclock) {
668 case SYSCLK_147456:
669 printf("clock 147.456 MHz");
670 break;
671 }
672
673 switch (features.ram_config) {
674 case RAM_DDR2_32BIT_295MBPS:
675 printf(", RAM 32 bit DDR2");
676 break;
677 case RAM_DDR3_32BIT_590MBPS:
678 printf(", RAM 32 bit DDR3");
679 break;
680 case RAM_DDR3_48BIT_590MBPS:
681 case RAM_DDR3_48BIT_1800MBPS:
682 printf(", RAM 48 bit DDR3");
683 break;
684 case RAM_DDR3_64BIT_1800MBPS:
685 printf(", RAM 64 bit DDR3");
686 break;
687 }
688
689 printf(", %d carrier(s)", features.carriers);
690
691 switch (features.carrier_speed) {
692 case CARRIER_SPEED_1G:
693 printf(", 1Gbit/s");
694 break;
695 case CARRIER_SPEED_3G:
696 printf(", 3Gbit/s");
697 break;
698 case CARRIER_SPEED_10G:
699 printf(", 10Gbit/s");
700 break;
701 }
702
703 printf(", %d video channel(s)\n", features.video_channels);
704}
705
706/**
707 * do_reflection_test() - Run reflection test on a FPGA device
708 * @dev: FPGA device to run reflection test on
709 *
710 * Return: 0 if reflection test succeeded, -ve on error
711 */
712static int do_reflection_test(struct udevice *dev)
713{
714 struct ihs_fpga_priv *priv = dev_get_priv(dev);
715 int ctr = 0;
716
717 while (1) {
718 u16 val;
719
720 ihs_fpga_set(priv->map, reflection_low, REFLECTION_TESTPATTERN);
721
722 ihs_fpga_get(priv->map, reflection_low, &val);
723 if (val == (~REFLECTION_TESTPATTERN & 0xffff))
724 return -EIO;
725
726 mdelay(REFLECTION_TEST_DELAY);
727 if (ctr++ > REFLECTION_TEST_ROUNDS)
728 return 0;
729 }
730}
731
732/**
733 * wait_for_fpga_done() - Wait until 'done'-flag is set for FPGA device
734 * @dev: FPGA device whose done flag to wait for
735 *
736 * This function waits until it detects that the done-GPIO's value was changed
737 * to 1 by the FPGA, which indicates that the device is configured and ready to
738 * use.
739 *
740 * Return: 0 if done flag was detected, -ve on error
741 */
742static int wait_for_fpga_done(struct udevice *dev)
743{
744 struct ihs_fpga_priv *priv = dev_get_priv(dev);
745 int ctr = 0;
746 int done_val;
747
748 while (1) {
749 done_val = dm_gpio_get_value(&priv->done_gpio);
750 if (done_val < 0) {
751 debug("%s: Error while reading done-GPIO (err = %d)\n",
752 dev->name, done_val);
753 return done_val;
754 }
755
756 if (done_val)
757 return 0;
758
759 mdelay(FPGA_DONE_WAIT_DELAY);
760 if (ctr++ > FPGA_DONE_WAIT_ROUND) {
761 debug("%s: FPGA init failed (done not detected)\n",
762 dev->name);
763 return -EIO;
764 }
765 }
766}
767
768static int ihs_fpga_probe(struct udevice *dev)
769{
770 struct ihs_fpga_priv *priv = dev_get_priv(dev);
771 int ret;
772
773 /* TODO(mario.six@gdsys.cc): Case of FPGA attached to MCLink bus */
774
775 ret = regmap_init_mem(dev_ofnode(dev), &priv->map);
776 if (ret) {
777 debug("%s: Could not initialize regmap (err = %d)",
778 dev->name, ret);
779 return ret;
780 }
781
782 ret = gpio_request_by_name(dev, "reset-gpios", 0, &priv->reset_gpio,
783 GPIOD_IS_OUT);
784 if (ret) {
785 debug("%s: Could not get reset-GPIO (err = %d)\n",
786 dev->name, ret);
787 return ret;
788 }
789
790 if (!priv->reset_gpio.dev) {
791 debug("%s: Could not get reset-GPIO\n", dev->name);
792 return -ENOENT;
793 }
794
795 ret = gpio_request_by_name(dev, "done-gpios", 0, &priv->done_gpio,
796 GPIOD_IS_IN);
797 if (ret) {
798 debug("%s: Could not get done-GPIO (err = %d)\n",
799 dev->name, ret);
800 return ret;
801 }
802
803 if (!priv->done_gpio.dev) {
804 debug("%s: Could not get done-GPIO\n", dev->name);
805 return -ENOENT;
806 }
807
808 ret = dm_gpio_set_value(&priv->reset_gpio, 1);
809 if (ret) {
810 debug("%s: Error while setting reset-GPIO (err = %d)\n",
811 dev->name, ret);
812 return ret;
813 }
814
815 /* If FPGA already runs, don't initialize again */
816 if (do_reflection_test(dev))
817 goto reflection_ok;
818
819 ret = dm_gpio_set_value(&priv->reset_gpio, 0);
820 if (ret) {
821 debug("%s: Error while setting reset-GPIO (err = %d)\n",
822 dev->name, ret);
823 return ret;
824 }
825
826 ret = wait_for_fpga_done(dev);
827 if (ret) {
828 debug("%s: Error while waiting for FPGA done (err = %d)\n",
829 dev->name, ret);
830 return ret;
831 }
832
833 udelay(10);
834
835 ret = dm_gpio_set_value(&priv->reset_gpio, 1);
836 if (ret) {
837 debug("%s: Error while setting reset-GPIO (err = %d)\n",
838 dev->name, ret);
839 return ret;
840 }
841
842 if (!do_reflection_test(dev)) {
843 debug("%s: Reflection test FAILED\n", dev->name);
844 return -EIO;
845 }
846
847reflection_ok:
848 printf("%s: Reflection test passed.\n", dev->name);
849
850 fpga_print_info(dev);
851
852 return 0;
853}
854
855static const struct udevice_id ihs_fpga_ids[] = {
856 { .compatible = "gdsys,iocon_fpga" },
857 { .compatible = "gdsys,iocpu_fpga" },
858 { }
859};
860
861U_BOOT_DRIVER(ihs_fpga_bus) = {
862 .name = "ihs_fpga_bus",
863 .id = UCLASS_MISC,
864 .of_match = ihs_fpga_ids,
865 .probe = ihs_fpga_probe,
866 .priv_auto_alloc_size = sizeof(struct ihs_fpga_priv),
867};
diff --git a/drivers/misc/ihs_fpga.h b/drivers/misc/ihs_fpga.h
new file mode 100644
index 0000000000..efb5dabb9c
--- /dev/null
+++ b/drivers/misc/ihs_fpga.h
@@ -0,0 +1,49 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * (C) Copyright 2018
4 * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
5 */
6
7/**
8 * struct ihs_fpga_regs - IHS FPGA register map structure
9 * @reflection_low: Lower reflection register
10 * @versions: PCB versions register
11 * @fpga_version: FPGA versions register
12 * @features: FPGA features register
13 * @extended_features: FPGA extended features register
14 * @top_interrupt: Top interrupt register
15 * @top_interrupt_enable: Top interrupt enable register
16 * @status: FPGA status register
17 * @control: FPGA control register
18 * @extended_control: FPGA extended control register
19 */
20struct ihs_fpga_regs {
21 u16 reflection_low;
22 u16 versions;
23 u16 fpga_version;
24 u16 features;
25 u16 extended_features;
26 u16 top_interrupt;
27 u16 top_interrupt_enable;
28 u16 status;
29 u16 control;
30 u16 extended_control;
31};
32
33/**
34 * ihs_fpga_set() - Convenience macro to set values in FPGA register map
35 * @map: Register map to set a value in
36 * @member: Name of member (described by ihs_fpga_regs) to set
37 * @val: Value to set the member to
38 */
39#define ihs_fpga_set(map, member, val) \
40 regmap_set(map, struct ihs_fpga_regs, member, val)
41
42/**
43 * ihs_fpga_get() - Convenience macro to get values from FPGA register map
44 * @map: Register map to read value from
45 * @member: Name of member (described by ihs_fpga_regs) to get
46 * @valp: Pointe to variable to receive the value read
47 */
48#define ihs_fpga_get(map, member, valp) \
49 regmap_get(map, struct ihs_fpga_regs, member, valp)
diff --git a/drivers/misc/imx8/scu.c b/drivers/misc/imx8/scu.c
index 0647ddf103..b824ac79e6 100644
--- a/drivers/misc/imx8/scu.c
+++ b/drivers/misc/imx8/scu.c
@@ -223,7 +223,7 @@ static int imx8_scu_bind(struct udevice *dev)
223 if (node < 0) 223 if (node < 0)
224 panic("No clk node found\n"); 224 panic("No clk node found\n");
225 225
226 ret = lists_bind_fdt(dev, offset_to_ofnode(node), &child); 226 ret = lists_bind_fdt(dev, offset_to_ofnode(node), &child, true);
227 if (ret) 227 if (ret)
228 return ret; 228 return ret;
229 229
@@ -234,7 +234,7 @@ static int imx8_scu_bind(struct udevice *dev)
234 if (node < 0) 234 if (node < 0)
235 panic("No iomuxc node found\n"); 235 panic("No iomuxc node found\n");
236 236
237 ret = lists_bind_fdt(dev, offset_to_ofnode(node), &child); 237 ret = lists_bind_fdt(dev, offset_to_ofnode(node), &child, true);
238 if (ret) 238 if (ret)
239 return ret; 239 return ret;
240 240
diff --git a/drivers/misc/swap_case.c b/drivers/misc/swap_case.c
index bffb809f14..fa608cec1b 100644
--- a/drivers/misc/swap_case.c
+++ b/drivers/misc/swap_case.c
@@ -124,12 +124,21 @@ static int sandbox_swap_case_read_config(struct udevice *emul, uint offset,
124 case PCI_CAP_ID_PM_OFFSET: 124 case PCI_CAP_ID_PM_OFFSET:
125 *valuep = (PCI_CAP_ID_EXP_OFFSET << 8) | PCI_CAP_ID_PM; 125 *valuep = (PCI_CAP_ID_EXP_OFFSET << 8) | PCI_CAP_ID_PM;
126 break; 126 break;
127 case PCI_CAP_ID_PM_OFFSET + PCI_CAP_LIST_NEXT:
128 *valuep = PCI_CAP_ID_EXP_OFFSET;
129 break;
127 case PCI_CAP_ID_EXP_OFFSET: 130 case PCI_CAP_ID_EXP_OFFSET:
128 *valuep = (PCI_CAP_ID_MSIX_OFFSET << 8) | PCI_CAP_ID_EXP; 131 *valuep = (PCI_CAP_ID_MSIX_OFFSET << 8) | PCI_CAP_ID_EXP;
129 break; 132 break;
133 case PCI_CAP_ID_EXP_OFFSET + PCI_CAP_LIST_NEXT:
134 *valuep = PCI_CAP_ID_MSIX_OFFSET;
135 break;
130 case PCI_CAP_ID_MSIX_OFFSET: 136 case PCI_CAP_ID_MSIX_OFFSET:
131 *valuep = PCI_CAP_ID_MSIX; 137 *valuep = PCI_CAP_ID_MSIX;
132 break; 138 break;
139 case PCI_CAP_ID_MSIX_OFFSET + PCI_CAP_LIST_NEXT:
140 *valuep = 0;
141 break;
133 case PCI_EXT_CAP_ID_ERR_OFFSET: 142 case PCI_EXT_CAP_ID_ERR_OFFSET:
134 *valuep = (PCI_EXT_CAP_ID_VC_OFFSET << 20) | PCI_EXT_CAP_ID_ERR; 143 *valuep = (PCI_EXT_CAP_ID_VC_OFFSET << 20) | PCI_EXT_CAP_ID_ERR;
135 break; 144 break;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 585951cd78..d6b9cdc992 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -2444,9 +2444,6 @@ static int mmc_startup(struct mmc *mmc)
2444 bdesc->product[0] = 0; 2444 bdesc->product[0] = 0;
2445 bdesc->revision[0] = 0; 2445 bdesc->revision[0] = 0;
2446#endif 2446#endif
2447#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT)
2448 part_init(bdesc);
2449#endif
2450 2447
2451 return 0; 2448 return 0;
2452} 2449}
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index ec853d063f..5cb97eb02a 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -1953,6 +1953,8 @@ U_BOOT_DRIVER(omap_hsmmc) = {
1953 .ops = &omap_hsmmc_ops, 1953 .ops = &omap_hsmmc_ops,
1954 .probe = omap_hsmmc_probe, 1954 .probe = omap_hsmmc_probe,
1955 .priv_auto_alloc_size = sizeof(struct omap_hsmmc_data), 1955 .priv_auto_alloc_size = sizeof(struct omap_hsmmc_data),
1956#if !CONFIG_IS_ENABLED(OF_CONTROL)
1956 .flags = DM_FLAG_PRE_RELOC, 1957 .flags = DM_FLAG_PRE_RELOC,
1958#endif
1957}; 1959};
1958#endif 1960#endif
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index eb6fdeda50..1ee0a0aefb 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -664,7 +664,6 @@ static int nvme_blk_probe(struct udevice *udev)
664 sprintf(desc->vendor, "0x%.4x", pplat->vendor); 664 sprintf(desc->vendor, "0x%.4x", pplat->vendor);
665 memcpy(desc->product, ndev->serial, sizeof(ndev->serial)); 665 memcpy(desc->product, ndev->serial, sizeof(ndev->serial));
666 memcpy(desc->revision, ndev->firmware_rev, sizeof(ndev->firmware_rev)); 666 memcpy(desc->revision, ndev->firmware_rev, sizeof(ndev->firmware_rev));
667 part_init(desc);
668 667
669 return 0; 668 return 0;
670} 669}
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index da49c96ed5..0c52337f33 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -1344,26 +1344,14 @@ void *dm_pci_map_bar(struct udevice *dev, int bar, int flags)
1344 return dm_pci_bus_to_virt(dev, pci_bus_addr, flags, 0, MAP_NOCACHE); 1344 return dm_pci_bus_to_virt(dev, pci_bus_addr, flags, 0, MAP_NOCACHE);
1345} 1345}
1346 1346
1347int dm_pci_find_capability(struct udevice *dev, int cap) 1347static int _dm_pci_find_next_capability(struct udevice *dev, u8 pos, int cap)
1348{ 1348{
1349 u16 status;
1350 u8 header_type;
1351 int ttl = PCI_FIND_CAP_TTL; 1349 int ttl = PCI_FIND_CAP_TTL;
1352 u8 id; 1350 u8 id;
1353 u16 ent; 1351 u16 ent;
1354 u8 pos;
1355
1356 dm_pci_read_config16(dev, PCI_STATUS, &status);
1357 if (!(status & PCI_STATUS_CAP_LIST))
1358 return 0;
1359
1360 dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type);
1361 if ((header_type & 0x7f) == PCI_HEADER_TYPE_CARDBUS)
1362 pos = PCI_CB_CAPABILITY_LIST;
1363 else
1364 pos = PCI_CAPABILITY_LIST;
1365 1352
1366 dm_pci_read_config8(dev, pos, &pos); 1353 dm_pci_read_config8(dev, pos, &pos);
1354
1367 while (ttl--) { 1355 while (ttl--) {
1368 if (pos < PCI_STD_HEADER_SIZEOF) 1356 if (pos < PCI_STD_HEADER_SIZEOF)
1369 break; 1357 break;
@@ -1381,7 +1369,32 @@ int dm_pci_find_capability(struct udevice *dev, int cap)
1381 return 0; 1369 return 0;
1382} 1370}
1383 1371
1384int dm_pci_find_ext_capability(struct udevice *dev, int cap) 1372int dm_pci_find_next_capability(struct udevice *dev, u8 start, int cap)
1373{
1374 return _dm_pci_find_next_capability(dev, start + PCI_CAP_LIST_NEXT,
1375 cap);
1376}
1377
1378int dm_pci_find_capability(struct udevice *dev, int cap)
1379{
1380 u16 status;
1381 u8 header_type;
1382 u8 pos;
1383
1384 dm_pci_read_config16(dev, PCI_STATUS, &status);
1385 if (!(status & PCI_STATUS_CAP_LIST))
1386 return 0;
1387
1388 dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type);
1389 if ((header_type & 0x7f) == PCI_HEADER_TYPE_CARDBUS)
1390 pos = PCI_CB_CAPABILITY_LIST;
1391 else
1392 pos = PCI_CAPABILITY_LIST;
1393
1394 return _dm_pci_find_next_capability(dev, pos, cap);
1395}
1396
1397int dm_pci_find_next_ext_capability(struct udevice *dev, int start, int cap)
1385{ 1398{
1386 u32 header; 1399 u32 header;
1387 int ttl; 1400 int ttl;
@@ -1390,6 +1403,9 @@ int dm_pci_find_ext_capability(struct udevice *dev, int cap)
1390 /* minimum 8 bytes per capability */ 1403 /* minimum 8 bytes per capability */
1391 ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8; 1404 ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
1392 1405
1406 if (start)
1407 pos = start;
1408
1393 dm_pci_read_config32(dev, pos, &header); 1409 dm_pci_read_config32(dev, pos, &header);
1394 /* 1410 /*
1395 * If we have no capabilities, this is indicated by cap ID, 1411 * If we have no capabilities, this is indicated by cap ID,
@@ -1412,6 +1428,11 @@ int dm_pci_find_ext_capability(struct udevice *dev, int cap)
1412 return 0; 1428 return 0;
1413} 1429}
1414 1430
1431int dm_pci_find_ext_capability(struct udevice *dev, int cap)
1432{
1433 return dm_pci_find_next_ext_capability(dev, 0, cap);
1434}
1435
1415UCLASS_DRIVER(pci) = { 1436UCLASS_DRIVER(pci) = {
1416 .id = UCLASS_PCI, 1437 .id = UCLASS_PCI,
1417 .name = "pci", 1438 .name = "pci",
diff --git a/drivers/pinctrl/broadcom/pinctrl-bcm283x.c b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c
index 891b4c25fd..3be080d29e 100644
--- a/drivers/pinctrl/broadcom/pinctrl-bcm283x.c
+++ b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c
@@ -148,5 +148,7 @@ U_BOOT_DRIVER(pinctrl_bcm283x) = {
148 .priv_auto_alloc_size = sizeof(struct bcm283x_pinctrl_priv), 148 .priv_auto_alloc_size = sizeof(struct bcm283x_pinctrl_priv),
149 .ops = &bcm283x_pinctrl_ops, 149 .ops = &bcm283x_pinctrl_ops,
150 .probe = bcm283x_pinctl_probe, 150 .probe = bcm283x_pinctl_probe,
151#if !CONFIG_IS_ENABLED(OF_CONTROL)
151 .flags = DM_FLAG_PRE_RELOC, 152 .flags = DM_FLAG_PRE_RELOC,
153#endif
152}; 154};
diff --git a/drivers/pinctrl/exynos/pinctrl-exynos7420.c b/drivers/pinctrl/exynos/pinctrl-exynos7420.c
index cb5975b252..ff6d6c4143 100644
--- a/drivers/pinctrl/exynos/pinctrl-exynos7420.c
+++ b/drivers/pinctrl/exynos/pinctrl-exynos7420.c
@@ -113,5 +113,4 @@ U_BOOT_DRIVER(pinctrl_exynos7420) = {
113 .priv_auto_alloc_size = sizeof(struct exynos_pinctrl_priv), 113 .priv_auto_alloc_size = sizeof(struct exynos_pinctrl_priv),
114 .ops = &exynos7420_pinctrl_ops, 114 .ops = &exynos7420_pinctrl_ops,
115 .probe = exynos_pinctrl_probe, 115 .probe = exynos_pinctrl_probe,
116 .flags = DM_FLAG_PRE_RELOC
117}; 116};
diff --git a/drivers/pinctrl/nxp/pinctrl-imx5.c b/drivers/pinctrl/nxp/pinctrl-imx5.c
index 5d17380919..4e831b6f39 100644
--- a/drivers/pinctrl/nxp/pinctrl-imx5.c
+++ b/drivers/pinctrl/nxp/pinctrl-imx5.c
@@ -40,5 +40,7 @@ U_BOOT_DRIVER(imx5_pinctrl) = {
40 .remove = imx_pinctrl_remove, 40 .remove = imx_pinctrl_remove,
41 .priv_auto_alloc_size = sizeof(struct imx_pinctrl_priv), 41 .priv_auto_alloc_size = sizeof(struct imx_pinctrl_priv),
42 .ops = &imx_pinctrl_ops, 42 .ops = &imx_pinctrl_ops,
43#if !CONFIG_IS_ENABLED(OF_CONTROL)
43 .flags = DM_FLAG_PRE_RELOC, 44 .flags = DM_FLAG_PRE_RELOC,
45#endif
44}; 46};
diff --git a/drivers/pinctrl/nxp/pinctrl-imx6.c b/drivers/pinctrl/nxp/pinctrl-imx6.c
index e63ecbdee6..d7c95bb738 100644
--- a/drivers/pinctrl/nxp/pinctrl-imx6.c
+++ b/drivers/pinctrl/nxp/pinctrl-imx6.c
@@ -49,5 +49,7 @@ U_BOOT_DRIVER(imx6_pinctrl) = {
49 .remove = imx_pinctrl_remove, 49 .remove = imx_pinctrl_remove,
50 .priv_auto_alloc_size = sizeof(struct imx_pinctrl_priv), 50 .priv_auto_alloc_size = sizeof(struct imx_pinctrl_priv),
51 .ops = &imx_pinctrl_ops, 51 .ops = &imx_pinctrl_ops,
52#if !CONFIG_IS_ENABLED(OF_CONTROL)
52 .flags = DM_FLAG_PRE_RELOC, 53 .flags = DM_FLAG_PRE_RELOC,
54#endif
53}; 55};
diff --git a/drivers/pinctrl/nxp/pinctrl-imx7.c b/drivers/pinctrl/nxp/pinctrl-imx7.c
index 769d428dda..8776fd9650 100644
--- a/drivers/pinctrl/nxp/pinctrl-imx7.c
+++ b/drivers/pinctrl/nxp/pinctrl-imx7.c
@@ -37,5 +37,7 @@ U_BOOT_DRIVER(imx7_pinctrl) = {
37 .remove = imx_pinctrl_remove, 37 .remove = imx_pinctrl_remove,
38 .priv_auto_alloc_size = sizeof(struct imx_pinctrl_priv), 38 .priv_auto_alloc_size = sizeof(struct imx_pinctrl_priv),
39 .ops = &imx_pinctrl_ops, 39 .ops = &imx_pinctrl_ops,
40#if !CONFIG_IS_ENABLED(OF_CONTROL)
40 .flags = DM_FLAG_PRE_RELOC, 41 .flags = DM_FLAG_PRE_RELOC,
42#endif
41}; 43};
diff --git a/drivers/pinctrl/nxp/pinctrl-imx7ulp.c b/drivers/pinctrl/nxp/pinctrl-imx7ulp.c
index 598bbfaf35..d778f82aac 100644
--- a/drivers/pinctrl/nxp/pinctrl-imx7ulp.c
+++ b/drivers/pinctrl/nxp/pinctrl-imx7ulp.c
@@ -41,5 +41,7 @@ U_BOOT_DRIVER(imx7ulp_pinctrl) = {
41 .remove = imx_pinctrl_remove, 41 .remove = imx_pinctrl_remove,
42 .priv_auto_alloc_size = sizeof(struct imx_pinctrl_priv), 42 .priv_auto_alloc_size = sizeof(struct imx_pinctrl_priv),
43 .ops = &imx_pinctrl_ops, 43 .ops = &imx_pinctrl_ops,
44#if !CONFIG_IS_ENABLED(OF_CONTROL)
44 .flags = DM_FLAG_PRE_RELOC, 45 .flags = DM_FLAG_PRE_RELOC,
46#endif
45}; 47};
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index d80c6eda70..9dec88c1aa 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -136,7 +136,6 @@ U_BOOT_DRIVER(single_pinctrl) = {
136 .id = UCLASS_PINCTRL, 136 .id = UCLASS_PINCTRL,
137 .of_match = single_pinctrl_match, 137 .of_match = single_pinctrl_match,
138 .ops = &single_pinctrl_ops, 138 .ops = &single_pinctrl_ops,
139 .flags = DM_FLAG_PRE_RELOC,
140 .platdata_auto_alloc_size = sizeof(struct single_pdata), 139 .platdata_auto_alloc_size = sizeof(struct single_pdata),
141 .ofdata_to_platdata = single_ofdata_to_platdata, 140 .ofdata_to_platdata = single_ofdata_to_platdata,
142}; 141};
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
index a1da90baa4..eb5978a166 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
@@ -171,5 +171,7 @@ U_BOOT_DRIVER(uniphier_pro4_pinctrl) = {
171 .probe = uniphier_pro4_pinctrl_probe, 171 .probe = uniphier_pro4_pinctrl_probe,
172 .priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv), 172 .priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
173 .ops = &uniphier_pinctrl_ops, 173 .ops = &uniphier_pinctrl_ops,
174#if !CONFIG_IS_ENABLED(OF_CONTROL)
174 .flags = DM_FLAG_PRE_RELOC, 175 .flags = DM_FLAG_PRE_RELOC,
176#endif
175}; 177};
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
index 0ba2052b29..685d8be80c 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
@@ -153,5 +153,7 @@ U_BOOT_DRIVER(uniphier_pro5_pinctrl) = {
153 .probe = uniphier_pro5_pinctrl_probe, 153 .probe = uniphier_pro5_pinctrl_probe,
154 .priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv), 154 .priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
155 .ops = &uniphier_pinctrl_ops, 155 .ops = &uniphier_pinctrl_ops,
156#if !CONFIG_IS_ENABLED(OF_CONTROL)
156 .flags = DM_FLAG_PRE_RELOC, 157 .flags = DM_FLAG_PRE_RELOC,
158#endif
157}; 159};
diff --git a/drivers/ram/bmips_ram.c b/drivers/ram/bmips_ram.c
index b5f19c983c..3e1dd9e241 100644
--- a/drivers/ram/bmips_ram.c
+++ b/drivers/ram/bmips_ram.c
@@ -173,5 +173,4 @@ U_BOOT_DRIVER(bmips_ram) = {
173 .probe = bmips_ram_probe, 173 .probe = bmips_ram_probe,
174 .priv_auto_alloc_size = sizeof(struct bmips_ram_priv), 174 .priv_auto_alloc_size = sizeof(struct bmips_ram_priv),
175 .ops = &bmips_ram_ops, 175 .ops = &bmips_ram_ops,
176 .flags = DM_FLAG_PRE_RELOC,
177}; 176};
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index bc6ac8cd32..df47e2fc78 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -592,7 +592,6 @@ static int do_scsi_scan_one(struct udevice *dev, int id, int lun, bool verbose)
592 memcpy(&bdesc->vendor, &bd.vendor, sizeof(bd.vendor)); 592 memcpy(&bdesc->vendor, &bd.vendor, sizeof(bd.vendor));
593 memcpy(&bdesc->product, &bd.product, sizeof(bd.product)); 593 memcpy(&bdesc->product, &bd.product, sizeof(bd.product));
594 memcpy(&bdesc->revision, &bd.revision, sizeof(bd.revision)); 594 memcpy(&bdesc->revision, &bd.revision, sizeof(bd.revision));
595 part_init(bdesc);
596 595
597 if (verbose) { 596 if (verbose) {
598 printf(" Device %d: ", 0); 597 printf(" Device %d: ", 0);
diff --git a/drivers/serial/altera_jtag_uart.c b/drivers/serial/altera_jtag_uart.c
index 61052a92d6..86c3de4e45 100644
--- a/drivers/serial/altera_jtag_uart.c
+++ b/drivers/serial/altera_jtag_uart.c
@@ -121,7 +121,6 @@ U_BOOT_DRIVER(altera_jtaguart) = {
121 .platdata_auto_alloc_size = sizeof(struct altera_jtaguart_platdata), 121 .platdata_auto_alloc_size = sizeof(struct altera_jtaguart_platdata),
122 .probe = altera_jtaguart_probe, 122 .probe = altera_jtaguart_probe,
123 .ops = &altera_jtaguart_ops, 123 .ops = &altera_jtaguart_ops,
124 .flags = DM_FLAG_PRE_RELOC,
125}; 124};
126 125
127#ifdef CONFIG_DEBUG_UART_ALTERA_JTAGUART 126#ifdef CONFIG_DEBUG_UART_ALTERA_JTAGUART
diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c
index b7b0a13ca1..67d47199aa 100644
--- a/drivers/serial/altera_uart.c
+++ b/drivers/serial/altera_uart.c
@@ -117,7 +117,6 @@ U_BOOT_DRIVER(altera_uart) = {
117 .platdata_auto_alloc_size = sizeof(struct altera_uart_platdata), 117 .platdata_auto_alloc_size = sizeof(struct altera_uart_platdata),
118 .probe = altera_uart_probe, 118 .probe = altera_uart_probe,
119 .ops = &altera_uart_ops, 119 .ops = &altera_uart_ops,
120 .flags = DM_FLAG_PRE_RELOC,
121}; 120};
122 121
123#ifdef CONFIG_DEBUG_UART_ALTERA_UART 122#ifdef CONFIG_DEBUG_UART_ALTERA_UART
diff --git a/drivers/serial/arm_dcc.c b/drivers/serial/arm_dcc.c
index 43e8691a93..dfcb6fd698 100644
--- a/drivers/serial/arm_dcc.c
+++ b/drivers/serial/arm_dcc.c
@@ -155,7 +155,6 @@ U_BOOT_DRIVER(serial_dcc) = {
155 .id = UCLASS_SERIAL, 155 .id = UCLASS_SERIAL,
156 .of_match = arm_dcc_ids, 156 .of_match = arm_dcc_ids,
157 .ops = &arm_dcc_ops, 157 .ops = &arm_dcc_ops,
158 .flags = DM_FLAG_PRE_RELOC,
159}; 158};
160 159
161#ifdef CONFIG_DEBUG_UART_ARM_DCC 160#ifdef CONFIG_DEBUG_UART_ARM_DCC
diff --git a/drivers/serial/atmel_usart.c b/drivers/serial/atmel_usart.c
index 9414f5f692..aa8cdff840 100644
--- a/drivers/serial/atmel_usart.c
+++ b/drivers/serial/atmel_usart.c
@@ -294,7 +294,9 @@ U_BOOT_DRIVER(serial_atmel) = {
294#endif 294#endif
295 .probe = atmel_serial_probe, 295 .probe = atmel_serial_probe,
296 .ops = &atmel_serial_ops, 296 .ops = &atmel_serial_ops,
297#if !CONFIG_IS_ENABLED(OF_CONTROL)
297 .flags = DM_FLAG_PRE_RELOC, 298 .flags = DM_FLAG_PRE_RELOC,
299#endif
298 .priv_auto_alloc_size = sizeof(struct atmel_serial_priv), 300 .priv_auto_alloc_size = sizeof(struct atmel_serial_priv),
299}; 301};
300#endif 302#endif
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index f9041aa626..1e6fc6c668 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -267,12 +267,26 @@ static inline void _debug_uart_init(void)
267 serial_dout(&com_port->lcr, UART_LCRVAL); 267 serial_dout(&com_port->lcr, UART_LCRVAL);
268} 268}
269 269
270static inline int NS16550_read_baud_divisor(struct NS16550 *com_port)
271{
272 int ret;
273
274 serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL);
275 ret = serial_din(&com_port->dll) & 0xff;
276 ret |= (serial_din(&com_port->dlm) & 0xff) << 8;
277 serial_dout(&com_port->lcr, UART_LCRVAL);
278
279 return ret;
280}
281
270static inline void _debug_uart_putc(int ch) 282static inline void _debug_uart_putc(int ch)
271{ 283{
272 struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; 284 struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
273 285
274 while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) 286 while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) {
275 ; 287 if (!NS16550_read_baud_divisor(com_port))
288 return;
289 }
276 serial_dout(&com_port->thr, ch); 290 serial_dout(&com_port->thr, ch);
277} 291}
278 292
@@ -473,7 +487,9 @@ U_BOOT_DRIVER(ns16550_serial) = {
473 .priv_auto_alloc_size = sizeof(struct NS16550), 487 .priv_auto_alloc_size = sizeof(struct NS16550),
474 .probe = ns16550_serial_probe, 488 .probe = ns16550_serial_probe,
475 .ops = &ns16550_serial_ops, 489 .ops = &ns16550_serial_ops,
490#if !CONFIG_IS_ENABLED(OF_CONTROL)
476 .flags = DM_FLAG_PRE_RELOC, 491 .flags = DM_FLAG_PRE_RELOC,
492#endif
477}; 493};
478#endif 494#endif
479#endif /* SERIAL_PRESENT */ 495#endif /* SERIAL_PRESENT */
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index 665cca85cb..3ded62732d 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -62,7 +62,7 @@ static int serial_check_stdout(const void *blob, struct udevice **devp)
62 * anyway. 62 * anyway.
63 */ 63 */
64 if (node > 0 && !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node), 64 if (node > 0 && !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node),
65 devp)) { 65 devp, false)) {
66 if (!device_probe(*devp)) 66 if (!device_probe(*devp))
67 return 0; 67 return 0;
68 } 68 }
diff --git a/drivers/serial/serial_ar933x.c b/drivers/serial/serial_ar933x.c
index e91a5f7b24..5249c55398 100644
--- a/drivers/serial/serial_ar933x.c
+++ b/drivers/serial/serial_ar933x.c
@@ -189,7 +189,6 @@ U_BOOT_DRIVER(serial_ar933x) = {
189 .priv_auto_alloc_size = sizeof(struct ar933x_serial_priv), 189 .priv_auto_alloc_size = sizeof(struct ar933x_serial_priv),
190 .probe = ar933x_serial_probe, 190 .probe = ar933x_serial_probe,
191 .ops = &ar933x_serial_ops, 191 .ops = &ar933x_serial_ops,
192 .flags = DM_FLAG_PRE_RELOC,
193}; 192};
194 193
195#ifdef CONFIG_DEBUG_UART_AR933X 194#ifdef CONFIG_DEBUG_UART_AR933X
diff --git a/drivers/serial/serial_arc.c b/drivers/serial/serial_arc.c
index 925f0c2555..980b38d2a1 100644
--- a/drivers/serial/serial_arc.c
+++ b/drivers/serial/serial_arc.c
@@ -128,7 +128,6 @@ U_BOOT_DRIVER(serial_arc) = {
128 .ofdata_to_platdata = arc_serial_ofdata_to_platdata, 128 .ofdata_to_platdata = arc_serial_ofdata_to_platdata,
129 .probe = arc_serial_probe, 129 .probe = arc_serial_probe,
130 .ops = &arc_serial_ops, 130 .ops = &arc_serial_ops,
131 .flags = DM_FLAG_PRE_RELOC,
132}; 131};
133 132
134#ifdef CONFIG_DEBUG_ARC_SERIAL 133#ifdef CONFIG_DEBUG_ARC_SERIAL
diff --git a/drivers/serial/serial_bcm283x_mu.c b/drivers/serial/serial_bcm283x_mu.c
index 1f87f0cb28..bd1d89ec83 100644
--- a/drivers/serial/serial_bcm283x_mu.c
+++ b/drivers/serial/serial_bcm283x_mu.c
@@ -199,6 +199,8 @@ U_BOOT_DRIVER(serial_bcm283x_mu) = {
199 .platdata_auto_alloc_size = sizeof(struct bcm283x_mu_serial_platdata), 199 .platdata_auto_alloc_size = sizeof(struct bcm283x_mu_serial_platdata),
200 .probe = bcm283x_mu_serial_probe, 200 .probe = bcm283x_mu_serial_probe,
201 .ops = &bcm283x_mu_serial_ops, 201 .ops = &bcm283x_mu_serial_ops,
202#if !CONFIG_IS_ENABLED(OF_CONTROL)
202 .flags = DM_FLAG_PRE_RELOC, 203 .flags = DM_FLAG_PRE_RELOC,
204#endif
203 .priv_auto_alloc_size = sizeof(struct bcm283x_mu_priv), 205 .priv_auto_alloc_size = sizeof(struct bcm283x_mu_priv),
204}; 206};
diff --git a/drivers/serial/serial_bcm283x_pl011.c b/drivers/serial/serial_bcm283x_pl011.c
index 54fc9b5b39..2527bb8b1c 100644
--- a/drivers/serial/serial_bcm283x_pl011.c
+++ b/drivers/serial/serial_bcm283x_pl011.c
@@ -90,6 +90,8 @@ U_BOOT_DRIVER(bcm283x_pl011_uart) = {
90 .platdata_auto_alloc_size = sizeof(struct pl01x_serial_platdata), 90 .platdata_auto_alloc_size = sizeof(struct pl01x_serial_platdata),
91 .probe = pl01x_serial_probe, 91 .probe = pl01x_serial_probe,
92 .ops = &bcm283x_pl011_serial_ops, 92 .ops = &bcm283x_pl011_serial_ops,
93#if !CONFIG_IS_ENABLED(OF_CONTROL)
93 .flags = DM_FLAG_PRE_RELOC, 94 .flags = DM_FLAG_PRE_RELOC,
95#endif
94 .priv_auto_alloc_size = sizeof(struct pl01x_priv), 96 .priv_auto_alloc_size = sizeof(struct pl01x_priv),
95}; 97};
diff --git a/drivers/serial/serial_bcm6345.c b/drivers/serial/serial_bcm6345.c
index ee5d561bfd..a0e709a11e 100644
--- a/drivers/serial/serial_bcm6345.c
+++ b/drivers/serial/serial_bcm6345.c
@@ -264,7 +264,6 @@ U_BOOT_DRIVER(bcm6345_serial) = {
264 .probe = bcm6345_serial_probe, 264 .probe = bcm6345_serial_probe,
265 .priv_auto_alloc_size = sizeof(struct bcm6345_serial_priv), 265 .priv_auto_alloc_size = sizeof(struct bcm6345_serial_priv),
266 .ops = &bcm6345_serial_ops, 266 .ops = &bcm6345_serial_ops,
267 .flags = DM_FLAG_PRE_RELOC,
268}; 267};
269 268
270#ifdef CONFIG_DEBUG_UART_BCM6345 269#ifdef CONFIG_DEBUG_UART_BCM6345
diff --git a/drivers/serial/serial_efi.c b/drivers/serial/serial_efi.c
index 1b54d1880f..dd3e511fc9 100644
--- a/drivers/serial/serial_efi.c
+++ b/drivers/serial/serial_efi.c
@@ -152,5 +152,4 @@ U_BOOT_DRIVER(serial_efi) = {
152 .priv_auto_alloc_size = sizeof(struct serial_efi_priv), 152 .priv_auto_alloc_size = sizeof(struct serial_efi_priv),
153 .probe = serial_efi_probe, 153 .probe = serial_efi_probe,
154 .ops = &serial_efi_ops, 154 .ops = &serial_efi_ops,
155 .flags = DM_FLAG_PRE_RELOC,
156}; 155};
diff --git a/drivers/serial/serial_intel_mid.c b/drivers/serial/serial_intel_mid.c
index bdb5adb2a4..39bd40e68b 100644
--- a/drivers/serial/serial_intel_mid.c
+++ b/drivers/serial/serial_intel_mid.c
@@ -64,5 +64,4 @@ U_BOOT_DRIVER(serial_intel_mid) = {
64 .priv_auto_alloc_size = sizeof(struct NS16550), 64 .priv_auto_alloc_size = sizeof(struct NS16550),
65 .probe = mid_serial_probe, 65 .probe = mid_serial_probe,
66 .ops = &ns16550_serial_ops, 66 .ops = &ns16550_serial_ops,
67 .flags = DM_FLAG_PRE_RELOC,
68}; 67};
diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c
index 6106c1f9ec..a357b00d28 100644
--- a/drivers/serial/serial_lpuart.c
+++ b/drivers/serial/serial_lpuart.c
@@ -540,5 +540,4 @@ U_BOOT_DRIVER(serial_lpuart) = {
540 .platdata_auto_alloc_size = sizeof(struct lpuart_serial_platdata), 540 .platdata_auto_alloc_size = sizeof(struct lpuart_serial_platdata),
541 .probe = lpuart_serial_probe, 541 .probe = lpuart_serial_probe,
542 .ops = &lpuart_serial_ops, 542 .ops = &lpuart_serial_ops,
543 .flags = DM_FLAG_PRE_RELOC,
544}; 543};
diff --git a/drivers/serial/serial_meson.c b/drivers/serial/serial_meson.c
index dbb853735f..b3dad77aa2 100644
--- a/drivers/serial/serial_meson.c
+++ b/drivers/serial/serial_meson.c
@@ -132,7 +132,6 @@ U_BOOT_DRIVER(serial_meson) = {
132 .of_match = meson_serial_ids, 132 .of_match = meson_serial_ids,
133 .probe = meson_serial_probe, 133 .probe = meson_serial_probe,
134 .ops = &meson_serial_ops, 134 .ops = &meson_serial_ops,
135 .flags = DM_FLAG_PRE_RELOC,
136 .ofdata_to_platdata = meson_serial_ofdata_to_platdata, 135 .ofdata_to_platdata = meson_serial_ofdata_to_platdata,
137 .platdata_auto_alloc_size = sizeof(struct meson_serial_platdata), 136 .platdata_auto_alloc_size = sizeof(struct meson_serial_platdata),
138}; 137};
diff --git a/drivers/serial/serial_mvebu_a3700.c b/drivers/serial/serial_mvebu_a3700.c
index ce26d2bd15..7e4cd6c4b4 100644
--- a/drivers/serial/serial_mvebu_a3700.c
+++ b/drivers/serial/serial_mvebu_a3700.c
@@ -129,7 +129,6 @@ U_BOOT_DRIVER(serial_mvebu) = {
129 .platdata_auto_alloc_size = sizeof(struct mvebu_platdata), 129 .platdata_auto_alloc_size = sizeof(struct mvebu_platdata),
130 .probe = mvebu_serial_probe, 130 .probe = mvebu_serial_probe,
131 .ops = &mvebu_serial_ops, 131 .ops = &mvebu_serial_ops,
132 .flags = DM_FLAG_PRE_RELOC,
133}; 132};
134 133
135#ifdef CONFIG_DEBUG_MVEBU_A3700_UART 134#ifdef CONFIG_DEBUG_MVEBU_A3700_UART
diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c
index e586c18cf0..7e4e6d36b8 100644
--- a/drivers/serial/serial_mxc.c
+++ b/drivers/serial/serial_mxc.c
@@ -354,7 +354,9 @@ U_BOOT_DRIVER(serial_mxc) = {
354#endif 354#endif
355 .probe = mxc_serial_probe, 355 .probe = mxc_serial_probe,
356 .ops = &mxc_serial_ops, 356 .ops = &mxc_serial_ops,
357#if !CONFIG_IS_ENABLED(OF_CONTROL)
357 .flags = DM_FLAG_PRE_RELOC, 358 .flags = DM_FLAG_PRE_RELOC,
359#endif
358}; 360};
359#endif 361#endif
360 362
diff --git a/drivers/serial/serial_omap.c b/drivers/serial/serial_omap.c
index af3c755f96..ee6ad9c9e5 100644
--- a/drivers/serial/serial_omap.c
+++ b/drivers/serial/serial_omap.c