From 2a87f7fdd599172879633faf33cae7005344d666 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Mon, 8 Oct 2018 16:35:47 +0800 Subject: [PATCH 01/33] dm/pci: Change the first CFG read to Vendor ID in enumeration As the PCIe specification recommend reading the Vendor ID register to determine if a Function is present, read the Vendor ID of a non-existent Function must not result in system error, so we'd better make the first CFG read to Vendor ID instead of Header Type register in the PCIe enumeration. Signed-off-by: Hou Zhiqiang Reviewed-by: Bin Meng --- drivers/pci/pci-uclass.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 0c52337f33..2cf55cb743 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -774,16 +774,19 @@ int pci_bind_bus_devices(struct udevice *bus) found_multi = false; if (PCI_FUNC(bdf) && !found_multi) continue; + /* Check only the first access, we don't expect problems */ - ret = pci_bus_read_config(bus, bdf, PCI_HEADER_TYPE, - &header_type, PCI_SIZE_8); + ret = pci_bus_read_config(bus, bdf, PCI_VENDOR_ID, &vendor, + PCI_SIZE_16); if (ret) goto error; - pci_bus_read_config(bus, bdf, PCI_VENDOR_ID, &vendor, - PCI_SIZE_16); + if (vendor == 0xffff || vendor == 0x0000) continue; + pci_bus_read_config(bus, bdf, PCI_HEADER_TYPE, + &header_type, PCI_SIZE_8); + if (!PCI_FUNC(bdf)) found_multi = header_type & 0x80; From 9190a3eb8010cdfbcd56905b784c5a21ca90914a Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 14 Oct 2018 20:45:32 +0200 Subject: [PATCH 02/33] sandbox: remove stray DEBUG DEBUG should not be defined in production code. Change printf() to debug() where this writes a debug message. Signed-off-by: Heinrich Schuchardt Reviewed-by: Alexander Graf Reviewed-by: Simon Glass --- arch/sandbox/cpu/cpu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index 6098945049..fdfb209f77 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c @@ -2,7 +2,7 @@ /* * Copyright (c) 2011 The Chromium OS Authors. */ -#define DEBUG + #include #include #include @@ -105,8 +105,8 @@ void *phys_to_virt(phys_addr_t paddr) state = state_get_current(); list_for_each_entry(mentry, &state->mapmem_head, sibling_node) { if (mentry->tag == paddr) { - printf("%s: Used map from %lx to %p\n", __func__, - (ulong)paddr, mentry->ptr); + debug("%s: Used map from %lx to %p\n", __func__, + (ulong)paddr, mentry->ptr); return mentry->ptr; } } @@ -152,7 +152,7 @@ phys_addr_t virt_to_phys(void *ptr) __func__, ptr, (ulong)gd->ram_size); os_abort(); } - printf("%s: Used map from %p to %lx\n", __func__, ptr, mentry->tag); + debug("%s: Used map from %p to %lx\n", __func__, ptr, mentry->tag); return mentry->tag; } From 6c6260ecfcc44ad5d609966a756e995746578b31 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 14 Oct 2018 21:40:02 +0200 Subject: [PATCH 03/33] sandbox: README: setting environment variables The command to set environment variables is setenv. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass --- board/sandbox/README.sandbox | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox index a28fc9f36c..ee4421801b 100644 --- a/board/sandbox/README.sandbox +++ b/board/sandbox/README.sandbox @@ -247,25 +247,25 @@ sudo /path/to/u-boot -D DHCP .... -set autoload no -set ethact eth1 +setenv autoload no +setenv ethact eth1 dhcp PING .... -set autoload no -set ethact eth1 +setenv autoload no +setenv ethact eth1 dhcp ping $gatewayip TFTP .... -set autoload no -set ethact eth1 +setenv autoload no +setenv ethact eth1 dhcp -set serverip WWW.XXX.YYY.ZZZ +setenv serverip WWW.XXX.YYY.ZZZ tftpboot u-boot.bin The bridge also supports (to a lesser extent) the localhost interface, 'lo'. @@ -287,7 +287,7 @@ operation being tested on the lo interface. TFTP .... -set ethact eth5 +setenv ethact eth5 tftpboot u-boot.bin From 0c943e5da64987a622544cafab791caee6e14c9d Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 14 Oct 2018 22:01:28 +0200 Subject: [PATCH 04/33] sandbox: README: use setenv ethrotate no If we want to control which network interface is actually used, we have to issue 'setenv ethrotate no'. If ethrotate is not set any interface may be used. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass --- board/sandbox/README.sandbox | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox index ee4421801b..0f59da4400 100644 --- a/board/sandbox/README.sandbox +++ b/board/sandbox/README.sandbox @@ -248,6 +248,7 @@ DHCP .... setenv autoload no +setenv ethrotate no setenv ethact eth1 dhcp @@ -255,6 +256,7 @@ PING .... setenv autoload no +setenv ethrotate no setenv ethact eth1 dhcp ping $gatewayip @@ -263,6 +265,7 @@ TFTP .... setenv autoload no +setenv ethrotate no setenv ethact eth1 dhcp setenv serverip WWW.XXX.YYY.ZZZ @@ -287,6 +290,7 @@ operation being tested on the lo interface. TFTP .... +setenv ethrotate no setenv ethact eth5 tftpboot u-boot.bin From 5197dafc42eb926525a12fc5aa38d2a05f22d177 Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Mon, 15 Oct 2018 10:03:06 +0100 Subject: [PATCH 05/33] dm: core: Widen the dump tree to show more of the driver's name. With drivers that have prefix names that are quite long (like 'versatile_') it is useful to have a wider column for the driver's name when dumping the device driver tree. Also update the tests to take into account the wider output format. Signed-off-by: Liviu Dudau Reviewed-by: Simon Glass --- drivers/core/dump.c | 8 ++++---- test/py/tests/test_bind.py | 28 ++++++++++++++-------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/core/dump.c b/drivers/core/dump.c index 9068084404..04217cbde8 100644 --- a/drivers/core/dump.c +++ b/drivers/core/dump.c @@ -15,8 +15,8 @@ static void show_devices(struct udevice *dev, int depth, int last_flag) int i, is_last; struct udevice *child; - /* print the first 11 characters to not break the tree-format. */ - printf(" %-10.10s %d [ %c ] %-10.10s ", dev->uclass->uc_drv->name, + /* print the first 20 characters to not break the tree-format. */ + printf(" %-10.10s %d [ %c ] %-20.20s ", dev->uclass->uc_drv->name, dev_get_uclass_index(dev, NULL), dev->flags & DM_FLAG_ACTIVATED ? '+' : ' ', dev->driver->name); @@ -49,8 +49,8 @@ void dm_dump_all(void) root = dm_root(); if (root) { - printf(" Class index Probed Driver Name\n"); - printf("-----------------------------------------\n"); + printf(" Class index Probed Driver Name\n"); + printf("-----------------------------------------------------------\n"); show_devices(root, -1, 0); } } diff --git a/test/py/tests/test_bind.py b/test/py/tests/test_bind.py index f21b7059ea..dee3fee566 100644 --- a/test/py/tests/test_bind.py +++ b/test/py/tests/test_bind.py @@ -13,7 +13,7 @@ def in_tree(response, name, uclass, drv, depth, last_child): else: leaf = leaf + '`' leaf = leaf + '-- ' + name - line = ' *{:10.10} [0-9]* \[ [ +] \] {:10.10} {}$'.format(uclass, drv,leaf) + line = ' *{:10.10} [0-9]* \[ [ +] \] {:20.20} {}$'.format(uclass, drv, leaf) prog = re.compile(line) for l in lines: if prog.match(l): @@ -28,31 +28,31 @@ def test_bind_unbind_with_node(u_boot_console): response = u_boot_console.run_command("bind /bind-test generic_simple_bus") assert response == '' tree = u_boot_console.run_command("dm tree") - assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True) + assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True) assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, False) - assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True) + assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True) #Unbind child #1. No error expected and all devices should be there except for bind-test-child1 response = u_boot_console.run_command("unbind /bind-test/bind-test-child1") assert response == '' tree = u_boot_console.run_command("dm tree") - assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True) + assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True) assert "bind-test-child1" not in tree - assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True) + assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True) #bind child #1. No error expected and all devices should be there response = u_boot_console.run_command("bind /bind-test/bind-test-child1 phy_sandbox") assert response == '' tree = u_boot_console.run_command("dm tree") - assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True) + assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True) assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, True) - assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, False) + assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, False) #Unbind child #2. No error expected and all devices should be there except for bind-test-child2 response = u_boot_console.run_command("unbind /bind-test/bind-test-child2") assert response == '' tree = u_boot_console.run_command("dm tree") - assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True) + assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True) assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, True) assert "bind-test-child2" not in tree @@ -61,9 +61,9 @@ def test_bind_unbind_with_node(u_boot_console): response = u_boot_console.run_command("bind /bind-test/bind-test-child2 generic_simple_bus") assert response == '' tree = u_boot_console.run_command("dm tree") - assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True) + assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True) assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, False) - assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True) + assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True) #Unbind parent. No error expected. All devices should be removed and unbound response = u_boot_console.run_command("unbind /bind-test") @@ -89,9 +89,9 @@ def test_bind_unbind_with_node(u_boot_console): response = u_boot_console.run_command("bind /bind-test generic_simple_bus") assert response == '' tree = u_boot_console.run_command("dm tree") - assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True) + assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True) assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, False) - assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True) + assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True) response = u_boot_console.run_command("unbind /bind-test") assert response == '' @@ -138,7 +138,7 @@ def test_bind_unbind_with_uclass(u_boot_console): response = u_boot_console.run_command("unbind simple_bus {}".format(child_of_child2_index)) assert response == '' tree = u_boot_console.run_command("dm tree") - assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True) + assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True) assert not in_tree(tree, "generic_simple_bus", "simple_bus", "generic_simple_bus", 2, True) child_of_child2_line = get_next_line(tree, "bind-test-child2") assert child_of_child2_line == "" @@ -161,7 +161,7 @@ def test_bind_unbind_with_uclass(u_boot_console): assert response == '' tree = u_boot_console.run_command("dm tree") - assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True) + assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True) child_of_child2_line = get_next_line(tree, "bind-test-child2") assert child_of_child2_line == "" From 410d9b644639799259cddba9cbff96c2db038a6b Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 18 Oct 2018 20:37:05 +0200 Subject: [PATCH 06/33] fdt: Fix uncompress_blob() for U-Boot proper When U-Boot proper is compiled with CONFIG_MULTI_DTB_FIT and tries to call uncompress_blob(), it fails with -ENOTSUPP. This is because the full implementation of this function which includes compression is available only in SPL. In U-Boot proper or if the compression is not enabled, the blob is not compressed and thus can be passed to locate_dtb_in_fit() in fdtdec_setup() without any changes. Pass the blob without any changes if compression is not enabled instead of failing. Signed-off-by: Marek Vasut Cc: Michal Simek Cc: Tom Rini Reviewed-by: Simon Glass --- lib/fdtdec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/fdtdec.c b/lib/fdtdec.c index a420ba1885..d28f2cbb1c 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1198,7 +1198,8 @@ static int uncompress_blob(const void *src, ulong sz_src, void **dstp) # else static int uncompress_blob(const void *src, ulong sz_src, void **dstp) { - return -ENOTSUPP; + *dstp = (void *)src; + return 0; } # endif #endif From b1a7e79949a972231ddf793fd48ca0ce9cf48da5 Mon Sep 17 00:00:00 2001 From: Hiroyuki Yokoyama Date: Thu, 18 Oct 2018 20:43:54 +0200 Subject: [PATCH 07/33] cmd: fdt: Fix fdt address information after the movement This patch fixes the address information of fdt. wrong case: => fdt addr 0x48000000 => fdt move 0x48000000 0x41000000 0xa000 => fdt addr The address of the fdt is 48000000 Active address in this case is 0x41000000. Signed-off-by: Hiroyuki Yokoyama Signed-off-by: Marek Vasut Cc: Hiroyuki Yokoyama Cc: Nobuhiro Iwamatsu Cc: Pantelis Antoniou Reviewed-by: Simon Glass --- cmd/fdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/fdt.c b/cmd/fdt.c index 8a19a3fdbf..84be26f4f1 100644 --- a/cmd/fdt.c +++ b/cmd/fdt.c @@ -202,7 +202,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) fdt_strerror(err)); return 1; } - working_fdt = newaddr; + set_working_fdt_addr((ulong)newaddr); #ifdef CONFIG_OF_SYSTEM_SETUP /* Call the board-specific fixup routine */ } else if (strncmp(argv[1], "sys", 3) == 0) { From b23644858bec1a21743debccb6643af7df5c48b4 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Sun, 28 Oct 2018 14:41:14 +0200 Subject: [PATCH 08/33] fdt: restore board_fdt_blob_setup() declaration Commit 90c08fa038451d (fdt: Add device tree memory bindings) removed the prototype declaration of board_fdt_blob_setup(), most likely by mistake. This didn't break the build because the only file calling this function (lib/fdtdec.c) provides a local weak definition. Restore the declaration. Cc: Michael Pratt Signed-off-by: Baruch Siach Reviewed-by: Simon Glass --- include/fdtdec.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/fdtdec.h b/include/fdtdec.h index c26df50543..b15da00fb2 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -956,6 +956,7 @@ int fdtdec_setup(void); * Called when CONFIG_OF_BOARD is defined, or if CONFIG_OF_SEPARATE is defined * and the board implements it. */ +void *board_fdt_blob_setup(void); /* * Decode the size of memory From 12bfb2e05fc29bfbec7eb76ea8cc02e130268801 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Tue, 30 Oct 2018 21:09:48 +0100 Subject: [PATCH 09/33] dm: spi: prevent setting a speed of 0 Hz When the device tree is missing a correct spi slave description below the bus (compatible "spi-flash" or spi-max-frequency are missing), the 'set_speed' callback can be called with 'speed' == 0 Hz. At least with cadence qspi, this leads to a division by zero. Prevent this by initializing speed to 100 kHz in this case (same fallback value as is done in 'dm_spi_claim_bus') and issue a warning to console. Signed-off-by: Simon Goldschmidt Reviewed-by: Simon Glass --- drivers/spi/spi-uclass.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c index b84255bd27..2bc289a74c 100644 --- a/drivers/spi/spi-uclass.c +++ b/drivers/spi/spi-uclass.c @@ -15,6 +15,8 @@ DECLARE_GLOBAL_DATA_PTR; +#define SPI_DEFAULT_SPEED_HZ 100000 + static int spi_set_speed_mode(struct udevice *bus, int speed, int mode) { struct dm_spi_ops *ops; @@ -58,7 +60,7 @@ int dm_spi_claim_bus(struct udevice *dev) speed = spi->max_hz; } if (!speed) - speed = 100000; + speed = SPI_DEFAULT_SPEED_HZ; if (speed != slave->speed) { int ret = spi_set_speed_mode(bus, speed, slave->mode); @@ -300,7 +302,13 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode, } plat = dev_get_parent_platdata(dev); plat->cs = cs; - plat->max_hz = speed; + if (speed) { + plat->max_hz = speed; + } else { + printf("Warning: SPI speed fallback to %u kHz\n", + SPI_DEFAULT_SPEED_HZ / 1000); + plat->max_hz = SPI_DEFAULT_SPEED_HZ; + } plat->mode = mode; created = true; } else if (ret) { @@ -374,7 +382,8 @@ int spi_slave_ofdata_to_platdata(struct udevice *dev, int value; plat->cs = dev_read_u32_default(dev, "reg", -1); - plat->max_hz = dev_read_u32_default(dev, "spi-max-frequency", 0); + plat->max_hz = dev_read_u32_default(dev, "spi-max-frequency", + SPI_DEFAULT_SPEED_HZ); if (dev_read_bool(dev, "spi-cpol")) mode |= SPI_CPOL; if (dev_read_bool(dev, "spi-cpha")) From 40232c91d70f4f2066408cabf1afba1deb190df6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 16:02:10 -0700 Subject: [PATCH 10/33] buildman: Only print toolchain probing with -v At present --list-tool-chains prints a lot of information about the toolchain-probing process. This is generally not very interesting. Update buildman to print this only if --list-tool-chains is given with -v. Signed-off-by: Simon Glass --- tools/buildman/cmdline.py | 2 +- tools/buildman/control.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/buildman/cmdline.py b/tools/buildman/cmdline.py index 49a8a13118..93d09ca08d 100644 --- a/tools/buildman/cmdline.py +++ b/tools/buildman/cmdline.py @@ -66,7 +66,7 @@ def ParseArgs(): parser.add_option('-l', '--list-error-boards', action='store_true', default=False, help='Show a list of boards next to each error/warning') parser.add_option('--list-tool-chains', action='store_true', default=False, - help='List available tool chains') + help='List available tool chains (use -v to see probing detail)') parser.add_option('-n', '--dry-run', action='store_true', dest='dry_run', default=False, help="Do a dry run (describe actions, but do nothing)") parser.add_option('-N', '--no-subdirs', action='store_true', dest='no_subdirs', diff --git a/tools/buildman/control.py b/tools/buildman/control.py index 96f8ccfe07..c900211510 100644 --- a/tools/buildman/control.py +++ b/tools/buildman/control.py @@ -164,7 +164,7 @@ def DoBuildman(options, args, toolchains=None, make_func=None, boards=None, if no_toolchains: toolchains.GetSettings() - toolchains.Scan(options.list_tool_chains) + toolchains.Scan(options.list_tool_chains and options.verbose) if options.list_tool_chains: toolchains.List() print From 2d48333e447e8cc5a2bd3eaed6be657925cbee16 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 16:02:11 -0700 Subject: [PATCH 11/33] buildman: Detect dtc warnings At present messages from the device-tree compiler like this: arch/arm/dts/socfpga_arria10_socdk_sdmmc.dtb: Warning (avoid_unnecessary_addr_size): /clocks: unnecessary #address-cells/#size-cells without "ranges" or child "reg" property are detected as errors since they don't match the gcc warning regex. Add a new one for dtc to fix this. Signed-off-by: Simon Glass --- tools/buildman/builder.py | 4 +++- tools/buildman/test.py | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/buildman/builder.py b/tools/buildman/builder.py index 05f8299541..fc80705a45 100644 --- a/tools/buildman/builder.py +++ b/tools/buildman/builder.py @@ -290,6 +290,7 @@ class Builder: self._re_function = re.compile('(.*): In function.*') self._re_files = re.compile('In file included from.*') self._re_warning = re.compile('(.*):(\d*):(\d*): warning: .*') + self._re_dtb_warning = re.compile('(.*): Warning .*') self._re_note = re.compile('(.*):(\d*):(\d*): note: this is the location of the previous.*') self.queue = Queue.Queue() @@ -788,7 +789,8 @@ class Builder: self._re_files.match(line)): last_func = line else: - is_warning = self._re_warning.match(line) + is_warning = (self._re_warning.match(line) or + self._re_dtb_warning.match(line)) is_note = self._re_note.match(line) if is_warning or (last_was_warning and is_note): if last_func: diff --git a/tools/buildman/test.py b/tools/buildman/test.py index 61a462655f..5c82c50793 100644 --- a/tools/buildman/test.py +++ b/tools/buildman/test.py @@ -46,8 +46,9 @@ make[1]: *** [main.o] Error 1 make: *** [common/libcommon.o] Error 2 Make failed ''', - '''main.c: In function 'main_loop3': -main.c:280:6: warning: unused variable 'mary' [-Wunused-variable] + '''arch/arm/dts/socfpga_arria10_socdk_sdmmc.dtb: Warning \ +(avoid_unnecessary_addr_size): /clocks: unnecessary #address-cells/#size-cells \ +without "ranges" or child "reg" property ''', '''powerpc-linux-ld: warning: dot moved backwards before `.bss' powerpc-linux-ld: warning: dot moved backwards before `.bss' From 4cf2b221c6f283aa0fb646cf637ae08fc90dd6d2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 16:02:12 -0700 Subject: [PATCH 12/33] buildman: Rename the good, better, worse variables At present we don't distinguish between errors and warnings when printing the architecture summary. Rename the variables to better describe their purpose. 'Worse' at present means we got an error, so use that as the name. Signed-off-by: Simon Glass --- tools/buildman/builder.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tools/buildman/builder.py b/tools/buildman/builder.py index fc80705a45..d9d86ef6a3 100644 --- a/tools/buildman/builder.py +++ b/tools/buildman/builder.py @@ -1196,10 +1196,10 @@ class Builder: Print(' ' + line, newline=True, colour=col) - better = [] # List of boards fixed since last commit - worse = [] # List of new broken boards since last commit - new = [] # List of boards that didn't exist last time - unknown = [] # List of boards that were not built + ok_boards = [] # List of boards fixed since last commit + err_boards = [] # List of new broken boards since last commit + new_boards = [] # List of boards that didn't exist last time + unknown_boards = [] # List of boards that were not built for target in board_dict: if target not in board_selected: @@ -1210,13 +1210,13 @@ class Builder: base_outcome = self._base_board_dict[target].rc outcome = board_dict[target] if outcome.rc == OUTCOME_UNKNOWN: - unknown.append(target) + unknown_boards.append(target) elif outcome.rc < base_outcome: - better.append(target) + ok_boards.append(target) elif outcome.rc > base_outcome: - worse.append(target) + err_boards.append(target) else: - new.append(target) + new_boards.append(target) # Get a list of errors that have appeared, and disappeared better_err, worse_err = _CalcErrorDelta(self._base_err_lines, @@ -1225,16 +1225,16 @@ class Builder: self._base_warn_line_boards, warn_lines, warn_line_boards, 'w') # Display results by arch - if (better or worse or unknown or new or worse_err or better_err - or worse_warn or better_warn): + if any((ok_boards, err_boards, unknown_boards, new_boards, worse_err, + better_err, worse_warn, better_warn)): arch_list = {} - self.AddOutcome(board_selected, arch_list, better, '', + self.AddOutcome(board_selected, arch_list, ok_boards, '', self.col.GREEN) - self.AddOutcome(board_selected, arch_list, worse, '+', + self.AddOutcome(board_selected, arch_list, err_boards, '+', self.col.RED) - self.AddOutcome(board_selected, arch_list, new, '*', self.col.BLUE) + self.AddOutcome(board_selected, arch_list, new_boards, '*', self.col.BLUE) if self._show_unknown: - self.AddOutcome(board_selected, arch_list, unknown, '?', + self.AddOutcome(board_selected, arch_list, unknown_boards, '?', self.col.MAGENTA) for arch, target_list in arch_list.iteritems(): Print('%10s: %s' % (arch, target_list)) From 6af7101b75d0e30cf7ed7d1f57fdb68ed5f8ffa0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 16:02:13 -0700 Subject: [PATCH 13/33] buildman: Show boards with warning with w+ At present we should boards with warnings in the same way as those with errors. This is not ideal. Add a new 'warn' state and show these listed in yellow to match the actual warning lines printing with -e. Signed-off-by: Simon Glass --- tools/buildman/builder.py | 17 +++++++++--- tools/buildman/test.py | 54 +++++++++++++++++++++++++++++---------- 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/tools/buildman/builder.py b/tools/buildman/builder.py index d9d86ef6a3..6a6c83bf33 100644 --- a/tools/buildman/builder.py +++ b/tools/buildman/builder.py @@ -1197,6 +1197,7 @@ class Builder: ok_boards = [] # List of boards fixed since last commit + warn_boards = [] # List of boards with warnings since last commit err_boards = [] # List of new broken boards since last commit new_boards = [] # List of boards that didn't exist last time unknown_boards = [] # List of boards that were not built @@ -1212,9 +1213,15 @@ class Builder: if outcome.rc == OUTCOME_UNKNOWN: unknown_boards.append(target) elif outcome.rc < base_outcome: - ok_boards.append(target) + if outcome.rc == OUTCOME_WARNING: + warn_boards.append(target) + else: + ok_boards.append(target) elif outcome.rc > base_outcome: - err_boards.append(target) + if outcome.rc == OUTCOME_WARNING: + warn_boards.append(target) + else: + err_boards.append(target) else: new_boards.append(target) @@ -1225,11 +1232,13 @@ class Builder: self._base_warn_line_boards, warn_lines, warn_line_boards, 'w') # Display results by arch - if any((ok_boards, err_boards, unknown_boards, new_boards, worse_err, - better_err, worse_warn, better_warn)): + if any((ok_boards, warn_boards, err_boards, unknown_boards, new_boards, + worse_err, better_err, worse_warn, better_warn)): arch_list = {} self.AddOutcome(board_selected, arch_list, ok_boards, '', self.col.GREEN) + self.AddOutcome(board_selected, arch_list, warn_boards, 'w+', + self.col.YELLOW) self.AddOutcome(board_selected, arch_list, err_boards, '+', self.col.RED) self.AddOutcome(board_selected, arch_list, new_boards, '*', self.col.BLUE) diff --git a/tools/buildman/test.py b/tools/buildman/test.py index 5c82c50793..de02f61be6 100644 --- a/tools/buildman/test.py +++ b/tools/buildman/test.py @@ -97,6 +97,8 @@ boards = [ BASE_DIR = 'base' +OUTCOME_OK, OUTCOME_WARN, OUTCOME_ERR = range(3) + class Options: """Class that holds build options""" pass @@ -166,9 +168,10 @@ class TestBuild(unittest.TestCase): result.combined = result.stdout + result.stderr return result - def assertSummary(self, text, arch, plus, boards, ok=False): + def assertSummary(self, text, arch, plus, boards, outcome=OUTCOME_ERR): col = self._col - expected_colour = col.GREEN if ok else col.RED + expected_colour = (col.GREEN if outcome == OUTCOME_OK else + col.YELLOW if outcome == OUTCOME_WARN else col.RED) expect = '%10s: ' % arch # TODO(sjg@chromium.org): If plus is '', we shouldn't need this expect += ' ' + col.Color(expected_colour, plus) @@ -192,6 +195,8 @@ class TestBuild(unittest.TestCase): build.do_make = self.Make board_selected = self.boards.GetSelectedDict() + # Build the boards for the pre-defined commits and warnings/errors + # associated with each. This calls our Make() to inject the fake output. build.BuildBoards(self.commits, board_selected, keep_outputs=False, verbose=False) lines = terminal.GetPrintTestLines() @@ -207,33 +212,49 @@ class TestBuild(unittest.TestCase): build.ShowSummary(self.commits, board_selected) #terminal.EchoPrintTestLines() lines = terminal.GetPrintTestLines() + + # Upstream commit: no errors self.assertEqual(lines[0].text, '01: %s' % commits[0][1]) + + # Second commit: all archs should fail with warnings self.assertEqual(lines[1].text, '02: %s' % commits[1][1]) - # We expect all archs to fail col = terminal.Color() - self.assertSummary(lines[2].text, 'sandbox', '+', ['board4']) - self.assertSummary(lines[3].text, 'arm', '+', ['board1']) - self.assertSummary(lines[4].text, 'powerpc', '+', ['board2', 'board3']) + self.assertSummary(lines[2].text, 'sandbox', 'w+', ['board4'], + outcome=OUTCOME_WARN) + self.assertSummary(lines[3].text, 'arm', 'w+', ['board1'], + outcome=OUTCOME_WARN) + self.assertSummary(lines[4].text, 'powerpc', 'w+', ['board2', 'board3'], + outcome=OUTCOME_WARN) - # Now we should have the compiler warning + # Second commit: The warnings should be listed self.assertEqual(lines[5].text, 'w+%s' % errors[0].rstrip().replace('\n', '\nw+')) self.assertEqual(lines[5].colour, col.MAGENTA) + # Third commit: Still fails self.assertEqual(lines[6].text, '03: %s' % commits[2][1]) self.assertSummary(lines[7].text, 'sandbox', '+', ['board4']) - self.assertSummary(lines[8].text, 'arm', '', ['board1'], ok=True) + self.assertSummary(lines[8].text, 'arm', '', ['board1'], + outcome=OUTCOME_OK) self.assertSummary(lines[9].text, 'powerpc', '+', ['board2', 'board3']) - # Compiler error + # Expect a compiler error self.assertEqual(lines[10].text, '+%s' % errors[1].rstrip().replace('\n', '\n+')) + # Fourth commit: Compile errors are fixed, just have warning for board3 self.assertEqual(lines[11].text, '04: %s' % commits[3][1]) - self.assertSummary(lines[12].text, 'sandbox', '', ['board4'], ok=True) - self.assertSummary(lines[13].text, 'powerpc', '', ['board2', 'board3'], - ok=True) + self.assertSummary(lines[12].text, 'sandbox', 'w+', ['board4'], + outcome=OUTCOME_WARN) + expect = '%10s: ' % 'powerpc' + expect += ' ' + col.Color(col.GREEN, '') + expect += ' ' + expect += col.Color(col.GREEN, ' %s' % 'board2') + expect += ' ' + col.Color(col.YELLOW, 'w+') + expect += ' ' + expect += col.Color(col.YELLOW, ' %s' % 'board3') + self.assertEqual(lines[13].text, expect) # Compile error fixed self.assertEqual(lines[14].text, '-%s' % @@ -244,9 +265,11 @@ class TestBuild(unittest.TestCase): errors[2].rstrip().replace('\n', '\nw+')) self.assertEqual(lines[15].colour, col.MAGENTA) + # Fifth commit self.assertEqual(lines[16].text, '05: %s' % commits[4][1]) self.assertSummary(lines[17].text, 'sandbox', '+', ['board4']) - self.assertSummary(lines[18].text, 'powerpc', '', ['board3'], ok=True) + self.assertSummary(lines[18].text, 'powerpc', '', ['board3'], + outcome=OUTCOME_OK) # The second line of errors[3] is a duplicate, so buildman will drop it expect = errors[3].rstrip().split('\n') @@ -257,8 +280,10 @@ class TestBuild(unittest.TestCase): self.assertEqual(lines[20].text, 'w-%s' % errors[2].rstrip().replace('\n', '\nw-')) + # Sixth commit self.assertEqual(lines[21].text, '06: %s' % commits[5][1]) - self.assertSummary(lines[22].text, 'sandbox', '', ['board4'], ok=True) + self.assertSummary(lines[22].text, 'sandbox', '', ['board4'], + outcome=OUTCOME_OK) # The second line of errors[3] is a duplicate, so buildman will drop it expect = errors[3].rstrip().split('\n') @@ -269,6 +294,7 @@ class TestBuild(unittest.TestCase): self.assertEqual(lines[24].text, 'w-%s' % errors[0].rstrip().replace('\n', '\nw-')) + # Seventh commit self.assertEqual(lines[25].text, '07: %s' % commits[6][1]) self.assertSummary(lines[26].text, 'sandbox', '+', ['board4']) From 9fea76f5d30264dc08ac591a7a89427b8441555b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:18 -0700 Subject: [PATCH 14/33] cros_ec: Use uint instead of u8 for parameters There is no advantage to using a u8 for function parameters. It forces the compiler to mask values and can increase code size. Also the command enum has been extended to 16 bits. Update the functions to use uint instead. Signed-off-by: Simon Glass --- drivers/misc/cros_ec.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index 190505c11c..4013f50d59 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -227,7 +227,7 @@ static int send_command_proto3(struct cros_ec_dev *cdev, return handle_proto3_response(cdev, dinp, din_len); } -static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version, +static int send_command(struct cros_ec_dev *dev, uint cmd, int cmd_version, const void *dout, int dout_len, uint8_t **dinp, int din_len) { @@ -330,7 +330,7 @@ static int ec_command_inptr(struct udevice *dev, uint8_t cmd, * @param din_len Maximum size of response in bytes * @return number of bytes in response, or -ve on error */ -static int ec_command(struct udevice *dev, uint8_t cmd, int cmd_version, +static int ec_command(struct udevice *dev, uint cmd, int cmd_version, const void *dout, int dout_len, void *din, int din_len) { @@ -650,16 +650,14 @@ static int cros_ec_check_version(struct udevice *dev) cdev->protocol_version = 3; req.in_data = 0; if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req), - (uint8_t **)&resp, sizeof(*resp)) > 0) { + (uint8_t **)&resp, sizeof(*resp)) > 0) return 0; - } /* Try sending a version 2 packet */ cdev->protocol_version = 2; if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req), - (uint8_t **)&resp, sizeof(*resp)) > 0) { + (uint8_t **)&resp, sizeof(*resp)) > 0) return 0; - } /* * Fail if we're still here, since the EC doesn't understand any From ac80652342dafa5356cd25959f1c45d003ba9dcf Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:19 -0700 Subject: [PATCH 15/33] cros_ec: Add error logging on a few commands Add some more logging to provide more information on failures. Signed-off-by: Simon Glass --- drivers/misc/cros_ec.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index 4013f50d59..e0f3dfc98e 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -13,6 +13,8 @@ * is not reset. */ +#define LOG_CATEGORY UCLASS_CROS_EC + #include #include #include @@ -365,10 +367,14 @@ int cros_ec_scan_keyboard(struct udevice *dev, struct mbkp_keyscan *scan) int cros_ec_read_id(struct udevice *dev, char *id, int maxlen) { struct ec_response_get_version *r; + int ret; - if (ec_command_inptr(dev, EC_CMD_GET_VERSION, 0, NULL, 0, - (uint8_t **)&r, sizeof(*r)) != sizeof(*r)) + 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)); return -1; + } if (maxlen > (int)sizeof(r->version_string_ro)) maxlen = sizeof(r->version_string_ro); @@ -381,6 +387,7 @@ int cros_ec_read_id(struct udevice *dev, char *id, int maxlen) memcpy(id, r->version_string_rw, maxlen); break; default: + log_err("Invalid EC image %d\n", r->current_image); return -1; } From dc05ac0f2f3a5b2f301e2790afe45cb11cf0258f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:20 -0700 Subject: [PATCH 16/33] cros_ec: Fail if we cannot determine the flash burst size This value is required for flashing to work correctly. Add a check for it. Signed-off-by: Simon Glass --- drivers/misc/cros_ec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index e0f3dfc98e..7daf16499a 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -827,6 +827,9 @@ int cros_ec_flash_write(struct udevice *dev, const uint8_t *data, uint32_t end, off; int ret; + if (!burst) + return -EINVAL; + /* * TODO: round up to the nearest multiple of write size. Can get away * without that on link right now because its write size is 4 bytes. From 4bf6f2ad47f481d161876a87969c46f80a9b8e9d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:21 -0700 Subject: [PATCH 17/33] cros_ec: Align uclass data to a cache boundary The LPC driver expects its buffer to be word-aligned. Add the required flag to the uclass driver to ensure this. Signed-off-by: Simon Glass --- drivers/misc/cros_ec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index 7daf16499a..828e50eb1c 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -1152,4 +1152,5 @@ UCLASS_DRIVER(cros_ec) = { .name = "cros_ec", .per_device_auto_alloc_size = sizeof(struct cros_ec_dev), .post_bind = dm_scan_fdt_dev, + .flags = DM_UC_FLAG_ALLOC_PRIV_DMA, }; From 72ef8bfd6dd83412577f9c5da8a5b6bec5c22182 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:22 -0700 Subject: [PATCH 18/33] cros_ec: Add new features for events and power This adds new commands to the EC related to setting and clearing events as well as controlling power-related settings. Signed-off-by: Simon Glass --- drivers/misc/cros_ec.c | 345 ++++++++++++++++++++++++++++++++- drivers/misc/cros_ec_sandbox.c | 2 +- include/cros_ec.h | 89 +++++++++ 3 files changed, 429 insertions(+), 7 deletions(-) diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index 828e50eb1c..2dcdb3d8d6 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -43,6 +43,54 @@ enum { CROS_EC_CMD_HASH_TIMEOUT_MS = 2000, }; +#define INVALID_HCMD 0xFF + +/* + * Map UHEPI masks to non UHEPI commands in order to support old EC FW + * which does not support UHEPI command. + */ +static const struct { + u8 set_cmd; + u8 clear_cmd; + u8 get_cmd; +} event_map[] = { + [EC_HOST_EVENT_MAIN] = { + INVALID_HCMD, EC_CMD_HOST_EVENT_CLEAR, + INVALID_HCMD, + }, + [EC_HOST_EVENT_B] = { + INVALID_HCMD, EC_CMD_HOST_EVENT_CLEAR_B, + EC_CMD_HOST_EVENT_GET_B, + }, + [EC_HOST_EVENT_SCI_MASK] = { + EC_CMD_HOST_EVENT_SET_SCI_MASK, INVALID_HCMD, + EC_CMD_HOST_EVENT_GET_SCI_MASK, + }, + [EC_HOST_EVENT_SMI_MASK] = { + EC_CMD_HOST_EVENT_SET_SMI_MASK, INVALID_HCMD, + EC_CMD_HOST_EVENT_GET_SMI_MASK, + }, + [EC_HOST_EVENT_ALWAYS_REPORT_MASK] = { + INVALID_HCMD, INVALID_HCMD, INVALID_HCMD, + }, + [EC_HOST_EVENT_ACTIVE_WAKE_MASK] = { + EC_CMD_HOST_EVENT_SET_WAKE_MASK, INVALID_HCMD, + EC_CMD_HOST_EVENT_GET_WAKE_MASK, + }, + [EC_HOST_EVENT_LAZY_WAKE_MASK_S0IX] = { + EC_CMD_HOST_EVENT_SET_WAKE_MASK, INVALID_HCMD, + EC_CMD_HOST_EVENT_GET_WAKE_MASK, + }, + [EC_HOST_EVENT_LAZY_WAKE_MASK_S3] = { + EC_CMD_HOST_EVENT_SET_WAKE_MASK, INVALID_HCMD, + EC_CMD_HOST_EVENT_GET_WAKE_MASK, + }, + [EC_HOST_EVENT_LAZY_WAKE_MASK_S5] = { + EC_CMD_HOST_EVENT_SET_WAKE_MASK, INVALID_HCMD, + EC_CMD_HOST_EVENT_GET_WAKE_MASK, + }, +}; + void cros_ec_dump_data(const char *name, int cmd, const uint8_t *data, int len) { #ifdef DEBUG @@ -570,6 +618,36 @@ int cros_ec_info(struct udevice *dev, struct ec_response_mkbp_info *info) return 0; } +int cros_ec_get_event_mask(struct udevice *dev, uint type, uint32_t *mask) +{ + struct ec_response_host_event_mask rsp; + int ret; + + ret = ec_command(dev, type, 0, NULL, 0, &rsp, sizeof(rsp)); + if (ret < 0) + return ret; + else if (ret != sizeof(rsp)) + return -EINVAL; + + *mask = rsp.mask; + + return 0; +} + +int cros_ec_set_event_mask(struct udevice *dev, uint type, uint32_t mask) +{ + struct ec_params_host_event_mask req; + int ret; + + req.mask = mask; + + ret = ec_command(dev, type, 0, &req, sizeof(req), NULL, 0); + if (ret < 0) + return ret; + + return 0; +} + int cros_ec_get_host_events(struct udevice *dev, uint32_t *events_ptr) { struct ec_response_host_event_mask *resp; @@ -623,6 +701,17 @@ int cros_ec_flash_protect(struct udevice *dev, uint32_t set_mask, return 0; } +int cros_ec_entering_mode(struct udevice *dev, int mode) +{ + int rc; + + rc = ec_command(dev, EC_CMD_ENTERING_MODE, 0, &mode, sizeof(mode), + NULL, 0); + if (rc) + return -1; + return 0; +} + static int cros_ec_check_version(struct udevice *dev) { struct cros_ec_dev *cdev = dev_get_uclass_priv(dev); @@ -852,6 +941,35 @@ int cros_ec_flash_write(struct udevice *dev, const uint8_t *data, return 0; } +/** + * Run verification on a slot + * + * @param me CrosEc instance + * @param region Region to run verification on + * @return 0 if success or not applicable. Non-zero if verification failed. + */ +int cros_ec_efs_verify(struct udevice *dev, enum ec_flash_region region) +{ + struct ec_params_efs_verify p; + int rv; + + log_info("EFS: EC is verifying updated image...\n"); + p.region = region; + + rv = ec_command(dev, EC_CMD_EFS_VERIFY, 0, &p, sizeof(p), NULL, 0); + if (rv >= 0) { + log_info("EFS: Verification success\n"); + return 0; + } + if (rv == -EC_RES_INVALID_COMMAND) { + log_info("EFS: EC doesn't support EFS_VERIFY command\n"); + return 0; + } + log_info("EFS: Verification failed\n"); + + return rv; +} + /** * Read a single block from the flash * @@ -942,15 +1060,17 @@ int cros_ec_read_nvdata(struct udevice *dev, uint8_t *block, int size) struct ec_params_vbnvcontext p; int len; - if (size != EC_VBNV_BLOCK_SIZE) + if (size != EC_VBNV_BLOCK_SIZE && size != EC_VBNV_BLOCK_SIZE_V2) return -EINVAL; p.op = EC_VBNV_CONTEXT_OP_READ; len = ec_command(dev, EC_CMD_VBNV_CONTEXT, EC_VER_VBNV_CONTEXT, - &p, sizeof(p), block, EC_VBNV_BLOCK_SIZE); - if (len < EC_VBNV_BLOCK_SIZE) + &p, sizeof(uint32_t) + size, block, size); + if (len != size) { + log_err("Expected %d bytes, got %d\n", size, len); return -EIO; + } return 0; } @@ -960,19 +1080,33 @@ int cros_ec_write_nvdata(struct udevice *dev, const uint8_t *block, int size) struct ec_params_vbnvcontext p; int len; - if (size != EC_VBNV_BLOCK_SIZE) + if (size != EC_VBNV_BLOCK_SIZE && size != EC_VBNV_BLOCK_SIZE_V2) return -EINVAL; p.op = EC_VBNV_CONTEXT_OP_WRITE; - memcpy(p.block, block, sizeof(p.block)); + memcpy(p.block, block, size); len = ec_command_inptr(dev, EC_CMD_VBNV_CONTEXT, EC_VER_VBNV_CONTEXT, - &p, sizeof(p), NULL, 0); + &p, sizeof(uint32_t) + size, NULL, 0); if (len < 0) return -1; return 0; } +int cros_ec_battery_cutoff(struct udevice *dev, uint8_t flags) +{ + struct ec_params_battery_cutoff p; + int len; + + p.flags = flags; + len = ec_command(dev, EC_CMD_BATTERY_CUT_OFF, 1, &p, sizeof(p), + NULL, 0); + + if (len < 0) + return -1; + return 0; +} + int cros_ec_set_ldo(struct udevice *dev, uint8_t index, uint8_t state) { struct ec_params_ldo_set params; @@ -1147,6 +1281,205 @@ int cros_ec_i2c_tunnel(struct udevice *dev, int port, struct i2c_msg *in, return 0; } +int cros_ec_check_feature(struct udevice *dev, int feature) +{ + struct ec_response_get_features r; + int rv; + + rv = ec_command(dev, EC_CMD_GET_FEATURES, 0, &r, sizeof(r), NULL, 0); + if (rv) + return rv; + + if (feature >= 8 * sizeof(r.flags)) + return -1; + + return r.flags[feature / 32] & EC_FEATURE_MASK_0(feature); +} + +/* + * Query the EC for specified mask indicating enabled events. + * The EC maintains separate event masks for SMI, SCI and WAKE. + */ +static int cros_ec_uhepi_cmd(struct udevice *dev, uint mask, uint action, + uint64_t *value) +{ + int ret; + struct ec_params_host_event req; + struct ec_response_host_event rsp; + + req.action = action; + req.mask_type = mask; + if (action != EC_HOST_EVENT_GET) + req.value = *value; + else + *value = 0; + ret = ec_command(dev, EC_CMD_HOST_EVENT, 0, &req, sizeof(req), &rsp, + sizeof(rsp)); + + if (action != EC_HOST_EVENT_GET) + return ret; + if (ret == 0) + *value = rsp.value; + + return ret; +} + +static int cros_ec_handle_non_uhepi_cmd(struct udevice *dev, uint hcmd, + uint action, uint64_t *value) +{ + int ret = -1; + struct ec_params_host_event_mask req; + struct ec_response_host_event_mask rsp; + + if (hcmd == INVALID_HCMD) + return ret; + + if (action != EC_HOST_EVENT_GET) + req.mask = (uint32_t)*value; + else + *value = 0; + + ret = ec_command(dev, hcmd, 0, &req, sizeof(req), &rsp, sizeof(rsp)); + if (action != EC_HOST_EVENT_GET) + return ret; + if (ret == 0) + *value = rsp.mask; + + return ret; +} + +bool cros_ec_is_uhepi_supported(struct udevice *dev) +{ +#define UHEPI_SUPPORTED 1 +#define UHEPI_NOT_SUPPORTED 2 + static int uhepi_support; + + if (!uhepi_support) { + uhepi_support = cros_ec_check_feature(dev, + EC_FEATURE_UNIFIED_WAKE_MASKS) > 0 ? UHEPI_SUPPORTED : + UHEPI_NOT_SUPPORTED; + log_debug("Chrome EC: UHEPI %s\n", + uhepi_support == UHEPI_SUPPORTED ? "supported" : + "not supported"); + } + return uhepi_support == UHEPI_SUPPORTED; +} + +static int cros_ec_get_mask(struct udevice *dev, uint type) +{ + u64 value = 0; + + if (cros_ec_is_uhepi_supported(dev)) { + cros_ec_uhepi_cmd(dev, type, EC_HOST_EVENT_GET, &value); + } else { + assert(type < ARRAY_SIZE(event_map)); + cros_ec_handle_non_uhepi_cmd(dev, event_map[type].get_cmd, + EC_HOST_EVENT_GET, &value); + } + return value; +} + +static int cros_ec_clear_mask(struct udevice *dev, uint type, u64 mask) +{ + if (cros_ec_is_uhepi_supported(dev)) + return cros_ec_uhepi_cmd(dev, type, EC_HOST_EVENT_CLEAR, &mask); + + assert(type < ARRAY_SIZE(event_map)); + + return cros_ec_handle_non_uhepi_cmd(dev, event_map[type].clear_cmd, + EC_HOST_EVENT_CLEAR, &mask); +} + +uint64_t cros_ec_get_events_b(struct udevice *dev) +{ + return cros_ec_get_mask(dev, EC_HOST_EVENT_B); +} + +int cros_ec_clear_events_b(struct udevice *dev, uint64_t mask) +{ + log_debug("Chrome EC: clear events_b mask to 0x%016llx\n", mask); + + return cros_ec_clear_mask(dev, EC_HOST_EVENT_B, mask); +} + +int cros_ec_read_limit_power(struct udevice *dev, int *limit_powerp) +{ + struct ec_params_charge_state p; + struct ec_response_charge_state r; + int ret; + + p.cmd = CHARGE_STATE_CMD_GET_PARAM; + p.get_param.param = CS_PARAM_LIMIT_POWER; + ret = ec_command(dev, EC_CMD_CHARGE_STATE, 0, &p, sizeof(p), + &r, sizeof(r)); + + /* + * If our EC doesn't support the LIMIT_POWER parameter, assume that + * LIMIT_POWER is not requested. + */ + if (ret == -EC_RES_INVALID_PARAM || ret == -EC_RES_INVALID_COMMAND) { + log_warning("PARAM_LIMIT_POWER not supported by EC\n"); + return -ENOSYS; + } + + if (ret != sizeof(r.get_param)) + return -EINVAL; + + *limit_powerp = r.get_param.value; + return 0; +} + +int cros_ec_config_powerbtn(struct udevice *dev, uint32_t flags) +{ + struct ec_params_config_power_button params; + int ret; + + params.flags = flags; + ret = ec_command(dev, EC_CMD_CONFIG_POWER_BUTTON, 0, + ¶ms, sizeof(params), NULL, 0); + if (ret < 0) + return ret; + + return 0; +} + +int cros_ec_get_lid_shutdown_mask(struct udevice *dev) +{ + u32 mask; + int ret; + + ret = cros_ec_get_event_mask(dev, EC_CMD_HOST_EVENT_GET_SMI_MASK, + &mask); + if (ret < 0) + return ret; + + return !!(mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED)); +} + +int cros_ec_set_lid_shutdown_mask(struct udevice *dev, int enable) +{ + u32 mask; + int ret; + + ret = cros_ec_get_event_mask(dev, EC_CMD_HOST_EVENT_GET_SMI_MASK, + &mask); + if (ret < 0) + return ret; + + // Set lid close event state in the EC SMI event mask + if (enable) + mask |= EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED); + else + mask &= ~EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED); + + ret = cros_ec_set_event_mask(dev, EC_CMD_HOST_EVENT_SET_SMI_MASK, mask); + if (ret < 0) + return ret; + + printf("EC: %sabled lid close event\n", enable ? "en" : "dis"); + return 0; +} + UCLASS_DRIVER(cros_ec) = { .id = UCLASS_CROS_EC, .name = "cros_ec", diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c index d741554d8a..429f1a9b26 100644 --- a/drivers/misc/cros_ec_sandbox.c +++ b/drivers/misc/cros_ec_sandbox.c @@ -74,7 +74,7 @@ struct ec_keymatrix_entry { * @recovery_req: Keyboard recovery requested */ struct ec_state { - uint8_t vbnv_context[EC_VBNV_BLOCK_SIZE]; + u8 vbnv_context[EC_VBNV_BLOCK_SIZE_V2]; struct fdt_cros_ec ec_config; uint8_t *flash_data; int flash_data_len; diff --git a/include/cros_ec.h b/include/cros_ec.h index 4771e6b7d1..f4b9b7a5c2 100644 --- a/include/cros_ec.h +++ b/include/cros_ec.h @@ -187,6 +187,14 @@ int cros_ec_flash_protect(struct udevice *dev, uint32_t set_mask, uint32_t set_flags, struct ec_response_flash_protect *resp); +/** + * Notify EC of current boot mode + * + * @param dev CROS-EC device + * @param vboot_mode Verified boot mode + * @return 0 if ok, <0 on error + */ +int cros_ec_entering_mode(struct udevice *dev, int mode); /** * Run internal tests on the cros_ec interface. @@ -397,4 +405,85 @@ struct i2c_msg; int cros_ec_i2c_tunnel(struct udevice *dev, int port, struct i2c_msg *msg, int nmsgs); +/** + * cros_ec_get_events_b() - Get event mask B + * + * @return value of event mask, default value of 0 if it could not be read + */ +uint64_t cros_ec_get_events_b(struct udevice *dev); + +/** + * cros_ec_clear_events_b() - Clear even mask B + * + * Any pending events in the B range are cleared + * + * @return 0 if OK, -ve on error + */ +int cros_ec_clear_events_b(struct udevice *dev, uint64_t mask); + +/** + * cros_ec_efs_verify() - tell the EC to verify one of its images + * + * @param dev CROS-EC device + * @param region Flash region to query + * @return 0 if OK, -ve on error + */ +int cros_ec_efs_verify(struct udevice *dev, enum ec_flash_region region); + +/** + * cros_ec_battery_cutoff() - Request that the battery be cut off + * + * This tells the battery to stop supplying power. This is used before shipping + * a device to ensure that the battery remains charged while the device is + * shipped or sitting on the shelf waiting to be purchased. + * + * @param dev CROS-EC device + * @param flags Flags to use (EC_BATTERY_CUTOFF_FLAG_...) + * @return 0 if OK, -ve on error + */ +int cros_ec_battery_cutoff(struct udevice *dev, uint8_t flags); + +/** + * cros_ec_read_limit_power() - Check if power is limited by batter/charger + * + * Sometimes the battery is low and / or the device is connected to a charger + * that cannot supply much power. + * + * @param dev CROS-EC device + * @param limit_powerp Returns whether power is limited (0 or 1) + * @return 0 if OK, -ENOSYS if the EC does not support this comment, -EINVAL + * if the EC returned an invalid response + */ +int cros_ec_read_limit_power(struct udevice *dev, int *limit_powerp); + +/** + * cros_ec_config_powerbtn() - Configure the behaviour of the power button + * + * @param dev CROS-EC device + * @param flags Flags to use (EC_POWER_BUTTON_...) + * @return 0 if OK, -ve on error + */ +int cros_ec_config_powerbtn(struct udevice *dev, uint32_t flags); + +/** + * cros_ec_get_lid_shutdown_mask() - Set the lid shutdown mask + * + * Determines whether a lid close event is reported + * + * @param dev CROS-EC device + * @return shufdown mas if OK, -ve on error + */ +int cros_ec_get_lid_shutdown_mask(struct udevice *dev); + +/** + * cros_ec_set_lid_shutdown_mask() - Set the lid shutdown mask + * + * Set whether a lid close event is reported + * + * @param dev CROS-EC device + * @param enable true to enable reporting, false to disable + * @return shufdown mas if OK, -ve on error + */ +int cros_ec_set_lid_shutdown_mask(struct udevice *dev, int enable); + #endif From 04488c4d15189a05674962eba890396b498731cc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:23 -0700 Subject: [PATCH 19/33] sandbox: tpm: Allow debugging of data packages This is not normally useful, so change the code to avoid writing out every data package. This can be enabled with #define DEBUG. Signed-off-by: Simon Glass --- drivers/tpm/tpm_tis_sandbox.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/tpm/tpm_tis_sandbox.c b/drivers/tpm/tpm_tis_sandbox.c index 79517f015a..3336f559e5 100644 --- a/drivers/tpm/tpm_tis_sandbox.c +++ b/drivers/tpm/tpm_tis_sandbox.c @@ -187,9 +187,11 @@ static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, code = get_unaligned_be32(sendbuf + sizeof(uint16_t) + sizeof(uint32_t)); +#ifdef DEBUG printf("tpm: %zd bytes, recv_len %zd, cmd = %x\n", send_size, *recv_len, code); print_buffer(0, sendbuf, 1, send_size, 0); +#endif switch (code) { case TPM_CMD_GET_CAPABILITY: type = get_unaligned_be32(sendbuf + 14); @@ -306,6 +308,10 @@ static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, printf("Unknown tpm command %02x\n", code); return -ENOSYS; } +#ifdef DEBUG + printf("tpm: rx recv_len %zd\n", *recv_len); + print_buffer(0, recvbuf, 1, *recv_len, 0); +#endif return 0; } From a5c13b68e7516d3680c87f7207dcf337a1b3dd7c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:24 -0700 Subject: [PATCH 20/33] sandbox: log: Add a category for sandbox It seems useful to make sandbox its own log category since it is used for so much testing. Add this as a new category. Signed-off-by: Simon Glass --- include/log.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/log.h b/include/log.h index a872fc6ef5..deab82966b 100644 --- a/include/log.h +++ b/include/log.h @@ -47,6 +47,7 @@ enum log_category_t { LOGC_DT, /* Device-tree */ LOGC_EFI, /* EFI implementation */ LOGC_ALLOC, /* Memory allocation */ + LOGC_SANDBOX, /* Related to the sandbox board */ LOGC_COUNT, /* Number of log categories */ LOGC_END, /* Sentinel value for a list of log categories */ From 566bf3a8698780079196da742c363ca3b627ca31 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:25 -0700 Subject: [PATCH 21/33] sandbox: Add a function to read a host file Add a way to read a file from the host filesystem. This can be useful for reading test data, for example. Also fix up the writing function which was not the right version, and drop the debugging lines. Signed-off-by: Simon Glass --- arch/sandbox/cpu/os.c | 44 ++++++++++++++++++++++++++++++++++++++++--- include/os.h | 14 ++++++++++++++ 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 325ded51d8..3e0f4c30af 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -98,9 +98,8 @@ void os_exit(int exit_code) exit(exit_code); } -int os_write_file(const char *name, const void *buf, int size) +int os_write_file(const char *fname, const void *buf, int size) { - char fname[256]; int fd; fd = os_open(fname, OS_O_WRONLY | OS_O_CREAT | OS_O_TRUNC); @@ -110,14 +109,53 @@ int os_write_file(const char *name, const void *buf, int size) } if (os_write(fd, buf, size) != size) { printf("Cannot write to file '%s'\n", fname); + os_close(fd); return -EIO; } os_close(fd); - printf("Write '%s', size %#x (%d)\n", name, size, size); return 0; } +int os_read_file(const char *fname, void **bufp, int *sizep) +{ + off_t size; + int ret = -EIO; + int fd; + + fd = os_open(fname, OS_O_RDONLY); + if (fd < 0) { + printf("Cannot open file '%s'\n", fname); + goto err; + } + size = os_lseek(fd, 0, OS_SEEK_END); + if (size < 0) { + printf("Cannot seek to end of file '%s'\n", fname); + goto err; + } + if (os_lseek(fd, 0, OS_SEEK_SET) < 0) { + printf("Cannot seek to start of file '%s'\n", fname); + goto err; + } + *bufp = os_malloc(size); + if (!*bufp) { + printf("Not enough memory to read file '%s'\n", fname); + ret = -ENOMEM; + goto err; + } + if (os_read(fd, *bufp, size) != size) { + printf("Cannot read from file '%s'\n", fname); + goto err; + } + os_close(fd); + *sizep = size; + + return 0; +err: + os_close(fd); + return ret; +} + /* Restore tty state when we exit */ static struct termios orig_term; static bool term_setup; diff --git a/include/os.h b/include/os.h index 28eb625284..6f33b08cf0 100644 --- a/include/os.h +++ b/include/os.h @@ -350,4 +350,18 @@ int os_mprotect_allow(void *start, size_t len); */ int os_write_file(const char *name, const void *buf, int size); +/** + * os_read_file() - Read a file from the host filesystem + * + * This can be useful when reading test data into sandbox for use by test + * routines. The data is allocated using os_malloc() and should be freed by + * the caller. + * + * @name: File path to read from + * @bufp: Returns buffer containing data read + * @sizep: Returns size of data + * @return 0 if OK, -ve on error + */ +int os_read_file(const char *name, void **bufp, int *sizep); + #endif From a2a63a35b2ad6da434aaf8426f2902c6c3bc2352 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:26 -0700 Subject: [PATCH 22/33] sandbox: cros_ec: exynos: Drop use of cros_ec_get_error() This function is really just a call to uclass_get_device() and there is no reason why the caller cannot do it. Update sandbox and snow accordingly. Signed-off-by: Simon Glass Acked-by: Minkyu Kang --- board/samsung/common/board.c | 10 ++++++---- board/sandbox/sandbox.c | 9 ++++++--- common/cros_ec.c | 12 ------------ 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/board/samsung/common/board.c b/board/samsung/common/board.c index c4b6baedf0..6fd26a3a91 100644 --- a/board/samsung/common/board.c +++ b/board/samsung/common/board.c @@ -306,14 +306,16 @@ int checkboard(void) #ifdef CONFIG_BOARD_LATE_INIT int board_late_init(void) { - stdio_print_current_devices(); + struct udevice *dev; + int ret; - if (cros_ec_get_error()) { + stdio_print_current_devices(); + ret = uclass_first_device_err(UCLASS_CROS_EC, &dev); + if (ret && ret != -ENODEV) { /* Force console on */ gd->flags &= ~GD_FLG_SILENT; - printf("cros-ec communications failure %d\n", - cros_ec_get_error()); + printf("cros-ec communications failure %d\n", ret); puts("\nPlease reset with Power+Refresh\n\n"); panic("Cannot init cros-ec device"); return -1; diff --git a/board/sandbox/sandbox.c b/board/sandbox/sandbox.c index 0e87674826..397e7561d4 100644 --- a/board/sandbox/sandbox.c +++ b/board/sandbox/sandbox.c @@ -59,12 +59,15 @@ int board_init(void) #ifdef CONFIG_BOARD_LATE_INIT int board_late_init(void) { - if (cros_ec_get_error()) { + struct udevice *dev; + int ret; + + ret = uclass_first_device_err(UCLASS_CROS_EC, &dev); + if (ret && ret != -ENODEV) { /* Force console on */ gd->flags &= ~GD_FLG_SILENT; - printf("cros-ec communications failure %d\n", - cros_ec_get_error()); + printf("cros-ec communications failure %d\n", ret); puts("\nPlease reset with Power+Refresh\n\n"); panic("Cannot init cros-ec device"); return -1; diff --git a/common/cros_ec.c b/common/cros_ec.c index 4ca15e19d5..e66471ebd1 100644 --- a/common/cros_ec.c +++ b/common/cros_ec.c @@ -25,15 +25,3 @@ struct udevice *board_get_cros_ec_dev(void) } return dev; } - -int cros_ec_get_error(void) -{ - struct udevice *dev; - int ret; - - ret = uclass_get_device(UCLASS_CROS_EC, 0, &dev); - if (ret && ret != -ENODEV) - return ret; - - return 0; -} From 4a5b5e1a466d76fc1c9e6fc8a6ee1337acdcadd0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:27 -0700 Subject: [PATCH 23/33] sandbox: Update some drivers to work in SPL/TPL At present sandbox drivers are mostly not used before relocation. Some of these are needed by Chromium OS verified boot, since it uses sandbox TPL, so update them accordingly. Signed-off-by: Simon Glass --- arch/sandbox/dts/sandbox.dts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts index fb866e8807..1cda911d1f 100644 --- a/arch/sandbox/dts/sandbox.dts +++ b/arch/sandbox/dts/sandbox.dts @@ -20,6 +20,7 @@ cros_ec: cros-ec { reg = <0 0>; + u-boot,dm-pre-reloc; compatible = "google,cros-ec-sandbox"; /* @@ -27,6 +28,7 @@ * that the STM32L flash erases to 0, not 0xff. */ flash { + u-boot,dm-pre-reloc; image-pos = <0x08000000>; size = <0x20000>; erase-value = <0>; @@ -59,6 +61,7 @@ }; gpio_a: gpios@0 { + u-boot,dm-pre-reloc; gpio-controller; compatible = "sandbox,gpio"; #gpio-cells = <1>; @@ -67,6 +70,7 @@ }; gpio_b: gpios@1 { + u-boot,dm-pre-reloc; gpio-controller; compatible = "sandbox,gpio"; #gpio-cells = <2>; @@ -178,12 +182,14 @@ }; spi@0 { + u-boot,dm-pre-reloc; #address-cells = <1>; #size-cells = <0>; reg = <0 0>; compatible = "sandbox,spi"; cs-gpios = <0>, <&gpio_a 0>; firmware_storage_spi: flash@0 { + u-boot,dm-pre-reloc; reg = <0>; compatible = "spansion,m25p16", "sandbox,spi-flash"; spi-max-frequency = <40000000>; @@ -239,6 +245,7 @@ }; tpm { + u-boot,dm-pre-reloc; compatible = "google,sandbox-tpm"; }; @@ -256,6 +263,7 @@ /* Needs to be available prior to relocation */ uart0: serial { + u-boot,dm-spl; compatible = "sandbox,serial"; sandbox,text-colour = "cyan"; pinctrl-names = "default"; @@ -350,3 +358,10 @@ #include "cros-ec-keyboard.dtsi" #include "sandbox_pmic.dtsi" + +&cros_ec { + u-boot,dm-pre-reloc; + keyboard-controller { + u-boot,dm-pre-reloc; + }; +}; From c0126bd862a0dfd59e568e133c4db0a3742e0b0e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:28 -0700 Subject: [PATCH 24/33] spl: Support bootstage, log, hash and early malloc in TPL At present these features are supported in SPL but not TPL. Update the Kconfig and Makefile to allow this. Also add a few Makefile comments to make earier to track what is going on. Signed-off-by: Simon Glass --- common/Kconfig | 35 +++++++++++++++++++++++++++++++++++ common/Makefile | 10 +++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/common/Kconfig b/common/Kconfig index d7300c212f..ba460d9150 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -27,6 +27,15 @@ config SPL_BOOTSTAGE information when SPL finishes and load it when U-Boot proper starts up. +config TPL_BOOTSTAGE + bool "Boot timing and reported in TPL" + depends on BOOTSTAGE + help + Enable recording of boot time in SPL. To make this visible to U-Boot + proper, enable BOOTSTAGE_STASH as well. This will stash the timing + information when TPL finishes and load it when U-Boot proper starts + up. + config BOOTSTAGE_REPORT bool "Display a detailed boot timing report before booting the OS" depends on BOOTSTAGE @@ -444,6 +453,16 @@ config LOG config SPL_LOG bool "Enable logging support in SPL" + depends on LOG + help + This enables support for logging of status and debug messages. These + can be displayed on the console, recorded in a memory buffer, or + discarded if not needed. Logging supports various categories and + levels of severity. + +config TPL_LOG + bool "Enable logging support in TPL" + depends on LOG help This enables support for logging of status and debug messages. These can be displayed on the console, recorded in a memory buffer, or @@ -660,6 +679,22 @@ config AVB_VERIFY * Helpers to access MMC, similar to drivers/fastboot/fb_mmc.c. * Helpers to alloc/init/free avb ops. +config SPL_HASH + bool # "Support hashing API (SHA1, SHA256, etc.)" + help + This provides a way to hash data in memory using various supported + algorithms (such as SHA1, MD5, CRC32). The API is defined in hash.h + and the algorithms it supports are defined in common/hash.c. See + also CMD_HASH for command-line access. + +config TPL_HASH + bool # "Support hashing API (SHA1, SHA256, etc.)" + help + This provides a way to hash data in memory using various supported + algorithms (such as SHA1, MD5, CRC32). The API is defined in hash.h + and the algorithms it supports are defined in common/hash.c. See + also CMD_HASH for command-line access. + endmenu menu "Update support" diff --git a/common/Makefile b/common/Makefile index a2388364d9..bbe2a6e239 100644 --- a/common/Makefile +++ b/common/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_DFU_OVER_USB) += dfu.o endif obj-$(CONFIG_SPL_DFU_SUPPORT) += cli_hush.o obj-$(CONFIG_SPL_HASH_SUPPORT) += hash.o +obj-$(CONFIG_TPL_HASH_SUPPORT) += hash.o obj-$(CONFIG_SPL_YMODEM_SUPPORT) += xyzModem.o obj-$(CONFIG_SPL_LOAD_FIT) += common_fit.o obj-$(CONFIG_SPL_NET_SUPPORT) += miiphyutil.o @@ -76,7 +77,8 @@ ifdef CONFIG_SPL_USB_HOST_SUPPORT obj-$(CONFIG_SPL_USB_SUPPORT) += usb.o usb_hub.o obj-$(CONFIG_USB_STORAGE) += usb_storage.o endif -endif +endif # CONFIG_SPL_BUILD + #others obj-$(CONFIG_DDR_SPD) += ddr_spd.o obj-$(CONFIG_SPD_EEPROM) += ddr_spd.o @@ -90,14 +92,16 @@ obj-$(CONFIG_SPL_SERIAL_SUPPORT) += console.o endif else obj-y += console.o -endif +endif # CONFIG_SPL_BUILD + obj-$(CONFIG_CROS_EC) += cros_ec.o obj-y += dlmalloc.o ifdef CONFIG_SYS_MALLOC_F -ifneq ($(CONFIG_$(SPL_)SYS_MALLOC_F_LEN),0) +ifneq ($(CONFIG_$(SPL_TPL_)SYS_MALLOC_F_LEN),0) obj-y += malloc_simple.o endif endif + obj-y += image.o obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o From 048c6e895647c3337450405388bcd538f92e1e3d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:30 -0700 Subject: [PATCH 25/33] spl: lz4: Allow use of lz4 compression in SPL In some cases U-Boot is compressed and it is useful to be able to decompress it in SPL. Add a Kconfig and Makefile change to allow this. Note that this does not actually implement decompression. Signed-off-by: Simon Glass --- lib/Kconfig | 8 ++++++++ lib/Makefile | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/Kconfig b/lib/Kconfig index 847e797a3a..0333ab172f 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -301,6 +301,14 @@ config LZO help This enables support for LZO compression algorithm.r +config SPL_LZ4 + bool "Enable LZ4 decompression support in SPL" + help + This enables support for tge LZ4 decompression algorithm in SPL. LZ4 + is a lossless data compression algorithm that is focused on + fast compression and decompression speed. It belongs to the LZ77 + family of byte-oriented compression schemes. + config SPL_LZO bool "Enable LZO decompression support in SPL" help diff --git a/lib/Makefile b/lib/Makefile index fb6944128a..4d2e22027d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -38,7 +38,6 @@ obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o obj-y += initcall.o obj-$(CONFIG_LMB) += lmb.o obj-y += ldiv.o -obj-$(CONFIG_LZ4) += lz4_wrapper.o obj-$(CONFIG_MD5) += md5.o obj-y += net_utils.o obj-$(CONFIG_PHYSMEM) += physmem.o @@ -64,6 +63,7 @@ obj-$(CONFIG_SHA256) += sha256.o obj-$(CONFIG_$(SPL_)ZLIB) += zlib/ obj-$(CONFIG_$(SPL_)GZIP) += gunzip.o obj-$(CONFIG_$(SPL_)LZO) += lzo/ +obj-$(CONFIG_$(SPL_)LZ4) += lz4_wrapper.o obj-$(CONFIG_LIBAVB) += libavb/ From a3c005506ac87f3684603fc40ada98070027aaa0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:31 -0700 Subject: [PATCH 26/33] binman: Add a way to enable debugging from the build When the build fails due to something wrong in binman it is sometimes useful to get a full backtrace showing the location of the failure. Add a BINMAN_DEBUG environment variable to support this along with some documentation. Signed-off-by: Simon Glass --- Makefile | 6 ++++-- tools/binman/README | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 552687db53..aeb1c1455b 100644 --- a/Makefile +++ b/Makefile @@ -1048,9 +1048,11 @@ u-boot.ldr: u-boot # binman # --------------------------------------------------------------------------- +# Use 'make BINMAN_DEBUG=1' to enable debugging quiet_cmd_binman = BINMAN $@ -cmd_binman = $(srctree)/tools/binman/binman -d u-boot.dtb -O . \ - -I . -I $(srctree)/board/$(BOARDDIR) $< +cmd_binman = $(srctree)/tools/binman/binman -u -d u-boot.dtb -O . -m \ + -I . -I $(srctree) -I $(srctree)/board/$(BOARDDIR) \ + $(if $(BINMAN_DEBUG),-D) $(BINMAN_$(@F)) $< OBJCOPYFLAGS_u-boot.ldr.hex := -I binary -O ihex diff --git a/tools/binman/README b/tools/binman/README index b64dedf2eb..04ed2b799c 100644 --- a/tools/binman/README +++ b/tools/binman/README @@ -723,6 +723,12 @@ If you need to specify a particular device-tree compiler to use, you can define the DTC environment variable. This can be useful when the system dtc is too old. +To enable a full backtrace and other debugging features in binman, pass +BINMAN_DEBUG=1 to your build: + + make sandbox_defconfig + make BINMAN_DEBUG=1 + History / Credits ----------------- From 26cc8fccc61a6846e763c3cf36c28bc547308bbe Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:32 -0700 Subject: [PATCH 27/33] binman: Drop an unnecessary comma in blob handling This comma is not needed. Drop it. Signed-off-by: Simon Glass --- tools/binman/etype/blob.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binman/etype/blob.py b/tools/binman/etype/blob.py index 642a0e482a..ae80bbee53 100644 --- a/tools/binman/etype/blob.py +++ b/tools/binman/etype/blob.py @@ -60,7 +60,7 @@ class Entry_blob(Entry): except AttributeError: data = lz4.compress(data) ''' - data = tools.Run('lz4', '-c', self._pathname, ) + data = tools.Run('lz4', '-c', self._pathname) self.SetContents(data) return True From 4b6dbaa3073adb24f8c67f89d0f70dbcf00808b9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:33 -0700 Subject: [PATCH 28/33] binman: Set the pathname correctly for ELF files At present, stripped files don't have the right pathname which means that blob compression cannot be used. Fix this. Signed-off-by: Simon Glass --- tools/binman/etype/u_boot_elf.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/binman/etype/u_boot_elf.py b/tools/binman/etype/u_boot_elf.py index 134b6cc15b..f83860dc0a 100644 --- a/tools/binman/etype/u_boot_elf.py +++ b/tools/binman/etype/u_boot_elf.py @@ -30,9 +30,8 @@ class Entry_u_boot_elf(Entry_blob): out_fname = tools.GetOutputFilename('%s.stripped' % uniq) tools.WriteFile(out_fname, tools.ReadFile(self._pathname)) tools.Run('strip', out_fname) - self.SetContents(tools.ReadFile(out_fname)) - else: - self.SetContents(tools.ReadFile(self._pathname)) + self._pathname = out_fname + Entry_blob.ReadBlobContents(self) return True def GetDefaultFilename(self): From b9f210a35c39a191ca375e541e09686a3303e428 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:36 -0700 Subject: [PATCH 29/33] video: Update video_set_default_colors() to support invert It is useful to be able to invert the colours in some cases so that the text matches the background colour. Add a parameter to the function to support this. It is strange that function takes a private data structure from another driver as an argument. It seems better to pass the device and have the function internally work out how to find its required information. Signed-off-by: Simon Glass --- drivers/video/vidconsole-uclass.c | 2 +- drivers/video/video-uclass.c | 27 +++++++++++++++++++-------- include/video.h | 5 +++-- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index 1874887f2f..d7568bc79a 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -344,7 +344,7 @@ static void vidconsole_escape_char(struct udevice *dev, char ch) switch (val) { case 0: /* all attributes off */ - video_set_default_colors(vid_priv); + video_set_default_colors(dev->parent, false); break; case 1: /* bold */ diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index 44dfa71b6f..b6551b69d3 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -115,18 +115,29 @@ int video_clear(struct udevice *dev) return 0; } -void video_set_default_colors(struct video_priv *priv) +void video_set_default_colors(struct udevice *dev, bool invert) { + struct video_priv *priv = dev_get_uclass_priv(dev); + int fore, back; + #ifdef CONFIG_SYS_WHITE_ON_BLACK /* White is used when switching to bold, use light gray here */ - priv->fg_col_idx = VID_LIGHT_GRAY; - priv->colour_fg = vid_console_color(priv, VID_LIGHT_GRAY); - priv->colour_bg = vid_console_color(priv, VID_BLACK); + fore = VID_LIGHT_GRAY; + back = VID_BLACK; #else - priv->fg_col_idx = VID_BLACK; - priv->colour_fg = vid_console_color(priv, VID_BLACK); - priv->colour_bg = vid_console_color(priv, VID_WHITE); + fore = VID_BLACK; + back = VID_WHITE; #endif + if (invert) { + int temp; + + temp = fore; + fore = back; + back = temp; + } + priv->fg_col_idx = fore; + priv->colour_fg = vid_console_color(priv, fore); + priv->colour_bg = vid_console_color(priv, back); } /* Flush video activity to the caches */ @@ -219,7 +230,7 @@ static int video_post_probe(struct udevice *dev) priv->fb_size = priv->line_length * priv->ysize; /* Set up colors */ - video_set_default_colors(priv); + video_set_default_colors(dev, false); if (!CONFIG_IS_ENABLED(NO_FB_CLEAR)) video_clear(dev); diff --git a/include/video.h b/include/video.h index 75200f0e45..3f9139eea4 100644 --- a/include/video.h +++ b/include/video.h @@ -191,9 +191,10 @@ void video_set_flush_dcache(struct udevice *dev, bool flush); /** * Set default colors and attributes * - * @priv device information + * @dev: video device + * @invert true to invert colours */ -void video_set_default_colors(struct video_priv *priv); +void video_set_default_colors(struct udevice *dev, bool invert); #endif /* CONFIG_DM_VIDEO */ From 96794a3eaee9bf368efe475f0a040d0e08b09dc9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:38 -0700 Subject: [PATCH 30/33] string: Include the config header At present the config header is not included in this file, but it does use a CONFIG option. Fix it. Signed-off-by: Simon Glass --- lib/string.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/string.c b/lib/string.c index c4ca944bb4..af17c16f61 100644 --- a/lib/string.c +++ b/lib/string.c @@ -15,6 +15,7 @@ * reentrant and should be faster). Use only strsep() in new code, please. */ +#include #include #include #include From 8729b1ae2cbda83059a55811614a2b0dbfdf7e53 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:39 -0700 Subject: [PATCH 31/33] misc: Update read() and write() methods to return bytes xfered At present these functions return 0 on success. For some devices we want to know how many bytes were transferred. It seems useful to adjust the API to be more like the POSIX read() and write() functions. Update these two methods, a test and all users. Signed-off-by: Simon Glass Reviewed-by: Patrick Delaunay --- arch/arm/mach-stm32mp/cpu.c | 4 ++-- drivers/clk/clk_vexpress_osc.c | 4 ++-- drivers/misc/altera_sysid.c | 2 +- drivers/misc/misc_sandbox.c | 4 ++-- drivers/misc/rockchip-efuse.c | 2 +- drivers/misc/stm32mp_fuse.c | 12 ++++++++++++ include/misc.h | 8 ++++---- test/dm/misc.c | 6 +++--- 8 files changed, 27 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c index 0e01f8e613..b8933587ad 100644 --- a/arch/arm/mach-stm32mp/cpu.c +++ b/arch/arm/mach-stm32mp/cpu.c @@ -306,7 +306,7 @@ static int setup_mac_address(void) ret = misc_read(dev, BSEC_OTP_MAC * 4 + STM32_BSEC_OTP_OFFSET, otp, sizeof(otp)); - if (ret) + if (ret < 0) return ret; for (i = 0; i < 6; i++) @@ -344,7 +344,7 @@ static int setup_serial_number(void) ret = misc_read(dev, BSEC_OTP_SERIAL * 4 + STM32_BSEC_OTP_OFFSET, otp, sizeof(otp)); - if (ret) + if (ret < 0) return ret; sprintf(serial_string, "%08x%08x%08x", otp[0], otp[1], otp[2]); diff --git a/drivers/clk/clk_vexpress_osc.c b/drivers/clk/clk_vexpress_osc.c index 7fef4b2e31..c692a6d0b8 100644 --- a/drivers/clk/clk_vexpress_osc.c +++ b/drivers/clk/clk_vexpress_osc.c @@ -29,7 +29,7 @@ static ulong vexpress_osc_clk_get_rate(struct clk *clk) data = CLK_FUNCTION | priv->osc; err = misc_read(vexpress_cfg, 0, &data, sizeof(data)); - if (err) + if (err < 0) return err; return data; @@ -53,7 +53,7 @@ static ulong vexpress_osc_clk_set_rate(struct clk *clk, ulong rate) buffer[0] = CLK_FUNCTION | priv->osc; buffer[1] = rate; err = misc_write(vexpress_cfg, 0, buffer, 2 * sizeof(u32)); - if (err) + if (err < 0) return err; return rate; diff --git a/drivers/misc/altera_sysid.c b/drivers/misc/altera_sysid.c index 883b2a35e0..eff33f7343 100644 --- a/drivers/misc/altera_sysid.c +++ b/drivers/misc/altera_sysid.c @@ -35,7 +35,7 @@ void display_sysid(void) if (ret) return; ret = misc_read(dev, 0, &sysid, sizeof(sysid)); - if (ret) + if (ret < 0) return; stamp = sysid[1]; diff --git a/drivers/misc/misc_sandbox.c b/drivers/misc/misc_sandbox.c index e4164f76fb..f7c5b2e25f 100644 --- a/drivers/misc/misc_sandbox.c +++ b/drivers/misc/misc_sandbox.c @@ -20,7 +20,7 @@ int misc_sandbox_read(struct udevice *dev, int offset, void *buf, int size) memcpy(buf, priv->mem + offset, size); - return 0; + return size; } int misc_sandbox_write(struct udevice *dev, int offset, const void *buf, @@ -30,7 +30,7 @@ int misc_sandbox_write(struct udevice *dev, int offset, const void *buf, memcpy(priv->mem + offset, buf, size); - return 0; + return size; } int misc_sandbox_ioctl(struct udevice *dev, unsigned long request, void *buf) diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c index 8a213c9e27..2520c6a38e 100644 --- a/drivers/misc/rockchip-efuse.c +++ b/drivers/misc/rockchip-efuse.c @@ -65,7 +65,7 @@ static int dump_efuses(cmd_tbl_t *cmdtp, int flag, } ret = misc_read(dev, 0, &fuses, sizeof(fuses)); - if (ret) { + if (ret < 0) { printf("%s: misc_read failed\n", __func__); return 0; } diff --git a/drivers/misc/stm32mp_fuse.c b/drivers/misc/stm32mp_fuse.c index 2d661351a1..33943a231b 100644 --- a/drivers/misc/stm32mp_fuse.c +++ b/drivers/misc/stm32mp_fuse.c @@ -29,6 +29,9 @@ int fuse_read(u32 bank, u32 word, u32 *val) return ret; ret = misc_read(dev, word * 4 + STM32_BSEC_SHADOW_OFFSET, val, 4); + if (ret < 0) + return ret; + ret = 0; break; default: @@ -54,6 +57,9 @@ int fuse_prog(u32 bank, u32 word, u32 val) return ret; ret = misc_write(dev, word * 4 + STM32_BSEC_OTP_OFFSET, &val, 4); + if (ret < 0) + return ret; + ret = 0; break; default: @@ -78,6 +84,9 @@ int fuse_sense(u32 bank, u32 word, u32 *val) if (ret) return ret; ret = misc_read(dev, word * 4 + STM32_BSEC_OTP_OFFSET, val, 4); + if (ret < 0) + return ret; + ret = 0; break; default: @@ -103,6 +112,9 @@ int fuse_override(u32 bank, u32 word, u32 val) return ret; ret = misc_write(dev, word * 4 + STM32_BSEC_SHADOW_OFFSET, &val, 4); + if (ret < 0) + return ret; + ret = 0; break; default: diff --git a/include/misc.h b/include/misc.h index 50515852b2..12d1325ee2 100644 --- a/include/misc.h +++ b/include/misc.h @@ -13,7 +13,7 @@ * @buf: pointer to data buffer * @size: data size in bytes to read the device * - * Return: 0 if OK, -ve on error + * Return: number of bytes read if OK (may be 0 if EOF), -ve on error */ int misc_read(struct udevice *dev, int offset, void *buf, int size); @@ -24,7 +24,7 @@ int misc_read(struct udevice *dev, int offset, void *buf, int size); * @buf: pointer to data buffer * @size: data size in bytes to write the device * - * Return: 0 if OK, -ve on error + * Return: number of bytes written if OK (may be < @size), -ve on error */ int misc_write(struct udevice *dev, int offset, void *buf, int size); @@ -90,7 +90,7 @@ struct misc_ops { * @buf: pointer to data buffer * @size: data size in bytes to read the device * - * Return: 0 if OK, -ve on error + * Return: number of bytes read if OK (may be 0 if EOF), -ve on error */ int (*read)(struct udevice *dev, int offset, void *buf, int size); @@ -101,7 +101,7 @@ struct misc_ops { * @buf: pointer to data buffer * @size: data size in bytes to write the device * - * Return: 0 if OK, -ve on error + * Return: number of bytes written if OK (may be < @size), -ve on error */ int (*write)(struct udevice *dev, int offset, const void *buf, int size); diff --git a/test/dm/misc.c b/test/dm/misc.c index 61279665ef..4d4232adf1 100644 --- a/test/dm/misc.c +++ b/test/dm/misc.c @@ -21,9 +21,9 @@ static int dm_test_misc(struct unit_test_state *uts) ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "misc-test", &dev)); /* Read / write tests */ - ut_assertok(misc_write(dev, 0, "TEST", 4)); - ut_assertok(misc_write(dev, 4, "WRITE", 5)); - ut_assertok(misc_read(dev, 0, buf, 9)); + ut_asserteq(4, misc_write(dev, 0, "TEST", 4)); + ut_asserteq(5, misc_write(dev, 4, "WRITE", 5)); + ut_asserteq(9, misc_read(dev, 0, buf, 9)); ut_assertok(memcmp(buf, "TESTWRITE", 9)); From f9d49f92f8cdf04a47704519a63368259595c3a0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:40 -0700 Subject: [PATCH 32/33] test: sf: Add a simple SPI flash test The current test is a functional test, covering all the way from the command line to the sandbox SPI driver. This is useful, but it is easier to diagnose failures with a smaller test. Add a simple test which reads and writes data and checks that it is stored and retrieved correctly. Signed-off-by: Simon Glass --- test/dm/sf.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/test/dm/sf.c b/test/dm/sf.c index 35241b9f57..b23e7f8edd 100644 --- a/test/dm/sf.c +++ b/test/dm/sf.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include #include @@ -13,8 +15,48 @@ #include #include -/* Test that sandbox SPI flash works correctly */ +/* Simple test of sandbox SPI flash */ static int dm_test_spi_flash(struct unit_test_state *uts) +{ + struct udevice *dev, *emul; + int full_size = 0x200000; + int size = 0x10000; + u8 *src, *dst; + int i; + + src = map_sysmem(0x20000, full_size); + ut_assertok(os_write_file("spi.bin", src, full_size)); + ut_assertok(uclass_first_device_err(UCLASS_SPI_FLASH, &dev)); + + dst = map_sysmem(0x20000 + full_size, full_size); + ut_assertok(spi_flash_read_dm(dev, 0, size, dst)); + ut_assertok(memcmp(src, dst, size)); + + /* Erase */ + ut_assertok(spi_flash_erase_dm(dev, 0, size)); + ut_assertok(spi_flash_read_dm(dev, 0, size, dst)); + for (i = 0; i < size; i++) + ut_asserteq(dst[i], 0xff); + + /* Write some new data */ + for (i = 0; i < size; i++) + src[i] = i; + ut_assertok(spi_flash_write_dm(dev, 0, size, src)); + ut_assertok(spi_flash_read_dm(dev, 0, size, dst)); + ut_assertok(memcmp(src, dst, size)); + + /* + * Since we are about to destroy all devices, we must tell sandbox + * to forget the emulation device + */ + sandbox_sf_unbind_emul(state_get_current(), 0, 0); + + return 0; +} +DM_TEST(dm_test_spi_flash, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Functional test that sandbox SPI flash works correctly */ +static int dm_test_spi_flash_func(struct unit_test_state *uts) { /* * Create an empty test file and run the SPI flash tests. This is a @@ -39,4 +81,4 @@ static int dm_test_spi_flash(struct unit_test_state *uts) return 0; } -DM_TEST(dm_test_spi_flash, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); +DM_TEST(dm_test_spi_flash_func, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); From a58986ca8b53d8c7a441397082f84edc7f47d19f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 6 Nov 2018 15:21:41 -0700 Subject: [PATCH 33/33] sf: Add a method to obtain the block-protect setting It is useful to obtain the block-protect setting of the SPI flash, so we know whether it is fully open or (perhaps partially) write-protected. Add a method for this. Update the sandbox driver to process this operation and add a test. Signed-off-by: Simon Glass --- arch/sandbox/include/asm/test.h | 8 ++++++++ drivers/mtd/spi/sandbox.c | 10 ++++++++++ drivers/mtd/spi/sf-uclass.c | 9 +++++++++ drivers/mtd/spi/sf_internal.h | 3 +++ drivers/mtd/spi/sf_probe.c | 8 ++++++++ drivers/mtd/spi/spi_flash.c | 12 ++++++++++++ include/spi_flash.h | 27 +++++++++++++++++++++++++++ test/dm/sf.c | 9 +++++++++ 8 files changed, 86 insertions(+) diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h index 8e60f80ae7..5e81839295 100644 --- a/arch/sandbox/include/asm/test.h +++ b/arch/sandbox/include/asm/test.h @@ -113,4 +113,12 @@ int sandbox_osd_get_mem(struct udevice *dev, u8 *buf, size_t buflen); int sandbox_pwm_get_config(struct udevice *dev, uint channel, uint *period_nsp, uint *duty_nsp, bool *enablep, bool *polarityp); +/** + * sandbox_sf_set_block_protect() - Set the BP bits of the status register + * + * @dev: Device to update + * @bp_mask: BP bits to set (bits 2:0, so a value of 0 to 7) + */ +void sandbox_sf_set_block_protect(struct udevice *dev, int bp_mask); + #endif diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c index 7fef754c63..7b9891cb98 100644 --- a/drivers/mtd/spi/sandbox.c +++ b/drivers/mtd/spi/sandbox.c @@ -57,6 +57,8 @@ static const char *sandbox_sf_state_name(enum sandbox_sf_state state) /* Bits for the status register */ #define STAT_WIP (1 << 0) #define STAT_WEL (1 << 1) +#define STAT_BP_SHIFT 2 +#define STAT_BP_MASK (7 << STAT_BP_SHIFT) /* Assume all SPI flashes have 3 byte addresses since they do atm */ #define SF_ADDR_LEN 3 @@ -102,6 +104,14 @@ struct sandbox_spi_flash_plat_data { int cs; }; +void sandbox_sf_set_block_protect(struct udevice *dev, int bp_mask) +{ + struct sandbox_spi_flash *sbsf = dev_get_priv(dev); + + sbsf->status &= ~STAT_BP_MASK; + sbsf->status |= bp_mask << STAT_BP_SHIFT; +} + /** * This is a very strange probe function. If it has platform data (which may * have come from the device tree) then this function gets the filename and diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c index 662525f016..719a2fd23a 100644 --- a/drivers/mtd/spi/sf-uclass.c +++ b/drivers/mtd/spi/sf-uclass.c @@ -28,6 +28,15 @@ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len) return log_ret(sf_get_ops(dev)->erase(dev, offset, len)); } +int spl_flash_get_sw_write_prot(struct udevice *dev) +{ + struct dm_spi_flash_ops *ops = sf_get_ops(dev); + + if (!ops->get_sw_write_prot) + return -ENOSYS; + return log_ret(ops->get_sw_write_prot(dev)); +} + /* * TODO(sjg@chromium.org): This is an old-style function. We should remove * it when all SPI flash drivers use dm diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 26f5c7c995..46a5044417 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -170,6 +170,9 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, /* Flash erase(sectors) operation, support all possible erase commands */ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len); +/* Get software write-protect value (BP bits) */ +int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash); + /* Lock stmicro spi flash region */ int stm_lock(struct spi_flash *flash, u32 ofs, size_t len); diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 94fde2ae7a..5a2e932de8 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -124,6 +124,13 @@ static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) return spi_flash_cmd_erase_ops(flash, offset, len); } +static int spi_flash_std_get_sw_write_prot(struct udevice *dev) +{ + struct spi_flash *flash = dev_get_uclass_priv(dev); + + return spi_flash_cmd_get_sw_write_prot(flash); +} + static int spi_flash_std_probe(struct udevice *dev) { struct spi_slave *slave = dev_get_parent_priv(dev); @@ -141,6 +148,7 @@ static const struct dm_spi_flash_ops spi_flash_std_ops = { .read = spi_flash_std_read, .write = spi_flash_std_write, .erase = spi_flash_std_erase, + .get_sw_write_prot = spi_flash_std_get_sw_write_prot, }; static const struct udevice_id spi_flash_std_ids[] = { diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index a87bacd4ac..0c2392f28a 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -110,6 +110,18 @@ static int write_cr(struct spi_flash *flash, u8 wc) } #endif +int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash) +{ + u8 status; + int ret; + + ret = read_sr(flash, &status); + if (ret) + return ret; + + return (status >> 2) & 7; +} + #ifdef CONFIG_SPI_FLASH_BAR /* * This "clean_bar" is necessary in a situation when one was accessing diff --git a/include/spi_flash.h b/include/spi_flash.h index 0ec98fb55d..e427e960d5 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -112,6 +112,19 @@ struct dm_spi_flash_ops { int (*write)(struct udevice *dev, u32 offset, size_t len, const void *buf); int (*erase)(struct udevice *dev, u32 offset, size_t len); + /** + * get_sw_write_prot() - Check state of software write-protect feature + * + * SPI flash chips can lock a region of the flash defined by a + * 'protected area'. This function checks if this protected area is + * defined. + * + * @dev: SPI flash device + * @return 0 if no region is write-protected, 1 if a region is + * write-protected, -ENOSYS if the driver does not implement this, + * other -ve value on error + */ + int (*get_sw_write_prot)(struct udevice *dev); }; /* Access the serial operations for a device */ @@ -153,6 +166,20 @@ int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len, */ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len); +/** + * spl_flash_get_sw_write_prot() - Check state of software write-protect feature + * + * SPI flash chips can lock a region of the flash defined by a + * 'protected area'. This function checks if this protected area is + * defined. + * + * @dev: SPI flash device + * @return 0 if no region is write-protected, 1 if a region is + * write-protected, -ENOSYS if the driver does not implement this, + * other -ve value on error + */ +int spl_flash_get_sw_write_prot(struct udevice *dev); + int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs, unsigned int max_hz, unsigned int spi_mode, struct udevice **devp); diff --git a/test/dm/sf.c b/test/dm/sf.c index b23e7f8edd..35dce4e4c9 100644 --- a/test/dm/sf.c +++ b/test/dm/sf.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -45,6 +46,14 @@ static int dm_test_spi_flash(struct unit_test_state *uts) ut_assertok(spi_flash_read_dm(dev, 0, size, dst)); ut_assertok(memcmp(src, dst, size)); + /* Try the write-protect stuff */ + ut_assertok(uclass_first_device_err(UCLASS_SPI_EMUL, &emul)); + ut_asserteq(0, spl_flash_get_sw_write_prot(dev)); + sandbox_sf_set_block_protect(emul, 1); + ut_asserteq(1, spl_flash_get_sw_write_prot(dev)); + sandbox_sf_set_block_protect(emul, 0); + ut_asserteq(0, spl_flash_get_sw_write_prot(dev)); + /* * Since we are about to destroy all devices, we must tell sandbox * to forget the emulation device