Re: [RESEND PATCH v2 5/5] net: dwc_eth_qos: Add glue driver for Intel MAC

2024-06-29 Thread Marek Vasut

On 6/24/24 10:34 AM, Philip Oberfichtner wrote:


+++ b/drivers/net/dwc_eth_qos_intel.c
@@ -0,0 +1,446 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 DENX Software Engineering GmbH
+ * Philip Oberfichtner 
+ *
+ * Based on linux v6.1.38, especially drivers/net/ethernet/stmicro/stmmac


It is 2024 now , also you might want to update this to match Linux 6.6.y 
which is the current LTS .



+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "dwc_eth_qos.h"
+#include "dwc_eth_qos_intel.h"
+
+static struct pci_device_id intel_pci_ids[] = {
+   { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EHL_RGMII1G) },
+   { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EHL_SGMII1) },
+   { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EHL_SGMII2G5) },
+   { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EHL_PSE0_RGMII1G) 
},
+   { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EHL_PSE0_SGMII1G) 
},
+   { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 
PCI_DEVICE_ID_INTEL_EHL_PSE0_SGMII2G5) },
+   { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EHL_PSE1_RGMII1G) 
},
+   { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EHL_PSE1_SGMII1G) 
},
+   { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 
PCI_DEVICE_ID_INTEL_EHL_PSE1_SGMII2G5) },
+   {}
+};
+
+static int __pci_config(struct udevice *dev)
+{
+   u32 val;
+
+   /* Try to enable I/O accesses and bus-mastering */
+   dm_pci_read_config32(dev, PCI_COMMAND, &val);
+   val |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+   dm_pci_write_config32(dev, PCI_COMMAND, val);
+
+   /* Make sure it worked */
+   dm_pci_read_config32(dev, PCI_COMMAND, &val);
+   if (!(val & PCI_COMMAND_MEMORY)) {
+   pr_err("%s: Can't enable I/O memory\n", __func__);


dev_err() please


+   return -ENOSPC;
+   }
+
+   if (!(val & PCI_COMMAND_MASTER)) {
+   pr_err("%s: Can't enable bus-mastering\n", __func__);


dev_err() , fix globally.


+   return -EPERM;
+   }
+
+   return 0;
+}
+
+static void __limit_fifo_size(struct udevice *dev)


Please drop the leading __ from function names .


+{
+   /*
+* As described in Intel Erratum EHL22, Document Number: 636674-2.1,
+* the PSE GbE Controllers advertise a wrong RX and TX fifo size.
+* Software should limit this value to 64KB.
+*/
+   struct eqos_priv *eqos = dev_get_priv(dev);
+
+   eqos->tx_fifo_sz = 0x8000;
+   eqos->rx_fifo_sz = 0x8000;
+}
+
+static int __serdes_status_poll(struct udevice *dev,
+   unsigned char phyaddr, unsigned char phyreg,
+   unsigned short mask, unsigned short val)
+{
+   struct eqos_priv *eqos = dev_get_priv(dev);
+   unsigned int retries = 10;
+   unsigned short val_rd;
+
+   do {
+   miiphy_read(eqos->mii->name, phyaddr, phyreg, &val_rd);
+   if ((val_rd & mask) == (val & mask))
+   return 0;
+   udelay(POLL_DELAY_US);
+   } while (--retries);


Is this some implementation of phy_read_mmd_poll_timeout() ?


+   return -ETIMEDOUT;
+}
+
+ /* Returns -ve if MAC is unknown and 0 on success */
+static int __mac_check_pse(const struct udevice *dev, bool *is_pse)
+{
+   struct pci_child_plat *plat = dev_get_parent_plat(dev);
+
+   if (!plat || plat->vendor != PCI_VENDOR_ID_INTEL)
+   return -ENXIO;
+
+   switch (plat->device) {
+   case PCI_DEVICE_ID_INTEL_EHL_PSE0_RGMII1G:
+   case PCI_DEVICE_ID_INTEL_EHL_PSE1_RGMII1G:
+   case PCI_DEVICE_ID_INTEL_EHL_PSE0_SGMII1G:
+   case PCI_DEVICE_ID_INTEL_EHL_PSE1_SGMII1G:
+   case PCI_DEVICE_ID_INTEL_EHL_PSE0_SGMII2G5:
+   case PCI_DEVICE_ID_INTEL_EHL_PSE1_SGMII2G5:
+   *is_pse = 1;
+   return 0;
+
+   case PCI_DEVICE_ID_INTEL_EHL_RGMII1G:
+   case PCI_DEVICE_ID_INTEL_EHL_SGMII1:
+   case PCI_DEVICE_ID_INTEL_EHL_SGMII2G5:
+   *is_pse = 0;
+   return 0;
+   };
+
+   return -ENXIO;
+}
+
+/* Check if we're in 2G5 mode */
+static bool __serdes_link_mode_2500(struct udevice *dev)
+{
+   const unsigned char phyad = INTEL_MGBE_ADHOC_ADDR;
+   struct eqos_priv *eqos = dev_get_priv(dev);
+   unsigned short data;
+
+   miiphy_read(eqos->mii->name, phyad, SERDES_GCR, &data);
+   if (((data & SERDES_LINK_MODE_MASK) >> SERDES_LINK_MODE_SHIFT) ==
+   SERDES_LINK_MODE_2G5)


Use FIELD_PREP() and FIELD_GET() to simplify this bitfield extraction.


+   return true;
+
+   return false;
+}
+
+static int __serdes_powerup(struct udevice *dev)
+{
+   /* Based on linux/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c */
+
+   const unsigned char phyad = INTEL_MGBE_ADHOC_ADDR;
+   struct eqos_priv *eqos = dev_get_priv(dev);
+   unsigned short data;
+   int ret;
+

Re: [RESEND PATCH v2 3/5] net: dwc_eth_qos: Adapt probe() for PCI devices

2024-06-29 Thread Marek Vasut

On 6/24/24 10:34 AM, Philip Oberfichtner wrote:

PCI devices do not necessarily use a device tree. In that case, the
driver currently fails to find eqos->config and eqos->regs.

This commit factors out the respective functionality. Device tree usage
remains default, but board specific implementations will be possible as
well.

Signed-off-by: Philip Oberfichtner 
---
  drivers/net/dwc_eth_qos.c  | 28 +---
  drivers/net/dwc_eth_qos.h  |  3 +++
  drivers/net/dwc_eth_qos_imx.c  |  1 +
  drivers/net/dwc_eth_qos_qcom.c |  1 +
  drivers/net/dwc_eth_qos_rockchip.c |  1 +
  drivers/net/dwc_eth_qos_starfive.c |  1 +
  drivers/net/dwc_eth_qos_stm32.c|  1 +
  7 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index b87634f1f5..34e29301cc 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -1376,6 +1376,21 @@ static int eqos_remove_resources_tegra186(struct udevice 
*dev)
return 0;
  }
  
+/*

+ * Get driver data based on the device tree. Boards not using a device tree can
+ * overwrite this function.
+ */
+__weak void *eqos_get_driver_data(struct udevice *dev)
+{
+   return (void *)dev_get_driver_data(dev);
+}
+
+/* Function to get base address, useable for all boards having a device tree. 
*/
+fdt_addr_t eqos_get_base_addr_dt(struct udevice *dev)
+{
+   return dev_read_addr(dev);
+}
+
  static int eqos_probe(struct udevice *dev)
  {
struct eqos_priv *eqos = dev_get_priv(dev);
@@ -1384,13 +1399,19 @@ static int eqos_probe(struct udevice *dev)
debug("%s(dev=%p):\n", __func__, dev);
  
  	eqos->dev = dev;

-   eqos->config = (void *)dev_get_driver_data(dev);
  
-	eqos->regs = dev_read_addr(dev);

+   eqos->config = eqos_get_driver_data(dev);
+   if (!eqos->config) {
+   pr_err("Failed to get driver data.\n");
+   return -ENODEV;
+   }
+
+   eqos->regs = eqos->config->ops->eqos_get_base_addr(dev);
if (eqos->regs == FDT_ADDR_T_NONE) {
-   pr_err("dev_read_addr() failed\n");
+   pr_err("Failed to get device address.\n");
return -ENODEV;
}
+
eqos->mac_regs = (void *)(eqos->regs + EQOS_MAC_REGS_BASE);
eqos->mtl_regs = (void *)(eqos->regs + EQOS_MTL_REGS_BASE);
eqos->dma_regs = (void *)(eqos->regs + EQOS_DMA_REGS_BASE);


Could you factor out the entirety of:

 eqos->regs = dev_read_addr(dev);
 if (eqos->regs == FDT_ADDR_T_NONE) {
 pr_err("dev_read_addr() failed\n");
 return -ENODEV;
 }
 eqos->mac_regs = (void *)(eqos->regs + EQOS_MAC_REGS_BASE);
 eqos->mtl_regs = (void *)(eqos->regs + EQOS_MTL_REGS_BASE);
 eqos->dma_regs = (void *)(eqos->regs + EQOS_DMA_REGS_BASE);
 eqos->tegra186_regs = (void *)(eqos->regs + 
EQOS_TEGRA186_REGS_BASE);


into some common function, like eqos_get_base_addr_dt() , and call it 
from .eqos_probe_resources callback instead ? That way you wouldn't have 
to add new callback specifically for register address.


Re: [RESEND PATCH v2 2/5] net: dwc_eth_qos: Fix header to be self-contained

2024-06-29 Thread Marek Vasut

On 6/24/24 10:34 AM, Philip Oberfichtner wrote:

Before this commit, usage of this header relied on a specific include
order. Fix it by including all dependencies.

Signed-off-by: Philip Oberfichtner 


Reviewed-by: Marek Vasut 


Re: [PATCH v2] ARM: imx: verdin-imx8mm: Set CAN oscillator frequency based on model

2024-06-29 Thread Marek Vasut

On 5/23/24 5:03 PM, Francesco Dolcini wrote:

On Wed, May 22, 2024 at 03:23:51PM +0200, Marek Vasut wrote:

On 5/22/24 8:39 AM, Francesco Dolcini wrote:

diff --git a/board/toradex/verdin-imx8mm/verdin-imx8mm.c 
b/board/toradex/verdin-imx8mm/verdin-imx8mm.c
index 55c02653da6..ef632d95f0a 100644
--- a/board/toradex/verdin-imx8mm/verdin-imx8mm.c
+++ b/board/toradex/verdin-imx8mm/verdin-imx8mm.c
@@ -125,6 +125,36 @@ int board_phys_sdram_size(phys_size_t *size)
   #if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
   int ft_board_setup(void *blob, struct bd_info *bd)
   {
+   const char *canoscpath = "/oscillator";
+   int freq = 4000;/* 40 MHz is used on most variants */
+   int canoscoff, ret;
+
+   canoscoff = fdt_path_offset(blob, canoscpath);
+   if (canoscoff < 0)   /* No CAN oscillator found. */
+   goto exit;
+
+   /*
+* The actual "prodid" (PID4 in Toradex naming) that have the CAN
+* functionality are 0055 and 0059. Special case 20 MHz variant
+* here:
+* - 0055, V1.1A, V1.1B, V1.1C and V1.1D, use a 20MHz oscillator
+* - 0059, V1.1A and V1.1B, use a 20MHz oscillator
+*/


Any reason why you ignored my suggestion here? The variants you list
here are the only one with a 20MHz oscillator, and this is correct.

What is not correct is that 0055/0059 are the only variant with CAN
functionality. We have other "prodid" with CAN functionality.

With that said, the code is correct, thanks. I appreciate you taking care
of this.


So ... what should I change for V3 ?

Maybe just create me a diff I can squash into the patch before resend ? (I
think I am a bit confused, I thought I addressed all the V1 feedback)


Sorry for the confusion, here the diff.
With that please add


Thank you. I missed this mail and now I found it. Fixed in V3.


Re: [PATCH 1/2] usb: dwc2: Extract USB DWC2 register definitions

2024-06-29 Thread Marek Vasut

On 6/27/24 1:33 PM, Kongyang Liu wrote:

Marek Vasut  于2024年6月23日周日 07:49写道:


On 5/22/24 4:22 PM, Kongyang Liu wrote:

Hi,

sorry for the late reply.


diff --git a/drivers/usb/common/dwc2_core.c b/drivers/usb/common/dwc2_core.c
new file mode 100644
index 00..2fa11fd59d
--- /dev/null
+++ b/drivers/usb/common/dwc2_core.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2024, Kongyang Liu 
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "dwc2_core.h"
+
+void dwc2_flush_tx_fifo(struct dwc2_core_regs *regs, const int num)
+{
+ int ret;
+
+ log_debug("Flush Tx FIFO %d\n", num);
+
+ /* Wait for AHB master IDLE state */
+ ret = wait_for_bit_le32(®s->global_regs.grstctl, GRSTCTL_AHBIDLE, 
true, 1000, false);


Just a quick design point, would it be possible to split this patch into
two, one which adds this .global_regs and changes the code accordingly,
and another which does the code refactoring/move ? That would make it
easier to review.


This patch only extracts the common parts of the host mode and gadget
mode, without any code refactoring. Could you please describe more clearly
how the patch should be split?


Sure, sorry for being unclear. There seems to be multiple types of 
changes that are combined in this patch:


1) Structure reorganization:
-   writel(DIEPMSK_INIT, ®->diepmsk);
+   writel(DIEPMSK_INIT, ®->device_regs.diepmsk);

2) Structure rename:
-   reg = (struct dwc2_usbotg_reg *)pdata->regs_otg;
+   reg = (struct dwc2_core_regs *)pdata->regs_otg;

3) Conversion from (1 << n) to BIT(n)
4) Macro rename:
5) Moving code around between files:
#define DWC2_HWCFG4_IDDIG_FILT_EN   (1 << 20)
#define GHWCFG4_IDDIG_FILT_EN   BIT(20)

It would be good to have those as separate patches (one type of clean up 
change per patch), otherwise it is really hard to review such a combined 
patch.


Thanks !


Re: [PATCH] spl: fit: List DTOs applied by SPL in U-Boot control DT

2024-06-29 Thread Marek Vasut

On 6/28/24 10:27 AM, Quentin Schulz wrote:

Hi,


Shouldn't this rather be in /config node?


This is what I had there originally, but then I realized that some DTs 
might not have the /config node in them (or am I mistaken?), so I 
moved the new properties into the root node, which surely exists.


It also keeps the code simpler, as it doesn't have to fiddle with 
creation of the /config node if it doesn't exist.




I don't think we should pollute the root node with this. If we want to 
be able to expose this in a proper binding to the upstream DT binding 
repo, I'm not sure this is going to fly :/


The other option is to add more code into SPL, that's not great.

I can check if /config node exists, and if so, add it there, otherwise 
do nothing. That should be some sort of compromise between bloat and 
config node. What do you think ?


[...]

I am wondering if we cannot simply have a string array with overlays 
applied left-to-right or right-to-left instead? Or u-boot,fdt-dto-N = 
"imx8mp-dhcom-pdk3-overlay-rev100";


We can, but that is much harder to test for presence of specific DTO 
on U-Boot command line. It is easy to test for presence of boolean or 
integer DT property using 'fdt' command.




Not sure dt-bindings people would love to hear that we adapt the fdt to 
be easier to work with from the U-Boot CLI :)


In any case, another few thoughts that popped up overnight:
1- do we want to have this for SPL DTB modified by TPL? If so, I'm sure 
we want it different from the one passed from SPL to U-Boot proper IFF 
we start from a clean sheet (new DTB) and/or add the DTBO we applied on 
top the DTBOs already applied by the TPL to the SPL DTB before passing 
it to proper


As far as I can tell, TPL currently does not support loading fitImages 
and applying DTOs from them. When this is available, I suspect the 
prefix of the newly added property would change from 
u-boot,spl-applied-dto- to u-boot,tpl-applied-dto- and that would be it.



2- Add info about which DTBOs were applied to the kernel DTB?


SPL DTOs or DTOs applied from kernel fitImage ? Or a merging of those ?


Re: [PATCH v2] spl: fit: List DTOs applied by SPL in U-Boot control DT

2024-06-29 Thread Marek Vasut

On 6/28/24 9:32 AM, Simon Glass wrote:

Hi Marek,


Hi,


---
  common/spl/spl_fit.c| 29 +++--
  doc/device-tree-bindings/config.txt | 11 +++
  2 files changed, 38 insertions(+), 2 deletions(-)


Once this is figured out, can you extend test/image/spl_load_os.c to
test this code?


It seems there is nothing which would do even basic tests for SPL 
fitImage DT handling in that test? Or am I reading the current test wrong ?



diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 988125be008..0a6b5ea8212 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -363,6 +363,7 @@ static int spl_fit_append_fdt(struct spl_image_info 
*spl_image,
  {
 struct spl_image_info image_info;
 int node, ret = 0, index = 0;
+   char dtoname[256];

 /*
  * Use the address following the image as target address for the
@@ -448,9 +449,13 @@ static int spl_fit_append_fdt(struct spl_image_info 
*spl_image,
 if (ret < 0)
 break;

-   /* Make room in FDT for changes from the overlay */
+   /*
+* Make room in FDT for changes from the overlay,
+* the overlay name and the trailing NUL byte in
+* that name.
+*/
 ret = fdt_increase_size(spl_image->fdt_addr,
-   image_info.size);
+   image_info.size + strlen(str) + 
1);


Oh and I missed the room for the property, sorry. It needs something like this:

ALIGN(strlen(str) + 1, 4) + 12 + 4

the first bit is the string-table size increase

12 is sizeof(struct fdt_property)
4 is the u32 size

Alos, is there any way to check that there is actually enough space to
increase the size?


fdt_increase_size() would fail if there isn't enough space, so that 
should cover the check.



diff --git a/doc/device-tree-bindings/config.txt 
b/doc/device-tree-bindings/config.txt
index f50c68bbdc3..7aa6d9a72c6 100644
--- a/doc/device-tree-bindings/config.txt
+++ b/doc/device-tree-bindings/config.txt
@@ -95,6 +95,17 @@ rootdisk-offset (int)
  silent-console (int)
 If present and non-zero, the console is silenced by default on boot.

+u-boot,spl-applied-dto-* (int)
+   Emitted by SPL into U-Boot control DT root node in case a DTO from
+   fitImage was applied on top of U-Boot control DT by the SPL fitImage
+   loader. The single integer cell indicates in which order was the DTO
+   applied by the SPL and matches the index of the DTO in the fitImage.
+   DTOs in fitImage may be skipped using board_spl_fit_append_fdt_skip(),
+   therefore the integers might not be monotonically incrementing, there
+   may be gaps. This property can be used to determine which DTOs were
+   applied by the SPL from running U-Boot by inspecting the U-Boot
+   control DT.


Should we send a binding with this? I wonder if it would be better to
make the filename a property value rather than including it in the
property name/string table? That way you would not need the
integers...the ordering would be enough.

E.g.

u-boot,spl-applied-dtos = "fdt-dto-imx8mp-dhcom-som-overlay-eth2xfast",
   "fdt-dto-imx8mp-dhcom-pdk-overlay-eth2xfast";

But that might be more annoying to construct as you would probably
need fdt_setprop_placeholder()


It is easier to test for a presence of property from U-Boot shell, also 
the property is integer where the integer indicates the index of the DTO 
when it was applied.


[PATCH v2 1/1] efi_loader: print device-tree in dtbdump.efi

2024-06-29 Thread Heinrich Schuchardt
The dtbdump.efi binary can be used for testing the EFI_DT_FIXUP_PROTOCOL.
It provides a command to load a file and have it fixed up and a
command to save the resulting file.

Add a command 'dump' for displaying the device-tree.

Signed-off-by: Heinrich Schuchardt 
---
v2:
print leading '/dts-v1/;'
print memory reservation block
allow space in string property value to match dtc logic
correct formatting of byte strings
---
 lib/efi_loader/dtbdump.c | 261 +++
 1 file changed, 261 insertions(+)

diff --git a/lib/efi_loader/dtbdump.c b/lib/efi_loader/dtbdump.c
index 5f39cf22da7..116593d9e25 100644
--- a/lib/efi_loader/dtbdump.c
+++ b/lib/efi_loader/dtbdump.c
@@ -40,6 +40,53 @@ static void print(u16 *string)
cout->output_string(cout, string);
 }
 
+/**
+ * print_char() - print character
+ *
+ * 0x00 is replaced by '", "'.
+ *
+ * @c: - character
+ */
+static void print_char(unsigned char c)
+{
+   u16 out[2] = u"?";
+
+   if (!c) {
+   print(u"\", \"");
+   return;
+   }
+
+   if (c > 0x1f && c < 0x80)
+   out[0] = c;
+
+   print(out);
+}
+
+/**
+ * print_hex_digit() - print hexadecimal digit
+ *
+ * @digit: digit to print
+ */
+static void print_hex_digit(unsigned char digit)
+{
+   if (digit < 10)
+   digit += '0';
+   else
+   digit += 'a' - 10;
+   print_char(digit);
+}
+
+/**
+ * printx() - print hexadecimal byte
+ *
+ * @val:   value to print
+ */
+static void printx(unsigned char val)
+{
+   print_hex_digit(val >> 4);
+   print_hex_digit(val & 0xf);
+}
+
 /**
  * error() - print error string
  *
@@ -227,6 +274,7 @@ bool starts_with(u16 *string, u16 *keyword)
  */
 void do_help(void)
 {
+   error(u"dump   - print device-tree\r\n");
error(u"load  - load device-tree from file\r\n");
error(u"save  - save device-tree to file\r\n");
error(u"exit   - exit the shell\r\n");
@@ -489,6 +537,217 @@ efi_status_t do_save(u16 *filename)
return ret;
 }
 
+/**
+ * indent() - print a number of tabstops
+ *
+ * @level: indentation level
+ */
+static void indent(u32 level)
+{
+   for (; level; --level)
+   print(u"\t");
+}
+
+/**
+ * is_string_value() - determine if property is a string
+ *
+ * If a property is a string, an x-string, or a u32 cannot be deducted
+ * from the device-tree. Therefore a heuristic is used.
+ *
+ * @str:   pointer to device-tree property
+ * @len:   length of the device-tree property
+ * Return: 1 for string, 0 otherwise
+ */
+static int is_string_value(const unsigned char *str, u32 len)
+{
+   int nonzero_flag = 0;
+
+   /* Zero length or not ending with 0x00 */
+   if (!len || str[len - 1])
+   return 0;
+
+   for (u32 i = 0; i < len; ++i) {
+   if (!str[i]) {
+   /* Zero length string or two consecutive 0x00 */
+   if (!nonzero_flag)
+   return 0;
+
+   nonzero_flag = 0;
+
+   continue;
+   }
+   /* Non-printable */
+   if (str[i] < 0x20 || str[i] >= 0x80)
+   return 0;
+
+   nonzero_flag = 1;
+   }
+
+   return 1;
+}
+
+/**
+ * print_property() - print device-tree property
+ *
+ * If a property is a string, an x-string, or a u32 cannot be deducted
+ * from the device-tree. Therefore a heuristic is used.
+ *
+ * @str:   property value
+ * @len:   length of property value
+ */
+static void print_property(const unsigned char *val, u32 len)
+{
+   if (is_string_value(val, len)) {
+   /* string */
+   print(u"\"");
+   for (int i = 0; i < len - 1; ++i)
+   print_char(val[i]);
+   print(u"\"");
+   } else if (len & 0x3) {
+   /* byte string */
+   print(u"[");
+   for (int i = 0; i < len; ++i) {
+   if (i)
+   print(u" ");
+   printx(val[i]);
+   }
+   print(u"]\"");
+   } else {
+   /* cell list */
+   print(u"<");
+   for (u32 i = 0; i < len; ++i) {
+   if ((i & 0x3) == 0) {
+   if (i > 0)
+   print(u" ");
+   print(u"0x");
+   }
+   printx(val[i]);
+   }
+   print(u">");
+   }
+}
+
+/**
+ * print_mem_res_block() - print memory reservation block
+ *
+ * @rsvblk:memory reservation block
+ */
+static void print_mem_res_block(const struct fdt_reserve_entry *rsvblk)
+{
+   for (; rsvblk->address || rsvblk->size; ++rsvblk) {
+   const unsigned char *val;
+
+   print(u"/memr