Prepare v2021.07-rc2
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEEGjx/cOCPqxcHgJu/FHw5/5Y0tywFAmCZn8UACgkQFHw5/5Y0 tyw+GAwAsupHDouwir3d710jhMnFfJk6PBRkbwdeypBNA3zkQlQE2dbLZ9p4NBCv CYCS1LsmWxWIehrJu3qXiddl+k6pbQ5eI3g6sl/cus27q39hIo3B6/4prXs4alH3 a6lf1x9HjzOM+TblIReI9Zqd6S7FzS1L/f3xeYMGn1+vNg1rQMtrzbOlnsCB5ESq XFcfzvTur+hBsCe+9D1g9RxxEpnn0QKN4/9qtzes2loX9QL2WcloOWIaz9ZBtc0P 7me8Tj0AMaRiWbpyHzumYK/qENJu/Pb1DZeFLH5ETCNHKsg1znc/82MScuUYqxJe 3CTRu2ws83Chc1hBlFbHVoC4M8PuMKewwfQlqtIKvNxOKYVqUwpIDvAB4aQRW7Dd s8dVIWqzWCQA34SoaX/pw0JCYznhs+ByM4+x1cxfXqAW0kV92E5Ytdf19DdbQSkx Vq93jFe13uv0MFNWTzguiXzV83i9L43P8hmvAQvzucTbb4C2KEzYvi/WIq/bjHPw zEdEAZ7v =aTso -----END PGP SIGNATURE----- Merge tag 'v2021.07-rc2' into 2021.07+fslc Prepare v2021.07-rc2 * tag 'v2021.07-rc2': Prepare v2021.07-rc2 MAINTAINERS: Add an entry for VirtIO doc: develop: Convert README.virtio to reST x86: Correct regwidth prompt in cbsysinfo cmd/exception: support ebreak exception on RISC-V atcspi200: Add timeout mechanism in spi_xfer() riscv: cpu: fu740: clear feature disable CSR riscv: cpu: Add callback to init each core fdt_support.c: Allow late kernel cmdline modification cmd: gpt: Add option to write GPT partitions to environment variable sandbox: add test of CONFIG_ENV_IMPORT_FDT env: allow environment to be amended from control dtb test: Add gpio-sysinfo test sysinfo: Add gpio-sysinfo driver sysinfo: Require that sysinfo_detect be called before other methods sysinfo: Use global sysinfo IDs for existing sysinfo drivers dm: gpio: Fix gpio_get_list_count failing with livetree Change-Id: I391f68fc2c7413372aa66f38805b8dca3cdb80c2
This commit is contained in:
commit
f0f7f23c85
12
MAINTAINERS
12
MAINTAINERS
|
@ -1171,6 +1171,18 @@ F: common/lcd*.c
|
|||
F: include/lcd*.h
|
||||
F: include/video*.h
|
||||
|
||||
VirtIO
|
||||
M: Bin Meng <bmeng.cn@gmail.com>
|
||||
S: Maintained
|
||||
F: drivers/virtio/
|
||||
F: cmd/virtio.c
|
||||
F: include/config/virtio/
|
||||
F: include/config/virtio.h
|
||||
F: include/config/cmd/virtio.h
|
||||
F: include/virtio*.h
|
||||
F: test/dm/virtio.c
|
||||
F: doc/develop/driver-model/virtio.rst
|
||||
|
||||
X86
|
||||
M: Simon Glass <sjg@chromium.org>
|
||||
M: Bin Meng <bmeng.cn@gmail.com>
|
||||
|
|
2
Makefile
2
Makefile
|
@ -3,7 +3,7 @@
|
|||
VERSION = 2021
|
||||
PATCHLEVEL = 07
|
||||
SUBLEVEL =
|
||||
EXTRAVERSION = -rc1
|
||||
EXTRAVERSION = -rc2
|
||||
NAME =
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
@ -140,3 +140,14 @@ int arch_early_init_r(void)
|
|||
{
|
||||
return riscv_cpu_probe();
|
||||
}
|
||||
|
||||
/**
|
||||
* harts_early_init() - A callback function called by start.S to configure
|
||||
* feature settings of each hart.
|
||||
*
|
||||
* In a multi-core system, memory access shall be careful here, it shall
|
||||
* take care of race conditions.
|
||||
*/
|
||||
__weak void harts_early_init(void)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
#include <dm.h>
|
||||
#include <log.h>
|
||||
#include <asm/csr.h>
|
||||
|
||||
#define CSR_U74_FEATURE_DISABLE 0x7c1
|
||||
|
||||
int spl_soc_init(void)
|
||||
{
|
||||
|
@ -21,3 +24,15 @@ int spl_soc_init(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void harts_early_init(void)
|
||||
{
|
||||
/*
|
||||
* Feature Disable CSR
|
||||
*
|
||||
* Clear feature disable CSR to '0' to turn on all features for
|
||||
* each core. This operation must be in M-mode.
|
||||
*/
|
||||
if (CONFIG_IS_ENABLED(RISCV_MMODE))
|
||||
csr_write(CSR_U74_FEATURE_DISABLE, 0);
|
||||
}
|
||||
|
|
|
@ -117,6 +117,10 @@ call_board_init_f_0:
|
|||
mv sp, a0
|
||||
#endif
|
||||
|
||||
/* Configure proprietary settings and customized CSRs of harts */
|
||||
call_harts_early_init:
|
||||
jal harts_early_init
|
||||
|
||||
#ifndef CONFIG_XIP
|
||||
/*
|
||||
* Pick hart to initialize global data and run U-Boot. The other harts
|
||||
|
|
|
@ -53,6 +53,13 @@
|
|||
osd0 = "/osd";
|
||||
};
|
||||
|
||||
config {
|
||||
environment {
|
||||
from_fdt = "yes";
|
||||
fdt_env_path = "";
|
||||
};
|
||||
};
|
||||
|
||||
audio: audio-codec {
|
||||
compatible = "sandbox,audio-codec";
|
||||
#sound-dai-cells = <1>;
|
||||
|
@ -1526,6 +1533,13 @@
|
|||
compatible = "sandbox,sysinfo-sandbox";
|
||||
};
|
||||
|
||||
sysinfo-gpio {
|
||||
compatible = "gpio-sysinfo";
|
||||
gpios = <&gpio_a 15>, <&gpio_a 16>, <&gpio_a 17>;
|
||||
revisions = <19>, <5>;
|
||||
names = "rev_a", "foo";
|
||||
};
|
||||
|
||||
some_regmapped-bus {
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x1>;
|
||||
|
|
46
cmd/gpt.c
46
cmd/gpt.c
|
@ -350,17 +350,46 @@ static int get_gpt_info(struct blk_desc *dev_desc)
|
|||
}
|
||||
|
||||
/* a wrapper to test get_gpt_info */
|
||||
static int do_get_gpt_info(struct blk_desc *dev_desc)
|
||||
static int do_get_gpt_info(struct blk_desc *dev_desc, char * const namestr)
|
||||
{
|
||||
int ret;
|
||||
int numparts;
|
||||
|
||||
ret = get_gpt_info(dev_desc);
|
||||
if (ret > 0) {
|
||||
print_gpt_info();
|
||||
numparts = get_gpt_info(dev_desc);
|
||||
|
||||
if (numparts > 0) {
|
||||
if (namestr) {
|
||||
char disk_guid[UUID_STR_LEN + 1];
|
||||
char *partitions_list;
|
||||
int partlistlen;
|
||||
int ret = -1;
|
||||
|
||||
ret = get_disk_guid(dev_desc, disk_guid);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
partlistlen = calc_parts_list_len(numparts);
|
||||
partitions_list = malloc(partlistlen);
|
||||
if (!partitions_list) {
|
||||
del_gpt_info();
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(partitions_list, '\0', partlistlen);
|
||||
|
||||
ret = create_gpt_partitions_list(numparts, disk_guid,
|
||||
partitions_list);
|
||||
if (ret < 0)
|
||||
printf("Error: Could not create partition list string!\n");
|
||||
else
|
||||
env_set(namestr, partitions_list);
|
||||
|
||||
free(partitions_list);
|
||||
} else {
|
||||
print_gpt_info();
|
||||
}
|
||||
del_gpt_info();
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
return numparts;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -982,7 +1011,7 @@ static int do_gpt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
|||
ret = do_disk_guid(blk_dev_desc, argv[4]);
|
||||
#ifdef CONFIG_CMD_GPT_RENAME
|
||||
} else if (strcmp(argv[1], "read") == 0) {
|
||||
ret = do_get_gpt_info(blk_dev_desc);
|
||||
ret = do_get_gpt_info(blk_dev_desc, (argc == 5) ? argv[4] : NULL);
|
||||
} else if ((strcmp(argv[1], "swap") == 0) ||
|
||||
(strcmp(argv[1], "rename") == 0)) {
|
||||
ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]);
|
||||
|
@ -1028,8 +1057,9 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
|
|||
" gpt guid mmc 0 varname\n"
|
||||
#ifdef CONFIG_CMD_GPT_RENAME
|
||||
"gpt partition renaming commands:\n"
|
||||
" gpt read <interface> <dev>\n"
|
||||
" gpt read <interface> <dev> [<varname>]\n"
|
||||
" - read GPT into a data structure for manipulation\n"
|
||||
" - read GPT partitions into environment variable\n"
|
||||
" gpt swap <interface> <dev> <name1> <name2>\n"
|
||||
" - change all partitions named name1 to name2\n"
|
||||
" and vice-versa\n"
|
||||
|
|
|
@ -8,6 +8,13 @@
|
|||
#include <common.h>
|
||||
#include <command.h>
|
||||
|
||||
static int do_ebreak(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
char *const argv[])
|
||||
{
|
||||
asm volatile ("ebreak\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
static int do_unaligned(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
char *const argv[])
|
||||
{
|
||||
|
@ -28,6 +35,8 @@ static int do_undefined(struct cmd_tbl *cmdtp, int flag, int argc,
|
|||
}
|
||||
|
||||
static struct cmd_tbl cmd_sub[] = {
|
||||
U_BOOT_CMD_MKENT(ebreak, CONFIG_SYS_MAXARGS, 1, do_ebreak,
|
||||
"", ""),
|
||||
U_BOOT_CMD_MKENT(unaligned, CONFIG_SYS_MAXARGS, 1, do_unaligned,
|
||||
"", ""),
|
||||
U_BOOT_CMD_MKENT(undefined, CONFIG_SYS_MAXARGS, 1, do_undefined,
|
||||
|
@ -37,6 +46,7 @@ static struct cmd_tbl cmd_sub[] = {
|
|||
static char exception_help_text[] =
|
||||
"<ex>\n"
|
||||
" The following exceptions are available:\n"
|
||||
" ebreak - breakpoint\n"
|
||||
" undefined - illegal instruction\n"
|
||||
" unaligned - load address misaligned\n"
|
||||
;
|
||||
|
|
|
@ -205,7 +205,7 @@ static void show_table(struct sysinfo_t *info, bool verbose)
|
|||
print_hex(">type", ser->type);
|
||||
print_addr(">base", ser->baseaddr);
|
||||
print_dec(">baud", ser->baud);
|
||||
print_hex(">baud", ser->regwidth);
|
||||
print_hex(">regwidth", ser->regwidth);
|
||||
print_dec(">input_hz", ser->input_hertz);
|
||||
print_addr(">PCI addr", ser->uart_pci_addr);
|
||||
}
|
||||
|
|
|
@ -459,6 +459,8 @@ static int initr_env(void)
|
|||
else
|
||||
env_set_default(NULL, 0);
|
||||
|
||||
env_import_fdt();
|
||||
|
||||
if (IS_ENABLED(CONFIG_OF_CONTROL))
|
||||
env_set_hex("fdtcontroladdr",
|
||||
(unsigned long)map_to_sysmem(gd->fdt_blob));
|
||||
|
|
|
@ -269,6 +269,15 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* board_fdt_chosen_bootargs - boards may override this function to use
|
||||
* alternative kernel command line arguments
|
||||
*/
|
||||
__weak char *board_fdt_chosen_bootargs(void)
|
||||
{
|
||||
return env_get("bootargs");
|
||||
}
|
||||
|
||||
int fdt_chosen(void *fdt)
|
||||
{
|
||||
int nodeoffset;
|
||||
|
@ -286,7 +295,8 @@ int fdt_chosen(void *fdt)
|
|||
if (nodeoffset < 0)
|
||||
return nodeoffset;
|
||||
|
||||
str = env_get("bootargs");
|
||||
str = board_fdt_chosen_bootargs();
|
||||
|
||||
if (str) {
|
||||
err = fdt_setprop(fdt, nodeoffset, "bootargs", str,
|
||||
strlen(str) + 1);
|
||||
|
|
|
@ -110,6 +110,10 @@ static int spl_fit_get_image_name(const struct spl_fit_info *ctx,
|
|||
* no string in the property for this index. Check if the
|
||||
* sysinfo-level code can supply one.
|
||||
*/
|
||||
rc = sysinfo_detect(sysinfo);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = sysinfo_get_fit_loadable(sysinfo, index - i - 1, type,
|
||||
&str);
|
||||
if (rc && rc != -ENOENT)
|
||||
|
|
|
@ -91,6 +91,7 @@ CONFIG_ENV_IS_NOWHERE=y
|
|||
CONFIG_ENV_IS_IN_EXT4=y
|
||||
CONFIG_ENV_EXT4_INTERFACE="host"
|
||||
CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
|
||||
CONFIG_ENV_IMPORT_FDT=y
|
||||
CONFIG_BOOTP_SEND_HOSTNAME=y
|
||||
CONFIG_NETCONSOLE=y
|
||||
CONFIG_IP_DEFRAG=y
|
||||
|
@ -204,6 +205,7 @@ CONFIG_SPMI=y
|
|||
CONFIG_SPMI_SANDBOX=y
|
||||
CONFIG_SYSINFO=y
|
||||
CONFIG_SYSINFO_SANDBOX=y
|
||||
CONFIG_SYSINFO_GPIO=y
|
||||
CONFIG_SYSRESET=y
|
||||
CONFIG_TIMER=y
|
||||
CONFIG_TIMER_EARLY=y
|
||||
|
|
|
@ -106,6 +106,7 @@ CONFIG_ENV_IS_NOWHERE=y
|
|||
CONFIG_ENV_IS_IN_EXT4=y
|
||||
CONFIG_ENV_EXT4_INTERFACE="host"
|
||||
CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
|
||||
CONFIG_ENV_IMPORT_FDT=y
|
||||
CONFIG_BOOTP_SEND_HOSTNAME=y
|
||||
CONFIG_NETCONSOLE=y
|
||||
CONFIG_IP_DEFRAG=y
|
||||
|
@ -245,6 +246,7 @@ CONFIG_SPMI=y
|
|||
CONFIG_SPMI_SANDBOX=y
|
||||
CONFIG_SYSINFO=y
|
||||
CONFIG_SYSINFO_SANDBOX=y
|
||||
CONFIG_SYSINFO_GPIO=y
|
||||
CONFIG_SYSRESET=y
|
||||
CONFIG_TIMER=y
|
||||
CONFIG_TIMER_EARLY=y
|
||||
|
|
|
@ -178,6 +178,7 @@ CONFIG_SPMI=y
|
|||
CONFIG_SPMI_SANDBOX=y
|
||||
CONFIG_SYSINFO=y
|
||||
CONFIG_SYSINFO_SANDBOX=y
|
||||
CONFIG_SYSINFO_GPIO=y
|
||||
CONFIG_SYSRESET=y
|
||||
CONFIG_TIMER=y
|
||||
CONFIG_TIMER_EARLY=y
|
||||
|
|
|
@ -197,6 +197,7 @@ CONFIG_SPMI=y
|
|||
CONFIG_SPMI_SANDBOX=y
|
||||
CONFIG_SYSINFO=y
|
||||
CONFIG_SYSINFO_SANDBOX=y
|
||||
CONFIG_SYSINFO_GPIO=y
|
||||
CONFIG_SYSRESET=y
|
||||
CONFIG_SPL_SYSRESET=y
|
||||
CONFIG_TIMER=y
|
||||
|
|
|
@ -199,6 +199,7 @@ CONFIG_SPMI=y
|
|||
CONFIG_SPMI_SANDBOX=y
|
||||
CONFIG_SYSINFO=y
|
||||
CONFIG_SYSINFO_SANDBOX=y
|
||||
CONFIG_SYSINFO_GPIO=y
|
||||
CONFIG_SYSRESET=y
|
||||
CONFIG_SPL_SYSRESET=y
|
||||
CONFIG_TIMER=y
|
||||
|
|
|
@ -237,6 +237,23 @@ doc/arch/index.rst:
|
|||
=> gpt swap host 0 name othername
|
||||
[ . . . ]
|
||||
|
||||
Modifying GPT partition layout from U-Boot:
|
||||
===========================================
|
||||
|
||||
The entire GPT partition layout can be exported to an environment
|
||||
variable and then modified enmasse. Users can change the partition
|
||||
numbers, offsets, names and sizes. The resulting variable can used to
|
||||
reformat the device. Here is an example of reading the GPT partitions
|
||||
into a variable and then modifying them:
|
||||
|
||||
U-BOOT> gpt read mmc 0 current_partitions
|
||||
U-BOOT> env edit current_partitions
|
||||
edit: uuid_disk=[...];name=part1,start=0x4000,size=0x4000,uuid=[...];
|
||||
name=part2,start=0xc000,size=0xc000,uuid=[...];[ . . . ]
|
||||
|
||||
U-BOOT> gpt write mmc 0 $current_partitions
|
||||
U-BOOT> gpt verify mmc 0 $current_partitions
|
||||
|
||||
Partition type GUID:
|
||||
====================
|
||||
|
||||
|
|
|
@ -27,3 +27,4 @@ subsystems
|
|||
soc-framework
|
||||
spi-howto
|
||||
usb-info
|
||||
virtio
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
.. sectionauthor:: Bin Meng <bmeng.cn@gmail.com>
|
||||
|
||||
VirtIO Support
|
||||
==============
|
||||
|
||||
This document describes the information about U-Boot support for VirtIO [1]
|
||||
This document describes the information about U-Boot support for VirtIO_
|
||||
devices, including supported boards, build instructions, driver details etc.
|
||||
|
||||
What's VirtIO?
|
||||
|
@ -15,7 +14,7 @@ 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.
|
||||
virtual environment are normally QEMU_ targets like ARM, RISC-V and x86.
|
||||
|
||||
Status
|
||||
------
|
||||
|
@ -49,6 +48,8 @@ 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:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ make qemu_arm_defconfig
|
||||
$ make
|
||||
|
||||
|
@ -56,11 +57,13 @@ 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
|
||||
.. code-block:: none
|
||||
|
||||
Device Drivers --->
|
||||
...
|
||||
VirtIO Drivers --->
|
||||
...
|
||||
[*] PCI driver for virtio devices
|
||||
|
||||
Other drivers are at the same location and can be tuned to suit the needs.
|
||||
|
||||
|
@ -74,6 +77,8 @@ Testing
|
|||
The following QEMU command line is used to get U-Boot up and running with
|
||||
VirtIO net and block devices on ARM.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ qemu-system-arm -nographic -machine virt -bios u-boot.bin \
|
||||
-netdev tap,ifname=tap0,id=net0 \
|
||||
-device virtio-net-device,netdev=net0 \
|
||||
|
@ -82,6 +87,8 @@ VirtIO net and block devices on ARM.
|
|||
|
||||
On x86, command is slightly different to create PCI VirtIO devices.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ qemu-system-i386 -nographic -bios u-boot.rom \
|
||||
-netdev tap,ifname=tap0,id=net0 \
|
||||
-device virtio-net-pci,netdev=net0 \
|
||||
|
@ -93,6 +100,8 @@ 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.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ qemu-system-arm -nographic -machine virt -bios u-boot.bin \
|
||||
-netdev tap,ifname=tap0,id=net0 \
|
||||
-device virtio-net-pci,netdev=net0 \
|
||||
|
@ -104,6 +113,8 @@ and 2 on PCI bus.
|
|||
By default QEMU creates VirtIO legacy devices by default. To create non-legacy
|
||||
(aka modern) devices, pass additional device property/value pairs like below:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ 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 \
|
||||
|
@ -112,6 +123,8 @@ By default QEMU creates VirtIO legacy devices by default. To create non-legacy
|
|||
|
||||
A 'virtio' command is provided in U-Boot shell.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
=> virtio
|
||||
virtio - virtio block devices sub-system
|
||||
|
||||
|
@ -127,10 +140,14 @@ A 'virtio' command is provided in U-Boot shell.
|
|||
|
||||
To probe all the VirtIO devices, type:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
=> virtio scan
|
||||
|
||||
Then we can show the connected block device details by:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
=> virtio info
|
||||
Device 0: QEMU VirtIO Block Device
|
||||
Type: Hard Disk
|
||||
|
@ -138,6 +155,8 @@ Then we can show the connected block device details by:
|
|||
|
||||
And list the directories and files on the disk by:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
=> ls virtio 0 /
|
||||
<DIR> 4096 .
|
||||
<DIR> 4096 ..
|
||||
|
@ -167,6 +186,8 @@ Driver Internals
|
|||
----------------
|
||||
There are 3 level of drivers in the VirtIO driver family.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
+---------------------------------------+
|
||||
| virtio device drivers |
|
||||
| +-------------+ +------------+ |
|
||||
|
@ -199,20 +220,26 @@ 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)
|
||||
.. code-block:: C
|
||||
|
||||
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)
|
||||
.. code-block:: C
|
||||
|
||||
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)
|
||||
.. code-block:: C
|
||||
|
||||
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.
|
||||
|
||||
|
@ -223,20 +250,29 @@ 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
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
#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"
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
#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,
|
||||
}
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
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
|
||||
|
@ -247,7 +283,5 @@ for the remove method to be called before jumping to OS.
|
|||
|
||||
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
|
||||
.. _VirtIO: http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.pdf
|
||||
.. _QEMU: https://www.qemu.org
|
|
@ -0,0 +1,37 @@
|
|||
GPIO-based Sysinfo device
|
||||
|
||||
This binding describes several GPIOs which specify a board revision. Each GPIO
|
||||
forms a digit in a ternary revision number. This revision is then mapped to a
|
||||
name using the revisions and names properties.
|
||||
|
||||
Each GPIO may be floating, pulled-up, or pulled-down, mapping to digits 2, 1,
|
||||
and 0, respectively. The first GPIO forms the least-significant digit of the
|
||||
revision. For example, consider the property
|
||||
|
||||
gpios = <&gpio 0>, <&gpio 1>, <&gpio 2>;
|
||||
|
||||
If GPIO 0 is pulled-up, GPIO 1 is pulled-down, and GPIO 2 is floating, then the
|
||||
revision would be
|
||||
|
||||
0t201 = 2*9 + 0*3 + 1*3 = 19
|
||||
|
||||
If instead GPIO 0 is floating, GPIO 1 is pulled-up, and GPIO 2 is pulled-down,
|
||||
then the revision would be
|
||||
|
||||
0t012 = 0*9 + 1*3 + 2*1 = 5
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "gpio-sysinfo".
|
||||
- gpios: should be a list of gpios forming the revision number,
|
||||
least-significant-digit first
|
||||
- revisions: a list of known revisions; any revisions not present will have the
|
||||
name "unknown"
|
||||
- names: the name of each revision in revisions
|
||||
|
||||
Example:
|
||||
sysinfo {
|
||||
compatible = "gpio-sysinfo";
|
||||
gpios = <&gpio_a 15>, <&gpio_a 16>, <&gpio_a 17>;
|
||||
revisions = <19>, <5>;
|
||||
names = "rev_a", "foo";
|
||||
};
|
|
@ -31,6 +31,9 @@ type
|
|||
|
||||
**RISC-V:**
|
||||
|
||||
ebreak
|
||||
breakpoint exception
|
||||
|
||||
unaligned
|
||||
load address misaligned
|
||||
|
||||
|
|
|
@ -1215,9 +1215,9 @@ int gpio_get_list_count(struct udevice *dev, const char *list_name)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = dev_read_phandle_with_args(dev, list_name, "#gpio-cells", 0, -1,
|
||||
NULL);
|
||||
if (ret) {
|
||||
ret = dev_count_phandle_with_args(dev, list_name, "#gpio-cells",
|
||||
-ENOENT);
|
||||
if (ret < 0) {
|
||||
debug("%s: Node '%s', property '%s', GPIO count failed: %d\n",
|
||||
__func__, dev->name, list_name, ret);
|
||||
}
|
||||
|
|
|
@ -201,7 +201,7 @@ static int __atcspi200_spi_xfer(struct nds_spi_slave *ns,
|
|||
size_t cmd_len = ns->cmd_len;
|
||||
unsigned long data_len = bitlen / 8;
|
||||
int rf_cnt;
|
||||
int ret = 0;
|
||||
int ret = 0, timeout = 0;
|
||||
|
||||
max_tran_len = ns->max_transfer_length;
|
||||
switch (flags) {
|
||||
|
@ -243,11 +243,12 @@ static int __atcspi200_spi_xfer(struct nds_spi_slave *ns,
|
|||
ns->tran_len = tran_len;
|
||||
num_blks = DIV_ROUND_UP(tran_len , CHUNK_SIZE);
|
||||
num_bytes = (tran_len) % CHUNK_SIZE;
|
||||
timeout = SPI_TIMEOUT;
|
||||
if(num_bytes == 0)
|
||||
num_bytes = CHUNK_SIZE;
|
||||
__atcspi200_spi_start(ns);
|
||||
|
||||
while (num_blks) {
|
||||
while (num_blks && (timeout--)) {
|
||||
event = in_le32(&ns->regs->status);
|
||||
if ((event & TXEPTY) && (data_out)) {
|
||||
__nspi_espi_tx(ns, dout);
|
||||
|
@ -269,6 +270,11 @@ static int __atcspi200_spi_xfer(struct nds_spi_slave *ns,
|
|||
din = (unsigned char *)din + rx_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
debug("spi_xfer: %s() timeout\n", __func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data_len -= tran_len;
|
||||
|
|
|
@ -30,4 +30,12 @@ config SYSINFO_SMBIOS
|
|||
one which provides a way to specify this SMBIOS information in the
|
||||
devicetree, without needing any board-specific functionality.
|
||||
|
||||
config SYSINFO_GPIO
|
||||
bool "Enable gpio sysinfo driver"
|
||||
help
|
||||
Support querying gpios to determine board revision. This uses gpios to
|
||||
form a ternary number (when they are pulled-up, -down, or floating).
|
||||
This ternary number is then mapped to a board revision name using
|
||||
device tree properties.
|
||||
|
||||
endif
|
||||
|
|
|
@ -4,5 +4,6 @@
|
|||
# Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
obj-y += sysinfo-uclass.o
|
||||
obj-$(CONFIG_SYSINFO_GAZERBEAM) += gazerbeam.o
|
||||
obj-$(CONFIG_SYSINFO_GPIO) += gpio.o
|
||||
obj-$(CONFIG_SYSINFO_SANDBOX) += sandbox.o
|
||||
obj-$(CONFIG_SYSINFO_SMBIOS) += smbios.o
|
||||
|
|
|
@ -5,10 +5,12 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sysinfo.h>
|
||||
|
||||
enum {
|
||||
BOARD_MULTICHANNEL,
|
||||
BOARD_VARIANT,
|
||||
BOARD_HWVERSION,
|
||||
BOARD_HWVERSION = SYSINFO_ID_BOARD_MODEL,
|
||||
BOARD_MULTICHANNEL = SYSINFO_ID_USER,
|
||||
BOARD_VARIANT
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2021 Sean Anderson <sean.anderson@seco.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <log.h>
|
||||
#include <sysinfo.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <dm/device_compat.h>
|
||||
|
||||
/**
|
||||
* struct sysinfo_gpio_priv - GPIO sysinfo private data
|
||||
* @gpios: List of GPIOs used to detect the revision
|
||||
* @gpio_num: The number of GPIOs in @gpios
|
||||
* @revision: The revision as detected from the GPIOs.
|
||||
*/
|
||||
struct sysinfo_gpio_priv {
|
||||
struct gpio_desc *gpios;
|
||||
int gpio_num, revision;
|
||||
};
|
||||
|
||||
static int sysinfo_gpio_detect(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
struct sysinfo_gpio_priv *priv = dev_get_priv(dev);
|
||||
|
||||
ret = dm_gpio_get_values_as_int_base3(priv->gpios, priv->gpio_num);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
priv->revision = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sysinfo_gpio_get_int(struct udevice *dev, int id, int *val)
|
||||
{
|
||||
struct sysinfo_gpio_priv *priv = dev_get_priv(dev);
|
||||
|
||||
switch (id) {
|
||||
case SYSINFO_ID_BOARD_MODEL:
|
||||
*val = priv->revision;
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
static int sysinfo_gpio_get_str(struct udevice *dev, int id, size_t size, char *val)
|
||||
{
|
||||
struct sysinfo_gpio_priv *priv = dev_get_priv(dev);
|
||||
|
||||
switch (id) {
|
||||
case SYSINFO_ID_BOARD_MODEL: {
|
||||
const char *name = NULL;
|
||||
int i, ret;
|
||||
u32 revision;
|
||||
|
||||
for (i = 0; i < priv->gpio_num; i++) {
|
||||
ret = dev_read_u32_index(dev, "revisions", i,
|
||||
&revision);
|
||||
if (ret) {
|
||||
if (ret != -EOVERFLOW)
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
|
||||
if (revision == priv->revision) {
|
||||
ret = dev_read_string_index(dev, "names", i,
|
||||
&name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!name)
|
||||
name = "unknown";
|
||||
|
||||
strncpy(val, name, size);
|
||||
val[size - 1] = '\0';
|
||||
return 0;
|
||||
} default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
static const struct sysinfo_ops sysinfo_gpio_ops = {
|
||||
.detect = sysinfo_gpio_detect,
|
||||
.get_int = sysinfo_gpio_get_int,
|
||||
.get_str = sysinfo_gpio_get_str,
|
||||
};
|
||||
|
||||
static int sysinfo_gpio_probe(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
struct sysinfo_gpio_priv *priv = dev_get_priv(dev);
|
||||
|
||||
priv->gpio_num = gpio_get_list_count(dev, "gpios");
|
||||
if (priv->gpio_num < 0) {
|
||||
dev_err(dev, "could not get gpios length (err = %d)\n",
|
||||
priv->gpio_num);
|
||||
return priv->gpio_num;
|
||||
}
|
||||
|
||||
priv->gpios = calloc(priv->gpio_num, sizeof(*priv->gpios));
|
||||
if (!priv->gpios) {
|
||||
dev_err(dev, "could not allocate memory for %d gpios\n",
|
||||
priv->gpio_num);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = gpio_request_list_by_name(dev, "gpios", priv->gpios,
|
||||
priv->gpio_num, GPIOD_IS_IN);
|
||||
if (ret != priv->gpio_num) {
|
||||
dev_err(dev, "could not get gpios (err = %d)\n",
|
||||
priv->gpio_num);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!dev_read_bool(dev, "revisions") || !dev_read_bool(dev, "names")) {
|
||||
dev_err(dev, "revisions or names properties missing\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id sysinfo_gpio_ids[] = {
|
||||
{ .compatible = "gpio-sysinfo" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sysinfo_gpio) = {
|
||||
.name = "sysinfo_gpio",
|
||||
.id = UCLASS_SYSINFO,
|
||||
.of_match = sysinfo_gpio_ids,
|
||||
.ops = &sysinfo_gpio_ops,
|
||||
.priv_auto = sizeof(struct sysinfo_gpio_priv),
|
||||
.probe = sysinfo_gpio_probe,
|
||||
};
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
enum {
|
||||
BOOL_CALLED_DETECT,
|
||||
BOOL_CALLED_DETECT = SYSINFO_ID_USER,
|
||||
INT_TEST1,
|
||||
INT_TEST2,
|
||||
STR_VACATIONSPOT,
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
#include <dm.h>
|
||||
#include <sysinfo.h>
|
||||
|
||||
struct sysinfo_priv {
|
||||
bool detected;
|
||||
};
|
||||
|
||||
int sysinfo_get(struct udevice **devp)
|
||||
{
|
||||
return uclass_first_device_err(UCLASS_SYSINFO, devp);
|
||||
|
@ -15,19 +19,29 @@ int sysinfo_get(struct udevice **devp)
|
|||
|
||||
int sysinfo_detect(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
struct sysinfo_priv *priv = dev_get_uclass_priv(dev);
|
||||
struct sysinfo_ops *ops = sysinfo_get_ops(dev);
|
||||
|
||||
if (!ops->detect)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->detect(dev);
|
||||
ret = ops->detect(dev);
|
||||
if (!ret)
|
||||
priv->detected = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sysinfo_get_fit_loadable(struct udevice *dev, int index, const char *type,
|
||||
const char **strp)
|
||||
{
|
||||
struct sysinfo_priv *priv = dev_get_uclass_priv(dev);
|
||||
struct sysinfo_ops *ops = sysinfo_get_ops(dev);
|
||||
|
||||
if (!priv->detected)
|
||||
return -EPERM;
|
||||
|
||||
if (!ops->get_fit_loadable)
|
||||
return -ENOSYS;
|
||||
|
||||
|
@ -36,8 +50,12 @@ int sysinfo_get_fit_loadable(struct udevice *dev, int index, const char *type,
|
|||
|
||||
int sysinfo_get_bool(struct udevice *dev, int id, bool *val)
|
||||
{
|
||||
struct sysinfo_priv *priv = dev_get_uclass_priv(dev);
|
||||
struct sysinfo_ops *ops = sysinfo_get_ops(dev);
|
||||
|
||||
if (!priv->detected)
|
||||
return -EPERM;
|
||||
|
||||
if (!ops->get_bool)
|
||||
return -ENOSYS;
|
||||
|
||||
|
@ -46,8 +64,12 @@ int sysinfo_get_bool(struct udevice *dev, int id, bool *val)
|
|||
|
||||
int sysinfo_get_int(struct udevice *dev, int id, int *val)
|
||||
{
|
||||
struct sysinfo_priv *priv = dev_get_uclass_priv(dev);
|
||||
struct sysinfo_ops *ops = sysinfo_get_ops(dev);
|
||||
|
||||
if (!priv->detected)
|
||||
return -EPERM;
|
||||
|
||||
if (!ops->get_int)
|
||||
return -ENOSYS;
|
||||
|
||||
|
@ -56,8 +78,12 @@ int sysinfo_get_int(struct udevice *dev, int id, int *val)
|
|||
|
||||
int sysinfo_get_str(struct udevice *dev, int id, size_t size, char *val)
|
||||
{
|
||||
struct sysinfo_priv *priv = dev_get_uclass_priv(dev);
|
||||
struct sysinfo_ops *ops = sysinfo_get_ops(dev);
|
||||
|
||||
if (!priv->detected)
|
||||
return -EPERM;
|
||||
|
||||
if (!ops->get_str)
|
||||
return -ENOSYS;
|
||||
|
||||
|
@ -68,4 +94,5 @@ UCLASS_DRIVER(sysinfo) = {
|
|||
.id = UCLASS_SYSINFO,
|
||||
.name = "sysinfo",
|
||||
.post_bind = dm_scan_fdt_dev,
|
||||
.per_device_auto = sizeof(bool),
|
||||
};
|
||||
|
|
|
@ -670,6 +670,24 @@ config DELAY_ENVIRONMENT
|
|||
later by U-Boot code. With CONFIG_OF_CONTROL this is instead
|
||||
controlled by the value of /config/load-environment.
|
||||
|
||||
config ENV_IMPORT_FDT
|
||||
bool "Amend environment by FDT properties"
|
||||
depends on OF_CONTROL
|
||||
help
|
||||
If selected, after the environment has been loaded from its
|
||||
persistent location, the "env_fdt_path" variable is looked
|
||||
up and used as a path to a node in the control DTB. The
|
||||
property/value pairs in that node is then used to update the
|
||||
run-time environment. This can be useful to use the same
|
||||
U-Boot binary with different board variants.
|
||||
|
||||
config ENV_FDT_PATH
|
||||
string "Default value for env_fdt_path variable"
|
||||
depends on ENV_IMPORT_FDT
|
||||
default "/config/environment"
|
||||
help
|
||||
The initial value of the env_fdt_path variable.
|
||||
|
||||
config ENV_APPEND
|
||||
bool "Always append the environment with new data"
|
||||
default n
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <u-boot/crc.h>
|
||||
#include <dm/ofnode.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
@ -334,3 +335,32 @@ int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf,
|
|||
return found;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ENV_IMPORT_FDT
|
||||
void env_import_fdt(void)
|
||||
{
|
||||
const char *path;
|
||||
struct ofprop prop;
|
||||
ofnode node;
|
||||
int res;
|
||||
|
||||
path = env_get("env_fdt_path");
|
||||
if (!path || !path[0])
|
||||
return;
|
||||
|
||||
node = ofnode_path(path);
|
||||
if (!ofnode_valid(node)) {
|
||||
printf("Warning: device tree node '%s' not found\n", path);
|
||||
return;
|
||||
}
|
||||
|
||||
for (res = ofnode_get_first_property(node, &prop);
|
||||
!res;
|
||||
res = ofnode_get_next_property(&prop)) {
|
||||
const char *name, *val;
|
||||
|
||||
val = ofnode_get_property_by_prop(&prop, &name, NULL);
|
||||
env_set(name, val);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -375,4 +375,19 @@ int env_get_char(int index);
|
|||
* This is used for those unfortunate archs with crappy toolchains
|
||||
*/
|
||||
void env_reloc(void);
|
||||
|
||||
|
||||
/**
|
||||
* env_import_fdt() - Import environment values from device tree blob
|
||||
*
|
||||
* This uses the value of the environment variable "env_fdt_path" as a
|
||||
* path to an fdt node, whose property/value pairs are added to the
|
||||
* environment.
|
||||
*/
|
||||
#ifdef CONFIG_ENV_IMPORT_FDT
|
||||
void env_import_fdt(void);
|
||||
#else
|
||||
static inline void env_import_fdt(void) {}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -103,6 +103,9 @@ const uchar default_environment[] = {
|
|||
#ifdef CONFIG_SYS_SOC
|
||||
"soc=" CONFIG_SYS_SOC "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_ENV_IMPORT_FDT
|
||||
"env_fdt_path=" CONFIG_ENV_FDT_PATH "\0"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(CONFIG_BOOTCOUNT_BOOTLIMIT) && (CONFIG_BOOTCOUNT_BOOTLIMIT > 0)
|
||||
"bootlimit=" __stringify(CONFIG_BOOTCOUNT_BOOTLIMIT)"\0"
|
||||
|
|
|
@ -185,6 +185,16 @@ int fdt_find_or_add_subnode(void *fdt, int parentoffset, const char *name);
|
|||
*/
|
||||
int ft_board_setup(void *blob, struct bd_info *bd);
|
||||
|
||||
/**
|
||||
* board_fdt_chosen_bootargs() - Arbitrarily amend fdt kernel command line
|
||||
*
|
||||
* This is used for late modification of kernel command line arguments just
|
||||
* before they are added into the /chosen node in flat device tree.
|
||||
*
|
||||
* @return: pointer to kernel command line arguments in memory
|
||||
*/
|
||||
char *board_fdt_chosen_bootargs(void);
|
||||
|
||||
/*
|
||||
* The keystone2 SOC requires all 32 bit aliased addresses to be converted
|
||||
* to their 36 physical format. This has to happen after all fdt nodes
|
||||
|
|
|
@ -60,7 +60,8 @@ struct sysinfo_ops {
|
|||
* This operation might take a long time (e.g. read from EEPROM,
|
||||
* check the presence of a device on a bus etc.), hence this is not
|
||||
* done in the probe() method, but later during operation in this
|
||||
* dedicated method.
|
||||
* dedicated method. This method will be called before any other
|
||||
* methods.
|
||||
*
|
||||
* Return: 0 if OK, -ve on error.
|
||||
*/
|
||||
|
@ -104,7 +105,7 @@ struct sysinfo_ops {
|
|||
* get_fit_loadable - Get the name of an image to load from FIT
|
||||
* This function can be used to provide the image names based on runtime
|
||||
* detection. A classic use-case would when DTBOs are used to describe
|
||||
* additionnal daughter cards.
|
||||
* additional daughter cards.
|
||||
*
|
||||
* @dev: The sysinfo instance to gather the data.
|
||||
* @index: Index of the image. Starts at 0 and gets incremented
|
||||
|
@ -127,6 +128,9 @@ struct sysinfo_ops {
|
|||
*
|
||||
* @dev: The device containing the information
|
||||
*
|
||||
* This function must be called before any other accessor function for this
|
||||
* device.
|
||||
*
|
||||
* Return: 0 if OK, -ve on error.
|
||||
*/
|
||||
int sysinfo_detect(struct udevice *dev);
|
||||
|
@ -138,7 +142,8 @@ int sysinfo_detect(struct udevice *dev);
|
|||
* @id: A unique identifier for the bool value to be read.
|
||||
* @val: Pointer to a buffer that receives the value read.
|
||||
*
|
||||
* Return: 0 if OK, -ve on error.
|
||||
* Return: 0 if OK, -EPERM if called before sysinfo_detect(), else -ve on
|
||||
* error.
|
||||
*/
|
||||
int sysinfo_get_bool(struct udevice *dev, int id, bool *val);
|
||||
|
||||
|
@ -149,7 +154,8 @@ int sysinfo_get_bool(struct udevice *dev, int id, bool *val);
|
|||
* @id: A unique identifier for the int value to be read.
|
||||
* @val: Pointer to a buffer that receives the value read.
|
||||
*
|
||||
* Return: 0 if OK, -ve on error.
|
||||
* Return: 0 if OK, -EPERM if called before sysinfo_detect(), else -ve on
|
||||
* error.
|
||||
*/
|
||||
int sysinfo_get_int(struct udevice *dev, int id, int *val);
|
||||
|
||||
|
@ -161,7 +167,8 @@ int sysinfo_get_int(struct udevice *dev, int id, int *val);
|
|||
* @size: The size of the buffer to receive the string data.
|
||||
* @val: Pointer to a buffer that receives the value read.
|
||||
*
|
||||
* Return: 0 if OK, -ve on error.
|
||||
* Return: 0 if OK, -EPERM if called before sysinfo_detect(), else -ve on
|
||||
* error.
|
||||
*/
|
||||
int sysinfo_get_str(struct udevice *dev, int id, size_t size, char *val);
|
||||
|
||||
|
@ -173,7 +180,8 @@ int sysinfo_get_str(struct udevice *dev, int id, size_t size, char *val);
|
|||
* function that returns the unique device. This is especially useful for use
|
||||
* in sysinfo files.
|
||||
*
|
||||
* Return: 0 if OK, -ve on error.
|
||||
* Return: 0 if OK, -EPERM if called before sysinfo_detect(), else -ve on
|
||||
* error.
|
||||
*/
|
||||
int sysinfo_get(struct udevice **devp);
|
||||
|
||||
|
@ -181,7 +189,7 @@ int sysinfo_get(struct udevice **devp);
|
|||
* sysinfo_get_fit_loadable - Get the name of an image to load from FIT
|
||||
* This function can be used to provide the image names based on runtime
|
||||
* detection. A classic use-case would when DTBOs are used to describe
|
||||
* additionnal daughter cards.
|
||||
* additional daughter cards.
|
||||
*
|
||||
* @dev: The sysinfo instance to gather the data.
|
||||
* @index: Index of the image. Starts at 0 and gets incremented
|
||||
|
@ -190,8 +198,8 @@ int sysinfo_get(struct udevice **devp);
|
|||
* @strp: A pointer to string. Untouched if the function fails
|
||||
*
|
||||
*
|
||||
* Return: 0 if OK, -ENOENT if no loadable is available else -ve on
|
||||
* error.
|
||||
* Return: 0 if OK, -EPERM if called before sysinfo_detect(), -ENOENT if no
|
||||
* loadable is available else -ve on error.
|
||||
*/
|
||||
int sysinfo_get_fit_loadable(struct udevice *dev, int index, const char *type,
|
||||
const char **strp);
|
||||
|
|
|
@ -96,6 +96,7 @@ obj-$(CONFIG_SPMI) += spmi.o
|
|||
obj-y += syscon.o
|
||||
obj-$(CONFIG_RESET_SYSCON) += syscon-reset.o
|
||||
obj-$(CONFIG_SYSINFO) += sysinfo.o
|
||||
obj-$(CONFIG_SYSINFO_GPIO) += sysinfo-gpio.o
|
||||
obj-$(CONFIG_TEE) += tee.o
|
||||
obj-$(CONFIG_TIMER) += timer.o
|
||||
obj-$(CONFIG_DM_USB) += usb.o
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2021 Sean Anderson <sean.anderson@seco.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <log.h>
|
||||
#include <sysinfo.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <dm/test.h>
|
||||
#include <test/test.h>
|
||||
#include <test/ut.h>
|
||||
|
||||
static int dm_test_sysinfo_gpio(struct unit_test_state *uts)
|
||||
{
|
||||
char buf[64];
|
||||
int val;
|
||||
struct udevice *sysinfo, *gpio;
|
||||
|
||||
ut_assertok(uclass_get_device_by_name(UCLASS_SYSINFO, "sysinfo-gpio",
|
||||
&sysinfo));
|
||||
ut_assertok(uclass_get_device_by_name(UCLASS_GPIO, "base-gpios", &gpio));
|
||||
|
||||
/*
|
||||
* Set up pins: pull-up (1), pull-down (0) and floating (2). This should
|
||||
* result in digits 2 0 1, i.e. 2 * 9 + 1 * 3 = 19
|
||||
*/
|
||||
sandbox_gpio_set_flags(gpio, 15, GPIOD_EXT_PULL_UP);
|
||||
sandbox_gpio_set_flags(gpio, 16, GPIOD_EXT_PULL_DOWN);
|
||||
sandbox_gpio_set_flags(gpio, 17, 0);
|
||||
ut_assertok(sysinfo_detect(sysinfo));
|
||||
ut_assertok(sysinfo_get_int(sysinfo, SYSINFO_ID_BOARD_MODEL, &val));
|
||||
ut_asserteq(19, val);
|
||||
ut_assertok(sysinfo_get_str(sysinfo, SYSINFO_ID_BOARD_MODEL, sizeof(buf),
|
||||
buf));
|
||||
ut_asserteq_str("rev_a", buf);
|
||||
|
||||
/*
|
||||
* Set up pins: floating (2), pull-up (1) and pull-down (0). This should
|
||||
* result in digits 0 1 2, i.e. 1 * 3 + 2 = 5
|
||||
*/
|
||||
sandbox_gpio_set_flags(gpio, 15, 0);
|
||||
sandbox_gpio_set_flags(gpio, 16, GPIOD_EXT_PULL_UP);
|
||||
sandbox_gpio_set_flags(gpio, 17, GPIOD_EXT_PULL_DOWN);
|
||||
ut_assertok(sysinfo_detect(sysinfo));
|
||||
ut_assertok(sysinfo_get_int(sysinfo, SYSINFO_ID_BOARD_MODEL, &val));
|
||||
ut_asserteq(5, val);
|
||||
ut_assertok(sysinfo_get_str(sysinfo, SYSINFO_ID_BOARD_MODEL, sizeof(buf),
|
||||
buf));
|
||||
ut_asserteq_str("foo", buf);
|
||||
|
||||
/*
|
||||
* Set up pins: floating (2), pull-up (1) and pull-down (0). This should
|
||||
* result in digits 1 2 0, i.e. 1 * 9 + 2 * 3 = 15
|
||||
*/
|
||||
sandbox_gpio_set_flags(gpio, 15, GPIOD_EXT_PULL_DOWN);
|
||||
sandbox_gpio_set_flags(gpio, 16, 0);
|
||||
sandbox_gpio_set_flags(gpio, 17, GPIOD_EXT_PULL_UP);
|
||||
ut_assertok(sysinfo_detect(sysinfo));
|
||||
ut_assertok(sysinfo_get_int(sysinfo, SYSINFO_ID_BOARD_MODEL, &val));
|
||||
ut_asserteq(15, val);
|
||||
ut_assertok(sysinfo_get_str(sysinfo, SYSINFO_ID_BOARD_MODEL, sizeof(buf),
|
||||
buf));
|
||||
ut_asserteq_str("unknown", buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_sysinfo_gpio, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
|
|
@ -17,40 +17,45 @@
|
|||
static int dm_test_sysinfo(struct unit_test_state *uts)
|
||||
{
|
||||
struct udevice *sysinfo;
|
||||
bool called_detect;
|
||||
bool called_detect = false;
|
||||
char str[64];
|
||||
int i;
|
||||
|
||||
ut_assertok(sysinfo_get(&sysinfo));
|
||||
ut_assert(sysinfo);
|
||||
|
||||
sysinfo_get_bool(sysinfo, BOOL_CALLED_DETECT, &called_detect);
|
||||
ut_asserteq(-EPERM, sysinfo_get_bool(sysinfo, BOOL_CALLED_DETECT,
|
||||
&called_detect));
|
||||
ut_assert(!called_detect);
|
||||
|
||||
sysinfo_detect(sysinfo);
|
||||
|
||||
sysinfo_get_bool(sysinfo, BOOL_CALLED_DETECT, &called_detect);
|
||||
ut_assertok(sysinfo_get_bool(sysinfo, BOOL_CALLED_DETECT,
|
||||
&called_detect));
|
||||
ut_assert(called_detect);
|
||||
|
||||
sysinfo_get_str(sysinfo, STR_VACATIONSPOT, sizeof(str), str);
|
||||
ut_assertok(sysinfo_get_str(sysinfo, STR_VACATIONSPOT, sizeof(str),
|
||||
str));
|
||||
ut_assertok(strcmp(str, "R'lyeh"));
|
||||
|
||||
sysinfo_get_int(sysinfo, INT_TEST1, &i);
|
||||
ut_assertok(sysinfo_get_int(sysinfo, INT_TEST1, &i));
|
||||
ut_asserteq(0, i);
|
||||
|
||||
sysinfo_get_int(sysinfo, INT_TEST2, &i);
|
||||
ut_assertok(sysinfo_get_int(sysinfo, INT_TEST2, &i));
|
||||
ut_asserteq(100, i);
|
||||
|
||||
sysinfo_get_str(sysinfo, STR_VACATIONSPOT, sizeof(str), str);
|
||||
ut_assertok(sysinfo_get_str(sysinfo, STR_VACATIONSPOT, sizeof(str),
|
||||
str));
|
||||
ut_assertok(strcmp(str, "Carcosa"));
|
||||
|
||||
sysinfo_get_int(sysinfo, INT_TEST1, &i);
|
||||
ut_assertok(sysinfo_get_int(sysinfo, INT_TEST1, &i));
|
||||
ut_asserteq(1, i);
|
||||
|
||||
sysinfo_get_int(sysinfo, INT_TEST2, &i);
|
||||
ut_assertok(sysinfo_get_int(sysinfo, INT_TEST2, &i));
|
||||
ut_asserteq(99, i);
|
||||
|
||||
sysinfo_get_str(sysinfo, STR_VACATIONSPOT, sizeof(str), str);
|
||||
ut_assertok(sysinfo_get_str(sysinfo, STR_VACATIONSPOT, sizeof(str),
|
||||
str));
|
||||
ut_assertok(strcmp(str, "Yuggoth"));
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -5,3 +5,4 @@
|
|||
obj-y += cmd_ut_env.o
|
||||
obj-y += attr.o
|
||||
obj-y += hashtable.o
|
||||
obj-$(CONFIG_ENV_IMPORT_FDT) += fdt.o
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <env_attr.h>
|
||||
#include <test/env.h>
|
||||
#include <test/ut.h>
|
||||
|
||||
static int env_test_fdt_import(struct unit_test_state *uts)
|
||||
{
|
||||
const char *val;
|
||||
|
||||
val = env_get("from_fdt");
|
||||
ut_assertnonnull(val);
|
||||
ut_asserteq_str("yes", val);
|
||||
|
||||
val = env_get("fdt_env_path");
|
||||
ut_assertnull(val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
ENV_TEST(env_test_fdt_import, 0);
|
Loading…
Reference in New Issue