Parcourir la source

Merge tag 'dm-pull-6oct20' of git://git.denx.de/u-boot-dm

bloblist enhancement for alignment
Update ofnode/dev_read phandle function
sandbox keyboard enhancements and fixes
Tom Rini il y a 3 ans
Parent
commit
42378e3cd2

+ 1 - 0
MAINTAINERS

@@ -959,6 +959,7 @@ SANDBOX
 M:	Simon Glass <sjg@chromium.org>
 M:	Simon Glass <sjg@chromium.org>
 S:	Maintained
 S:	Maintained
 F:	arch/sandbox/
 F:	arch/sandbox/
+F:	doc/arch/sandbox.rst
 
 
 SH
 SH
 M:	Marek Vasut <marek.vasut+renesas@gmail.com>
 M:	Marek Vasut <marek.vasut+renesas@gmail.com>

+ 89 - 67
arch/sandbox/cpu/sdl.c

@@ -172,33 +172,7 @@ int sandbox_sdl_sync(void *lcd_base)
 }
 }
 
 
 static const unsigned short sdl_to_keycode[SDL_NUM_SCANCODES] = {
 static const unsigned short sdl_to_keycode[SDL_NUM_SCANCODES] = {
-	[SDL_SCANCODE_A]	= KEY_A,
-	[SDL_SCANCODE_B]	= KEY_B,
-	[SDL_SCANCODE_C]	= KEY_C,
-	[SDL_SCANCODE_D]	= KEY_D,
-	[SDL_SCANCODE_E]	= KEY_E,
-	[SDL_SCANCODE_F]	= KEY_F,
-	[SDL_SCANCODE_G]	= KEY_G,
-	[SDL_SCANCODE_H]	= KEY_H,
-	[SDL_SCANCODE_I]	= KEY_I,
-	[SDL_SCANCODE_J]	= KEY_J,
-	[SDL_SCANCODE_K]	= KEY_K,
-	[SDL_SCANCODE_L]	= KEY_L,
-	[SDL_SCANCODE_M]	= KEY_M,
-	[SDL_SCANCODE_N]	= KEY_N,
-	[SDL_SCANCODE_O]	= KEY_O,
-	[SDL_SCANCODE_P]	= KEY_P,
-	[SDL_SCANCODE_Q]	= KEY_Q,
-	[SDL_SCANCODE_R]	= KEY_R,
-	[SDL_SCANCODE_S]	= KEY_S,
-	[SDL_SCANCODE_T]	= KEY_T,
-	[SDL_SCANCODE_U]	= KEY_U,
-	[SDL_SCANCODE_V]	= KEY_V,
-	[SDL_SCANCODE_W]	= KEY_W,
-	[SDL_SCANCODE_X]	= KEY_X,
-	[SDL_SCANCODE_Y]	= KEY_Y,
-	[SDL_SCANCODE_Z]	= KEY_Z,
-
+	[SDL_SCANCODE_ESCAPE]	= KEY_ESC,
 	[SDL_SCANCODE_1]	= KEY_1,
 	[SDL_SCANCODE_1]	= KEY_1,
 	[SDL_SCANCODE_2]	= KEY_2,
 	[SDL_SCANCODE_2]	= KEY_2,
 	[SDL_SCANCODE_3]	= KEY_3,
 	[SDL_SCANCODE_3]	= KEY_3,
@@ -209,25 +183,53 @@ static const unsigned short sdl_to_keycode[SDL_NUM_SCANCODES] = {
 	[SDL_SCANCODE_8]	= KEY_8,
 	[SDL_SCANCODE_8]	= KEY_8,
 	[SDL_SCANCODE_9]	= KEY_9,
 	[SDL_SCANCODE_9]	= KEY_9,
 	[SDL_SCANCODE_0]	= KEY_0,
 	[SDL_SCANCODE_0]	= KEY_0,
-
-	[SDL_SCANCODE_RETURN]	= KEY_ENTER,
-	[SDL_SCANCODE_ESCAPE]	= KEY_ESC,
-	[SDL_SCANCODE_BACKSPACE]	= KEY_BACKSPACE,
-	[SDL_SCANCODE_TAB]	= KEY_TAB,
-	[SDL_SCANCODE_SPACE]	= KEY_SPACE,
-
 	[SDL_SCANCODE_MINUS]	= KEY_MINUS,
 	[SDL_SCANCODE_MINUS]	= KEY_MINUS,
 	[SDL_SCANCODE_EQUALS]	= KEY_EQUAL,
 	[SDL_SCANCODE_EQUALS]	= KEY_EQUAL,
-	[SDL_SCANCODE_BACKSLASH]	= KEY_BACKSLASH,
+	[SDL_SCANCODE_BACKSPACE]	= KEY_BACKSPACE,
+	[SDL_SCANCODE_TAB]	= KEY_TAB,
+	[SDL_SCANCODE_Q]	= KEY_Q,
+	[SDL_SCANCODE_W]	= KEY_W,
+	[SDL_SCANCODE_E]	= KEY_E,
+	[SDL_SCANCODE_R]	= KEY_R,
+	[SDL_SCANCODE_T]	= KEY_T,
+	[SDL_SCANCODE_Y]	= KEY_Y,
+	[SDL_SCANCODE_U]	= KEY_U,
+	[SDL_SCANCODE_I]	= KEY_I,
+	[SDL_SCANCODE_O]	= KEY_O,
+	[SDL_SCANCODE_P]	= KEY_P,
+	[SDL_SCANCODE_LEFTBRACKET]	= KEY_LEFTBRACE,
+	[SDL_SCANCODE_RIGHTBRACKET]	= KEY_RIGHTBRACE,
+	[SDL_SCANCODE_RETURN]	= KEY_ENTER,
+	[SDL_SCANCODE_LCTRL]	= KEY_LEFTCTRL,
+	[SDL_SCANCODE_A]	= KEY_A,
+	[SDL_SCANCODE_S]	= KEY_S,
+	[SDL_SCANCODE_D]	= KEY_D,
+	[SDL_SCANCODE_F]	= KEY_F,
+	[SDL_SCANCODE_G]	= KEY_G,
+	[SDL_SCANCODE_H]	= KEY_H,
+	[SDL_SCANCODE_J]	= KEY_J,
+	[SDL_SCANCODE_K]	= KEY_K,
+	[SDL_SCANCODE_L]	= KEY_L,
 	[SDL_SCANCODE_SEMICOLON]	= KEY_SEMICOLON,
 	[SDL_SCANCODE_SEMICOLON]	= KEY_SEMICOLON,
 	[SDL_SCANCODE_APOSTROPHE]	= KEY_APOSTROPHE,
 	[SDL_SCANCODE_APOSTROPHE]	= KEY_APOSTROPHE,
 	[SDL_SCANCODE_GRAVE]	= KEY_GRAVE,
 	[SDL_SCANCODE_GRAVE]	= KEY_GRAVE,
+	[SDL_SCANCODE_LSHIFT]	= KEY_LEFTSHIFT,
+	[SDL_SCANCODE_BACKSLASH]	= KEY_BACKSLASH,
+	[SDL_SCANCODE_Z]	= KEY_Z,
+	[SDL_SCANCODE_X]	= KEY_X,
+	[SDL_SCANCODE_C]	= KEY_C,
+	[SDL_SCANCODE_V]	= KEY_V,
+	[SDL_SCANCODE_B]	= KEY_B,
+	[SDL_SCANCODE_N]	= KEY_N,
+	[SDL_SCANCODE_M]	= KEY_M,
 	[SDL_SCANCODE_COMMA]	= KEY_COMMA,
 	[SDL_SCANCODE_COMMA]	= KEY_COMMA,
 	[SDL_SCANCODE_PERIOD]	= KEY_DOT,
 	[SDL_SCANCODE_PERIOD]	= KEY_DOT,
 	[SDL_SCANCODE_SLASH]	= KEY_SLASH,
 	[SDL_SCANCODE_SLASH]	= KEY_SLASH,
-
+	[SDL_SCANCODE_RSHIFT]	= KEY_RIGHTSHIFT,
+	[SDL_SCANCODE_KP_MULTIPLY] = KEY_KPASTERISK,
+	[SDL_SCANCODE_LALT]	= KEY_LEFTALT,
+	[SDL_SCANCODE_SPACE]	= KEY_SPACE,
 	[SDL_SCANCODE_CAPSLOCK]	= KEY_CAPSLOCK,
 	[SDL_SCANCODE_CAPSLOCK]	= KEY_CAPSLOCK,
-
 	[SDL_SCANCODE_F1]	= KEY_F1,
 	[SDL_SCANCODE_F1]	= KEY_F1,
 	[SDL_SCANCODE_F2]	= KEY_F2,
 	[SDL_SCANCODE_F2]	= KEY_F2,
 	[SDL_SCANCODE_F3]	= KEY_F3,
 	[SDL_SCANCODE_F3]	= KEY_F3,
@@ -238,45 +240,65 @@ static const unsigned short sdl_to_keycode[SDL_NUM_SCANCODES] = {
 	[SDL_SCANCODE_F8]	= KEY_F8,
 	[SDL_SCANCODE_F8]	= KEY_F8,
 	[SDL_SCANCODE_F9]	= KEY_F9,
 	[SDL_SCANCODE_F9]	= KEY_F9,
 	[SDL_SCANCODE_F10]	= KEY_F10,
 	[SDL_SCANCODE_F10]	= KEY_F10,
-	[SDL_SCANCODE_F11]	= KEY_F11,
-	[SDL_SCANCODE_F12]	= KEY_F12,
-
-	[SDL_SCANCODE_PRINTSCREEN]	= KEY_PRINT,
-	[SDL_SCANCODE_SCROLLLOCK]	= KEY_SCROLLLOCK,
-	[SDL_SCANCODE_PAUSE]	= KEY_PAUSE,
-	[SDL_SCANCODE_INSERT]	= KEY_INSERT,
-	[SDL_SCANCODE_HOME]	= KEY_HOME,
-	[SDL_SCANCODE_PAGEUP]	= KEY_PAGEUP,
-	[SDL_SCANCODE_DELETE]	= KEY_DELETE,
-	[SDL_SCANCODE_END]	= KEY_END,
-	[SDL_SCANCODE_PAGEDOWN]	= KEY_PAGEDOWN,
-	[SDL_SCANCODE_RIGHT]	= KEY_RIGHT,
-	[SDL_SCANCODE_LEFT]	= KEY_LEFT,
-	[SDL_SCANCODE_DOWN]	= KEY_DOWN,
-	[SDL_SCANCODE_UP]	= KEY_UP,
-
 	[SDL_SCANCODE_NUMLOCKCLEAR]	= KEY_NUMLOCK,
 	[SDL_SCANCODE_NUMLOCKCLEAR]	= KEY_NUMLOCK,
-	[SDL_SCANCODE_KP_DIVIDE]	= KEY_KPSLASH,
-	[SDL_SCANCODE_KP_MULTIPLY]	= KEY_KPASTERISK,
+	[SDL_SCANCODE_SCROLLLOCK]	= KEY_SCROLLLOCK,
+	[SDL_SCANCODE_KP_7]	= KEY_KP7,
+	[SDL_SCANCODE_KP_8]	= KEY_KP8,
+	[SDL_SCANCODE_KP_9]	= KEY_KP9,
 	[SDL_SCANCODE_KP_MINUS]	= KEY_KPMINUS,
 	[SDL_SCANCODE_KP_MINUS]	= KEY_KPMINUS,
+	[SDL_SCANCODE_KP_4]	= KEY_KP4,
+	[SDL_SCANCODE_KP_5]	= KEY_KP5,
+	[SDL_SCANCODE_KP_6]	= KEY_KP6,
 	[SDL_SCANCODE_KP_PLUS]	= KEY_KPPLUS,
 	[SDL_SCANCODE_KP_PLUS]	= KEY_KPPLUS,
-	[SDL_SCANCODE_KP_ENTER]	= KEY_KPENTER,
 	[SDL_SCANCODE_KP_1]	= KEY_KP1,
 	[SDL_SCANCODE_KP_1]	= KEY_KP1,
 	[SDL_SCANCODE_KP_2]	= KEY_KP2,
 	[SDL_SCANCODE_KP_2]	= KEY_KP2,
 	[SDL_SCANCODE_KP_3]	= KEY_KP3,
 	[SDL_SCANCODE_KP_3]	= KEY_KP3,
-	[SDL_SCANCODE_KP_4]	= KEY_KP4,
-	[SDL_SCANCODE_KP_5]	= KEY_KP5,
-	[SDL_SCANCODE_KP_6]	= KEY_KP6,
-	[SDL_SCANCODE_KP_7]	= KEY_KP7,
-	[SDL_SCANCODE_KP_8]	= KEY_KP8,
-	[SDL_SCANCODE_KP_9]	= KEY_KP9,
 	[SDL_SCANCODE_KP_0]	= KEY_KP0,
 	[SDL_SCANCODE_KP_0]	= KEY_KP0,
 	[SDL_SCANCODE_KP_PERIOD]	= KEY_KPDOT,
 	[SDL_SCANCODE_KP_PERIOD]	= KEY_KPDOT,
-
-	[SDL_SCANCODE_KP_EQUALS]	= KEY_KPEQUAL,
-	[SDL_SCANCODE_KP_COMMA]	= KEY_KPCOMMA,
-
+	/* key 84 does not exist linux_input.h */
+	[SDL_SCANCODE_LANG5]	=  KEY_ZENKAKUHANKAKU,
+	[SDL_SCANCODE_NONUSBACKSLASH]	= KEY_102ND,
+	[SDL_SCANCODE_F11]	= KEY_F11,
+	[SDL_SCANCODE_F12]	= KEY_F12,
+	[SDL_SCANCODE_INTERNATIONAL1]	= KEY_RO,
+	[SDL_SCANCODE_LANG3]	= KEY_KATAKANA,
+	[SDL_SCANCODE_LANG4]	= KEY_HIRAGANA,
+	[SDL_SCANCODE_INTERNATIONAL4] = KEY_HENKAN,
+	[SDL_SCANCODE_INTERNATIONAL2] = KEY_KATAKANAHIRAGANA,
+	[SDL_SCANCODE_INTERNATIONAL5] = KEY_MUHENKAN,
+	/* [SDL_SCANCODE_INTERNATIONAL5] -> [KEY_KPJPCOMMA] */
+	[SDL_SCANCODE_KP_ENTER]	= KEY_KPENTER,
+	[SDL_SCANCODE_RCTRL]	= KEY_RIGHTCTRL,
+	[SDL_SCANCODE_KP_DIVIDE] = KEY_KPSLASH,
 	[SDL_SCANCODE_SYSREQ]	= KEY_SYSRQ,
 	[SDL_SCANCODE_SYSREQ]	= KEY_SYSRQ,
+	[SDL_SCANCODE_RALT]	= KEY_RIGHTALT,
+	/* KEY_LINEFEED */
+	[SDL_SCANCODE_HOME]	= KEY_HOME,
+	[SDL_SCANCODE_UP]	= KEY_UP,
+	[SDL_SCANCODE_PAGEUP]	= KEY_PAGEUP,
+	[SDL_SCANCODE_LEFT]	= KEY_LEFT,
+	[SDL_SCANCODE_RIGHT]	= KEY_RIGHT,
+	[SDL_SCANCODE_END]	= KEY_END,
+	[SDL_SCANCODE_DOWN]	= KEY_DOWN,
+	[SDL_SCANCODE_PAGEDOWN]	= KEY_PAGEDOWN,
+	[SDL_SCANCODE_INSERT]	= KEY_INSERT,
+	[SDL_SCANCODE_DELETE]	= KEY_DELETE,
+	/* KEY_MACRO */
+	[SDL_SCANCODE_MUTE]	= KEY_MUTE,
+	[SDL_SCANCODE_VOLUMEDOWN]	= KEY_VOLUMEDOWN,
+	[SDL_SCANCODE_VOLUMEUP]	= KEY_VOLUMEUP,
+	[SDL_SCANCODE_POWER]	= KEY_POWER,
+	[SDL_SCANCODE_KP_EQUALS]	= KEY_KPEQUAL,
+	[SDL_SCANCODE_KP_PLUSMINUS]	= KEY_KPPLUSMINUS,
+	[SDL_SCANCODE_PAUSE]	= KEY_PAUSE,
+	/* KEY_SCALE */
+	[SDL_SCANCODE_KP_COMMA] = KEY_KPCOMMA,
+	[SDL_SCANCODE_LANG1]	= KEY_HANGUEL,
+	[SDL_SCANCODE_LANG2]	= KEY_HANJA,
+	[SDL_SCANCODE_INTERNATIONAL3]	= KEY_YEN,
+	[SDL_SCANCODE_LGUI]	= KEY_LEFTMETA,
+	[SDL_SCANCODE_RGUI]	= KEY_RIGHTMETA,
+	[SDL_SCANCODE_APPLICATION] = KEY_COMPOSE,
 };
 };
 
 
 int sandbox_sdl_scan_keys(int key[], int max_keys)
 int sandbox_sdl_scan_keys(int key[], int max_keys)

+ 15 - 5
arch/sandbox/dts/cros-ec-keyboard.dtsi

@@ -1,12 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
  * Keyboard dts fragment for devices that use cros-ec-keyboard
  * Keyboard dts fragment for devices that use cros-ec-keyboard
  *
  *
  * Copyright (c) 2014 Google, Inc
  * Copyright (c) 2014 Google, Inc
  *
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
+ * This file is taken from Linux
+ * arch/arm/boot/dts/cros-ec-keyboard.dtsi.
+ *
+ * A duplicate KEY_BACKSLASH key had to be removed.
+ */
 
 
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/input/input.h>
 
 
@@ -22,6 +24,7 @@
 			MATRIX_KEY(0x00, 0x02, KEY_F1)
 			MATRIX_KEY(0x00, 0x02, KEY_F1)
 			MATRIX_KEY(0x00, 0x03, KEY_B)
 			MATRIX_KEY(0x00, 0x03, KEY_B)
 			MATRIX_KEY(0x00, 0x04, KEY_F10)
 			MATRIX_KEY(0x00, 0x04, KEY_F10)
+			MATRIX_KEY(0x00, 0x05, KEY_RO)
 			MATRIX_KEY(0x00, 0x06, KEY_N)
 			MATRIX_KEY(0x00, 0x06, KEY_N)
 			MATRIX_KEY(0x00, 0x08, KEY_EQUAL)
 			MATRIX_KEY(0x00, 0x08, KEY_EQUAL)
 			MATRIX_KEY(0x00, 0x0a, KEY_RIGHTALT)
 			MATRIX_KEY(0x00, 0x0a, KEY_RIGHTALT)
@@ -34,6 +37,7 @@
 			MATRIX_KEY(0x01, 0x08, KEY_APOSTROPHE)
 			MATRIX_KEY(0x01, 0x08, KEY_APOSTROPHE)
 			MATRIX_KEY(0x01, 0x09, KEY_F9)
 			MATRIX_KEY(0x01, 0x09, KEY_F9)
 			MATRIX_KEY(0x01, 0x0b, KEY_BACKSPACE)
 			MATRIX_KEY(0x01, 0x0b, KEY_BACKSPACE)
+			MATRIX_KEY(0x01, 0x0c, KEY_HENKAN)
 
 
 			MATRIX_KEY(0x02, 0x00, KEY_LEFTCTRL)
 			MATRIX_KEY(0x02, 0x00, KEY_LEFTCTRL)
 			MATRIX_KEY(0x02, 0x01, KEY_TAB)
 			MATRIX_KEY(0x02, 0x01, KEY_TAB)
@@ -45,6 +49,7 @@
 			MATRIX_KEY(0x02, 0x07, KEY_102ND)
 			MATRIX_KEY(0x02, 0x07, KEY_102ND)
 			MATRIX_KEY(0x02, 0x08, KEY_LEFTBRACE)
 			MATRIX_KEY(0x02, 0x08, KEY_LEFTBRACE)
 			MATRIX_KEY(0x02, 0x09, KEY_F8)
 			MATRIX_KEY(0x02, 0x09, KEY_F8)
+			MATRIX_KEY(0x02, 0x0a, KEY_YEN)
 
 
 			MATRIX_KEY(0x03, 0x01, KEY_GRAVE)
 			MATRIX_KEY(0x03, 0x01, KEY_GRAVE)
 			MATRIX_KEY(0x03, 0x02, KEY_F2)
 			MATRIX_KEY(0x03, 0x02, KEY_F2)
@@ -52,7 +57,9 @@
 			MATRIX_KEY(0x03, 0x04, KEY_F5)
 			MATRIX_KEY(0x03, 0x04, KEY_F5)
 			MATRIX_KEY(0x03, 0x06, KEY_6)
 			MATRIX_KEY(0x03, 0x06, KEY_6)
 			MATRIX_KEY(0x03, 0x08, KEY_MINUS)
 			MATRIX_KEY(0x03, 0x08, KEY_MINUS)
+			MATRIX_KEY(0x03, 0x09, KEY_F13)
 			MATRIX_KEY(0x03, 0x0b, KEY_BACKSLASH)
 			MATRIX_KEY(0x03, 0x0b, KEY_BACKSLASH)
+			MATRIX_KEY(0x03, 0x0c, KEY_MUHENKAN)
 
 
 			MATRIX_KEY(0x04, 0x00, KEY_RIGHTCTRL)
 			MATRIX_KEY(0x04, 0x00, KEY_RIGHTCTRL)
 			MATRIX_KEY(0x04, 0x01, KEY_A)
 			MATRIX_KEY(0x04, 0x01, KEY_A)
@@ -63,7 +70,10 @@
 			MATRIX_KEY(0x04, 0x06, KEY_J)
 			MATRIX_KEY(0x04, 0x06, KEY_J)
 			MATRIX_KEY(0x04, 0x08, KEY_SEMICOLON)
 			MATRIX_KEY(0x04, 0x08, KEY_SEMICOLON)
 			MATRIX_KEY(0x04, 0x09, KEY_L)
 			MATRIX_KEY(0x04, 0x09, KEY_L)
-			MATRIX_KEY(0x04, 0x0a, KEY_BACKSLASH)
+			/*
+			 * Do not map any key twice
+			 * MATRIX_KEY(0x04, 0x0a, KEY_BACKSLASH)
+			 */
 			MATRIX_KEY(0x04, 0x0b, KEY_ENTER)
 			MATRIX_KEY(0x04, 0x0b, KEY_ENTER)
 
 
 			MATRIX_KEY(0x05, 0x01, KEY_Z)
 			MATRIX_KEY(0x05, 0x01, KEY_Z)

+ 1 - 0
arch/sandbox/dts/test.dts

@@ -131,6 +131,7 @@
 		str-value = "test string";
 		str-value = "test string";
 		interrupts-extended = <&irq 3 0>;
 		interrupts-extended = <&irq 3 0>;
 		acpi,name = "GHIJ";
 		acpi,name = "GHIJ";
+		phandle-value = <&gpio_c 10>, <0xFFFFFFFF 20>, <&gpio_a 30>;
 	};
 	};
 
 
 	junk {
 	junk {

+ 1 - 1
arch/x86/cpu/intel_common/acpi.c

@@ -198,7 +198,7 @@ int southbridge_inject_dsdt(const struct udevice *dev, struct acpi_ctx *ctx)
 	struct acpi_global_nvs *gnvs;
 	struct acpi_global_nvs *gnvs;
 	int ret;
 	int ret;
 
 
-	ret = bloblist_ensure_size(BLOBLISTT_ACPI_GNVS, sizeof(*gnvs),
+	ret = bloblist_ensure_size(BLOBLISTT_ACPI_GNVS, sizeof(*gnvs), 0,
 				   (void **)&gnvs);
 				   (void **)&gnvs);
 	if (ret)
 	if (ret)
 		return log_msg_ret("bloblist", ret);
 		return log_msg_ret("bloblist", ret);

+ 1 - 1
arch/x86/cpu/intel_common/intel_opregion.c

@@ -108,7 +108,7 @@ int intel_gma_init_igd_opregion(struct udevice *dev,
 		struct optionrom_vbt *ext_vbt;
 		struct optionrom_vbt *ext_vbt;
 
 
 		ret = bloblist_ensure_size(BLOBLISTT_INTEL_VBT,
 		ret = bloblist_ensure_size(BLOBLISTT_INTEL_VBT,
-					   vbt->hdr_vbt_size,
+					   vbt->hdr_vbt_size, 0,
 					   (void **)&ext_vbt);
 					   (void **)&ext_vbt);
 		if (ret) {
 		if (ret) {
 			log_err("GMA: Unable to add Ext VBT to bloblist\n");
 			log_err("GMA: Unable to add Ext VBT to bloblist\n");

+ 1 - 1
board/st/stm32mp1/stm32mp1.c

@@ -314,7 +314,7 @@ static int board_check_usb_power(void)
 	 * for each of them
 	 * for each of them
 	 */
 	 */
 	adc_count = ofnode_count_phandle_with_args(node, "st,adc_usb_pd",
 	adc_count = ofnode_count_phandle_with_args(node, "st,adc_usb_pd",
-						   "#io-channel-cells");
+						   "#io-channel-cells", 0);
 	if (adc_count < 0) {
 	if (adc_count < 0) {
 		if (adc_count == -ENOENT)
 		if (adc_count == -ENOENT)
 			return 0;
 			return 0;

+ 9 - 0
cmd/Kconfig

@@ -631,6 +631,15 @@ config CMD_BINOP
 	  Compute binary operations (xor, or, and) of byte arrays of arbitrary
 	  Compute binary operations (xor, or, and) of byte arrays of arbitrary
 	  size from memory and store the result in memory or the environment.
 	  size from memory and store the result in memory or the environment.
 
 
+config CMD_BLOBLIST
+	bool "bloblist"
+	default y if BLOBLIST
+	help
+	  Show information about the bloblist, a collection of binary blobs
+	  held in memory that persist between SPL and U-Boot. In the case of
+	  x86 devices the bloblist can be used to hold ACPI tables so that they
+	  remain available in memory.
+
 config CMD_CRC32
 config CMD_CRC32
 	bool "crc32"
 	bool "crc32"
 	default y
 	default y

+ 1 - 0
cmd/Makefile

@@ -24,6 +24,7 @@ obj-$(CONFIG_CMD_BDI) += bdinfo.o
 obj-$(CONFIG_CMD_BEDBUG) += bedbug.o
 obj-$(CONFIG_CMD_BEDBUG) += bedbug.o
 obj-$(CONFIG_CMD_BIND) += bind.o
 obj-$(CONFIG_CMD_BIND) += bind.o
 obj-$(CONFIG_CMD_BINOP) += binop.o
 obj-$(CONFIG_CMD_BINOP) += binop.o
+obj-$(CONFIG_CMD_BLOBLIST) += bloblist.o
 obj-$(CONFIG_CMD_BLOCK_CACHE) += blkcache.o
 obj-$(CONFIG_CMD_BLOCK_CACHE) += blkcache.o
 obj-$(CONFIG_CMD_BMP) += bmp.o
 obj-$(CONFIG_CMD_BMP) += bmp.o
 obj-$(CONFIG_CMD_BOOTCOUNT) += bootcount.o
 obj-$(CONFIG_CMD_BOOTCOUNT) += bootcount.o

+ 37 - 0
cmd/bloblist.c

@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Command-line access to bloblist features
+ *
+ * Copyright 2020 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bloblist.h>
+#include <command.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int do_bloblist_info(struct cmd_tbl *cmdtp, int flag, int argc,
+			    char *const argv[])
+{
+	bloblist_show_stats();
+
+	return 0;
+}
+
+static int do_bloblist_list(struct cmd_tbl *cmdtp, int flag, int argc,
+			    char *const argv[])
+{
+	bloblist_show_list();
+
+	return 0;
+}
+
+static char bloblist_help_text[] =
+	"info   - show information about the bloblist\n"
+	"bloblist list   - list blobs in the bloblist";
+
+U_BOOT_CMD_WITH_SUBCMDS(bloblist, "Bloblists", bloblist_help_text,
+	U_BOOT_SUBCMD_MKENT(info, 1, 1, do_bloblist_info),
+	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_bloblist_list));

+ 102 - 18
common/bloblist.c

@@ -11,17 +11,47 @@
 #include <spl.h>
 #include <spl.h>
 #include <u-boot/crc.h>
 #include <u-boot/crc.h>
 
 
+/*
+ * A bloblist is a single contiguous chunk of memory with a header
+ * (struct bloblist_hdr) and a number of blobs in it.
+ *
+ * Each blob starts on a BLOBLIST_ALIGN boundary relative to the start of the
+ * bloblist and consists of a struct bloblist_rec, some padding to the required
+ * alignment for the blog and then the actual data. The padding ensures that the
+ * start address of the data in each blob is aligned as required. Note that
+ * each blob's *data* is aligned to BLOBLIST_ALIGN regardless of the alignment
+ * of the bloblist itself or the blob header.
+ *
+ * So far, only BLOBLIST_ALIGN alignment is supported.
+ */
+
 DECLARE_GLOBAL_DATA_PTR;
 DECLARE_GLOBAL_DATA_PTR;
 
 
-struct bloblist_rec *bloblist_first_blob(struct bloblist_hdr *hdr)
+static const char *const tag_name[] = {
+	[BLOBLISTT_NONE]		= "(none)",
+	[BLOBLISTT_EC_HOSTEVENT]	= "EC host event",
+	[BLOBLISTT_SPL_HANDOFF]		= "SPL hand-off",
+	[BLOBLISTT_VBOOT_CTX]		= "Chrome OS vboot context",
+	[BLOBLISTT_VBOOT_HANDOFF]	= "Chrome OS vboot hand-off",
+};
+
+const char *bloblist_tag_name(enum bloblist_tag_t tag)
+{
+	if (tag < 0 || tag >= BLOBLISTT_COUNT)
+		return "invalid";
+
+	return tag_name[tag];
+}
+
+static struct bloblist_rec *bloblist_first_blob(struct bloblist_hdr *hdr)
 {
 {
 	if (hdr->alloced <= hdr->hdr_size)
 	if (hdr->alloced <= hdr->hdr_size)
 		return NULL;
 		return NULL;
 	return (struct bloblist_rec *)((void *)hdr + hdr->hdr_size);
 	return (struct bloblist_rec *)((void *)hdr + hdr->hdr_size);
 }
 }
 
 
-struct bloblist_rec *bloblist_next_blob(struct bloblist_hdr *hdr,
-					struct bloblist_rec *rec)
+static struct bloblist_rec *bloblist_next_blob(struct bloblist_hdr *hdr,
+					       struct bloblist_rec *rec)
 {
 {
 	ulong offset;
 	ulong offset;
 
 
@@ -53,13 +83,25 @@ static struct bloblist_rec *bloblist_findrec(uint tag)
 	return NULL;
 	return NULL;
 }
 }
 
 
-static int bloblist_addrec(uint tag, int size, struct bloblist_rec **recp)
+static int bloblist_addrec(uint tag, int size, int align,
+			   struct bloblist_rec **recp)
 {
 {
 	struct bloblist_hdr *hdr = gd->bloblist;
 	struct bloblist_hdr *hdr = gd->bloblist;
 	struct bloblist_rec *rec;
 	struct bloblist_rec *rec;
-	int new_alloced;
+	int data_start, new_alloced;
+
+	if (!align)
+		align = BLOBLIST_ALIGN;
+
+	/* Figure out where the new data will start */
+	data_start = map_to_sysmem(hdr) + hdr->alloced + sizeof(*rec);
+
+	/* Align the address and then calculate the offset from ->alloced */
+	data_start = ALIGN(data_start, align) - map_to_sysmem(hdr);
+
+	/* Calculate the new allocated total */
+	new_alloced = data_start + ALIGN(size, align);
 
 
-	new_alloced = hdr->alloced + sizeof(*rec) + ALIGN(size, BLOBLIST_ALIGN);
 	if (new_alloced >= hdr->size) {
 	if (new_alloced >= hdr->size) {
 		log(LOGC_BLOBLIST, LOGL_ERR,
 		log(LOGC_BLOBLIST, LOGL_ERR,
 		    "Failed to allocate %x bytes size=%x, need size=%x\n",
 		    "Failed to allocate %x bytes size=%x, need size=%x\n",
@@ -67,21 +109,23 @@ static int bloblist_addrec(uint tag, int size, struct bloblist_rec **recp)
 		return log_msg_ret("bloblist add", -ENOSPC);
 		return log_msg_ret("bloblist add", -ENOSPC);
 	}
 	}
 	rec = (void *)hdr + hdr->alloced;
 	rec = (void *)hdr + hdr->alloced;
-	hdr->alloced = new_alloced;
 
 
 	rec->tag = tag;
 	rec->tag = tag;
-	rec->hdr_size = sizeof(*rec);
+	rec->hdr_size = data_start - hdr->alloced;
 	rec->size = size;
 	rec->size = size;
 	rec->spare = 0;
 	rec->spare = 0;
 
 
 	/* Zero the record data */
 	/* Zero the record data */
-	memset(rec + 1, '\0', rec->size);
+	memset((void *)rec + rec->hdr_size, '\0', rec->size);
+
+	hdr->alloced = new_alloced;
 	*recp = rec;
 	*recp = rec;
 
 
 	return 0;
 	return 0;
 }
 }
 
 
-static int bloblist_ensurerec(uint tag, struct bloblist_rec **recp, int size)
+static int bloblist_ensurerec(uint tag, struct bloblist_rec **recp, int size,
+			      int align)
 {
 {
 	struct bloblist_rec *rec;
 	struct bloblist_rec *rec;
 
 
@@ -94,7 +138,7 @@ static int bloblist_ensurerec(uint tag, struct bloblist_rec **recp, int size)
 	} else {
 	} else {
 		int ret;
 		int ret;
 
 
-		ret = bloblist_addrec(tag, size, &rec);
+		ret = bloblist_addrec(tag, size, align, &rec);
 		if (ret)
 		if (ret)
 			return ret;
 			return ret;
 	}
 	}
@@ -116,22 +160,22 @@ void *bloblist_find(uint tag, int size)
 	return (void *)rec + rec->hdr_size;
 	return (void *)rec + rec->hdr_size;
 }
 }
 
 
-void *bloblist_add(uint tag, int size)
+void *bloblist_add(uint tag, int size, int align)
 {
 {
 	struct bloblist_rec *rec;
 	struct bloblist_rec *rec;
 
 
-	if (bloblist_addrec(tag, size, &rec))
+	if (bloblist_addrec(tag, size, align, &rec))
 		return NULL;
 		return NULL;
 
 
-	return rec + 1;
+	return (void *)rec + rec->hdr_size;
 }
 }
 
 
-int bloblist_ensure_size(uint tag, int size, void **blobp)
+int bloblist_ensure_size(uint tag, int size, int align, void **blobp)
 {
 {
 	struct bloblist_rec *rec;
 	struct bloblist_rec *rec;
 	int ret;
 	int ret;
 
 
-	ret = bloblist_ensurerec(tag, &rec, size);
+	ret = bloblist_ensurerec(tag, &rec, size, align);
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 	*blobp = (void *)rec + rec->hdr_size;
 	*blobp = (void *)rec + rec->hdr_size;
@@ -143,7 +187,7 @@ void *bloblist_ensure(uint tag, int size)
 {
 {
 	struct bloblist_rec *rec;
 	struct bloblist_rec *rec;
 
 
-	if (bloblist_ensurerec(tag, &rec, size))
+	if (bloblist_ensurerec(tag, &rec, size, 0))
 		return NULL;
 		return NULL;
 
 
 	return (void *)rec + rec->hdr_size;
 	return (void *)rec + rec->hdr_size;
@@ -154,7 +198,7 @@ int bloblist_ensure_size_ret(uint tag, int *sizep, void **blobp)
 	struct bloblist_rec *rec;
 	struct bloblist_rec *rec;
 	int ret;
 	int ret;
 
 
-	ret = bloblist_ensurerec(tag, &rec, *sizep);
+	ret = bloblist_ensurerec(tag, &rec, *sizep, 0);
 	if (ret == -ESPIPE)
 	if (ret == -ESPIPE)
 		*sizep = rec->size;
 		*sizep = rec->size;
 	else if (ret)
 	else if (ret)
@@ -233,6 +277,46 @@ int bloblist_finish(void)
 	return 0;
 	return 0;
 }
 }
 
 
+void bloblist_get_stats(ulong *basep, ulong *sizep, ulong *allocedp)
+{
+	struct bloblist_hdr *hdr = gd->bloblist;
+
+	*basep = map_to_sysmem(gd->bloblist);
+	*sizep = hdr->size;
+	*allocedp = hdr->alloced;
+}
+
+static void show_value(const char *prompt, ulong value)
+{
+	printf("%s:%*s %-5lx  ", prompt, 8 - (int)strlen(prompt), "", value);
+	print_size(value, "\n");
+}
+
+void bloblist_show_stats(void)
+{
+	ulong base, size, alloced;
+
+	bloblist_get_stats(&base, &size, &alloced);
+	printf("base:     %lx\n", base);
+	show_value("size", size);
+	show_value("alloced", alloced);
+	show_value("free", size - alloced);
+}
+
+void bloblist_show_list(void)
+{
+	struct bloblist_hdr *hdr = gd->bloblist;
+	struct bloblist_rec *rec;
+
+	printf("%-8s  %8s  Tag Name\n", "Address", "Size");
+	for (rec = bloblist_first_blob(hdr); rec;
+	     rec = bloblist_next_blob(hdr, rec)) {
+		printf("%08lx  %8x  %3d %s\n",
+		       (ulong)map_to_sysmem((void *)rec + rec->hdr_size),
+		       rec->size, rec->tag, bloblist_tag_name(rec->tag));
+	}
+}
+
 int bloblist_init(void)
 int bloblist_init(void)
 {
 {
 	bool expected;
 	bool expected;

+ 33 - 24
doc/arch/sandbox.rst

@@ -97,30 +97,39 @@ Command-line Options
 --------------------
 --------------------
 
 
 Various options are available, mostly for test purposes. Use -h to see
 Various options are available, mostly for test purposes. Use -h to see
-available options. Some of these are described below.
-
-The terminal is normally in what is called 'raw-with-sigs' mode. This means
-that you can use arrow keys for command editing and history, but if you
-press Ctrl-C, U-Boot will exit instead of handling this as a keypress.
-
-Other options are 'raw' (so Ctrl-C is handled within U-Boot) and 'cooked'
-(where the terminal is in cooked mode and cursor keys will not work, Ctrl-C
-will exit).
-
-As mentioned above, -l causes the LCD emulation window to be shown.
-
-A device tree binary file can be provided with -d. If you edit the source
-(it is stored at arch/sandbox/dts/sandbox.dts) you must rebuild U-Boot to
-recreate the binary file.
-
-To use the default device tree, use -D. To use the test device tree, use -T.
-
-To execute commands directly, use the -c option. You can specify a single
-command, or multiple commands separated by a semicolon, as is normal in
-U-Boot. Be careful with quoting as the shell will normally process and
-swallow quotes. When -c is used, U-Boot exits after the command is complete,
-but you can force it to go to interactive mode instead with -i.
-
+available options. Some of these are described below:
+
+* -t, --terminal <arg>
+  - The terminal is normally in what is called 'raw-with-sigs' mode. This means
+  that you can use arrow keys for command editing and history, but if you
+  press Ctrl-C, U-Boot will exit instead of handling this as a keypress.
+  Other options are 'raw' (so Ctrl-C is handled within U-Boot) and 'cooked'
+  (where the terminal is in cooked mode and cursor keys will not work, Ctrl-C
+  will exit).
+
+* -l
+  - Show the LCD emulation window.
+
+* -d <device_tree>
+  - A device tree binary file can be provided with -d. If you edit the source
+  (it is stored at arch/sandbox/dts/sandbox.dts) you must rebuild U-Boot to
+  recreate the binary file.
+
+* -D
+  - To use the default device tree, use -D.
+
+* -T
+  - To use the test device tree, use -T.
+
+* -c [<cmd>;]<cmd>
+  - To execute commands directly, use the -c option. You can specify a single
+  command, or multiple commands separated by a semicolon, as is normal in
+  U-Boot. Be careful with quoting as the shell will normally process and
+  swallow quotes. When -c is used, U-Boot exits after the command is complete,
+  but you can force it to go to interactive mode instead with -i.
+
+* -i
+  - Go to interactive mode after executing the commands specified by -c.
 
 
 Memory Emulation
 Memory Emulation
 ----------------
 ----------------

+ 2 - 2
drivers/clk/clk-uclass.c

@@ -161,7 +161,7 @@ int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk)
 	
 	
 	bulk->count = 0;
 	bulk->count = 0;
 
 
-	count = dev_count_phandle_with_args(dev, "clocks", "#clock-cells");
+	count = dev_count_phandle_with_args(dev, "clocks", "#clock-cells", 0);
 	if (count < 1)
 	if (count < 1)
 		return count;
 		return count;
 
 
@@ -213,7 +213,7 @@ static int clk_set_default_parents(struct udevice *dev, int stage)
 	int ret;
 	int ret;
 
 
 	num_parents = dev_count_phandle_with_args(dev, "assigned-clock-parents",
 	num_parents = dev_count_phandle_with_args(dev, "assigned-clock-parents",
-						  "#clock-cells");
+						  "#clock-cells", 0);
 	if (num_parents < 0) {
 	if (num_parents < 0) {
 		debug("%s: could not read assigned-clock-parents for %p\n",
 		debug("%s: could not read assigned-clock-parents for %p\n",
 		      __func__, dev);
 		      __func__, dev);

+ 4 - 3
drivers/core/of_access.c

@@ -756,10 +756,11 @@ int of_parse_phandle_with_args(const struct device_node *np,
 }
 }
 
 
 int of_count_phandle_with_args(const struct device_node *np,
 int of_count_phandle_with_args(const struct device_node *np,
-			       const char *list_name, const char *cells_name)
+			       const char *list_name, const char *cells_name,
+			       int cell_count)
 {
 {
-	return __of_parse_phandle_with_args(np, list_name, cells_name, 0,
-					    -1, NULL);
+	return __of_parse_phandle_with_args(np, list_name, cells_name,
+					    cell_count, -1, NULL);
 }
 }
 
 
 static void of_alias_add(struct alias_prop *ap, struct device_node *np,
 static void of_alias_add(struct alias_prop *ap, struct device_node *np,

+ 3 - 3
drivers/core/ofnode.c

@@ -432,15 +432,15 @@ int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
 }
 }
 
 
 int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
 int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
-				   const char *cells_name)
+				   const char *cells_name, int cell_count)
 {
 {
 	if (ofnode_is_np(node))
 	if (ofnode_is_np(node))
 		return of_count_phandle_with_args(ofnode_to_np(node),
 		return of_count_phandle_with_args(ofnode_to_np(node),
-				list_name, cells_name);
+				list_name, cells_name, cell_count);
 	else
 	else
 		return fdtdec_parse_phandle_with_args(gd->fdt_blob,
 		return fdtdec_parse_phandle_with_args(gd->fdt_blob,
 				ofnode_to_offset(node), list_name, cells_name,
 				ofnode_to_offset(node), list_name, cells_name,
-				0, -1, NULL);
+				cell_count, -1, NULL);
 }
 }
 
 
 ofnode ofnode_path(const char *path)
 ofnode ofnode_path(const char *path)

+ 3 - 2
drivers/core/read.c

@@ -214,10 +214,11 @@ int dev_read_phandle_with_args(const struct udevice *dev, const char *list_name,
 }
 }
 
 
 int dev_count_phandle_with_args(const struct udevice *dev,
 int dev_count_phandle_with_args(const struct udevice *dev,
-				const char *list_name, const char *cells_name)
+				const char *list_name, const char *cells_name,
+				int cell_count)
 {
 {
 	return ofnode_count_phandle_with_args(dev_ofnode(dev), list_name,
 	return ofnode_count_phandle_with_args(dev_ofnode(dev), list_name,
-					      cells_name);
+					      cells_name, cell_count);
 }
 }
 
 
 int dev_read_addr_cells(const struct udevice *dev)
 int dev_read_addr_cells(const struct udevice *dev)

+ 2 - 1
drivers/net/designware.c

@@ -688,7 +688,8 @@ int designware_eth_probe(struct udevice *dev)
 	int i, clock_nb;
 	int i, clock_nb;
 
 
 	priv->clock_count = 0;
 	priv->clock_count = 0;
-	clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells");
+	clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells",
+					       0);
 	if (clock_nb > 0) {
 	if (clock_nb > 0) {
 		priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
 		priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
 					    GFP_KERNEL);
 					    GFP_KERNEL);

+ 1 - 1
drivers/phy/phy-uclass.c

@@ -214,7 +214,7 @@ int generic_phy_get_bulk(struct udevice *dev, struct phy_bulk *bulk)
 	if (!dev_read_prop(dev, "phys", NULL))
 	if (!dev_read_prop(dev, "phys", NULL))
 		return 0;
 		return 0;
 
 
-	count = dev_count_phandle_with_args(dev, "phys", "#phy-cells");
+	count = dev_count_phandle_with_args(dev, "phys", "#phy-cells", 0);
 	if (count < 1)
 	if (count < 1)
 		return count;
 		return count;
 
 

+ 1 - 1
drivers/power/domain/power-domain-uclass.c

@@ -117,7 +117,7 @@ static int dev_power_domain_ctrl(struct udevice *dev, bool on)
 	int i, count, ret = 0;
 	int i, count, ret = 0;
 
 
 	count = dev_count_phandle_with_args(dev, "power-domains",
 	count = dev_count_phandle_with_args(dev, "power-domains",
-					    "#power-domain-cells");
+					    "#power-domain-cells", 0);
 	for (i = 0; i < count; i++) {
 	for (i = 0; i < count; i++) {
 		ret = power_domain_get_by_index(dev, &pd, i);
 		ret = power_domain_get_by_index(dev, &pd, i);
 		if (ret)
 		if (ret)

+ 2 - 1
drivers/reset/reset-uclass.c

@@ -108,7 +108,8 @@ static int __reset_get_bulk(struct udevice *dev, ofnode node,
 
 
 	bulk->count = 0;
 	bulk->count = 0;
 
 
-	count = ofnode_count_phandle_with_args(node, "resets", "#reset-cells");
+	count = ofnode_count_phandle_with_args(node, "resets", "#reset-cells",
+					       0);
 	if (count < 1)
 	if (count < 1)
 		return count;
 		return count;
 
 

+ 2 - 2
drivers/usb/host/ehci-generic.c

@@ -86,7 +86,7 @@ static int ehci_usb_probe(struct udevice *dev)
 	err = 0;
 	err = 0;
 	priv->clock_count = 0;
 	priv->clock_count = 0;
 	clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks",
 	clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks",
-						  "#clock-cells");
+						  "#clock-cells", 0);
 	if (clock_nb > 0) {
 	if (clock_nb > 0) {
 		priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
 		priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
 					    GFP_KERNEL);
 					    GFP_KERNEL);
@@ -116,7 +116,7 @@ static int ehci_usb_probe(struct udevice *dev)
 
 
 	priv->reset_count = 0;
 	priv->reset_count = 0;
 	reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets",
 	reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets",
-						  "#reset-cells");
+						  "#reset-cells", 0);
 	if (reset_nb > 0) {
 	if (reset_nb > 0) {
 		priv->resets = devm_kcalloc(dev, reset_nb,
 		priv->resets = devm_kcalloc(dev, reset_nb,
 					    sizeof(struct reset_ctl),
 					    sizeof(struct reset_ctl),

+ 2 - 1
drivers/usb/host/ohci-da8xx.c

@@ -95,7 +95,8 @@ static int ohci_da8xx_probe(struct udevice *dev)
 
 
 	err = 0;
 	err = 0;
 	priv->clock_count = 0;
 	priv->clock_count = 0;
-	clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells");
+	clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells",
+					       0);
 
 
 	if (clock_nb < 0)
 	if (clock_nb < 0)
 		return clock_nb;
 		return clock_nb;

+ 4 - 2
drivers/usb/host/ohci-generic.c

@@ -85,7 +85,8 @@ static int ohci_usb_probe(struct udevice *dev)
 
 
 	err = 0;
 	err = 0;
 	priv->clock_count = 0;
 	priv->clock_count = 0;
-	clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells");
+	clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells",
+					       0);
 	if (clock_nb > 0) {
 	if (clock_nb > 0) {
 		priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
 		priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
 					    GFP_KERNEL);
 					    GFP_KERNEL);
@@ -111,7 +112,8 @@ static int ohci_usb_probe(struct udevice *dev)
 	}
 	}
 
 
 	priv->reset_count = 0;
 	priv->reset_count = 0;
-	reset_nb = dev_count_phandle_with_args(dev, "resets", "#reset-cells");
+	reset_nb = dev_count_phandle_with_args(dev, "resets", "#reset-cells",
+					       0);
 	if (reset_nb > 0) {
 	if (reset_nb > 0) {
 		priv->resets = devm_kcalloc(dev, reset_nb,
 		priv->resets = devm_kcalloc(dev, reset_nb,
 					    sizeof(struct reset_ctl),
 					    sizeof(struct reset_ctl),

+ 38 - 4
include/bloblist.h

@@ -19,6 +19,7 @@ enum {
 	BLOBLIST_ALIGN		= 16,
 	BLOBLIST_ALIGN		= 16,
 };
 };
 
 
+/* Supported tags - add new ones to tag_name in bloblist.c */
 enum bloblist_tag_t {
 enum bloblist_tag_t {
 	BLOBLISTT_NONE = 0,
 	BLOBLISTT_NONE = 0,
 
 
@@ -35,6 +36,8 @@ enum bloblist_tag_t {
 	BLOBLISTT_INTEL_VBT,		/* Intel Video-BIOS table */
 	BLOBLISTT_INTEL_VBT,		/* Intel Video-BIOS table */
 	BLOBLISTT_TPM2_TCG_LOG,		/* TPM v2 log space */
 	BLOBLISTT_TPM2_TCG_LOG,		/* TPM v2 log space */
 	BLOBLISTT_TCPA_LOG,		/* TPM log space */
 	BLOBLISTT_TCPA_LOG,		/* TPM log space */
+
+	BLOBLISTT_COUNT
 };
 };
 
 
 /**
 /**
@@ -65,7 +68,7 @@ enum bloblist_tag_t {
  *	the bloblist can grow up to this size. This starts out as
  *	the bloblist can grow up to this size. This starts out as
  *	sizeof(bloblist_hdr) since we need at least that much space to store a
  *	sizeof(bloblist_hdr) since we need at least that much space to store a
  *	valid bloblist
  *	valid bloblist
- * @spare: Space space
+ * @spare: Spare space (for future use)
  * @chksum: CRC32 for the entire bloblist allocated area. Since any of the
  * @chksum: CRC32 for the entire bloblist allocated area. Since any of the
  *	blobs can be altered after being created, this checksum is only valid
  *	blobs can be altered after being created, this checksum is only valid
  *	when the bloblist is finalised before jumping to the next stage of boot.
  *	when the bloblist is finalised before jumping to the next stage of boot.
@@ -112,7 +115,7 @@ struct bloblist_rec {
  * Searches the bloblist and returns the blob with the matching tag
  * Searches the bloblist and returns the blob with the matching tag
  *
  *
  * @tag:	Tag to search for (enum bloblist_tag_t)
  * @tag:	Tag to search for (enum bloblist_tag_t)
- * @size:	Expected size of the blob
+ * @size:	Expected size of the blob, or 0 for any size
  * @return pointer to blob if found, or NULL if not found, or a blob was found
  * @return pointer to blob if found, or NULL if not found, or a blob was found
  *	but it is the wrong size
  *	but it is the wrong size
  */
  */
@@ -129,10 +132,11 @@ void *bloblist_find(uint tag, int size);
  *
  *
  * @tag:	Tag to add (enum bloblist_tag_t)
  * @tag:	Tag to add (enum bloblist_tag_t)
  * @size:	Size of the blob
  * @size:	Size of the blob
+ * @align:	Alignment of the blob (in bytes), 0 for default
  * @return pointer to the newly added block, or NULL if there is not enough
  * @return pointer to the newly added block, or NULL if there is not enough
  *	space for the blob
  *	space for the blob
  */
  */
-void *bloblist_add(uint tag, int size);
+void *bloblist_add(uint tag, int size, int align);
 
 
 /**
 /**
  * bloblist_ensure_size() - Find or add a blob
  * bloblist_ensure_size() - Find or add a blob
@@ -142,10 +146,11 @@ void *bloblist_add(uint tag, int size);
  * @tag:	Tag to add (enum bloblist_tag_t)
  * @tag:	Tag to add (enum bloblist_tag_t)
  * @size:	Size of the blob
  * @size:	Size of the blob
  * @blobp:	Returns a pointer to blob on success
  * @blobp:	Returns a pointer to blob on success
+ * @align:	Alignment of the blob (in bytes), 0 for default
  * @return 0 if OK, -ENOSPC if it is missing and could not be added due to lack
  * @return 0 if OK, -ENOSPC if it is missing and could not be added due to lack
  *	of space, or -ESPIPE it exists but has the wrong size
  *	of space, or -ESPIPE it exists but has the wrong size
  */
  */
-int bloblist_ensure_size(uint tag, int size, void **blobp);
+int bloblist_ensure_size(uint tag, int size, int align, void **blobp);
 
 
 /**
 /**
  * bloblist_ensure() - Find or add a blob
  * bloblist_ensure() - Find or add a blob
@@ -206,6 +211,35 @@ int bloblist_check(ulong addr, uint size);
  */
  */
 int bloblist_finish(void);
 int bloblist_finish(void);
 
 
+/**
+ * bloblist_get_stats() - Get information about the bloblist
+ *
+ * This returns useful information about the bloblist
+ */
+void bloblist_get_stats(ulong *basep, ulong *sizep, ulong *allocedp);
+
+/**
+ * bloblist_show_stats() - Show information about the bloblist
+ *
+ * This shows useful information about the bloblist on the console
+ */
+void bloblist_show_stats(void);
+
+/**
+ * bloblist_show_list() - Show a list of blobs in the bloblist
+ *
+ * This shows a list of blobs, showing their address, size and tag.
+ */
+void bloblist_show_list(void);
+
+/**
+ * bloblist_tag_name() - Get the name for a tag
+ *
+ * @tag: Tag to check
+ * @return name of tag, or "invalid" if an invalid tag is provided
+ */
+const char *bloblist_tag_name(enum bloblist_tag_t tag);
+
 /**
 /**
  * bloblist_init() - Init the bloblist system with a single bloblist
  * bloblist_init() - Init the bloblist system with a single bloblist
  *
  *

+ 3 - 1
include/dm/of_access.h

@@ -450,6 +450,7 @@ int of_parse_phandle_with_args(const struct device_node *np,
  * @np:		pointer to a device tree node containing a list
  * @np:		pointer to a device tree node containing a list
  * @list_name:	property name that contains a list
  * @list_name:	property name that contains a list
  * @cells_name:	property name that specifies phandles' arguments count
  * @cells_name:	property name that specifies phandles' arguments count
+ * @cells_count: Cell count to use if @cells_name is NULL
  * @return number of phandle found, -ENOENT if
  * @return number of phandle found, -ENOENT if
  *	@list_name does not exist, -EINVAL if a phandle was not found,
  *	@list_name does not exist, -EINVAL if a phandle was not found,
  *	@cells_name could not be found, the arguments were truncated or there
  *	@cells_name could not be found, the arguments were truncated or there
@@ -460,7 +461,8 @@ int of_parse_phandle_with_args(const struct device_node *np,
  *
  *
  */
  */
 int of_count_phandle_with_args(const struct device_node *np,
 int of_count_phandle_with_args(const struct device_node *np,
-			       const char *list_name, const char *cells_name);
+			       const char *list_name, const char *cells_name,
+			       int cells_count);
 
 
 /**
 /**
  * of_alias_scan() - Scan all properties of the 'aliases' node
  * of_alias_scan() - Scan all properties of the 'aliases' node

+ 7 - 5
include/dm/ofnode.h

@@ -10,6 +10,7 @@
 /* TODO(sjg@chromium.org): Drop fdtdec.h include */
 /* TODO(sjg@chromium.org): Drop fdtdec.h include */
 #include <fdtdec.h>
 #include <fdtdec.h>
 #include <dm/of.h>
 #include <dm/of.h>
+#include <log.h>
 
 
 /* Enable checks to protect against invalid calls */
 /* Enable checks to protect against invalid calls */
 #undef OF_CHECKS
 #undef OF_CHECKS
@@ -84,7 +85,7 @@ struct ofprop {
 };
 };
 
 
 /**
 /**
- * _ofnode_to_np() - convert an ofnode to a live DT node pointer
+ * ofnode_to_np() - convert an ofnode to a live DT node pointer
  *
  *
  * This cannot be called if the reference contains an offset.
  * This cannot be called if the reference contains an offset.
  *
  *
@@ -127,7 +128,7 @@ static inline bool ofnode_valid(ofnode node)
 	if (of_live_active())
 	if (of_live_active())
 		return node.np != NULL;
 		return node.np != NULL;
 	else
 	else
-		return node.of_offset != -1;
+		return node.of_offset >= 0;
 }
 }
 
 
 /**
 /**
@@ -182,8 +183,8 @@ static inline bool ofnode_is_np(ofnode node)
 	 * live tree is in use.
 	 * live tree is in use.
 	 */
 	 */
 	assert(!ofnode_valid(node) ||
 	assert(!ofnode_valid(node) ||
-	       (of_live_active() ? _ofnode_to_np(node)
-				  : _ofnode_to_np(node)));
+	       (of_live_active() ? ofnode_to_np(node)
+				  : ofnode_to_np(node)));
 #endif
 #endif
 	return of_live_active() && ofnode_valid(node);
 	return of_live_active() && ofnode_valid(node);
 }
 }
@@ -555,12 +556,13 @@ int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
  * @node:	device tree node containing a list
  * @node:	device tree node containing a list
  * @list_name:	property name that contains a list
  * @list_name:	property name that contains a list
  * @cells_name:	property name that specifies phandles' arguments count
  * @cells_name:	property name that specifies phandles' arguments count
+ * @cells_count: Cell count to use if @cells_name is NULL
  * @return number of phandle on success, -ENOENT if @list_name does not
  * @return number of phandle on success, -ENOENT if @list_name does not
  *      exist, -EINVAL if a phandle was not found, @cells_name could not
  *      exist, -EINVAL if a phandle was not found, @cells_name could not
  *      be found.
  *      be found.
  */
  */
 int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
 int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
-				   const char *cells_name);
+				   const char *cells_name, int cell_count);
 
 
 /**
 /**
  * ofnode_path() - find a node by full path
  * ofnode_path() - find a node by full path

+ 5 - 3
include/dm/read.h

@@ -429,12 +429,14 @@ int dev_read_phandle_with_args(const struct udevice *dev, const char *list_name,
  * @dev:	device whose node containing a list
  * @dev:	device whose node containing a list
  * @list_name:	property name that contains a list
  * @list_name:	property name that contains a list
  * @cells_name:	property name that specifies phandles' arguments count
  * @cells_name:	property name that specifies phandles' arguments count
+ * @cells_count: Cell count to use if @cells_name is NULL
  * @Returns number of phandle found on success, on error returns appropriate
  * @Returns number of phandle found on success, on error returns appropriate
  * errno value.
  * errno value.
  */
  */
 
 
 int dev_count_phandle_with_args(const struct udevice *dev,
 int dev_count_phandle_with_args(const struct udevice *dev,
-				const char *list_name, const char *cells_name);
+				const char *list_name, const char *cells_name,
+				int cell_count);
 
 
 /**
 /**
  * dev_read_addr_cells() - Get the number of address cells for a device's node
  * dev_read_addr_cells() - Get the number of address cells for a device's node
@@ -880,10 +882,10 @@ static inline int dev_read_phandle_with_args(const struct udevice *dev,
 }
 }
 
 
 static inline int dev_count_phandle_with_args(const struct udevice *dev,
 static inline int dev_count_phandle_with_args(const struct udevice *dev,
-		const char *list_name, const char *cells_name)
+		const char *list_name, const char *cells_name, int cell_count)
 {
 {
 	return ofnode_count_phandle_with_args(dev_ofnode(dev), list_name,
 	return ofnode_count_phandle_with_args(dev_ofnode(dev), list_name,
-					      cells_name);
+					      cells_name, cell_count);
 }
 }
 
 
 static inline int dev_read_addr_cells(const struct udevice *dev)
 static inline int dev_read_addr_cells(const struct udevice *dev)

+ 13 - 0
include/test/ut.h

@@ -224,6 +224,19 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes);
 	}								\
 	}								\
 }
 }
 
 
+/* Assert that two addresses (converted from pointers) are equal */
+#define ut_asserteq_addr(expr1, expr2) {				\
+	ulong _val1 = map_to_sysmem(expr1);				\
+	ulong _val2 = map_to_sysmem(expr2);				\
+									\
+	if (_val1 != _val2) {						\
+		ut_failf(uts, __FILE__, __LINE__, __func__,		\
+			 #expr1 " = " #expr2,				\
+			 "Expected %lx, got %lx", _val1, _val2);	\
+		return CMD_RET_FAILURE;					\
+	}								\
+}
+
 /* Assert that a pointer is NULL */
 /* Assert that a pointer is NULL */
 #define ut_assertnull(expr) {					\
 #define ut_assertnull(expr) {					\
 	const void *_val = (expr);					\
 	const void *_val = (expr);					\

+ 1 - 1
lib/fdtdec.c

@@ -746,7 +746,7 @@ int fdtdec_parse_phandle_with_args(const void *blob, int src_node,
 			if (cells_name || cur_index == index) {
 			if (cells_name || cur_index == index) {
 				node = fdt_node_offset_by_phandle(blob,
 				node = fdt_node_offset_by_phandle(blob,
 								  phandle);
 								  phandle);
-				if (!node) {
+				if (node < 0) {
 					debug("%s: could not find phandle\n",
 					debug("%s: could not find phandle\n",
 					      fdt_get_name(blob, src_node,
 					      fdt_get_name(blob, src_node,
 							   NULL));
 							   NULL));

+ 133 - 15
test/bloblist.c

@@ -7,6 +7,7 @@
 #include <bloblist.h>
 #include <bloblist.h>
 #include <log.h>
 #include <log.h>
 #include <mapmem.h>
 #include <mapmem.h>
+#include <asm/state.h>
 #include <test/suites.h>
 #include <test/suites.h>
 #include <test/test.h>
 #include <test/test.h>
 #include <test/ut.h>
 #include <test/ut.h>
@@ -24,10 +25,12 @@ enum {
 
 
 	TEST_SIZE		= 10,
 	TEST_SIZE		= 10,
 	TEST_SIZE2		= 20,
 	TEST_SIZE2		= 20,
-	TEST_SIZE_LARGE		= 0xe0,
+	TEST_SIZE_LARGE		= 0x3e0,
 
 
 	TEST_ADDR		= CONFIG_BLOBLIST_ADDR,
 	TEST_ADDR		= CONFIG_BLOBLIST_ADDR,
-	TEST_BLOBLIST_SIZE	= 0x100,
+	TEST_BLOBLIST_SIZE	= 0x400,
+
+	ERASE_BYTE		= '\xff',
 };
 };
 
 
 static struct bloblist_hdr *clear_bloblist(void)
 static struct bloblist_hdr *clear_bloblist(void)
@@ -40,7 +43,7 @@ static struct bloblist_hdr *clear_bloblist(void)
 	 * to 0xff for testing purposes.
 	 * to 0xff for testing purposes.
 	 */
 	 */
 	hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
 	hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
-	memset(hdr, '\xff', TEST_BLOBLIST_SIZE);
+	memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
 	memset(hdr, '\0', sizeof(*hdr));
 	memset(hdr, '\0', sizeof(*hdr));
 
 
 	return hdr;
 	return hdr;
@@ -94,26 +97,27 @@ static int bloblist_test_blob(struct unit_test_state *uts)
 	hdr = clear_bloblist();
 	hdr = clear_bloblist();
 	ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
 	ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+	ut_asserteq(map_to_sysmem(hdr), TEST_ADDR);
 
 
 	/* Add a record and check that we can find it */
 	/* Add a record and check that we can find it */
-	data = bloblist_add(TEST_TAG, TEST_SIZE);
+	data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
 	rec = (void *)(hdr + 1);
 	rec = (void *)(hdr + 1);
-	ut_asserteq_ptr(rec + 1, data);
+	ut_asserteq_addr(rec + 1, data);
 	data = bloblist_find(TEST_TAG, TEST_SIZE);
 	data = bloblist_find(TEST_TAG, TEST_SIZE);
-	ut_asserteq_ptr(rec + 1, data);
+	ut_asserteq_addr(rec + 1, data);
 
 
 	/* Check the data is zeroed */
 	/* Check the data is zeroed */
 	ut_assertok(check_zero(data, TEST_SIZE));
 	ut_assertok(check_zero(data, TEST_SIZE));
 
 
 	/* Check the 'ensure' method */
 	/* Check the 'ensure' method */
-	ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
+	ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
 	ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
 	ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
 	rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
 	rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
 	ut_assertok(check_zero(data, TEST_SIZE));
 	ut_assertok(check_zero(data, TEST_SIZE));
 
 
 	/* Check for a non-existent record */
 	/* Check for a non-existent record */
-	ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
-	ut_asserteq_ptr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
+	ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
+	ut_asserteq_addr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
 	ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
 	ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
 
 
 	return 0;
 	return 0;
@@ -139,7 +143,7 @@ static int bloblist_test_blob_ensure(struct unit_test_state *uts)
 	/* Check that we get the same thing again */
 	/* Check that we get the same thing again */
 	ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data2));
 	ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data2));
 	ut_asserteq(TEST_SIZE, size);
 	ut_asserteq(TEST_SIZE, size);
-	ut_asserteq_ptr(data, data2);
+	ut_asserteq_addr(data, data2);
 
 
 	/* Check that the size remains the same */
 	/* Check that the size remains the same */
 	size = TEST_SIZE2;
 	size = TEST_SIZE2;
@@ -163,8 +167,8 @@ static int bloblist_test_bad_blob(struct unit_test_state *uts)
 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
 	data = hdr + 1;
 	data = hdr + 1;
 	data += sizeof(struct bloblist_rec);
 	data += sizeof(struct bloblist_rec);
-	ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
-	ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
+	ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
+	ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
 
 
 	return 0;
 	return 0;
 }
 }
@@ -202,10 +206,10 @@ static int bloblist_test_checksum(struct unit_test_state *uts)
 	hdr->chksum--;
 	hdr->chksum--;
 
 
 	/* Make sure the checksum changes when we add blobs */
 	/* Make sure the checksum changes when we add blobs */
-	data = bloblist_add(TEST_TAG, TEST_SIZE);
+	data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
 
 
-	data2 = bloblist_add(TEST_TAG2, TEST_SIZE2);
+	data2 = bloblist_add(TEST_TAG2, TEST_SIZE2, 0);
 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
 	ut_assertok(bloblist_finish());
 	ut_assertok(bloblist_finish());
 
 
@@ -231,9 +235,123 @@ static int bloblist_test_checksum(struct unit_test_state *uts)
 
 
 	return 0;
 	return 0;
 }
 }
-
 BLOBLIST_TEST(bloblist_test_checksum, 0);
 BLOBLIST_TEST(bloblist_test_checksum, 0);
 
 
+/* Test the 'bloblist info' command */
+static int bloblist_test_cmd_info(struct unit_test_state *uts)
+{
+	struct sandbox_state *state = state_get_current();
+	struct bloblist_hdr *hdr;
+	char *data, *data2;
+
+	hdr = clear_bloblist();
+	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+	data = bloblist_ensure(TEST_TAG, TEST_SIZE);
+	data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
+
+	console_record_reset_enable();
+	if (!state->show_test_output)
+		gd->flags |= GD_FLG_SILENT;
+	console_record_reset();
+	run_command("bloblist info", 0);
+	ut_assert_nextline("base:     %lx", (ulong)map_to_sysmem(hdr));
+	ut_assert_nextline("size:     400    1 KiB");
+	ut_assert_nextline("alloced:  70     112 Bytes");
+	ut_assert_nextline("free:     390    912 Bytes");
+	ut_assert_console_end();
+	gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
+
+	return 0;
+}
+BLOBLIST_TEST(bloblist_test_cmd_info, 0);
+
+/* Test the 'bloblist list' command */
+static int bloblist_test_cmd_list(struct unit_test_state *uts)
+{
+	struct sandbox_state *state = state_get_current();
+	struct bloblist_hdr *hdr;
+	char *data, *data2;
+
+	hdr = clear_bloblist();
+	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+	data = bloblist_ensure(TEST_TAG, TEST_SIZE);
+	data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
+
+	console_record_reset_enable();
+	if (!state->show_test_output)
+		gd->flags |= GD_FLG_SILENT;
+	console_record_reset();
+	run_command("bloblist list", 0);
+	ut_assert_nextline("Address       Size  Tag Name");
+	ut_assert_nextline("%08lx  %8x    1 EC host event",
+			   (ulong)map_to_sysmem(data), TEST_SIZE);
+	ut_assert_nextline("%08lx  %8x    2 SPL hand-off",
+			   (ulong)map_to_sysmem(data2), TEST_SIZE2);
+	ut_assert_console_end();
+	gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
+
+	return 0;
+}
+BLOBLIST_TEST(bloblist_test_cmd_list, 0);
+
+/* Test alignment of bloblist blobs */
+static int bloblist_test_align(struct unit_test_state *uts)
+{
+	struct bloblist_hdr *hdr;
+	ulong addr;
+	char *data;
+	int i;
+
+	/* At the start there should be no records */
+	hdr = clear_bloblist();
+	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+	ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
+
+	/* Check the default alignment */
+	for (i = 0; i < 3; i++) {
+		int size = i * 3;
+		ulong addr;
+		char *data;
+		int j;
+
+		data = bloblist_add(i, size, 0);
+		ut_assertnonnull(data);
+		addr = map_to_sysmem(data);
+		ut_asserteq(0, addr & (BLOBLIST_ALIGN - 1));
+
+		/* Only the bytes in the blob data should be zeroed */
+		for (j = 0; j < size; j++)
+			ut_asserteq(0, data[j]);
+		for (; j < BLOBLIST_ALIGN; j++)
+			ut_asserteq(ERASE_BYTE, data[j]);
+	}
+
+	/* Check larger alignment */
+	for (i = 0; i < 3; i++) {
+		int align = 32 << i;
+
+		data = bloblist_add(3 + i, i * 4, align);
+		ut_assertnonnull(data);
+		addr = map_to_sysmem(data);
+		ut_asserteq(0, addr & (align - 1));
+	}
+
+	/* Check alignment with an bloblist starting on a smaller alignment */
+	hdr = map_sysmem(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE);
+	memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
+	memset(hdr, '\0', sizeof(*hdr));
+	ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE,
+				 0));
+
+	data = bloblist_add(1, 5, BLOBLIST_ALIGN * 2);
+	ut_assertnonnull(data);
+	addr = map_to_sysmem(data);
+	ut_asserteq(0, addr & (BLOBLIST_ALIGN * 2 - 1));
+
+	return 0;
+}
+BLOBLIST_TEST(bloblist_test_align, 0);
+
 int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
 int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
 		   char *const argv[])
 		   char *const argv[])
 {
 {

+ 91 - 0
test/dm/ofnode.c

@@ -19,6 +19,22 @@ static int dm_test_ofnode_compatible(struct unit_test_state *uts)
 }
 }
 DM_TEST(dm_test_ofnode_compatible, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
 DM_TEST(dm_test_ofnode_compatible, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
 
 
+static int dm_test_ofnode_get_by_phandle(struct unit_test_state *uts)
+{
+	/* test invalid phandle */
+	ut_assert(!ofnode_valid(ofnode_get_by_phandle(0)));
+	ut_assert(!ofnode_valid(ofnode_get_by_phandle(-1)));
+
+	/* test first valid phandle */
+	ut_assert(ofnode_valid(ofnode_get_by_phandle(1)));
+
+	/* test unknown phandle */
+	ut_assert(!ofnode_valid(ofnode_get_by_phandle(0x1000000)));
+
+	return 0;
+}
+DM_TEST(dm_test_ofnode_get_by_phandle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
 static int dm_test_ofnode_by_prop_value(struct unit_test_state *uts)
 static int dm_test_ofnode_by_prop_value(struct unit_test_state *uts)
 {
 {
 	const char propname[] = "compatible";
 	const char propname[] = "compatible";
@@ -87,6 +103,81 @@ static int dm_test_ofnode_read(struct unit_test_state *uts)
 }
 }
 DM_TEST(dm_test_ofnode_read, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
 DM_TEST(dm_test_ofnode_read, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
 
 
+static int dm_test_ofnode_phandle(struct unit_test_state *uts)
+{
+	struct ofnode_phandle_args args;
+	ofnode node;
+	int ret;
+	const char prop[] = "test-gpios";
+	const char cell[] = "#gpio-cells";
+	const char prop2[] = "phandle-value";
+
+	node = ofnode_path("/a-test");
+	ut_assert(ofnode_valid(node));
+
+	/* Test ofnode_count_phandle_with_args with cell name */
+	ret = ofnode_count_phandle_with_args(node, "missing", cell, 0);
+	ut_asserteq(-ENOENT, ret);
+	ret = ofnode_count_phandle_with_args(node, prop, "#invalid", 0);
+	ut_asserteq(-EINVAL, ret);
+	ret = ofnode_count_phandle_with_args(node, prop, cell, 0);
+	ut_asserteq(5, ret);
+
+	/* Test ofnode_parse_phandle_with_args with cell name */
+	ret = ofnode_parse_phandle_with_args(node, "missing", cell, 0, 0,
+					     &args);
+	ut_asserteq(-ENOENT, ret);
+	ret = ofnode_parse_phandle_with_args(node, prop, "#invalid", 0, 0,
+					     &args);
+	ut_asserteq(-EINVAL, ret);
+	ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 0, &args);
+	ut_assertok(ret);
+	ut_asserteq(1, args.args_count);
+	ut_asserteq(1, args.args[0]);
+	ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 1, &args);
+	ut_assertok(ret);
+	ut_asserteq(1, args.args_count);
+	ut_asserteq(4, args.args[0]);
+	ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 2, &args);
+	ut_assertok(ret);
+	ut_asserteq(5, args.args_count);
+	ut_asserteq(5, args.args[0]);
+	ut_asserteq(1, args.args[4]);
+	ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 3, &args);
+	ut_asserteq(-ENOENT, ret);
+	ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 4, &args);
+	ut_assertok(ret);
+	ut_asserteq(1, args.args_count);
+	ut_asserteq(12, args.args[0]);
+	ret = ofnode_parse_phandle_with_args(node, prop, cell, 0, 5, &args);
+	ut_asserteq(-ENOENT, ret);
+
+	/* Test ofnode_count_phandle_with_args with cell count */
+	ret = ofnode_count_phandle_with_args(node, "missing", NULL, 2);
+	ut_asserteq(-ENOENT, ret);
+	ret = ofnode_count_phandle_with_args(node, prop2, NULL, 1);
+	ut_asserteq(3, ret);
+
+	/* Test ofnode_parse_phandle_with_args with cell count */
+	ret = ofnode_parse_phandle_with_args(node, prop2, NULL, 1, 0, &args);
+	ut_assertok(ret);
+	ut_asserteq(1, ofnode_valid(args.node));
+	ut_asserteq(1, args.args_count);
+	ut_asserteq(10, args.args[0]);
+	ret = ofnode_parse_phandle_with_args(node, prop2, NULL, 1, 1, &args);
+	ut_asserteq(-EINVAL, ret);
+	ret = ofnode_parse_phandle_with_args(node, prop2, NULL, 1, 2, &args);
+	ut_assertok(ret);
+	ut_asserteq(1, ofnode_valid(args.node));
+	ut_asserteq(1, args.args_count);
+	ut_asserteq(30, args.args[0]);
+	ret = ofnode_parse_phandle_with_args(node, prop2, NULL, 1, 3, &args);
+	ut_asserteq(-ENOENT, ret);
+
+	return 0;
+}
+DM_TEST(dm_test_ofnode_phandle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
 static int dm_test_ofnode_read_chosen(struct unit_test_state *uts)
 static int dm_test_ofnode_read_chosen(struct unit_test_state *uts)
 {
 {
 	const char *str;
 	const char *str;

+ 65 - 0
test/dm/test-fdt.c

@@ -968,6 +968,71 @@ static int dm_test_read_int_index(struct unit_test_state *uts)
 }
 }
 DM_TEST(dm_test_read_int_index, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
 DM_TEST(dm_test_read_int_index, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
 
 
+static int dm_test_read_phandle(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	struct ofnode_phandle_args args;
+	int ret;
+	const char prop[] = "test-gpios";
+	const char cell[] = "#gpio-cells";
+	const char prop2[] = "phandle-value";
+
+	ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev));
+	ut_asserteq_str("a-test", dev->name);
+
+	/* Test dev_count_phandle_with_args with cell name */
+	ret = dev_count_phandle_with_args(dev, "missing", cell, 0);
+	ut_asserteq(-ENOENT, ret);
+	ret = dev_count_phandle_with_args(dev, prop, "#invalid", 0);
+	ut_asserteq(-EINVAL, ret);
+	ut_asserteq(5, dev_count_phandle_with_args(dev, prop, cell, 0));
+
+	/* Test dev_read_phandle_with_args with cell name */
+	ret = dev_read_phandle_with_args(dev, "missing", cell, 0, 0, &args);
+	ut_asserteq(-ENOENT, ret);
+	ret = dev_read_phandle_with_args(dev, prop, "#invalid", 0, 0, &args);
+	ut_asserteq(-EINVAL, ret);
+	ut_assertok(dev_read_phandle_with_args(dev, prop, cell, 0, 0, &args));
+	ut_asserteq(1, args.args_count);
+	ut_asserteq(1, args.args[0]);
+	ut_assertok(dev_read_phandle_with_args(dev, prop, cell, 0, 1, &args));
+	ut_asserteq(1, args.args_count);
+	ut_asserteq(4, args.args[0]);
+	ut_assertok(dev_read_phandle_with_args(dev, prop, cell, 0, 2, &args));
+	ut_asserteq(5, args.args_count);
+	ut_asserteq(5, args.args[0]);
+	ut_asserteq(1, args.args[4]);
+	ret = dev_read_phandle_with_args(dev, prop, cell, 0, 3, &args);
+	ut_asserteq(-ENOENT, ret);
+	ut_assertok(dev_read_phandle_with_args(dev, prop, cell, 0, 4, &args));
+	ut_asserteq(1, args.args_count);
+	ut_asserteq(12, args.args[0]);
+	ret = dev_read_phandle_with_args(dev, prop, cell, 0, 5, &args);
+	ut_asserteq(-ENOENT, ret);
+
+	/* Test dev_count_phandle_with_args with cell count */
+	ret = dev_count_phandle_with_args(dev, "missing", NULL, 2);
+	ut_asserteq(-ENOENT, ret);
+	ut_asserteq(3, dev_count_phandle_with_args(dev, prop2, NULL, 1));
+
+	/* Test dev_read_phandle_with_args with cell count */
+	ut_assertok(dev_read_phandle_with_args(dev, prop2, NULL, 1, 0, &args));
+	ut_asserteq(1, ofnode_valid(args.node));
+	ut_asserteq(1, args.args_count);
+	ut_asserteq(10, args.args[0]);
+	ret = dev_read_phandle_with_args(dev, prop2, NULL, 1, 1, &args);
+	ut_asserteq(-EINVAL, ret);
+	ut_assertok(dev_read_phandle_with_args(dev, prop2, NULL, 1, 2, &args));
+	ut_asserteq(1, ofnode_valid(args.node));
+	ut_asserteq(1, args.args_count);
+	ut_asserteq(30, args.args[0]);
+	ret = dev_read_phandle_with_args(dev, prop2, NULL, 1, 3, &args);
+	ut_asserteq(-ENOENT, ret);
+
+	return 0;
+}
+DM_TEST(dm_test_read_phandle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
 /* Test iteration through devices by drvdata */
 /* Test iteration through devices by drvdata */
 static int dm_test_uclass_drvdata(struct unit_test_state *uts)
 static int dm_test_uclass_drvdata(struct unit_test_state *uts)
 {
 {