From 6b5e420137b42f3c23669b07a7b0c6ff5502fcb9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:24 -0700 Subject: [PATCH 01/32] sandbox: Fix up the debug message for the image filename This currently prints out the wrong filename. Fix it. Signed-off-by: Simon Glass --- arch/sandbox/cpu/os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 62e05c554a..a8d01e4001 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -668,7 +668,7 @@ static int os_jump_to_file(const char *fname) os_free(argv); if (err) { perror("Unable to run image"); - printf("Image filename '%s'\n", mem_fname); + printf("Image filename '%s'\n", fname); return err; } From 12efc933b9e69f7340703655d84b9b610fa42fd4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:25 -0700 Subject: [PATCH 02/32] sandbox: Check the filename in jump_to_image_no_args() If the filename is NULL this function currently crashes. Update it to fail gracefully. Signed-off-by: Simon Glass --- arch/sandbox/cpu/spl.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c index 5005ed2f54..2ca4cd6e35 100644 --- a/arch/sandbox/cpu/spl.c +++ b/arch/sandbox/cpu/spl.c @@ -69,7 +69,11 @@ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) { const char *fname = spl_image->arg; - os_fd_restore(); - os_spl_to_uboot(fname); + if (fname) { + os_fd_restore(); + os_spl_to_uboot(fname); + } else { + printf("No filename provided for U-Boot\n"); + } hang(); } From e3491fb11f54e642925f587ed2dd6c98aea9c65d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:26 -0700 Subject: [PATCH 03/32] sandbox: physmem: Use mapping to support sandbox Replace the raw cast with a map_sysmem() call so this code works with sandbox. Signed-off-by: Simon Glass --- lib/physmem.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/physmem.c b/lib/physmem.c index f21ac243ed..84b191dae3 100644 --- a/lib/physmem.c +++ b/lib/physmem.c @@ -9,14 +9,16 @@ */ #include +#include #include #include phys_addr_t __weak arch_phys_memset(phys_addr_t s, int c, phys_size_t n) { - void *s_ptr = (void *)(uintptr_t)s; + void *s_ptr = map_sysmem(s, n); assert(((phys_addr_t)(uintptr_t)s) == s); assert(((phys_addr_t)(uintptr_t)(s + n)) == s + n); + return (phys_addr_t)(uintptr_t)memset(s_ptr, c, n); } From e628bba785a310e80193f9a34c0b53fcb2136c46 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:27 -0700 Subject: [PATCH 04/32] sandbox: net: Correct name copy in eth_raw_bus_post_bind() We cannot be sure that the interface name takes up the full length of the space available to it. Use strcpy() instead of memcpy() in this case. This corrects a valgrind warning. Signed-off-by: Simon Glass --- drivers/net/sandbox-raw-bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/sandbox-raw-bus.c b/drivers/net/sandbox-raw-bus.c index 76d65afe6c..0086f25fc1 100644 --- a/drivers/net/sandbox-raw-bus.c +++ b/drivers/net/sandbox-raw-bus.c @@ -42,7 +42,7 @@ static int eth_raw_bus_post_bind(struct udevice *dev) device_probe(child); priv = dev_get_priv(child); if (priv) { - memcpy(priv->host_ifname, i->if_name, IFNAMSIZ); + strcpy(priv->host_ifname, i->if_name); priv->host_ifindex = i->if_index; priv->local = local; } From 2a07269062a8e63dadc23be0f8b0d4638da7d2d2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:28 -0700 Subject: [PATCH 05/32] sandbox: sysreset: Update to support power-on reset If U-Boot is started from SPL or TPL, then those earlier phases deal with the reset cause. On real hardware this cause may be lost once it is read. Emulate that behaviour in sandbox by reporting a warm reset when a previous phase has run since start-up. Signed-off-by: Simon Glass --- drivers/sysreset/sysreset_sandbox.c | 8 +++++++- test/dm/sysreset.c | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c index 7f6d4186e1..38e2a7e241 100644 --- a/drivers/sysreset/sysreset_sandbox.c +++ b/drivers/sysreset/sysreset_sandbox.c @@ -84,7 +84,13 @@ int sandbox_sysreset_get_status(struct udevice *dev, char *buf, int size) int sandbox_sysreset_get_last(struct udevice *dev) { - return SYSRESET_COLD; + struct sandbox_state *state = state_get_current(); + + /* + * The first phase is a power reset, after that we assume we don't + * know. + */ + return state->jumped_fname ? SYSRESET_WARM : SYSRESET_POWER; } static struct sysreset_ops sandbox_sysreset_ops = { diff --git a/test/dm/sysreset.c b/test/dm/sysreset.c index e1b7bf5277..5b2358ef67 100644 --- a/test/dm/sysreset.c +++ b/test/dm/sysreset.c @@ -102,10 +102,10 @@ static int dm_test_sysreset_get_last(struct unit_test_state *uts) /* Device 2 is the cold sysreset device */ ut_assertok(uclass_get_device(UCLASS_SYSRESET, 2, &dev)); - ut_asserteq(SYSRESET_COLD, sysreset_get_last(dev)); + ut_asserteq(SYSRESET_POWER, sysreset_get_last(dev)); /* This is device 0, the non-DT one */ - ut_asserteq(SYSRESET_COLD, sysreset_get_last_walk()); + ut_asserteq(SYSRESET_POWER, sysreset_get_last_walk()); return 0; } From a65d1a06c9f76d3285948a059b861d7534589cfc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:29 -0700 Subject: [PATCH 06/32] sandbox: Zero the ram buffer on startup At present the RAM buffer is not inited unless it is read from a file, likely produced by an earlier phase of U-Boot. This causes valgrind warnings whenever the RAM buffer is used. Correct this by initing it if needed. Signed-off-by: Simon Glass --- arch/sandbox/cpu/start.c | 7 +++++++ arch/sandbox/include/asm/state.h | 1 + 2 files changed, 8 insertions(+) diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index b1566a8143..2f5e6e9518 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -180,6 +180,7 @@ static int sandbox_cmdline_cb_memory(struct sandbox_state *state, printf("Failed to read RAM buffer '%s': %d\n", arg, err); return err; } + state->ram_buf_read = true; return 0; } @@ -301,6 +302,12 @@ int board_run_command(const char *cmdline) static void setup_ram_buf(struct sandbox_state *state) { + /* Zero the RAM buffer if we didn't read it, to keep valgrind happy */ + if (!state->ram_buf_read) { + memset(state->ram_buf, '\0', state->ram_size); + printf("clear %p %x\n", state->ram_buf, state->ram_size); + } + gd->arch.ram_buf = state->ram_buf; gd->ram_size = state->ram_size; } diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h index 8fabe70a86..5a14485102 100644 --- a/arch/sandbox/include/asm/state.h +++ b/arch/sandbox/include/asm/state.h @@ -90,6 +90,7 @@ struct sandbox_state { bool show_test_output; /* Don't suppress stdout in tests */ int default_log_level; /* Default log level for sandbox */ bool show_of_platdata; /* Show of-platdata in SPL */ + bool ram_buf_read; /* true if we read the RAM buffer */ /* Pointer to information for each SPI bus/cs */ struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS] From 40e9ede1dcd852a97d772b8d592e36195c5d8b80 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:30 -0700 Subject: [PATCH 07/32] sandbox: Use 'extras' to specify 'head' files At present sandbox has a start.o in the 'start' target but also includes it in the normal target list. This is not how this is normally handled. It is needed because sandbox does not include the u-boot-init variable in its link rule. Update the rule and move start.o from the normal target list to the 'extras' list. Signed-off-by: Simon Glass --- arch/sandbox/Makefile | 4 ++-- arch/sandbox/config.mk | 3 ++- arch/sandbox/cpu/Makefile | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/arch/sandbox/Makefile b/arch/sandbox/Makefile index 261079441c..f6cf859f24 100644 --- a/arch/sandbox/Makefile +++ b/arch/sandbox/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0+ -head-y := arch/sandbox/cpu/start.o - +head-y := arch/sandbox/cpu/start.o arch/sandbox/cpu/os.o +head-$(CONFIG_SANDBOX_SDL) += arch/sandbox/cpu/sdl.o libs-y += arch/sandbox/cpu/ libs-y += arch/sandbox/lib/ diff --git a/arch/sandbox/config.mk b/arch/sandbox/config.mk index 95f9e3ff63..7226b7be42 100644 --- a/arch/sandbox/config.mk +++ b/arch/sandbox/config.mk @@ -17,11 +17,12 @@ PLATFORM_CPPFLAGS += $(shell sdl-config --cflags) endif endif -cmd_u-boot__ = $(CC) -o $@ -Wl,-T u-boot.lds \ +cmd_u-boot__ = $(CC) -o $@ -Wl,-T u-boot.lds $(u-boot-init) \ -Wl,--start-group $(u-boot-main) -Wl,--end-group \ $(PLATFORM_LIBS) -Wl,-Map -Wl,u-boot.map cmd_u-boot-spl = (cd $(obj) && $(CC) -o $(SPL_BIN) -Wl,-T u-boot-spl.lds \ + $(patsubst $(obj)/%,%,$(u-boot-spl-init)) \ -Wl,--start-group $(patsubst $(obj)/%,%,$(u-boot-spl-main)) \ $(patsubst $(obj)/%,%,$(u-boot-spl-platdata)) -Wl,--end-group \ $(PLATFORM_LIBS) -Wl,-Map -Wl,u-boot-spl.map -Wl,--gc-sections) diff --git a/arch/sandbox/cpu/Makefile b/arch/sandbox/cpu/Makefile index 8fe681844d..bac96447d5 100644 --- a/arch/sandbox/cpu/Makefile +++ b/arch/sandbox/cpu/Makefile @@ -5,10 +5,11 @@ # (C) Copyright 2000-2003 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. -obj-y := cpu.o os.o start.o state.o +obj-y := cpu.o state.o +extra-y := start.o os.o +extra-$(CONFIG_SANDBOX_SDL) += sdl.o obj-$(CONFIG_SPL_BUILD) += spl.o obj-$(CONFIG_ETH_SANDBOX_RAW) += eth-raw-os.o -obj-$(CONFIG_SANDBOX_SDL) += sdl.o # os.c is build in the system environment, so needs standard includes # CFLAGS_REMOVE_os.o cannot be used to drop header include path From 0a60a0a65fa98f265c79f3928d8628aabcba8a92 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:32 -0700 Subject: [PATCH 08/32] tpm: Remove use of build-time TPM versions There is only one place in the code which assumes at build-time that we are using either a v1 or a v2 TPM. Fix this up and add a new function to return the version of a TPM. Supported TPM versions (v1 and v2) can be enabled independently and it is possible to use both versions at once. This is useful for sandbox when running tests. Signed-off-by: Simon Glass --- include/tpm-common.h | 11 +++++++++++ lib/tpm-common.c | 7 +++++++ lib/tpm-v1.c | 22 +++++++++++----------- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/include/tpm-common.h b/include/tpm-common.h index 3d88b44db7..91a1484b3d 100644 --- a/include/tpm-common.h +++ b/include/tpm-common.h @@ -274,4 +274,15 @@ static inline cmd_tbl_t *get_tpm2_commands(unsigned int *size) } #endif +/** + * tpm_get_version() - Find the version of a TPM + * + * This checks the uclass data for a TPM device and returns the version number + * it supports. + * + * @dev: TPM device + * @return version number (TPM_V1 or TPMV2) + */ +enum tpm_version tpm_get_version(struct udevice *dev); + #endif /* __TPM_COMMON_H */ diff --git a/lib/tpm-common.c b/lib/tpm-common.c index 6afe59b1fe..2bf0b41e26 100644 --- a/lib/tpm-common.c +++ b/lib/tpm-common.c @@ -12,6 +12,13 @@ #include #include "tpm-utils.h" +enum tpm_version tpm_get_version(struct udevice *dev) +{ + struct tpm_chip_priv *priv = dev_get_uclass_priv(dev); + + return priv->version; +} + int pack_byte_string(u8 *str, size_t size, const char *format, ...) { va_list args; diff --git a/lib/tpm-v1.c b/lib/tpm-v1.c index f29e62ff7b..3e89f84544 100644 --- a/lib/tpm-v1.c +++ b/lib/tpm-v1.c @@ -79,19 +79,19 @@ u32 tpm_clear_and_reenable(struct udevice *dev) return ret; } -#if IS_ENABLED(CONFIG_TPM_V1) - ret = tpm_physical_enable(dev); - if (ret != TPM_SUCCESS) { - log_err("TPM: Can't set enabled state\n"); - return ret; - } + if (tpm_get_version(dev) == TPM_V1) { + ret = tpm_physical_enable(dev); + if (ret != TPM_SUCCESS) { + log_err("TPM: Can't set enabled state\n"); + return ret; + } - ret = tpm_physical_set_deactivated(dev, 0); - if (ret != TPM_SUCCESS) { - log_err("TPM: Can't set deactivated state\n"); - return ret; + ret = tpm_physical_set_deactivated(dev, 0); + if (ret != TPM_SUCCESS) { + log_err("TPM: Can't set deactivated state\n"); + return ret; + } } -#endif return TPM_SUCCESS; } From 5e69b8bc049cbc357c3d13a6e83e43161642de57 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:33 -0700 Subject: [PATCH 09/32] tpm: Export tpm_clear_and_reenable() This function is intended to be exported but is not. Add it to the header file. Signed-off-by: Simon Glass --- include/tpm-common.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/tpm-common.h b/include/tpm-common.h index 91a1484b3d..f9c2ca2053 100644 --- a/include/tpm-common.h +++ b/include/tpm-common.h @@ -209,6 +209,14 @@ int tpm_open(struct udevice *dev); */ int tpm_close(struct udevice *dev); +/** + * tpm_clear_and_reenable() - Force clear the TPM and reenable it + * + * @dev: TPM device + * @return 0 on success, -ve on failure + */ +u32 tpm_clear_and_reenable(struct udevice *dev); + /** * tpm_get_desc() - Get a text description of the TPM * From be8a025ed750edde0207ea7d75a73cb12313d288 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:34 -0700 Subject: [PATCH 10/32] tpm: Add non-volatile index attributes needed for v2 Version-2 TPMs support attributes for nvdata. Add definitions to the header file so that clients can use it. Signed-off-by: Simon Glass --- include/tpm-v2.h | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 2f2e66de19..ae00803f6d 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -128,6 +128,39 @@ enum tpm2_algorithms { TPM2_ALG_NULL = 0x10, }; +/* NV index attributes */ +enum tpm_index_attrs { + TPMA_NV_PPWRITE = 1UL << 0, + TPMA_NV_OWNERWRITE = 1UL << 1, + TPMA_NV_AUTHWRITE = 1UL << 2, + TPMA_NV_POLICYWRITE = 1UL << 3, + TPMA_NV_COUNTER = 1UL << 4, + TPMA_NV_BITS = 1UL << 5, + TPMA_NV_EXTEND = 1UL << 6, + TPMA_NV_POLICY_DELETE = 1UL << 10, + TPMA_NV_WRITELOCKED = 1UL << 11, + TPMA_NV_WRITEALL = 1UL << 12, + TPMA_NV_WRITEDEFINE = 1UL << 13, + TPMA_NV_WRITE_STCLEAR = 1UL << 14, + TPMA_NV_GLOBALLOCK = 1UL << 15, + TPMA_NV_PPREAD = 1UL << 16, + TPMA_NV_OWNERREAD = 1UL << 17, + TPMA_NV_AUTHREAD = 1UL << 18, + TPMA_NV_POLICYREAD = 1UL << 19, + TPMA_NV_NO_DA = 1UL << 25, + TPMA_NV_ORDERLY = 1UL << 26, + TPMA_NV_CLEAR_STCLEAR = 1UL << 27, + TPMA_NV_READLOCKED = 1UL << 28, + TPMA_NV_WRITTEN = 1UL << 29, + TPMA_NV_PLATFORMCREATE = 1UL << 30, + TPMA_NV_READ_STCLEAR = 1UL << 31, + + TPMA_NV_MASK_READ = TPMA_NV_PPREAD | TPMA_NV_OWNERREAD | + TPMA_NV_AUTHREAD | TPMA_NV_POLICYREAD, + TPMA_NV_MASK_WRITE = TPMA_NV_PPWRITE | TPMA_NV_OWNERWRITE | + TPMA_NV_AUTHWRITE | TPMA_NV_POLICYWRITE, +}; + /** * Issue a TPM2_Startup command. * From 5092af6b571c883c49da2b6df7419d73874cdba4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:35 -0700 Subject: [PATCH 11/32] tpm: Fix a logging warning in unpack_byte_string() Fix the printf() string to avoid a warning. Signed-off-by: Simon Glass --- lib/tpm-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tpm-common.c b/lib/tpm-common.c index 2bf0b41e26..86b4f413c2 100644 --- a/lib/tpm-common.c +++ b/lib/tpm-common.c @@ -119,7 +119,7 @@ int unpack_byte_string(const u8 *str, size_t size, const char *format, ...) if (offset + length > size) { va_end(args); - log_err("Failed to read: size=%d, offset=%x, len=%x\n", + log_err("Failed to read: size=%zd, offset=%zx, len=%zx\n", size, offset, length); return -1; } From a749c09a1ea7376ff7a891663bb80ffbe308c485 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:36 -0700 Subject: [PATCH 12/32] cros: Correct a printf() string and comment Correct a warning that occurs on sandbox. Also fix the comment style in cros_ec_set_lid_shutdown_mask(). Signed-off-by: Simon Glass --- drivers/misc/cros_ec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index 2dcdb3d8d6..565de040fe 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -420,7 +420,7 @@ int cros_ec_read_id(struct udevice *dev, char *id, int maxlen) ret = ec_command_inptr(dev, EC_CMD_GET_VERSION, 0, NULL, 0, (uint8_t **)&r, sizeof(*r)); if (ret != sizeof(*r)) { - log_err("Got rc %d, expected %d\n", ret, sizeof(*r)); + log_err("Got rc %d, expected %u\n", ret, (uint)sizeof(*r)); return -1; } @@ -1466,7 +1466,7 @@ int cros_ec_set_lid_shutdown_mask(struct udevice *dev, int enable) if (ret < 0) return ret; - // Set lid close event state in the EC SMI event mask + /* Set lid close event state in the EC SMI event mask */ if (enable) mask |= EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED); else From eafb4a59dbb90a63c9676f16ffa1e099ee26ec28 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:37 -0700 Subject: [PATCH 13/32] cros_ec: Adjust to use v1 vboot context only At present there are no users of the 64-byte v2 context. The v1 context is only 16 bytes long and currently an error is raised if too much data is returned from the EC. Update the code to limit the size to 16 bytes. Signed-off-by: Simon Glass --- drivers/misc/cros_ec_sandbox.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c index 429f1a9b26..4fcb2d96f5 100644 --- a/drivers/misc/cros_ec_sandbox.c +++ b/drivers/misc/cros_ec_sandbox.c @@ -313,13 +313,15 @@ static int process_cmd(struct ec_state *ec, switch (req->op) { case EC_VBNV_CONTEXT_OP_READ: + /* TODO(sjg@chromium.org): Support full-size context */ memcpy(resp->block, ec->vbnv_context, - sizeof(resp->block)); - len = sizeof(*resp); + EC_VBNV_BLOCK_SIZE); + len = 16; break; case EC_VBNV_CONTEXT_OP_WRITE: - memcpy(ec->vbnv_context, resp->block, - sizeof(resp->block)); + /* TODO(sjg@chromium.org): Support full-size context */ + memcpy(ec->vbnv_context, req->block, + EC_VBNV_BLOCK_SIZE); len = 0; break; default: From 165be50f5ad128e0b87bddf8a12dcafd3c8ba7f4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:38 -0700 Subject: [PATCH 14/32] input: i8042: Use remove() instead of exported functions We should not have exported functions in a driver. The i8042_disable() function is used to disable the keyboard. Provide a remove() method instead, which is the standard way of disabling a device. We could potentially add a method to flush input but that does not seem necessary. Signed-off-by: Simon Glass --- drivers/input/i8042.c | 35 ++++++++++++++++++++--------------- include/i8042.h | 15 --------------- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/drivers/input/i8042.c b/drivers/input/i8042.c index 5678f8e3cf..9a5dc46207 100644 --- a/drivers/input/i8042.c +++ b/drivers/input/i8042.c @@ -167,19 +167,8 @@ static int kbd_controller_present(void) return in8(I8042_STS_REG) != 0xff; } -/* - * Implement a weak default function for boards that optionally - * need to skip the i8042 initialization. - * - * TODO(sjg@chromium.org): Use device tree for this? - */ -int __weak board_i8042_skip(void) -{ - /* As default, don't skip */ - return 0; -} - -void i8042_flush(void) +/** Flush all buffer from keyboard controller to host*/ +static void i8042_flush(void) { int timeout; @@ -202,7 +191,13 @@ void i8042_flush(void) } } -int i8042_disable(void) +/** + * Disables the keyboard so that key strokes no longer generate scancodes to + * the host. + * + * @return 0 if ok, -1 if keyboard input was found while disabling + */ +static int i8042_disable(void) { if (kbd_input_empty() == 0) return -1; @@ -266,7 +261,7 @@ static int i8042_start(struct udevice *dev) char *penv; int ret; - if (!kbd_controller_present() || board_i8042_skip()) { + if (!kbd_controller_present()) { debug("i8042 keyboard controller is not present\n"); return -ENOENT; } @@ -294,6 +289,15 @@ static int i8042_start(struct udevice *dev) return 0; } +static int i8042_kbd_remove(struct udevice *dev) +{ + if (i8042_disable()) + log_debug("i8042_disable() failed. fine, continue.\n"); + i8042_flush(); + + return 0; +} + /** * Set up the i8042 keyboard. This is called by the stdio device handler * @@ -348,6 +352,7 @@ U_BOOT_DRIVER(i8042_kbd) = { .id = UCLASS_KEYBOARD, .of_match = i8042_kbd_ids, .probe = i8042_kbd_probe, + .remove = i8042_kbd_remove, .ops = &i8042_kbd_ops, .priv_auto_alloc_size = sizeof(struct i8042_kbd_priv), }; diff --git a/include/i8042.h b/include/i8042.h index 2b9e5c4d37..8d69fa13bc 100644 --- a/include/i8042.h +++ b/include/i8042.h @@ -72,19 +72,4 @@ #define BRK 0x0100 /* make break flag for keyboard */ #define ALT 0x0200 /* right alt */ -/* exports */ - -/** - * Flush all buffer from keyboard controller to host. - */ -void i8042_flush(void); - -/** - * Disables the keyboard so that key strokes no longer generate scancodes to - * the host. - * - * @return 0 if ok, -1 if keyboard input was found while disabling - */ -int i8042_disable(void); - #endif /* _I8042_H_ */ From 4a978e86d73e792b3136ad9e83df4ba566a040c7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:39 -0700 Subject: [PATCH 15/32] video: backlight: Fix log message in enable_sequence() This has an extra argument. Remove it. Signed-off-by: Simon Glass Acked-by: Anatolij Gustschin --- drivers/video/pwm_backlight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/pwm_backlight.c b/drivers/video/pwm_backlight.c index c13a907709..bd733f5f1c 100644 --- a/drivers/video/pwm_backlight.c +++ b/drivers/video/pwm_backlight.c @@ -78,7 +78,7 @@ static int enable_sequence(struct udevice *dev, int seq) ret = regulator_set_enable(priv->reg, true); if (ret) { log_debug("Cannot enable regulator for PWM '%s'\n", - __func__, dev->name); + dev->name); return log_ret(ret); } mdelay(120); From 49c751603c5abfe32019640834bc34a0a424eb57 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:40 -0700 Subject: [PATCH 16/32] time: Update mdelay() to delay in one large chunk The current function delays in one millisecond at a time. This does not work well on sandbox since it results in lots of calls to usleep(1000) in a tight loop. This makes the sleep duration quite variable since each call results in a sleep of *at least* 1000us, but possibly more. Depending on how busy the machine is, the sleep time can change quite a bit. We cannot fix this in general, but we can reduce the effect by doing a single sleep. The multiplication works fine with an unsigned long argument up until a sleep time of about 4m milliseconds. This is over an hour and we can be sure that delays of that length are not useful. Update the mdelay() function to call udelay() only once with the calculated delay value. Signed-off-by: Simon Glass --- include/linux/delay.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/linux/delay.h b/include/linux/delay.h index 193603451a..71a38e15fb 100644 --- a/include/linux/delay.h +++ b/include/linux/delay.h @@ -10,8 +10,7 @@ void udelay(unsigned long usec); static inline void mdelay(unsigned long msec) { - while (msec--) - udelay(1000); + udelay(1000 * msec); } static inline void ndelay(unsigned long nsec) From 277f4eb2e88ba64e0926b189f99d548069089160 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:42 -0700 Subject: [PATCH 17/32] Add UINT32_MAX and UINT64_MAX These constants are defined by stdint.h but not by kernel.h, which is its stand-in in U-Boot. Add the definitions so that libraries which expect stdint.h constants can work. Signed-off-by: Simon Glass --- include/linux/kernel.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 04a09eb4f6..bd88483b9f 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -33,6 +33,10 @@ #define S64_MAX ((s64)(U64_MAX>>1)) #define S64_MIN ((s64)(-S64_MAX - 1)) +/* Aliases defined by stdint.h */ +#define UINT32_MAX U32_MAX +#define UINT64_MAX U64_MAX + #define STACK_MAGIC 0xdeadbeef #define REPEAT_BYTE(x) ((~0ul / 0xff) * (x)) From bcb514ac02e8b8b823b7db4faa00ddcb8e78876a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 23 Nov 2018 21:29:43 -0700 Subject: [PATCH 18/32] Add inttypes.h Even if U-Boot does not use this, some libraries do. Add back this header file so that the build does not fall back to using the host version, which may include stdint.h and break the build due to conflicts with uint64_t, etc. This partially reverts commit dee37fc99d94 ("Remove includes and PRI* usages in printf() entirely") The only change from the file that was in U-Boot until recently is that it now comes twice as close to passing checkpatch. The remaining warnings pertain to the typedefs, which checkpatch does not like. Signed-off-by: Simon Glass --- include/inttypes.h | 271 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 include/inttypes.h diff --git a/include/inttypes.h b/include/inttypes.h new file mode 100644 index 0000000000..dcb6785228 --- /dev/null +++ b/include/inttypes.h @@ -0,0 +1,271 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 1997-2001, 2004, 2007 Free Software Foundation, Inc. + * + * This file is taken from the GNU C Library v2.15, with the unimplemented + * functions removed and a few style fixes. + */ + +/* + * ISO C99: 7.8 Format conversion of integer types + */ + +#ifndef _INTTYPES_H +#define _INTTYPES_H 1 + +#include + +/* Get a definition for wchar_t. But we must not define wchar_t itself. */ +#ifndef ____gwchar_t_defined +# ifdef __cplusplus +# define __gwchar_t wchar_t +# elif defined __WCHAR_TYPE__ +typedef __WCHAR_TYPE__ __gwchar_t; +# else +# define __need_wchar_t +# include +typedef wchar_t __gwchar_t; +# endif +# define ____gwchar_t_defined 1 +#endif + +/* + * The ISO C99 standard specifies that these macros must only be defined if + * explicitly requested + */ +#if !defined __cplusplus || defined __STDC_FORMAT_MACROS + +/* linux/types.h always uses long long for 64-bit and long for uintptr_t */ +# define __PRI64_PREFIX "ll" +# define __PRIPTR_PREFIX "l" + +/* Macros for printing format specifiers. */ + +/* Decimal notation. */ +# define PRId8 "d" +# define PRId16 "d" +# define PRId32 "d" +# define PRId64 __PRI64_PREFIX "d" + +# define PRIdLEAST8 "d" +# define PRIdLEAST16 "d" +# define PRIdLEAST32 "d" +# define PRIdLEAST64 __PRI64_PREFIX "d" + +# define PRIdFAST8 "d" +# define PRIdFAST16 __PRIPTR_PREFIX "d" +# define PRIdFAST32 __PRIPTR_PREFIX "d" +# define PRIdFAST64 __PRI64_PREFIX "d" + +# define PRIi8 "i" +# define PRIi16 "i" +# define PRIi32 "i" +# define PRIi64 __PRI64_PREFIX "i" + +# define PRIiLEAST8 "i" +# define PRIiLEAST16 "i" +# define PRIiLEAST32 "i" +# define PRIiLEAST64 __PRI64_PREFIX "i" + +# define PRIiFAST8 "i" +# define PRIiFAST16 __PRIPTR_PREFIX "i" +# define PRIiFAST32 __PRIPTR_PREFIX "i" +# define PRIiFAST64 __PRI64_PREFIX "i" + +/* Octal notation. */ +# define PRIo8 "o" +# define PRIo16 "o" +# define PRIo32 "o" +# define PRIo64 __PRI64_PREFIX "o" + +# define PRIoLEAST8 "o" +# define PRIoLEAST16 "o" +# define PRIoLEAST32 "o" +# define PRIoLEAST64 __PRI64_PREFIX "o" + +# define PRIoFAST8 "o" +# define PRIoFAST16 __PRIPTR_PREFIX "o" +# define PRIoFAST32 __PRIPTR_PREFIX "o" +# define PRIoFAST64 __PRI64_PREFIX "o" + +/* Unsigned integers. */ +# define PRIu8 "u" +# define PRIu16 "u" +# define PRIu32 "u" +# define PRIu64 __PRI64_PREFIX "u" + +# define PRIuLEAST8 "u" +# define PRIuLEAST16 "u" +# define PRIuLEAST32 "u" +# define PRIuLEAST64 __PRI64_PREFIX "u" + +# define PRIuFAST8 "u" +# define PRIuFAST16 __PRIPTR_PREFIX "u" +# define PRIuFAST32 __PRIPTR_PREFIX "u" +# define PRIuFAST64 __PRI64_PREFIX "u" + +/* lowercase hexadecimal notation. */ +# define PRIx8 "x" +# define PRIx16 "x" +# define PRIx32 "x" +# define PRIx64 __PRI64_PREFIX "x" + +# define PRIxLEAST8 "x" +# define PRIxLEAST16 "x" +# define PRIxLEAST32 "x" +# define PRIxLEAST64 __PRI64_PREFIX "x" + +# define PRIxFAST8 "x" +# define PRIxFAST16 __PRIPTR_PREFIX "x" +# define PRIxFAST32 __PRIPTR_PREFIX "x" +# define PRIxFAST64 __PRI64_PREFIX "x" + +/* UPPERCASE hexadecimal notation. */ +# define PRIX8 "X" +# define PRIX16 "X" +# define PRIX32 "X" +# define PRIX64 __PRI64_PREFIX "X" + +# define PRIXLEAST8 "X" +# define PRIXLEAST16 "X" +# define PRIXLEAST32 "X" +# define PRIXLEAST64 __PRI64_PREFIX "X" + +# define PRIXFAST8 "X" +# define PRIXFAST16 __PRIPTR_PREFIX "X" +# define PRIXFAST32 __PRIPTR_PREFIX "X" +# define PRIXFAST64 __PRI64_PREFIX "X" + +/* Macros for printing `intmax_t' and `uintmax_t'. */ +# define PRIdMAX __PRI64_PREFIX "d" +# define PRIiMAX __PRI64_PREFIX "i" +# define PRIoMAX __PRI64_PREFIX "o" +# define PRIuMAX __PRI64_PREFIX "u" +# define PRIxMAX __PRI64_PREFIX "x" +# define PRIXMAX __PRI64_PREFIX "X" + +/* Macros for printing `intptr_t' and `uintptr_t'. */ +# define PRIdPTR __PRIPTR_PREFIX "d" +# define PRIiPTR __PRIPTR_PREFIX "i" +# define PRIoPTR __PRIPTR_PREFIX "o" +# define PRIuPTR __PRIPTR_PREFIX "u" +# define PRIxPTR __PRIPTR_PREFIX "x" +# define PRIXPTR __PRIPTR_PREFIX "X" + +/* Macros for scanning format specifiers. */ + +/* Signed decimal notation. */ +# define SCNd8 "hhd" +# define SCNd16 "hd" +# define SCNd32 "d" +# define SCNd64 __PRI64_PREFIX "d" + +# define SCNdLEAST8 "hhd" +# define SCNdLEAST16 "hd" +# define SCNdLEAST32 "d" +# define SCNdLEAST64 __PRI64_PREFIX "d" + +# define SCNdFAST8 "hhd" +# define SCNdFAST16 __PRIPTR_PREFIX "d" +# define SCNdFAST32 __PRIPTR_PREFIX "d" +# define SCNdFAST64 __PRI64_PREFIX "d" + +/* Signed decimal notation. */ +# define SCNi8 "hhi" +# define SCNi16 "hi" +# define SCNi32 "i" +# define SCNi64 __PRI64_PREFIX "i" + +# define SCNiLEAST8 "hhi" +# define SCNiLEAST16 "hi" +# define SCNiLEAST32 "i" +# define SCNiLEAST64 __PRI64_PREFIX "i" + +# define SCNiFAST8 "hhi" +# define SCNiFAST16 __PRIPTR_PREFIX "i" +# define SCNiFAST32 __PRIPTR_PREFIX "i" +# define SCNiFAST64 __PRI64_PREFIX "i" + +/* Unsigned decimal notation. */ +# define SCNu8 "hhu" +# define SCNu16 "hu" +# define SCNu32 "u" +# define SCNu64 __PRI64_PREFIX "u" + +# define SCNuLEAST8 "hhu" +# define SCNuLEAST16 "hu" +# define SCNuLEAST32 "u" +# define SCNuLEAST64 __PRI64_PREFIX "u" + +# define SCNuFAST8 "hhu" +# define SCNuFAST16 __PRIPTR_PREFIX "u" +# define SCNuFAST32 __PRIPTR_PREFIX "u" +# define SCNuFAST64 __PRI64_PREFIX "u" + +/* Octal notation. */ +# define SCNo8 "hho" +# define SCNo16 "ho" +# define SCNo32 "o" +# define SCNo64 __PRI64_PREFIX "o" + +# define SCNoLEAST8 "hho" +# define SCNoLEAST16 "ho" +# define SCNoLEAST32 "o" +# define SCNoLEAST64 __PRI64_PREFIX "o" + +# define SCNoFAST8 "hho" +# define SCNoFAST16 __PRIPTR_PREFIX "o" +# define SCNoFAST32 __PRIPTR_PREFIX "o" +# define SCNoFAST64 __PRI64_PREFIX "o" + +/* Hexadecimal notation. */ +# define SCNx8 "hhx" +# define SCNx16 "hx" +# define SCNx32 "x" +# define SCNx64 __PRI64_PREFIX "x" + +# define SCNxLEAST8 "hhx" +# define SCNxLEAST16 "hx" +# define SCNxLEAST32 "x" +# define SCNxLEAST64 __PRI64_PREFIX "x" + +# define SCNxFAST8 "hhx" +# define SCNxFAST16 __PRIPTR_PREFIX "x" +# define SCNxFAST32 __PRIPTR_PREFIX "x" +# define SCNxFAST64 __PRI64_PREFIX "x" + +/* Macros for scanning `intmax_t' and `uintmax_t'. */ +# define SCNdMAX __PRI64_PREFIX "d" +# define SCNiMAX __PRI64_PREFIX "i" +# define SCNoMAX __PRI64_PREFIX "o" +# define SCNuMAX __PRI64_PREFIX "u" +# define SCNxMAX __PRI64_PREFIX "x" + +/* Macros for scanning `intptr_t' and `uintptr_t'. */ +# define SCNdPTR __PRIPTR_PREFIX "d" +# define SCNiPTR __PRIPTR_PREFIX "i" +# define SCNoPTR __PRIPTR_PREFIX "o" +# define SCNuPTR __PRIPTR_PREFIX "u" +# define SCNxPTR __PRIPTR_PREFIX "x" + +#endif /* C++ && format macros */ + +#if __WORDSIZE == 64 + +/* We have to define the `uintmax_t' type using `ldiv_t'. */ +typedef struct { + long int quot; /* Quotient. */ + long int rem; /* Remainder. */ +} imaxdiv_t; + +#else + +/* We have to define the `uintmax_t' type using `lldiv_t'. */ +typedef struct { + long long int quot; /* Quotient. */ + long long int rem; /* Remainder. */ +} imaxdiv_t; + +#endif + +#endif /* inttypes.h */ From d82f539ab900c52a669a4f8407a39b8fb125f0ab Mon Sep 17 00:00:00 2001 From: Trevor Woerner Date: Wed, 21 Nov 2018 03:31:12 -0500 Subject: [PATCH 19/32] buildman/toolchain.py: fix toolchain directory The hexagon toolchain (4.6.1) from kernel.org, for example, was packaged in a way that is different from most toolchains. The first entry when unpacking most toolchain tarballs is: gcc--nolib/- e.g.: gcc-8.1.0-nolibc/aarch64-linux/ The first entry of the hexagon toolchain, however, is: gcc-4.6.1-nolibc/ This causes the buildman logic in toolchain.py::ScanPath() to not be able to find the "*gcc" executable since it looks in gcc-4.6.1-nolib/{.|bin|usr/bin} instead of gcc-4.6.1/hexagon-linux/{.|bin|usr/bin}. Therefore when buildman tries to download a set of toolchains that includes hexagon, the script fails. This update takes the second line of the tarball unpacking (which works for all the toolchains I've tested from kernel.org) and parses it to take the first two elements, separated by '/'. It makes this logic a bit more robust. Signed-off-by: Trevor Woerner Reviewed-by: Simon Glass --- tools/buildman/toolchain.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/buildman/toolchain.py b/tools/buildman/toolchain.py index 4b35f400e9..59dd309c2b 100644 --- a/tools/buildman/toolchain.py +++ b/tools/buildman/toolchain.py @@ -502,7 +502,8 @@ class Toolchains: trailing / """ stdout = command.Output('tar', 'xvfJ', fname, '-C', dest) - return stdout.splitlines()[0][:-1] + dirs = stdout.splitlines()[1].split('/')[:2] + return '/'.join(dirs) def TestSettingsHasPath(self, path): """Check if buildman will find this toolchain From b11f12642f4da249d5f07bb45ba5ba9b01235818 Mon Sep 17 00:00:00 2001 From: Trevor Woerner Date: Wed, 21 Nov 2018 03:31:13 -0500 Subject: [PATCH 20/32] buildman/toolchain.py: handle inconsistent tarball names Unfortunately, for some releases the kernel.org toolchain tarball names adhere to the following pattern: -gcc--nolib--.tar.xz e.g.: x86_64-gcc-8.1.0-nolibc-aarch64-linux.tar.xz while others use the following pattern: -gcc--nolib_-.tar.xz e.g.: x86_64-gcc-7.3.0-nolibc_aarch64-linux.tar.xz Notice that the first pattern has dashes throughout, while the second has dashes throughout except just before the target architecture which has an underscore. The "dash throughout" versions from kernel.org are: 8.1.0, 6.4.0, 5.5.0, 4.9.4, 4.8.5, 4.6.1 while the "dash and underscore" versions from kernel.org are: 7.3.0, 4.9.0, 4.8.0, 4.7.3, 4.6.3, 4.6.2, 4.5.1, 4.2.4 This tweak allows the code to handle both versions. Note that this tweak also causes the architecture parsing to get confused and find the following two bogus architectures, "2.0" and "64", which are explicitly checked for, and removed. Signed-off-by: Trevor Woerner Reviewed-by: Simon Glass Change single quotes to double quotes: Signed-off-by: Simon Glass --- tools/buildman/toolchain.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/buildman/toolchain.py b/tools/buildman/toolchain.py index 59dd309c2b..c62ce136fa 100644 --- a/tools/buildman/toolchain.py +++ b/tools/buildman/toolchain.py @@ -517,13 +517,14 @@ class Toolchains: def ListArchs(self): """List architectures with available toolchains to download""" host_arch, archives = self.LocateArchUrl('list') - re_arch = re.compile('[-a-z0-9.]*_([^-]*)-.*') + re_arch = re.compile('[-a-z0-9.]*[-_]([^-]*)-.*') arch_set = set() for archive in archives: # Remove the host architecture from the start arch = re_arch.match(archive[len(host_arch):]) if arch: - arch_set.add(arch.group(1)) + if arch.group(1) != '2.0' and arch.group(1) != '64': + arch_set.add(arch.group(1)) return sorted(arch_set) def FetchAndInstall(self, arch): From a4b33c5aba8cd155d5cf49eeaf7fce38a1965fc1 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Sun, 25 Nov 2018 19:32:54 +0100 Subject: [PATCH 21/32] dm: rtc: Fix function name in comment The documentation comment for dm_rtc_set was referring to dm_rtc_put instead. Fix it. Signed-off-by: Philipp Tomsich --- include/rtc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/rtc.h b/include/rtc.h index 0d964d56d5..2c3a5743e3 100644 --- a/include/rtc.h +++ b/include/rtc.h @@ -86,7 +86,7 @@ struct rtc_ops { int dm_rtc_get(struct udevice *dev, struct rtc_time *time); /** - * dm_rtc_put() - Write a time to an RTC + * dm_rtc_set() - Write a time to an RTC * * @dev: Device to read from * @time: Time to write into the RTC From 759a99c24201eac0a9ade628021cd49d208f0fbb Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Sun, 25 Nov 2018 19:38:54 +0100 Subject: [PATCH 22/32] dm: (re)sort uclass ids alphabetically The comment in uclass-id.h states that "U-Boot uclasses start here - in alphabetical order" but the subsequent list is not sorted alphabetically. This reestablishes order. Signed-off-by: Philipp Tomsich --- include/dm/uclass-id.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index a5fcb69dba..62d9e2f404 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -29,6 +29,7 @@ enum uclass_id { /* U-Boot uclasses start here - in alphabetical order */ UCLASS_ADC, /* Analog-to-digital converter */ UCLASS_AHCI, /* SATA disk controller */ + UCLASS_AXI, /* AXI bus */ UCLASS_BLK, /* Block device */ UCLASS_BOARD, /* Device information from hardware */ UCLASS_CLK, /* Clock source, e.g. used by peripherals */ @@ -38,15 +39,14 @@ enum uclass_id { UCLASS_DMA, /* Direct Memory Access */ UCLASS_EFI, /* EFI managed devices */ UCLASS_ETH, /* Ethernet device */ + UCLASS_FIRMWARE, /* Firmware */ UCLASS_FS_FIRMWARE_LOADER, /* Generic loader */ UCLASS_GPIO, /* Bank of general-purpose I/O pins */ - UCLASS_FIRMWARE, /* Firmware */ UCLASS_I2C, /* I2C bus */ UCLASS_I2C_EEPROM, /* I2C EEPROM device */ UCLASS_I2C_GENERIC, /* Generic I2C device */ UCLASS_I2C_MUX, /* I2C multiplexer */ UCLASS_IDE, /* IDE device */ - UCLASS_AXI, /* AXI bus */ UCLASS_IRQ, /* Interrupt controller */ UCLASS_KEYBOARD, /* Keyboard input device */ UCLASS_LED, /* Light-emitting diode (LED) */ @@ -68,8 +68,8 @@ enum uclass_id { UCLASS_PINCONFIG, /* Pin configuration node device */ UCLASS_PINCTRL, /* Pinctrl (pin muxing/configuration) device */ UCLASS_PMIC, /* PMIC I/O device */ - UCLASS_PWM, /* Pulse-width modulator */ UCLASS_POWER_DOMAIN, /* (SoC) Power domains */ + UCLASS_PWM, /* Pulse-width modulator */ UCLASS_PWRSEQ, /* Power sequence device */ UCLASS_RAM, /* RAM controller */ UCLASS_REGULATOR, /* Regulator device */ @@ -81,9 +81,9 @@ enum uclass_id { UCLASS_SIMPLE_BUS, /* Bus with child devices */ UCLASS_SMEM, /* Shared memory interface */ UCLASS_SPI, /* SPI bus */ - UCLASS_SPMI, /* System Power Management Interface bus */ UCLASS_SPI_FLASH, /* SPI flash */ UCLASS_SPI_GENERIC, /* Generic SPI flash target */ + UCLASS_SPMI, /* System Power Management Interface bus */ UCLASS_SYSCON, /* System configuration device */ UCLASS_SYSRESET, /* System reset device */ UCLASS_TEE, /* Trusted Execution Environment device */ From bb48470df21c0ce4ebed47f5dc3ea25ff02fd4dd Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 25 Nov 2018 20:07:26 -0700 Subject: [PATCH 23/32] binman: Add myself as maintainer Add an entry for my maintainership of this tool. Signed-off-by: Simon Glass --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8ea8ef9924..0cec39c542 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -380,6 +380,11 @@ S: Maintained T: git git://git.denx.de/u-boot-microblaze.git F: arch/arm/mach-zynqmp-r5/ +BINMAN +M: Simon Glass +S: Maintained +F: tools/binman/ + BUILDMAN M: Simon Glass S: Maintained From 7959882049a9b389c131eff9a128437ee8ebe08e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Mon, 3 Dec 2018 19:37:09 +0100 Subject: [PATCH 24/32] dm: core: add functions to get/remap I/O addresses by name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This functions allow us to get and remap I/O addresses by name, which is useful when there are multiple reg addresses indexed by reg-names property. This is needed in bmips dma/eth patch series, but can also be used on many other drivers. Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Daniel Schwierzeck Reviewed-by: Simon Glass --- arch/sandbox/dts/test.dts | 1 + drivers/core/fdtaddr.c | 10 +++++ drivers/core/read.c | 20 ++++++++++ include/dm/fdtaddr.h | 13 +++++++ include/dm/read.h | 36 +++++++++++++++++ test/dm/test-fdt.c | 82 ++++++++++++++++++++++++++++++++++++++- 6 files changed, 160 insertions(+), 2 deletions(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 252aa7b6b6..6722e18bc3 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -690,6 +690,7 @@ dev@0,0 { compatible = "denx,u-boot-fdt-dummy"; reg = <0 0x0 0x1000>; + reg-names = "sandbox-dummy-0"; }; dev@1,100 { diff --git a/drivers/core/fdtaddr.c b/drivers/core/fdtaddr.c index bfd9580050..e113f1dd39 100644 --- a/drivers/core/fdtaddr.c +++ b/drivers/core/fdtaddr.c @@ -146,6 +146,16 @@ void *devfdt_remap_addr_index(struct udevice *dev, int index) return map_physmem(addr, 0, MAP_NOCACHE); } +void *devfdt_remap_addr_name(struct udevice *dev, const char *name) +{ + fdt_addr_t addr = devfdt_get_addr_name(dev, name); + + if (addr == FDT_ADDR_T_NONE) + return NULL; + + return map_physmem(addr, 0, MAP_NOCACHE); +} + void *devfdt_remap_addr(struct udevice *dev) { return devfdt_remap_addr_index(dev, 0); diff --git a/drivers/core/read.c b/drivers/core/read.c index 96766c7876..cdd78be03e 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -69,6 +69,26 @@ void *dev_remap_addr_index(struct udevice *dev, int index) return map_physmem(addr, 0, MAP_NOCACHE); } +fdt_addr_t dev_read_addr_name(struct udevice *dev, const char *name) +{ + int index = dev_read_stringlist_search(dev, "reg-names", name); + + if (index < 0) + return FDT_ADDR_T_NONE; + else + return dev_read_addr_index(dev, index); +} + +void *dev_remap_addr_name(struct udevice *dev, const char *name) +{ + fdt_addr_t addr = dev_read_addr_name(dev, name); + + if (addr == FDT_ADDR_T_NONE) + return NULL; + + return map_physmem(addr, 0, MAP_NOCACHE); +} + fdt_addr_t dev_read_addr(struct udevice *dev) { return dev_read_addr_index(dev, 0); diff --git a/include/dm/fdtaddr.h b/include/dm/fdtaddr.h index 49a6ffd5f8..c171d9bc2f 100644 --- a/include/dm/fdtaddr.h +++ b/include/dm/fdtaddr.h @@ -55,6 +55,19 @@ void *devfdt_remap_addr(struct udevice *dev); */ void *devfdt_remap_addr_index(struct udevice *dev, int index); +/** + * devfdt_remap_addr_name() - Get the reg property of a device, indexed by + * name, as a memory-mapped I/O pointer + * @name: the 'reg' property can hold a list of pairs, with the + * 'reg-names' property providing named-based identification. @index + * indicates the value to search for in 'reg-names'. + * + * @dev: Pointer to a device + * + * @return Pointer to addr, or NULL if there is no such property + */ +void *devfdt_remap_addr_name(struct udevice *dev, const char *name); + /** * devfdt_map_physmem() - Read device address from reg property of the * device node and map the address into CPU address diff --git a/include/dm/read.h b/include/dm/read.h index a27b8554fb..efcbee15ec 100644 --- a/include/dm/read.h +++ b/include/dm/read.h @@ -124,6 +124,31 @@ fdt_addr_t dev_read_addr_index(struct udevice *dev, int index); */ void *dev_remap_addr_index(struct udevice *dev, int index); +/** + * dev_read_addr_name() - Get the reg property of a device, indexed by name + * + * @dev: Device to read from + * @name: the 'reg' property can hold a list of pairs, with the + * 'reg-names' property providing named-based identification. @index + * indicates the value to search for in 'reg-names'. + * + * @return address or FDT_ADDR_T_NONE if not found + */ +fdt_addr_t dev_read_addr_name(struct udevice *dev, const char* name); + +/** + * dev_remap_addr_name() - Get the reg property of a device, indexed by name, + * as a memory-mapped I/O pointer + * + * @dev: Device to read from + * @name: the 'reg' property can hold a list of pairs, with the + * 'reg-names' property providing named-based identification. @index + * indicates the value to search for in 'reg-names'. + * + * @return pointer or NULL if not found + */ +void *dev_remap_addr_name(struct udevice *dev, const char* name); + /** * dev_read_addr() - Get the reg property of a device * @@ -494,6 +519,12 @@ static inline fdt_addr_t dev_read_addr_index(struct udevice *dev, int index) return devfdt_get_addr_index(dev, index); } +static inline fdt_addr_t dev_read_addr_name(struct udevice *dev, + const char *name) +{ + return devfdt_get_addr_name(dev, name); +} + static inline fdt_addr_t dev_read_addr(struct udevice *dev) { return devfdt_get_addr(dev); @@ -514,6 +545,11 @@ static inline void *dev_remap_addr_index(struct udevice *dev, int index) return devfdt_remap_addr_index(dev, index); } +static inline void *dev_remap_addr_name(struct udevice *dev, const char *name) +{ + return devfdt_remap_addr_name(dev, name); +} + static inline fdt_addr_t dev_read_addr_size(struct udevice *dev, const char *propname, fdt_size_t *sizep) diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c index 0fbd9be765..96d2528acc 100644 --- a/test/dm/test-fdt.c +++ b/test/dm/test-fdt.c @@ -490,7 +490,6 @@ static int dm_test_fdt_translation(struct unit_test_state *uts) } DM_TEST(dm_test_fdt_translation, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); -/* Test devfdt_remap_addr_index() */ static int dm_test_fdt_remap_addr_flat(struct unit_test_state *uts) { struct udevice *dev; @@ -511,7 +510,46 @@ static int dm_test_fdt_remap_addr_flat(struct unit_test_state *uts) DM_TEST(dm_test_fdt_remap_addr_flat, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | DM_TESTF_FLAT_TREE); -/* Test dev_remap_addr_index() */ +static int dm_test_fdt_remap_addr_index_flat(struct unit_test_state *uts) +{ + struct udevice *dev; + fdt_addr_t addr; + void *paddr; + + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev)); + + addr = devfdt_get_addr_index(dev, 0); + ut_asserteq(0x8000, addr); + + paddr = map_physmem(addr, 0, MAP_NOCACHE); + ut_assertnonnull(paddr); + ut_asserteq_ptr(paddr, devfdt_remap_addr_index(dev, 0)); + + return 0; +} +DM_TEST(dm_test_fdt_remap_addr_index_flat, + DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | DM_TESTF_FLAT_TREE); + +static int dm_test_fdt_remap_addr_name_flat(struct unit_test_state *uts) +{ + struct udevice *dev; + fdt_addr_t addr; + void *paddr; + + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev)); + + addr = devfdt_get_addr_name(dev, "sandbox-dummy-0"); + ut_asserteq(0x8000, addr); + + paddr = map_physmem(addr, 0, MAP_NOCACHE); + ut_assertnonnull(paddr); + ut_asserteq_ptr(paddr, devfdt_remap_addr_name(dev, "sandbox-dummy-0")); + + return 0; +} +DM_TEST(dm_test_fdt_remap_addr_name_flat, + DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | DM_TESTF_FLAT_TREE); + static int dm_test_fdt_remap_addr_live(struct unit_test_state *uts) { struct udevice *dev; @@ -532,6 +570,46 @@ static int dm_test_fdt_remap_addr_live(struct unit_test_state *uts) DM_TEST(dm_test_fdt_remap_addr_live, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); +static int dm_test_fdt_remap_addr_index_live(struct unit_test_state *uts) +{ + struct udevice *dev; + fdt_addr_t addr; + void *paddr; + + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev)); + + addr = dev_read_addr_index(dev, 0); + ut_asserteq(0x8000, addr); + + paddr = map_physmem(addr, 0, MAP_NOCACHE); + ut_assertnonnull(paddr); + ut_asserteq_ptr(paddr, dev_remap_addr_index(dev, 0)); + + return 0; +} +DM_TEST(dm_test_fdt_remap_addr_index_live, + DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +static int dm_test_fdt_remap_addr_name_live(struct unit_test_state *uts) +{ + struct udevice *dev; + fdt_addr_t addr; + void *paddr; + + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev)); + + addr = dev_read_addr_name(dev, "sandbox-dummy-0"); + ut_asserteq(0x8000, addr); + + paddr = map_physmem(addr, 0, MAP_NOCACHE); + ut_assertnonnull(paddr); + ut_asserteq_ptr(paddr, dev_remap_addr_name(dev, "sandbox-dummy-0")); + + return 0; +} +DM_TEST(dm_test_fdt_remap_addr_name_live, + DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + static int dm_test_fdt_livetree_writing(struct unit_test_state *uts) { struct udevice *dev; From 4f86a724e82c0b74d9ffb7b65f8ae4b011dd0b03 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 15 Nov 2018 13:45:31 +0100 Subject: [PATCH 25/32] power: regulator: denied disable on always-on regulator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't disable regulator which are tagged as "regulator-always-on" in DT. Signed-off-by: Patrick Delaunay Reviewed-by: Simon Glass Reviewed-by: Jack Mitchell Tested-by: Jack Mitchell Signed-off-by: Patrice Chotard Reviewed-by: Richard Röjfors Tested-by: Richard Röjfors Reviewed-by: Felix Brack Tested-by: Felix Brack --- drivers/power/regulator/regulator-uclass.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/power/regulator/regulator-uclass.c b/drivers/power/regulator/regulator-uclass.c index 4da8e43259..4511625ff2 100644 --- a/drivers/power/regulator/regulator-uclass.c +++ b/drivers/power/regulator/regulator-uclass.c @@ -106,10 +106,15 @@ int regulator_get_enable(struct udevice *dev) int regulator_set_enable(struct udevice *dev, bool enable) { const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); + struct dm_regulator_uclass_platdata *uc_pdata; if (!ops || !ops->set_enable) return -ENOSYS; + uc_pdata = dev_get_uclass_platdata(dev); + if (!enable && uc_pdata->always_on) + return -EACCES; + return ops->set_enable(dev, enable); } From ac7f5db9dc690901d99fe0afbcb3d4241c3cab8e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Nov 2018 23:52:32 +0200 Subject: [PATCH 26/32] dm: serial: Add ->getconfig() callback In some cases it would be good to know the settings, such as parity, of current serial console. One example might be an ACPI SPCR table to generate using these parameters. Signed-off-by: Andy Shevchenko Reviewed-by: Simon Glass --- drivers/serial/sandbox.c | 13 +++++++++++++ drivers/serial/serial-uclass.c | 16 ++++++++++++++++ include/common.h | 1 + include/serial.h | 26 +++++++++++++++++++++++--- test/dm/serial.c | 7 +++++++ 5 files changed, 60 insertions(+), 3 deletions(-) diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c index 4a05ea44ce..76d26d3c59 100644 --- a/drivers/serial/sandbox.c +++ b/drivers/serial/sandbox.c @@ -163,6 +163,18 @@ DEBUG_UART_FUNCS #endif /* CONFIG_DEBUG_UART_SANDBOX */ +static int sandbox_serial_getconfig(struct udevice *dev, uint *serial_config) +{ + uint config = SERIAL_DEFAULT_CONFIG; + + if (!serial_config) + return -EINVAL; + + *serial_config = config; + + return 0; +} + static int sandbox_serial_setconfig(struct udevice *dev, uint serial_config) { u8 parity = SERIAL_GET_PARITY(serial_config); @@ -207,6 +219,7 @@ static const struct dm_serial_ops sandbox_serial_ops = { .putc = sandbox_serial_putc, .pending = sandbox_serial_pending, .getc = sandbox_serial_getc, + .getconfig = sandbox_serial_getconfig, .setconfig = sandbox_serial_setconfig, }; diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 3ded62732d..51ae1763fb 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -294,6 +294,20 @@ void serial_setbrg(void) ops->setbrg(gd->cur_serial_dev, gd->baudrate); } +int serial_getconfig(uint *config) +{ + struct dm_serial_ops *ops; + + if (!gd->cur_serial_dev) + return 0; + + ops = serial_get_ops(gd->cur_serial_dev); + if (ops->getconfig) + return ops->getconfig(gd->cur_serial_dev, config); + + return 0; +} + int serial_setconfig(uint config) { struct dm_serial_ops *ops; @@ -419,6 +433,8 @@ static int serial_post_probe(struct udevice *dev) ops->pending += gd->reloc_off; if (ops->clear) ops->clear += gd->reloc_off; + if (ops->getconfig) + ops->getconfig += gd->reloc_off; if (ops->setconfig) ops->setconfig += gd->reloc_off; #if CONFIG_POST & CONFIG_SYS_POST_UART diff --git a/include/common.h b/include/common.h index a8e879e1b9..57478365c7 100644 --- a/include/common.h +++ b/include/common.h @@ -364,6 +364,7 @@ void serial_putc_raw(const char); void serial_puts (const char *); int serial_getc (void); int serial_tstc (void); +int serial_getconfig(uint *config); int serial_setconfig(uint config); /* $(CPU)/speed.c */ diff --git a/include/serial.h b/include/serial.h index 9133d07fd5..de21514c0c 100644 --- a/include/serial.h +++ b/include/serial.h @@ -75,6 +75,8 @@ enum serial_par { #define SERIAL_PAR_SHIFT 0 #define SERIAL_PAR_MASK (0x03 << SERIAL_PAR_SHIFT) +#define SERIAL_SET_PARITY(parity) \ + ((parity << SERIAL_PAR_SHIFT) & SERIAL_PAR_MASK) #define SERIAL_GET_PARITY(config) \ ((config & SERIAL_PAR_MASK) >> SERIAL_PAR_SHIFT) @@ -87,6 +89,8 @@ enum serial_bits { #define SERIAL_BITS_SHIFT 2 #define SERIAL_BITS_MASK (0x3 << SERIAL_BITS_SHIFT) +#define SERIAL_SET_BITS(bits) \ + ((bits << SERIAL_BITS_SHIFT) & SERIAL_BITS_MASK) #define SERIAL_GET_BITS(config) \ ((config & SERIAL_BITS_MASK) >> SERIAL_BITS_SHIFT) @@ -99,6 +103,8 @@ enum serial_stop { #define SERIAL_STOP_SHIFT 4 #define SERIAL_STOP_MASK (0x3 << SERIAL_STOP_SHIFT) +#define SERIAL_SET_STOP(stop) \ + ((stop << SERIAL_STOP_SHIFT) & SERIAL_STOP_MASK) #define SERIAL_GET_STOP(config) \ ((config & SERIAL_STOP_MASK) >> SERIAL_STOP_SHIFT) @@ -107,9 +113,10 @@ enum serial_stop { bits << SERIAL_BITS_SHIFT | \ stop << SERIAL_STOP_SHIFT) -#define SERIAL_DEFAULT_CONFIG SERIAL_PAR_NONE << SERIAL_PAR_SHIFT | \ - SERIAL_8_BITS << SERIAL_BITS_SHIFT | \ - SERIAL_ONE_STOP << SERIAL_STOP_SHIFT +#define SERIAL_DEFAULT_CONFIG \ + (SERIAL_PAR_NONE << SERIAL_PAR_SHIFT | \ + SERIAL_8_BITS << SERIAL_BITS_SHIFT | \ + SERIAL_ONE_STOP << SERIAL_STOP_SHIFT) /** * struct struct dm_serial_ops - Driver model serial operations @@ -188,6 +195,19 @@ struct dm_serial_ops { int (*loop)(struct udevice *dev, int on); #endif + /** + * getconfig() - Get the uart configuration + * (parity, 5/6/7/8 bits word length, stop bits) + * + * Get a current config for this device. + * + * @dev: Device pointer + * @parity: parity to use + * @bits: bits number to use + * @stop: stop bits number to use + * @return 0 if OK, -ve on error + */ + int (*getconfig)(struct udevice *dev, uint *serial_config); /** * setconfig() - Set up the uart configuration * (parity, 5/6/7/8 bits word length, stop bits) diff --git a/test/dm/serial.c b/test/dm/serial.c index 5c603e1f42..7a1a1526a4 100644 --- a/test/dm/serial.c +++ b/test/dm/serial.c @@ -12,6 +12,7 @@ static int dm_test_serial(struct unit_test_state *uts) { struct udevice *dev_serial; + uint value_serial; ut_assertok(uclass_get_device_by_name(UCLASS_SERIAL, "serial", &dev_serial)); @@ -22,6 +23,12 @@ static int dm_test_serial(struct unit_test_state *uts) * sandbox_serial driver */ ut_assertok(serial_setconfig(SERIAL_DEFAULT_CONFIG)); + ut_assertok(serial_getconfig(&value_serial)); + ut_assert(value_serial == SERIAL_DEFAULT_CONFIG); + /* + * test with a parameter which is NULL pointer + */ + ut_asserteq(-EINVAL, serial_getconfig(NULL)); /* * test with a serial config which is not supported by * sandbox_serial driver: test with wrong parity From d5bb4f862b47ad9112132071ad18f9936494e307 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Nov 2018 23:52:33 +0200 Subject: [PATCH 27/32] dm: serial: Introduce ->getinfo() callback New callback will give a necessary information to fill up ACPI SPCR table, for example. Maybe used later for other purposes. Signed-off-by: Andy Shevchenko Reviewed-by: Simon Glass Change ADR_SPACE_SYSTEM_IO to SERIAL_ADDRESS_SPACE_IO to fix build error: Signed-off-by: Simon Glass --- drivers/serial/sandbox.c | 21 ++++++++++++++++++ drivers/serial/serial-uclass.c | 21 ++++++++++++++++++ include/common.h | 3 +++ include/serial.h | 40 ++++++++++++++++++++++++++++++++++ test/dm/serial.c | 5 +++++ 5 files changed, 90 insertions(+) diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c index 76d26d3c59..33102fc872 100644 --- a/drivers/serial/sandbox.c +++ b/drivers/serial/sandbox.c @@ -188,6 +188,26 @@ static int sandbox_serial_setconfig(struct udevice *dev, uint serial_config) return 0; } +static int sandbox_serial_getinfo(struct udevice *dev, + struct serial_device_info *serial_info) +{ + struct serial_device_info info = { + .type = SERIAL_CHIP_UNKNOWN, + .addr_space = SERIAL_ADDRESS_SPACE_IO, + .addr = SERIAL_DEFAULT_ADDRESS, + .reg_width = 1, + .reg_offset = 0, + .reg_shift = 0, + }; + + if (!serial_info) + return -EINVAL; + + *serial_info = info; + + return 0; +} + #if CONFIG_IS_ENABLED(OF_CONTROL) static const char * const ansi_colour[] = { "black", "red", "green", "yellow", "blue", "megenta", "cyan", @@ -221,6 +241,7 @@ static const struct dm_serial_ops sandbox_serial_ops = { .getc = sandbox_serial_getc, .getconfig = sandbox_serial_getconfig, .setconfig = sandbox_serial_setconfig, + .getinfo = sandbox_serial_getinfo, }; static const struct udevice_id sandbox_serial_ids[] = { diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 51ae1763fb..ffcd6d15af 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -322,6 +322,25 @@ int serial_setconfig(uint config) return 0; } +int serial_getinfo(struct serial_device_info *info) +{ + struct dm_serial_ops *ops; + + if (!gd->cur_serial_dev) + return -ENODEV; + + if (!info) + return -EINVAL; + + info->baudrate = gd->baudrate; + + ops = serial_get_ops(gd->cur_serial_dev); + if (ops->getinfo) + return ops->getinfo(gd->cur_serial_dev, info); + + return -EINVAL; +} + void serial_stdio_init(void) { } @@ -441,6 +460,8 @@ static int serial_post_probe(struct udevice *dev) if (ops->loop) ops->loop += gd->reloc_off; #endif + if (ops->getinfo) + ops->getinfo += gd->reloc_off; #endif /* Set the baud rate */ if (ops->setbrg) { diff --git a/include/common.h b/include/common.h index 57478365c7..20c99da1aa 100644 --- a/include/common.h +++ b/include/common.h @@ -357,6 +357,8 @@ void smp_set_core_boot_addr(unsigned long addr, int corenr); void smp_kick_all_cpus(void); /* $(CPU)/serial.c */ +struct serial_device_info; + int serial_init (void); void serial_setbrg (void); void serial_putc (const char); @@ -366,6 +368,7 @@ int serial_getc (void); int serial_tstc (void); int serial_getconfig(uint *config); int serial_setconfig(uint config); +int serial_getinfo(struct serial_device_info *info); /* $(CPU)/speed.c */ int get_clocks (void); diff --git a/include/serial.h b/include/serial.h index de21514c0c..c1a9fee250 100644 --- a/include/serial.h +++ b/include/serial.h @@ -118,6 +118,39 @@ enum serial_stop { SERIAL_8_BITS << SERIAL_BITS_SHIFT | \ SERIAL_ONE_STOP << SERIAL_STOP_SHIFT) +enum serial_chip_type { + SERIAL_CHIP_UNKNOWN = -1, + SERIAL_CHIP_16550_COMPATIBLE, +}; + +enum adr_space_type { + SERIAL_ADDRESS_SPACE_MEMORY = 0, + SERIAL_ADDRESS_SPACE_IO, +}; + +/** + * struct serial_device_info - structure to hold serial device info + * + * @type: type of the UART chip + * @addr_space: address space to access the registers + * @addr: physical address of the registers + * @reg_width: size (in bytes) of the IO accesses to the registers + * @reg_offset: offset to apply to the @addr from the start of the registers + * @reg_shift: quantity to shift the register offsets by + * @baudrate: baud rate + */ +struct serial_device_info { + enum serial_chip_type type; + enum adr_space_type addr_space; + ulong addr; + u8 reg_width; + u8 reg_offset; + u8 reg_shift; + unsigned int baudrate; +}; + +#define SERIAL_DEFAULT_ADDRESS 0xBADACCE5 + /** * struct struct dm_serial_ops - Driver model serial operations * @@ -219,6 +252,13 @@ struct dm_serial_ops { * @return 0 if OK, -ve on error */ int (*setconfig)(struct udevice *dev, uint serial_config); + /** + * getinfo() - Get serial device information + * + * @dev: Device pointer + * @info: struct serial_device_info to fill + */ + int (*getinfo)(struct udevice *dev, struct serial_device_info *info); }; /** diff --git a/test/dm/serial.c b/test/dm/serial.c index 7a1a1526a4..19a15d5d95 100644 --- a/test/dm/serial.c +++ b/test/dm/serial.c @@ -11,6 +11,7 @@ static int dm_test_serial(struct unit_test_state *uts) { + struct serial_device_info info_serial = {0}; struct udevice *dev_serial; uint value_serial; @@ -25,10 +26,14 @@ static int dm_test_serial(struct unit_test_state *uts) ut_assertok(serial_setconfig(SERIAL_DEFAULT_CONFIG)); ut_assertok(serial_getconfig(&value_serial)); ut_assert(value_serial == SERIAL_DEFAULT_CONFIG); + ut_assertok(serial_getinfo(&info_serial)); + ut_assert(info_serial.type == SERIAL_CHIP_UNKNOWN); + ut_assert(info_serial.addr == SERIAL_DEFAULT_ADDRESS); /* * test with a parameter which is NULL pointer */ ut_asserteq(-EINVAL, serial_getconfig(NULL)); + ut_asserteq(-EINVAL, serial_getinfo(NULL)); /* * test with a serial config which is not supported by * sandbox_serial driver: test with wrong parity From 0af761620f2bb0aac739e1f5c2f5c231bc279599 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Nov 2018 23:52:34 +0200 Subject: [PATCH 28/32] serial: ns16550: Group reg_* members of ns16550_platdata Group reg_* members of struct ns16550_platdata together for better maintenance. No functional change intended. Signed-off-by: Andy Shevchenko Reviewed-by: Simon Glass --- include/ns16550.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ns16550.h b/include/ns16550.h index 5fcbcd2e74..f565645d65 100644 --- a/include/ns16550.h +++ b/include/ns16550.h @@ -55,8 +55,8 @@ struct ns16550_platdata { unsigned long base; int reg_shift; - int clock; int reg_offset; + int clock; u32 fcr; }; From 4e7207791c05b3ecff916c1b1b1b21401ec29b0b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Nov 2018 23:52:35 +0200 Subject: [PATCH 29/32] serial: ns16550: Read reg-io-width from device tree Cache the value of the reg-io-width property for the future use. Signed-off-by: Andy Shevchenko Reviewed-by: Simon Glass --- drivers/serial/ns16550.c | 1 + include/ns16550.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 25b9d17243..9d78b1ffc4 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -446,6 +446,7 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev) plat->reg_offset = dev_read_u32_default(dev, "reg-offset", 0); plat->reg_shift = dev_read_u32_default(dev, "reg-shift", 0); + plat->reg_width = dev_read_u32_default(dev, "reg-io-width", 1); err = clk_get_by_index(dev, 0, &clk); if (!err) { diff --git a/include/ns16550.h b/include/ns16550.h index f565645d65..22b89e4d6d 100644 --- a/include/ns16550.h +++ b/include/ns16550.h @@ -49,11 +49,13 @@ * struct ns16550_platdata - information about a NS16550 port * * @base: Base register address + * @reg_width: IO accesses size of registers (in bytes) * @reg_shift: Shift size of registers (0=byte, 1=16bit, 2=32bit...) * @clock: UART base clock speed in Hz */ struct ns16550_platdata { unsigned long base; + int reg_width; int reg_shift; int reg_offset; int clock; From 50bf7d03c26b81f8644c52c6300b6a4c47f5822c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Nov 2018 23:52:36 +0200 Subject: [PATCH 30/32] serial: ns16550: Provide ->getinfo() implementation New callback will supply necessary information, for example, to ACPI SPCR table. Signed-off-by: Andy Shevchenko Reviewed-by: Simon Glass --- drivers/serial/ns16550.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 9d78b1ffc4..f3bd8dbcdf 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -372,6 +372,25 @@ static int ns16550_serial_setconfig(struct udevice *dev, uint serial_config) return 0; } +static int ns16550_serial_getinfo(struct udevice *dev, + struct serial_device_info *info) +{ + struct NS16550 *const com_port = dev_get_priv(dev); + struct ns16550_platdata *plat = com_port->plat; + + info->type = SERIAL_CHIP_16550_COMPATIBLE; +#ifdef CONFIG_SYS_NS16550_PORT_MAPPED + info->addr_space = SERIAL_ADDRESS_SPACE_IO; +#else + info->addr_space = SERIAL_ADDRESS_SPACE_MEMORY; +#endif + info->addr = plat->base; + info->reg_width = plat->reg_width; + info->reg_shift = plat->reg_shift; + info->reg_offset = plat->reg_offset; + return 0; +} + int ns16550_serial_probe(struct udevice *dev) { struct NS16550 *const com_port = dev_get_priv(dev); @@ -479,7 +498,8 @@ const struct dm_serial_ops ns16550_serial_ops = { .pending = ns16550_serial_pending, .getc = ns16550_serial_getc, .setbrg = ns16550_serial_setbrg, - .setconfig = ns16550_serial_setconfig + .setconfig = ns16550_serial_setconfig, + .getinfo = ns16550_serial_getinfo, }; #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) From f3275aa4a17f5307b4c70485e1d75088dd9c4526 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Nov 2018 23:52:37 +0200 Subject: [PATCH 31/32] x86: acpi: Add SPCR table description Add SPCR table description as it provided in Linux kernel. Port subtype for ACPI_DBG2_SERIAL_PORT is used as an interface type in SPCR. Thus, provide a set of definitions to be utilized later. Signed-off-by: Andy Shevchenko Reviewed-by: Bin Meng --- arch/x86/include/asm/acpi_table.h | 49 +++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h index 95fae036f6..51cc806673 100644 --- a/arch/x86/include/asm/acpi_table.h +++ b/arch/x86/include/asm/acpi_table.h @@ -303,6 +303,55 @@ struct acpi_mcfg_mmconfig { /* ACPI global NVS structure */ struct acpi_global_nvs; +/* DBG2 definitions are partially used for SPCR interface_type */ + +/* Types for port_type field */ + +#define ACPI_DBG2_SERIAL_PORT 0x8000 +#define ACPI_DBG2_1394_PORT 0x8001 +#define ACPI_DBG2_USB_PORT 0x8002 +#define ACPI_DBG2_NET_PORT 0x8003 + +/* Subtypes for port_subtype field */ + +#define ACPI_DBG2_16550_COMPATIBLE 0x0000 +#define ACPI_DBG2_16550_SUBSET 0x0001 +#define ACPI_DBG2_ARM_PL011 0x0003 +#define ACPI_DBG2_ARM_SBSA_32BIT 0x000D +#define ACPI_DBG2_ARM_SBSA_GENERIC 0x000E +#define ACPI_DBG2_ARM_DCC 0x000F +#define ACPI_DBG2_BCM2835 0x0010 + +#define ACPI_DBG2_1394_STANDARD 0x0000 + +#define ACPI_DBG2_USB_XHCI 0x0000 +#define ACPI_DBG2_USB_EHCI 0x0001 + +/* SPCR (Serial Port Console Redirection table) */ +struct __packed acpi_spcr { + struct acpi_table_header header; + u8 interface_type; + u8 reserved[3]; + struct acpi_gen_regaddr serial_port; + u8 interrupt_type; + u8 pc_interrupt; + u32 interrupt; /* Global system interrupt */ + u8 baud_rate; + u8 parity; + u8 stop_bits; + u8 flow_control; + u8 terminal_type; + u8 reserved1; + u16 pci_device_id; /* Must be 0xffff if not PCI device */ + u16 pci_vendor_id; /* Must be 0xffff if not PCI device */ + u8 pci_bus; + u8 pci_device; + u8 pci_function; + u32 pci_flags; + u8 pci_segment; + u32 reserved2; +}; + /* These can be used by the target port */ void acpi_fill_header(struct acpi_table_header *header, char *signature); From b288cd9600724ad3a0e55c8786e70741dd13deae Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 20 Nov 2018 23:52:38 +0200 Subject: [PATCH 32/32] x86: acpi: Generate SPCR table Microsoft specifies a SPCR (Serial Port Console Redirection Table) [1]. Let's provide it in U-Boot. [1]: https://docs.microsoft.com/en-us/windows-hardware/drivers/serports/serial-port-console-redirection-table Signed-off-by: Andy Shevchenko Reviewed-by: Simon Glass --- arch/x86/include/asm/acpi_table.h | 2 + arch/x86/lib/acpi_table.c | 118 ++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h index 51cc806673..e3b65cff66 100644 --- a/arch/x86/include/asm/acpi_table.h +++ b/arch/x86/include/asm/acpi_table.h @@ -327,6 +327,8 @@ struct acpi_global_nvs; #define ACPI_DBG2_USB_XHCI 0x0000 #define ACPI_DBG2_USB_EHCI 0x0001 +#define ACPI_DBG2_UNKNOWN 0x00FF + /* SPCR (Serial Port Console Redirection table) */ struct __packed acpi_spcr { struct acpi_table_header header; diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index e48c9b9574..79bc2000bd 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -336,6 +337,115 @@ static void acpi_create_mcfg(struct acpi_mcfg *mcfg) header->checksum = table_compute_checksum((void *)mcfg, header->length); } +static void acpi_create_spcr(struct acpi_spcr *spcr) +{ + struct acpi_table_header *header = &(spcr->header); + struct serial_device_info serial_info = {0}; + ulong serial_address, serial_offset; + uint serial_config; + uint serial_width; + int access_size; + int space_id; + int ret; + + /* Fill out header fields */ + acpi_fill_header(header, "SPCR"); + header->length = sizeof(struct acpi_spcr); + header->revision = 2; + + ret = serial_getinfo(&serial_info); + if (ret) + serial_info.type = SERIAL_CHIP_UNKNOWN; + + /* Encode chip type */ + switch (serial_info.type) { + case SERIAL_CHIP_16550_COMPATIBLE: + spcr->interface_type = ACPI_DBG2_16550_COMPATIBLE; + break; + case SERIAL_CHIP_UNKNOWN: + default: + spcr->interface_type = ACPI_DBG2_UNKNOWN; + break; + } + + /* Encode address space */ + switch (serial_info.addr_space) { + case SERIAL_ADDRESS_SPACE_MEMORY: + space_id = ACPI_ADDRESS_SPACE_MEMORY; + break; + case SERIAL_ADDRESS_SPACE_IO: + default: + space_id = ACPI_ADDRESS_SPACE_IO; + break; + } + + serial_width = serial_info.reg_width * 8; + serial_offset = serial_info.reg_offset << serial_info.reg_shift; + serial_address = serial_info.addr + serial_offset; + + /* Encode register access size */ + switch (serial_info.reg_shift) { + case 0: + access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS; + break; + case 1: + access_size = ACPI_ACCESS_SIZE_WORD_ACCESS; + break; + case 2: + access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS; + break; + case 3: + access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS; + break; + default: + access_size = ACPI_ACCESS_SIZE_UNDEFINED; + break; + } + + debug("UART type %u @ %lx\n", spcr->interface_type, serial_address); + + /* Fill GAS */ + spcr->serial_port.space_id = space_id; + spcr->serial_port.bit_width = serial_width; + spcr->serial_port.bit_offset = 0; + spcr->serial_port.access_size = access_size; + spcr->serial_port.addrl = lower_32_bits(serial_address); + spcr->serial_port.addrh = upper_32_bits(serial_address); + + /* Encode baud rate */ + switch (serial_info.baudrate) { + case 9600: + spcr->baud_rate = 3; + break; + case 19200: + spcr->baud_rate = 4; + break; + case 57600: + spcr->baud_rate = 6; + break; + case 115200: + spcr->baud_rate = 7; + break; + default: + spcr->baud_rate = 0; + break; + } + + ret = serial_getconfig(&serial_config); + if (ret) + serial_config = SERIAL_DEFAULT_CONFIG; + + spcr->parity = SERIAL_GET_PARITY(serial_config); + spcr->stop_bits = SERIAL_GET_STOP(serial_config); + + /* No PCI devices for now */ + spcr->pci_device_id = 0xffff; + spcr->pci_vendor_id = 0xffff; + + /* Fix checksum */ + header->checksum = table_compute_checksum((void *)spcr, header->length); +} + /* * QEMU's version of write_acpi_tables is defined in drivers/misc/qfw.c */ @@ -350,6 +460,7 @@ ulong write_acpi_tables(ulong start) struct acpi_fadt *fadt; struct acpi_mcfg *mcfg; struct acpi_madt *madt; + struct acpi_spcr *spcr; int i; current = start; @@ -438,6 +549,13 @@ ulong write_acpi_tables(ulong start) acpi_add_table(rsdp, mcfg); current = ALIGN(current, 16); + debug("ACPI: * SPCR\n"); + spcr = (struct acpi_spcr *)current; + acpi_create_spcr(spcr); + current += spcr->header.length; + acpi_add_table(rsdp, spcr); + current = ALIGN(current, 16); + debug("current = %x\n", current); acpi_rsdp_addr = (unsigned long)rsdp;