- virtio implementation and supporting patches
- DM_FLAG_PRE_RELOC fixes - regmap improvements - minor buildman and sandbox things -----BEGIN PGP SIGNATURE----- iQFFBAABCgAvFiEEslwAIq+Gp8wWVbYnfxc6PpAIreYFAlvsxt8RHHNqZ0BjaHJv bWl1bS5vcmcACgkQfxc6PpAIrebPtQgAxR8bKdTNODUuVrw5OUIl40ziKQvNIlG5 uiVsQLDI7Cd9D3Yls8yNffXqkNcQj+0/MJa38UZsm32c/uR4PU0zyFxpz4mwgyXk ZMrJ15AEAxf4IOHjbh52sNgR2mw+PeP9A3NO5LnZAMd/rnRF2MgBTy28FvjsBlNn z4OUjUpNv4ePND0QQ1EoGPlYotYPASEw8iK1pc5L+Rwq/ponAnNqegKIxQtiMugY kLtuFe0JJ704T20UkwYvI8LsnuB50ANRLLMyy5JLy1UtCpS24cc86ml49IKk3pqb v4GbnMI67s7S+Imzm4A7Mg8fgGnkkpLqacI3gnlpbIPkLrqRM2C20g== =RORj -----END PGP SIGNATURE----- Merge tag 'pull-14nov18' of git://git.denx.de/u-boot-dm - virtio implementation and supporting patches - DM_FLAG_PRE_RELOC fixes - regmap improvements - minor buildman and sandbox things
This commit is contained in:
commit
1d6edcbfed
171 changed files with 7490 additions and 347 deletions
19
Documentation/devicetree/bindings/misc/gdsys,iocon_fpga.txt
Normal file
19
Documentation/devicetree/bindings/misc/gdsys,iocon_fpga.txt
Normal file
|
@ -0,0 +1,19 @@
|
|||
gdsys IHS FPGA for CON devices
|
||||
|
||||
The gdsys IHS FPGA is the main FPGA on gdsys CON devices. This driver provides
|
||||
support for enabling and starting the FPGA, as well as verifying working bus
|
||||
communication.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "gdsys,iocon_fpga"
|
||||
- reset-gpios: List of GPIOs controlling the FPGA's reset
|
||||
- done-gpios: List of GPIOs notifying whether the FPGA's reconfiguration is
|
||||
done
|
||||
|
||||
Example:
|
||||
|
||||
FPGA0 {
|
||||
compatible = "gdsys,iocon_fpga";
|
||||
reset-gpios = <&PPCPCA 26 0>;
|
||||
done-gpios = <&GPIO_VB0 19 0>;
|
||||
};
|
19
Documentation/devicetree/bindings/misc/gdsys,iocpu_fpga.txt
Normal file
19
Documentation/devicetree/bindings/misc/gdsys,iocpu_fpga.txt
Normal file
|
@ -0,0 +1,19 @@
|
|||
gdsys IHS FPGA for CPU devices
|
||||
|
||||
The gdsys IHS FPGA is the main FPGA on gdsys CPU devices. This driver provides
|
||||
support for enabling and starting the FPGA, as well as verifying working bus
|
||||
communication.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "gdsys,iocpu_fpga"
|
||||
- reset-gpios: List of GPIOs controlling the FPGA's reset
|
||||
- done-gpios: List of GPIOs notifying whether the FPGA's reconfiguration is
|
||||
done
|
||||
|
||||
Example:
|
||||
|
||||
FPGA0 {
|
||||
compatible = "gdsys,iocpu_fpga";
|
||||
reset-gpios = <&PPCPCA 26 0>;
|
||||
done-gpios = <&GPIO_VB0 19 0>;
|
||||
};
|
16
Documentation/devicetree/bindings/misc/gdsys,soc.txt
Normal file
16
Documentation/devicetree/bindings/misc/gdsys,soc.txt
Normal file
|
@ -0,0 +1,16 @@
|
|||
gdsys soc bus driver
|
||||
|
||||
This driver provides a simple interface for the busses associated with gdsys
|
||||
IHS FPGAs. The bus itself contains devices whose register maps are contained
|
||||
within the FPGA's register space.
|
||||
|
||||
Required properties:
|
||||
- fpga: A phandle to the controlling IHS FPGA
|
||||
|
||||
Example:
|
||||
|
||||
FPGA0BUS: fpga0bus {
|
||||
compatible = "gdsys,soc";
|
||||
ranges = <0x0 0xe0600000 0x00004000>;
|
||||
fpga = <&FPGA0>;
|
||||
};
|
|
@ -110,6 +110,11 @@ config SANDBOX
|
|||
imply LIBAVB
|
||||
imply CMD_AVB
|
||||
imply UDP_FUNCTION_FASTBOOT
|
||||
imply VIRTIO_MMIO
|
||||
imply VIRTIO_PCI
|
||||
imply VIRTIO_SANDBOX
|
||||
imply VIRTIO_BLK
|
||||
imply VIRTIO_NET
|
||||
|
||||
config SH
|
||||
bool "SuperH architecture"
|
||||
|
@ -120,6 +125,7 @@ config X86
|
|||
select CREATE_ARCH_SYMLINK
|
||||
select DM
|
||||
select DM_PCI
|
||||
select HAVE_ARCH_IOMAP
|
||||
select HAVE_PRIVATE_LIBGCC
|
||||
select OF_CONTROL
|
||||
select PCI
|
||||
|
|
|
@ -1496,6 +1496,7 @@ source "board/broadcom/bcmns2/Kconfig"
|
|||
source "board/cavium/thunderx/Kconfig"
|
||||
source "board/cirrus/edb93xx/Kconfig"
|
||||
source "board/eets/pdu001/Kconfig"
|
||||
source "board/emulation/qemu-arm/Kconfig"
|
||||
source "board/freescale/ls2080a/Kconfig"
|
||||
source "board/freescale/ls2080aqds/Kconfig"
|
||||
source "board/freescale/ls2080ardb/Kconfig"
|
||||
|
|
|
@ -417,7 +417,6 @@ U_BOOT_DRIVER(stm32mp_bsec) = {
|
|||
.ofdata_to_platdata = stm32mp_bsec_ofdata_to_platdata,
|
||||
.platdata_auto_alloc_size = sizeof(struct stm32mp_bsec_platdata),
|
||||
.ops = &stm32mp_bsec_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
/* bsec IP is not present in device tee, manage IP address by platdata */
|
||||
|
|
|
@ -547,6 +547,28 @@ __BUILD_CLRSETBITS(bwlq, sfx, end, type)
|
|||
#define __to_cpu(v) (v)
|
||||
#define cpu_to__(v) (v)
|
||||
|
||||
#define out_arch(type, endian, a, v) __raw_write##type(cpu_to_##endian(v),a)
|
||||
#define in_arch(type, endian, a) endian##_to_cpu(__raw_read##type(a))
|
||||
|
||||
#define out_le64(a, v) out_arch(q, le64, a, v)
|
||||
#define out_le32(a, v) out_arch(l, le32, a, v)
|
||||
#define out_le16(a, v) out_arch(w, le16, a, v)
|
||||
|
||||
#define in_le64(a) in_arch(q, le64, a)
|
||||
#define in_le32(a) in_arch(l, le32, a)
|
||||
#define in_le16(a) in_arch(w, le16, a)
|
||||
|
||||
#define out_be64(a, v) out_arch(q, be64, a, v)
|
||||
#define out_be32(a, v) out_arch(l, be32, a, v)
|
||||
#define out_be16(a, v) out_arch(w, be16, a, v)
|
||||
|
||||
#define in_be64(a) in_arch(q, be64, a)
|
||||
#define in_be32(a) in_arch(l, be32, a)
|
||||
#define in_be16(a) in_arch(w, be16, a)
|
||||
|
||||
#define out_8(a, v) __raw_writeb(v, a)
|
||||
#define in_8(a) __raw_readb(a)
|
||||
|
||||
BUILD_CLRSETBITS(b, 8, _, u8)
|
||||
BUILD_CLRSETBITS(w, le16, le16, u16)
|
||||
BUILD_CLRSETBITS(w, be16, be16, u16)
|
||||
|
|
|
@ -9,9 +9,11 @@
|
|||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <image.h>
|
||||
#include <u-boot/zlib.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/csr.h>
|
||||
#include <dm/device.h>
|
||||
#include <dm/root.h>
|
||||
#include <u-boot/zlib.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
@ -57,6 +59,13 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
|
|||
/* we assume that the kernel is in place */
|
||||
printf("\nStarting kernel ...\n\n");
|
||||
|
||||
/*
|
||||
* Call remove function of all devices with a removal flag set.
|
||||
* This may be useful for last-stage operations, like cancelling
|
||||
* of DMA operation or releasing device internal buffers.
|
||||
*/
|
||||
dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
|
||||
|
||||
cleanup_before_linux();
|
||||
|
||||
if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
|
||||
|
|
|
@ -174,7 +174,12 @@ void *os_malloc(size_t length)
|
|||
struct os_mem_hdr *hdr;
|
||||
int page_size = getpagesize();
|
||||
|
||||
hdr = mmap(NULL, length + page_size,
|
||||
/*
|
||||
* Use an address that is hopefully available to us so that pointers
|
||||
* to this memory are fairly obvious. If we end up with a different
|
||||
* address, that's fine too.
|
||||
*/
|
||||
hdr = mmap((void *)0x10000000, length + page_size,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (hdr == MAP_FAILED)
|
||||
|
|
|
@ -186,6 +186,10 @@
|
|||
compatible = "denx,u-boot-fdt-test";
|
||||
};
|
||||
|
||||
h-test {
|
||||
compatible = "denx,u-boot-fdt-test1";
|
||||
};
|
||||
|
||||
clocks {
|
||||
clk_fixed: clk-fixed {
|
||||
compatible = "fixed-clock";
|
||||
|
@ -346,14 +350,17 @@
|
|||
|
||||
cpu-test1 {
|
||||
compatible = "sandbox,cpu_sandbox";
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
cpu-test2 {
|
||||
compatible = "sandbox,cpu_sandbox";
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
cpu-test3 {
|
||||
compatible = "sandbox,cpu_sandbox";
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
misc-test {
|
||||
|
@ -525,7 +532,7 @@
|
|||
|
||||
syscon@0 {
|
||||
compatible = "sandbox,syscon0";
|
||||
reg = <0x10 4>;
|
||||
reg = <0x10 16>;
|
||||
};
|
||||
|
||||
syscon@1 {
|
||||
|
@ -712,6 +719,14 @@
|
|||
sandbox_tee {
|
||||
compatible = "sandbox,tee";
|
||||
};
|
||||
|
||||
sandbox_virtio1 {
|
||||
compatible = "sandbox,virtio1";
|
||||
};
|
||||
|
||||
sandbox_virtio2 {
|
||||
compatible = "sandbox,virtio2";
|
||||
};
|
||||
};
|
||||
|
||||
#include "sandbox_pmic.dtsi"
|
||||
|
|
|
@ -203,4 +203,5 @@ U_BOOT_DRIVER(cpu_x86_baytrail_drv) = {
|
|||
.bind = cpu_x86_bind,
|
||||
.probe = cpu_x86_baytrail_probe,
|
||||
.ops = &cpu_x86_baytrail_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
|
|
@ -764,4 +764,5 @@ U_BOOT_DRIVER(cpu_x86_broadwell_drv) = {
|
|||
.probe = cpu_x86_broadwell_probe,
|
||||
.ops = &cpu_x86_broadwell_ops,
|
||||
.priv_auto_alloc_size = sizeof(struct cpu_broadwell_priv),
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
|
|
@ -94,4 +94,5 @@ U_BOOT_DRIVER(cpu_x86_drv) = {
|
|||
.of_match = cpu_x86_ids,
|
||||
.bind = cpu_x86_bind,
|
||||
.ops = &cpu_x86_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
|
|
@ -478,4 +478,5 @@ U_BOOT_DRIVER(cpu_x86_model_206ax_drv) = {
|
|||
.bind = cpu_x86_bind,
|
||||
.probe = cpu_x86_model_206ax_probe,
|
||||
.ops = &cpu_x86_model_206ax_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
|
|
@ -44,5 +44,4 @@ U_BOOT_DRIVER(tangier_sysreset) = {
|
|||
.id = UCLASS_SYSRESET,
|
||||
.of_match = tangier_sysreset_ids,
|
||||
.ops = &tangier_sysreset_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
|
|
@ -241,6 +241,72 @@ static inline void sync(void)
|
|||
#define __iormb() dmb()
|
||||
#define __iowmb() dmb()
|
||||
|
||||
/*
|
||||
* Read/write from/to an (offsettable) iomem cookie. It might be a PIO
|
||||
* access or a MMIO access, these functions don't care. The info is
|
||||
* encoded in the hardware mapping set up by the mapping functions
|
||||
* (or the cookie itself, depending on implementation and hw).
|
||||
*
|
||||
* The generic routines don't assume any hardware mappings, and just
|
||||
* encode the PIO/MMIO as part of the cookie. They coldly assume that
|
||||
* the MMIO IO mappings are not in the low address range.
|
||||
*
|
||||
* Architectures for which this is not true can't use this generic
|
||||
* implementation and should do their own copy.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We assume that all the low physical PIO addresses (0-0xffff) always
|
||||
* PIO. That means we can do some sanity checks on the low bits, and
|
||||
* don't need to just take things for granted.
|
||||
*/
|
||||
#define PIO_RESERVED 0x10000UL
|
||||
|
||||
/*
|
||||
* Ugly macros are a way of life.
|
||||
*/
|
||||
#define IO_COND(addr, is_pio, is_mmio) do { \
|
||||
unsigned long port = (unsigned long __force)addr; \
|
||||
if (port >= PIO_RESERVED) { \
|
||||
is_mmio; \
|
||||
} else { \
|
||||
is_pio; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static inline u8 ioread8(const volatile void __iomem *addr)
|
||||
{
|
||||
IO_COND(addr, return inb(port), return readb(addr));
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
static inline u16 ioread16(const volatile void __iomem *addr)
|
||||
{
|
||||
IO_COND(addr, return inw(port), return readw(addr));
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
static inline u32 ioread32(const volatile void __iomem *addr)
|
||||
{
|
||||
IO_COND(addr, return inl(port), return readl(addr));
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
static inline void iowrite8(u8 value, volatile void __iomem *addr)
|
||||
{
|
||||
IO_COND(addr, outb(value, port), writeb(value, addr));
|
||||
}
|
||||
|
||||
static inline void iowrite16(u16 value, volatile void __iomem *addr)
|
||||
{
|
||||
IO_COND(addr, outw(value, port), writew(value, addr));
|
||||
}
|
||||
|
||||
static inline void iowrite32(u32 value, volatile void __iomem *addr)
|
||||
{
|
||||
IO_COND(addr, outl(value, port), writel(value, addr));
|
||||
}
|
||||
|
||||
#include <asm-generic/io.h>
|
||||
|
||||
#endif /* _ASM_IO_H */
|
||||
|
|
13
board/emulation/qemu-arm/Kconfig
Normal file
13
board/emulation/qemu-arm/Kconfig
Normal file
|
@ -0,0 +1,13 @@
|
|||
if TARGET_QEMU_ARM_32BIT || TARGET_QEMU_ARM_64BIT
|
||||
|
||||
config SYS_TEXT_BASE
|
||||
default 0x00000000
|
||||
|
||||
config BOARD_SPECIFIC_OPTIONS # dummy
|
||||
def_bool y
|
||||
imply VIRTIO_MMIO
|
||||
imply VIRTIO_PCI
|
||||
imply VIRTIO_NET
|
||||
imply VIRTIO_BLK
|
||||
|
||||
endif
|
|
@ -2,8 +2,12 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Tuomas Tynkkynen
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <fdtdec.h>
|
||||
#include <virtio_types.h>
|
||||
#include <virtio.h>
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
#include <asm/armv8/mmu.h>
|
||||
|
@ -58,6 +62,12 @@ struct mm_region *mem_map = qemu_arm64_mem_map;
|
|||
|
||||
int board_init(void)
|
||||
{
|
||||
/*
|
||||
* Make sure virtio bus is enumerated so that peripherals
|
||||
* on the virtio bus can be discovered by their drivers
|
||||
*/
|
||||
virtio_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,5 +18,16 @@ config SYS_TEXT_BASE
|
|||
config BOARD_SPECIFIC_OPTIONS # dummy
|
||||
def_bool y
|
||||
imply SYS_NS16550
|
||||
imply VIRTIO_MMIO
|
||||
imply VIRTIO_NET
|
||||
imply VIRTIO_BLK
|
||||
imply CMD_PING
|
||||
imply CMD_FS_GENERIC
|
||||
imply DOS_PARTITION
|
||||
imply EFI_PARTITION
|
||||
imply ISO_PARTITION
|
||||
imply CMD_EXT2
|
||||
imply CMD_EXT4
|
||||
imply CMD_FAT
|
||||
|
||||
endif
|
||||
|
|
|
@ -4,12 +4,21 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <fdtdec.h>
|
||||
#include <virtio_types.h>
|
||||
#include <virtio.h>
|
||||
|
||||
#define MROM_FDT_ADDR 0x1020
|
||||
|
||||
int board_init(void)
|
||||
{
|
||||
/*
|
||||
* Make sure virtio bus is enumerated so that peripherals
|
||||
* on the virtio bus can be discovered by their drivers
|
||||
*/
|
||||
virtio_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,5 +21,8 @@ config BOARD_SPECIFIC_OPTIONS # dummy
|
|||
select X86_RESET_VECTOR
|
||||
select QEMU
|
||||
select BOARD_ROMSIZE_KB_1024
|
||||
imply VIRTIO_PCI
|
||||
imply VIRTIO_NET
|
||||
imply VIRTIO_BLK
|
||||
|
||||
endif
|
||||
|
|
|
@ -1065,6 +1065,13 @@ config CMD_USB_MASS_STORAGE
|
|||
help
|
||||
USB mass storage support
|
||||
|
||||
config CMD_VIRTIO
|
||||
bool "virtio"
|
||||
depends on VIRTIO
|
||||
default y if VIRTIO
|
||||
help
|
||||
VirtIO block device support
|
||||
|
||||
config CMD_AXI
|
||||
bool "axi"
|
||||
depends on AXI
|
||||
|
|
|
@ -135,6 +135,7 @@ obj-$(CONFIG_CMD_UBI) += ubi.o
|
|||
obj-$(CONFIG_CMD_UBIFS) += ubifs.o
|
||||
obj-$(CONFIG_CMD_UNIVERSE) += universe.o
|
||||
obj-$(CONFIG_CMD_UNZIP) += unzip.o
|
||||
obj-$(CONFIG_CMD_VIRTIO) += virtio.o
|
||||
obj-$(CONFIG_CMD_LZMADEC) += lzmadec.o
|
||||
|
||||
obj-$(CONFIG_CMD_USB) += usb.o disk.o
|
||||
|
|
|
@ -51,7 +51,6 @@ int sata_probe(int devnum)
|
|||
{
|
||||
#ifdef CONFIG_AHCI
|
||||
struct udevice *dev;
|
||||
struct udevice *blk;
|
||||
int rc;
|
||||
|
||||
rc = uclass_get_device(UCLASS_AHCI, devnum, &dev);
|
||||
|
@ -67,14 +66,6 @@ int sata_probe(int devnum)
|
|||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
rc = blk_get_from_parent(dev, &blk);
|
||||
if (!rc) {
|
||||
struct blk_desc *desc = dev_get_uclass_platdata(blk);
|
||||
|
||||
if (desc->lba > 0 && desc->blksz > 0)
|
||||
part_init(desc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return sata_initialize() < 0 ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
|
||||
|
|
38
cmd/virtio.c
Normal file
38
cmd/virtio.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2018, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
|
||||
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <dm.h>
|
||||
#include <virtio_types.h>
|
||||
#include <virtio.h>
|
||||
|
||||
static int virtio_curr_dev;
|
||||
|
||||
static int do_virtio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
if (argc == 2 && !strcmp(argv[1], "scan")) {
|
||||
/* make sure all virtio devices are enumerated */
|
||||
virtio_init();
|
||||
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
return blk_common_cmd(argc, argv, IF_TYPE_VIRTIO, &virtio_curr_dev);
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
virtio, 8, 1, do_virtio,
|
||||
"virtio block devices sub-system",
|
||||
"scan - initialize virtio bus\n"
|
||||
"virtio info - show all available virtio block devices\n"
|
||||
"virtio device [dev] - show or set current virtio block device\n"
|
||||
"virtio part [dev] - print partition table of one or all virtio block devices\n"
|
||||
"virtio read addr blk# cnt - read `cnt' blocks starting at block\n"
|
||||
" `blk#' to memory address `addr'\n"
|
||||
"virtio write addr blk# cnt - write `cnt' blocks starting at block\n"
|
||||
" `blk#' from memory address `addr'"
|
||||
);
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <console.h>
|
||||
#include <cpu.h>
|
||||
#include <dm.h>
|
||||
#include <environment.h>
|
||||
#include <fdtdec.h>
|
||||
|
@ -165,6 +166,33 @@ static int print_resetinfo(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_DISPLAY_CPUINFO) && CONFIG_IS_ENABLED(CPU)
|
||||
static int print_cpuinfo(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
char desc[512];
|
||||
int ret;
|
||||
|
||||
ret = uclass_first_device_err(UCLASS_CPU, &dev);
|
||||
if (ret) {
|
||||
debug("%s: Could not get CPU device (err = %d)\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = cpu_get_desc(dev, desc, sizeof(desc));
|
||||
if (ret) {
|
||||
debug("%s: Could not get CPU description (err = %d)\n",
|
||||
dev->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
printf("CPU: %s\n", desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int announce_dram_init(void)
|
||||
{
|
||||
puts("DRAM: ");
|
||||
|
|
|
@ -226,9 +226,7 @@ static int usb_stor_probe_device(struct usb_device *udev)
|
|||
blkdev->lun = lun;
|
||||
|
||||
ret = usb_stor_get_info(udev, data, blkdev);
|
||||
if (ret == 1)
|
||||
ret = blk_prepare_device(dev);
|
||||
if (!ret) {
|
||||
if (ret == 1) {
|
||||
usb_max_devs++;
|
||||
debug("%s: Found device %p\n", __func__, udev);
|
||||
} else {
|
||||
|
|
|
@ -6,7 +6,6 @@ CONFIG_TARGET_IMX8QXP_MEK=y
|
|||
CONFIG_NR_DRAM_BANKS=3
|
||||
CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/imx8qxp_mek/imximage.cfg"
|
||||
CONFIG_BOOTDELAY=3
|
||||
# CONFIG_DISPLAY_CPUINFO is not set
|
||||
CONFIG_CMD_CPU=y
|
||||
# CONFIG_CMD_IMPORTENV is not set
|
||||
CONFIG_CMD_CLK=y
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
CONFIG_ARM=y
|
||||
CONFIG_ARM_SMCCC=y
|
||||
CONFIG_ARCH_QEMU=y
|
||||
CONFIG_SYS_TEXT_BASE=0x00000000
|
||||
CONFIG_TARGET_QEMU_ARM_64BIT=y
|
||||
CONFIG_AHCI=y
|
||||
CONFIG_DISTRO_DEFAULTS=y
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
CONFIG_ARM=y
|
||||
CONFIG_ARM_SMCCC=y
|
||||
CONFIG_ARCH_QEMU=y
|
||||
CONFIG_SYS_TEXT_BASE=0x00000000
|
||||
CONFIG_TARGET_QEMU_ARM_32BIT=y
|
||||
CONFIG_AHCI=y
|
||||
CONFIG_DISTRO_DEFAULTS=y
|
||||
|
|
|
@ -171,6 +171,7 @@ CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y
|
|||
CONFIG_VIDEO_SANDBOX_SDL=y
|
||||
CONFIG_OSD=y
|
||||
CONFIG_SANDBOX_OSD=y
|
||||
# CONFIG_VIRTIO_BLK is not set
|
||||
CONFIG_FS_CBFS=y
|
||||
CONFIG_FS_CRAMFS=y
|
||||
CONFIG_CMD_DHRYSTONE=y
|
||||
|
|
|
@ -150,6 +150,9 @@ void dev_print (struct blk_desc *dev_desc)
|
|||
dev_desc->revision,
|
||||
dev_desc->product);
|
||||
break;
|
||||
case IF_TYPE_VIRTIO:
|
||||
printf("%s VirtIO Block Device\n", dev_desc->vendor);
|
||||
break;
|
||||
case IF_TYPE_DOC:
|
||||
puts("device type DOC\n");
|
||||
return;
|
||||
|
@ -281,6 +284,9 @@ static void print_part_header(const char *type, struct blk_desc *dev_desc)
|
|||
case IF_TYPE_NVME:
|
||||
puts ("NVMe");
|
||||
break;
|
||||
case IF_TYPE_VIRTIO:
|
||||
puts("VirtIO");
|
||||
break;
|
||||
default:
|
||||
puts ("UNKNOWN");
|
||||
break;
|
||||
|
|
253
doc/README.virtio
Normal file
253
doc/README.virtio
Normal file
|
@ -0,0 +1,253 @@
|
|||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||
|
||||
VirtIO Support
|
||||
==============
|
||||
|
||||
This document describes the information about U-Boot support for VirtIO [1]
|
||||
devices, including supported boards, build instructions, driver details etc.
|
||||
|
||||
What's VirtIO?
|
||||
--------------
|
||||
VirtIO is a virtualization standard for network and disk device drivers where
|
||||
just the guest's device driver "knows" it is running in a virtual environment,
|
||||
and cooperates with the hypervisor. This enables guests to get high performance
|
||||
network and disk operations, and gives most of the performance benefits of
|
||||
paravirtualization. In the U-Boot case, the guest is U-Boot itself, while the
|
||||
virtual environment are normally QEMU [2] targets like ARM, RISC-V and x86.
|
||||
|
||||
Status
|
||||
------
|
||||
VirtIO can use various different buses, aka transports as described in the
|
||||
spec. While VirtIO devices are commonly implemented as PCI devices on x86,
|
||||
embedded devices models like ARM/RISC-V, which does not normally come with
|
||||
PCI support might use simple memory mapped device (MMIO) instead of the PCI
|
||||
device. The memory mapped virtio device behaviour is based on the PCI device
|
||||
specification. Therefore most operations including device initialization,
|
||||
queues configuration and buffer transfers are nearly identical. Both MMIO
|
||||
and PCI transport options are supported in U-Boot.
|
||||
|
||||
The VirtIO spec defines a lots of VirtIO device types, however at present only
|
||||
network and block device, the most two commonly used devices, are supported.
|
||||
|
||||
The following QEMU targets are supported.
|
||||
|
||||
- qemu_arm_defconfig
|
||||
- qemu_arm64_defconfig
|
||||
- qemu-riscv32_defconfig
|
||||
- qemu-riscv64_defconfig
|
||||
- qemu-x86_defconfig
|
||||
- qemu-x86_64_defconfig
|
||||
|
||||
Note ARM and RISC-V targets are configured with VirtIO MMIO transport driver,
|
||||
and on x86 it's the PCI transport driver.
|
||||
|
||||
Build Instructions
|
||||
------------------
|
||||
Building U-Boot for pre-configured QEMU targets is no different from others.
|
||||
For example, we can do the following with the CROSS_COMPILE environment
|
||||
variable being properly set to a working toolchain for ARM:
|
||||
|
||||
$ make qemu_arm_defconfig
|
||||
$ make
|
||||
|
||||
You can even create a QEMU ARM target with VirtIO devices showing up on both
|
||||
MMIO and PCI buses. In this case, you can enable the PCI transport driver
|
||||
from 'make menuconfig':
|
||||
|
||||
Device Drivers --->
|
||||
...
|
||||
VirtIO Drivers --->
|
||||
...
|
||||
[*] PCI driver for virtio devices
|
||||
|
||||
Other drivers are at the same location and can be tuned to suit the needs.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
It is required that QEMU v2.5.0+ should be used to test U-Boot VirtIO support
|
||||
on QEMU ARM and x86, and v2.12.0+ on QEMU RISC-V.
|
||||
|
||||
Testing
|
||||
-------
|
||||
The following QEMU command line is used to get U-Boot up and running with
|
||||
VirtIO net and block devices on ARM.
|
||||
|
||||
$ qemu-system-arm -nographic -machine virt -bios u-boot.bin \
|
||||
-netdev tap,ifname=tap0,id=net0 \
|
||||
-device virtio-net-device,netdev=net0 \
|
||||
-drive if=none,file=test.img,format=raw,id=hd0 \
|
||||
-device virtio-blk-device,drive=hd0
|
||||
|
||||
On x86, command is slightly different to create PCI VirtIO devices.
|
||||
|
||||
$ qemu-system-i386 -nographic -bios u-boot.rom \
|
||||
-netdev tap,ifname=tap0,id=net0 \
|
||||
-device virtio-net-pci,netdev=net0 \
|
||||
-drive if=none,file=test.img,format=raw,id=hd0 \
|
||||
-device virtio-blk-pci,drive=hd0
|
||||
|
||||
Additional net and block devices can be created by appending more '-device'
|
||||
parameters. It is also possible to specify both MMIO and PCI VirtIO devices.
|
||||
For example, the following commnad creates 3 VirtIO devices, with 1 on MMIO
|
||||
and 2 on PCI bus.
|
||||
|
||||
$ qemu-system-arm -nographic -machine virt -bios u-boot.bin \
|
||||
-netdev tap,ifname=tap0,id=net0 \
|
||||
-device virtio-net-pci,netdev=net0 \
|
||||
-drive if=none,file=test0.img,format=raw,id=hd0 \
|
||||
-device virtio-blk-device,drive=hd0 \
|
||||
-drive if=none,file=test1.img,format=raw,id=hd1 \
|
||||
-device virtio-blk-pci,drive=hd1
|
||||
|
||||
By default QEMU creates VirtIO legacy devices by default. To create non-legacy
|
||||
(aka modern) devices, pass additional device property/value pairs like below:
|
||||
|
||||
$ qemu-system-i386 -nographic -bios u-boot.rom \
|
||||
-netdev tap,ifname=tap0,id=net0 \
|
||||
-device virtio-net-pci,netdev=net0,disable-legacy=true,disable-modern=false \
|
||||
-drive if=none,file=test.img,format=raw,id=hd0 \
|
||||
-device virtio-blk-pci,drive=hd0,disable-legacy=true,disable-modern=false
|
||||
|
||||
A 'virtio' command is provided in U-Boot shell.
|
||||
|
||||
=> virtio
|
||||
virtio - virtio block devices sub-system
|
||||
|
||||
Usage:
|
||||
virtio scan - initialize virtio bus
|
||||
virtio info - show all available virtio block devices
|
||||
virtio device [dev] - show or set current virtio block device
|
||||
virtio part [dev] - print partition table of one or all virtio block devices
|
||||
virtio read addr blk# cnt - read `cnt' blocks starting at block
|
||||
`blk#' to memory address `addr'
|
||||
virtio write addr blk# cnt - write `cnt' blocks starting at block
|
||||
`blk#' from memory address `addr'
|
||||
|
||||
To probe all the VirtIO devices, type:
|
||||
|
||||
=> virtio scan
|
||||
|
||||
Then we can show the connected block device details by:
|
||||
|
||||
=> virtio info
|
||||
Device 0: QEMU VirtIO Block Device
|
||||
Type: Hard Disk
|
||||
Capacity: 4096.0 MB = 4.0 GB (8388608 x 512)
|
||||
|
||||
And list the directories and files on the disk by:
|
||||
|
||||
=> ls virtio 0 /
|
||||
<DIR> 4096 .
|
||||
<DIR> 4096 ..
|
||||
<DIR> 16384 lost+found
|
||||
<DIR> 4096 dev
|
||||
<DIR> 4096 proc
|
||||
<DIR> 4096 sys
|
||||
<DIR> 4096 var
|
||||
<DIR> 4096 etc
|
||||
<DIR> 4096 usr
|
||||
<SYM> 7 bin
|
||||
<SYM> 8 sbin
|
||||
<SYM> 7 lib
|
||||
<SYM> 9 lib64
|
||||
<DIR> 4096 run
|
||||
<DIR> 4096 boot
|
||||
<DIR> 4096 home
|
||||
<DIR> 4096 media
|
||||
<DIR> 4096 mnt
|
||||
<DIR> 4096 opt
|
||||
<DIR> 4096 root
|
||||
<DIR> 4096 srv
|
||||
<DIR> 4096 tmp
|
||||
0 .autorelabel
|
||||
|
||||
Driver Internals
|
||||
----------------
|
||||
There are 3 level of drivers in the VirtIO driver family.
|
||||
|
||||
+---------------------------------------+
|
||||
| virtio device drivers |
|
||||
| +-------------+ +------------+ |
|
||||
| | virtio-net | | virtio-blk | |
|
||||
| +-------------+ +------------+ |
|
||||
+---------------------------------------+
|
||||
+---------------------------------------+
|
||||
| virtio transport drivers |
|
||||
| +-------------+ +------------+ |
|
||||
| | virtio-mmio | | virtio-pci | |
|
||||
| +-------------+ +------------+ |
|
||||
+---------------------------------------+
|
||||
+----------------------+
|
||||
| virtio uclass driver |
|
||||
+----------------------+
|
||||
|
||||
The root one is the virtio uclass driver (virtio-uclass.c), which does lots of
|
||||
common stuff for the transport drivers (virtio_mmio.c, virtio_pci.c). The real
|
||||
virtio device is discovered in the transport driver's probe() method, and its
|
||||
device ID is saved in the virtio uclass's private data of the transport device.
|
||||
Then in the virtio uclass's post_probe() method, the real virtio device driver
|
||||
(virtio_net.c, virtio_blk.c) is bound if there is a match on the device ID.
|
||||
|
||||
The child_post_bind(), child_pre_probe() and child_post_probe() methods of the
|
||||
virtio uclass driver help bring the virtio device driver online. They do things
|
||||
like acknowledging device, feature negotiation, etc, which are really common
|
||||
for all virtio devices.
|
||||
|
||||
The transport drivers provide a set of ops (struct dm_virtio_ops) for the real
|
||||
virtio device driver to call. These ops APIs's parameter is designed to remind
|
||||
the caller to pass the correct 'struct udevice' id of the virtio device, eg:
|
||||
|
||||
int virtio_get_status(struct udevice *vdev, u8 *status)
|
||||
|
||||
So the parameter 'vdev' indicates the device should be the real virtio device.
|
||||
But we also have an API like:
|
||||
|
||||
struct virtqueue *vring_create_virtqueue(unsigned int index, unsigned int num,
|
||||
unsigned int vring_align,
|
||||
struct udevice *udev)
|
||||
|
||||
Here the parameter 'udev' indicates the device should be the transport device.
|
||||
Similar naming is applied in other functions that are even not APIs, eg:
|
||||
|
||||
static int virtio_uclass_post_probe(struct udevice *udev)
|
||||
static int virtio_uclass_child_pre_probe(struct udevice *vdev)
|
||||
|
||||
So it's easy to tell which device these functions are operating on.
|
||||
|
||||
Development Flow
|
||||
----------------
|
||||
At present only VirtIO network card (device ID 1) and block device (device
|
||||
ID 2) are supported. If you want to develop new driver for new devices,
|
||||
please follow the guideline below.
|
||||
|
||||
1. add new device ID in virtio.h
|
||||
#define VIRTIO_ID_XXX X
|
||||
|
||||
2. update VIRTIO_ID_MAX_NUM to be the largest device ID plus 1
|
||||
|
||||
3. add new driver name string in virtio.h
|
||||
#define VIRTIO_XXX_DRV_NAME "virtio-xxx"
|
||||
|
||||
4. create a new driver with name set to the name string above
|
||||
U_BOOT_DRIVER(virtio_xxx) = {
|
||||
.name = VIRTIO_XXX_DRV_NAME,
|
||||
...
|
||||
.remove = virtio_reset,
|
||||
.flags = DM_FLAG_ACTIVE_DMA,
|
||||
}
|
||||
|
||||
Note the driver needs to provide the remove method and normally this can be
|
||||
hooked to virtio_reset(). The driver flags should contain DM_FLAG_ACTIVE_DMA
|
||||
for the remove method to be called before jumping to OS.
|
||||
|
||||
5. provide bind() method in the driver, where virtio_driver_features_init()
|
||||
should be called for driver to negotiate feature support with the device.
|
||||
|
||||
6. do funny stuff with the driver
|
||||
|
||||
References
|
||||
----------
|
||||
[1] http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.pdf
|
||||
[2] https://www.qemu.org
|
|
@ -830,10 +830,18 @@ Pre-Relocation Support
|
|||
----------------------
|
||||
|
||||
For pre-relocation we simply call the driver model init function. Only
|
||||
drivers marked with DM_FLAG_PRE_RELOC or the device tree
|
||||
'u-boot,dm-pre-reloc' flag are initialised prior to relocation. This helps
|
||||
to reduce the driver model overhead. This flag applies to SPL and TPL as
|
||||
well, if device tree is enabled there.
|
||||
drivers marked with DM_FLAG_PRE_RELOC or the device tree 'u-boot,dm-pre-reloc'
|
||||
property are initialised prior to relocation. This helps to reduce the driver
|
||||
model overhead. This flag applies to SPL and TPL as well, if device tree is
|
||||
enabled (CONFIG_OF_CONTROL) there.
|
||||
|
||||
Note when device tree is enabled, the device tree 'u-boot,dm-pre-reloc'
|
||||
property can provide better control granularity on which device is bound
|
||||
before relocation. While with DM_FLAG_PRE_RELOC flag of the driver all
|
||||
devices with the same driver are bound, which requires allocation a large
|
||||
amount of memory. When device tree is not used, DM_FLAG_PRE_RELOC is the
|
||||
only way for statically declared devices via U_BOOT_DEVICE() to be bound
|
||||
prior to relocation.
|
||||
|
||||
It is possible to limit this to specific relocation steps, by using
|
||||
the more specialized 'u-boot,dm-spl' and 'u-boot,dm-tpl' flags
|
||||
|
|
|
@ -112,6 +112,8 @@ source "drivers/usb/Kconfig"
|
|||
|
||||
source "drivers/video/Kconfig"
|
||||
|
||||
source "drivers/virtio/Kconfig"
|
||||
|
||||
source "drivers/w1/Kconfig"
|
||||
|
||||
source "drivers/w1-eeprom/Kconfig"
|
||||
|
|
|
@ -14,6 +14,7 @@ obj-$(CONFIG_$(SPL_TPL_)SERIAL_SUPPORT) += serial/
|
|||
obj-$(CONFIG_$(SPL_TPL_)SPI_FLASH_SUPPORT) += mtd/spi/
|
||||
obj-$(CONFIG_$(SPL_TPL_)SPI_SUPPORT) += spi/
|
||||
obj-$(CONFIG_$(SPL_TPL_)TIMER) += timer/
|
||||
obj-$(CONFIG_$(SPL_TPL_)VIRTIO) += virtio/
|
||||
obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox/
|
||||
obj-$(CONFIG_$(SPL_)REMOTEPROC) += remoteproc/
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ static const char *if_typename_str[IF_TYPE_COUNT] = {
|
|||
[IF_TYPE_HOST] = "host",
|
||||
[IF_TYPE_NVME] = "nvme",
|
||||
[IF_TYPE_EFI] = "efi",
|
||||
[IF_TYPE_VIRTIO] = "virtio",
|
||||
};
|
||||
|
||||
static 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] = {
|
|||
[IF_TYPE_HOST] = UCLASS_ROOT,
|
||||
[IF_TYPE_NVME] = UCLASS_NVME,
|
||||
[IF_TYPE_EFI] = UCLASS_EFI,
|
||||
[IF_TYPE_VIRTIO] = UCLASS_VIRTIO,
|
||||
};
|
||||
|
||||
static 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,
|
|||
return ops->erase(dev, start, blkcnt);
|
||||
}
|
||||
|
||||
int blk_prepare_device(struct udevice *dev)
|
||||
{
|
||||
struct blk_desc *desc = dev_get_uclass_platdata(dev);
|
||||
|
||||
part_init(desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blk_get_from_parent(struct udevice *parent, struct udevice **devp)
|
||||
{
|
||||
struct udevice *dev;
|
||||
|
@ -526,7 +519,7 @@ int blk_find_max_devnum(enum if_type if_type)
|
|||
return max_devnum;
|
||||
}
|
||||
|
||||
static int blk_next_free_devnum(enum if_type if_type)
|
||||
int blk_next_free_devnum(enum if_type if_type)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -644,8 +637,20 @@ int blk_unbind_all(int if_type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int blk_post_probe(struct udevice *dev)
|
||||
{
|
||||
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT)
|
||||
struct blk_desc *desc = dev_get_uclass_platdata(dev);
|
||||
|
||||
part_init(desc);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UCLASS_DRIVER(blk) = {
|
||||
.id = UCLASS_BLK,
|
||||
.name = "blk",
|
||||
.post_probe = blk_post_probe,
|
||||
.per_device_platdata_auto_alloc_size = sizeof(struct blk_desc),
|
||||
};
|
||||
|
|
|
@ -1169,8 +1169,6 @@ static int ide_blk_probe(struct udevice *udev)
|
|||
BLK_REV_SIZE);
|
||||
desc->revision[BLK_REV_SIZE] = '\0';
|
||||
|
||||
part_init(desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ static unsigned long host_block_read(struct udevice *dev,
|
|||
unsigned long start, lbaint_t blkcnt,
|
||||
void *buffer)
|
||||
{
|
||||
struct host_block_dev *host_dev = dev_get_priv(dev);
|
||||
struct host_block_dev *host_dev = dev_get_platdata(dev);
|
||||
struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
|
||||
|
||||
#else
|
||||
|
@ -64,7 +64,7 @@ static unsigned long host_block_write(struct udevice *dev,
|
|||
unsigned long start, lbaint_t blkcnt,
|
||||
const void *buffer)
|
||||
{
|
||||
struct host_block_dev *host_dev = dev_get_priv(dev);
|
||||
struct host_block_dev *host_dev = dev_get_platdata(dev);
|
||||
struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
|
||||
#else
|
||||
static unsigned long host_block_write(struct blk_desc *block_dev,
|
||||
|
@ -131,17 +131,18 @@ int host_dev_bind(int devnum, char *filename)
|
|||
os_lseek(fd, 0, OS_SEEK_END) / 512, &dev);
|
||||
if (ret)
|
||||
goto err_file;
|
||||
|
||||
host_dev = dev_get_platdata(dev);
|
||||
host_dev->fd = fd;
|
||||
host_dev->filename = fname;
|
||||
|
||||
ret = device_probe(dev);
|
||||
if (ret) {
|
||||
device_unbind(dev);
|
||||
goto err_file;
|
||||
}
|
||||
|
||||
host_dev = dev_get_priv(dev);
|
||||
host_dev->fd = fd;
|
||||
host_dev->filename = fname;
|
||||
|
||||
return blk_prepare_device(dev);
|
||||
return 0;
|
||||
err_file:
|
||||
os_close(fd);
|
||||
err:
|
||||
|
@ -226,7 +227,7 @@ U_BOOT_DRIVER(sandbox_host_blk) = {
|
|||
.name = "sandbox_host_blk",
|
||||
.id = UCLASS_BLK,
|
||||
.ops = &sandbox_host_blk_ops,
|
||||
.priv_auto_alloc_size = sizeof(struct host_block_dev),
|
||||
.platdata_auto_alloc_size = sizeof(struct host_block_dev),
|
||||
};
|
||||
#else
|
||||
U_BOOT_LEGACY_BLK(sandbox_host) = {
|
||||
|
|
|
@ -352,7 +352,6 @@ static const struct udevice_id socfpga_a10_clk_match[] = {
|
|||
U_BOOT_DRIVER(socfpga_a10_clk) = {
|
||||
.name = "clk-a10",
|
||||
.id = UCLASS_CLK,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
.of_match = socfpga_a10_clk_match,
|
||||
.ops = &socfpga_a10_clk_ops,
|
||||
.bind = socfpga_a10_clk_bind,
|
||||
|
|
|
@ -418,7 +418,6 @@ U_BOOT_DRIVER(pic32_clk) = {
|
|||
.name = "pic32_clk",
|
||||
.id = UCLASS_CLK,
|
||||
.of_match = pic32_clk_ids,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
.ops = &pic32_pic32_clk_ops,
|
||||
.probe = pic32_clk_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct pic32_clk_priv),
|
||||
|
|
|
@ -480,7 +480,6 @@ U_BOOT_DRIVER(zynq_clk) = {
|
|||
.name = "zynq_clk",
|
||||
.id = UCLASS_CLK,
|
||||
.of_match = zynq_clk_ids,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
.ops = &zynq_clk_ops,
|
||||
.priv_auto_alloc_size = sizeof(struct zynq_clk_priv),
|
||||
.probe = zynq_clk_probe,
|
||||
|
|
|
@ -201,7 +201,6 @@ U_BOOT_DRIVER(exynos7420_clk_topc) = {
|
|||
.probe = exynos7420_clk_topc_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct exynos7420_clk_topc_priv),
|
||||
.ops = &exynos7420_clk_topc_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
static const struct udevice_id exynos7420_clk_top0_compat[] = {
|
||||
|
@ -216,7 +215,6 @@ U_BOOT_DRIVER(exynos7420_clk_top0) = {
|
|||
.probe = exynos7420_clk_top0_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct exynos7420_clk_top0_priv),
|
||||
.ops = &exynos7420_clk_top0_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
static const struct udevice_id exynos7420_clk_peric1_compat[] = {
|
||||
|
@ -229,5 +227,4 @@ U_BOOT_DRIVER(exynos7420_clk_peric1) = {
|
|||
.id = UCLASS_CLK,
|
||||
.of_match = exynos7420_clk_peric1_compat,
|
||||
.ops = &exynos7420_clk_peric1_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
|
|
@ -134,5 +134,4 @@ U_BOOT_DRIVER(clk_owl) = {
|
|||
.ops = &owl_clk_ops,
|
||||
.priv_auto_alloc_size = sizeof(struct owl_clk_priv),
|
||||
.probe = owl_clk_probe,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
|
|
@ -834,5 +834,5 @@ int dev_enable_by_path(const char *path)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
return lists_bind_fdt(parent, node, NULL);
|
||||
return lists_bind_fdt(parent, node, NULL, false);
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ void dm_dump_uclass(void)
|
|||
printf("uclass %d: %s\n", id, uc->uc_drv->name);
|
||||
if (list_empty(&uc->dev_head))
|
||||
continue;
|
||||
list_for_each_entry(dev, &uc->dev_head, uclass_node) {
|
||||
uclass_foreach_dev(dev, uc) {
|
||||
dm_display_line(dev, i);
|
||||
i++;
|
||||
}
|
||||
|
|
|
@ -122,7 +122,8 @@ static int driver_check_compatible(const struct udevice_id *of_match,
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp)
|
||||
int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp,
|
||||
bool pre_reloc_only)
|
||||
{
|
||||
struct driver *driver = ll_entry_start(struct driver, driver);
|
||||
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)
|
|||
if (entry == driver + n_ents)
|
||||
continue;
|
||||
|
||||
if (pre_reloc_only) {
|
||||
if (!dm_ofnode_pre_reloc(node) &&
|
||||
!(entry->flags & DM_FLAG_PRE_RELOC))
|
||||
return 0;
|
||||
}
|
||||
|
||||
pr_debug(" - found match at '%s'\n", entry->name);
|
||||
ret = device_bind_with_driver_data(parent, entry, name,
|
||||
id->data, node, &dev);
|
||||
|
|
|
@ -831,8 +831,10 @@ int ofnode_write_prop(ofnode node, const char *propname, int len,
|
|||
return -ENOMEM;
|
||||
|
||||
new->name = strdup(propname);
|
||||
if (!new->name)
|
||||
if (!new->name) {
|
||||
free(new);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
new->value = (void *)value;
|
||||
new->length = len;
|
||||
|
|
|
@ -17,6 +17,12 @@
|
|||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/**
|
||||
* regmap_alloc() - Allocate a regmap with a given number of ranges.
|
||||
*
|
||||
* @count: Number of ranges to be allocated for the regmap.
|
||||
* Return: A pointer to the newly allocated regmap, or NULL on error.
|
||||
*/
|
||||
static struct regmap *regmap_alloc(int count)
|
||||
{
|
||||
struct regmap *map;
|
||||
|
@ -50,6 +56,58 @@ int regmap_init_mem_platdata(struct udevice *dev, fdt_val_t *reg, int count,
|
|||
return 0;
|
||||
}
|
||||
#else
|
||||
/**
|
||||
* init_range() - Initialize a single range of a regmap
|
||||
* @node: Device node that will use the map in question
|
||||
* @range: Pointer to a regmap_range structure that will be initialized
|
||||
* @addr_len: The length of the addr parts of the reg property
|
||||
* @size_len: The length of the size parts of the reg property
|
||||
* @index: The index of the range to initialize
|
||||
*
|
||||
* This function will read the necessary 'reg' information from the device tree
|
||||
* (the 'addr' part, and the 'length' part), and initialize the range in
|
||||
* quesion.
|
||||
*
|
||||
* Return: 0 if OK, -ve on error
|
||||
*/
|
||||
static int init_range(ofnode node, struct regmap_range *range, int addr_len,
|
||||
int size_len, int index)
|
||||
{
|
||||
fdt_size_t sz;
|
||||
struct resource r;
|
||||
|
||||
if (of_live_active()) {
|
||||
int ret;
|
||||
|
||||
ret = of_address_to_resource(ofnode_to_np(node),
|
||||
index, &r);
|
||||
if (ret) {
|
||||
debug("%s: Could not read resource of range %d (ret = %d)\n",
|
||||
ofnode_get_name(node), index, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
range->start = r.start;
|
||||
range->size = r.end - r.start + 1;
|
||||
} else {
|
||||
int offset = ofnode_to_offset(node);
|
||||
|
||||
range->start = fdtdec_get_addr_size_fixed(gd->fdt_blob, offset,
|
||||
"reg", index,
|
||||
addr_len, size_len,
|
||||
&sz, true);
|
||||
if (range->start == FDT_ADDR_T_NONE) {
|
||||
debug("%s: Could not read start of range %d\n",
|
||||
ofnode_get_name(node), index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
range->size = sz;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int regmap_init_mem(ofnode node, struct regmap **mapp)
|
||||
{
|
||||
struct regmap_range *range;
|
||||
|
@ -58,19 +116,41 @@ int regmap_init_mem(ofnode node, struct regmap **mapp)
|
|||
int addr_len, size_len, both_len;
|
||||
int len;
|
||||
int index;
|
||||
struct resource r;
|
||||
|
||||
addr_len = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
|
||||
if (addr_len < 0) {
|
||||
debug("%s: Error while reading the addr length (ret = %d)\n",
|
||||
ofnode_get_name(node), addr_len);
|
||||
return addr_len;
|
||||
}
|
||||
|
||||
size_len = ofnode_read_simple_size_cells(ofnode_get_parent(node));
|
||||
if (size_len < 0) {
|
||||
debug("%s: Error while reading the size length: (ret = %d)\n",
|
||||
ofnode_get_name(node), size_len);
|
||||
return size_len;
|
||||
}
|
||||
|
||||
both_len = addr_len + size_len;
|
||||
if (!both_len) {
|
||||
debug("%s: Both addr and size length are zero\n",
|
||||
ofnode_get_name(node));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
len = ofnode_read_size(node, "reg");
|
||||
if (len < 0)
|
||||
if (len < 0) {
|
||||
debug("%s: Error while reading reg size (ret = %d)\n",
|
||||
ofnode_get_name(node), len);
|
||||
return len;
|
||||
}
|
||||
len /= sizeof(fdt32_t);
|
||||
count = len / both_len;
|
||||
if (!count)
|
||||
if (!count) {
|
||||
debug("%s: Not enough data in reg property\n",
|
||||
ofnode_get_name(node));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
map = regmap_alloc(count);
|
||||
if (!map)
|
||||
|
@ -78,19 +158,21 @@ int regmap_init_mem(ofnode node, struct regmap **mapp)
|
|||
|
||||
for (range = map->ranges, index = 0; count > 0;
|
||||
count--, range++, index++) {
|
||||
fdt_size_t sz;
|
||||
if (of_live_active()) {
|
||||
of_address_to_resource(ofnode_to_np(node), index, &r);
|
||||
range->start = r.start;
|
||||
range->size = r.end - r.start + 1;
|
||||
} else {
|
||||
range->start = fdtdec_get_addr_size_fixed(gd->fdt_blob,
|
||||
ofnode_to_offset(node), "reg", index,
|
||||
addr_len, size_len, &sz, true);
|
||||
range->size = sz;
|
||||
}
|
||||
int ret = init_range(node, range, addr_len, size_len, index);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ofnode_read_bool(node, "little-endian"))
|
||||
map->endianness = REGMAP_LITTLE_ENDIAN;
|
||||
else if (ofnode_read_bool(node, "big-endian"))
|
||||
map->endianness = REGMAP_BIG_ENDIAN;
|
||||
else if (ofnode_read_bool(node, "native-endian"))
|
||||
map->endianness = REGMAP_NATIVE_ENDIAN;
|
||||
else /* Default: native endianness */
|
||||
map->endianness = REGMAP_NATIVE_ENDIAN;
|
||||
|
||||
*mapp = map;
|
||||
|
||||
return 0;
|
||||
|
@ -115,24 +197,218 @@ int regmap_uninit(struct regmap *map)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int regmap_read(struct regmap *map, uint offset, uint *valp)
|
||||
static inline u8 __read_8(u8 *addr, enum regmap_endianness_t endianness)
|
||||
{
|
||||
u32 *ptr = map_physmem(map->ranges[0].start + offset, 4, MAP_NOCACHE);
|
||||
return readb(addr);
|
||||
}
|
||||
|
||||
*valp = le32_to_cpu(readl(ptr));
|
||||
static inline u16 __read_16(u16 *addr, enum regmap_endianness_t endianness)
|
||||
{
|
||||
switch (endianness) {
|
||||
case REGMAP_LITTLE_ENDIAN:
|
||||
return in_le16(addr);
|
||||
case REGMAP_BIG_ENDIAN:
|
||||
return in_be16(addr);
|
||||
case REGMAP_NATIVE_ENDIAN:
|
||||
return readw(addr);
|
||||
}
|
||||
|
||||
return readw(addr);
|
||||
}
|
||||
|
||||
static inline u32 __read_32(u32 *addr, enum regmap_endianness_t endianness)
|
||||
{
|
||||
switch (endianness) {
|
||||
case REGMAP_LITTLE_ENDIAN:
|
||||
return in_le32(addr);
|
||||
case REGMAP_BIG_ENDIAN:
|
||||
return in_be32(addr);
|
||||
case REGMAP_NATIVE_ENDIAN:
|
||||
return readl(addr);
|
||||
}
|
||||
|
||||
return readl(addr);
|
||||
}
|
||||
|
||||
#if defined(in_le64) && defined(in_be64) && defined(readq)
|
||||
static inline u64 __read_64(u64 *addr, enum regmap_endianness_t endianness)
|
||||
{
|
||||
switch (endianness) {
|
||||
case REGMAP_LITTLE_ENDIAN:
|
||||
return in_le64(addr);
|
||||
case REGMAP_BIG_ENDIAN:
|
||||
return in_be64(addr);
|
||||
case REGMAP_NATIVE_ENDIAN:
|
||||
return readq(addr);
|
||||
}
|
||||
|
||||
return readq(addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset,
|
||||
void *valp, size_t val_len)
|
||||
{
|
||||
struct regmap_range *range;
|
||||
void *ptr;
|
||||
|
||||
if (range_num >= map->range_count) {
|
||||
debug("%s: range index %d larger than range count\n",
|
||||
__func__, range_num);
|
||||
return -ERANGE;
|
||||
}
|
||||
range = &map->ranges[range_num];
|
||||
|
||||
ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE);
|
||||
|
||||
if (offset + val_len > range->size) {
|
||||
debug("%s: offset/size combination invalid\n", __func__);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
switch (val_len) {
|
||||
case REGMAP_SIZE_8:
|
||||
*((u8 *)valp) = __read_8(ptr, map->endianness);
|
||||
break;
|
||||
case REGMAP_SIZE_16:
|
||||
*((u16 *)valp) = __read_16(ptr, map->endianness);
|
||||
break;
|
||||
case REGMAP_SIZE_32:
|
||||
*((u32 *)valp) = __read_32(ptr, map->endianness);
|
||||
break;
|
||||
#if defined(in_le64) && defined(in_be64) && defined(readq)
|
||||
case REGMAP_SIZE_64:
|
||||
*((u64 *)valp) = __read_64(ptr, map->endianness);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
debug("%s: regmap size %zu unknown\n", __func__, val_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int regmap_write(struct regmap *map, uint offset, uint val)
|
||||
int regmap_raw_read(struct regmap *map, uint offset, void *valp, size_t val_len)
|
||||
{
|
||||
u32 *ptr = map_physmem(map->ranges[0].start + offset, 4, MAP_NOCACHE);
|
||||
return regmap_raw_read_range(map, 0, offset, valp, val_len);
|
||||
}
|
||||
|
||||
writel(cpu_to_le32(val), ptr);
|
||||
int regmap_read(struct regmap *map, uint offset, uint *valp)
|
||||
{
|
||||
return regmap_raw_read(map, offset, valp, REGMAP_SIZE_32);
|
||||
}
|
||||
|
||||
static inline void __write_8(u8 *addr, const u8 *val,
|
||||
enum regmap_endianness_t endianness)
|
||||
{
|
||||
writeb(*val, addr);
|
||||
}
|
||||
|
||||
static inline void __write_16(u16 *addr, const u16 *val,
|
||||
enum regmap_endianness_t endianness)
|
||||
{
|
||||
switch (endianness) {
|
||||
case REGMAP_NATIVE_ENDIAN:
|
||||
writew(*val, addr);
|
||||
break;
|
||||
case REGMAP_LITTLE_ENDIAN:
|
||||
out_le16(addr, *val);
|
||||
break;
|
||||
case REGMAP_BIG_ENDIAN:
|
||||
out_be16(addr, *val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __write_32(u32 *addr, const u32 *val,
|
||||
enum regmap_endianness_t endianness)
|
||||
{
|
||||
switch (endianness) {
|
||||
case REGMAP_NATIVE_ENDIAN:
|
||||
writel(*val, addr);
|
||||
break;
|
||||
case REGMAP_LITTLE_ENDIAN:
|
||||
out_le32(addr, *val);
|
||||
break;
|
||||
case REGMAP_BIG_ENDIAN:
|
||||
out_be32(addr, *val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(out_le64) && defined(out_be64) && defined(writeq)
|
||||
static inline void __write_64(u64 *addr, const u64 *val,
|
||||
enum regmap_endianness_t endianness)
|
||||
{
|
||||
switch (endianness) {
|
||||
case REGMAP_NATIVE_ENDIAN:
|
||||
writeq(*val, addr);
|
||||
break;
|
||||
case REGMAP_LITTLE_ENDIAN:
|
||||
out_le64(addr, *val);
|
||||
break;
|
||||
case REGMAP_BIG_ENDIAN:
|
||||
out_be64(addr, *val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset,
|
||||
const void *val, size_t val_len)
|
||||
{
|
||||
struct regmap_range *range;
|
||||
void *ptr;
|
||||
|
||||
if (range_num >= map->range_count) {
|
||||
debug("%s: range index %d larger than range count\n",
|
||||
__func__, range_num);
|
||||
return -ERANGE;
|
||||
}
|
||||
range = &map->ranges[range_num];
|
||||
|
||||
ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE);
|
||||
|
||||
if (offset + val_len > range->size) {
|
||||
debug("%s: offset/size combination invalid\n", __func__);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
switch (val_len) {
|
||||
case REGMAP_SIZE_8:
|
||||
__write_8(ptr, val, map->endianness);
|
||||
break;
|
||||
case REGMAP_SIZE_16:
|
||||
__write_16(ptr, val, map->endianness);
|
||||
break;
|
||||
case REGMAP_SIZE_32:
|
||||
__write_32(ptr, val, map->endianness);
|
||||
break;
|
||||
#if defined(out_le64) && defined(out_be64) && defined(writeq)
|
||||
case REGMAP_SIZE_64:
|
||||
__write_64(ptr, val, map->endianness);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
debug("%s: regmap size %zu unknown\n", __func__, val_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int regmap_raw_write(struct regmap *map, uint offset, const void *val,
|
||||
size_t val_len)
|
||||
{
|
||||
return regmap_raw_write_range(map, 0, offset, val, val_len);
|
||||
}
|
||||
|
||||
int regmap_write(struct regmap *map, uint offset, uint val)
|
||||
{
|
||||
return regmap_raw_write(map, offset, &val, REGMAP_SIZE_32);
|
||||
}
|
||||
|
||||
int regmap_update_bits(struct regmap *map, uint offset, uint mask, uint val)
|
||||
{
|
||||
uint reg;
|
||||
|
|
|
@ -222,14 +222,22 @@ static int dm_scan_fdt_live(struct udevice *parent,
|
|||
int ret = 0, err;
|
||||
|
||||
for (np = node_parent->child; np; np = np->sibling) {
|
||||
if (pre_reloc_only &&
|
||||
!of_find_property(np, "u-boot,dm-pre-reloc", NULL))
|
||||
/* "chosen" node isn't a device itself but may contain some: */
|
||||
if (!strcmp(np->name, "chosen")) {
|
||||
pr_debug("parsing subnodes of \"chosen\"\n");
|
||||
|
||||
err = dm_scan_fdt_live(parent, np, pre_reloc_only);
|
||||
if (err && !ret)
|
||||
ret = err;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!of_device_is_available(np)) {
|
||||
pr_debug(" - ignoring disabled device\n");
|
||||
continue;
|
||||
}
|
||||
err = lists_bind_fdt(parent, np_to_ofnode(np), NULL);
|
||||
err = lists_bind_fdt(parent, np_to_ofnode(np), NULL,
|
||||
pre_reloc_only);
|
||||
if (err && !ret) {
|
||||
ret = err;
|
||||
debug("%s: ret=%d\n", np->name, ret);
|
||||
|
@ -282,14 +290,12 @@ static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (pre_reloc_only &&
|
||||
!dm_fdt_pre_reloc(blob, offset))
|
||||
continue;
|
||||
if (!fdtdec_get_is_enabled(blob, offset)) {
|
||||
pr_debug(" - ignoring disabled device\n");
|
||||
continue;
|
||||
}
|
||||
err = lists_bind_fdt(parent, offset_to_ofnode(offset), NULL);
|
||||
err = lists_bind_fdt(parent, offset_to_ofnode(offset), NULL,
|
||||
pre_reloc_only);
|
||||
if (err && !ret) {
|
||||
ret = err;
|
||||
debug("%s: ret=%d\n", node_name, ret);
|
||||
|
|
|
@ -180,7 +180,7 @@ int dev_get_uclass_index(struct udevice *dev, struct uclass **ucp)
|
|||
if (list_empty(&uc->dev_head))
|
||||
return -ENODEV;
|
||||
|
||||
list_for_each_entry(iter, &uc->dev_head, uclass_node) {
|
||||
uclass_foreach_dev(iter, uc) {
|
||||
if (iter == dev) {
|
||||
if (ucp)
|
||||
*ucp = uc;
|
||||
|
@ -205,7 +205,7 @@ int uclass_find_device(enum uclass_id id, int index, struct udevice **devp)
|
|||
if (list_empty(&uc->dev_head))
|
||||
return -ENODEV;
|
||||
|
||||
list_for_each_entry(dev, &uc->dev_head, uclass_node) {
|
||||
uclass_foreach_dev(dev, uc) {
|
||||
if (!index--) {
|
||||
*devp = dev;
|
||||
return 0;
|
||||
|
@ -259,7 +259,7 @@ int uclass_find_device_by_name(enum uclass_id id, const char *name,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
list_for_each_entry(dev, &uc->dev_head, uclass_node) {
|
||||
uclass_foreach_dev(dev, uc) {
|
||||
if (!strncmp(dev->name, name, strlen(name))) {
|
||||
*devp = dev;
|
||||
return 0;
|
||||
|
@ -284,7 +284,7 @@ int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
list_for_each_entry(dev, &uc->dev_head, uclass_node) {
|
||||
uclass_foreach_dev(dev, uc) {
|
||||
debug(" - %d %d '%s'\n", dev->req_seq, dev->seq, dev->name);
|
||||
if ((find_req_seq ? dev->req_seq : dev->seq) ==
|
||||
seq_or_req_seq) {
|
||||
|
@ -312,7 +312,7 @@ int uclass_find_device_by_of_offset(enum uclass_id id, int node,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
list_for_each_entry(dev, &uc->dev_head, uclass_node) {
|
||||
uclass_foreach_dev(dev, uc) {
|
||||
if (dev_of_offset(dev) == node) {
|
||||
*devp = dev;
|
||||
return 0;
|
||||
|
@ -337,7 +337,7 @@ int uclass_find_device_by_ofnode(enum uclass_id id, ofnode node,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
list_for_each_entry(dev, &uc->dev_head, uclass_node) {
|
||||
uclass_foreach_dev(dev, uc) {
|
||||
log(LOGC_DM, LOGL_DEBUG_CONTENT, " - checking %s\n",
|
||||
dev->name);
|
||||
if (ofnode_equal(dev_ofnode(dev), node)) {
|
||||
|
@ -372,7 +372,7 @@ static int uclass_find_device_by_phandle(enum uclass_id id,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
list_for_each_entry(dev, &uc->dev_head, uclass_node) {
|
||||
uclass_foreach_dev(dev, uc) {
|
||||
uint phandle;
|
||||
|
||||
phandle = dev_read_phandle(dev);
|
||||
|
@ -399,7 +399,7 @@ int uclass_get_device_by_driver(enum uclass_id id,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
list_for_each_entry(dev, &uc->dev_head, uclass_node) {
|
||||
uclass_foreach_dev(dev, uc) {
|
||||
if (dev->driver == find_drv)
|
||||
return uclass_get_device_tail(dev, 0, devp);
|
||||
}
|
||||
|
@ -499,7 +499,7 @@ int uclass_get_device_by_phandle_id(enum uclass_id id, uint phandle_id,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
list_for_each_entry(dev, &uc->dev_head, uclass_node) {
|
||||
uclass_foreach_dev(dev, uc) {
|
||||
uint phandle;
|
||||
|
||||
phandle = dev_read_phandle(dev);
|
||||
|
@ -687,8 +687,19 @@ int uclass_pre_probe_device(struct udevice *dev)
|
|||
|
||||
int uclass_post_probe_device(struct udevice *dev)
|
||||
{
|
||||
struct uclass_driver *uc_drv = dev->uclass->uc_drv;
|
||||
struct uclass_driver *uc_drv;
|
||||
int ret;
|
||||
|
||||
if (dev->parent) {
|
||||
uc_drv = dev->parent->uclass->uc_drv;
|
||||
if (uc_drv->child_post_probe) {
|
||||
ret = uc_drv->child_post_probe(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
uc_drv = dev->uclass->uc_drv;
|
||||
if (uc_drv->post_probe)
|
||||
return uc_drv->post_probe(dev);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm/ofnode.h>
|
||||
#include <dm/util.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <vsprintf.h>
|
||||
|
@ -53,3 +54,27 @@ bool dm_fdt_pre_reloc(const void *blob, int offset)
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dm_ofnode_pre_reloc(ofnode node)
|
||||
{
|
||||
if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
|
||||
return true;
|
||||
|
||||
#ifdef CONFIG_TPL_BUILD
|
||||
if (ofnode_read_bool(node, "u-boot,dm-tpl"))
|
||||
return true;
|
||||
#elif defined(CONFIG_SPL_BUILD)
|
||||
if (ofnode_read_bool(node, "u-boot,dm-spl"))
|
||||
return true;
|
||||
#else
|
||||
/*
|
||||
* In regular builds individual spl and tpl handling both
|
||||
* count as handled pre-relocation for later second init.
|
||||
*/
|
||||
if (ofnode_read_bool(node, "u-boot,dm-spl") ||
|
||||
ofnode_read_bool(node, "u-boot,dm-tpl"))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -262,7 +262,7 @@ static int mpc83xx_cpu_get_desc(struct udevice *dev, char *buf, int size)
|
|||
determine_cpu_data(dev);
|
||||
|
||||
snprintf(buf, size,
|
||||
"CPU: %s, MPC%s%s%s, Rev: %d.%d at %s MHz, CSB: %s MHz\n",
|
||||
"%s, MPC%s%s%s, Rev: %d.%d at %s MHz, CSB: %s MHz",
|
||||
e300_names[priv->e300_type],
|
||||
cpu_type_names[priv->type],
|
||||
priv->is_e_processor ? "E" : "",
|
||||
|
|
|
@ -372,7 +372,9 @@ U_BOOT_DRIVER(gpio_omap) = {
|
|||
.ops = &gpio_omap_ops,
|
||||
.probe = omap_gpio_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct gpio_bank),
|
||||
#if !CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* CONFIG_DM_GPIO */
|
||||
|
|
|
@ -123,6 +123,6 @@ U_BOOT_DRIVER(gpio_stm32) = {
|
|||
.of_match = stm32_gpio_ids,
|
||||
.probe = gpio_stm32_probe,
|
||||
.ops = &gpio_stm32_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC | DM_UC_FLAG_SEQ_ALIAS,
|
||||
.flags = DM_UC_FLAG_SEQ_ALIAS,
|
||||
.priv_auto_alloc_size = sizeof(struct stm32_gpio_priv),
|
||||
};
|
||||
|
|
|
@ -281,5 +281,4 @@ U_BOOT_DRIVER(tegra186_gpio) = {
|
|||
.bind = tegra186_gpio_bind,
|
||||
.probe = tegra186_gpio_probe,
|
||||
.ops = &tegra186_gpio_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
|
|
@ -378,5 +378,4 @@ U_BOOT_DRIVER(gpio_tegra) = {
|
|||
.probe = gpio_tegra_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct tegra_port_info),
|
||||
.ops = &gpio_tegra_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
|
|
@ -925,7 +925,9 @@ U_BOOT_DRIVER(i2c_omap) = {
|
|||
.probe = omap_i2c_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct omap_i2c),
|
||||
.ops = &omap_i2c_ops,
|
||||
#if !CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* CONFIG_DM_I2C */
|
||||
|
|
|
@ -312,4 +312,21 @@ config FS_LOADER
|
|||
The consumer driver would then use this loader to program whatever,
|
||||
ie. the FPGA device.
|
||||
|
||||
config GDSYS_SOC
|
||||
bool "Enable gdsys SOC driver"
|
||||
depends on MISC
|
||||
help
|
||||
Support for gdsys IHS SOC, a simple bus associated with each gdsys
|
||||
IHS (Integrated Hardware Systems) FPGA, which holds all devices whose
|
||||
register maps are contained within the FPGA's register map.
|
||||
|
||||
config IHS_FPGA
|
||||
bool "Enable IHS FPGA driver"
|
||||
depends on MISC
|
||||
help
|
||||
Support IHS (Integrated Hardware Systems) FPGA, the main FPGAs on
|
||||
gdsys devices, which supply the majority of the functionality offered
|
||||
by the devices. This driver supports both CON and CPU variants of the
|
||||
devices, depending on the device tree entry.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -4,11 +4,6 @@
|
|||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
|
||||
obj-$(CONFIG_MISC) += misc-uclass.o
|
||||
obj-$(CONFIG_ALI152X) += ali512x.o
|
||||
obj-$(CONFIG_ALTERA_SYSID) += altera_sysid.o
|
||||
obj-$(CONFIG_ATSHA204A) += atsha204a-i2c.o
|
||||
obj-$(CONFIG_DS4510) += ds4510.o
|
||||
obj-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
obj-$(CONFIG_CROS_EC) += cros_ec.o
|
||||
obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpc.o
|
||||
|
@ -16,46 +11,54 @@ obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
|
|||
obj-$(CONFIG_CROS_EC_SANDBOX) += cros_ec_sandbox.o
|
||||
obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o
|
||||
endif
|
||||
obj-$(CONFIG_FSL_IIM) += fsl_iim.o
|
||||
obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o
|
||||
obj-$(CONFIG_$(SPL_)I2C_EEPROM) += i2c_eeprom.o
|
||||
obj-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o
|
||||
obj-$(CONFIG_IMX8) += imx8/
|
||||
obj-$(CONFIG_MXC_OCOTP) += mxc_ocotp.o
|
||||
obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o
|
||||
obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o
|
||||
obj-$(CONFIG_NS87308) += ns87308.o
|
||||
obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
|
||||
|
||||
ifdef CONFIG_DM_I2C
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
obj-$(CONFIG_SANDBOX) += i2c_eeprom_emul.o
|
||||
endif
|
||||
endif
|
||||
obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o
|
||||
obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o
|
||||
obj-$(CONFIG_LED_STATUS) += status_led.o
|
||||
obj-$(CONFIG_SANDBOX) += swap_case.o
|
||||
ifdef CONFIG_SPL_OF_PLATDATA
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
obj-$(CONFIG_SANDBOX) += spltest_sandbox.o
|
||||
endif
|
||||
endif
|
||||
obj-$(CONFIG_SANDBOX) += syscon_sandbox.o misc_sandbox.o
|
||||
obj-$(CONFIG_TEGRA_CAR) += tegra_car.o
|
||||
obj-$(CONFIG_TEGRA186_BPMP) += tegra186_bpmp.o
|
||||
obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
|
||||
obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
|
||||
obj-$(CONFIG_FSL_SEC_MON) += fsl_sec_mon.o
|
||||
obj-$(CONFIG_PCA9551_LED) += pca9551_led.o
|
||||
obj-$(CONFIG_ALI152X) += ali512x.o
|
||||
obj-$(CONFIG_ALTERA_SYSID) += altera_sysid.o
|
||||
obj-$(CONFIG_ATSHA204A) += atsha204a-i2c.o
|
||||
obj-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o
|
||||
obj-$(CONFIG_DS4510) += ds4510.o
|
||||
obj-$(CONFIG_FSL_DEVICE_DISABLE) += fsl_devdis.o
|
||||
obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o
|
||||
obj-$(CONFIG_QFW) += qfw.o
|
||||
obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o
|
||||
obj-$(CONFIG_STM32_RCC) += stm32_rcc.o
|
||||
obj-$(CONFIG_STM32MP_FUSE) += stm32mp_fuse.o
|
||||
obj-$(CONFIG_SYS_DPAA_QBMAN) += fsl_portals.o
|
||||
obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
|
||||
obj-$(CONFIG_FSL_IIM) += fsl_iim.o
|
||||
obj-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o
|
||||
obj-$(CONFIG_FSL_SEC_MON) += fsl_sec_mon.o
|
||||
obj-$(CONFIG_FS_LOADER) += fs_loader.o
|
||||
obj-$(CONFIG_GDSYS_IOEP) += gdsys_ioep.o
|
||||
obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o
|
||||
obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress_config.o
|
||||
obj-$(CONFIG_GDSYS_SOC) += gdsys_soc.o
|
||||
obj-$(CONFIG_$(SPL_)I2C_EEPROM) += i2c_eeprom.o
|
||||
obj-$(CONFIG_IHS_FPGA) += ihs_fpga.o
|
||||
obj-$(CONFIG_IMX8) += imx8/
|
||||
obj-$(CONFIG_LED_STATUS) += status_led.o
|
||||
obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o
|
||||
obj-$(CONFIG_MPC83XX_SERDES) += mpc83xx_serdes.o
|
||||
obj-$(CONFIG_FS_LOADER) += fs_loader.o
|
||||
obj-$(CONFIG_MXC_OCOTP) += mxc_ocotp.o
|
||||
obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o
|
||||
obj-$(CONFIG_NS87308) += ns87308.o
|
||||
obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o
|
||||
obj-$(CONFIG_PCA9551_LED) += pca9551_led.o
|
||||
obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
|
||||
obj-$(CONFIG_QFW) += qfw.o
|
||||
obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o
|
||||
obj-$(CONFIG_SANDBOX) += swap_case.o
|
||||
obj-$(CONFIG_SANDBOX) += syscon_sandbox.o misc_sandbox.o
|
||||
obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o
|
||||
obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o
|
||||
obj-$(CONFIG_STM32MP_FUSE) += stm32mp_fuse.o
|
||||
obj-$(CONFIG_STM32_RCC) += stm32_rcc.o
|
||||
obj-$(CONFIG_SYS_DPAA_QBMAN) += fsl_portals.o
|
||||
obj-$(CONFIG_TEGRA186_BPMP) += tegra186_bpmp.o
|
||||
obj-$(CONFIG_TEGRA_CAR) += tegra_car.o
|
||||
obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
|
||||
obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress_config.o
|
||||
obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o
|
||||
|
|
74
drivers/misc/gdsys_soc.c
Normal file
74
drivers/misc/gdsys_soc.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2017
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/lists.h>
|
||||
|
||||
#include "gdsys_soc.h"
|
||||
|
||||
/**
|
||||
* struct gdsys_soc_priv - Private data for gdsys soc bus
|
||||
* @fpga: The gdsys IHS FPGA this bus is associated with
|
||||
*/
|
||||
struct gdsys_soc_priv {
|
||||
struct udevice *fpga;
|
||||
};
|
||||
|
||||
static const struct udevice_id gdsys_soc_ids[] = {
|
||||
{ .compatible = "gdsys,soc" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
int gdsys_soc_get_fpga(struct udevice *child, struct udevice **fpga)
|
||||
{
|
||||
struct gdsys_soc_priv *bus_priv;
|
||||
|
||||
if (!child->parent) {
|
||||
debug("%s: Invalid parent\n", child->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!device_is_compatible(child->parent, "gdsys,soc")) {
|
||||
debug("%s: Not child of a gdsys soc\n", child->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bus_priv = dev_get_priv(child->parent);
|
||||
|
||||
*fpga = bus_priv->fpga;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gdsys_soc_probe(struct udevice *dev)
|
||||
{
|
||||
struct gdsys_soc_priv *priv = dev_get_priv(dev);
|
||||
struct udevice *fpga;
|
||||
int res = uclass_get_device_by_phandle(UCLASS_MISC, dev, "fpga",
|
||||
&fpga);
|
||||
if (res == -ENOENT) {
|
||||
debug("%s: Could not find 'fpga' phandle\n", dev->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (res == -ENODEV) {
|
||||
debug("%s: Could not get FPGA device\n", dev->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->fpga = fpga;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_DRIVER(gdsys_soc_bus) = {
|
||||
.name = "gdsys_soc_bus",
|
||||
.id = UCLASS_SIMPLE_BUS,
|
||||
.of_match = gdsys_soc_ids,
|
||||
.probe = gdsys_soc_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct gdsys_soc_priv),
|
||||
};
|
23
drivers/misc/gdsys_soc.h
Normal file
23
drivers/misc/gdsys_soc.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2017
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*/
|
||||
|
||||
#ifndef _GDSYS_SOC_H_
|
||||
#define _GDSYS_SOC_H_
|
||||
|
||||
/**
|
||||
* gdsys_soc_get_fpga() - Retrieve pointer to parent bus' FPGA device
|
||||
* @child: The child device on the FPGA bus needing access to the FPGA.
|
||||
* @fpga: Pointer to the retrieved FPGA device.
|
||||
*
|
||||
* To access their register maps, devices on gdsys soc buses usually have
|
||||
* facilitate the accessor function of the IHS FPGA their parent bus is
|
||||
* attached to. To access the FPGA device from within the bus' children, this
|
||||
* function returns a pointer to it.
|
||||
*
|
||||
* Return: 0 on success, -ve on failure
|
||||
*/
|
||||
int gdsys_soc_get_fpga(struct udevice *child, struct udevice **fpga);
|
||||
#endif /* _GDSYS_SOC_H_ */
|
867
drivers/misc/ihs_fpga.c
Normal file
867
drivers/misc/ihs_fpga.c
Normal file
|
@ -0,0 +1,867 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2017
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*
|
||||
* based on the ioep-fpga driver, which is
|
||||
*
|
||||
* (C) Copyright 2014
|
||||
* Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <regmap.h>
|
||||
#include <asm/gpio.h>
|
||||
|
||||
#include "ihs_fpga.h"
|
||||
|
||||
/**
|
||||
* struct ihs_fpga_priv - Private data structure for IHS FPGA driver
|
||||
* @map: Register map for the FPGA's own register space
|
||||
* @reset_gpio: GPIO to start FPGA reconfiguration
|
||||
* @done_gpio: GPOI to read the 'ready' status of the FPGA
|
||||
*/
|
||||
struct ihs_fpga_priv {
|
||||
struct regmap *map;
|
||||
struct gpio_desc reset_gpio;
|
||||
struct gpio_desc done_gpio;
|
||||
};
|
||||
|
||||
/* Test pattern for reflection test */
|
||||
const u16 REFLECTION_TESTPATTERN = 0xdead;
|
||||
/* Delay (in ms) for each round in the reflection test */
|
||||
const uint REFLECTION_TEST_DELAY = 100;
|
||||
/* Maximum number of rounds in the reflection test */
|
||||
const uint REFLECTION_TEST_ROUNDS = 5;
|
||||
/* Delay (in ms) for each round waiting for the FPGA's done GPIO */
|
||||
const uint FPGA_DONE_WAIT_DELAY = 100;
|
||||
/* Maximum number of rounds for waiting for the FPGA's done GPIO */
|
||||
const uint FPGA_DONE_WAIT_ROUND = 5;
|
||||
|
||||
/**
|
||||
* enum pcb_video_type - Video type of the PCB
|
||||
* @PCB_DVI_SL: Video type is DVI single-link
|
||||
* @PCB_DP_165MPIX: Video type is DisplayPort (165Mpix)
|
||||
* @PCB_DP_300MPIX: Video type is DisplayPort (300Mpix)
|
||||
* @PCB_HDMI: Video type is HDMI
|
||||
* @PCB_DP_1_2: Video type is DisplayPort 1.2
|
||||
* @PCB_HDMI_2_0: Video type is HDMI 2.0
|
||||
*/
|
||||
enum pcb_video_type {
|
||||
PCB_DVI_SL,
|
||||
PCB_DP_165MPIX,
|
||||
PCB_DP_300MPIX,
|
||||
PCB_HDMI,
|
||||
PCB_DP_1_2,
|
||||
PCB_HDMI_2_0,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum pcb_transmission_type - Transmission type of the PCB
|
||||
* @PCB_CAT_1G: Transmission type is 1G Ethernet
|
||||
* @PCB_FIBER_3G: Transmission type is 3G Fiber
|
||||
* @PCB_CAT_10G: Transmission type is 10G Ethernet
|
||||
* @PCB_FIBER_10G: Transmission type is 10G Fiber
|
||||
*/
|
||||
enum pcb_transmission_type {
|
||||
PCB_CAT_1G,
|
||||
PCB_FIBER_3G,
|
||||
PCB_CAT_10G,
|
||||
PCB_FIBER_10G,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum carrier_speed - Speed of the FPGA's carrier
|
||||
* @CARRIER_SPEED_1G: The carrier speed is 1G
|
||||
* @CARRIER_SPEED_2_5G: The carrier speed is 2.5G
|
||||
* @CARRIER_SPEED_3G: The carrier speed is 3G
|
||||
* @CARRIER_SPEED_10G: The carrier speed is 10G
|
||||
*/
|
||||
enum carrier_speed {
|
||||
CARRIER_SPEED_1G,
|
||||
CARRIER_SPEED_3G,
|
||||
CARRIER_SPEED_2_5G = CARRIER_SPEED_3G,
|
||||
CARRIER_SPEED_10G,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ram_config - FPGA's RAM configuration
|
||||
* @RAM_DDR2_32BIT_295MBPS: DDR2 32 bit at 295Mb/s
|
||||
* @RAM_DDR3_32BIT_590MBPS: DDR3 32 bit at 590Mb/s
|
||||
* @RAM_DDR3_48BIT_590MBPS: DDR3 48 bit at 590Mb/s
|
||||
* @RAM_DDR3_64BIT_1800MBPS: DDR3 64 bit at 1800Mb/s
|
||||
* @RAM_DDR3_48BIT_1800MBPS: DDR3 48 bit at 1800Mb/s
|
||||
*/
|
||||
enum ram_config {
|
||||
RAM_DDR2_32BIT_295MBPS,
|
||||
RAM_DDR3_32BIT_590MBPS,
|
||||
RAM_DDR3_48BIT_590MBPS,
|
||||
RAM_DDR3_64BIT_1800MBPS,
|
||||
RAM_DDR3_48BIT_1800MBPS,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum sysclock - Speed of the FPGA's system clock
|
||||
* @SYSCLK_147456: System clock is 147.456 MHz
|
||||
*/
|
||||
enum sysclock {
|
||||
SYSCLK_147456,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct fpga_versions - Data read from the versions register
|
||||
* @video_channel: Is the FPGA for a video channel (true) or main
|
||||
* channel (false) device?
|
||||
* @con_side: Is the FPGA for a CON (true) or a CPU (false) device?
|
||||
* @pcb_video_type: Defines for whch video type the FPGA is configured
|
||||
* @pcb_transmission_type: Defines for which transmission type the FPGA is
|
||||
* configured
|
||||
* @hw_version: Hardware version of the FPGA
|
||||
*/
|
||||
struct fpga_versions {
|
||||
bool video_channel;
|
||||
bool con_side;
|
||||
enum pcb_video_type pcb_video_type;
|
||||
enum pcb_transmission_type pcb_transmission_type;
|
||||
unsigned int hw_version;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct fpga_features - Data read from the features register
|
||||
* @video_channels: Number of video channels supported
|
||||
* @carriers: Number of carrier channels supported
|
||||
* @carrier_speed: Speed of carriers
|
||||
* @ram_config: RAM configuration of FPGA
|
||||
* @sysclock: System clock speed of FPGA
|
||||
* @pcm_tx: Support for PCM transmission
|
||||
* @pcm_rx: Support for PCM reception
|
||||
* @spdif_tx: Support for SPDIF audio transmission
|
||||
* @spdif_rx: Support for SPDIF audio reception
|
||||
* @usb2: Support for transparent USB2.0
|
||||
* @rs232: Support for bidirectional RS232
|
||||
* @compression_type1: Support for compression type 1
|
||||
* @compression_type2: Support for compression type 2
|
||||
* @compression_type3: Support for compression type 3
|
||||
* @interlace: Support for interlace image formats
|
||||
* @osd: Support for a OSD
|
||||
* @compression_pipes: Number of compression pipes supported
|
||||
*/
|
||||
struct fpga_features {
|
||||
u8 video_channels;
|
||||
u8 carriers;
|
||||
enum carrier_speed carrier_speed;
|
||||
enum ram_config ram_config;
|
||||
enum sysclock sysclock;
|
||||
bool pcm_tx;
|
||||
bool pcm_rx;
|
||||
bool spdif_tx;
|
||||
bool spdif_rx;
|
||||
bool usb2;
|
||||
bool rs232;
|
||||
bool compression_type1;
|
||||
bool compression_type2;
|
||||
bool compression_type3;
|
||||
bool interlace;
|
||||
bool osd;
|
||||
bool compression_pipes;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_FLAVOR_GAZERBEAM
|
||||
|
||||
/**
|
||||
* get_versions() - Fill structure with info from version register.
|
||||
* @dev: FPGA device to be queried for information
|
||||
* @versions: Pointer to the structure to fill with information from the
|
||||
* versions register
|
||||
* Return: 0
|
||||
*/
|
||||
static int get_versions(struct udevice *dev, struct fpga_versions *versions)
|
||||
{
|
||||
struct ihs_fpga_priv *priv = dev_get_priv(dev);
|
||||
enum {
|
||||
VERSIONS_FPGA_VIDEO_CHANNEL = BIT(12),
|
||||
VERSIONS_FPGA_CON_SIDE = BIT(13),
|
||||
VERSIONS_FPGA_SC = BIT(14),
|
||||
VERSIONS_PCB_CON = BIT(9),
|
||||
VERSIONS_PCB_SC = BIT(8),
|
||||
VERSIONS_PCB_VIDEO_MASK = 0x3 << 6,
|
||||
VERSIONS_PCB_VIDEO_DP_1_2 = 0x0 << 6,
|
||||
VERSIONS_PCB_VIDEO_HDMI_2_0 = 0x1 << 6,
|
||||
VERSIONS_PCB_TRANSMISSION_MASK = 0x3 << 4,
|
||||
VERSIONS_PCB_TRANSMISSION_FIBER_10G = 0x0 << 4,
|
||||
VERSIONS_PCB_TRANSMISSION_CAT_10G = 0x1 << 4,
|
||||
VERSIONS_PCB_TRANSMISSION_FIBER_3G = 0x2 << 4,
|
||||
VERSIONS_PCB_TRANSMISSION_CAT_1G = 0x3 << 4,
|
||||
VERSIONS_HW_VER_MASK = 0xf << 0,
|
||||
};
|
||||
u16 raw_versions;
|
||||
|
||||
memset(versions, 0, sizeof(struct fpga_versions));
|
||||
|
||||
ihs_fpga_get(priv->map, versions, &raw_versions);
|
||||
|
||||
versions->video_channel = raw_versions & VERSIONS_FPGA_VIDEO_CHANNEL;
|
||||
versions->con_side = raw_versions & VERSIONS_FPGA_CON_SIDE;
|
||||
|
||||
switch (raw_versions & VERSIONS_PCB_VIDEO_MASK) {
|
||||
case VERSIONS_PCB_VIDEO_DP_1_2:
|
||||
versions->pcb_video_type = PCB_DP_1_2;
|
||||
break;
|
||||
|
||||
case VERSIONS_PCB_VIDEO_HDMI_2_0:
|
||||
versions->pcb_video_type = PCB_HDMI_2_0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (raw_versions & VERSIONS_PCB_TRANSMISSION_MASK) {
|
||||
case VERSIONS_PCB_TRANSMISSION_FIBER_10G:
|
||||
versions->pcb_transmission_type = PCB_FIBER_10G;
|
||||
break;
|
||||
|
||||
case VERSIONS_PCB_TRANSMISSION_CAT_10G:
|
||||
versions->pcb_transmission_type = PCB_CAT_10G;
|
||||
break;
|
||||
|
||||
case VERSIONS_PCB_TRANSMISSION_FIBER_3G:
|
||||
versions->pcb_transmission_type = PCB_FIBER_3G;
|
||||
break;
|
||||
|
||||
case VERSIONS_PCB_TRANSMISSION_CAT_1G:
|
||||
versions->pcb_transmission_type = PCB_CAT_1G;
|
||||
break;
|
||||
}
|
||||
|
||||
versions->hw_version = raw_versions & VERSIONS_HW_VER_MASK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_features() - Fill structure with info from features register.
|
||||
* @dev: FPGA device to be queried for information
|
||||
* @features: Pointer to the structure to fill with information from the
|
||||
* features register
|
||||
* Return: 0
|
||||
*/
|
||||
static int get_features(struct udevice *dev, struct fpga_features *features)
|
||||
{
|
||||
struct ihs_fpga_priv *priv = dev_get_priv(dev);
|
||||
enum {
|
||||
FEATURE_SPDIF_RX = BIT(15),
|
||||
FEATURE_SPDIF_TX = BIT(14),
|
||||
FEATURE_PCM_RX = BIT(13),
|
||||
FEATURE_PCM_TX = BIT(12),
|
||||
FEATURE_RAM_MASK = GENMASK(11, 8),
|
||||
FEATURE_RAM_DDR2_32BIT_295MBPS = 0x0 << 8,
|
||||
FEATURE_RAM_DDR3_32BIT_590MBPS = 0x1 << 8,
|
||||
FEATURE_RAM_DDR3_48BIT_590MBPS = 0x2 << 8,
|
||||
FEATURE_RAM_DDR3_64BIT_1800MBPS = 0x3 << 8,
|
||||
FEATURE_RAM_DDR3_48BIT_1800MBPS = 0x4 << 8,
|
||||
FEATURE_CARRIER_SPEED_MASK = GENMASK(7, 6),
|
||||
FEATURE_CARRIER_SPEED_1G = 0x0 << 6,
|
||||
FEATURE_CARRIER_SPEED_2_5G = 0x1 << 6,
|
||||
FEATURE_CARRIER_SPEED_10G = 0x2 << 6,
|
||||
FEATURE_CARRIERS_MASK = GENMASK(5, 4),
|
||||
FEATURE_CARRIERS_0 = 0x0 << 4,
|
||||
FEATURE_CARRIERS_1 = 0x1 << 4,
|
||||
FEATURE_CARRIERS_2 = 0x2 << 4,
|
||||
FEATURE_CARRIERS_4 = 0x3 << 4,
|
||||
FEATURE_USB2 = BIT(3),
|
||||
FEATURE_VIDEOCHANNELS_MASK = GENMASK(2, 0),
|
||||
FEATURE_VIDEOCHANNELS_0 = 0x0 << 0,
|
||||
FEATURE_VIDEOCHANNELS_1 = 0x1 << 0,
|
||||
FEATURE_VIDEOCHANNELS_1_1 = 0x2 << 0,
|
||||
FEATURE_VIDEOCHANNELS_2 = 0x3 << 0,
|
||||
};
|
||||
|
||||
enum {
|
||||
EXT_FEATURE_OSD = BIT(15),
|
||||
EXT_FEATURE_ETHERNET = BIT(9),
|
||||
EXT_FEATURE_INTERLACE = BIT(8),
|
||||
EXT_FEATURE_RS232 = BIT(7),
|
||||
EXT_FEATURE_COMPRESSION_PERF_MASK = GENMASK(6, 4),
|
||||
EXT_FEATURE_COMPRESSION_PERF_1X = 0x0 << 4,
|
||||
EXT_FEATURE_COMPRESSION_PERF_2X = 0x1 << 4,
|
||||
EXT_FEATURE_COMPRESSION_PERF_4X = 0x2 << 4,
|
||||
EXT_FEATURE_COMPRESSION_TYPE1 = BIT(0),
|
||||
EXT_FEATURE_COMPRESSION_TYPE2 = BIT(1),
|
||||
EXT_FEATURE_COMPRESSION_TYPE3 = BIT(2),
|
||||
};
|
||||
|
||||
u16 raw_features;
|
||||
u16 raw_extended_features;
|
||||
|
||||
memset(features, 0, sizeof(struct fpga_features));
|
||||
|
||||
ihs_fpga_get(priv->map, features, &raw_features);
|
||||
ihs_fpga_get(priv->map, extended_features, &raw_extended_features);
|
||||
|
||||
switch (raw_features & FEATURE_VIDEOCHANNELS_MASK) {
|
||||
case FEATURE_VIDEOCHANNELS_0:
|
||||
features->video_channels = 0;
|
||||
break;
|
||||
|
||||
case FEATURE_VIDEOCHANNELS_1:
|
||||
features->video_channels = 1;
|
||||
break;
|
||||
|
||||
case FEATURE_VIDEOCHANNELS_1_1:
|
||||
case FEATURE_VIDEOCHANNELS_2:
|
||||
features->video_channels = 2;
|
||||
break;
|
||||
};
|
||||
|
||||
switch (raw_features & FEATURE_CARRIERS_MASK) {
|
||||
case FEATURE_CARRIERS_0:
|
||||
features->carriers = 0;
|
||||
break;
|
||||
|
||||
case FEATURE_CARRIERS_1:
|
||||
features->carriers = 1;
|
||||
break;
|
||||
|
||||
case FEATURE_CARRIERS_2:
|
||||
features->carriers = 2;
|
||||
break;
|
||||
|
||||
case FEATURE_CARRIERS_4:
|
||||
features->carriers = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (raw_features & FEATURE_CARRIER_SPEED_MASK) {
|
||||
case FEATURE_CARRIER_SPEED_1G:
|
||||
features->carrier_speed = CARRIER_SPEED_1G;
|
||||
break;
|
||||
case FEATURE_CARRIER_SPEED_2_5G:
|
||||
features->carrier_speed = CARRIER_SPEED_2_5G;
|
||||
break;
|
||||
case FEATURE_CARRIER_SPEED_10G:
|
||||
features->carrier_speed = CARRIER_SPEED_10G;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (raw_features & FEATURE_RAM_MASK) {
|
||||
case FEATURE_RAM_DDR2_32BIT_295MBPS:
|
||||
features->ram_config = RAM_DDR2_32BIT_295MBPS;
|
||||
break;
|
||||
|
||||
case FEATURE_RAM_DDR3_32BIT_590MBPS:
|
||||
features->ram_config = RAM_DDR3_32BIT_590MBPS;
|
||||
break;
|
||||
|
||||
case FEATURE_RAM_DDR3_48BIT_590MBPS:
|
||||
features->ram_config = RAM_DDR3_48BIT_590MBPS;
|
||||
break;
|
||||
|
||||
case FEATURE_RAM_DDR3_64BIT_1800MBPS:
|
||||
features->ram_config = RAM_DDR3_64BIT_1800MBPS;
|
||||
break;
|
||||
|
||||
case FEATURE_RAM_DDR3_48BIT_1800MBPS:
|
||||
features->ram_config = RAM_DDR3_48BIT_1800MBPS;
|
||||
break;
|
||||
}
|
||||
|
||||
features->pcm_tx = raw_features & FEATURE_PCM_TX;
|
||||
features->pcm_rx = raw_features & FEATURE_PCM_RX;
|
||||
features->spdif_tx = raw_features & FEATURE_SPDIF_TX;
|
||||
features->spdif_rx = raw_features & FEATURE_SPDIF_RX;
|
||||
features->usb2 = raw_features & FEATURE_USB2;
|
||||
features->rs232 = raw_extended_features & EXT_FEATURE_RS232;
|
||||
features->compression_type1 = raw_extended_features &
|
||||
EXT_FEATURE_COMPRESSION_TYPE1;
|
||||
features->compression_type2 = raw_extended_features &
|
||||
EXT_FEATURE_COMPRESSION_TYPE2;
|
||||
features->compression_type3 = raw_extended_features &
|
||||
EXT_FEATURE_COMPRESSION_TYPE3;
|
||||
features->interlace = raw_extended_features & EXT_FEATURE_INTERLACE;
|
||||
features->osd = raw_extended_features & EXT_FEATURE_OSD;
|
||||
features->compression_pipes = raw_extended_features &
|
||||
EXT_FEATURE_COMPRESSION_PERF_MASK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* get_versions() - Fill structure with info from version register.
|
||||
* @fpga: Identifier of the FPGA device to be queried for information
|
||||
* @versions: Pointer to the structure to fill with information from the
|
||||
* versions register
|
||||
*
|
||||
* This is the legacy version and should be considered deprecated for new
|
||||
* devices.
|
||||
*
|
||||
* Return: 0
|
||||
*/
|
||||
static int get_versions(unsigned int fpga, struct fpga_versions *versions)
|
||||
{
|
||||
enum {
|
||||
/* HW version encoding is a mess, leave it for the moment */
|
||||
VERSIONS_HW_VER_MASK = 0xf << 0,
|
||||
VERSIONS_PIX_CLOCK_GEN_IDT8N3QV01 = BIT(4),
|
||||
VERSIONS_SFP = BIT(5),
|
||||
VERSIONS_VIDEO_MASK = 0x7 << 6,
|
||||
VERSIONS_VIDEO_DVI = 0x0 << 6,
|
||||
VERSIONS_VIDEO_DP_165 = 0x1 << 6,
|
||||
VERSIONS_VIDEO_DP_300 = 0x2 << 6,
|
||||
VERSIONS_VIDEO_HDMI = 0x3 << 6,
|
||||
VERSIONS_UT_MASK = 0xf << 12,
|
||||
VERSIONS_UT_MAIN_SERVER = 0x0 << 12,
|
||||
VERSIONS_UT_MAIN_USER = 0x1 << 12,
|
||||
VERSIONS_UT_VIDEO_SERVER = 0x2 << 12,
|
||||
VERSIONS_UT_VIDEO_USER = 0x3 << 12,
|
||||
};
|
||||
u16 raw_versions;
|
||||
|
||||
memset(versions, 0, sizeof(struct fpga_versions));
|
||||
|
||||
FPGA_GET_REG(fpga, versions, &raw_versions);
|
||||
|
||||
switch (raw_versions & VERSIONS_UT_MASK) {
|
||||
case VERSIONS_UT_MAIN_SERVER:
|
||||
versions->video_channel = false;
|
||||
versions->con_side = false;
|
||||
break;
|
||||
|
||||
case VERSIONS_UT_MAIN_USER:
|
||||
versions->video_channel = false;
|
||||
versions->con_side = true;
|
||||
break;
|
||||
|
||||
case VERSIONS_UT_VIDEO_SERVER:
|
||||
versions->video_channel = true;
|
||||
versions->con_side = false;
|
||||
break;
|
||||
|
||||
case VERSIONS_UT_VIDEO_USER:
|
||||
versions->video_channel = true;
|
||||
versions->con_side = true;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (raw_versions & VERSIONS_VIDEO_MASK) {
|
||||
case VERSIONS_VIDEO_DVI:
|
||||
versions->pcb_video_type = PCB_DVI_SL;
|
||||
break;
|
||||
|
||||
case VERSIONS_VIDEO_DP_165:
|
||||
versions->pcb_video_type = PCB_DP_165MPIX;
|
||||
break;
|
||||
|
||||
case VERSIONS_VIDEO_DP_300:
|
||||
versions->pcb_video_type = PCB_DP_300MPIX;
|
||||
break;
|
||||
|
||||
case VERSIONS_VIDEO_HDMI:
|
||||
versions->pcb_video_type = PCB_HDMI;
|
||||
break;
|
||||
}
|
||||
|
||||
versions->hw_version = raw_versions & VERSIONS_HW_VER_MASK;
|
||||
|
||||
if (raw_versions & VERSIONS_SFP)
|
||||
versions->pcb_transmission_type = PCB_FIBER_3G;
|
||||
else
|
||||
versions->pcb_transmission_type = PCB_CAT_1G;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_features() - Fill structure with info from features register.
|
||||
* @fpga: Identifier of the FPGA device to be queried for information
|
||||
* @features: Pointer to the structure to fill with information from the
|
||||
* features register
|
||||
*
|
||||
* This is the legacy version and should be considered deprecated for new
|
||||
* devices.
|
||||
*
|
||||
* Return: 0
|
||||
*/
|
||||
static int get_features(unsigned int fpga, struct fpga_features *features)
|
||||
{
|
||||
enum {
|
||||
FEATURE_CARRIER_SPEED_2_5 = BIT(4),
|
||||
FEATURE_RAM_MASK = 0x7 << 5,
|
||||
FEATURE_RAM_DDR2_32BIT = 0x0 << 5,
|
||||
FEATURE_RAM_DDR3_32BIT = 0x1 << 5,
|
||||
FEATURE_RAM_DDR3_48BIT = 0x2 << 5,
|
||||
FEATURE_PCM_AUDIO_TX = BIT(9),
|
||||
FEATURE_PCM_AUDIO_RX = BIT(10),
|
||||
FEATURE_OSD = BIT(11),
|
||||
FEATURE_USB20 = BIT(12),
|
||||
FEATURE_COMPRESSION_MASK = 7 << 13,
|
||||
FEATURE_COMPRESSION_TYPE1 = 0x1 << 13,
|
||||
FEATURE_COMPRESSION_TYPE1_TYPE2 = 0x3 << 13,
|
||||
FEATURE_COMPRESSION_TYPE1_TYPE2_TYPE3 = 0x7 << 13,
|
||||
};
|
||||
|
||||
enum {
|
||||
EXTENDED_FEATURE_SPDIF_AUDIO_TX = BIT(0),
|
||||
EXTENDED_FEATURE_SPDIF_AUDIO_RX = BIT(1),
|
||||
EXTENDED_FEATURE_RS232 = BIT(2),
|
||||
EXTENDED_FEATURE_COMPRESSION_PIPES = BIT(3),
|
||||
EXTENDED_FEATURE_INTERLACE = BIT(4),
|
||||
};
|
||||
|
||||
u16 raw_features;
|
||||
u16 raw_extended_features;
|
||||
|
||||
memset(features, 0, sizeof(struct fpga_features));
|
||||
|
||||
FPGA_GET_REG(fpga, fpga_features, &raw_features);
|
||||
FPGA_GET_REG(fpga, fpga_ext_features, &raw_extended_features);
|
||||
|
||||
features->video_channels = raw_features & 0x3;
|
||||
features->carriers = (raw_features >> 2) & 0x3;
|
||||
|
||||
features->carrier_speed = (raw_features & FEATURE_CARRIER_SPEED_2_5)
|
||||
? CARRIER_SPEED_2_5G : CARRIER_SPEED_1G;
|
||||
|
||||
switch (raw_features & FEATURE_RAM_MASK) {
|
||||
case FEATURE_RAM_DDR2_32BIT:
|
||||
features->ram_config = RAM_DDR2_32BIT_295MBPS;
|
||||
break;
|
||||
|
||||
case FEATURE_RAM_DDR3_32BIT:
|
||||
features->ram_config = RAM_DDR3_32BIT_590MBPS;
|
||||
break;
|
||||
|
||||
case FEATURE_RAM_DDR3_48BIT:
|
||||
features->ram_config = RAM_DDR3_48BIT_590MBPS;
|
||||
break;
|
||||
}
|
||||
|
||||
features->pcm_tx = raw_features & FEATURE_PCM_AUDIO_TX;
|
||||
features->pcm_rx = raw_features & FEATURE_PCM_AUDIO_RX;
|
||||
features->spdif_tx = raw_extended_features &
|
||||
EXTENDED_FEATURE_SPDIF_AUDIO_TX;
|
||||
features->spdif_rx = raw_extended_features &
|
||||
EXTENDED_FEATURE_SPDIF_AUDIO_RX;
|
||||
|
||||
features->usb2 = raw_features & FEATURE_USB20;
|
||||
features->rs232 = raw_extended_features & EXTENDED_FEATURE_RS232;
|
||||
|
||||
features->compression_type1 = false;
|
||||
features->compression_type2 = false;
|
||||
features->compression_type3 = false;
|
||||
switch (raw_features & FEATURE_COMPRESSION_MASK) {
|
||||
case FEATURE_COMPRESSION_TYPE1_TYPE2_TYPE3:
|
||||
features->compression_type3 = true;
|
||||
/* fall-through */
|
||||
case FEATURE_COMPRESSION_TYPE1_TYPE2:
|
||||
features->compression_type2 = true;
|
||||
/* fall-through */
|
||||
case FEATURE_COMPRESSION_TYPE1:
|
||||
features->compression_type1 = true;
|
||||
break;
|
||||
}
|
||||
|
||||
features->interlace = raw_extended_features &
|
||||
EXTENDED_FEATURE_INTERLACE;
|
||||
features->osd = raw_features & FEATURE_OSD;
|
||||
features->compression_pipes = raw_extended_features &
|
||||
EXTENDED_FEATURE_COMPRESSION_PIPES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* fpga_print_info() - Print information about FPGA device
|
||||
* @dev: FPGA device to print information about
|
||||
*/
|
||||
static void fpga_print_info(struct udevice *dev)
|
||||
{
|
||||
struct ihs_fpga_priv *priv = dev_get_priv(dev);
|
||||
u16 fpga_version;
|
||||
struct fpga_versions versions;
|
||||
struct fpga_features features;
|
||||
|
||||
ihs_fpga_get(priv->map, fpga_version, &fpga_version);
|
||||
get_versions(dev, &versions);
|
||||
get_features(dev, &features);
|
||||
|
||||
if (versions.video_channel)
|
||||
printf("Videochannel");
|
||||
else
|
||||
printf("Mainchannel");
|
||||
|
||||
if (versions.con_side)
|
||||
printf(" User");
|
||||
else
|
||||
printf(" Server");
|
||||
|
||||
switch (versions.pcb_transmission_type) {
|
||||
case PCB_CAT_1G:
|
||||
case PCB_CAT_10G:
|
||||
printf(" CAT");
|
||||
break;
|
||||
case PCB_FIBER_3G:
|
||||
case PCB_FIBER_10G:
|
||||
printf(" Fiber");
|
||||
break;
|
||||
};
|
||||
|
||||
switch (versions.pcb_video_type) {
|
||||
case PCB_DVI_SL:
|
||||
printf(" DVI,");
|
||||
break;
|
||||
case PCB_DP_165MPIX:
|
||||
printf(" DP 165MPix/s,");
|
||||
break;
|
||||
case PCB_DP_300MPIX:
|
||||
printf(" DP 300MPix/s,");
|
||||
break;
|
||||
case PCB_HDMI:
|
||||
printf(" HDMI,");
|
||||
break;
|
||||
case PCB_DP_1_2:
|
||||
printf(" DP 1.2,");
|
||||
break;
|
||||
case PCB_HDMI_2_0:
|
||||
printf(" HDMI 2.0,");
|
||||
break;
|
||||
}
|
||||
|
||||
printf(" FPGA V %d.%02d\n features: ",
|
||||
fpga_version / 100, fpga_version % 100);
|
||||
|
||||
if (!features.compression_type1 &&
|
||||
!features.compression_type2 &&
|
||||
!features.compression_type3)
|
||||
printf("no compression, ");
|
||||
|
||||
if (features.compression_type1)
|
||||
printf("type1, ");
|
||||
|
||||
if (features.compression_type2)
|
||||
printf("type2, ");
|
||||
|
||||
if (features.compression_type3)
|
||||
printf("type3, ");
|
||||
|
||||
printf("%sosd", features.osd ? "" : "no ");
|
||||
|
||||
if (features.pcm_rx && features.pcm_tx)
|
||||
printf(", pcm rx+tx");
|
||||
else if (features.pcm_rx)
|
||||
printf(", pcm rx");
|
||||
else if (features.pcm_tx)
|
||||
printf(", pcm tx");
|
||||
|
||||
if (features.spdif_rx && features.spdif_tx)
|
||||
printf(", spdif rx+tx");
|
||||
else if (features.spdif_rx)
|
||||
printf(", spdif rx");
|
||||
else if (features.spdif_tx)
|
||||
printf(", spdif tx");
|
||||
|
||||
puts(",\n ");
|
||||
|
||||
switch (features.sysclock) {
|
||||
case SYSCLK_147456:
|
||||
printf("clock 147.456 MHz");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (features.ram_config) {
|
||||
case RAM_DDR2_32BIT_295MBPS:
|
||||
printf(", RAM 32 bit DDR2");
|
||||
break;
|
||||
case RAM_DDR3_32BIT_590MBPS:
|
||||
printf(", RAM 32 bit DDR3");
|
||||
break;
|
||||
case RAM_DDR3_48BIT_590MBPS:
|
||||
case RAM_DDR3_48BIT_1800MBPS:
|
||||
printf(", RAM 48 bit DDR3");
|
||||
break;
|
||||
case RAM_DDR3_64BIT_1800MBPS:
|
||||
printf(", RAM 64 bit DDR3");
|
||||
break;
|
||||
}
|
||||
|
||||
printf(", %d carrier(s)", features.carriers);
|
||||
|
||||
switch (features.carrier_speed) {
|
||||
case CARRIER_SPEED_1G:
|
||||
printf(", 1Gbit/s");
|
||||
break;
|
||||
case CARRIER_SPEED_3G:
|
||||
printf(", 3Gbit/s");
|
||||
break;
|
||||
case CARRIER_SPEED_10G:
|
||||
printf(", 10Gbit/s");
|
||||
break;
|
||||
}
|
||||
|
||||
printf(", %d video channel(s)\n", features.video_channels);
|
||||
}
|
||||
|
||||
/**
|
||||
* do_reflection_test() - Run reflection test on a FPGA device
|
||||
* @dev: FPGA device to run reflection test on
|
||||
*
|
||||
* Return: 0 if reflection test succeeded, -ve on error
|
||||
*/
|
||||
static int do_reflection_test(struct udevice *dev)
|
||||
{
|
||||
struct ihs_fpga_priv *priv = dev_get_priv(dev);
|
||||
int ctr = 0;
|
||||
|
||||
while (1) {
|
||||
u16 val;
|
||||
|
||||
ihs_fpga_set(priv->map, reflection_low, REFLECTION_TESTPATTERN);
|
||||
|
||||
ihs_fpga_get(priv->map, reflection_low, &val);
|
||||
if (val == (~REFLECTION_TESTPATTERN & 0xffff))
|
||||
return -EIO;
|
||||
|
||||
mdelay(REFLECTION_TEST_DELAY);
|
||||
if (ctr++ > REFLECTION_TEST_ROUNDS)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* wait_for_fpga_done() - Wait until 'done'-flag is set for FPGA device
|
||||
* @dev: FPGA device whose done flag to wait for
|
||||
*
|
||||
* This function waits until it detects that the done-GPIO's value was changed
|
||||
* to 1 by the FPGA, which indicates that the device is configured and ready to
|
||||
* use.
|
||||
*
|
||||
* Return: 0 if done flag was detected, -ve on error
|
||||
*/
|
||||
static int wait_for_fpga_done(struct udevice *dev)
|
||||
{
|
||||
struct ihs_fpga_priv *priv = dev_get_priv(dev);
|
||||
int ctr = 0;
|
||||
int done_val;
|
||||
|
||||
while (1) {
|
||||
done_val = dm_gpio_get_value(&priv->done_gpio);
|
||||
if (done_val < 0) {
|
||||
debug("%s: Error while reading done-GPIO (err = %d)\n",
|
||||
dev->name, done_val);
|
||||
return done_val;
|
||||
}
|
||||
|
||||
if (done_val)
|
||||
return 0;
|
||||
|
||||
mdelay(FPGA_DONE_WAIT_DELAY);
|
||||
if (ctr++ > FPGA_DONE_WAIT_ROUND) {
|
||||
debug("%s: FPGA init failed (done not detected)\n",
|
||||
dev->name);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int ihs_fpga_probe(struct udevice *dev)
|
||||
{
|
||||
struct ihs_fpga_priv *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
/* TODO(mario.six@gdsys.cc): Case of FPGA attached to MCLink bus */
|
||||
|
||||
ret = regmap_init_mem(dev_ofnode(dev), &priv->map);
|
||||
if (ret) {
|
||||
debug("%s: Could not initialize regmap (err = %d)",
|
||||
dev->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpio_request_by_name(dev, "reset-gpios", 0, &priv->reset_gpio,
|
||||
GPIOD_IS_OUT);
|
||||
if (ret) {
|
||||
debug("%s: Could not get reset-GPIO (err = %d)\n",
|
||||
dev->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!priv->reset_gpio.dev) {
|
||||
debug("%s: Could not get reset-GPIO\n", dev->name);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ret = gpio_request_by_name(dev, "done-gpios", 0, &priv->done_gpio,
|
||||
GPIOD_IS_IN);
|
||||
if (ret) {
|
||||
debug("%s: Could not get done-GPIO (err = %d)\n",
|
||||
dev->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!priv->done_gpio.dev) {
|
||||
debug("%s: Could not get done-GPIO\n", dev->name);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ret = dm_gpio_set_value(&priv->reset_gpio, 1);
|
||||
if (ret) {
|
||||
debug("%s: Error while setting reset-GPIO (err = %d)\n",
|
||||
dev->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If FPGA already runs, don't initialize again */
|
||||
if (do_reflection_test(dev))
|
||||
goto reflection_ok;
|
||||
|
||||
ret = dm_gpio_set_value(&priv->reset_gpio, 0);
|
||||
if (ret) {
|
||||
debug("%s: Error while setting reset-GPIO (err = %d)\n",
|
||||
dev->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wait_for_fpga_done(dev);
|
||||
if (ret) {
|
||||
debug("%s: Error while waiting for FPGA done (err = %d)\n",
|
||||
dev->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
udelay(10);
|
||||
|
||||
ret = dm_gpio_set_value(&priv->reset_gpio, 1);
|
||||
if (ret) {
|
||||
debug("%s: Error while setting reset-GPIO (err = %d)\n",
|
||||
dev->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!do_reflection_test(dev)) {
|
||||
debug("%s: Reflection test FAILED\n", dev->name);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
reflection_ok:
|
||||
printf("%s: Reflection test passed.\n", dev->name);
|
||||
|
||||
fpga_print_info(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id ihs_fpga_ids[] = {
|
||||
{ .compatible = "gdsys,iocon_fpga" },
|
||||
{ .compatible = "gdsys,iocpu_fpga" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(ihs_fpga_bus) = {
|
||||
.name = "ihs_fpga_bus",
|
||||
.id = UCLASS_MISC,
|
||||
.of_match = ihs_fpga_ids,
|
||||
.probe = ihs_fpga_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct ihs_fpga_priv),
|
||||
};
|
49
drivers/misc/ihs_fpga.h
Normal file
49
drivers/misc/ihs_fpga.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2018
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct ihs_fpga_regs - IHS FPGA register map structure
|
||||
* @reflection_low: Lower reflection register
|
||||
* @versions: PCB versions register
|
||||
* @fpga_version: FPGA versions register
|
||||
* @features: FPGA features register
|
||||
* @extended_features: FPGA extended features register
|
||||
* @top_interrupt: Top interrupt register
|
||||
* @top_interrupt_enable: Top interrupt enable register
|
||||
* @status: FPGA status register
|
||||
* @control: FPGA control register
|
||||
* @extended_control: FPGA extended control register
|
||||
*/
|
||||
struct ihs_fpga_regs {
|
||||
u16 reflection_low;
|
||||
u16 versions;
|
||||
u16 fpga_version;
|
||||
u16 features;
|
||||
u16 extended_features;
|
||||
u16 top_interrupt;
|
||||
u16 top_interrupt_enable;
|
||||
u16 status;
|
||||
u16 control;
|
||||
u16 extended_control;
|
||||
};
|
||||
|
||||
/**
|
||||
* ihs_fpga_set() - Convenience macro to set values in FPGA register map
|
||||
* @map: Register map to set a value in
|
||||
* @member: Name of member (described by ihs_fpga_regs) to set
|
||||
* @val: Value to set the member to
|
||||
*/
|
||||
#define ihs_fpga_set(map, member, val) \
|
||||
regmap_set(map, struct ihs_fpga_regs, member, val)
|
||||
|
||||
/**
|
||||
* ihs_fpga_get() - Convenience macro to get values from FPGA register map
|
||||
* @map: Register map to read value from
|
||||
* @member: Name of member (described by ihs_fpga_regs) to get
|
||||
* @valp: Pointe to variable to receive the value read
|
||||
*/
|
||||
#define ihs_fpga_get(map, member, valp) \
|
||||
regmap_get(map, struct ihs_fpga_regs, member, valp)
|
|
@ -223,7 +223,7 @@ static int imx8_scu_bind(struct udevice *dev)
|
|||
if (node < 0)
|
||||
panic("No clk node found\n");
|
||||
|
||||
ret = lists_bind_fdt(dev, offset_to_ofnode(node), &child);
|
||||
ret = lists_bind_fdt(dev, offset_to_ofnode(node), &child, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -234,7 +234,7 @@ static int imx8_scu_bind(struct udevice *dev)
|
|||
if (node < 0)
|
||||
panic("No iomuxc node found\n");
|
||||
|
||||
ret = lists_bind_fdt(dev, offset_to_ofnode(node), &child);
|
||||
ret = lists_bind_fdt(dev, offset_to_ofnode(node), &child, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -124,12 +124,21 @@ static int sandbox_swap_case_read_config(struct udevice *emul, uint offset,
|
|||
case PCI_CAP_ID_PM_OFFSET:
|
||||
*valuep = (PCI_CAP_ID_EXP_OFFSET << 8) | PCI_CAP_ID_PM;
|
||||
break;
|
||||
case PCI_CAP_ID_PM_OFFSET + PCI_CAP_LIST_NEXT:
|
||||
*valuep = PCI_CAP_ID_EXP_OFFSET;
|
||||
break;
|
||||
case PCI_CAP_ID_EXP_OFFSET:
|
||||
*valuep = (PCI_CAP_ID_MSIX_OFFSET << 8) | PCI_CAP_ID_EXP;
|
||||
break;
|
||||
case PCI_CAP_ID_EXP_OFFSET + PCI_CAP_LIST_NEXT:
|
||||
*valuep = PCI_CAP_ID_MSIX_OFFSET;
|
||||
break;
|
||||
case PCI_CAP_ID_MSIX_OFFSET:
|
||||
*valuep = PCI_CAP_ID_MSIX;
|
||||
break;
|
||||
case PCI_CAP_ID_MSIX_OFFSET + PCI_CAP_LIST_NEXT:
|
||||
*valuep = 0;
|
||||
break;
|
||||
case PCI_EXT_CAP_ID_ERR_OFFSET:
|
||||
*valuep = (PCI_EXT_CAP_ID_VC_OFFSET << 20) | PCI_EXT_CAP_ID_ERR;
|
||||
break;
|
||||
|
|
|
@ -2444,9 +2444,6 @@ static int mmc_startup(struct mmc *mmc)
|
|||
bdesc->product[0] = 0;
|
||||
bdesc->revision[0] = 0;
|
||||
#endif
|
||||
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT)
|
||||
part_init(bdesc);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1953,6 +1953,8 @@ U_BOOT_DRIVER(omap_hsmmc) = {
|
|||
.ops = &omap_hsmmc_ops,
|
||||
.probe = omap_hsmmc_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct omap_hsmmc_data),
|
||||
#if !CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -664,7 +664,6 @@ static int nvme_blk_probe(struct udevice *udev)
|
|||
sprintf(desc->vendor, "0x%.4x", pplat->vendor);
|
||||
memcpy(desc->product, ndev->serial, sizeof(ndev->serial));
|
||||
memcpy(desc->revision, ndev->firmware_rev, sizeof(ndev->firmware_rev));
|
||||
part_init(desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1344,26 +1344,14 @@ void *dm_pci_map_bar(struct udevice *dev, int bar, int flags)
|
|||
return dm_pci_bus_to_virt(dev, pci_bus_addr, flags, 0, MAP_NOCACHE);
|
||||
}
|
||||
|
||||
int dm_pci_find_capability(struct udevice *dev, int cap)
|
||||
static int _dm_pci_find_next_capability(struct udevice *dev, u8 pos, int cap)
|
||||
{
|
||||
u16 status;
|
||||
u8 header_type;
|
||||
int ttl = PCI_FIND_CAP_TTL;
|
||||
u8 id;
|
||||
u16 ent;
|
||||
u8 pos;
|
||||
|
||||
dm_pci_read_config16(dev, PCI_STATUS, &status);
|
||||
if (!(status & PCI_STATUS_CAP_LIST))
|
||||
return 0;
|
||||
|
||||
dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type);
|
||||
if ((header_type & 0x7f) == PCI_HEADER_TYPE_CARDBUS)
|
||||
pos = PCI_CB_CAPABILITY_LIST;
|
||||
else
|
||||
pos = PCI_CAPABILITY_LIST;
|
||||
|
||||
dm_pci_read_config8(dev, pos, &pos);
|
||||
|
||||
while (ttl--) {
|
||||
if (pos < PCI_STD_HEADER_SIZEOF)
|
||||
break;
|
||||
|
@ -1381,7 +1369,32 @@ int dm_pci_find_capability(struct udevice *dev, int cap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int dm_pci_find_ext_capability(struct udevice *dev, int cap)
|
||||
int dm_pci_find_next_capability(struct udevice *dev, u8 start, int cap)
|
||||
{
|
||||
return _dm_pci_find_next_capability(dev, start + PCI_CAP_LIST_NEXT,
|
||||
cap);
|
||||
}
|
||||
|
||||
int dm_pci_find_capability(struct udevice *dev, int cap)
|
||||
{
|
||||
u16 status;
|
||||
u8 header_type;
|
||||
u8 pos;
|
||||
|
||||
dm_pci_read_config16(dev, PCI_STATUS, &status);
|
||||
if (!(status & PCI_STATUS_CAP_LIST))
|
||||
return 0;
|
||||
|
||||
dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type);
|
||||
if ((header_type & 0x7f) == PCI_HEADER_TYPE_CARDBUS)
|
||||
pos = PCI_CB_CAPABILITY_LIST;
|
||||
else
|
||||
pos = PCI_CAPABILITY_LIST;
|
||||
|
||||
return _dm_pci_find_next_capability(dev, pos, cap);
|
||||
}
|
||||
|
||||
int dm_pci_find_next_ext_capability(struct udevice *dev, int start, int cap)
|
||||
{
|
||||
u32 header;
|
||||
int ttl;
|
||||
|
@ -1390,6 +1403,9 @@ int dm_pci_find_ext_capability(struct udevice *dev, int cap)
|
|||
/* minimum 8 bytes per capability */
|
||||
ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
|
||||
|
||||
if (start)
|
||||
pos = start;
|
||||
|
||||
dm_pci_read_config32(dev, pos, &header);
|
||||
/*
|
||||
* 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)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int dm_pci_find_ext_capability(struct udevice *dev, int cap)
|
||||
{
|
||||
return dm_pci_find_next_ext_capability(dev, 0, cap);
|
||||
}
|
||||
|
||||
UCLASS_DRIVER(pci) = {
|
||||
.id = UCLASS_PCI,
|
||||
.name = "pci",
|
||||
|
|
|
@ -148,5 +148,7 @@ U_BOOT_DRIVER(pinctrl_bcm283x) = {
|
|||
.priv_auto_alloc_size = sizeof(struct bcm283x_pinctrl_priv),
|
||||
.ops = &bcm283x_pinctrl_ops,
|
||||
.probe = bcm283x_pinctl_probe,
|
||||
#if !CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -113,5 +113,4 @@ U_BOOT_DRIVER(pinctrl_exynos7420) = {
|
|||
.priv_auto_alloc_size = sizeof(struct exynos_pinctrl_priv),
|
||||
.ops = &exynos7420_pinctrl_ops,
|
||||
.probe = exynos_pinctrl_probe,
|
||||
.flags = DM_FLAG_PRE_RELOC
|
||||
};
|
||||
|
|
|
@ -40,5 +40,7 @@ U_BOOT_DRIVER(imx5_pinctrl) = {
|
|||
.remove = imx_pinctrl_remove,
|
||||
.priv_auto_alloc_size = sizeof(struct imx_pinctrl_priv),
|
||||
.ops = &imx_pinctrl_ops,
|
||||
#if !CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -49,5 +49,7 @@ U_BOOT_DRIVER(imx6_pinctrl) = {
|
|||
.remove = imx_pinctrl_remove,
|
||||
.priv_auto_alloc_size = sizeof(struct imx_pinctrl_priv),
|
||||
.ops = &imx_pinctrl_ops,
|
||||
#if !CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -37,5 +37,7 @@ U_BOOT_DRIVER(imx7_pinctrl) = {
|
|||
.remove = imx_pinctrl_remove,
|
||||
.priv_auto_alloc_size = sizeof(struct imx_pinctrl_priv),
|
||||
.ops = &imx_pinctrl_ops,
|
||||
#if !CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -41,5 +41,7 @@ U_BOOT_DRIVER(imx7ulp_pinctrl) = {
|
|||
.remove = imx_pinctrl_remove,
|
||||
.priv_auto_alloc_size = sizeof(struct imx_pinctrl_priv),
|
||||
.ops = &imx_pinctrl_ops,
|
||||
#if !CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -136,7 +136,6 @@ U_BOOT_DRIVER(single_pinctrl) = {
|
|||
.id = UCLASS_PINCTRL,
|
||||
.of_match = single_pinctrl_match,
|
||||
.ops = &single_pinctrl_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
.platdata_auto_alloc_size = sizeof(struct single_pdata),
|
||||
.ofdata_to_platdata = single_ofdata_to_platdata,
|
||||
};
|
||||
|
|
|
@ -171,5 +171,7 @@ U_BOOT_DRIVER(uniphier_pro4_pinctrl) = {
|
|||
.probe = uniphier_pro4_pinctrl_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
|
||||
.ops = &uniphier_pinctrl_ops,
|
||||
#if !CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -153,5 +153,7 @@ U_BOOT_DRIVER(uniphier_pro5_pinctrl) = {
|
|||
.probe = uniphier_pro5_pinctrl_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct uniphier_pinctrl_priv),
|
||||
.ops = &uniphier_pinctrl_ops,
|
||||
#if !CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -173,5 +173,4 @@ U_BOOT_DRIVER(bmips_ram) = {
|
|||
.probe = bmips_ram_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct bmips_ram_priv),
|
||||
.ops = &bmips_ram_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
|
|
@ -592,7 +592,6 @@ static int do_scsi_scan_one(struct udevice *dev, int id, int lun, bool verbose)
|
|||
memcpy(&bdesc->vendor, &bd.vendor, sizeof(bd.vendor));
|
||||
memcpy(&bdesc->product, &bd.product, sizeof(bd.product));
|
||||
memcpy(&bdesc->revision, &bd.revision, sizeof(bd.revision));
|
||||
part_init(bdesc);
|
||||
|
||||
if (verbose) {
|
||||
printf(" Device %d: ", 0);
|
||||
|
|
|
@ -121,7 +121,6 @@ U_BOOT_DRIVER(altera_jtaguart) = {
|
|||
.platdata_auto_alloc_size = sizeof(struct altera_jtaguart_platdata),
|
||||
.probe = altera_jtaguart_probe,
|
||||
.ops = &altera_jtaguart_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_UART_ALTERA_JTAGUART
|
||||
|
|
|
@ -117,7 +117,6 @@ U_BOOT_DRIVER(altera_uart) = {
|
|||
.platdata_auto_alloc_size = sizeof(struct altera_uart_platdata),
|
||||
.probe = altera_uart_probe,
|
||||
.ops = &altera_uart_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_UART_ALTERA_UART
|
||||
|
|
|
@ -155,7 +155,6 @@ U_BOOT_DRIVER(serial_dcc) = {
|
|||
.id = UCLASS_SERIAL,
|
||||
.of_match = arm_dcc_ids,
|
||||
.ops = &arm_dcc_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_UART_ARM_DCC
|
||||
|
|
|
@ -294,7 +294,9 @@ U_BOOT_DRIVER(serial_atmel) = {
|
|||
#endif
|
||||
.probe = atmel_serial_probe,
|
||||
.ops = &atmel_serial_ops,
|
||||
#if !CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
#endif
|
||||
.priv_auto_alloc_size = sizeof(struct atmel_serial_priv),
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -267,12 +267,26 @@ static inline void _debug_uart_init(void)
|
|||
serial_dout(&com_port->lcr, UART_LCRVAL);
|
||||
}
|
||||
|
||||
static inline int NS16550_read_baud_divisor(struct NS16550 *com_port)
|
||||
{
|
||||
int ret;
|
||||
|
||||
serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL);
|
||||
ret = serial_din(&com_port->dll) & 0xff;
|
||||
ret |= (serial_din(&com_port->dlm) & 0xff) << 8;
|
||||
serial_dout(&com_port->lcr, UART_LCRVAL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void _debug_uart_putc(int ch)
|
||||
{
|
||||
struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
|
||||
|
||||
while (!(serial_din(&com_port->lsr) & UART_LSR_THRE))
|
||||
;
|
||||
while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) {
|
||||
if (!NS16550_read_baud_divisor(com_port))
|
||||
return;
|
||||
}
|
||||
serial_dout(&com_port->thr, ch);
|
||||
}
|
||||
|
||||
|
@ -473,7 +487,9 @@ U_BOOT_DRIVER(ns16550_serial) = {
|
|||
.priv_auto_alloc_size = sizeof(struct NS16550),
|
||||
.probe = ns16550_serial_probe,
|
||||
.ops = &ns16550_serial_ops,
|
||||
#if !CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
#endif /* SERIAL_PRESENT */
|
||||
|
|
|
@ -62,7 +62,7 @@ static int serial_check_stdout(const void *blob, struct udevice **devp)
|
|||
* anyway.
|
||||
*/
|
||||
if (node > 0 && !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node),
|
||||
devp)) {
|
||||
devp, false)) {
|
||||
if (!device_probe(*devp))
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -189,7 +189,6 @@ U_BOOT_DRIVER(serial_ar933x) = {
|
|||
.priv_auto_alloc_size = sizeof(struct ar933x_serial_priv),
|
||||
.probe = ar933x_serial_probe,
|
||||
.ops = &ar933x_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_UART_AR933X
|
||||
|
|
|
@ -128,7 +128,6 @@ U_BOOT_DRIVER(serial_arc) = {
|
|||
.ofdata_to_platdata = arc_serial_ofdata_to_platdata,
|
||||
.probe = arc_serial_probe,
|
||||
.ops = &arc_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_ARC_SERIAL
|
||||
|
|
|
@ -199,6 +199,8 @@ U_BOOT_DRIVER(serial_bcm283x_mu) = {
|
|||
.platdata_auto_alloc_size = sizeof(struct bcm283x_mu_serial_platdata),
|
||||
.probe = bcm283x_mu_serial_probe,
|
||||
.ops = &bcm283x_mu_serial_ops,
|
||||
#if !CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
#endif
|
||||
.priv_auto_alloc_size = sizeof(struct bcm283x_mu_priv),
|
||||
};
|
||||
|
|
|
@ -90,6 +90,8 @@ U_BOOT_DRIVER(bcm283x_pl011_uart) = {
|
|||
.platdata_auto_alloc_size = sizeof(struct pl01x_serial_platdata),
|
||||
.probe = pl01x_serial_probe,
|
||||
.ops = &bcm283x_pl011_serial_ops,
|
||||
#if !CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
#endif
|
||||
.priv_auto_alloc_size = sizeof(struct pl01x_priv),
|
||||
};
|
||||
|
|
|
@ -264,7 +264,6 @@ U_BOOT_DRIVER(bcm6345_serial) = {
|
|||
.probe = bcm6345_serial_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct bcm6345_serial_priv),
|
||||
.ops = &bcm6345_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_UART_BCM6345
|
||||
|
|
|
@ -152,5 +152,4 @@ U_BOOT_DRIVER(serial_efi) = {
|
|||
.priv_auto_alloc_size = sizeof(struct serial_efi_priv),
|
||||
.probe = serial_efi_probe,
|
||||
.ops = &serial_efi_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
|
|
@ -64,5 +64,4 @@ U_BOOT_DRIVER(serial_intel_mid) = {
|
|||
.priv_auto_alloc_size = sizeof(struct NS16550),
|
||||
.probe = mid_serial_probe,
|
||||
.ops = &ns16550_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
|
|
@ -540,5 +540,4 @@ U_BOOT_DRIVER(serial_lpuart) = {
|
|||
.platdata_auto_alloc_size = sizeof(struct lpuart_serial_platdata),
|
||||
.probe = lpuart_serial_probe,
|
||||
.ops = &lpuart_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
|
|
@ -132,7 +132,6 @@ U_BOOT_DRIVER(serial_meson) = {
|
|||
.of_match = meson_serial_ids,
|
||||
.probe = meson_serial_probe,
|
||||
.ops = &meson_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
.ofdata_to_platdata = meson_serial_ofdata_to_platdata,
|
||||
.platdata_auto_alloc_size = sizeof(struct meson_serial_platdata),
|
||||
};
|
||||
|
|
|
@ -129,7 +129,6 @@ U_BOOT_DRIVER(serial_mvebu) = {
|
|||
.platdata_auto_alloc_size = sizeof(struct mvebu_platdata),
|
||||
.probe = mvebu_serial_probe,
|
||||
.ops = &mvebu_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_MVEBU_A3700_UART
|
||||
|
|
|
@ -354,7 +354,9 @@ U_BOOT_DRIVER(serial_mxc) = {
|
|||
#endif
|
||||
.probe = mxc_serial_probe,
|
||||
.ops = &mxc_serial_ops,
|
||||
#if !CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -121,7 +121,9 @@ U_BOOT_DRIVER(omap_serial) = {
|
|||
.priv_auto_alloc_size = sizeof(struct NS16550),
|
||||
.probe = ns16550_serial_probe,
|
||||
.ops = &ns16550_serial_ops,
|
||||
#if !CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
#endif /* DM_SERIAL */
|
||||
|
|
|
@ -132,5 +132,4 @@ U_BOOT_DRIVER(serial_owl) = {
|
|||
.priv_auto_alloc_size = sizeof(struct owl_serial_priv),
|
||||
.probe = owl_serial_probe,
|
||||
.ops = &owl_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue