Re: [PATCH v1] board: mpfs_icicle: implement board_fdt_blob_setup()

2024-06-27 Thread Ilias Apalodimas
Hi Conor,


On Thu, 27 Jun 2024 at 23:27, Conor Dooley  wrote:
>
> On Thu, Jun 27, 2024 at 11:50:33AM +0100, Simon Glass wrote:
> > On Thu, 27 Jun 2024 at 10:38, Conor Dooley  
> > wrote:
> > > On Thu, Jun 27, 2024 at 09:36:49AM +0100, Simon Glass wrote:
> > > > On Tue, 25 Jun 2024 at 15:34, Tom Rini  wrote:
> > > > > On Tue, Jun 25, 2024 at 10:08:06AM +0100, Conor Dooley wrote:
> > > > > > The firmware on the Icicle is capable of providing a devicetree in 
> > > > > > a1 to
> > > > > > U-Boot, but until now the devicetree has been packaged in a 
> > > > > > "payload" [1]
> > > > > > alongside U-Boot (or other bootloaders/RTOSes) and appended to the 
> > > > > > image.
> > > > > > The address of this appended devicetree is placed in a1 by the 
> > > > > > firmware.
> > > > > > This meant that the mechanism used by OF_SEPARATE to locate the
> > > > > > devicetree at the end of the image would pick up the one provided 
> > > > > > by the
> > > > > > firmware when u-boot-nodtb.bin was in the payload and U-Boot's 
> > > > > > devicetree
> > > > > > when u-boot.bin was.
> > > > > >
> > > > > > The firmware is now going to be capable of providing a minimal 
> > > > > > devicetree
> > > > > > (quite cut down due to severe space constraints), but this 
> > > > > > devicetree is
> > > > > > linked into the firmware that runs out of the L2 rather than at the 
> > > > > > end
> > > > > > of the U-Boot image. Implement board_fdt_blob_setup() so that this
> > > > > > devicetree can be optionally used, and the devicetree provided in 
> > > > > > the
> > > > > > "payload" can be used without relying on "happening" to implement 
> > > > > > the
> > > > > > same strategy as OF_SEPARATE expects in combination with
> > > > > > u-boot-nodtb.bin. Unlike other RISC-V boards, the firmware provided
> > > > > > devicetree is only used when OF_BOARD is set, so that the almost
> > > > > > certainly more complete devicetree in U-Boot will be used unless
> > > > > > explicitly requested otherwise.
> > > > > >
> > > > > > Link: 
> > > > > > https://github.com/polarfire-soc/hart-software-services/blob/master/tools/hss-payload-generator/README.md
> > > > > >  [1]
> > > > > > Signed-off-by: Conor Dooley 
> > > > > > ---
> > > > > > CC: Ivan Griffin 
> > > > > > CC: Padmarao Begari 
> > > > > > CC: Cyril Jean 
> > > > > > CC: Tom Rini 
> > > > > > CC: Conor Dooley 
> > > > > > CC: u-boot@lists.denx.de
> > > > > > ---
> > > > > >  board/microchip/mpfs_icicle/mpfs_icicle.c | 19 +++
> > > > > >  1 file changed, 19 insertions(+)
> > > > > >
> > > > > > diff --git a/board/microchip/mpfs_icicle/mpfs_icicle.c 
> > > > > > b/board/microchip/mpfs_icicle/mpfs_icicle.c
> > > > > > index 4d7d843dfa3..2c1f7175f0e 100644
> > > > > > --- a/board/microchip/mpfs_icicle/mpfs_icicle.c
> > > > > > +++ b/board/microchip/mpfs_icicle/mpfs_icicle.c
> > > > > > @@ -9,6 +9,7 @@
> > > > > >  #include 
> > > > > >  #include 
> > > > > >  #include 
> > > > > > +#include 
> > > > > >
> > > > > >  DECLARE_GLOBAL_DATA_PTR;
> > > > > >
> > > > > > @@ -50,6 +51,24 @@ static void read_device_serial_number(u8 
> > > > > > *response, u8 response_size)
> > > > > >   response_buf[idx] = readb(MPFS_SYS_SERVICE_MAILBOX + 
> > > > > > idx);
> > > > > >  }
> > > > > >
> > > > > > +void *board_fdt_blob_setup(int *err)
> > > > > > +{
> > > > > > + *err = 0;
> > > > > > + /*
> > > > > > +  * The devicetree provided by the previous stage is very 
> > > > > > minimal due to
> > > > > > +  * severe space constraints. The firmware performs no fixups 
> > > > > > etc.
> > > > > > +  * U-Boot, if providing a devicetree, almost certainly has a 
> > > > > > better
> > > > > > +  * more complete one than the firmware so that provided by 
> > > > > > the firmware
> > > > > > +  * is ignored for OF_SEPARATE.
> > > > > > +  */
> > > > > > + if (IS_ENABLED(CONFIG_OF_BOARD)) {
> > > > > > + if (gd->arch.firmware_fdt_addr)
> > > > > > + return (ulong 
> > > > > > *)(uintptr_t)gd->arch.firmware_fdt_addr;
> > > > > > + }
> > > > > > +
> > > > > > + return (ulong *)_end;
> > > > > > +}
> > > > > > +
> > > > > >  int board_init(void)
> > > > > >  {
> > > > > >   /* For now nothing to do here. */
> > > > >
> > > > > I'm adding in Simon and Ilias as this touches on one of those frequent
> > > > > topics about how device trees can/should be passed along to us.
> > > >
> > > > The only thing I can think of is implementing bloblist in  the a1 (?)
> > > > firmware, then passing the DT in that.
> > >
> > > a1 is the register that is used on riscv to pass the dtb, I think the
> > > corresponding thing on arm64 is x0.
> > >
> > > Re-reading the firware handoff spec, it's difficult to see what benefits
> > > it actually provides us when we only ever have a single dtb which the
> > > firmware does not interact with/use.
> > > We are super space constrained in the firmware even carving out 4.5 KiB
> > > for 

Re: [PATCH next] doc: develop: Add a general section on gdb usage

2024-06-27 Thread Heinrich Schuchardt

On 6/26/24 12:47, Alexander Dahl wrote:

Mashed up from different sources linked below, including the now gone
Wiki and doc/README.arm-relocation file.  Tested on a custom board with
AT91 SAMA5D2 SoC and Segger J-Link Base adapter.  This is only generic
advice here, the usage is not board specific.  Some board docs have more
specific instructions on using gdb with a particular board.

Link: 
https://www.slideshare.net/slideshow/embedded-recipes-2019-introduction-to-jtag-debugging/177511981
Link: https://boundarydevices.com/debugging-using-segger-j-link-jtag/
Link: 
https://web.archive.org/web/20141224200032/http://www.denx.de/wiki/view/DULG/DebuggingUBoot
Link: 
https://web.archive.org/web/20141206064148/http://www.denx.de/wiki/view/DULG/GDBScripts1
Suggested-by: Marek Vasut 
Signed-off-by: Alexander Dahl 
---
  doc/develop/gdb.rst   | 154 ++
  doc/develop/index.rst |   1 +
  2 files changed, 155 insertions(+)
  create mode 100644 doc/develop/gdb.rst

diff --git a/doc/develop/gdb.rst b/doc/develop/gdb.rst
new file mode 100644
index 000..18d97857ce1
--- /dev/null
+++ b/doc/develop/gdb.rst
@@ -0,0 +1,154 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright (c) 2024 Alexander Dahl
+
+Debugging U-Boot with gdb
+=
+
+Using a JTAG adapter it is possible to debug a running U-Boot with gdb.
+A common way is to connect a debug adapter to the JTAG connector of your
+board, run gdbserver, connect gdb to gdbserver, and use gdb as usual.
+
+Preparing build
+---
+
+Building U-Boot with debug symbols and without optimizations is
+recommended for easier debugging::
+
+CONFIG_CC_OPTIMIZE_FOR_DEBUG=y
+
+Otherwise build, install, and run U-Boot as usual.
+
+Using OpenOCD as GDB server
+---
+
+[OpenOCD]_ is a FOSS tool supporting hardware debug probes, and
+providing a GDB interface.
+It is readily available in major Linux distributions or you can build it
+from source.
+Example for starting OpenOCD from Debian with a J-Link adapter and a
+board using an AT91 SAMA5D2 SoC:
+
+.. code-block:: console
+
+% openocd -f interface/jlink.cfg -f target/at91sama5d2.cfg -c 'adapter 
speed 4000'
+Open On-Chip Debugger 0.12.0
+Licensed under GNU GPL v2
+For bug reports, read
+http://openocd.org/doc/doxygen/bugs.html
+Info : auto-selecting first available session transport "jtag". To override use 
'transport select '.
+adapter speed: 4000 kHz
+
+Info : Listening on port  for tcl connections
+Info : Listening on port  for telnet connections
+Info : J-Link V10 compiled Jan 30 2023 11:28:07
+Info : Hardware version: 10.10
+Info : VTarget = 3.244 V
+Info : clock speed 4000 kHz
+Info : JTAG tap: at91sama5d2.cpu tap/device found: 0x5ba00477 (mfg: 0x23b 
(ARM Ltd), part: 0xba00, ver: 0x5)
+Info : at91sama5d2.cpu_a5.0: hardware has 3 breakpoints, 2 watchpoints
+Info : at91sama5d2.cpu_a5.0: MPIDR level2 0, cluster 0, core 0, mono core, 
no SMT
+Info : starting gdb server for at91sama5d2.cpu_a5.0 on 
+Info : Listening on port  for gdb connections
+
+Notice the port  the OpenOCD server is listening on for gdb
+connections.
+
+Running a gdb session
+--
+
+You need a gdb suited for your target.
+This can be gdb coming with your toolchain or *gdb-multiarch* available
+in your Linux distribution.
+
+.. code-block:: console
+
+% gdb-multiarch u-boot
+GNU gdb (Debian 13.1-3) 13.1
+Copyright (C) 2023 Free Software Foundation, Inc.
+License GPLv3+: GNU GPL version 3 or later 

+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+Type "show copying" and "show warranty" for details.
+This GDB was configured as "x86_64-linux-gnu".
+Type "show configuration" for configuration details.
+For bug reporting instructions, please see:
+.
+Find the GDB manual and other documentation resources online at:
+.
+
+For help, type "help".
+Type "apropos word" to search for commands related to "word"...
+Reading symbols from u-boot...
+(gdb)
+
+Notice in the above command-line *u-boot* is the binary file from your
+build folder, for which you might need to adapt the path when calling
+gdb.
+
+Connect to the gdb server then:


Thank you for this helpful document.

Please add:

.. code-block:: bash

gdb-multiarch u-boot -ex 'target remote localhost:'

Please, mention that the same debug port can be exposed on QEMU with
parameter '-gdb tcp::', e.g.

qemu-system-riscv64 -M virt -nographic -gdb tcp:: -kernel u-boot


+
+.. code-block:: console
+
+(gdb) target extended-remote :
+Remote debugging using :
+0x27fa9ac6 in ?? ()
+(gdb)
+
+This is fine 

Re: [PATCH 1/4] power: regulator: Trigger probe of regulators which are always-on or boot-on

2024-06-27 Thread Caleb Connolly




On 27/06/2024 11:26, Simon Glass wrote:

Hi Caleb,

On Thu, 27 Jun 2024 at 09:48, Caleb Connolly  wrote:




On 27/06/2024 10:37, Simon Glass wrote:

Hi Marek,

On Thu, 27 Jun 2024 at 00:57, Marek Vasut  wrote:


In case a regulator DT node contains regulator-always-on or regulator-boot-on
property, make sure the regulator gets correctly configured by U-Boot on start
up. Unconditionally probe such regulator drivers. This is a preparatory patch
for introduction of .regulator_post_probe() which would trigger the regulator
configuration.

Parsing of regulator-always-on and regulator-boot-on DT property has been
moved to regulator_post_bind() as the information is required early, the
rest of the DT parsing has been kept in regulator_pre_probe() to avoid
slowing down the boot process.

Signed-off-by: Marek Vasut 
---
Cc: Ben Wolsieffer 
Cc: Caleb Connolly 
Cc: Chris Morgan 
Cc: Dragan Simic 
Cc: Eugen Hristev 
Cc: Francesco Dolcini 
Cc: Heinrich Schuchardt 
Cc: Jaehoon Chung 
Cc: Jagan Teki 
Cc: Jonas Karlman 
Cc: Kever Yang 
Cc: Kostya Porotchkin 
Cc: Matteo Lisi 
Cc: Mattijs Korpershoek 
Cc: Max Krummenacher 
Cc: Neil Armstrong 
Cc: Patrice Chotard 
Cc: Patrick Delaunay 
Cc: Philipp Tomsich 
Cc: Quentin Schulz 
Cc: Sam Day 
Cc: Simon Glass 
Cc: Sumit Garg 
Cc: Svyatoslav Ryhel 
Cc: Thierry Reding 
Cc: Tom Rini 
Cc: Volodymyr Babchuk 
Cc: u-boot-amlo...@groups.io
Cc: u-boot-q...@groups.io
Cc: u-b...@dh-electronics.com
Cc: u-boot@lists.denx.de
Cc: uboot-st...@st-md-mailman.stormreply.com
---
   drivers/power/regulator/regulator-uclass.c | 22 +++---
   1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/power/regulator/regulator-uclass.c 
b/drivers/power/regulator/regulator-uclass.c
index 66fd531da04..ccc4ef33d83 100644
--- a/drivers/power/regulator/regulator-uclass.c
+++ b/drivers/power/regulator/regulator-uclass.c
@@ -433,6 +433,8 @@ static int regulator_post_bind(struct udevice *dev)
  const char *property = "regulator-name";

  uc_pdata = dev_get_uclass_plat(dev);
+   uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
+   uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");

  /* Regulator's mandatory constraint */
  uc_pdata->name = dev_read_string(dev, property);
@@ -444,13 +446,21 @@ static int regulator_post_bind(struct udevice *dev)
  return -EINVAL;
  }

-   if (regulator_name_is_unique(dev, uc_pdata->name))
-   return 0;
+   if (!regulator_name_is_unique(dev, uc_pdata->name)) {
+   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
+ property, dev->name, uc_pdata->name);
+   return -EINVAL;
+   }

-   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
- property, dev->name, uc_pdata->name);
+   /*
+* In case the regulator has regulator-always-on or
+* regulator-boot-on DT property, trigger probe() to
+* configure its default state during startup.
+*/
+   if (uc_pdata->always_on && uc_pdata->boot_on)
+   dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);

-   return -EINVAL;
+   return 0;
   }

   static int regulator_pre_probe(struct udevice *dev)
@@ -473,8 +483,6 @@ static int regulator_pre_probe(struct udevice *dev)
  -ENODATA);
  uc_pdata->max_uA = dev_read_u32_default(dev, "regulator-max-microamp",
  -ENODATA);
-   uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
-   uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
  uc_pdata->ramp_delay = dev_read_u32_default(dev, 
"regulator-ramp-delay",
  0);
  uc_pdata->force_off = dev_read_bool(dev, "regulator-force-boot-off");
--
2.43.0



This is reading a lot of DT stuff very early, which may be slow. It is
also reading from the DT in the bind() step which we sometimes have to
do, but try to avoid.


Could we set up the livetree pre-bind? What about MMU? On armv8 at least
this would have a huge impact on performance. I've done some
measurements and there is at least 1 order of magnitude difference
between parsing FDT with no caches vs parsing livetree with, it's huge.


That seems like a great idea to me, in general. The fact that SPL sets
up the MMU on armv8 makes it more practical.


Well, on qcom we don't use SPL (yet?), we did have a cyclical dependency 
since we rely on DTB for the memory layout, although I have some patches 
to do all the memory parsing in board_fdt_blob_setup() since that's 
needed for multi-dtb FIT. So I guess we could enable caches at the same 
time.


But for this series I believe we are going to have to define what
happens in what phase. We have power_init_board() which is the old way
of doing this...but perhaps we could use that as a way to start up

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

2024-06-27 Thread Marek Vasut

On 6/27/24 2:42 PM, Quentin Schulz wrote:

Hi Marek,


Hi,


On 6/27/24 1:58 AM, Marek Vasut wrote:

Insert /u-boot, =  property into the U-Boot control DT
during SPL DTO application process. This can be used by user to inspect
which DTOs got applied by the SPL and in which order from running U-Boot.

Example:
```
u-boot=> fdt addr $fdtcontroladdr && fdt list /
Working FDT set to aee9aeb0
/ {
 u-boot,fdt-dto-imx8mp-dhcom-pdk3-overlay-rev100 = <0x0005>;
 u-boot,fdt-dto-imx8mp-dhcom-som-overlay-rev100 = <0x0004>;
 u-boot,fdt-dto-imx8mp-dhcom-pdk-overlay-eth2xfast = 
<0x0003>;
 u-boot,fdt-dto-imx8mp-dhcom-som-overlay-eth2xfast = 
<0x0002>;

...
```



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.


Also, I am highly suggesting to have an additional prefix aside from 
u-boot to avoid unfortunate name clashes between DTO and existing 
properties.


OK, fixed in V2.


Or could be in its own child node of /config ?


Please see above.

In any case, can you please add or edit a file somewhere to define this 
new dt-binding.


Done in V2


Additional question, what is this index for?


To indicate in which order the DTOs were applied by the SPL. It matches 
the order in which the the DTOs are stored in the fitImage and the order 
in which SPL iterates over them. In case the SPL skips a DTO using 
board_spl_fit_append_fdt_skip(), the integer sequence might have gaps.


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.


Thanks !


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

2024-06-27 Thread Marek Vasut

On 6/27/24 10:37 AM, Simon Glass wrote:

Hi,



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


You may also need space for the string terminator (i.e. add 1 more byte).


Fixed in V2 with expanded comment, thanks.


 if (ret < 0)
 break;

@@ -464,6 +465,26 @@ static int spl_fit_append_fdt(struct spl_image_info 
*spl_image,

 debug("%s: DT overlay %s applied\n", __func__,
   fit_get_name(ctx->fit, node, NULL));
+
+   /*
+* Insert /u-boot, =  property into
+* the U-Boot control DT. This can be used by user
+* to inspect which DTOs got applied by the SPL from
+* a running U-Boot.
+*/
+   snprintf(dtoname, sizeof(dtoname), "u-boot,%s", str);
+   ret = fdt_setprop_u32(spl_image->fdt_addr, 0, dtoname,
+ index);
+   if (!ret) {


This means there was no error, right?


Yes, this should be inverted, thanks.


+   /*
+* The DTO itself was applied, do not treat the
+* insertion of /u-boot, as an error
+* so the system can possibly boot somehow.
+*/
+   debug("%s: DT overlay %s name not inserted into / 
node (%d)\n",
+ __func__,
+ fit_get_name(ctx->fit, node, NULL), ret);
+   }


log_debug()


The whole file uses debug(), so let's keep it consistent.

Thanks !


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

2024-06-27 Thread Marek Vasut
Insert /u-boot,spl-applied-dto- =  property into the
U-Boot control DT during SPL DTO application process. This can be used
by user to inspect which DTOs got applied by the SPL and in which order
from running U-Boot.

Example:
```
u-boot=> fdt addr $fdtcontroladdr && fdt list /
Working FDT set to aee9aeb0
/ {
u-boot,spl-applied-dto-fdt-dto-imx8mp-dhcom-pdk3-overlay-rev100 = 
<0x0005>;
u-boot,spl-applied-dto-fdt-dto-imx8mp-dhcom-som-overlay-rev100 = 
<0x0004>;
u-boot,spl-applied-dto-fdt-dto-imx8mp-dhcom-pdk-overlay-eth2xfast = 
<0x0003>;
u-boot,spl-applied-dto-fdt-dto-imx8mp-dhcom-som-overlay-eth2xfast = 
<0x0002>;
...
```

Signed-off-by: Marek Vasut 
---
Cc: Manoj Sai 
Cc: Sean Anderson 
Cc: Simon Glass 
Cc: Suniel Mahesh 
Cc: Tom Rini 
Cc: u-b...@dh-electronics.com
Cc: u-boot@lists.denx.de
---
V2: - Expand the DT by one more byte to cater for trailing NUL byte
- Update comment related to the expansion of DT
- Flip the !ret conditional, which was incorrect and missed
- Expand prefix to u-boot,spl-applied-dto-
- Document the binding
---
 common/spl/spl_fit.c| 29 +++--
 doc/device-tree-bindings/config.txt | 11 +++
 2 files changed, 38 insertions(+), 2 deletions(-)

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);
if (ret < 0)
break;
 
@@ -464,6 +469,26 @@ static int spl_fit_append_fdt(struct spl_image_info 
*spl_image,
 
debug("%s: DT overlay %s applied\n", __func__,
  fit_get_name(ctx->fit, node, NULL));
+
+   /*
+* Insert /u-boot, =  property into
+* the U-Boot control DT. This can be used by user
+* to inspect which DTOs got applied by the SPL from
+* a running U-Boot.
+*/
+   snprintf(dtoname, sizeof(dtoname), 
"u-boot,spl-applied-dto-%s", str);
+   ret = fdt_setprop_u32(spl_image->fdt_addr, 0, dtoname,
+ index);
+   if (ret) {
+   /*
+* The DTO itself was applied, do not treat the
+* insertion of /u-boot, as an error
+* so the system can possibly boot somehow.
+*/
+   debug("%s: DT overlay %s name not inserted into 
/ node (%d)\n",
+ __func__,
+ fit_get_name(ctx->fit, node, NULL), ret);
+   }
}
free(tmpbuffer);
if (ret)
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.
+
 u-boot,spl-payload-offset (int)
If present 

Re: [PATCH 2/3] dm: core: support dtb switching without devices/drivers unloading

2024-06-27 Thread Caleb Connolly




On 27/06/2024 13:35, Mikhail Kshevetskiy wrote:

Consider a case when we have several similar boards but leds & buttons
connected differently. Some of leds uses gpio, other pwm, third gpio over
spi bitbang. Also different board may have different gpio hogs. And last
but not least: board type stored inside a ubi volume.

We want a single u-boot image that will support all these boards (we are
not using SPL). So we need runtime dtb switching.

We can't use MULTI_DTB_FIT and DTB_RESELECT because they tries to switch
dtb too early when flash & ubi drivers are not loaded/activated.

The following code do runtime switching

ret = fdtdec_resetup();
if (!ret && rescan){
dm_uninit();
dm_init_and_scan(false);
}

but it have several nasty issues
  * additional code required to reinitialize console otherwise board will hang.
  * MTD subsystem is not cleared, we need to remove mtd partition before
switching to new dtb
  * spi-nand flash will be named "spi-nand1" instead of "spi-nand0", thus
flash becomes unusable
  * some drivers are unable to deinitialize properly (ex: network driver will
not release mdio interface)
  * some memory will leak, because most of drivers assumes that it will never
be unloaded

To avoid this nasty issues the following hack was implemented
  * Full DM and console reinitialization was skipped
  * Only missed device/subdevice added from new dtb during device scan.
  * Some driver renames their devices. As result we can't use device names
to match old device node with a new one. The special field was added to
struct udevice for this purposes.
  * Driver must be binded to the old device one more time to add missed
subdevices.
  * uclass must be post_bind to the old device one more time to add missed
subdevices.
  * We can't use old dtb anymore, so replace old device node with a new one
for existing devices.

The following restrictions are present:
  * initial dtb MUST be a subset of a new one


Surely dtbo is a better application for your usecase? Switching out the 
entire dtb and "rebooting" the entire driver model seems a bit overkill 
to add some LEDs? If you can just pick a dtbo at some point, overlay it, 
maybe re-generate livetree, and then just devices that are affected by 
the dtbo?


Maybe that's a bit of a naive idea... Perhaps it could be restricted to 
some specific situations, like only support dtbo's that either add new 
nodes or change just the status property of a node?


Though this seems like more or less what you're doing in this patch.

  * old devices will NOT be reinitialised
  * no devices will be deleted or deactivated
  * only new devices will be added

Typical usage:
ret = fdtdec_resetup();
if (!ret && rescan)
dm_rescan();

The code was tested with: gpio, gpio_hog, leds, buttons.

Signed-off-by: Mikhail Kshevetskiy 
---
  drivers/core/device.c | 31 +++
  drivers/core/root.c   | 15 +++
  dts/Kconfig   |  8 
  include/dm/device.h   |  3 +++
  include/dm/root.h | 23 +++
  5 files changed, 80 insertions(+)

diff --git a/drivers/core/device.c b/drivers/core/device.c
index bf7f261cbce..4f575ca82e7 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -62,6 +62,34 @@ static int device_bind_common(struct udevice *parent, const 
struct driver *drv,
return ret;
}
  
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT_RESCAN)

+   if (parent) {
+   struct list_head*entry;
+   ofnode  dev_node;
+
+   list_for_each(entry, >child_head) {
+   dev = list_entry(entry, struct udevice, sibling_node);
+   dev_node = dev_ofnode(dev);
+   if ((dev->driver == drv) && (dev->uclass == uc) &&
+   (dev->driver_data == driver_data) &&
+   (strcmp(dev->node_name, ofnode_get_name(node)) == 
0))
+   {
+   ret = 0;
+   dev_set_ofnode(dev, node);
+   if (drv->bind)
+   ret = drv->bind(dev);
+
+   if (!ret && uc->uc_drv->post_bind)
+   ret = uc->uc_drv->post_bind(dev);
+
+   if (!ret && devp)
+   *devp = dev;
+   return ret;
+   }
+   }
+   }
+#endif
+
dev = calloc(1, sizeof(struct udevice));
if (!dev)
return -ENOMEM;
@@ -75,6 +103,9 @@ static int device_bind_common(struct udevice *parent, const 
struct driver *drv,
dev_set_plat(dev, plat);
dev->driver_data = driver_data;
dev->name = name;
+#if 

Re: [PATCH 3/3] dm: mmc: fix driver rebinding in the case of dtb reloading

2024-06-27 Thread Caleb Connolly

Hi Mikhail,

On 27/06/2024 13:35, Mikhail Kshevetskiy wrote:

Rebinding of the mmc driver causes reregistration of block device.
Thus second mmc device appears and the first becomes broken.

Fix an issue by using already registered block device instead of
registering a new one.

Signed-off-by: Mikhail Kshevetskiy 
---
  drivers/mmc/mmc-uclass.c | 16 +++-
  1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 24170c59ecc..403d20dad53 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -420,11 +420,17 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const 
struct mmc_config *cfg)
/* Use the fixed index with aliases node's index */
debug("%s: alias devnum=%d\n", __func__, dev_seq(dev));
  
-	ret = blk_create_devicef(dev, "mmc_blk", "blk", UCLASS_MMC,

-dev_seq(dev), DEFAULT_BLKSZ, 0, );
-   if (ret) {
-   debug("Cannot create block device\n");
-   return ret;
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT_RESCAN)
+   device_find_first_child_by_uclass(dev, UCLASS_BLK, );
+   if (!bdev)


What about boards with multiple block devices (e.g. ufs + sdcard or mmc 
+ sdcard)?

+#endif
+   {
+   ret = blk_create_devicef(dev, "mmc_blk", "blk", UCLASS_MMC,
+dev_seq(dev), DEFAULT_BLKSZ, 0, );
+   if (ret) {
+   debug("Cannot create block device\n");
+   return ret;
+   }
}
bdesc = dev_get_uclass_plat(bdev);
mmc->cfg = cfg;


--
// Caleb (they/them)


Re: [PATCH v2 2/2] usb: musb-new: sunxi: make compatible with UDC/DM gadget model

2024-06-27 Thread Sam Edwards

On 6/27/24 09:06, Andre Przywara wrote:

On Thu,  8 Jun 2023 13:56:31 -0600
Sam Edwards  wrote:

Hi,

John asked me have a look at this.


Hi Andre, it's good to hear from you again,

I'd first like to make sure you're aware that the date on this patch is 
June *2023,* not June 2024. It's possible things have changed 
substantially in the past year. I do not know if this patch is still a 
necessity; though if John is nudging about it, it probably is.





Since many sunxi boards do not implement a `board_usb_init`, it's


I am confused, what has this have to do with gadget support? *No* sunxi
board build provides board_usb_init(), but apparently this works fine for
now.
I am all for this converting to DM part, but the rationale seems a bit
off.


For context, board_usb_init() is (was?) the non-DM entry point for USB 
functionality; it is (was?) *the* implementation of 
usb_gadget_initialize() when !DM_USB_GADGET.




Also can you give some reason for this patch? What does this fix or
improve? "it's better" is a bit thin, "complying with DM" would already be
sufficient, but maybe there is more?


Eh, yeah, "better" is something of a question-begging word isn't it? :)

The main point is to be compatible with DM's view of UDC, which as you 
said is a worthy goal in itself. It's "better" because this allows using 
DM's all-purpose implementation of usb_gadget_initialize(), which is 
(was?) necessary for those targets lacking board_usb_init().





better if we just make the sunxi USB driver compatible with the
DM gadget model, as many other musb-new variants already are.

This change has been verified working on a T113s.

Signed-off-by: Sam Edwards 
---
  drivers/usb/musb-new/sunxi.c | 50 +++-
  1 file changed, 32 insertions(+), 18 deletions(-)

diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
index 510b254f7d..6658cd995d 100644
--- a/drivers/usb/musb-new/sunxi.c
+++ b/drivers/usb/musb-new/sunxi.c
@@ -444,6 +444,16 @@ static struct musb_hdrc_config musb_config_h3 = {
.ram_bits   = SUNXI_MUSB_RAM_BITS,
  };
  
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)


Please no more #ifdef's. Is there any reason to *not* force
DM_USB_GADGET now, for all sunxi boards, in Kconfig?
Either by "select"ing it in the USB Kconfig, or in arch/arm/Kconfig, like
other platforms do.
Then you don't need to care about the !DM_USB_GADGET definition of this
function and can drop the #ifdef.


I wouldn't be the one to ask. I can't think of any such reason myself. 
But to me it sounds like since *no sunxi board provides 
board_usb_init()* the only way USB gadgets *could* work is with 
DM_USB_GADGET? That'd be reason enough to force it.





+int dm_usb_gadget_handle_interrupts(struct udevice *dev) {


coding style


Sentence fragments are harder to understand. I am assuming you are 
saying, "Please put the opening '{' on its own line."





+   struct sunxi_glue *glue = dev_get_priv(dev);
+   struct musb_host_data *host = >mdata;
+
+   host->host->isr(0, host->host);
+   return 0;
+}
+#endif
+
  static int musb_usb_probe(struct udevice *dev)
  {
struct sunxi_glue *glue = dev_get_priv(dev);
@@ -452,10 +462,6 @@ static int musb_usb_probe(struct udevice *dev)
void *base = dev_read_addr_ptr(dev);
int ret;
  
-#ifdef CONFIG_USB_MUSB_HOST

-   struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
-#endif
-
if (!base)
return -EINVAL;
  
@@ -486,23 +492,31 @@ static int musb_usb_probe(struct udevice *dev)

pdata.platform_ops = _musb_ops;
pdata.config = glue->cfg->config;
  
-#ifdef CONFIG_USB_MUSB_HOST

-   priv->desc_before_addr = true;
+   if (IS_ENABLED(CONFIG_USB_MUSB_HOST)) {
+   struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
+   priv->desc_before_addr = true;
  
-	pdata.mode = MUSB_HOST;

-   host->host = musb_init_controller(, >dev, base);
-   if (!host->host)
-   return -EIO;
+   pdata.mode = MUSB_HOST;
+   host->host = musb_init_controller(, >dev, base);
+   if (!host->host)
+   return -EIO;
  
-	return musb_lowlevel_init(host);

-#else
-   pdata.mode = MUSB_PERIPHERAL;
-   host->host = musb_register(, >dev, base);
-   if (IS_ERR_OR_NULL(host->host))
-   return -EIO;
+   return musb_lowlevel_init(host);
+   } else if (CONFIG_IS_ENABLED(DM_USB_GADGET)) {
+   pdata.mode = MUSB_PERIPHERAL;
+   host->host = musb_init_controller(, >dev, base);
+   if (!host->host)
+   return -EIO;
  
-	return 0;

-#endif
+   return usb_add_gadget_udc(>dev, >host->g);
+   } else {
+   pdata.mode = MUSB_PERIPHERAL;
+   host->host = musb_register(, >dev, base);
+   if (IS_ERR_OR_NULL(host->host))
+   return -EIO;
+
+   return 0;
+ 

Re: [PATCH 1/4] power: regulator: Trigger probe of regulators which are always-on or boot-on

2024-06-27 Thread Marek Vasut

On 6/27/24 10:37 AM, Simon Glass wrote:

Hi Marek,


Hi,

[...]


---
  drivers/power/regulator/regulator-uclass.c | 22 +++---
  1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/power/regulator/regulator-uclass.c 
b/drivers/power/regulator/regulator-uclass.c
index 66fd531da04..ccc4ef33d83 100644
--- a/drivers/power/regulator/regulator-uclass.c
+++ b/drivers/power/regulator/regulator-uclass.c
@@ -433,6 +433,8 @@ static int regulator_post_bind(struct udevice *dev)
 const char *property = "regulator-name";

 uc_pdata = dev_get_uclass_plat(dev);
+   uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
+   uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");

 /* Regulator's mandatory constraint */
 uc_pdata->name = dev_read_string(dev, property);
@@ -444,13 +446,21 @@ static int regulator_post_bind(struct udevice *dev)
 return -EINVAL;
 }

-   if (regulator_name_is_unique(dev, uc_pdata->name))
-   return 0;
+   if (!regulator_name_is_unique(dev, uc_pdata->name)) {
+   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
+ property, dev->name, uc_pdata->name);
+   return -EINVAL;
+   }

-   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
- property, dev->name, uc_pdata->name);
+   /*
+* In case the regulator has regulator-always-on or
+* regulator-boot-on DT property, trigger probe() to
+* configure its default state during startup.
+*/
+   if (uc_pdata->always_on && uc_pdata->boot_on)
+   dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);

-   return -EINVAL;
+   return 0;
  }

  static int regulator_pre_probe(struct udevice *dev)
@@ -473,8 +483,6 @@ static int regulator_pre_probe(struct udevice *dev)
 -ENODATA);
 uc_pdata->max_uA = dev_read_u32_default(dev, "regulator-max-microamp",
 -ENODATA);
-   uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
-   uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
 uc_pdata->ramp_delay = dev_read_u32_default(dev, 
"regulator-ramp-delay",
 0);
 uc_pdata->force_off = dev_read_bool(dev, "regulator-force-boot-off");
--
2.43.0



This is reading a lot of DT stuff very early, which may be slow. It is
also reading from the DT in the bind() step which we sometimes have to
do, but try to avoid.


Actually, it is reading only the bare minimum very early in bind, the 
always-on and boot-on, the rest is in pre_probe, i.e. later.



Also this seems to happen in SPL and again pre-reloc and again in
U-Boot post-reloc?


What does, the uclass post_bind ?


Should we have a step in the init sequence where we set up the
regulators, by calling regulators_enable_boot_on() ?


Let's not do this , the entire point of this series is to get rid of 
those functions and do the regulator configuration the same way LED 
subsystem does it -- by probing always-on/boot-on regulators and 
configuring them correctly on probe.


To me regulators_enable_boot_on() and the like was always an 
inconsistently applied workaround for missing DM_FLAG_PROBE_AFTER_BIND , 
which is now implemented, so such workarounds can be removed.


Re: [PATCH 1/2] led: Implement software led blinking

2024-06-27 Thread Christian Marangi
On Thu, Jun 27, 2024 at 01:36:09PM -0600, Tom Rini wrote:
> On Thu, Jun 27, 2024 at 02:31:13PM +0300, Mikhail Kshevetskiy wrote:
> 
> > From: Michael Polyntsov 
> > 
> > If hardware (or driver) doesn't support leds blinking, it's
> > now possible to use software implementation of blinking instead.
> > This relies on cyclic functions.
> > 
> > Signed-off-by: Michael Polyntsov 
> > Signed-off-by: Mikhail Kshevetskiy 
> > ---
> >  drivers/led/Kconfig  |   9 ++
> >  drivers/led/led-uclass.c | 190 ++-
> >  2 files changed, 195 insertions(+), 4 deletions(-)
> 
> As one of those "well, hunh" kind of moment, I'm cc'ing Christian
> Marangi who also just posted patches foor this kind of functionality.
> 

Eh... Well this implementation is better. I had the idea of adding
support on the uclass level but I preferred to limit it only to GPIO.

Think this would match how it's done in upstream linux kernel so I think
mine should be ignored and this taken (for sw blink).

Should not change a thing for the series since all the bits were using
generic LED functions.

-- 
Ansuel


Re: [PATCH v1] board: mpfs_icicle: implement board_fdt_blob_setup()

2024-06-27 Thread Conor Dooley
On Thu, Jun 27, 2024 at 11:50:33AM +0100, Simon Glass wrote:
> On Thu, 27 Jun 2024 at 10:38, Conor Dooley  wrote:
> > On Thu, Jun 27, 2024 at 09:36:49AM +0100, Simon Glass wrote:
> > > On Tue, 25 Jun 2024 at 15:34, Tom Rini  wrote:
> > > > On Tue, Jun 25, 2024 at 10:08:06AM +0100, Conor Dooley wrote:
> > > > > The firmware on the Icicle is capable of providing a devicetree in a1 
> > > > > to
> > > > > U-Boot, but until now the devicetree has been packaged in a "payload" 
> > > > > [1]
> > > > > alongside U-Boot (or other bootloaders/RTOSes) and appended to the 
> > > > > image.
> > > > > The address of this appended devicetree is placed in a1 by the 
> > > > > firmware.
> > > > > This meant that the mechanism used by OF_SEPARATE to locate the
> > > > > devicetree at the end of the image would pick up the one provided by 
> > > > > the
> > > > > firmware when u-boot-nodtb.bin was in the payload and U-Boot's 
> > > > > devicetree
> > > > > when u-boot.bin was.
> > > > >
> > > > > The firmware is now going to be capable of providing a minimal 
> > > > > devicetree
> > > > > (quite cut down due to severe space constraints), but this devicetree 
> > > > > is
> > > > > linked into the firmware that runs out of the L2 rather than at the 
> > > > > end
> > > > > of the U-Boot image. Implement board_fdt_blob_setup() so that this
> > > > > devicetree can be optionally used, and the devicetree provided in the
> > > > > "payload" can be used without relying on "happening" to implement the
> > > > > same strategy as OF_SEPARATE expects in combination with
> > > > > u-boot-nodtb.bin. Unlike other RISC-V boards, the firmware provided
> > > > > devicetree is only used when OF_BOARD is set, so that the almost
> > > > > certainly more complete devicetree in U-Boot will be used unless
> > > > > explicitly requested otherwise.
> > > > >
> > > > > Link: 
> > > > > https://github.com/polarfire-soc/hart-software-services/blob/master/tools/hss-payload-generator/README.md
> > > > >  [1]
> > > > > Signed-off-by: Conor Dooley 
> > > > > ---
> > > > > CC: Ivan Griffin 
> > > > > CC: Padmarao Begari 
> > > > > CC: Cyril Jean 
> > > > > CC: Tom Rini 
> > > > > CC: Conor Dooley 
> > > > > CC: u-boot@lists.denx.de
> > > > > ---
> > > > >  board/microchip/mpfs_icicle/mpfs_icicle.c | 19 +++
> > > > >  1 file changed, 19 insertions(+)
> > > > >
> > > > > diff --git a/board/microchip/mpfs_icicle/mpfs_icicle.c 
> > > > > b/board/microchip/mpfs_icicle/mpfs_icicle.c
> > > > > index 4d7d843dfa3..2c1f7175f0e 100644
> > > > > --- a/board/microchip/mpfs_icicle/mpfs_icicle.c
> > > > > +++ b/board/microchip/mpfs_icicle/mpfs_icicle.c
> > > > > @@ -9,6 +9,7 @@
> > > > >  #include 
> > > > >  #include 
> > > > >  #include 
> > > > > +#include 
> > > > >
> > > > >  DECLARE_GLOBAL_DATA_PTR;
> > > > >
> > > > > @@ -50,6 +51,24 @@ static void read_device_serial_number(u8 
> > > > > *response, u8 response_size)
> > > > >   response_buf[idx] = readb(MPFS_SYS_SERVICE_MAILBOX + 
> > > > > idx);
> > > > >  }
> > > > >
> > > > > +void *board_fdt_blob_setup(int *err)
> > > > > +{
> > > > > + *err = 0;
> > > > > + /*
> > > > > +  * The devicetree provided by the previous stage is very 
> > > > > minimal due to
> > > > > +  * severe space constraints. The firmware performs no fixups 
> > > > > etc.
> > > > > +  * U-Boot, if providing a devicetree, almost certainly has a 
> > > > > better
> > > > > +  * more complete one than the firmware so that provided by the 
> > > > > firmware
> > > > > +  * is ignored for OF_SEPARATE.
> > > > > +  */
> > > > > + if (IS_ENABLED(CONFIG_OF_BOARD)) {
> > > > > + if (gd->arch.firmware_fdt_addr)
> > > > > + return (ulong 
> > > > > *)(uintptr_t)gd->arch.firmware_fdt_addr;
> > > > > + }
> > > > > +
> > > > > + return (ulong *)_end;
> > > > > +}
> > > > > +
> > > > >  int board_init(void)
> > > > >  {
> > > > >   /* For now nothing to do here. */
> > > >
> > > > I'm adding in Simon and Ilias as this touches on one of those frequent
> > > > topics about how device trees can/should be passed along to us.
> > >
> > > The only thing I can think of is implementing bloblist in  the a1 (?)
> > > firmware, then passing the DT in that.
> >
> > a1 is the register that is used on riscv to pass the dtb, I think the
> > corresponding thing on arm64 is x0.
> >
> > Re-reading the firware handoff spec, it's difficult to see what benefits
> > it actually provides us when we only ever have a single dtb which the
> > firmware does not interact with/use.
> > We are super space constrained in the firmware even carving out 4.5 KiB
> > for a devicetree blob is a stretch and requires disabling other features
> > and ripping out anything in the DT not required for U-Boot to load the OS.
> > Even the ~1 KiB mentioned in bloblist.h for handling a bloblist would be a
> > challenge.
> >
> > I think the only way a bloblist could work is if it was created at 

Re: [PATCH] zlib: Fix big performance regression

2024-06-27 Thread Tom Rini
On Thu, Jun 27, 2024 at 01:34:55PM -0600, Tom Rini wrote:
> On Thu, Jun 27, 2024 at 10:25:21AM +0200, Christophe Leroy wrote:
> 
> > Commit 340fdf1303dc ("zlib: Port fix for CVE-2016-9841 to U-Boot")
> > brings a big performance regression in inflate_fast(), which leads
> > to watchdog timer reset on powerpc 8xx.
> > 
> > It looks like that commit does more than what it describe, it
> > especially removed an important optimisation that was doing copies
> > using halfwords instead of bytes. That unexpected change multiplied
> > by almost 4 the time spent in inflate_fast() and increased by 40%
> > the overall time needed to uncompress linux kernel image.
> > 
> > So partially revert that commit but keep post incrementation as it
> > is the initial purpose of said commit.
> > 
> > Fixes: 340fdf1303dc ("zlib: Port fix for CVE-2016-9841 to U-Boot")
> > Signed-off-by: Christophe Leroy 
> > ---
> >  lib/zlib/inffast.c | 51 --
> >  1 file changed, 40 insertions(+), 11 deletions(-)
> 
> Both this, and my mostly revert lead to CI failures around compression
> tests:
> https://source.denx.de/u-boot/u-boot/-/jobs/859329

A full revert however, is fine.

-- 
Tom


signature.asc
Description: PGP signature


Re: [PATCH 1/2] led: Implement software led blinking

2024-06-27 Thread Tom Rini
On Thu, Jun 27, 2024 at 02:31:13PM +0300, Mikhail Kshevetskiy wrote:

> From: Michael Polyntsov 
> 
> If hardware (or driver) doesn't support leds blinking, it's
> now possible to use software implementation of blinking instead.
> This relies on cyclic functions.
> 
> Signed-off-by: Michael Polyntsov 
> Signed-off-by: Mikhail Kshevetskiy 
> ---
>  drivers/led/Kconfig  |   9 ++
>  drivers/led/led-uclass.c | 190 ++-
>  2 files changed, 195 insertions(+), 4 deletions(-)

As one of those "well, hunh" kind of moment, I'm cc'ing Christian
Marangi who also just posted patches foor this kind of functionality.

-- 
Tom


signature.asc
Description: PGP signature


Re: [PATCH] zlib: Fix big performance regression

2024-06-27 Thread Tom Rini
On Thu, Jun 27, 2024 at 10:25:21AM +0200, Christophe Leroy wrote:

> Commit 340fdf1303dc ("zlib: Port fix for CVE-2016-9841 to U-Boot")
> brings a big performance regression in inflate_fast(), which leads
> to watchdog timer reset on powerpc 8xx.
> 
> It looks like that commit does more than what it describe, it
> especially removed an important optimisation that was doing copies
> using halfwords instead of bytes. That unexpected change multiplied
> by almost 4 the time spent in inflate_fast() and increased by 40%
> the overall time needed to uncompress linux kernel image.
> 
> So partially revert that commit but keep post incrementation as it
> is the initial purpose of said commit.
> 
> Fixes: 340fdf1303dc ("zlib: Port fix for CVE-2016-9841 to U-Boot")
> Signed-off-by: Christophe Leroy 
> ---
>  lib/zlib/inffast.c | 51 --
>  1 file changed, 40 insertions(+), 11 deletions(-)

Both this, and my mostly revert lead to CI failures around compression
tests:
https://source.denx.de/u-boot/u-boot/-/jobs/859329

> 
> diff --git a/lib/zlib/inffast.c b/lib/zlib/inffast.c
> index 5e2a65ad4d..c4b1d12258 100644
> --- a/lib/zlib/inffast.c
> +++ b/lib/zlib/inffast.c
> @@ -236,18 +236,47 @@ unsigned start; /* inflate()'s starting value 
> for strm->avail_out */
>  }
>  }
>  else {
> + unsigned short *sout;
> + unsigned long loops;
> +
>  from = out - dist;  /* copy direct from output */
> -do {/* minimum length is three */
> -*out++ = *from++;
> -*out++ = *from++;
> -*out++ = *from++;
> -len -= 3;
> -} while (len > 2);
> -if (len) {
> -*out++ = *from++;
> -if (len > 1)
> -*out++ = *from++;
> -}
> +/* minimum length is three */
> + /* Align out addr */
> + if (!((long)(out - 1) & 1)) {
> + *out++ = *from++;
> + len--;
> + }
> + sout = (unsigned short *)out;
> + if (dist > 2 ) {
> + unsigned short *sfrom;
> +
> + sfrom = (unsigned short *)from;
> + loops = len >> 1;
> + do
> + *sout++ = get_unaligned(++sfrom);
> + while (--loops);
> + out = (unsigned char *)sout;
> + from = (unsigned char *)sfrom;
> + } else { /* dist == 1 or dist == 2 */
> + unsigned short pat16;
> +
> + pat16 = *(sout-2);
> + if (dist == 1)
> +#if defined(__BIG_ENDIAN)
> + pat16 = (pat16 & 0xff) | ((pat16 & 0xff ) << 8);
> +#elif defined(__LITTLE_ENDIAN)
> + pat16 = (pat16 & 0xff00) | ((pat16 & 0xff00 ) >> 8);
> +#else
> +#error __BIG_ENDIAN nor __LITTLE_ENDIAN is defined
> +#endif
> + loops = len >> 1;
> + do
> + *sout++ = pat16;
> + while (--loops);
> + out = (unsigned char *)sout;
> + }
> + if (len & 1)
> + *out++ = *from++;
>  }
>  }
>  else if ((op & 64) == 0) {  /* 2nd level distance code */
> -- 
> 2.44.0
> 

-- 
Tom


signature.asc
Description: PGP signature


Re: [PATCH] Revert "zlib: Port fix for CVE-2016-9841 to U-Boot"

2024-06-27 Thread Christophe Leroy




Le 27/06/2024 à 17:49, Tom Rini a écrit :

In commit 340fdf1303dc ("zlib: Port fix for CVE-2016-9841 to U-Boot")
Michal brings in (correctly) the upstream fix for CVE-2016-9841.
However, when upstream was fixing this issue they also removed a
necessary optimization for some CPU classes as part of simplifying the
code. This in turn leads to boot failures on the platforms as they now
take too long to decompress images and so the watchdog sees the system
as stuck.

The long term fix here is as Christophe has posted, which is to restore
the optimization. Given the nearness of the release, what I do here is
very similar, result wise, but less so, code wise. This is a revert of
Michal's commit _except_ we only allow for post-increment in the code,
thus keeping the CVE resolved. For the next release this commit shall be
reverted and then Christophe's patch applied.

This largely reverts commit 340fdf1303dce7e5f53ddd981471836058ff23ef.

Reported-by: Christophe Leroy 
Signed-off-by: Tom Rini 


Tested-by: Christophe Leroy 


--
Cc: Christophe Leroy 
Cc: Michal Simek 
---
  lib/zlib/inffast.c | 117 +
  1 file changed, 75 insertions(+), 42 deletions(-)

diff --git a/lib/zlib/inffast.c b/lib/zlib/inffast.c
index 5e2a65ad4d27..c271d85ea191 100644
--- a/lib/zlib/inffast.c
+++ b/lib/zlib/inffast.c
@@ -1,5 +1,5 @@
  /* inffast.c -- fast decoding
- * Copyright (C) 1995-2008, 2010, 2013 Mark Adler
+ * Copyright (C) 1995-2004 Mark Adler
   * For conditions of distribution and use, see copyright notice in zlib.h
   */
  
@@ -12,6 +12,12 @@
  
  #ifndef ASMINF
  
+/*

+ * Only allow post-increment in order to resolve CVE-2016-9841
+ */
+#  define OFF 0
+#  define PUP(a) *(a)++
+
  /*
 Decode literal, length, and distance codes and write out the resulting
 literal and match bytes until either not enough input or output is
@@ -47,13 +53,12 @@
requires strm->avail_out >= 258 for each loop to avoid checking for
output space.
   */
-void ZLIB_INTERNAL inflate_fast(strm, start)
-z_streamp strm;
-unsigned start; /* inflate()'s starting value for strm->avail_out */
+void inflate_fast(z_streamp strm, unsigned start)
+/* start: inflate()'s starting value for strm->avail_out */
  {
  struct inflate_state FAR *state;
-z_const unsigned char FAR *in;  /* local strm->next_in */
-z_const unsigned char FAR *last;/* have enough input while in < last */
+unsigned char FAR *in;  /* local strm->next_in */
+unsigned char FAR *last;/* while in < last, enough input available */
  unsigned char FAR *out; /* local strm->next_out */
  unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
  unsigned char FAR *end; /* while out < end, enough space available */
@@ -79,7 +84,7 @@ unsigned start; /* inflate()'s starting value for 
strm->avail_out */
  
  /* copy state to local variables */

  state = (struct inflate_state FAR *)strm->state;
-in = strm->next_in;
+in = strm->next_in - OFF;
  last = in + (strm->avail_in - 5);
  if (in > last && strm->avail_in > 5) {
  /*
@@ -89,7 +94,7 @@ unsigned start; /* inflate()'s starting value for 
strm->avail_out */
strm->avail_in = 0x - (uintptr_t)in;
  last = in + (strm->avail_in - 5);
  }
-out = strm->next_out;
+out = strm->next_out - OFF;
  beg = out - (start - strm->avail_out);
  end = out + (strm->avail_out - 257);
  #ifdef INFLATE_STRICT
@@ -110,9 +115,9 @@ unsigned start; /* inflate()'s starting value for 
strm->avail_out */
 input data or output space */
  do {
  if (bits < 15) {
-hold += (unsigned long)(*in++) << bits;
+hold += (unsigned long)(PUP(in)) << bits;
  bits += 8;
-hold += (unsigned long)(*in++) << bits;
+hold += (unsigned long)(PUP(in)) << bits;
  bits += 8;
  }
  here = lcode[hold & lmask];
@@ -125,14 +130,14 @@ unsigned start; /* inflate()'s starting value for 
strm->avail_out */
  Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
  "inflate: literal '%c'\n" :
  "inflate: literal 0x%02x\n", here.val));
-*out++ = (unsigned char)(here.val);
+PUP(out) = (unsigned char)(here.val);
  }
  else if (op & 16) { /* length base */
  len = (unsigned)(here.val);
  op &= 15;   /* number of extra bits */
  if (op) {
  if (bits < op) {
-hold += (unsigned long)(*in++) << bits;
+hold += (unsigned long)(PUP(in)) << bits;
  bits += 8;
  }
  len += (unsigned)hold & ((1U << op) - 1);
@@ -141,9 +146,9 @@ unsigned start; /* inflate()'s starting value for 

Re: [PATCH] bootstd: cros: store partition type in an efi_guid_t

2024-06-27 Thread Heinrich Schuchardt



Am 27. Juni 2024 19:06:29 MESZ schrieb "Vincent Stehlé" 
:
>The scan_part() function uses a struct uuid to store the little-endian
>partition type GUID, but this structure should be used only to contain a
>big-endian UUID. Use an efi_guid_t instead.
>
>Signed-off-by: Vincent Stehlé 
>Cc: Simon Glass 
>Cc: Tom Rini 
>---
> boot/bootmeth_cros.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
>diff --git a/boot/bootmeth_cros.c b/boot/bootmeth_cros.c
>index f015f2e1c75..1f83c14aeab 100644
>--- a/boot/bootmeth_cros.c
>+++ b/boot/bootmeth_cros.c
>@@ -148,7 +148,7 @@ static int scan_part(struct udevice *blk, int partnum,
> {
>   struct blk_desc *desc = dev_get_uclass_plat(blk);
>   struct vb2_keyblock *hdr;
>-  struct uuid type;
>+  efi_guid_t type;

Does Chrome OS only support GPT partitioning?

>   ulong num_blks;
>   int ret;
> 
>@@ -161,7 +161,7 @@ static int scan_part(struct udevice *blk, int partnum,
> 
>   /* Check for kernel partition type */
>   log_debug("part %x: type=%s\n", partnum, info->type_guid);
>-  if (uuid_str_to_bin(info->type_guid, (u8 *), UUID_STR_FORMAT_GUID))
>+  if (uuid_str_to_bin(info->type_guid, type.b, UUID_STR_FORMAT_GUID))
>   return log_msg_ret("typ", -EINVAL);

struct disk_partition containing a string which is only needed in the CLI 
instead of the 16 byte GUID was a bad idea to start with. Shouldn't we replace 
it or add least add a GUID field instead of first converting to string and than 
back to GUID?

> 
>   if (memcmp(_kern_type, , sizeof(type)))

You could use the guidcmp() macro here.

Best regards

Heinrich



Re: [PATCH] bootstd: cros: store partition type in an efi_guid_t

2024-06-27 Thread Simon Glass
On Thu, 27 Jun 2024 at 18:06, Vincent Stehlé  wrote:
>
> The scan_part() function uses a struct uuid to store the little-endian
> partition type GUID, but this structure should be used only to contain a
> big-endian UUID. Use an efi_guid_t instead.
>
> Signed-off-by: Vincent Stehlé 
> Cc: Simon Glass 
> Cc: Tom Rini 
> ---
>  boot/bootmeth_cros.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

Reviewed-by: Simon Glass 


Re: [PATCH] CI: Make pytest export JUnitXML

2024-06-27 Thread Simon Glass
On Thu, 27 Jun 2024 at 14:43, Tom Rini  wrote:
>
> Both GitLab and Azure (and other CI systems) have native support for
> displaying JUnitXML test report results. The pytest framework that we
> use can generate these reports. Change our CI tests so that they will
> generate these reports and then have the respective CI platform pick
> them up. We write to different locations because of where each CI is
> (and isn't) able to easily pass things along.
>
> Signed-off-by: Tom Rini 
> ---
>  .azure-pipelines.yml | 12 +++-
>  .gitlab-ci.yml   |  5 -
>  2 files changed, 15 insertions(+), 2 deletions(-)
>

Reviewed-by: Simon Glass 

Nice!


Re: [PATCH 1/2] led: Implement software led blinking

2024-06-27 Thread Simon Glass
Hi Mikhail,

On Thu, 27 Jun 2024 at 12:31, Mikhail Kshevetskiy
 wrote:
>
> From: Michael Polyntsov 
>
> If hardware (or driver) doesn't support leds blinking, it's
> now possible to use software implementation of blinking instead.
> This relies on cyclic functions.
>
> Signed-off-by: Michael Polyntsov 
> Signed-off-by: Mikhail Kshevetskiy 
> ---
>  drivers/led/Kconfig  |   9 ++
>  drivers/led/led-uclass.c | 190 ++-
>  2 files changed, 195 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig
> index 9837960198d..4330f014239 100644
> --- a/drivers/led/Kconfig
> +++ b/drivers/led/Kconfig
> @@ -73,6 +73,15 @@ config LED_BLINK
>   This option enables support for this which adds slightly to the
>   code size.
>
> +config LED_SW_BLINK
> +   bool "Support software LED blinking"
> +   depends on LED_BLINK
> +   select CYCLIC
> +   help
> + Turns on led blinking implemented in the software, useful when
> + the hardware doesn't support led blinking. Does nothing if
> + driver supports blinking.

Can you talk about the blinking p[eriod / API?

> +
>  config SPL_LED
> bool "Enable LED support in SPL"
> depends on SPL_DM
> diff --git a/drivers/led/led-uclass.c b/drivers/led/led-uclass.c
> index a4be56fc258..b35964f2e99 100644
> --- a/drivers/led/led-uclass.c
> +++ b/drivers/led/led-uclass.c
> @@ -15,6 +15,10 @@
>  #include 
>  #include 
>
> +#ifdef CONFIG_LED_SW_BLINK
> +#include 
> +#endif

You should not need to #ifdef include files

> +
>  int led_bind_generic(struct udevice *parent, const char *driver_name)
>  {
> struct udevice *dev;
> @@ -41,6 +45,7 @@ int led_get_by_label(const char *label, struct udevice 
> **devp)
> ret = uclass_get(UCLASS_LED, );
> if (ret)
> return ret;
> +
> uclass_foreach_dev(dev, uc) {
> struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev);
>
> @@ -52,14 +57,180 @@ int led_get_by_label(const char *label, struct udevice 
> **devp)
> return -ENODEV;
>  }
>
> -int led_set_state(struct udevice *dev, enum led_state_t state)
> +#ifdef CONFIG_LED_SW_BLINK
> +
> +enum led_sw_blink_state_t {
> +   LED_SW_BLINK_ST_OFF = 0,
> +   LED_SW_BLINK_ST_ON = 1,
> +   LED_SW_BLINK_ST_NONE = 2,
> +};
> +
> +struct sw_blink_state {
> +   struct udevice *dev;
> +   enum led_sw_blink_state_t cur_blink_state;
> +};
> +
> +static bool led_driver_supports_hw_blinking(const struct udevice *dev)
> +{
> +   struct led_ops *ops = led_get_ops(dev);
> +
> +   /*
> +* We assume that if driver supports set_period, then it correctly
> +* handles all other requests, for example, that
> +* led_set_state(LEDST_BLINK) works correctly.
> +*/
> +   return ops->set_period != NULL;
> +}
> +
> +static const char *led_sw_label_to_cyclic_func_name(const char *label)
> +{
> +#define MAX_NAME_LEN 50
> +   static char cyclic_func_name[MAX_NAME_LEN] = {0};
> +
> +   snprintf(cyclic_func_name, MAX_NAME_LEN, "sw_blink_%s", label);
> +   return cyclic_func_name;
> +#undef MAX_NAME_LEN
> +}
> +
> +static struct cyclic_info *led_sw_find_blinking_led(const char *label)
> +{
> +   struct cyclic_info *cyclic;
> +   const char *cyclic_name;
> +
> +   cyclic_name = led_sw_label_to_cyclic_func_name(label);
> +
> +   hlist_for_each_entry(cyclic, cyclic_get_list(), list) {
> +   if (strcmp(cyclic->name, cyclic_name) == 0)
> +   return cyclic;
> +   }
> +
> +   return NULL;
> +}
> +
> +static bool led_sw_is_blinking(struct udevice *dev)
> +{
> +   struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev);
> +   struct cyclic_info *cyclic = led_sw_find_blinking_led(uc_plat->label);
> +
> +   if (cyclic != NULL) {

if (cyclic) {

> +   struct sw_blink_state *state;
> +
> +   state = (struct sw_blink_state *)cyclic->ctx;
> +   return state->cur_blink_state != LED_SW_BLINK_ST_NONE;
> +   }
> +
> +   return false;
> +}
> +
> +static void led_sw_blink(void *void_state)
> +{
> +   struct sw_blink_state *state = (struct sw_blink_state *)void_state;

You should not need that cast

> +   struct udevice *dev = state->dev;
> +   struct led_ops *ops = led_get_ops(dev);
> +
> +   switch (state->cur_blink_state) {
> +   case LED_SW_BLINK_ST_OFF:
> +   state->cur_blink_state = LED_SW_BLINK_ST_ON;
> +   ops->set_state(dev, LEDST_ON);
> +   break;
> +   case LED_SW_BLINK_ST_ON:
> +   state->cur_blink_state = LED_SW_BLINK_ST_OFF;
> +   ops->set_state(dev, LEDST_OFF);
> +   break;
> +   case LED_SW_BLINK_ST_NONE:
> +   /*
> +* led_set_period has been called, but
> +* led_set_state(LDST_BLINK) has not yet,
> +* so 

Re: [PATCH] gpt: allow spaces in partition list

2024-06-27 Thread Simon Glass
Hi Mikhail,

On Thu, 27 Jun 2024 at 12:29, Mikhail Kshevetskiy
 wrote:
>
> This allows spliting partition list to several lines in environment file
>
> ex:
> 
> gpt_partition_list=
> name=boot1,size=5MiB,start=0x10;
> name=boot2,size=5MiB;
> name=rootfs1,size=70MiB;
> name=rootfs2,size=70MiB;
> name=overlay1,size=20MiB;
> name=overlay2,size=20MiB;
> name=art,size=4MiB;

Is this referring to a .env file, i.e. a text environment file? If so,
I would hope that spaces at the start of a line would be automatically
removed.

>
> Signed-off-by: Mikhail Kshevetskiy 
> ---
>  cmd/gpt.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/cmd/gpt.c b/cmd/gpt.c
> index 7aaf1889a5a..2b29ab98ccc 100644
> --- a/cmd/gpt.c
> +++ b/cmd/gpt.c
> @@ -117,6 +117,7 @@ static char *extract_val(const char *str, const char *key)
> k = strsep(, "=");
> if (!k)
> break;
> +   k += strspn(k, " \t");
> if  (strcmp(k, key) == 0) {
> new = strdup(v);
> break;
> @@ -151,6 +152,7 @@ static bool found_key(const char *str, const char *key)
> k = strsep(, ",");
> if (!k)
> break;
> +   k += strspn(k, " \t");
> if  (strcmp(k, key) == 0) {
> result = true;
> break;
> --
> 2.43.0
>

Regards,
Simon


[PATCH] bootstd: cros: store partition type in an efi_guid_t

2024-06-27 Thread Vincent Stehlé
The scan_part() function uses a struct uuid to store the little-endian
partition type GUID, but this structure should be used only to contain a
big-endian UUID. Use an efi_guid_t instead.

Signed-off-by: Vincent Stehlé 
Cc: Simon Glass 
Cc: Tom Rini 
---
 boot/bootmeth_cros.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/boot/bootmeth_cros.c b/boot/bootmeth_cros.c
index f015f2e1c75..1f83c14aeab 100644
--- a/boot/bootmeth_cros.c
+++ b/boot/bootmeth_cros.c
@@ -148,7 +148,7 @@ static int scan_part(struct udevice *blk, int partnum,
 {
struct blk_desc *desc = dev_get_uclass_plat(blk);
struct vb2_keyblock *hdr;
-   struct uuid type;
+   efi_guid_t type;
ulong num_blks;
int ret;
 
@@ -161,7 +161,7 @@ static int scan_part(struct udevice *blk, int partnum,
 
/* Check for kernel partition type */
log_debug("part %x: type=%s\n", partnum, info->type_guid);
-   if (uuid_str_to_bin(info->type_guid, (u8 *), UUID_STR_FORMAT_GUID))
+   if (uuid_str_to_bin(info->type_guid, type.b, UUID_STR_FORMAT_GUID))
return log_msg_ret("typ", -EINVAL);
 
if (memcmp(_kern_type, , sizeof(type)))
-- 
2.43.0



Re: [PATCH] board/include: ti/env: j721e.env/ti_common: Fix cpsw0_qsgmii_phyinit

2024-06-27 Thread Nishanth Menon
On 15:19-20240627, Siddharth Vadapalli wrote:
> The command "main_cpsw0_qsgmii_phyinit" has to be run depending on
> whether or not the "do_main_cpsw0_qsgmii_phyinit" variable is set.
> However, there is no support for the cases where the environment variable
> "do_main_cpsw0_qsgmii_phyinit" is updated at runtime. On J721E, the value
> of "do_main_cpsw0_qsgmii_phyinit" is updated at runtime.
> 
> Fix the existing implementation in order to handle the case where the
> value of "do_main_cpsw0_qsgmii_phyinit" is updated at runtime. Do so by
> introducing the environment variable "update_do_main_cpsw0_qsgmii_phyinit"
> which defaults to setting "do_main_cpsw0_qsgmii_phyinit" to zero, but at
> the same time, it allows the board to update the value at runtime.
> 
> Fixes: 0d72b0f2f83b ("include: env: ti: ti_common: Run 
> main_cpsw0_qsgmii_phyinit conditionally")
> Signed-off-by: Siddharth Vadapalli 


Why cant we do this entirely in board files? we do the board detection
there anyways..

> ---
> 
> Hello,
> 
> This patch is based on commit
> 899b088674 Merge patch series "pxe: Add debugging for booting"
> of U-Boot's next branch.
> 
> Regards,
> Siddharth.
> 
>  board/ti/j721e/j721e.env | 9 +
>  include/env/ti/ti_common.env | 3 ++-
>  2 files changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/board/ti/j721e/j721e.env b/board/ti/j721e/j721e.env
> index 38bfd7d496..03d7e81aa8 100644
> --- a/board/ti/j721e/j721e.env
> +++ b/board/ti/j721e/j721e.env
> @@ -29,7 +29,7 @@ bootdir=/boot
>  rd_spec=-
>  
>  #if CONFIG_TARGET_J7200_A72_EVM
> -do_main_cpsw0_qsgmii_phyinit=1
> +update_do_main_cpsw0_qsgmii_phyinit=setenv do_main_cpsw0_qsgmii_phyinit 1;
>  init_main_cpsw0_qsgmii_phy=gpio set gpio@22_17;
>   gpio clear gpio@22_16
>  main_cpsw0_qsgmii_phyinit=
> @@ -39,10 +39,11 @@ main_cpsw0_qsgmii_phyinit=
>  #elif CONFIG_TARGET_J721E_A72_EVM
>  init_main_cpsw0_qsgmii_phy=gpio set gpio@22_17;
>   gpio clear gpio@22_16
> -main_cpsw0_qsgmii_phyinit=
> +update_do_main_cpsw0_qsgmii_phyinit=
>   if test $board_name = J721EX-PM1-SOM || test $board_name = 
> J721EX-PM2-SOM || test $board_name = j721e; then
> - do_main_cpsw0_qsgmii_phyinit=1; else
> - do_main_cpsw0_qsgmii_phyinit=0; fi;
> + setenv do_main_cpsw0_qsgmii_phyinit 1; else
> + setenv do_main_cpsw0_qsgmii_phyinit 0; fi;
> +main_cpsw0_qsgmii_phyinit=
>   if test ${do_main_cpsw0_qsgmii_phyinit} -eq 1 && test ${dorprocboot} 
> -eq 1 && test ${boot} = mmc; then
>   run init_main_cpsw0_qsgmii_phy; \
>   fi;
> diff --git a/include/env/ti/ti_common.env b/include/env/ti/ti_common.env
> index c5c3642177..d0b3d698a0 100644
> --- a/include/env/ti/ti_common.env
> +++ b/include/env/ti/ti_common.env
> @@ -23,9 +23,10 @@ get_fit_overlaystring=
>   done;
>  get_fit_config=setexpr name_fit_config gsub / _ conf-${fdtfile}
>  run_fit=run get_fit_config; bootm 
> ${addr_fit}#${name_fit_config}${overlaystring}
> -do_main_cpsw0_qsgmii_phyinit=0
> +update_do_main_cpsw0_qsgmii_phyinit=setenv do_main_cpsw0_qsgmii_phyinit 0;
>  bootcmd_ti_mmc=
>   run findfdt; run init_${boot};
> + run update_do_main_cpsw0_qsgmii_phyinit;
>  #if CONFIG_CMD_REMOTEPROC
>   if test ${do_main_cpsw0_qsgmii_phyinit} -eq 1;
>   then run main_cpsw0_qsgmii_phyinit;
> -- 
> 2.40.1
> 

-- 
Regards,
Nishanth Menon
Key (0xDDB5849D1736249D) / Fingerprint: F8A2 8693 54EB 8232 17A3  1A34 DDB5 
849D 1736 249D


[PATCH] Revert "zlib: Port fix for CVE-2016-9841 to U-Boot"

2024-06-27 Thread Tom Rini
In commit 340fdf1303dc ("zlib: Port fix for CVE-2016-9841 to U-Boot")
Michal brings in (correctly) the upstream fix for CVE-2016-9841.
However, when upstream was fixing this issue they also removed a
necessary optimization for some CPU classes as part of simplifying the
code. This in turn leads to boot failures on the platforms as they now
take too long to decompress images and so the watchdog sees the system
as stuck.

The long term fix here is as Christophe has posted, which is to restore
the optimization. Given the nearness of the release, what I do here is
very similar, result wise, but less so, code wise. This is a revert of
Michal's commit _except_ we only allow for post-increment in the code,
thus keeping the CVE resolved. For the next release this commit shall be
reverted and then Christophe's patch applied.

This largely reverts commit 340fdf1303dce7e5f53ddd981471836058ff23ef.

Reported-by: Christophe Leroy 
Signed-off-by: Tom Rini 
--
Cc: Christophe Leroy 
Cc: Michal Simek 
---
 lib/zlib/inffast.c | 117 +
 1 file changed, 75 insertions(+), 42 deletions(-)

diff --git a/lib/zlib/inffast.c b/lib/zlib/inffast.c
index 5e2a65ad4d27..c271d85ea191 100644
--- a/lib/zlib/inffast.c
+++ b/lib/zlib/inffast.c
@@ -1,5 +1,5 @@
 /* inffast.c -- fast decoding
- * Copyright (C) 1995-2008, 2010, 2013 Mark Adler
+ * Copyright (C) 1995-2004 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -12,6 +12,12 @@
 
 #ifndef ASMINF
 
+/*
+ * Only allow post-increment in order to resolve CVE-2016-9841
+ */
+#  define OFF 0
+#  define PUP(a) *(a)++
+
 /*
Decode literal, length, and distance codes and write out the resulting
literal and match bytes until either not enough input or output is
@@ -47,13 +53,12 @@
   requires strm->avail_out >= 258 for each loop to avoid checking for
   output space.
  */
-void ZLIB_INTERNAL inflate_fast(strm, start)
-z_streamp strm;
-unsigned start; /* inflate()'s starting value for strm->avail_out */
+void inflate_fast(z_streamp strm, unsigned start)
+/* start: inflate()'s starting value for strm->avail_out */
 {
 struct inflate_state FAR *state;
-z_const unsigned char FAR *in;  /* local strm->next_in */
-z_const unsigned char FAR *last;/* have enough input while in < last */
+unsigned char FAR *in;  /* local strm->next_in */
+unsigned char FAR *last;/* while in < last, enough input available */
 unsigned char FAR *out; /* local strm->next_out */
 unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
 unsigned char FAR *end; /* while out < end, enough space available */
@@ -79,7 +84,7 @@ unsigned start; /* inflate()'s starting value for 
strm->avail_out */
 
 /* copy state to local variables */
 state = (struct inflate_state FAR *)strm->state;
-in = strm->next_in;
+in = strm->next_in - OFF;
 last = in + (strm->avail_in - 5);
 if (in > last && strm->avail_in > 5) {
 /*
@@ -89,7 +94,7 @@ unsigned start; /* inflate()'s starting value for 
strm->avail_out */
strm->avail_in = 0x - (uintptr_t)in;
 last = in + (strm->avail_in - 5);
 }
-out = strm->next_out;
+out = strm->next_out - OFF;
 beg = out - (start - strm->avail_out);
 end = out + (strm->avail_out - 257);
 #ifdef INFLATE_STRICT
@@ -110,9 +115,9 @@ unsigned start; /* inflate()'s starting value for 
strm->avail_out */
input data or output space */
 do {
 if (bits < 15) {
-hold += (unsigned long)(*in++) << bits;
+hold += (unsigned long)(PUP(in)) << bits;
 bits += 8;
-hold += (unsigned long)(*in++) << bits;
+hold += (unsigned long)(PUP(in)) << bits;
 bits += 8;
 }
 here = lcode[hold & lmask];
@@ -125,14 +130,14 @@ unsigned start; /* inflate()'s starting value for 
strm->avail_out */
 Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
 "inflate: literal '%c'\n" :
 "inflate: literal 0x%02x\n", here.val));
-*out++ = (unsigned char)(here.val);
+PUP(out) = (unsigned char)(here.val);
 }
 else if (op & 16) { /* length base */
 len = (unsigned)(here.val);
 op &= 15;   /* number of extra bits */
 if (op) {
 if (bits < op) {
-hold += (unsigned long)(*in++) << bits;
+hold += (unsigned long)(PUP(in)) << bits;
 bits += 8;
 }
 len += (unsigned)hold & ((1U << op) - 1);
@@ -141,9 +146,9 @@ unsigned start; /* inflate()'s starting value for 
strm->avail_out */
 }
 Tracevv((stderr, "inflate: length %u\n", len));
 if (bits < 15) {

Re: [PATCH v2 2/2] usb: musb-new: sunxi: make compatible with UDC/DM gadget model

2024-06-27 Thread Andre Przywara
On Thu,  8 Jun 2023 13:56:31 -0600
Sam Edwards  wrote:

Hi,

John asked me have a look at this.

> Since many sunxi boards do not implement a `board_usb_init`, it's

I am confused, what has this have to do with gadget support? *No* sunxi
board build provides board_usb_init(), but apparently this works fine for
now.
I am all for this converting to DM part, but the rationale seems a bit
off.

Also can you give some reason for this patch? What does this fix or
improve? "it's better" is a bit thin, "complying with DM" would already be
sufficient, but maybe there is more?

> better if we just make the sunxi USB driver compatible with the
> DM gadget model, as many other musb-new variants already are.
> 
> This change has been verified working on a T113s.
> 
> Signed-off-by: Sam Edwards 
> ---
>  drivers/usb/musb-new/sunxi.c | 50 +++-
>  1 file changed, 32 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
> index 510b254f7d..6658cd995d 100644
> --- a/drivers/usb/musb-new/sunxi.c
> +++ b/drivers/usb/musb-new/sunxi.c
> @@ -444,6 +444,16 @@ static struct musb_hdrc_config musb_config_h3 = {
>   .ram_bits   = SUNXI_MUSB_RAM_BITS,
>  };
>  
> +#if CONFIG_IS_ENABLED(DM_USB_GADGET)

Please no more #ifdef's. Is there any reason to *not* force
DM_USB_GADGET now, for all sunxi boards, in Kconfig?
Either by "select"ing it in the USB Kconfig, or in arch/arm/Kconfig, like
other platforms do.
Then you don't need to care about the !DM_USB_GADGET definition of this
function and can drop the #ifdef.

> +int dm_usb_gadget_handle_interrupts(struct udevice *dev) {

coding style

> + struct sunxi_glue *glue = dev_get_priv(dev);
> + struct musb_host_data *host = >mdata;
> +
> + host->host->isr(0, host->host);
> + return 0;
> +}
> +#endif
> +
>  static int musb_usb_probe(struct udevice *dev)
>  {
>   struct sunxi_glue *glue = dev_get_priv(dev);
> @@ -452,10 +462,6 @@ static int musb_usb_probe(struct udevice *dev)
>   void *base = dev_read_addr_ptr(dev);
>   int ret;
>  
> -#ifdef CONFIG_USB_MUSB_HOST
> - struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
> -#endif
> -
>   if (!base)
>   return -EINVAL;
>  
> @@ -486,23 +492,31 @@ static int musb_usb_probe(struct udevice *dev)
>   pdata.platform_ops = _musb_ops;
>   pdata.config = glue->cfg->config;
>  
> -#ifdef CONFIG_USB_MUSB_HOST
> - priv->desc_before_addr = true;
> + if (IS_ENABLED(CONFIG_USB_MUSB_HOST)) {
> + struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
> + priv->desc_before_addr = true;
>  
> - pdata.mode = MUSB_HOST;
> - host->host = musb_init_controller(, >dev, base);
> - if (!host->host)
> - return -EIO;
> + pdata.mode = MUSB_HOST;
> + host->host = musb_init_controller(, >dev, base);
> + if (!host->host)
> + return -EIO;
>  
> - return musb_lowlevel_init(host);
> -#else
> - pdata.mode = MUSB_PERIPHERAL;
> - host->host = musb_register(, >dev, base);
> - if (IS_ERR_OR_NULL(host->host))
> - return -EIO;
> + return musb_lowlevel_init(host);
> + } else if (CONFIG_IS_ENABLED(DM_USB_GADGET)) {
> + pdata.mode = MUSB_PERIPHERAL;
> + host->host = musb_init_controller(, >dev, base);
> + if (!host->host)
> + return -EIO;
>  
> - return 0;
> -#endif
> + return usb_add_gadget_udc(>dev, >host->g);
> + } else {
> + pdata.mode = MUSB_PERIPHERAL;
> + host->host = musb_register(, >dev, base);
> + if (IS_ERR_OR_NULL(host->host))
> + return -EIO;
> +
> + return 0;
> + }

That looks like a good cleanup! Just need to test it briefly, but it seems
like the gist of this patch is fine.

Cheers,
Andre


>  }
>  
>  static int musb_usb_remove(struct udevice *dev)



Re: [ANN] U-Boot v2024.07-rc5 released

2024-06-27 Thread Tom Rini
On Thu, Jun 27, 2024 at 10:23:34AM +0200, Christophe Leroy wrote:
> 
> 
> Le 26/06/2024 à 17:01, Tom Rini a écrit :
> > On Tue, Jun 25, 2024 at 09:20:54PM +0200, Christophe Leroy wrote:
> > > 
> > > 
> > > Le 25/06/2024 à 17:19, Tom Rini a écrit :
> > > > On Tue, Jun 25, 2024 at 03:12:38PM +, LEROY Christophe wrote:
> > > > > Hi All,
> > > > > 
> > > > > Le 24/06/2024 à 21:30, Tom Rini a écrit :
> > > > > > Hey all,
> > > > > > 
> > > > > > Well, once again I need to check my calender reminders since, 
> > > > > > whoops,
> > > > > > I'm a week late. That said, looking at the list of changes in this
> > > > > > slightly elongated period, I think it's OK. At this point we're a 
> > > > > > week
> > > > > > out from the release, so it's time for clear and obvious regression
> > > > > > fixes. Ideally ones introduced this release cycle so there's less
> > > > > > chances of unintended side-effects.
> > > > > > 
> > > > > > In terms of a changelog,
> > > > > > git log --merges v2024.07-rc4..v2024.07-rc5
> > > > > > contains what I've pulled but as always, better PR messages and tags
> > > > > > will provide better results here.
> > > > > > 
> > > > > > With that, the final release is planned for Monday, July 1st, 2024.
> > > > > > Thanks all!
> > > > > > 
> > > > > 
> > > > > For your information, I have started testing v2024.07 on my powerpc
> > > > > boards in operational condition and I have a major problem : U-boot
> > > > > doesn't get the Linux kernel started before the watchdog fires. I have
> > > > > to disable watchdog to get it running.
> > > > > 
> > > > > This problem doesn't occur with v2024.04.
> > > > > 
> > > > > I bisected it to commit 340fdf1303dc ("zlib: Port fix for 
> > > > > CVE-2016-9841
> > > > > to U-Boot") and I also confirm that v2024.07-rc5 works well with that
> > > > > commit reverted on top of it.
> > > > > 
> > > > > Any idea of what is going wrong with that commit ?
> > > > 
> > > > Are you able to check the zlib performance before/after that commit?
> > > > 
> > > 
> > > Indeed there's a huge difference.
> > > 
> > > Before : 12298074 timebase ticks to decompress kernel
> > > After :  17145906 ticks, that is 40% more time.
> > > 
> > > But behind that, we also need to understand why the watchdog is not kept
> > > alive during that time.
> > 
> > That is odd, I would have expected it to have been kept alive.
> > 
> 
> I digged into it a bit more and really that commit 340fdf1303dc ("zlib: Port
> fix for CVE-2016-9841 to U-Boot") is the issue. The watchdog is still kept
> alive, but not fast enough. On powerpc 8xx, the CPU watchdog has a timeout
> of slightly more than 1s, so it must be kept alive very often.
> 
> schedule() is called in inflate() just before calling inflate_fast(), which
> worked until now because the maximum time spent in inflate_fast() was about
> 300ms. With the above commit, more than 1s is spent in inflate_fast() , for
> the problematic block the time spent inside inflate_fast() is multiplied by
> almost 4.
> 
> The problem is that the commit does more than what it says and removes
> an important optimisation that is using halfwords instead of bytes for the
> copy.
> 
> I'm going to send shortly a patch to partially revert that commit. But if
> you feel it is better to revert the commit completely and provide a fix in
> next cycle, it is ok as well, up to you but I think it is important to get
> that fixed for v2024.07.
> 
> I'm also sending a fix on the setup of 8xx watchdog, but that has almost no
> impact in reality and doesn't fix the problem.

Thanks for digging in to all of this, I'll have to think about what path
is better at this point in the cycle.

-- 
Tom


signature.asc
Description: PGP signature


Re: [PATCH 13/14] Update u-boot.cfg to include CFG also

2024-06-27 Thread Tom Rini
On Thu, Jun 27, 2024 at 09:37:15AM +0100, Simon Glass wrote:
> Hi Tom,
> 
> On Wed, 26 Jun 2024 at 15:07, Tom Rini  wrote:
> >
> > On Wed, Jun 26, 2024 at 09:00:41AM +0100, Simon Glass wrote:
> > > Hi Tom,
> > >
> > > On Tue, 25 Jun 2024 at 15:14, Tom Rini  wrote:
> > > >
> > > > On Tue, Jun 25, 2024 at 01:38:04PM +0100, Simon Glass wrote:
> > > > > Hi Tom,
> > > > >
> > > > > On Mon, 24 Jun 2024 at 19:29, Tom Rini  wrote:
> > > > > >
> > > > > > On Sun, Jun 23, 2024 at 02:30:32PM -0600, Simon Glass wrote:
> > > > > >
> > > > > > > Some configuration is now in variables with a CFG_ prefix. Add 
> > > > > > > these to
> > > > > > > the .cfg file so that we can see everything in one place. Sort the
> > > > > > > options so they are easier to find and compare.
> > > > > > >
> > > > > > > Signed-off-by: Simon Glass 
> > > > > > > ---
> > > > > > >
> > > > > > > Changes in v2:
> > > > > > > - Add new patch to update u-boot.cfg with CFG_... options
> > > > > > >
> > > > > > >  scripts/Makefile.autoconf | 2 +-
> > > > > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > > > > >
> > > > > > > diff --git a/scripts/Makefile.autoconf b/scripts/Makefile.autoconf
> > > > > > > index b42f9b525fe..65ff11ea508 100644
> > > > > > > --- a/scripts/Makefile.autoconf
> > > > > > > +++ b/scripts/Makefile.autoconf
> > > > > > > @@ -71,7 +71,7 @@ quiet_cmd_autoconf = GEN $@
> > > > > > >  quiet_cmd_u_boot_cfg = CFG $@
> > > > > > >cmd_u_boot_cfg = \
> > > > > > >   $(CPP) $(c_flags) $2 -DDO_DEPS_ONLY -dM include/config.h > 
> > > > > > > $@.tmp && { \
> > > > > > > - grep 'define CONFIG_' $@.tmp | \
> > > > > > > + egrep 'define (CONFIG_|CFG_)' $@.tmp | sort | \
> > > > > > >   sed '/define CONFIG_IS_ENABLED(/d;/define 
> > > > > > > CONFIG_IF_ENABLED_INT(/d;/define CONFIG_VAL(/d;' > $@; \
> > > > > > >   rm $@.tmp;  
> > > > > > > \
> > > > > > >   } || {  
> > > > > > > \
> > > > > >
> > > > > > I don't like this because whereas "CONFIG_" is enforced to be set 
> > > > > > only
> > > > > > by Kconfig and so always all reliably set and found via a single 
> > > > > > header,
> > > > > > CFG_ stuff is not.
> > > > >
> > > > > OK, so how are CFG_ options found? I hit this when trying to find the
> > > > > SDRAM size on rockchip 3399 and I could not find any way of figuring
> > > > > it out.
> > > >
> > > > It's just another define, there's no uniformity to it. For some of the
> > > > SDRAM values really we need some build time way to grab some information
> > > > out of the default device tree.
> > >
> > > Can you give an example of a board that could use this? I looked at
> > > the devicetree for chromebook_kevin and don't see a memory range in
> > > ther.
> >
> > OK, wow, I didn't realize /memory was optional now. But indeed, I don't
> > see it in the dtb file. That removes that option then, sadly.
> 
> Well, we can still require it, so long as an error is produced if the
> property is needed but does not exist.

"We" who? I don't feel like we'll have a lot of traction with linux
kernel folks in requiring /memory to be added to the dts files on
however many platforms don't have it today because I'm going to guess
it's added at run time, possibly by us, with the correct size and we'd
be asking for statically adding things half-wrong like a lot of
platforms used to do (and in turn rely on U-Boot to correct the size).

-- 
Tom


signature.asc
Description: PGP signature


Re: [PATCH v2 00/40] mmc: dw_mmc: Enable eMMC on E850-96 board

2024-06-27 Thread Tom Rini
On Wed, Jun 26, 2024 at 10:12:12PM +0530, Anand Moon wrote:
> Hi Sam,
> 
> On Wed, 19 Jun 2024 at 02:26, Sam Protsenko  
> wrote:
> >
> > If there are no new comments on this series, can you please apply it?
> >
> > Thanks!
> 
> Tested on Odroid XU4 and Odrroid U3 boards
> 
> Please add my
> 
> Reviewed-by: Anand Moon 
> Tested-by: Anand Moon 

Thanks, Minkyu will you be able to pick these up (and other outstanding
patches) for a pull request to -next soon?

-- 
Tom


signature.asc
Description: PGP signature


Re: [PATCH] arm: davinci: remove unused defines

2024-06-27 Thread Tom Rini
On Wed, Jun 19, 2024 at 11:00:01AM +, Emil Kronborg wrote:

> The last usage of the DV_TIMER_ and DV_WDT_ definitions were removed in
> commits 8d7757637138 ("ARM: davinci: remove support for cam_enc_4xx")
> and cef443c1666c ("arm: davinci: remove leftover code for dm* SoCs"),
> respectively.
> 
> Signed-off-by: Emil Kronborg 

Applied to u-boot/next, thanks!

-- 
Tom


signature.asc
Description: PGP signature


Re: [PATCH] zlib: Fix big performance regression

2024-06-27 Thread Joakim Tjernlund
On Thu, 2024-06-27 at 10:25 +0200, Christophe Leroy wrote:
> Commit 340fdf1303dc ("zlib: Port fix for CVE-2016-9841 to U-Boot")
> brings a big performance regression in inflate_fast(), which leads
> to watchdog timer reset on powerpc 8xx.
> 
> It looks like that commit does more than what it describe, it
> especially removed an important optimisation that was doing copies
> using halfwords instead of bytes. That unexpected change multiplied
> by almost 4 the time spent in inflate_fast() and increased by 40%
> the overall time needed to uncompress linux kernel image.
> 
> So partially revert that commit but keep post incrementation as it
> is the initial purpose of said commit.
> 
> Fixes: 340fdf1303dc ("zlib: Port fix for CVE-2016-9841 to U-Boot")
> Signed-off-by: Christophe Leroy 
> ---

Thanks for looking after my old optimization :)

 Jocke


Re: [PATCH] zlib: Fix big performance regression

2024-06-27 Thread Tom Rini
On Thu, Jun 27, 2024 at 10:25:21AM +0200, Christophe Leroy wrote:

> Commit 340fdf1303dc ("zlib: Port fix for CVE-2016-9841 to U-Boot")
> brings a big performance regression in inflate_fast(), which leads
> to watchdog timer reset on powerpc 8xx.
> 
> It looks like that commit does more than what it describe, it
> especially removed an important optimisation that was doing copies
> using halfwords instead of bytes. That unexpected change multiplied
> by almost 4 the time spent in inflate_fast() and increased by 40%
> the overall time needed to uncompress linux kernel image.
> 
> So partially revert that commit but keep post incrementation as it
> is the initial purpose of said commit.
> 
> Fixes: 340fdf1303dc ("zlib: Port fix for CVE-2016-9841 to U-Boot")
> Signed-off-by: Christophe Leroy 

Good work.

Reviewed-by: Tom Rini 

And can you please head over to https://github.com/madler/zlib and file
an issue, or pull request with your changes explaining why? I would hope
they're interested in performance regressions on slower parts still.
Thanks!

-- 
Tom


signature.asc
Description: PGP signature


[PATCH] CI: Make pytest export JUnitXML

2024-06-27 Thread Tom Rini
Both GitLab and Azure (and other CI systems) have native support for
displaying JUnitXML test report results. The pytest framework that we
use can generate these reports. Change our CI tests so that they will
generate these reports and then have the respective CI platform pick
them up. We write to different locations because of where each CI is
(and isn't) able to easily pass things along.

Signed-off-by: Tom Rini 
---
 .azure-pipelines.yml | 12 +++-
 .gitlab-ci.yml   |  5 -
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index c43bb51066a5..fff78785ee92 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -287,7 +287,7 @@ stages:
   export PATH=/opt/qemu/bin:/tmp/uboot-test-hooks/bin:\${PATH}
   export PYTHONPATH=/tmp/uboot-test-hooks/py/travis-ci
   # "\${var:+"-k \$var"}" expands to "" if \$var is empty, "-k \$var" 
if not
-  ./test/py/test.py -ra -o 
cache_dir="\$UBOOT_TRAVIS_BUILD_DIR"/.pytest_cache --bd \${TEST_PY_BD} 
\${TEST_PY_ID} \${TEST_PY_TEST_SPEC:+"-k \${TEST_PY_TEST_SPEC}"} --build-dir 
"\$UBOOT_TRAVIS_BUILD_DIR" --report-dir "\$UBOOT_TRAVIS_BUILD_DIR"
+  ./test/py/test.py -ra -o 
cache_dir="\$UBOOT_TRAVIS_BUILD_DIR"/.pytest_cache --bd \${TEST_PY_BD} 
\${TEST_PY_ID} \${TEST_PY_TEST_SPEC:+"-k \${TEST_PY_TEST_SPEC}"} --build-dir 
"\$UBOOT_TRAVIS_BUILD_DIR" --report-dir "\$UBOOT_TRAVIS_BUILD_DIR" 
--junitxml=\$(System.DefaultWorkingDirectory)/results.xml
   # the below corresponds to .gitlab-ci.yml "after_script"
   rm -rf /tmp/uboot-test-hooks /tmp/venv
   EOF
@@ -371,6 +371,7 @@ stages:
   docker run "$@" --device /dev/fuse:/dev/fuse \
  -v $PWD:$(work_dir) \
  -v $(Pipeline.Workspace):$(Pipeline.Workspace) \
+ -v 
$(System.DefaultWorkingDirectory):$(System.DefaultWorkingDirectory) \
  -e WORK_DIR="${WORK_DIR}" \
  -e TEST_PY_BD="${TEST_PY_BD}" \
  -e TEST_PY_ID="${TEST_PY_ID}" \
@@ -378,6 +379,10 @@ stages:
  -e OVERRIDE="${OVERRIDE}" \
  -e BUILD_ENV="${BUILD_ENV}" $(ci_runner_image) \
  $(Pipeline.Workspace)/testsh/test.sh
+  - task: PublishTestResults@2
+inputs:
+  testResultsFormat: 'JUnit'
+  testResultsFiles: 'results.xml'
 
 - stage: test_py_qemu
   jobs:
@@ -495,6 +500,7 @@ stages:
   docker run "$@" --device /dev/fuse:/dev/fuse \
  -v $PWD:$(work_dir) \
  -v $(Pipeline.Workspace):$(Pipeline.Workspace) \
+ -v 
$(System.DefaultWorkingDirectory):$(System.DefaultWorkingDirectory) \
  -e WORK_DIR="${WORK_DIR}" \
  -e TEST_PY_BD="${TEST_PY_BD}" \
  -e TEST_PY_ID="${TEST_PY_ID}" \
@@ -503,6 +509,10 @@ stages:
  -e BUILD_ENV="${BUILD_ENV}" $(ci_runner_image) \
  $(Pipeline.Workspace)/testsh/test.sh
 retryCountOnTaskFailure: 2 # QEMU may be too slow, etc.
+  - task: PublishTestResults@2
+inputs:
+  testResultsFormat: 'JUnit'
+  testResultsFiles: 'results.xml'
 
 - stage: world_build
   jobs:
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 165f765a8332..a6c5040239ae 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -41,7 +41,7 @@ stages:
   fi
 
   after_script:
-- cp -v /tmp/${TEST_PY_BD}/*.{html,css} .
+- cp -v /tmp/${TEST_PY_BD}/*.{html,css,xml} .
 - rm -rf /tmp/uboot-test-hooks /tmp/venv
   script:
 # If we've been asked to use clang only do one configuration.
@@ -83,11 +83,14 @@ stages:
   ./test/py/test.py -ra --bd ${TEST_PY_BD} ${TEST_PY_ID}
 ${TEST_PY_TEST_SPEC:+"-k ${TEST_PY_TEST_SPEC}"}
 --build-dir "$UBOOT_TRAVIS_BUILD_DIR"
+--junitxml=/tmp/${TEST_PY_BD}/results.xml
   artifacts:
 when: always
 paths:
   - "*.html"
   - "*.css"
+reports:
+  junit: results.xml
 expire_in: 1 week
 
 .world_build:
-- 
2.34.1



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

2024-06-27 Thread Quentin Schulz

Hi Marek,

On 6/27/24 1:58 AM, Marek Vasut wrote:

Insert /u-boot, =  property into the U-Boot control DT
during SPL DTO application process. This can be used by user to inspect
which DTOs got applied by the SPL and in which order from running U-Boot.

Example:
```
u-boot=> fdt addr $fdtcontroladdr && fdt list /
Working FDT set to aee9aeb0
/ {
 u-boot,fdt-dto-imx8mp-dhcom-pdk3-overlay-rev100 = <0x0005>;
 u-boot,fdt-dto-imx8mp-dhcom-som-overlay-rev100 = <0x0004>;
 u-boot,fdt-dto-imx8mp-dhcom-pdk-overlay-eth2xfast = <0x0003>;
 u-boot,fdt-dto-imx8mp-dhcom-som-overlay-eth2xfast = <0x0002>;
...
```



Shouldn't this rather be in /config node?

Also, I am highly suggesting to have an additional prefix aside from 
u-boot to avoid unfortunate name clashes between DTO and existing 
properties. Or could be in its own child node of /config ?


In any case, can you please add or edit a file somewhere to define this 
new dt-binding.


Additional question, what is this index for?

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";


Cheers,
Quentin


Re: [PATCH 1/3] net: give a different name to rtl8169 interfaces

2024-06-27 Thread Quentin Schulz

Hi Etienne,

On 6/25/24 1:42 PM, Etienne Dublé wrote:


Hello,

Le 25/06/2024 à 12:25, Dragan Simic a écrit :
Another option may be to name them "rtl8169@", with "" 
reflecting the PCI region address (so it is unique and stable). What 
do you think?


I guess that's one way, I'm also wondering how systemd renames those
to be unique but stable on the same machine, maybe we could take some
inspiration from them for that?


Systemd also allows renaming of network interfaces using some rules
predefined by the user, so there's also the possibility to rename the
interfaces in U-Boot to ethernet0 and ethernet1, using fixed rules
that would be based on the PCI region address.


OK but the renaming occurs in the rtl8169 driver, that is used by 
several boards, whereas the PCI region addresses come from the 
device-tree, so they differ from board to board.




I'm of the opinion that we only care about stability for the same 
product, not for different products with the same Ethernet PHY on 
different SoCs/products.


Cheers,
Quentin


[PATCH 12/12] net/tcp: define a fallback value for rcv_wnd size

2024-06-27 Thread Mikhail Kshevetskiy
Some driver implements it's own network packet pool, so PKTBUFSRX is zero.
This results in zero-size TCP receive window, so data transfer doesn't
work. Avod it by setting a reasonable fallback value.

Signed-off-by: Mikhail Kshevetskiy 
---
 net/tcp.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/net/tcp.c b/net/tcp.c
index c0045e32198..3f12c71e1f7 100644
--- a/net/tcp.c
+++ b/net/tcp.c
@@ -30,7 +30,11 @@
 #define TCP_SEND_TIMEOUT   2000UL
 #define TCP_RX_INACTIVE_TIMEOUT3UL
 #define TCP_START_SEQ_INC  2153/* just large prime number */
-#define TCP_RCV_WND_SIZE   (PKTBUFSRX * TCP_MSS)
+#if PKTBUFSRX != 0
+  #define TCP_RCV_WND_SIZE (PKTBUFSRX * TCP_MSS)
+#else
+  #define TCP_RCV_WND_SIZE (4 * TCP_MSS)
+#endif
 
 #define TCP_PACKET_OK  0
 #define TCP_PACKET_DROP1
-- 
2.43.0



[PATCH 11/12] net/tcp: add support of multiple tcp connections

2024-06-27 Thread Mikhail Kshevetskiy
As we don't support ARP table in U-Boot, these
connections must come from the same host.

Signed-off-by: Mikhail Kshevetskiy 
---
 net/Kconfig| 10 
 net/fastboot_tcp.c | 12 +
 net/httpd.c| 20 ++-
 net/netcat.c   |  7 +
 net/tcp.c  | 64 ++
 net/wget.c |  7 +
 6 files changed, 97 insertions(+), 23 deletions(-)

diff --git a/net/Kconfig b/net/Kconfig
index 424c5f0dae8..e46d519f507 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -257,6 +257,16 @@ config HTTPD_COMMON
* object will be stored to a memory area specified in
  image_load_addr variable
 
+config PROT_TCP_MAX_CONNS
+   int "Maximum number of TCP connections"
+   depends on PROT_TCP
+   default 1
+   help
+ In some cases (like httpd support) it may be desirable
+ to support more than one TCP connection at the time.
+ As we don't support ARP table, these connections MUST
+ comes from a single host.
+
 config IPV6
bool "IPv6 support"
help
diff --git a/net/fastboot_tcp.c b/net/fastboot_tcp.c
index 30eacca8d1e..dfa02709393 100644
--- a/net/fastboot_tcp.c
+++ b/net/fastboot_tcp.c
@@ -19,6 +19,12 @@ static char txbuf[sizeof(u64) + FASTBOOT_RESPONSE_LEN + 1];
 
 static u32 data_read;
 static u32 tx_last_offs, tx_last_len;
+static int connections;
+
+static void tcp_stream_on_closed(struct tcp_stream *tcp)
+{
+   connections = 0;
+}
 
 static void tcp_stream_on_rcv_nxt_update(struct tcp_stream *tcp, u32 rx_bytes)
 {
@@ -96,10 +102,16 @@ static int tcp_stream_on_create(struct tcp_stream *tcp)
if (tcp->lport != FASTBOOT_TCP_PORT)
return 0;
 
+   if (connections > 0)
+   return 0;
+
+   connections++;
+
data_read = 0;
tx_last_offs = 0;
tx_last_len = 0;
 
+   tcp->on_closed = tcp_stream_on_closed;
tcp->on_rcv_nxt_update = tcp_stream_on_rcv_nxt_update;
tcp->rx = tcp_stream_rx;
tcp->tx = tcp_stream_tx;
diff --git a/net/httpd.c b/net/httpd.c
index 31c10843a44..ad13b155912 100644
--- a/net/httpd.c
+++ b/net/httpd.c
@@ -85,6 +85,8 @@ static struct http_reply options_reply = {
 
 static int stop_server;
 static int tsize_num_hash;
+static int connections;
+static struct httpd_priv *post_id;
 
 static struct httpd_config *cfg;
 
@@ -109,6 +111,12 @@ static void tcp_stream_on_closed(struct tcp_stream *tcp)
 {
struct httpd_priv *priv = tcp->priv;
 
+   connections--;
+   if (tcp->priv == post_id) {
+   /* forget completed POST */
+   post_id = NULL;
+   }
+
if ((priv->req_state != ST_REQ_DONE) &&
(priv->req_state >= ST_REQ_MPFILE)) {
printf("\nHTTPD: transfer was terminated\n");
@@ -119,7 +127,7 @@ static void tcp_stream_on_closed(struct tcp_stream *tcp)
 
free(tcp->priv);
 
-   if (stop_server)
+   if (stop_server && (connections == 0))
net_set_state(cfg->on_stop != NULL ?
  cfg->on_stop() :
  NETLOOP_SUCCESS);
@@ -334,6 +342,11 @@ static enum httpd_req_check http_parse_line(struct 
httpd_priv *priv, char *line)
/* expect: "\r\n--${boundary}--\r\n", so strlen() + 8 */
priv->post_flen -= strlen(priv->post_boundary) + 8;
 
+   if (post_id != NULL) {
+   /* do not allow multiple POST requests */
+   return HTTPD_BAD_REQ;
+   }
+
if (cfg->pre_post != NULL) {
post.addr = NULL;
post.name = priv->post_name;
@@ -345,6 +358,8 @@ static enum httpd_req_check http_parse_line(struct 
httpd_priv *priv, char *line)
return ret;
}
 
+   post_id = priv;
+
tsize_num_hash = 0;
printf("File: %s, %u bytes\n", priv->post_fname, 
priv->post_flen);
printf("Loading: ");
@@ -660,6 +675,7 @@ static int tcp_stream_on_create(struct tcp_stream *tcp)
if (priv == NULL)
return 0;
 
+   connections++;
memset(priv, 0, sizeof(struct httpd_priv));
priv->tcp = tcp;
 
@@ -688,6 +704,8 @@ void httpd_start(void)
net_set_state(NETLOOP_FAIL);
return;
}
+   post_id = NULL;
+   connections = 0;
stop_server = 0;
memset(net_server_ethaddr, 0, 6);
tcp_stream_set_on_create_handler(tcp_stream_on_create);
diff --git a/net/netcat.c b/net/netcat.c
index ea225c68c87..cfd39fafb61 100644
--- a/net/netcat.c
+++ b/net/netcat.c
@@ -23,6 +23,7 @@ static intlisten;
 static int reading;
 static unsigned intpackets;
 

[PATCH 10/12] net/tcp: simplify tcp header filling code

2024-06-27 Thread Mikhail Kshevetskiy
Signed-off-by: Mikhail Kshevetskiy 
---
 net/tcp.c | 70 +--
 1 file changed, 37 insertions(+), 33 deletions(-)

diff --git a/net/tcp.c b/net/tcp.c
index a5689a892b2..9fb80f9c2a8 100644
--- a/net/tcp.c
+++ b/net/tcp.c
@@ -528,10 +528,37 @@ void net_set_syn_options(struct tcp_stream *tcp, union 
tcp_build_pkt *b)
b->ip.end = TCP_O_END;
 }
 
+const char *tcpflags_to_str(char tcpflags, char *buf, int size)
+{
+   int i = 0, len;
+   char *orig = buf;
+   const struct {
+   int bit;
+   const char  *name;
+   } desc[] = {{TCP_RST, "RST"}, {TCP_SYN, "SYN"}, {TCP_PUSH, "PSH"},
+   {TCP_FIN, "FIN"}, {TCP_ACK, "ACK"}, {0, NULL}};
+
+   *orig = '\0';
+   while (desc[i].name != NULL) {
+   len = strlen(desc[i].name);
+   if (size <= len + 1)
+   break;
+   if (buf != orig) {
+   *buf++ = ',';
+   size--;
+   }
+   strcpy(buf, desc[i].name);
+   buf += len;
+   size -= len;
+   }
+   return orig;
+}
+
 int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int payload_len,
   u8 action, u32 tcp_seq_num, u32 tcp_ack_num)
 {
union tcp_build_pkt *b = (union tcp_build_pkt *)pkt;
+   char buf[24];
int pkt_hdr_len;
int pkt_len;
int tcp_len;
@@ -541,55 +568,32 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar 
*pkt, int payload_len,
 * 4 bits reserved options
 */
b->ip.hdr.tcp_flags = action;
-   pkt_hdr_len = IP_TCP_HDR_SIZE;
b->ip.hdr.tcp_hlen = 
SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
 
switch (action) {
case TCP_SYN:
debug_cond(DEBUG_DEV_PKT,
-  "TCP Hdr:SYN (%pI4, %pI4, sq=%u, ak=%u)\n",
-  >rhost, _ip,
-  tcp_seq_num, tcp_ack_num);
+  "TCP Hdr:%s (%pI4, %pI4, s=%u, a=%u)\n",
+  tcpflags_to_str(action, buf, sizeof(buf)),
+  >rhost, _ip, tcp_seq_num, tcp_ack_num);
net_set_syn_options(tcp, b);
pkt_hdr_len = IP_TCP_O_SIZE;
break;
-   case TCP_SYN | TCP_ACK:
-   case TCP_ACK:
-   pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(tcp, b);
-   b->ip.hdr.tcp_flags = action;
-   debug_cond(DEBUG_DEV_PKT,
-  "TCP Hdr:ACK (%pI4, %pI4, s=%u, a=%u, A=%x)\n",
-  >rhost, _ip, tcp_seq_num, tcp_ack_num,
-  action);
-   break;
-   case TCP_FIN:
-   debug_cond(DEBUG_DEV_PKT,
-  "TCP Hdr:FIN  (%pI4, %pI4, s=%u, a=%u)\n",
-  >rhost, _ip, tcp_seq_num, tcp_ack_num);
-   payload_len = 0;
-   pkt_hdr_len = IP_TCP_HDR_SIZE;
-   break;
case TCP_RST | TCP_ACK:
case TCP_RST:
debug_cond(DEBUG_DEV_PKT,
-  "TCP Hdr:RST  (%pI4, %pI4, s=%u, a=%u)\n",
+  "TCP Hdr:%s (%pI4, %pI4, s=%u, a=%u)\n",
+  tcpflags_to_str(action, buf, sizeof(buf)),
   >rhost, _ip, tcp_seq_num, tcp_ack_num);
+   pkt_hdr_len = IP_TCP_HDR_SIZE;
break;
-   /* Notify connection closing */
-   case (TCP_FIN | TCP_ACK):
-   case (TCP_FIN | TCP_ACK | TCP_PUSH):
-   debug_cond(DEBUG_DEV_PKT,
-  "TCP Hdr:FIN ACK PSH(%pI4, %pI4, s=%u, a=%u, 
A=%x)\n",
-  >rhost, _ip,
-  tcp_seq_num, tcp_ack_num, action);
-   fallthrough;
default:
pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(tcp, b);
-   b->ip.hdr.tcp_flags = action | TCP_PUSH | TCP_ACK;
debug_cond(DEBUG_DEV_PKT,
-  "TCP Hdr:dft  (%pI4, %pI4, s=%u, a=%u, A=%x)\n",
-  >rhost, _ip,
-  tcp_seq_num, tcp_ack_num, action);
+  "TCP Hdr:%s (%pI4, %pI4, s=%u, a=%u)\n",
+  tcpflags_to_str(action, buf, sizeof(buf)),
+  >rhost, _ip, tcp_seq_num, tcp_ack_num);
+   break;
}
 
pkt_len = pkt_hdr_len + payload_len;
-- 
2.43.0



[PATCH 09/12] net/httpd-upload: add web-server for file uploading

2024-06-27 Thread Mikhail Kshevetskiy
Signed-off-by: Mikhail Kshevetskiy 
---
 cmd/Kconfig |  14 
 cmd/net.c   |  20 ++
 include/net/httpd-upload.h  |  12 
 net/Makefile|  19 +
 net/httpd-upload.c  | 123 
 net/httpd_upload/error_400.html |   9 +++
 net/httpd_upload/error_404.html |  10 +++
 net/httpd_upload/index.html |  14 
 net/httpd_upload/upload_ok.html |   7 ++
 9 files changed, 228 insertions(+)
 create mode 100644 include/net/httpd-upload.h
 create mode 100644 net/httpd-upload.c
 create mode 100644 net/httpd_upload/error_400.html
 create mode 100644 net/httpd_upload/error_404.html
 create mode 100644 net/httpd_upload/index.html
 create mode 100644 net/httpd_upload/upload_ok.html

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 00cc13e2006..e5d2852168b 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1997,6 +1997,20 @@ config CMD_NETCAT
  netcat is a simple command to load/store kernel, or other files,
  using netcat like manner over TCP.
 
+config CMD_HTTPD_UPLOAD
+   bool "HTTP server for file uploading"
+   depends on HTTPD_COMMON
+   help
+ HTTP/1.1 compatible server for file uploading.
+
+config CMD_HTTPD_UPLOAD_MAX_SIZE
+   int "Maximum uploading size"
+   depends on CMD_HTTPD_UPLOAD
+   default 209715200
+   help
+ This sets maximum size of uploaded file. Real transfer will be
+ slightly more than this limit.
+
 config CMD_MII
bool "mii"
imply CMD_MDIO
diff --git a/cmd/net.c b/cmd/net.c
index ecc1b49f52f..22e9d1910b6 100644
--- a/cmd/net.c
+++ b/cmd/net.c
@@ -22,6 +22,9 @@
 #include 
 #include 
 #include 
+#if defined(CONFIG_CMD_HTTPD_UPLOAD)
+#include 
+#endif
 
 static int netboot_common(enum proto_t, struct cmd_tbl *, int, char * const 
[]);
 
@@ -230,6 +233,23 @@ U_BOOT_CMD(
 );
 #endif
 
+#if defined(CONFIG_CMD_HTTPD_UPLOAD)
+static int do_httpd_upload(struct cmd_tbl *cmdtp, int flag, int argc, char 
*const argv[])
+{
+   if (argc < 2)
+   return 1;
+
+   httpd_upload_prepare();
+   return netboot_common(HTTPD, cmdtp, argc, argv);
+}
+
+U_BOOT_CMD(
+   httpd_upload,   2,  1,  do_httpd_upload,
+   "starts httpd server for file uploading",
+   "[loadAddress]\n"
+);
+#endif
+
 static void netboot_update_env(void)
 {
char tmp[46];
diff --git a/include/net/httpd-upload.h b/include/net/httpd-upload.h
new file mode 100644
index 000..a80df214668
--- /dev/null
+++ b/include/net/httpd-upload.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-2-Clause
+ *
+ * httpd-upload include file
+ * Copyright (C) 2024 IOPSYS Software Solutions AB
+ * Author: Mikhail Kshevetskiy 
+ */
+#ifndef __NET_HTTPD_UPLOAD_TCP_H__
+#define __NET_HTTPD_UPLOAD_TCP_H__
+
+void httpd_upload_prepare(void);
+
+#endif /* __NET_HTTPD_UPLOAD_TCP_H__ */
diff --git a/net/Makefile b/net/Makefile
index c1f491fad02..e7cbbc2248e 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -35,8 +35,27 @@ obj-$(CONFIG_PROT_TCP) += tcp.o
 obj-$(CONFIG_CMD_WGET) += wget.o
 obj-$(CONFIG_CMD_NETCAT) += netcat.o
 obj-$(CONFIG_HTTPD_COMMON) += httpd.o
+obj-$(CONFIG_CMD_HTTPD_UPLOAD) += httpd-upload.o
 
 # Disable this warning as it is triggered by:
 # sprintf(buf, index ? "foo%d" : "foo", index)
 # and this is intentional usage.
 CFLAGS_eth_common.o += -Wno-format-extra-args
+
+STATIC_SUBST := 's/^\(unsigned char \)/static \1/'
+SIZE_REMOVE_SUBST := 's/^unsigned int .*//'
+
+httpd_upload_generated:
+   rm -rf $(src)/httpd_upload_generated
+   mkdir -p $(src)/httpd_upload_generated
+   cd $(src)/httpd_upload && find . -type f | while read fname; do \
+   name="$${fname##*/}" && \
+   name="$${name%%.*}"  && \
+   set -o pipefail && xxd -i "$${fname##./}" | \
+   sed $(STATIC_SUBST) | \
+   sed $(SIZE_REMOVE_SUBST) > 
../httpd_upload_generated/$${name}.h; \
+   done
+
+.PHONY: httpd_upload_generated
+
+net/httpd-upload.o:httpd_upload_generated
diff --git a/net/httpd-upload.c b/net/httpd-upload.c
new file mode 100644
index 000..f3015a37f2f
--- /dev/null
+++ b/net/httpd-upload.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * httpd-upload support driver
+ * Copyright (C) 2024 IOPSYS Software Solutions AB
+ * Author: Mikhail Kshevetskiy 
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#define MAX_FILE_SIZE  CONFIG_CMD_HTTPD_UPLOAD_MAX_SIZE
+
+static enum net_loop_state  httpd_on_stop(void);
+
+static enum httpd_req_check httpd_pre_post(void *req_id, const char *url,
+  struct httpd_post_data *post);
+static struct http_reply*httpd_get(void *req_id, const char *url);
+static struct http_reply*httpd_post(void *req_id, const char *url,
+   struct httpd_post_data *post);
+static void httpd_on_req_end(void 

[PATCH 08/12] net/httpd: add httpd common code

2024-06-27 Thread Mikhail Kshevetskiy
This patch adds HTTP/1.1 compatible web-server that can be used
by other. Server supports GET, POST, and HEAD requests. On client
request it will call user specified GET/POST callback. Then results
will be transmitted to client.

The following restrictions exist on the POST request
at the moment:
  * only multipart/form-data with a single file object
  * object will be stored to a memory area specified in
image_load_addr variable

Signed-off-by: Mikhail Kshevetskiy 
---
 include/net.h   |   2 +-
 include/net/httpd.h |  64 
 net/Kconfig |  14 +
 net/Makefile|   1 +
 net/httpd.c | 695 
 net/net.c   |   6 +
 6 files changed, 781 insertions(+), 1 deletion(-)
 create mode 100644 include/net/httpd.h
 create mode 100644 net/httpd.c

diff --git a/include/net.h b/include/net.h
index 235396a171b..6debbf8ed2a 100644
--- a/include/net.h
+++ b/include/net.h
@@ -516,7 +516,7 @@ extern int  net_restart_wrap;   /* Tried all 
network devices */
 enum proto_t {
BOOTP, RARP, ARP, TFTPGET, DHCP, DHCP6, PING, PING6, DNS, NFS, CDP,
NETCONS, SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT_UDP, FASTBOOT_TCP,
-   WOL, UDP, NCSI, WGET, NETCAT_LOAD, NETCAT_STORE, RS
+   WOL, UDP, NCSI, WGET, NETCAT_LOAD, NETCAT_STORE, HTTPD, RS
 };
 
 extern charnet_boot_file_name[1024];/* Boot File name */
diff --git a/include/net/httpd.h b/include/net/httpd.h
new file mode 100644
index 000..ff0dc93ecf5
--- /dev/null
+++ b/include/net/httpd.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * httpd support header file
+ * Copyright (C) 2024 IOPSYS Software Solutions AB
+ * Author: Mikhail Kshevetskiy 
+ *
+ */
+#ifndef __NET_HTTPD_COMMON_H__
+#define __NET_HTTPD_COMMON_H__
+
+struct http_reply {
+   int code;
+   const char  *code_msg;
+   const char  *data_type;
+   void*data;
+   u32 len;
+};
+
+struct httpd_post_data {
+   const char  *name;
+   const char  *filename;
+   void*addr;
+   u32 size;
+};
+
+enum httpd_req_check {
+   HTTPD_REQ_OK,
+   HTTPD_BAD_URL,
+   HTTPD_BAD_REQ,
+   HTTPD_CLNT_RST
+};
+
+struct httpd_config {
+   enum net_loop_state (*on_stop)(void);
+   void(*on_req_end)(void *req_id);
+
+   enum httpd_req_check(*pre_get)(void *req_id, const char *url);
+   enum httpd_req_check(*pre_post)(void *req_id, const char *url,
+   struct httpd_post_data *post);
+
+   struct http_reply * (*get)(void *req_id, const char *url);
+   struct http_reply * (*post)(void *req_id, const char *url,
+   struct httpd_post_data *post);
+
+   struct http_reply   *error_400;
+   struct http_reply   *error_404;
+};
+
+/**
+ * httpd_setup() - configure the webserver
+ */
+void httpd_setup(struct httpd_config *config);
+
+/**
+ * httpd_stop() - start stopping of the webserver
+ */
+void httpd_stop(void);
+
+/**
+ * httpd_start() - start the webserver
+ */
+void httpd_start(void);
+
+#endif /* __NET_HTTPD_COMMON_H__ */
diff --git a/net/Kconfig b/net/Kconfig
index 5dff6336293..424c5f0dae8 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -243,6 +243,20 @@ config PROT_TCP_SACK
  This option should be turn on if you want to achieve the fastest
  file transfer possible.
 
+config HTTPD_COMMON
+   bool "HTTP server common code"
+   depends on PROT_TCP
+   help
+ HTTP/1.1 compatible web-server common code. It supports standard
+ GET/POST requests. User MUST provide a configuration to the
+ web-server. On client request web-server will call user specified
+ GET/POST callback. Then results will be transmitted to the client.
+ The following restricions on the POST request are present at the
+ moment:
+   * only mulipart/form-data with a single binary object
+   * object will be stored to a memory area specified in
+ image_load_addr variable
+
 config IPV6
bool "IPv6 support"
help
diff --git a/net/Makefile b/net/Makefile
index dac7b4859fb..c1f491fad02 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_PROT_UDP) += udp.o
 obj-$(CONFIG_PROT_TCP) += tcp.o
 obj-$(CONFIG_CMD_WGET) += wget.o
 obj-$(CONFIG_CMD_NETCAT) += netcat.o
+obj-$(CONFIG_HTTPD_COMMON) += httpd.o
 
 # Disable this warning as it is triggered by:
 # sprintf(buf, index ? "foo%d" : "foo", index)
diff --git a/net/httpd.c b/net/httpd.c
new file mode 100644
index 000..31c10843a44
--- /dev/null
+++ b/net/httpd.c
@@ -0,0 +1,695 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * httpd support driver
+ * Copyright (C) 2024 IOPSYS Software Solutions AB
+ * Author: Mikhail Kshevetskiy 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 

[PATCH 07/12] net/netcat: add netcat over tcp support

2024-06-27 Thread Mikhail Kshevetskiy
This patch adds downloading/uploading of data with netcat.
Client/server mode both supported.

Signed-off-by: Mikhail Kshevetskiy 
---
 cmd/Kconfig  |   7 ++
 cmd/net.c|  34 +++--
 include/net.h|   2 +-
 include/net/netcat.h |  20 ++
 net/Makefile |   1 +
 net/net.c|   9 +++
 net/netcat.c | 159 +++
 7 files changed, 226 insertions(+), 6 deletions(-)
 create mode 100644 include/net/netcat.h
 create mode 100644 net/netcat.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 6834bbd82f3..00cc13e2006 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1990,6 +1990,13 @@ config CMD_WGET
  wget is a simple command to download kernel, or other files,
  from a http server over TCP.
 
+config CMD_NETCAT
+   bool "netcat"
+   select PROT_TCP
+   help
+ netcat is a simple command to load/store kernel, or other files,
+ using netcat like manner over TCP.
+
 config CMD_MII
bool "mii"
imply CMD_MDIO
diff --git a/cmd/net.c b/cmd/net.c
index d407d8320a3..ecc1b49f52f 100644
--- a/cmd/net.c
+++ b/cmd/net.c
@@ -208,6 +208,28 @@ U_BOOT_CMD(
 );
 #endif
 
+#if defined(CONFIG_CMD_NETCAT)
+static int do_netcat(struct cmd_tbl *cmdtp, int flag, int argc, char *const 
argv[])
+{
+   if (argc < 2)
+   return 1;
+
+   if (strcmp(argv[1], "load") == 0)
+   return netboot_common(NETCAT_LOAD, cmdtp, argc - 1, argv + 1);
+   else if (strcmp(argv[1], "store") == 0)
+   return netboot_common(NETCAT_STORE, cmdtp, argc - 1, argv + 1);
+   else
+   return 1;
+}
+
+U_BOOT_CMD(
+   netcat,   5,  1,  do_netcat,
+   "load/store data via tcp netcat utility",
+   "load [loadAddress] [[hostIPaddr:]port]\n"
+   "store Address Size [[hostIPaddr:]port]\n"
+);
+#endif
+
 static void netboot_update_env(void)
 {
char tmp[46];
@@ -325,16 +347,17 @@ static int parse_args(enum proto_t proto, int argc, char 
*const argv[])
 
switch (argc) {
case 1:
-   if (IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT)
+   if ((IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) ||
+   (IS_ENABLED(CONFIG_CMD_NETCAT) && proto == NETCAT_STORE))
return 1;
-
/* refresh bootfile name from env */
copy_filename(net_boot_file_name, env_get("bootfile"),
  sizeof(net_boot_file_name));
break;
 
case 2:
-   if (IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT)
+   if ((IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) ||
+   (IS_ENABLED(CONFIG_CMD_NETCAT) && proto == NETCAT_STORE))
return 1;
/*
 * Only one arg - accept two forms:
@@ -356,7 +379,8 @@ static int parse_args(enum proto_t proto, int argc, char 
*const argv[])
break;
 
case 3:
-   if (IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) {
+   if ((IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) ||
+   (IS_ENABLED(CONFIG_CMD_NETCAT) && proto == NETCAT_STORE)) {
if (parse_addr_size(argv))
return 1;
} else {
@@ -367,7 +391,7 @@ static int parse_args(enum proto_t proto, int argc, char 
*const argv[])
}
break;
 
-#ifdef CONFIG_CMD_TFTPPUT
+#if defined(CONFIG_CMD_TFTPPUT) || defined(CONFIG_CMD_NETCAT)
case 4:
if (parse_addr_size(argv))
return 1;
diff --git a/include/net.h b/include/net.h
index fe645245f0f..235396a171b 100644
--- a/include/net.h
+++ b/include/net.h
@@ -516,7 +516,7 @@ extern int  net_restart_wrap;   /* Tried all 
network devices */
 enum proto_t {
BOOTP, RARP, ARP, TFTPGET, DHCP, DHCP6, PING, PING6, DNS, NFS, CDP,
NETCONS, SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT_UDP, FASTBOOT_TCP,
-   WOL, UDP, NCSI, WGET, RS
+   WOL, UDP, NCSI, WGET, NETCAT_LOAD, NETCAT_STORE, RS
 };
 
 extern charnet_boot_file_name[1024];/* Boot File name */
diff --git a/include/net/netcat.h b/include/net/netcat.h
new file mode 100644
index 000..09470e7f0ce
--- /dev/null
+++ b/include/net/netcat.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-2-Clause
+ *
+ * netcat include file
+ * Copyright (C) 2024 IOPSYS Software Solutions AB
+ * Author: Mikhail Kshevetskiy 
+ */
+#ifndef __NET_NETCAT_TCP_H__
+#define __NET_NETCAT_TCP_H__
+
+/**
+ * netcat_load_start() - begin netcat in loading mode
+ */
+void netcat_load_start(void);
+
+/**
+ * netcat_store_start() - begin netcat in data storing mode
+ */
+void netcat_store_start(void);
+
+#endif /* __NET_NETCAT_TCP_H__ */
diff --git a/net/Makefile b/net/Makefile
index 64ab7ec740a..dac7b4859fb 100644
--- a/net/Makefile
+++ 

[PATCH 06/12] net/tcp: improve tcp framework, use better state machine

2024-06-27 Thread Mikhail Kshevetskiy
Changes:
 * Fix initial send sequence always zero issue
 * Use state machine close to RFC 9293. This should make TCP
   transfers more reliable.
 * Improve TCP framework a lot. This should make tcp client
   code much more simple.
 * rewrite wget with new tcp stack
 * rewrite fastboot_tcp with new tcp stack

Signed-off-by: Mikhail Kshevetskiy 
---
 include/net/tcp.h  | 171 +++--
 include/net/wget.h |   8 -
 net/fastboot_tcp.c | 190 +-
 net/net.c  |   4 +
 net/tcp.c  | 837 ++---
 net/wget.c | 460 +++--
 6 files changed, 992 insertions(+), 678 deletions(-)

diff --git a/include/net/tcp.h b/include/net/tcp.h
index 0694af9d5b1..b070354e871 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -265,6 +265,7 @@ union tcp_build_pkt {
  * @TCP_CLOSING: Rec FIN, sent FIN, ACK waiting for ACK
  * @TCP_FIN_WAIT_1: Sent FIN waiting for response
  * @TCP_FIN_WAIT_2: Rec ACK from FIN sent, waiting for FIN
+ * @TCP_LAST_ACK: Waiting for ACK of the connection termination
  */
 enum tcp_state {
TCP_CLOSED,
@@ -274,7 +275,20 @@ enum tcp_state {
TCP_CLOSE_WAIT,
TCP_CLOSING,
TCP_FIN_WAIT_1,
-   TCP_FIN_WAIT_2
+   TCP_FIN_WAIT_2,
+   TCP_LAST_ACK,
+};
+
+/**
+ * enum tcp_status - TCP stream status for connection
+ * @TCP_ERR_OK: no rx/tx errors
+ * @TCP_ERR_TOUT: rx/tx timeout happened
+ * @TCP_ERR_RST: connection was reset
+ */
+enum tcp_status {
+   TCP_ERR_OK = 0,
+   TCP_ERR_TOUT,
+   TCP_ERR_RST,
 };
 
 /**
@@ -283,51 +297,150 @@ enum tcp_state {
  * @rport: Remote port, host byte order
  * @lport: Local port, host byte order
  *
+ * @priv:  User private data (not used by tcp module)
+ *
+ * @max_retry_count:   Maximum retransmit attempts (default 3)
+ * @initial_timeout:   Timeout from initial TX to reTX (default 2 sec)
+ * @rx_inactiv_timeout:Maximum time from last rx till connection drop
+ *   (default 30 sec)
+ *
+ * @on_closed: User callback, called just before destroying TCP stream
+ * @on_established:User callback, called when TCP stream enters
+ *   TCP_ESTABLISHED state
+ * @on_rcv_nxt_update: User callback, called when all data in the segment
+ *   [0..rx_bytes - 1] was received
+ * @on_snd_una_update: User callback, called when all data in the segment
+ *   [0..tx_bytes - 1] were transferred and acknowledged
+ * @rx:User callback, called on receive of segment
+ *   [rx_offs..rx_offs+len-1]. If NULL -- all incoming data
+ *   will be ignored. User SHOULD store the segment and
+ *   return the number of accepted bytes.
+ *   WARNING: Previous segmengs may not be received yet
+ * @tx:User callback, called on transmit/retransmit of 
segment
+ *   [tx_offs..tx_offs+maxlen-1]. If NULL -- no data will
+ *   be transmitted. User SHOULD fill provided buffer and
+ *   return the number of bytes in the buffer.
+ *   WARNING: do not use tcp_stream_close() from this
+ * callback (it will break stream). Better use
+ * on_snd_una_update() callback for such purposes.
+ *
+ * @time_last_rx:  Arrival time of last valid incoming package (ticks)
+ * @time_start:Timeout start time (ticks)
+ * @time_delta:Timeout duration (ticks)
+ * @time_handler   Timeout handler for a stream
+ *
  * @state: TCP connection state
+ * @status:TCP stream status (OK or ERR)
+ *
+ * @fin_rx:Non-zero if TCP_FIN was received
+ * @fin_rx_seq:TCP sequence of rx FIN bit
+ * @fin_tx:Non-zero if TCP_FIN was sent (or planned to send)
+ * @fin_tx_seq:TCP sequence of tx FIN bit
+ *
+ * @iss:   Initial send sequence number
+ * @snd_una:   Send unacknowledged
+ * @snd_nxt:   Send next
+ * @snd_wnd:   Send window (in bytes)
+ * @snd_wl1:   Segment sequence number used for last window update
+ * @snd_wl2:   Segment acknowledgment number used for last window 
update
  *
  * @irs:   Initial receive sequence number
  * @rcv_nxt:   Receive next
+ * @rcv_wnd:   Receive window (in bytes)
  *
  * @loc_timestamp: Local timestamp
  * @rmt_timestamp: Remote timestamp
  *
+ * @rmt_win_scale: Remote window scale factor
+ *
  * @lost:  Used for SACK
+ *
+ * @retry_cnt: Number of retry attempts remaining. Only SYN, FIN
+ *   or DATA segments are tried to retransmit.
+ * @retry_timeout: Current retry timeout (ms)
+ * @retry_action:  TCP flags used for sending
+ * @retry_seq_num: TCP 

[PATCH 04/12] net/tcp: add connection info to tcp_stream structure

2024-06-27 Thread Mikhail Kshevetskiy
Changes:
 * Avoid use net_server_ip in tcp code, use tcp_stream data instead
 * Ignore packets from other connections if connection already created.
   This prevents us from connection break caused by other tcp stream.

Signed-off-by: Mikhail Kshevetskiy 
---
 include/net.h  |   5 +-
 include/net/tcp.h  |  57 +---
 net/fastboot_tcp.c |  46 
 net/net.c  |  12 ++---
 net/tcp.c  | 129 ++---
 net/wget.c |  52 +++---
 6 files changed, 201 insertions(+), 100 deletions(-)

diff --git a/include/net.h b/include/net.h
index ac511eab103..fe645245f0f 100644
--- a/include/net.h
+++ b/include/net.h
@@ -668,6 +668,7 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, 
int dport, int sport,
 /**
  * net_send_tcp_packet() - Transmit TCP packet.
  * @payload_len: length of payload
+ * @dhost: Destination host
  * @dport: Destination TCP port
  * @sport: Source TCP port
  * @action: TCP action to be performed
@@ -676,8 +677,8 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, 
int dport, int sport,
  *
  * Return: 0 on success, other value on failure
  */
-int net_send_tcp_packet(int payload_len, int dport, int sport, u8 action,
-   u32 tcp_seq_num, u32 tcp_ack_num);
+int net_send_tcp_packet(int payload_len, struct in_addr dhost, int dport,
+   int sport, u8 action, u32 tcp_seq_num, u32 tcp_ack_num);
 int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport,
int sport, int payload_len);
 
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 14aee64cb1c..f224d0cae2f 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -279,6 +279,9 @@ enum tcp_state {
 
 /**
  * struct tcp_stream - TCP data stream structure
+ * @rhost: Remote host, network byte order
+ * @rport: Remote port, host byte order
+ * @lport: Local port, host byte order
  *
  * @state: TCP connection state
  *
@@ -291,6 +294,10 @@ enum tcp_state {
  * @lost:  Used for SACK
  */
 struct tcp_stream {
+   struct in_addr  rhost;
+   u16 rport;
+   u16 lport;
+
/* TCP connection state */
enum tcp_state  state;
 
@@ -305,16 +312,53 @@ struct tcp_stream {
struct tcp_sack_v lost;
 };
 
-struct tcp_stream *tcp_stream_get(void);
+void tcp_init(void);
+
+typedef int tcp_incoming_filter(struct in_addr rhost,
+   u16 rport, u16 sport);
+
+/*
+ * This function sets user callback used to accept/drop incoming
+ * connections. Callback should:
+ *  + Check TCP stream endpoint and make connection verdict
+ *- return non-zero value to accept connection
+ *- return zero to drop connection
+ *
+ * WARNING: If callback is NOT defined, all incoming connections
+ *  will be dropped.
+ */
+void tcp_set_incoming_filter(tcp_incoming_filter *filter);
+
+/*
+ * tcp_stream_get -- Get or create TCP stream
+ * @is_new:if non-zero and no stream found, then create a new one
+ * @rhost: Remote host, network byte order
+ * @rport: Remote port, host byte order
+ * @lport: Local port, host byte order
+ *
+ * Returns: TCP stream structure or NULL (if not found/created)
+ */
+struct tcp_stream *tcp_stream_get(int is_new, struct in_addr rhost,
+ u16 rport, u16 lport);
+
+/*
+ * tcp_stream_connect -- Create new TCP stream for remote connection.
+ * @rhost: Remote host, network byte order
+ * @rport: Remote port, host byte order
+ *
+ * Returns: TCP new stream structure or NULL (if not created).
+ *  Random local port will be used.
+ */
+struct tcp_stream *tcp_stream_connect(struct in_addr rhost, u16 rport);
+
+enum tcp_state tcp_stream_get_state(struct tcp_stream *tcp);
 
-enum tcp_state tcp_get_tcp_state(struct tcp_stream *tcp);
-void tcp_set_tcp_state(struct tcp_stream *tcp, enum tcp_state new_state);
-int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport,
-  int sport, int payload_len,
+int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int payload_len,
   u8 action, u32 tcp_seq_num, u32 tcp_ack_num);
 
 /**
  * rxhand_tcp() - An incoming packet handler.
+ * @tcp: TCP stream
  * @pkt: pointer to the application packet
  * @dport: destination TCP port
  * @sip: source IP address
@@ -324,8 +368,7 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, 
int dport,
  * @action: TCP action (SYN, ACK, FIN, etc)
  * @len: packet length
  */
-typedef void rxhand_tcp(uchar *pkt, u16 dport,
-   struct in_addr sip, u16 sport,
+typedef void rxhand_tcp(struct tcp_stream *tcp, uchar *pkt,
u32 tcp_seq_num, u32 tcp_ack_num,
u8 action, unsigned int len);
 void tcp_set_tcp_handler(rxhand_tcp *f);
diff --git a/net/fastboot_tcp.c b/net/fastboot_tcp.c

[PATCH 05/12] net/tcp: rename ack_edge and seq_init to more common rcv_nxt and irs

2024-06-27 Thread Mikhail Kshevetskiy
Use the names from RFC 9293

Signed-off-by: Mikhail Kshevetskiy 
---
 include/net/tcp.h |  8 
 net/tcp.c | 32 
 2 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/include/net/tcp.h b/include/net/tcp.h
index f224d0cae2f..0694af9d5b1 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -285,8 +285,8 @@ enum tcp_state {
  *
  * @state: TCP connection state
  *
- * @seq_init:  Initial receive sequence number
- * @ack_edge:  Receive next
+ * @irs:   Initial receive sequence number
+ * @rcv_nxt:   Receive next
  *
  * @loc_timestamp: Local timestamp
  * @rmt_timestamp: Remote timestamp
@@ -301,8 +301,8 @@ struct tcp_stream {
/* TCP connection state */
enum tcp_state  state;
 
-   u32 seq_init;
-   u32 ack_edge;
+   u32 irs;
+   u32 rcv_nxt;
 
/* TCP option timestamp */
u32 loc_timestamp;
diff --git a/net/tcp.c b/net/tcp.c
index efa12c9e8d3..2a0dcc4e771 100644
--- a/net/tcp.c
+++ b/net/tcp.c
@@ -361,9 +361,9 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, 
int payload_len,
pkt_len = pkt_hdr_len + payload_len;
tcp_len = pkt_len - IP_HDR_SIZE;
 
-   tcp->ack_edge = tcp_ack_num;
+   tcp->rcv_nxt = tcp_ack_num;
/* TCP Header */
-   b->ip.hdr.tcp_ack = htonl(tcp->ack_edge);
+   b->ip.hdr.tcp_ack = htonl(tcp->rcv_nxt);
b->ip.hdr.tcp_src = htons(tcp->lport);
b->ip.hdr.tcp_dst = htons(tcp->rport);
b->ip.hdr.tcp_seq = htonl(tcp_seq_num);
@@ -397,10 +397,10 @@ int tcp_set_tcp_header(struct tcp_stream *tcp, uchar 
*pkt, int payload_len,
return pkt_hdr_len;
 }
 
-static void tcp_update_ack_edge(struct tcp_stream *tcp)
+static void tcp_update_rcv_nxt(struct tcp_stream *tcp)
 {
-   if (tcp_seq_cmp(tcp->ack_edge, tcp->lost.hill[0].l) >= 0) {
-   tcp->ack_edge = tcp->lost.hill[0].r;
+   if (tcp_seq_cmp(tcp->rcv_nxt, tcp->lost.hill[0].l) >= 0) {
+   tcp->rcv_nxt = tcp->lost.hill[0].r;
 
memmove(>lost.hill[0], >lost.hill[1],
(TCP_SACK_HILLS - 1) * sizeof(struct sack_edges));
@@ -435,7 +435,7 @@ void tcp_hole(struct tcp_stream *tcp, u32 tcp_seq_num, u32 
len)
tcp_seq_num = tcp->lost.hill[i].l;
}
if (tcp_seq_cmp(tcp->lost.hill[i].r, tcp_seq_num + len) >= 0) {
-   tcp_update_ack_edge(tcp);
+   tcp_update_rcv_nxt(tcp);
return;
}
 
@@ -464,12 +464,12 @@ void tcp_hole(struct tcp_stream *tcp, u32 tcp_seq_num, 
u32 len)
}
}
 
-   tcp_update_ack_edge(tcp);
+   tcp_update_rcv_nxt(tcp);
return;
}
 
if (i == TCP_SACK_HILLS) {
-   tcp_update_ack_edge(tcp);
+   tcp_update_rcv_nxt(tcp);
return;
}
 
@@ -490,7 +490,7 @@ void tcp_hole(struct tcp_stream *tcp, u32 tcp_seq_num, u32 
len)
tcp->lost.hill[i].r = tcp_seq_num + len;
tcp->lost.len = TCP_OPT_LEN_2 + cnt * TCP_OPT_LEN_8;
 
-   tcp_update_ack_edge(tcp);
+   tcp_update_rcv_nxt(tcp);
 };
 
 /**
@@ -567,8 +567,8 @@ static u8 tcp_state_machine(struct tcp_stream *tcp, u8 
tcp_flags,
debug_cond(DEBUG_INT_STATE, "TCP CLOSED %x\n", tcp_flags);
if (tcp_syn) {
action = TCP_SYN | TCP_ACK;
-   tcp->seq_init = tcp_seq_num;
-   tcp->ack_edge = tcp_seq_num + 1;
+   tcp->irs = tcp_seq_num;
+   tcp->rcv_nxt = tcp_seq_num + 1;
tcp->lost.len = TCP_OPT_LEN_2;
tcp->state = TCP_SYN_RECEIVED;
} else if (tcp_ack || tcp_fin) {
@@ -584,8 +584,8 @@ static u8 tcp_state_machine(struct tcp_stream *tcp, u8 
tcp_flags,
tcp->state = TCP_CLOSE_WAIT;
} else if (tcp_ack || (tcp_syn && tcp_ack)) {
action |= TCP_ACK;
-   tcp->seq_init = tcp_seq_num;
-   tcp->ack_edge = tcp_seq_num + 1;
+   tcp->irs = tcp_seq_num;
+   tcp->rcv_nxt = tcp_seq_num + 1;
tcp->state = TCP_ESTABLISHED;
 
if (tcp_syn && tcp_ack)
@@ -634,7 +634,7 @@ static u8 tcp_state_machine(struct tcp_stream *tcp, u8 
tcp_flags,
case TCP_FIN_WAIT_1:
debug_cond(DEBUG_INT_STATE, "TCP_FIN_WAIT_1 (%x)\n", tcp_flags);
if (tcp_fin) {
-   tcp->ack_edge++;
+   tcp->rcv_nxt++;
action = TCP_ACK | TCP_FIN;
tcp->state = TCP_FIN_WAIT_2;
}
@@ -749,7 +749,7 @@ void 

[PATCH 03/12] net/tcp: preparing for multiple connections

2024-06-27 Thread Mikhail Kshevetskiy
no functional changes, just put connection specific data
into a tcp_stream structure

Signed-off-by: Mikhail Kshevetskiy 
---
 include/net/tcp.h |  37 +++-
 net/net.c |  11 ++-
 net/tcp.c | 231 +++---
 net/wget.c|   3 +-
 4 files changed, 163 insertions(+), 119 deletions(-)

diff --git a/include/net/tcp.h b/include/net/tcp.h
index c29d4ce24a7..14aee64cb1c 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -277,9 +277,40 @@ enum tcp_state {
TCP_FIN_WAIT_2
 };
 
-enum tcp_state tcp_get_tcp_state(void);
-void tcp_set_tcp_state(enum tcp_state new_state);
-int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
+/**
+ * struct tcp_stream - TCP data stream structure
+ *
+ * @state: TCP connection state
+ *
+ * @seq_init:  Initial receive sequence number
+ * @ack_edge:  Receive next
+ *
+ * @loc_timestamp: Local timestamp
+ * @rmt_timestamp: Remote timestamp
+ *
+ * @lost:  Used for SACK
+ */
+struct tcp_stream {
+   /* TCP connection state */
+   enum tcp_state  state;
+
+   u32 seq_init;
+   u32 ack_edge;
+
+   /* TCP option timestamp */
+   u32 loc_timestamp;
+   u32 rmt_timestamp;
+
+   /* TCP sliding window control used to request re-TX */
+   struct tcp_sack_v lost;
+};
+
+struct tcp_stream *tcp_stream_get(void);
+
+enum tcp_state tcp_get_tcp_state(struct tcp_stream *tcp);
+void tcp_set_tcp_state(struct tcp_stream *tcp, enum tcp_state new_state);
+int tcp_set_tcp_header(struct tcp_stream *tcp, uchar *pkt, int dport,
+  int sport, int payload_len,
   u8 action, u32 tcp_seq_num, u32 tcp_ack_num);
 
 /**
diff --git a/net/net.c b/net/net.c
index 0fb2d250773..8f076fa18e3 100644
--- a/net/net.c
+++ b/net/net.c
@@ -416,7 +416,7 @@ int net_init(void)
/* Only need to setup buffer pointers once. */
first_call = 0;
if (IS_ENABLED(CONFIG_PROT_TCP))
-   tcp_set_tcp_state(TCP_CLOSED);
+   tcp_set_tcp_state(tcp_stream_get(), TCP_CLOSED);
}
 
return net_init_loop();
@@ -917,6 +917,9 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, 
int dport, int sport,
uchar *pkt;
int eth_hdr_size;
int pkt_hdr_size;
+#if defined(CONFIG_PROT_TCP)
+   struct tcp_stream *tcp;
+#endif
 
/* make sure the net_tx_packet is initialized (net_init() was called) */
assert(net_tx_packet != NULL);
@@ -943,8 +946,12 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, 
int dport, int sport,
break;
 #if defined(CONFIG_PROT_TCP)
case IPPROTO_TCP:
+   tcp = tcp_stream_get();
+   if (tcp == NULL)
+   return -EINVAL;
+
pkt_hdr_size = eth_hdr_size
-   + tcp_set_tcp_header(pkt + eth_hdr_size, dport, sport,
+   + tcp_set_tcp_header(tcp, pkt + eth_hdr_size, dport, 
sport,
 payload_len, action, tcp_seq_num,
 tcp_ack_num);
break;
diff --git a/net/tcp.c b/net/tcp.c
index 228e1e4872c..80a161838f5 100644
--- a/net/tcp.c
+++ b/net/tcp.c
@@ -25,19 +25,8 @@
 #include 
 #include 
 
-/*
- * TCP sliding window  control used by us to request re-TX
- */
-static struct tcp_sack_v tcp_lost;
-
-/* TCP option timestamp */
-static u32 loc_timestamp;
-static u32 rmt_timestamp;
-
-static u32 tcp_seq_init;
-static u32 tcp_ack_edge;
-
 static int tcp_activity_count;
+static struct tcp_stream tcp_stream;
 
 /*
  * TCP lengths are stored as a rounded up number of 32 bit words.
@@ -49,9 +38,6 @@ static int tcp_activity_count;
 #define SHIFT_TO_TCPHDRLEN_FIELD(x) ((x) << 4)
 #define GET_TCP_HDR_LEN_IN_BYTES(x) ((x) >> 2)
 
-/* TCP connection state */
-static enum tcp_state current_tcp_state;
-
 /* Current TCP RX packet handler */
 static rxhand_tcp *tcp_packet_handler;
 
@@ -61,22 +47,30 @@ static inline s32 tcp_seq_cmp(u32 a, u32 b)
 }
 
 /**
- * tcp_get_tcp_state() - get current TCP state
+ * tcp_get_tcp_state() - get TCP stream state
+ * @tcp: tcp stream
  *
- * Return: Current TCP state
+ * Return: TCP stream state
  */
-enum tcp_state tcp_get_tcp_state(void)
+enum tcp_state tcp_get_tcp_state(struct tcp_stream *tcp)
 {
-   return current_tcp_state;
+   return tcp->state;
 }
 
 /**
- * tcp_set_tcp_state() - set current TCP state
+ * tcp_set_tcp_state() - set TCP stream state
+ * @tcp: tcp stream
  * @new_state: new TCP state
  */
-void tcp_set_tcp_state(enum tcp_state new_state)
+void tcp_set_tcp_state(struct tcp_stream *tcp,
+  enum tcp_state new_state)
 {
-   current_tcp_state = new_state;
+   tcp->state = new_state;
+}
+
+struct tcp_stream *tcp_stream_get(void)
+{
+   return _stream;
 

[PATCH 02/12] net/tcp: fix selective acknowledge

2024-06-27 Thread Mikhail Kshevetskiy
Current code assume that all (except last) packets are of the same size.
This is definitely wrong. Replace SACK code with a new one, that does
not rely on this assumption. Also this code uses less memory.

Signed-off-by: Mikhail Kshevetskiy 
---
 net/tcp.c | 200 +++---
 1 file changed, 86 insertions(+), 114 deletions(-)

diff --git a/net/tcp.c b/net/tcp.c
index c9bcd364ee3..228e1e4872c 100644
--- a/net/tcp.c
+++ b/net/tcp.c
@@ -39,21 +39,6 @@ static u32 tcp_ack_edge;
 
 static int tcp_activity_count;
 
-/*
- * Search for TCP_SACK and review the comments before the code section
- * TCP_SACK is the number of packets at the front of the stream
- */
-
-enum pkt_state {PKT, NOPKT};
-struct sack_r {
-   struct sack_edges se;
-   enum pkt_state st;
-};
-
-static struct sack_r edge_a[TCP_SACK];
-static unsigned int sack_idx;
-static unsigned int prev_len;
-
 /*
  * TCP lengths are stored as a rounded up number of 32 bit words.
  * Add 3 to length round up, rounded, then divided into the
@@ -70,6 +55,11 @@ static enum tcp_state current_tcp_state;
 /* Current TCP RX packet handler */
 static rxhand_tcp *tcp_packet_handler;
 
+static inline s32 tcp_seq_cmp(u32 a, u32 b)
+{
+   return (s32)(a - b);
+}
+
 /**
  * tcp_get_tcp_state() - get current TCP state
  *
@@ -268,6 +258,7 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, 
int payload_len,
action = TCP_FIN;
current_tcp_state = TCP_FIN_WAIT_1;
} else {
+   tcp_lost.len = TCP_OPT_LEN_2;
current_tcp_state = TCP_SYN_SENT;
}
break;
@@ -354,6 +345,20 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, 
int payload_len,
return pkt_hdr_len;
 }
 
+static void tcp_update_ack_edge(void)
+{
+   if (tcp_seq_cmp(tcp_ack_edge, tcp_lost.hill[0].l) >= 0) {
+   tcp_ack_edge = tcp_lost.hill[0].r;
+
+   memmove(_lost.hill[0], _lost.hill[1],
+   (TCP_SACK_HILLS - 1) * sizeof(struct sack_edges));
+
+   tcp_lost.len -= TCP_OPT_LEN_8;
+   tcp_lost.hill[TCP_SACK_HILLS - 1].l = TCP_O_NOP;
+   tcp_lost.hill[TCP_SACK_HILLS - 1].r = TCP_O_NOP;
+   }
+}
+
 /**
  * tcp_hole() - Selective Acknowledgment (Essential for fast stream transfer)
  * @tcp_seq_num: TCP sequence start number
@@ -361,106 +366,79 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, 
int payload_len,
  */
 void tcp_hole(u32 tcp_seq_num, u32 len)
 {
-   u32 idx_sack, sack_in;
-   u32 sack_end = TCP_SACK - 1;
-   u32 hill = 0;
-   enum pkt_state expect = PKT;
-   u32 seq = tcp_seq_num - tcp_seq_init;
-   u32 hol_l = tcp_ack_edge - tcp_seq_init;
-   u32 hol_r = 0;
-
-   /* Place new seq number in correct place in receive array */
-   if (prev_len == 0)
-   prev_len = len;
-
-   idx_sack = sack_idx + ((tcp_seq_num - tcp_ack_edge) / prev_len);
-   if (idx_sack < TCP_SACK) {
-   edge_a[idx_sack].se.l = tcp_seq_num;
-   edge_a[idx_sack].se.r = tcp_seq_num + len;
-   edge_a[idx_sack].st = PKT;
+   int i, j, cnt, cnt_move;
 
-   /*
-* The fin (last) packet is not the same length as data
-* packets, and if it's length is recorded and used for
-*  array index calculation, calculation breaks.
-*/
-   if (prev_len < len)
-   prev_len = len;
-   }
+   cnt = (tcp_lost.len - TCP_OPT_LEN_2) / TCP_OPT_LEN_8;
+   for (i = 0; i < cnt; i++) {
+   if (tcp_seq_cmp(tcp_lost.hill[i].r, tcp_seq_num) < 0)
+   continue;
+   if (tcp_seq_cmp(tcp_lost.hill[i].l, tcp_seq_num + len) > 0)
+   break;
 
-   debug_cond(DEBUG_DEV_PKT,
-  "TCP 1 seq %d, edg %d, len %d, sack_idx %d, sack_end %d\n",
-   seq, hol_l, len, sack_idx, sack_end);
+   if (tcp_seq_cmp(tcp_lost.hill[i].l, tcp_seq_num) > 0)
+   tcp_lost.hill[i].l = tcp_seq_num;
+   if (tcp_seq_cmp(tcp_lost.hill[i].l, tcp_seq_num) < 0) {
+   len += tcp_seq_num - tcp_lost.hill[i].l;
+   tcp_seq_num = tcp_lost.hill[i].l;
+   }
+   if (tcp_seq_cmp(tcp_lost.hill[i].r, tcp_seq_num + len) >= 0) {
+   tcp_update_ack_edge();
+   return;
+   }
 
-   /* Right edge of contiguous stream, is the left edge of first hill */
-   hol_l = tcp_seq_num - tcp_seq_init;
-   hol_r = hol_l + len;
+   /* check overlapping with next hills */
+   cnt_move = 0;
+   tcp_lost.hill[i].r = tcp_seq_num + len;
+   for (j = i + 1; j < cnt; j++) {
+   if 

[PATCH 01/12] net/tcp: fix TCP options processing

2024-06-27 Thread Mikhail Kshevetskiy
Current TCP code may miss an option if TCP_O_NOP option was used before
it for proper aligning.

Signed-off-by: Mikhail Kshevetskiy 
---
 net/tcp.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/tcp.c b/net/tcp.c
index a713e1dd609..c9bcd364ee3 100644
--- a/net/tcp.c
+++ b/net/tcp.c
@@ -476,7 +476,7 @@ void tcp_parse_options(uchar *o, int o_len)
 * NOPs are options with a zero length, and thus are special.
 * All other options have length fields.
 */
-   for (p = o; p < (o + o_len); p = p + p[1]) {
+   for (p = o; p < (o + o_len); ) {
if (!p[1])
return; /* Finished processing options */
 
@@ -491,12 +491,14 @@ void tcp_parse_options(uchar *o, int o_len)
case TCP_O_TS:
tsopt = (struct tcp_t_opt *)p;
rmt_timestamp = tsopt->t_snd;
-   return;
+   break;
}
 
/* Process optional NOPs */
if (p[0] == TCP_O_NOP)
p++;
+   else
+   p += p[1];
}
 }
 
-- 
2.43.0



Re: [PATCH v1 1/1] include: configs: tegra-common-post: make usb first boot target

2024-06-27 Thread Svyatoslav Ryhel
чт, 27 черв. 2024 р. о 14:36 Thierry Reding  пише:
>
> On Thu Jun 27, 2024 at 12:27 PM CEST, Svyatoslav Ryhel wrote:
> > вт, 18 черв. 2024 р. о 17:16 Svyatoslav  пише:
> > >
> > >
> > >
> > > 18 червня 2024 р. 15:23:09 GMT+03:00, Thierry Reding  
> > > написав(-ла):
> > > >On Tue Jun 18, 2024 at 2:00 PM CEST, Svyatoslav Ryhel wrote:
> > > >> This ensures that the device can boot from a USB device prior to MMC. 
> > > >> Useful
> > > >> cases are when installing a new OS from USB while MMC still has a 
> > > >> working OS
> > > >> configuration or if the OS configuration is broken in late boot stages
> > > >> (kernel boots but the system does not start).
> > > >>
> > > >> Signed-off-by: Svyatoslav Ryhel 
> > > >> ---
> > > >>  include/configs/tegra-common-post.h | 2 +-
> > > >>  1 file changed, 1 insertion(+), 1 deletion(-)
> > > >
> > > >What's the implication of this if no USB mass storage device is found?
> > > >How does this behave when USB cannot be read or booting from it doesn't
> > > >work?
> > > >
> > > >I vaguely recall that boot order doesn't always proceed, though
> > > >admittedly I haven't tested all of these edge-cases in a long time.
> > > >
> > > >Thierry
> > >
> > > If no USB mass storage is found bootflow will continue with the next
> > > device in the list (mmc1) with co-responding info that booting from
> > > usb failed. I have tested this on lg p895 which has only mmc0 and
> > > with asus transformers which have usb, mmc0 and mmc1 in all
> > > possible configurations. I did not have booting issues whatsoever.
> > > ATM, transformers use boot order which I have proposed in this
> > > commit.
> > >
> > > Best regards,
> > > Svyatoslav R.
> >
> > Thierry,
> >
> > Since you have not responded to my statement above I assume that
> > you are fine with applying this change. In case you have any
> > objections please answer as soon as you can since I am planning to
> > include it into merge request for the next merge window.
>
> Sorry, I had meant to reply to this. I have no objections if this was
> properly tested and there's a reasonable fallback that works.
>

Np. Thanks for feedback!

> Thierry


Re: [PATCH v1 1/1] include: configs: tegra-common-post: make usb first boot target

2024-06-27 Thread Thierry Reding
On Thu Jun 27, 2024 at 12:27 PM CEST, Svyatoslav Ryhel wrote:
> вт, 18 черв. 2024 р. о 17:16 Svyatoslav  пише:
> >
> >
> >
> > 18 червня 2024 р. 15:23:09 GMT+03:00, Thierry Reding  
> > написав(-ла):
> > >On Tue Jun 18, 2024 at 2:00 PM CEST, Svyatoslav Ryhel wrote:
> > >> This ensures that the device can boot from a USB device prior to MMC. 
> > >> Useful
> > >> cases are when installing a new OS from USB while MMC still has a 
> > >> working OS
> > >> configuration or if the OS configuration is broken in late boot stages
> > >> (kernel boots but the system does not start).
> > >>
> > >> Signed-off-by: Svyatoslav Ryhel 
> > >> ---
> > >>  include/configs/tegra-common-post.h | 2 +-
> > >>  1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > >What's the implication of this if no USB mass storage device is found?
> > >How does this behave when USB cannot be read or booting from it doesn't
> > >work?
> > >
> > >I vaguely recall that boot order doesn't always proceed, though
> > >admittedly I haven't tested all of these edge-cases in a long time.
> > >
> > >Thierry
> >
> > If no USB mass storage is found bootflow will continue with the next
> > device in the list (mmc1) with co-responding info that booting from
> > usb failed. I have tested this on lg p895 which has only mmc0 and
> > with asus transformers which have usb, mmc0 and mmc1 in all
> > possible configurations. I did not have booting issues whatsoever.
> > ATM, transformers use boot order which I have proposed in this
> > commit.
> >
> > Best regards,
> > Svyatoslav R.
>
> Thierry,
>
> Since you have not responded to my statement above I assume that
> you are fine with applying this change. In case you have any
> objections please answer as soon as you can since I am planning to
> include it into merge request for the next merge window.

Sorry, I had meant to reply to this. I have no objections if this was
properly tested and there's a reasonable fallback that works.

Thierry


[PATCH 3/3] dm: mmc: fix driver rebinding in the case of dtb reloading

2024-06-27 Thread Mikhail Kshevetskiy
Rebinding of the mmc driver causes reregistration of block device.
Thus second mmc device appears and the first becomes broken.

Fix an issue by using already registered block device instead of
registering a new one.

Signed-off-by: Mikhail Kshevetskiy 
---
 drivers/mmc/mmc-uclass.c | 16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 24170c59ecc..403d20dad53 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -420,11 +420,17 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const 
struct mmc_config *cfg)
/* Use the fixed index with aliases node's index */
debug("%s: alias devnum=%d\n", __func__, dev_seq(dev));
 
-   ret = blk_create_devicef(dev, "mmc_blk", "blk", UCLASS_MMC,
-dev_seq(dev), DEFAULT_BLKSZ, 0, );
-   if (ret) {
-   debug("Cannot create block device\n");
-   return ret;
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT_RESCAN)
+   device_find_first_child_by_uclass(dev, UCLASS_BLK, );
+   if (!bdev)
+#endif
+   {
+   ret = blk_create_devicef(dev, "mmc_blk", "blk", UCLASS_MMC,
+dev_seq(dev), DEFAULT_BLKSZ, 0, );
+   if (ret) {
+   debug("Cannot create block device\n");
+   return ret;
+   }
}
bdesc = dev_get_uclass_plat(bdev);
mmc->cfg = cfg;
-- 
2.43.0



[PATCH 2/3] dm: core: support dtb switching without devices/drivers unloading

2024-06-27 Thread Mikhail Kshevetskiy
Consider a case when we have several similar boards but leds & buttons
connected differently. Some of leds uses gpio, other pwm, third gpio over
spi bitbang. Also different board may have different gpio hogs. And last
but not least: board type stored inside a ubi volume.

We want a single u-boot image that will support all these boards (we are
not using SPL). So we need runtime dtb switching.

We can't use MULTI_DTB_FIT and DTB_RESELECT because they tries to switch
dtb too early when flash & ubi drivers are not loaded/activated.

The following code do runtime switching

ret = fdtdec_resetup();
if (!ret && rescan){
dm_uninit();
dm_init_and_scan(false);
}

but it have several nasty issues
 * additional code required to reinitialize console otherwise board will hang.
 * MTD subsystem is not cleared, we need to remove mtd partition before
   switching to new dtb
 * spi-nand flash will be named "spi-nand1" instead of "spi-nand0", thus
   flash becomes unusable
 * some drivers are unable to deinitialize properly (ex: network driver will
   not release mdio interface)
 * some memory will leak, because most of drivers assumes that it will never
   be unloaded

To avoid this nasty issues the following hack was implemented
 * Full DM and console reinitialization was skipped
 * Only missed device/subdevice added from new dtb during device scan.
 * Some driver renames their devices. As result we can't use device names
   to match old device node with a new one. The special field was added to
   struct udevice for this purposes.
 * Driver must be binded to the old device one more time to add missed
   subdevices.
 * uclass must be post_bind to the old device one more time to add missed
   subdevices.
 * We can't use old dtb anymore, so replace old device node with a new one
   for existing devices.

The following restrictions are present:
 * initial dtb MUST be a subset of a new one
 * old devices will NOT be reinitialised
 * no devices will be deleted or deactivated
 * only new devices will be added

Typical usage:
ret = fdtdec_resetup();
if (!ret && rescan)
dm_rescan();

The code was tested with: gpio, gpio_hog, leds, buttons.

Signed-off-by: Mikhail Kshevetskiy 
---
 drivers/core/device.c | 31 +++
 drivers/core/root.c   | 15 +++
 dts/Kconfig   |  8 
 include/dm/device.h   |  3 +++
 include/dm/root.h | 23 +++
 5 files changed, 80 insertions(+)

diff --git a/drivers/core/device.c b/drivers/core/device.c
index bf7f261cbce..4f575ca82e7 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -62,6 +62,34 @@ static int device_bind_common(struct udevice *parent, const 
struct driver *drv,
return ret;
}
 
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT_RESCAN)
+   if (parent) {
+   struct list_head*entry;
+   ofnode  dev_node;
+
+   list_for_each(entry, >child_head) {
+   dev = list_entry(entry, struct udevice, sibling_node);
+   dev_node = dev_ofnode(dev);
+   if ((dev->driver == drv) && (dev->uclass == uc) &&
+   (dev->driver_data == driver_data) &&
+   (strcmp(dev->node_name, ofnode_get_name(node)) == 
0))
+   {
+   ret = 0;
+   dev_set_ofnode(dev, node);
+   if (drv->bind)
+   ret = drv->bind(dev);
+
+   if (!ret && uc->uc_drv->post_bind)
+   ret = uc->uc_drv->post_bind(dev);
+
+   if (!ret && devp)
+   *devp = dev;
+   return ret;
+   }
+   }
+   }
+#endif
+
dev = calloc(1, sizeof(struct udevice));
if (!dev)
return -ENOMEM;
@@ -75,6 +103,9 @@ static int device_bind_common(struct udevice *parent, const 
struct driver *drv,
dev_set_plat(dev, plat);
dev->driver_data = driver_data;
dev->name = name;
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT_RESCAN)
+   dev->node_name = name;
+#endif
dev_set_ofnode(dev, node);
dev->parent = parent;
dev->driver = drv;
diff --git a/drivers/core/root.c b/drivers/core/root.c
index d4ae652bcfb..4bf1ff80636 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -340,6 +340,21 @@ static int dm_scan(bool pre_reloc_only)
return dm_probe_devices(gd->dm_root, pre_reloc_only);
 }
 
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT_RESCAN)
+int dm_rescan(void)
+{
+   int ret;
+
+   ret = dm_extended_scan(false);
+   if (ret) {
+   debug("dm_extended_scan() failed: %d\n", ret);
+   return ret;
+   }
+
+ 

[PATCH 1/3] fit_dtb: relocate whole fit dtb image instead of selected dtb only

2024-06-27 Thread Mikhail Kshevetskiy
U-Boot with linked fit dtb image may be loaded by a bootloader to
a low memory. On a later stage U-Boot will relocate itself and used
dtb.

There is no problem until we decide to reselect dtb on a later stage.
In this case dtb placed in the low memory address may be selected.
But this data can be overwritted by flash reading or network file
transfer. Thus we will use damaged dtb.

To fix it move the whole fit dtb image instead of just used dtb.

Signed-off-by: Mikhail Kshevetskiy 
---
 boot/boot_fit.c| 48 ++
 common/board_f.c   | 34 
 include/boot_fit.h |  8 
 3 files changed, 86 insertions(+), 4 deletions(-)

diff --git a/boot/boot_fit.c b/boot/boot_fit.c
index 9d394126563..e9aac61c6a8 100644
--- a/boot/boot_fit.c
+++ b/boot/boot_fit.c
@@ -13,6 +13,54 @@
 #include 
 #include 
 
+int dtb_fit_image_size(const void *fit)
+{
+   struct legacy_img_hdr   *header;
+   int fdt_size, blob_total_size;
+   int images, conf, node;
+   int blob_offset, blob_len;
+
+   header = (struct legacy_img_hdr *)fit;
+   if (image_get_magic(header) != FDT_MAGIC) {
+   debug("No FIT image appended to U-Boot\n");
+   return -EINVAL;
+   }
+
+   fdt_size = fdt_totalsize(fit);
+   fdt_size = (fdt_size + 3) & ~3;
+
+   conf = fdt_path_offset(fit, FIT_CONFS_PATH);
+   if (conf < 0) {
+   debug("%s: Cannot find /configurations node: %d\n", __func__, 
conf);
+   return -EINVAL;
+   }
+
+   images = fdt_path_offset(fit, FIT_IMAGES_PATH);
+   if (images < 0) {
+   debug("%s: Cannot find /images node: %d\n", __func__, images);
+   return -EINVAL;
+   }
+
+   blob_total_size = 0;
+   node = fdt_first_subnode(fit, images);
+   while (node >= 0) {
+   blob_offset = fdt_getprop_u32(fit, node, "data-offset");
+   if (blob_offset == FDT_ERROR)
+   return -ENOENT;
+
+   blob_len = fdt_getprop_u32(fit, node, "data-size");
+   if (blob_len < 0)
+   return blob_len;
+
+   if (blob_total_size < blob_offset + blob_len)
+   blob_total_size = blob_offset + blob_len;
+
+   node = fdt_next_subnode(fit, node);
+   }
+
+   return fdt_size + blob_total_size;
+}
+
 static int fdt_offset(const void *fit)
 {
int images, node, fdt_len, fdt_node, fdt_offset;
diff --git a/common/board_f.c b/common/board_f.c
index 039d6d712d0..89a1a0b563c 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -49,6 +49,7 @@
 #include 
 #include 
 #include 
+#include 
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -574,7 +575,24 @@ static int reserve_fdt(void)
 * section, then it will be relocated with other data.
 */
if (gd->fdt_blob) {
-   gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob), 32);
+   if (gd_multi_dtb_fit()) {
+   int dtb_fit_size = 
dtb_fit_image_size(gd_multi_dtb_fit());
+
+   if (dtb_fit_size < 0) {
+   /*
+* Fallback to default:
+*   - switch to non-multi dtb case 
(single dtb)
+*   - reserve space for current dtb 
only
+*/
+   gd_set_multi_dtb_fit(NULL);
+   gd->fdt_size = 
ALIGN(fdt_totalsize(gd->fdt_blob), 32);
+   } else {
+   /* reserve space for the whole dtb fit 
image */
+   gd->fdt_size = ALIGN(dtb_fit_size, 32);
+   }
+   } else {
+   gd->fdt_size = 
ALIGN(fdt_totalsize(gd->fdt_blob), 32);
+   }
 
gd->start_addr_sp = reserve_stack_aligned(gd->fdt_size);
gd->new_fdt = map_sysmem(gd->start_addr_sp, 
gd->fdt_size);
@@ -668,9 +686,17 @@ static int reloc_fdt(void)
 {
if (!IS_ENABLED(CONFIG_OF_EMBED)) {
if (gd->new_fdt) {
-   memcpy(gd->new_fdt, gd->fdt_blob,
-  fdt_totalsize(gd->fdt_blob));
-   gd->fdt_blob = gd->new_fdt;
+   if (gd_multi_dtb_fit()) {
+   memcpy(gd->new_fdt, gd_multi_dtb_fit(),
+  dtb_fit_image_size(gd_multi_dtb_fit()));
+   gd->fdt_blob = gd->new_fdt + (gd->fdt_blob -
+  gd_multi_dtb_fit());
+   

Re: [PATCH 1/2] spi: soft_spi: fix miso gpio property name

2024-06-27 Thread Fabio Estevam
On Thu, Jun 27, 2024 at 8:31 AM Mikhail Kshevetskiy
 wrote:
>
> Signed-off-by: Mikhail Kshevetskiy 
> ---
>  drivers/spi/soft_spi.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/spi/soft_spi.c b/drivers/spi/soft_spi.c
> index 0fa14339bdc..3fe62818a44 100644
> --- a/drivers/spi/soft_spi.c
> +++ b/drivers/spi/soft_spi.c
> @@ -272,7 +272,7 @@ static int soft_spi_probe(struct udevice *dev)
> ret = gpio_request_by_name(dev, "gpio-miso", 0, >miso,
>GPIOD_IS_IN);
> if (ret)
> -   ret = gpio_request_by_name(dev, "gpio-miso", 0, >miso,
> +   ret = gpio_request_by_name(dev, "miso-gpios", 0, >miso,

We should support the deprecated 'gpio-miso' property and the
preferred 'miso-gpios' one.

The same applies for  gpio-sck and gpio-mosi.


>GPIOD_IS_IN);
> if (ret)
> plat->flags |= SPI_MASTER_NO_RX;
> --
> 2.43.0
>


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

2024-06-27 Thread Kongyang Liu
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(>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?

Best regards
Kongyang Liu


[PATCH 2/2] led: Add dts property to specify blinking of the led

2024-06-27 Thread Mikhail Kshevetskiy
From: Michael Polyntsov 

The standard property

linux,default-trigger = "pattern";

used to get an effect. No blinking parameters can be set yet.

Signed-off-by: Michael Polyntsov 
Signed-off-by: Mikhail Kshevetskiy 
---
 drivers/led/led-uclass.c | 34 ++
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/drivers/led/led-uclass.c b/drivers/led/led-uclass.c
index b35964f2e99..645d0069efe 100644
--- a/drivers/led/led-uclass.c
+++ b/drivers/led/led-uclass.c
@@ -271,6 +271,9 @@ static int led_post_bind(struct udevice *dev)
 {
struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev);
const char *default_state;
+#ifdef CONFIG_LED_BLINK
+   const char *trigger;
+#endif
 
if (!uc_plat->label)
uc_plat->label = dev_read_string(dev, "label");
@@ -291,6 +294,13 @@ static int led_post_bind(struct udevice *dev)
else
return 0;
 
+#ifdef CONFIG_LED_BLINK
+   trigger = dev_read_string(dev, "linux,default-trigger");
+   if (trigger && !strncmp(trigger, "pattern", 7)) {
+   uc_plat->default_state = LEDST_BLINK;
+   }
+#endif
+
/*
 * In case the LED has default-state DT property, trigger
 * probe() to configure its default state during startup.
@@ -302,12 +312,28 @@ static int led_post_bind(struct udevice *dev)
 static int led_post_probe(struct udevice *dev)
 {
struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev);
+   int rc = 0;
 
-   if (uc_plat->default_state == LEDST_ON ||
-   uc_plat->default_state == LEDST_OFF)
-   led_set_state(dev, uc_plat->default_state);
+   switch (uc_plat->default_state) {
+   case LEDST_ON:
+   case LEDST_OFF:
+   rc = led_set_state(dev, uc_plat->default_state);
+   break;
+#ifdef CONFIG_LED_BLINK
+   case LEDST_BLINK: {
+   const int default_period_ms = 1000;
 
-   return 0;
+   rc = led_set_period(dev, default_period_ms);
+   if (rc == 0)
+   rc = led_set_state(dev, uc_plat->default_state);
+   break;
+   }
+#endif
+   default:
+   break;
+   }
+
+   return rc;
 }
 
 UCLASS_DRIVER(led) = {
-- 
2.43.0



[PATCH 1/2] led: Implement software led blinking

2024-06-27 Thread Mikhail Kshevetskiy
From: Michael Polyntsov 

If hardware (or driver) doesn't support leds blinking, it's
now possible to use software implementation of blinking instead.
This relies on cyclic functions.

Signed-off-by: Michael Polyntsov 
Signed-off-by: Mikhail Kshevetskiy 
---
 drivers/led/Kconfig  |   9 ++
 drivers/led/led-uclass.c | 190 ++-
 2 files changed, 195 insertions(+), 4 deletions(-)

diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig
index 9837960198d..4330f014239 100644
--- a/drivers/led/Kconfig
+++ b/drivers/led/Kconfig
@@ -73,6 +73,15 @@ config LED_BLINK
  This option enables support for this which adds slightly to the
  code size.
 
+config LED_SW_BLINK
+   bool "Support software LED blinking"
+   depends on LED_BLINK
+   select CYCLIC
+   help
+ Turns on led blinking implemented in the software, useful when
+ the hardware doesn't support led blinking. Does nothing if
+ driver supports blinking.
+
 config SPL_LED
bool "Enable LED support in SPL"
depends on SPL_DM
diff --git a/drivers/led/led-uclass.c b/drivers/led/led-uclass.c
index a4be56fc258..b35964f2e99 100644
--- a/drivers/led/led-uclass.c
+++ b/drivers/led/led-uclass.c
@@ -15,6 +15,10 @@
 #include 
 #include 
 
+#ifdef CONFIG_LED_SW_BLINK
+#include 
+#endif
+
 int led_bind_generic(struct udevice *parent, const char *driver_name)
 {
struct udevice *dev;
@@ -41,6 +45,7 @@ int led_get_by_label(const char *label, struct udevice **devp)
ret = uclass_get(UCLASS_LED, );
if (ret)
return ret;
+
uclass_foreach_dev(dev, uc) {
struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev);
 
@@ -52,14 +57,180 @@ int led_get_by_label(const char *label, struct udevice 
**devp)
return -ENODEV;
 }
 
-int led_set_state(struct udevice *dev, enum led_state_t state)
+#ifdef CONFIG_LED_SW_BLINK
+
+enum led_sw_blink_state_t {
+   LED_SW_BLINK_ST_OFF = 0,
+   LED_SW_BLINK_ST_ON = 1,
+   LED_SW_BLINK_ST_NONE = 2,
+};
+
+struct sw_blink_state {
+   struct udevice *dev;
+   enum led_sw_blink_state_t cur_blink_state;
+};
+
+static bool led_driver_supports_hw_blinking(const struct udevice *dev)
+{
+   struct led_ops *ops = led_get_ops(dev);
+
+   /*
+* We assume that if driver supports set_period, then it correctly
+* handles all other requests, for example, that
+* led_set_state(LEDST_BLINK) works correctly.
+*/
+   return ops->set_period != NULL;
+}
+
+static const char *led_sw_label_to_cyclic_func_name(const char *label)
+{
+#define MAX_NAME_LEN 50
+   static char cyclic_func_name[MAX_NAME_LEN] = {0};
+
+   snprintf(cyclic_func_name, MAX_NAME_LEN, "sw_blink_%s", label);
+   return cyclic_func_name;
+#undef MAX_NAME_LEN
+}
+
+static struct cyclic_info *led_sw_find_blinking_led(const char *label)
+{
+   struct cyclic_info *cyclic;
+   const char *cyclic_name;
+
+   cyclic_name = led_sw_label_to_cyclic_func_name(label);
+
+   hlist_for_each_entry(cyclic, cyclic_get_list(), list) {
+   if (strcmp(cyclic->name, cyclic_name) == 0)
+   return cyclic;
+   }
+
+   return NULL;
+}
+
+static bool led_sw_is_blinking(struct udevice *dev)
+{
+   struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev);
+   struct cyclic_info *cyclic = led_sw_find_blinking_led(uc_plat->label);
+
+   if (cyclic != NULL) {
+   struct sw_blink_state *state;
+
+   state = (struct sw_blink_state *)cyclic->ctx;
+   return state->cur_blink_state != LED_SW_BLINK_ST_NONE;
+   }
+
+   return false;
+}
+
+static void led_sw_blink(void *void_state)
+{
+   struct sw_blink_state *state = (struct sw_blink_state *)void_state;
+   struct udevice *dev = state->dev;
+   struct led_ops *ops = led_get_ops(dev);
+
+   switch (state->cur_blink_state) {
+   case LED_SW_BLINK_ST_OFF:
+   state->cur_blink_state = LED_SW_BLINK_ST_ON;
+   ops->set_state(dev, LEDST_ON);
+   break;
+   case LED_SW_BLINK_ST_ON:
+   state->cur_blink_state = LED_SW_BLINK_ST_OFF;
+   ops->set_state(dev, LEDST_OFF);
+   break;
+   case LED_SW_BLINK_ST_NONE:
+   /*
+* led_set_period has been called, but
+* led_set_state(LDST_BLINK) has not yet,
+* so doing nothing
+*/
+   break;
+   }
+}
+
+static void led_sw_free_cyclic(struct cyclic_info *cyclic)
+{
+   free(cyclic->ctx);
+   cyclic_unregister(cyclic);
+}
+
+static int led_sw_set_period(struct udevice *dev, int period_ms)
+{
+   struct cyclic_info *cyclic;
+   struct sw_blink_state *state;
+   struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev);
+   const char *cyclic_func_name;
+
+   state = malloc(sizeof(struct sw_blink_state));

[PATCH] gpt: allow spaces in partition list

2024-06-27 Thread Mikhail Kshevetskiy
This allows spliting partition list to several lines in environment file

ex:

gpt_partition_list=
name=boot1,size=5MiB,start=0x10;
name=boot2,size=5MiB;
name=rootfs1,size=70MiB;
name=rootfs2,size=70MiB;
name=overlay1,size=20MiB;
name=overlay2,size=20MiB;
name=art,size=4MiB;

Signed-off-by: Mikhail Kshevetskiy 
---
 cmd/gpt.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/cmd/gpt.c b/cmd/gpt.c
index 7aaf1889a5a..2b29ab98ccc 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -117,6 +117,7 @@ static char *extract_val(const char *str, const char *key)
k = strsep(, "=");
if (!k)
break;
+   k += strspn(k, " \t");
if  (strcmp(k, key) == 0) {
new = strdup(v);
break;
@@ -151,6 +152,7 @@ static bool found_key(const char *str, const char *key)
k = strsep(, ",");
if (!k)
break;
+   k += strspn(k, " \t");
if  (strcmp(k, key) == 0) {
result = true;
break;
-- 
2.43.0



[PATCH 3/3] cmd: mtd: add nandtest command support

2024-06-27 Thread Mikhail Kshevetskiy
This patch implements readonly test of nand flashes.

Signed-off-by: Mikhail Kshevetskiy 
---
 cmd/Kconfig |   6 ++
 cmd/mtd.c   | 203 
 2 files changed, 209 insertions(+)

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 0685b598679..d5cc6de93cd 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1430,6 +1430,12 @@ config CMD_MTD_TORTURE
help
  MTD torture command support.
 
+config CMD_MTD_NANDTEST
+   bool "mtd nandtest"
+   depends on CMD_MTD
+   help
+ MTD nandtest command support.
+
 config CMD_MUX
bool "mux"
depends on MULTIPLEXER
diff --git a/cmd/mtd.c b/cmd/mtd.c
index df4130b90d1..bb89e783d54 100644
--- a/cmd/mtd.c
+++ b/cmd/mtd.c
@@ -932,6 +932,202 @@ out_put_mtd:
 }
 #endif
 
+#ifdef CONFIG_CMD_MTD_NANDTEST
+enum nandtest_status {
+   NANDTEST_STATUS_UNKNOWN = 0,
+   NANDTEST_STATUS_NONECC_READ_FAIL,
+   NANDTEST_STATUS_ECC_READ_FAIL,
+   NANDTEST_STATUS_BAD_BLOCK,
+   NANDTEST_STATUS_BITFLIP_ABOVE_MAX,
+   NANDTEST_STATUS_BITFLIP_MISMATCH,
+   NANDTEST_STATUS_BITFLIP_MAX,
+   NANDTEST_STATUS_OK,
+};
+
+static enum nandtest_status nandtest_block_check(struct mtd_info *mtd,
+loff_t off, size_t blocksize)
+{
+   struct mtd_oob_ops  ops = {};
+   u_char  *buf;
+   int i, d, ret, len, pos, cnt, max;
+
+   if (blocksize % mtd->writesize != 0) {
+   printf("\r  block at %llx: bad block size\n", off);
+   return NANDTEST_STATUS_UNKNOWN;
+   }
+
+   buf = malloc_cache_aligned(2 * blocksize);
+   if (buf == NULL) {
+   printf("\r  block at %llx: can't allocate memory\n", off);
+   return NANDTEST_STATUS_UNKNOWN;
+   }
+
+   ops.mode = MTD_OPS_RAW;
+   ops.len = blocksize;
+   ops.datbuf = buf;
+   ops.ooblen = 0;
+   ops.oobbuf = NULL;
+
+   if (mtd->_read_oob)
+   ret = mtd->_read_oob(mtd, off, );
+   else
+   ret = mtd->_read(mtd, off, ops.len, , ops.datbuf);
+
+   if (ret != 0) {
+   free(buf);
+   printf("\r  block at %llx: non-ecc reading error %d\n",
+  off, ret);
+   return NANDTEST_STATUS_NONECC_READ_FAIL;
+   }
+
+   ops.mode = MTD_OPS_AUTO_OOB;
+   ops.datbuf = buf + blocksize;
+
+   if (mtd->_read_oob)
+   ret = mtd->_read_oob(mtd, off, );
+   else
+   ret = mtd->_read(mtd, off, ops.len, , ops.datbuf);
+
+   if (ret == -EBADMSG) {
+   free(buf);
+   printf("\r  block at %llx: bad block\n", off);
+   return NANDTEST_STATUS_BAD_BLOCK;
+   }
+
+   if (ret < 0) {
+   free(buf);
+   printf("\r  block at %llx: ecc reading error %d\n", off, ret);
+   return NANDTEST_STATUS_ECC_READ_FAIL;
+   }
+
+   if (mtd->ecc_strength == 0) {
+   free(buf);
+   return NANDTEST_STATUS_OK;
+   }
+
+   if (ret > mtd->ecc_strength) {
+   free(buf);
+   printf("\r  block at %llx: returned bit-flips value %d "
+  "is above maximum value %d\n",
+  off, ret, mtd->ecc_strength);
+   return NANDTEST_STATUS_BITFLIP_ABOVE_MAX;
+   }
+
+   max = 0;
+   pos = 0;
+   len = blocksize;
+   while (len > 0) {
+   cnt = 0;
+   for (i = 0; i < mtd->ecc_step_size; i++) {
+   d = buf[pos + i] ^ buf[blocksize + pos + i];
+   if (d == 0)
+   continue;
+
+   while (d > 0) {
+   d &= (d - 1);
+   cnt++;
+   }
+   }
+   if (cnt > max)
+   max = cnt;
+
+   len -= mtd->ecc_step_size;
+   pos += mtd->ecc_step_size;
+   }
+
+   free(buf);
+
+   if (max > ret) {
+   printf("\r  block at %llx: bitflip mismatch, "
+  "read %d but actual %d\n", off, ret, max);
+   return NANDTEST_STATUS_BITFLIP_MISMATCH;
+   }
+
+   if (ret == mtd->ecc_strength) {
+   printf("\r  block at %llx: max bitflip reached, "
+  "block is unreliable\n", off);
+   return NANDTEST_STATUS_BITFLIP_MAX;
+   }
+
+   return NANDTEST_STATUS_OK;
+}
+
+static int do_mtd_nandtest(struct cmd_tbl *cmdtp, int flag, int argc,
+  char *const argv[])
+{
+   struct mtd_info *mtd;
+   loff_t  off, len;
+   int stat[NANDTEST_STATUS_OK + 1];
+   enum nandtest_statusret;
+   size_t  block_size;
+
+   if (argc < 2)
+   return CMD_RET_USAGE;
+
+   

[PATCH 2/3] cmd: mtd: add torture command support

2024-06-27 Thread Mikhail Kshevetskiy
Some nand flashes (like spi-nand one) are registered with mtd
subsystem only, thus nand command can't be used to work with
such flashes. As result some functionality is missing.

This patch implements 'nand torture' functionality for mtd command.

Signed-off-by: Mikhail Kshevetskiy 
---
 cmd/Kconfig |   6 ++
 cmd/mtd.c   | 196 
 2 files changed, 202 insertions(+)

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 70c2d6a2dda..0685b598679 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1424,6 +1424,12 @@ config CMD_MTD_MARKBAD
help
  MTD markbad command support.
 
+config CMD_MTD_TORTURE
+   bool "mtd torture"
+   depends on CMD_MTD
+   help
+ MTD torture command support.
+
 config CMD_MUX
bool "mux"
depends on MULTIPLEXER
diff --git a/cmd/mtd.c b/cmd/mtd.c
index 18f00493780..df4130b90d1 100644
--- a/cmd/mtd.c
+++ b/cmd/mtd.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -743,6 +744,194 @@ out_put_mtd:
 }
 #endif
 
+#ifdef CONFIG_CMD_MTD_TORTURE
+/**
+ * nand_check_pattern:
+ *
+ * Check if buffer contains only a certain byte pattern.
+ *
+ * @param buf buffer to check
+ * @param patt the pattern to check
+ * @param size buffer size in bytes
+ * Return: 1 if there are only patt bytes in buf
+ * 0 if something else was found
+ */
+static int nand_check_pattern(const u_char *buf, u_char patt, int size)
+{
+   int i;
+
+   for (i = 0; i < size; i++)
+   if (buf[i] != patt)
+   return 0;
+   return 1;
+}
+
+/**
+ * nand_torture:
+ *
+ * Torture a block of NAND flash.
+ * This is useful to determine if a block that caused a write error is still
+ * good or should be marked as bad.
+ *
+ * @param mtd nand mtd instance
+ * @param offset offset in flash
+ * Return: 0 if the block is still good
+ */
+static int nand_torture(struct mtd_info *mtd, loff_t offset)
+{
+   u_char patterns[] = {0xa5, 0x5a, 0x00};
+   struct erase_info instr = {
+   .mtd = mtd,
+   .addr = offset,
+   .len = mtd->erasesize,
+   };
+   size_t retlen;
+   int err, ret = -1, i, patt_count;
+   u_char *buf;
+
+   if ((offset & (mtd->erasesize - 1)) != 0) {
+   puts("Attempt to torture a block at a non block-aligned 
offset\n");
+   return -EINVAL;
+   }
+
+   if (offset + mtd->erasesize > mtd->size) {
+   puts("Attempt to torture a block outside the flash area\n");
+   return -EINVAL;
+   }
+
+   patt_count = ARRAY_SIZE(patterns);
+
+   buf = malloc_cache_aligned(mtd->erasesize);
+   if (buf == NULL) {
+   puts("Out of memory for erase block buffer\n");
+   return -ENOMEM;
+   }
+
+   for (i = 0; i < patt_count; i++) {
+   err = mtd_erase(mtd, );
+   if (err) {
+   printf("%s: erase() failed for block at 0x%llx: %d\n",
+  mtd->name, instr.addr, err);
+   goto out;
+   }
+
+   /* Make sure the block contains only 0xff bytes */
+   err = mtd_read(mtd, offset, mtd->erasesize, , buf);
+   if ((err && err != -EUCLEAN) || retlen != mtd->erasesize) {
+   printf("%s: read() failed for block at 0x%llx: %d\n",
+  mtd->name, instr.addr, err);
+   goto out;
+   }
+
+   err = nand_check_pattern(buf, 0xff, mtd->erasesize);
+   if (!err) {
+   printf("Erased block at 0x%llx, but a non-0xff byte was 
found\n",
+  offset);
+   ret = -EIO;
+   goto out;
+   }
+
+   /* Write a pattern and check it */
+   memset(buf, patterns[i], mtd->erasesize);
+   err = mtd_write(mtd, offset, mtd->erasesize, , buf);
+   if (err || retlen != mtd->erasesize) {
+   printf("%s: write() failed for block at 0x%llx: %d\n",
+  mtd->name, instr.addr, err);
+   goto out;
+   }
+
+   err = mtd_read(mtd, offset, mtd->erasesize, , buf);
+   if ((err && err != -EUCLEAN) || retlen != mtd->erasesize) {
+   printf("%s: read() failed for block at 0x%llx: %d\n",
+  mtd->name, instr.addr, err);
+   goto out;
+   }
+
+   err = nand_check_pattern(buf, patterns[i], mtd->erasesize);
+   if (!err) {
+   printf("Pattern 0x%.2x checking failed for block at "
+  "0x%llx\n", patterns[i], offset);
+   ret = -EIO;
+   goto out;
+   }
+   }
+
+   ret = 0;
+
+out:
+ 

[PATCH 1/3] cmd: mtd: add markbad command support

2024-06-27 Thread Mikhail Kshevetskiy
Some nand flashes (like spi-nand one) are registered with mtd
subsystem only, thus nand command can't be used to work with
such flashes. As result some functionality is missing.

This patch implements 'nand markbad' functionality for mtd command.

Signed-off-by: Mikhail Kshevetskiy 
---
 cmd/Kconfig |  6 ++
 cmd/mtd.c   | 58 +
 2 files changed, 64 insertions(+)

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 6834bbd82f3..70c2d6a2dda 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1418,6 +1418,12 @@ config CMD_MTD_OTP
help
  MTD commands for OTP access.
 
+config CMD_MTD_MARKBAD
+   bool "mtd markbad"
+   depends on CMD_MTD
+   help
+ MTD markbad command support.
+
 config CMD_MUX
bool "mux"
depends on MULTIPLEXER
diff --git a/cmd/mtd.c b/cmd/mtd.c
index 9189f45cabd..18f00493780 100644
--- a/cmd/mtd.c
+++ b/cmd/mtd.c
@@ -692,6 +692,57 @@ out_put_mtd:
return ret;
 }
 
+#ifdef CONFIG_CMD_MTD_MARKBAD
+static int do_mtd_markbad(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+   struct mtd_info *mtd;
+   loff_t off;
+   int ret = 0;
+
+   if (argc < 3)
+   return CMD_RET_USAGE;
+
+   mtd = get_mtd_by_name(argv[1]);
+   if (IS_ERR_OR_NULL(mtd))
+   return CMD_RET_FAILURE;
+
+   if (!mtd_can_have_bb(mtd)) {
+   printf("Only NAND-based devices can have bad blocks\n");
+   goto out_put_mtd;
+   }
+
+   argc -= 2;
+   argv += 2;
+   while (argc > 0) {
+   off = hextoul(argv[0], NULL);
+   if (!mtd_is_aligned_with_block_size(mtd, off)) {
+   printf("Offset not aligned with a block (0x%x)\n",
+  mtd->erasesize);
+   ret = CMD_RET_FAILURE;
+   goto out_put_mtd;
+   }
+
+   ret = mtd_block_markbad(mtd, off);
+   if (ret) {
+   printf("block 0x%08llx NOT marked as bad! ERROR %d\n",
+  off, ret);
+   ret = CMD_RET_FAILURE;
+   } else {
+   printf("block 0x%08llx successfully marked as bad\n",
+  off);
+   }
+   --argc;
+   ++argv;
+   }
+
+out_put_mtd:
+   put_mtd_device(mtd);
+
+   return ret;
+}
+#endif
+
 static int do_mtd_bad(struct cmd_tbl *cmdtp, int flag, int argc,
  char *const argv[])
 {
@@ -774,6 +825,9 @@ U_BOOT_LONGHELP(mtd,
"mtd otpwrite\n"
"mtd otplock \n"
"mtd otpinfo[u|f]\n"
+#endif
+#ifdef CONFIG_CMD_MTD_MARKBAD
+   "mtd markbad [ 
...]\n"
 #endif
"\n"
"With:\n"
@@ -808,5 +862,9 @@ U_BOOT_CMD_WITH_SUBCMDS(mtd, "MTD utils", mtd_help_text,
 mtd_name_complete),
U_BOOT_SUBCMD_MKENT_COMPLETE(erase, 4, 0, do_mtd_erase,
 mtd_name_complete),
+#ifdef CONFIG_CMD_MTD_MARKBAD
+   U_BOOT_SUBCMD_MKENT_COMPLETE(markbad, 20, 0, do_mtd_markbad,
+mtd_name_complete),
+#endif
U_BOOT_SUBCMD_MKENT_COMPLETE(bad, 2, 1, do_mtd_bad,
 mtd_name_complete));
-- 
2.43.0



[PATCH 2/2] spi: soft_spi: Parse cs-gpios only if num-chipselects is not <0>

2024-06-27 Thread Mikhail Kshevetskiy
From: Michael Polyntsov 

Some boards don't have chipselect lines for leds so cs-gpios is not
specified in the dts leading to probing error. Fix it by making
behavior similar to the one in Linux, parse num-chipselects and
if it is zero, ignore cs-gpios.

Signed-off-by: Michael Polyntsov 
Signed-off-by: Mikhail Kshevetskiy 
---
 doc/device-tree-bindings/spi/soft-spi.txt |  5 +++--
 drivers/spi/soft_spi.c| 22 +-
 2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/doc/device-tree-bindings/spi/soft-spi.txt 
b/doc/device-tree-bindings/spi/soft-spi.txt
index bdf7e86befb..77b01b2fd9a 100644
--- a/doc/device-tree-bindings/spi/soft-spi.txt
+++ b/doc/device-tree-bindings/spi/soft-spi.txt
@@ -8,14 +8,15 @@ The soft SPI node requires the following properties:
 
 Mandatory properties:
 compatible: "spi-gpio"
-cs-gpios: GPIOs to use for SPI chip select (output)
+cs-gpios: GPIOs to use for SPI chip select (output), not required if 
num-chipselects = <0>
 sck-gpios: GPIO to use for SPI clock (output)
 And at least one of:
 mosi-gpios: GPIO to use for SPI MOSI line (output)
 miso-gpios: GPIO to use for SPI MISO line (input)
 
-Optional propertie:
+Optional properties:
 spi-delay-us: Number of microseconds of delay between each CS transition
+num-chipselects: Number of chipselect lines
 
 The GPIOs should be specified as required by the GPIO controller referenced.
 The first cell holds the phandle of the controller and the second cell
diff --git a/drivers/spi/soft_spi.c b/drivers/spi/soft_spi.c
index 3fe62818a44..2e80b7bb08e 100644
--- a/drivers/spi/soft_spi.c
+++ b/drivers/spi/soft_spi.c
@@ -238,6 +238,18 @@ static int soft_spi_of_to_plat(struct udevice *dev)
return 0;
 }
 
+static int retrieve_num_chipselects(struct udevice *dev)
+{
+   int chipselects;
+   int ret;
+
+   ret = ofnode_read_u32(dev_ofnode(dev), "num-chipselects", );
+   if (ret)
+   return ret;
+
+   return chipselects;
+}
+
 static int soft_spi_probe(struct udevice *dev)
 {
struct spi_slave *slave = dev_get_parent_priv(dev);
@@ -250,7 +262,15 @@ static int soft_spi_probe(struct udevice *dev)
 
ret = gpio_request_by_name(dev, "cs-gpios", 0, >cs,
   GPIOD_IS_OUT | cs_flags);
-   if (ret)
+   /*
+* If num-chipselects is zero we're ignoring absence of cs-gpios. This
+* code relies on the fact that `gpio_request_by_name` call above
+* initiailizes plat->cs to correct value with invalid GPIO even when
+* there is no cs-gpios node in dts. All other functions which work
+* with plat->cs verify it via `dm_gpio_is_valid` before using it, so
+* such value doesn't cause any problems.
+*/
+   if (ret && retrieve_num_chipselects(dev) != 0)
return -EINVAL;
 
ret = gpio_request_by_name(dev, "gpio-sck", 0, >sclk,
-- 
2.43.0



[PATCH 1/2] spi: soft_spi: fix miso gpio property name

2024-06-27 Thread Mikhail Kshevetskiy
Signed-off-by: Mikhail Kshevetskiy 
---
 drivers/spi/soft_spi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/soft_spi.c b/drivers/spi/soft_spi.c
index 0fa14339bdc..3fe62818a44 100644
--- a/drivers/spi/soft_spi.c
+++ b/drivers/spi/soft_spi.c
@@ -272,7 +272,7 @@ static int soft_spi_probe(struct udevice *dev)
ret = gpio_request_by_name(dev, "gpio-miso", 0, >miso,
   GPIOD_IS_IN);
if (ret)
-   ret = gpio_request_by_name(dev, "gpio-miso", 0, >miso,
+   ret = gpio_request_by_name(dev, "miso-gpios", 0, >miso,
   GPIOD_IS_IN);
if (ret)
plat->flags |= SPI_MASTER_NO_RX;
-- 
2.43.0



[PATCH 6/7] mtd: spinand: sync supported flashes with linux-6.6

2024-06-27 Thread Mikhail Kshevetskiy
Signed-off-by: Mikhail Kshevetskiy 
---
 drivers/mtd/nand/spi/Makefile |   4 +-
 drivers/mtd/nand/spi/alliancememory.c | 155 +
 drivers/mtd/nand/spi/ato.c|  84 
 drivers/mtd/nand/spi/core.c   |   4 +-
 drivers/mtd/nand/spi/esmt.c   |   9 ++
 drivers/mtd/nand/spi/gigadevice.c | 188 +-
 drivers/mtd/nand/spi/macronix.c   |  20 +++
 drivers/mtd/nand/spi/toshiba.c|  33 +
 include/linux/mtd/spinand.h   |   4 +-
 9 files changed, 496 insertions(+), 5 deletions(-)
 create mode 100644 drivers/mtd/nand/spi/alliancememory.c
 create mode 100644 drivers/mtd/nand/spi/ato.c

diff --git a/drivers/mtd/nand/spi/Makefile b/drivers/mtd/nand/spi/Makefile
index 65b836b34ca..6c733c0cc65 100644
--- a/drivers/mtd/nand/spi/Makefile
+++ b/drivers/mtd/nand/spi/Makefile
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 
-spinand-objs := core.o esmt.o gigadevice.o macronix.o micron.o paragon.o
-spinand-objs += toshiba.o winbond.o xtx.o
+spinand-objs := core.o alliancememory.o ato.o esmt.o gigadevice.o macronix.o
+spinand-objs += micron.o paragon.o toshiba.o winbond.o xtx.o
 obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
diff --git a/drivers/mtd/nand/spi/alliancememory.c 
b/drivers/mtd/nand/spi/alliancememory.c
new file mode 100644
index 000..e29e4cc77ec
--- /dev/null
+++ b/drivers/mtd/nand/spi/alliancememory.c
@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author: Mario Kicherer 
+ */
+
+#ifndef __UBOOT__
+#include 
+#include 
+#endif
+#include 
+
+#define SPINAND_MFR_ALLIANCEMEMORY 0x52
+
+#define AM_STATUS_ECC_BITMASK  (3 << 4)
+
+#define AM_STATUS_ECC_NONE_DETECTED(0 << 4)
+#define AM_STATUS_ECC_CORRECTED(1 << 4)
+#define AM_STATUS_ECC_ERRORED  (2 << 4)
+#define AM_STATUS_ECC_MAX_CORRECTED(3 << 4)
+
+static SPINAND_OP_VARIANTS(read_cache_variants,
+   SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0),
+   SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
+   SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
+   SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
+   SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
+   SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
+
+static SPINAND_OP_VARIANTS(write_cache_variants,
+  SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
+  SPINAND_PROG_LOAD(true, 0, NULL, 0));
+
+static SPINAND_OP_VARIANTS(update_cache_variants,
+  SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
+  SPINAND_PROG_LOAD(false, 0, NULL, 0));
+
+static int am_get_eccsize(struct mtd_info *mtd)
+{
+   if (mtd->oobsize == 64)
+   return 0x20;
+   else if (mtd->oobsize == 128)
+   return 0x38;
+   else if (mtd->oobsize == 256)
+   return 0x70;
+   else
+   return -EINVAL;
+}
+
+static int am_ooblayout_ecc(struct mtd_info *mtd, int section,
+   struct mtd_oob_region *region)
+{
+   int ecc_bytes;
+
+   ecc_bytes = am_get_eccsize(mtd);
+   if (ecc_bytes < 0)
+   return ecc_bytes;
+
+   region->offset = mtd->oobsize - ecc_bytes;
+   region->length = ecc_bytes;
+
+   return 0;
+}
+
+static int am_ooblayout_free(struct mtd_info *mtd, int section,
+struct mtd_oob_region *region)
+{
+   int ecc_bytes;
+
+   if (section)
+   return -ERANGE;
+
+   ecc_bytes = am_get_eccsize(mtd);
+   if (ecc_bytes < 0)
+   return ecc_bytes;
+
+   /*
+* It is unclear how many bytes are used for the bad block marker. We
+* reserve the common two bytes here.
+*
+* The free area in this kind of flash is divided into chunks where the
+* first 4 bytes of each chunk are unprotected. The number of chunks
+* depends on the specific model. The models with 4096+256 bytes pages
+* have 8 chunks, the others 4 chunks.
+*/
+
+   region->offset = 2;
+   region->length = mtd->oobsize - 2 - ecc_bytes;
+
+   return 0;
+}
+
+static const struct mtd_ooblayout_ops am_ooblayout = {
+   .ecc = am_ooblayout_ecc,
+   .rfree = am_ooblayout_free,
+};
+
+static int am_ecc_get_status(struct spinand_device *spinand, u8 status)
+{
+   switch (status & AM_STATUS_ECC_BITMASK) {
+   case AM_STATUS_ECC_NONE_DETECTED:
+   return 0;
+
+   case AM_STATUS_ECC_CORRECTED:
+   /*
+* use oobsize to determine the flash model and the maximum of
+* correctable errors and return maximum - 1 by convention
+*/
+   if (spinand->base.mtd->oobsize == 64)
+   return 3;
+   else
+   return 7;
+
+   case AM_STATUS_ECC_ERRORED:
+  

[PATCH 7/7] mtd: spinand: add Winbond W25N04KV flash support

2024-06-27 Thread Mikhail Kshevetskiy
Signed-off-by: Mikhail Kshevetskiy 
---
 drivers/mtd/nand/spi/winbond.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
index 5fe35e35ed5..f38ae95c570 100644
--- a/drivers/mtd/nand/spi/winbond.c
+++ b/drivers/mtd/nand/spi/winbond.c
@@ -172,6 +172,15 @@ static const struct spinand_info winbond_spinand_table[] = 
{
  _cache_variants),
 0,
 SPINAND_ECCINFO(_ooblayout, 
w25n02kv_ecc_get_status)),
+   SPINAND_INFO("W25N04KV",
+SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23),
+NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1),
+NAND_ECCREQ(8, 512),
+SPINAND_INFO_OP_VARIANTS(_cache_variants,
+ _cache_variants,
+ _cache_variants),
+0,
+SPINAND_ECCINFO(_ooblayout, 
w25n02kv_ecc_get_status)),
 };
 
 static int winbond_spinand_init(struct spinand_device *spinand)
-- 
2.43.0



[PATCH 5/7] mtd: nand: add initial ecc engine support

2024-06-27 Thread Mikhail Kshevetskiy
just now only spinand on_die ecc is supported

Signed-off-by: Mikhail Kshevetskiy 
---
 drivers/mtd/nand/Makefile   |   2 +-
 drivers/mtd/nand/core.c | 130 +++-
 drivers/mtd/nand/ecc.c  | 150 ++
 drivers/mtd/nand/spi/core.c | 206 -
 drivers/mtd/nand/spi/macronix.c |   7 +-
 drivers/mtd/nand/spi/micron.c   |   2 +-
 drivers/mtd/nand/spi/toshiba.c  |  10 +-
 drivers/mtd/nand/spi/winbond.c  |  10 +-
 include/linux/mtd/nand.h| 260 ++--
 include/linux/mtd/spinand.h |  13 +-
 include/spi-mem.h   |   2 +
 11 files changed, 724 insertions(+), 68 deletions(-)
 create mode 100644 drivers/mtd/nand/ecc.c

diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 96e186600a1..56179188e92 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 
 ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),)
-nandcore-objs := core.o bbt.o
+nandcore-objs := core.o bbt.o ecc.o
 obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
 obj-$(CONFIG_MTD_RAW_NAND) += raw/
 obj-$(CONFIG_MTD_SPI_NAND) += spi/
diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c
index f6d9c584f78..62bbc12c662 100644
--- a/drivers/mtd/nand/core.c
+++ b/drivers/mtd/nand/core.c
@@ -130,7 +130,7 @@ EXPORT_SYMBOL_GPL(nanddev_isreserved);
  *
  * Return: 0 in case of success, a negative error code otherwise.
  */
-static int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos)
+int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos)
 {
unsigned int entry;
 
@@ -188,6 +188,134 @@ int nanddev_mtd_erase(struct mtd_info *mtd, struct 
erase_info *einfo)
 }
 EXPORT_SYMBOL_GPL(nanddev_mtd_erase);
 
+/**
+ * nanddev_get_ecc_engine() - Find and get a suitable ECC engine
+ * @nand: NAND device
+ */
+static int nanddev_get_ecc_engine(struct nand_device *nand)
+{
+   int engine_type;
+
+   /* Read the user desires in terms of ECC engine/configuration */
+   of_get_nand_ecc_user_config(nand);
+
+   engine_type = nand->ecc.user_conf.engine_type;
+   if (engine_type == NAND_ECC_ENGINE_TYPE_INVALID)
+   engine_type = nand->ecc.defaults.engine_type;
+
+   switch (engine_type) {
+   case NAND_ECC_ENGINE_TYPE_NONE:
+   return 0;
+   case NAND_ECC_ENGINE_TYPE_SOFT:
+   nand->ecc.engine = nand_ecc_get_sw_engine(nand);
+   break;
+   case NAND_ECC_ENGINE_TYPE_ON_DIE:
+   nand->ecc.engine = nand_ecc_get_on_die_hw_engine(nand);
+   break;
+   case NAND_ECC_ENGINE_TYPE_ON_HOST:
+   nand->ecc.engine = nand_ecc_get_on_host_hw_engine(nand);
+   if (PTR_ERR(nand->ecc.engine) == -EPROBE_DEFER)
+   return -EPROBE_DEFER;
+   break;
+   default:
+   pr_err("Missing ECC engine type\n");
+   }
+
+   if (!nand->ecc.engine)
+   return  -EINVAL;
+
+   return 0;
+}
+
+/**
+ * nanddev_put_ecc_engine() - Dettach and put the in-use ECC engine
+ * @nand: NAND device
+ */
+static int nanddev_put_ecc_engine(struct nand_device *nand)
+{
+   switch (nand->ecc.ctx.conf.engine_type) {
+   case NAND_ECC_ENGINE_TYPE_ON_HOST:
+   nand_ecc_put_on_host_hw_engine(nand);
+   break;
+   case NAND_ECC_ENGINE_TYPE_NONE:
+   case NAND_ECC_ENGINE_TYPE_SOFT:
+   case NAND_ECC_ENGINE_TYPE_ON_DIE:
+   default:
+   break;
+   }
+
+   return 0;
+}
+
+/**
+ * nanddev_find_ecc_configuration() - Find a suitable ECC configuration
+ * @nand: NAND device
+ */
+static int nanddev_find_ecc_configuration(struct nand_device *nand)
+{
+   int ret;
+
+   if (!nand->ecc.engine)
+   return -ENOTSUPP;
+
+   ret = nand_ecc_init_ctx(nand);
+   if (ret)
+   return ret;
+
+   if (!nand_ecc_is_strong_enough(nand))
+   pr_warn("WARNING: %s: the ECC used on your system is too weak 
compared to the one required by the NAND chip\n",
+   nand->mtd->name);
+
+   return 0;
+}
+
+/**
+ * nanddev_ecc_engine_init() - Initialize an ECC engine for the chip
+ * @nand: NAND device
+ */
+int nanddev_ecc_engine_init(struct nand_device *nand)
+{
+   int ret;
+
+   /* Look for the ECC engine to use */
+   ret = nanddev_get_ecc_engine(nand);
+   if (ret) {
+   if (ret != -EPROBE_DEFER)
+   pr_err("No ECC engine found\n");
+
+   return ret;
+   }
+
+   /* No ECC engine requested */
+   if (!nand->ecc.engine)
+   return 0;
+
+   /* Configure the engine: balance user input and chip requirements */
+   ret = nanddev_find_ecc_configuration(nand);
+   if (ret) {
+   pr_err("No suitable ECC configuration\n");
+   nanddev_put_ecc_engine(nand);
+
+   return 

[PATCH 4/7] mtd: spinand: preparation for ecc engine adding

2024-06-27 Thread Mikhail Kshevetskiy
Signed-off-by: Mikhail Kshevetskiy 
---
 drivers/mtd/nand/spi/core.c | 259 +---
 1 file changed, 151 insertions(+), 108 deletions(-)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 8664e882753..1b2eefc9041 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -156,20 +156,12 @@ int spinand_select_target(struct spinand_device *spinand, 
unsigned int target)
return 0;
 }
 
-static int spinand_init_cfg_cache(struct spinand_device *spinand)
+static int spinand_read_cfg(struct spinand_device *spinand)
 {
struct nand_device *nand = spinand_to_nand(spinand);
-   struct udevice *dev = spinand->slave->dev;
unsigned int target;
int ret;
 
-   spinand->cfg_cache = devm_kzalloc(dev,
- sizeof(*spinand->cfg_cache) *
- nand->memorg.ntargets,
- GFP_KERNEL);
-   if (!spinand->cfg_cache)
-   return -ENOMEM;
-
for (target = 0; target < nand->memorg.ntargets; target++) {
ret = spinand_select_target(spinand, target);
if (ret)
@@ -188,6 +180,21 @@ static int spinand_init_cfg_cache(struct spinand_device 
*spinand)
return 0;
 }
 
+static int spinand_init_cfg_cache(struct spinand_device *spinand)
+{
+   struct nand_device *nand = spinand_to_nand(spinand);
+   struct udevice *dev = spinand->slave->dev;
+
+   spinand->cfg_cache = devm_kcalloc(dev,
+ nand->memorg.ntargets,
+ sizeof(*spinand->cfg_cache),
+ GFP_KERNEL);
+   if (!spinand->cfg_cache)
+   return -ENOMEM;
+
+   return 0;
+}
+
 static int spinand_init_quad_enable(struct spinand_device *spinand)
 {
bool enable = false;
@@ -211,6 +218,59 @@ static int spinand_ecc_enable(struct spinand_device 
*spinand,
   enable ? CFG_ECC_ENABLE : 0);
 }
 
+static int spinand_check_ecc_status(struct spinand_device *spinand, u8 status)
+{
+   struct nand_device *nand = spinand_to_nand(spinand);
+
+   if (spinand->eccinfo.get_status)
+   return spinand->eccinfo.get_status(spinand, status);
+
+   switch (status & STATUS_ECC_MASK) {
+   case STATUS_ECC_NO_BITFLIPS:
+   return 0;
+
+   case STATUS_ECC_HAS_BITFLIPS:
+   /*
+* We have no way to know exactly how many bitflips have been
+* fixed, so let's return the maximum possible value so that
+* wear-leveling layers move the data immediately.
+*/
+   return nand->eccreq.strength;
+
+   case STATUS_ECC_UNCOR_ERROR:
+   return -EBADMSG;
+
+   default:
+   break;
+   }
+
+   return -EINVAL;
+}
+
+static int spinand_noecc_ooblayout_ecc(struct mtd_info *mtd, int section,
+  struct mtd_oob_region *region)
+{
+   return -ERANGE;
+}
+
+static int spinand_noecc_ooblayout_free(struct mtd_info *mtd, int section,
+   struct mtd_oob_region *region)
+{
+   if (section)
+   return -ERANGE;
+
+   /* Reserve 2 bytes for the BBM. */
+   region->offset = 2;
+   region->length = 62;
+
+   return 0;
+}
+
+static const struct mtd_ooblayout_ops spinand_noecc_ooblayout = {
+   .ecc = spinand_noecc_ooblayout_ecc,
+   .rfree = spinand_noecc_ooblayout_free,
+};
+
 static int spinand_write_enable_op(struct spinand_device *spinand)
 {
struct spi_mem_op op = SPINAND_WR_EN_DIS_OP(true);
@@ -232,7 +292,7 @@ static int spinand_read_from_cache_op(struct spinand_device 
*spinand,
  const struct nand_page_io_req *req)
 {
struct nand_device *nand = spinand_to_nand(spinand);
-   struct mtd_info *mtd = nanddev_to_mtd(nand);
+   struct mtd_info *mtd = spinand_to_mtd(spinand);
struct spi_mem_dirmap_desc *rdesc;
unsigned int nbytes = 0;
void *buf = NULL;
@@ -290,7 +350,7 @@ static int spinand_write_to_cache_op(struct spinand_device 
*spinand,
 const struct nand_page_io_req *req)
 {
struct nand_device *nand = spinand_to_nand(spinand);
-   struct mtd_info *mtd = nanddev_to_mtd(nand);
+   struct mtd_info *mtd = spinand_to_mtd(spinand);
struct spi_mem_dirmap_desc *wdesc;
unsigned int nbytes, column = 0;
void *buf = spinand->databuf;
@@ -352,7 +412,7 @@ static int spinand_program_op(struct spinand_device 
*spinand,
 static int spinand_erase_op(struct spinand_device *spinand,
const struct nand_pos *pos)
 {
-   struct nand_device *nand = >base;
+   struct nand_device *nand = spinand_to_nand(spinand);
unsigned int row = 

[PATCH 3/7] mtd: spinand: simulate behavior of linux's function spinand_wait()

2024-06-27 Thread Mikhail Kshevetskiy
also call schedule() to allow periodic actions

Signed-off-by: Mikhail Kshevetskiy 
---
 drivers/mtd/nand/spi/core.c | 35 ---
 include/linux/mtd/spinand.h | 22 ++
 2 files changed, 50 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index f10a3dbfdff..8664e882753 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -32,6 +32,7 @@
 #include 
 #include 
 #include 
+#include 
 #endif
 
 /* SPI NAND index visible in MTD names */
@@ -358,21 +359,29 @@ static int spinand_erase_op(struct spinand_device 
*spinand,
return spi_mem_exec_op(spinand->slave, );
 }
 
-static int spinand_wait(struct spinand_device *spinand, u8 *s)
+static int spinand_wait(struct spinand_device *spinand,
+   unsigned long initial_delay_us,
+   unsigned long poll_delay_us,
+   u8 *s)
 {
unsigned long start, stop;
u8 status;
int ret;
 
+   udelay(initial_delay_us);
start = get_timer(0);
-   stop = 400;
+   stop = SPINAND_WAITRDY_TIMEOUT_MS;
do {
+   schedule();
+
ret = spinand_read_status(spinand, );
if (ret)
return ret;
 
if (!(status & STATUS_BUSY))
goto out;
+
+   udelay(poll_delay_us);
} while (get_timer(start) < stop);
 
/*
@@ -414,7 +423,10 @@ static int spinand_reset_op(struct spinand_device *spinand)
if (ret)
return ret;
 
-   return spinand_wait(spinand, NULL);
+   return spinand_wait(spinand,
+   SPINAND_RESET_INITIAL_DELAY_US,
+   SPINAND_RESET_POLL_DELAY_US,
+   NULL);
 }
 
 static int spinand_lock_block(struct spinand_device *spinand, u8 lock)
@@ -462,7 +474,10 @@ static int spinand_read_page(struct spinand_device 
*spinand,
if (ret)
return ret;
 
-   ret = spinand_wait(spinand, );
+   ret = spinand_wait(spinand,
+  SPINAND_READ_INITIAL_DELAY_US,
+  SPINAND_READ_POLL_DELAY_US,
+  );
if (ret < 0)
return ret;
 
@@ -494,9 +509,12 @@ static int spinand_write_page(struct spinand_device 
*spinand,
if (ret)
return ret;
 
-   ret = spinand_wait(spinand, );
+   ret = spinand_wait(spinand,
+  SPINAND_WRITE_INITIAL_DELAY_US,
+  SPINAND_WRITE_POLL_DELAY_US,
+  );
if (!ret && (status & STATUS_PROG_FAILED))
-   ret = -EIO;
+   return -EIO;
 
return ret;
 }
@@ -698,7 +716,10 @@ static int spinand_erase(struct nand_device *nand, const 
struct nand_pos *pos)
if (ret)
return ret;
 
-   ret = spinand_wait(spinand, );
+   ret = spinand_wait(spinand,
+  SPINAND_ERASE_INITIAL_DELAY_US,
+  SPINAND_ERASE_POLL_DELAY_US,
+  );
if (!ret && (status & STATUS_ERASE_FAILED))
ret = -EIO;
 
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index 5934b7604cc..b701d25f73d 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -176,6 +176,28 @@ struct spinand_op;
 struct spinand_device;
 
 #define SPINAND_MAX_ID_LEN 4
+/*
+ * For erase, write and read operation, we got the following timings :
+ * tBERS (erase) 1ms to 4ms
+ * tPROG 300us to 400us
+ * tREAD 25us to 100us
+ * In order to minimize latency, the min value is divided by 4 for the
+ * initial delay, and dividing by 20 for the poll delay.
+ * For reset, 5us/10us/500us if the device is respectively
+ * reading/programming/erasing when the RESET occurs. Since we always
+ * issue a RESET when the device is IDLE, 5us is selected for both initial
+ * and poll delay.
+ */
+#define SPINAND_READ_INITIAL_DELAY_US  6
+#define SPINAND_READ_POLL_DELAY_US 5
+#define SPINAND_RESET_INITIAL_DELAY_US 5
+#define SPINAND_RESET_POLL_DELAY_US5
+#define SPINAND_WRITE_INITIAL_DELAY_US 75
+#define SPINAND_WRITE_POLL_DELAY_US15
+#define SPINAND_ERASE_INITIAL_DELAY_US 250
+#define SPINAND_ERASE_POLL_DELAY_US50
+
+#define SPINAND_WAITRDY_TIMEOUT_MS 400
 
 /**
  * struct spinand_id - SPI NAND id structure
-- 
2.43.0



[PATCH 2/7] mtd: spinand: Add a NAND page I/O request type

2024-06-27 Thread Mikhail Kshevetskiy
Use an enum to differentiate the type of I/O (reading or writing a
page). Also update the request iterator.

This is a port of linux patch 701981cab01696584a12e5f0e7c2ad931a326059
created by Miquel Raynal 

Signed-off-by: Mikhail Kshevetskiy 
---
 drivers/mtd/nand/spi/core.c |  4 ++--
 include/linux/mtd/nand.h| 18 --
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index adc67d7a40d..f10a3dbfdff 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -519,7 +519,7 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t 
from,
mutex_lock(>lock);
 #endif
 
-   nanddev_io_for_each_page(nand, from, ops, ) {
+   nanddev_io_for_each_page(nand, NAND_PAGE_READ, from, ops, ) {
schedule();
ret = spinand_select_target(spinand, iter.req.pos.target);
if (ret)
@@ -571,7 +571,7 @@ static int spinand_mtd_write(struct mtd_info *mtd, loff_t 
to,
mutex_lock(>lock);
 #endif
 
-   nanddev_io_for_each_page(nand, to, ops, ) {
+   nanddev_io_for_each_page(nand, NAND_PAGE_WRITE, to, ops, ) {
schedule();
ret = spinand_select_target(spinand, iter.req.pos.target);
if (ret)
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 651f8706df5..0afdaed5715 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -80,8 +80,19 @@ struct nand_pos {
unsigned int page;
 };
 
+/**
+ * enum nand_page_io_req_type - Direction of an I/O request
+ * @NAND_PAGE_READ: from the chip, to the controller
+ * @NAND_PAGE_WRITE: from the controller, to the chip
+ */
+enum nand_page_io_req_type {
+   NAND_PAGE_READ = 0,
+   NAND_PAGE_WRITE,
+};
+
 /**
  * struct nand_page_io_req - NAND I/O request object
+ * @type: the type of page I/O: read or write
  * @pos: the position this I/O request is targeting
  * @dataoffs: the offset within the page
  * @datalen: number of data bytes to read from/write to this page
@@ -97,6 +108,7 @@ struct nand_pos {
  * specific commands/operations.
  */
 struct nand_page_io_req {
+   enum nand_page_io_req_type type;
struct nand_pos pos;
unsigned int dataoffs;
unsigned int datalen;
@@ -613,11 +625,13 @@ static inline void nanddev_pos_next_page(struct 
nand_device *nand,
  * layer.
  */
 static inline void nanddev_io_iter_init(struct nand_device *nand,
+   enum nand_page_io_req_type reqtype,
loff_t offs, struct mtd_oob_ops *req,
struct nand_io_iter *iter)
 {
struct mtd_info *mtd = nanddev_to_mtd(nand);
 
+   iter->req.type = reqtype;
iter->req.mode = req->mode;
iter->req.dataoffs = nanddev_offs_to_pos(nand, offs, >req.pos);
iter->req.ooboffs = req->ooboffs;
@@ -687,8 +701,8 @@ static inline bool nanddev_io_iter_end(struct nand_device 
*nand,
  *
  * Should be used for iterate over pages that are contained in an MTD request.
  */
-#define nanddev_io_for_each_page(nand, start, req, iter)   \
-   for (nanddev_io_iter_init(nand, start, req, iter);  \
+#define nanddev_io_for_each_page(nand, type, start, req, iter) \
+   for (nanddev_io_iter_init(nand, type, start, req, iter);\
 !nanddev_io_iter_end(nand, iter);  \
 nanddev_io_iter_next_page(nand, iter))
 
-- 
2.43.0



[PATCH 1/7] mtd: spinand: Use the spi-mem dirmap API

2024-06-27 Thread Mikhail Kshevetskiy
Make use of the spi-mem direct mapping API to let advanced controllers
optimize read/write operations when they support direct mapping.

This is a port of linux patch 981d1aa0697ce1393e00933f154d181e965703d0
created by Boris Brezillon .

Signed-off-by: Mikhail Kshevetskiy 
---
 drivers/mtd/nand/spi/core.c | 185 +---
 include/linux/mtd/spinand.h |   7 ++
 2 files changed, 95 insertions(+), 97 deletions(-)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 62c28aa422d..adc67d7a40d 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -37,21 +37,6 @@
 /* SPI NAND index visible in MTD names */
 static int spi_nand_idx;
 
-static void spinand_cache_op_adjust_colum(struct spinand_device *spinand,
- const struct nand_page_io_req *req,
- u16 *column)
-{
-   struct nand_device *nand = spinand_to_nand(spinand);
-   unsigned int shift;
-
-   if (nand->memorg.planes_per_lun < 2)
-   return;
-
-   /* The plane number is passed in MSB just above the column address */
-   shift = fls(nand->memorg.pagesize);
-   *column |= req->pos.plane << shift;
-}
-
 static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val)
 {
struct spi_mem_op op = SPINAND_GET_FEATURE_OP(reg,
@@ -245,27 +230,21 @@ static int spinand_load_page_op(struct spinand_device 
*spinand,
 static int spinand_read_from_cache_op(struct spinand_device *spinand,
  const struct nand_page_io_req *req)
 {
-   struct spi_mem_op op = *spinand->op_templates.read_cache;
struct nand_device *nand = spinand_to_nand(spinand);
struct mtd_info *mtd = nanddev_to_mtd(nand);
-   struct nand_page_io_req adjreq = *req;
+   struct spi_mem_dirmap_desc *rdesc;
unsigned int nbytes = 0;
void *buf = NULL;
u16 column = 0;
-   int ret;
+   ssize_t ret;
 
if (req->datalen) {
-   adjreq.datalen = nanddev_page_size(nand);
-   adjreq.dataoffs = 0;
-   adjreq.databuf.in = spinand->databuf;
buf = spinand->databuf;
-   nbytes = adjreq.datalen;
+   nbytes = nanddev_page_size(nand);
+   column = 0;
}
 
if (req->ooblen) {
-   adjreq.ooblen = nanddev_per_page_oobsize(nand);
-   adjreq.ooboffs = 0;
-   adjreq.oobbuf.in = spinand->oobbuf;
nbytes += nanddev_per_page_oobsize(nand);
if (!buf) {
buf = spinand->oobbuf;
@@ -273,28 +252,19 @@ static int spinand_read_from_cache_op(struct 
spinand_device *spinand,
}
}
 
-   spinand_cache_op_adjust_colum(spinand, , );
-   op.addr.val = column;
+   rdesc = spinand->dirmaps[req->pos.plane].rdesc;
 
-   /*
-* Some controllers are limited in term of max RX data size. In this
-* case, just repeat the READ_CACHE operation after updating the
-* column.
-*/
while (nbytes) {
-   op.data.buf.in = buf;
-   op.data.nbytes = nbytes;
-   ret = spi_mem_adjust_op_size(spinand->slave, );
-   if (ret)
+   ret = spi_mem_dirmap_read(rdesc, column, nbytes, buf);
+   if (ret < 0)
return ret;
 
-   ret = spi_mem_exec_op(spinand->slave, );
-   if (ret)
-   return ret;
+   if (!ret || ret > nbytes)
+   return -EIO;
 
-   buf += op.data.nbytes;
-   nbytes -= op.data.nbytes;
-   op.addr.val += op.data.nbytes;
+   nbytes -= ret;
+   column += ret;
+   buf += ret;
}
 
if (req->datalen)
@@ -318,14 +288,12 @@ static int spinand_read_from_cache_op(struct 
spinand_device *spinand,
 static int spinand_write_to_cache_op(struct spinand_device *spinand,
 const struct nand_page_io_req *req)
 {
-   struct spi_mem_op op = *spinand->op_templates.write_cache;
struct nand_device *nand = spinand_to_nand(spinand);
struct mtd_info *mtd = nanddev_to_mtd(nand);
-   struct nand_page_io_req adjreq = *req;
-   unsigned int nbytes = 0;
-   void *buf = NULL;
-   u16 column = 0;
-   int ret;
+   struct spi_mem_dirmap_desc *wdesc;
+   unsigned int nbytes, column = 0;
+   void *buf = spinand->databuf;
+   ssize_t ret;
 
/*
 * Looks like PROGRAM LOAD (AKA write cache) does not necessarily reset
@@ -334,19 +302,12 @@ static int spinand_write_to_cache_op(struct 
spinand_device *spinand,
 * the data portion of the page, otherwise we might corrupt the BBM or
 * user data previously programmed in OOB area.
 */
-   memset(spinand->databuf, 

[PATCH] net/tftp: make tftpput working with servers that do not use OACK

2024-06-27 Thread Mikhail Kshevetskiy
Signed-off-by: Mikhail Kshevetskiy 
---
 net/tftp.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/net/tftp.c b/net/tftp.c
index 2e335413492..2534dec1c9f 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -494,8 +494,15 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct 
in_addr sip,
tftp_prev_block = tftp_cur_block;
tftp_cur_block = (unsigned short)(block + 1);
update_block_number();
-   if (ack_ok)
+   if (ack_ok) {
+   if (block == 0 &&
+   tftp_state == STATE_SEND_WRQ){
+   /* connection's first ACK */
+   tftp_state = STATE_DATA;
+   tftp_remote_port = src;
+   }
tftp_send(); /* Send next data block */
+   }
}
}
 #endif
-- 
2.43.0



[PATCH 01/79] net/tftp: make tftpput working with servers that do not use OACK

2024-06-27 Thread Mikhail Kshevetskiy
Signed-off-by: Mikhail Kshevetskiy 
---
 net/tftp.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/net/tftp.c b/net/tftp.c
index 2e335413492..2534dec1c9f 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -494,8 +494,15 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct 
in_addr sip,
tftp_prev_block = tftp_cur_block;
tftp_cur_block = (unsigned short)(block + 1);
update_block_number();
-   if (ack_ok)
+   if (ack_ok) {
+   if (block == 0 &&
+   tftp_state == STATE_SEND_WRQ){
+   /* connection's first ACK */
+   tftp_state = STATE_DATA;
+   tftp_remote_port = src;
+   }
tftp_send(); /* Send next data block */
+   }
}
}
 #endif
-- 
2.43.0



Re: [PATCH 1/4] power: regulator: Trigger probe of regulators which are always-on or boot-on

2024-06-27 Thread Simon Glass
Hi Svyatoslav,

On Thu, 27 Jun 2024 at 11:34, Svyatoslav Ryhel  wrote:
>
> чт, 27 черв. 2024 р. о 12:26 Simon Glass  пише:
> >
> > Hi Svyatoslav,
> >
> > On Thu, 27 Jun 2024 at 10:09, Svyatoslav  wrote:
> > >
> > >
> > >
> > > 27 червня 2024 р. 11:48:46 GMT+03:00, Caleb Connolly 
> > >  написав(-ла):
> > > >
> > > >
> > > >On 27/06/2024 10:37, Simon Glass wrote:
> > > >> Hi Marek,
> > > >>
> > > >> On Thu, 27 Jun 2024 at 00:57, Marek Vasut  wrote:
> > > >>>
> > > >>> In case a regulator DT node contains regulator-always-on or 
> > > >>> regulator-boot-on
> > > >>> property, make sure the regulator gets correctly configured by U-Boot 
> > > >>> on start
> > > >>> up. Unconditionally probe such regulator drivers. This is a 
> > > >>> preparatory patch
> > > >>> for introduction of .regulator_post_probe() which would trigger the 
> > > >>> regulator
> > > >>> configuration.
> > > >>>
> > > >>> Parsing of regulator-always-on and regulator-boot-on DT property has 
> > > >>> been
> > > >>> moved to regulator_post_bind() as the information is required early, 
> > > >>> the
> > > >>> rest of the DT parsing has been kept in regulator_pre_probe() to avoid
> > > >>> slowing down the boot process.
> > > >>>
> > > >>> Signed-off-by: Marek Vasut 
> > > >>> ---
> > > >>> Cc: Ben Wolsieffer 
> > > >>> Cc: Caleb Connolly 
> > > >>> Cc: Chris Morgan 
> > > >>> Cc: Dragan Simic 
> > > >>> Cc: Eugen Hristev 
> > > >>> Cc: Francesco Dolcini 
> > > >>> Cc: Heinrich Schuchardt 
> > > >>> Cc: Jaehoon Chung 
> > > >>> Cc: Jagan Teki 
> > > >>> Cc: Jonas Karlman 
> > > >>> Cc: Kever Yang 
> > > >>> Cc: Kostya Porotchkin 
> > > >>> Cc: Matteo Lisi 
> > > >>> Cc: Mattijs Korpershoek 
> > > >>> Cc: Max Krummenacher 
> > > >>> Cc: Neil Armstrong 
> > > >>> Cc: Patrice Chotard 
> > > >>> Cc: Patrick Delaunay 
> > > >>> Cc: Philipp Tomsich 
> > > >>> Cc: Quentin Schulz 
> > > >>> Cc: Sam Day 
> > > >>> Cc: Simon Glass 
> > > >>> Cc: Sumit Garg 
> > > >>> Cc: Svyatoslav Ryhel 
> > > >>> Cc: Thierry Reding 
> > > >>> Cc: Tom Rini 
> > > >>> Cc: Volodymyr Babchuk 
> > > >>> Cc: u-boot-amlo...@groups.io
> > > >>> Cc: u-boot-q...@groups.io
> > > >>> Cc: u-b...@dh-electronics.com
> > > >>> Cc: u-boot@lists.denx.de
> > > >>> Cc: uboot-st...@st-md-mailman.stormreply.com
> > > >>> ---
> > > >>>   drivers/power/regulator/regulator-uclass.c | 22 
> > > >>> +++---
> > > >>>   1 file changed, 15 insertions(+), 7 deletions(-)
> > > >>>
> > > >>> diff --git a/drivers/power/regulator/regulator-uclass.c 
> > > >>> b/drivers/power/regulator/regulator-uclass.c
> > > >>> index 66fd531da04..ccc4ef33d83 100644
> > > >>> --- a/drivers/power/regulator/regulator-uclass.c
> > > >>> +++ b/drivers/power/regulator/regulator-uclass.c
> > > >>> @@ -433,6 +433,8 @@ static int regulator_post_bind(struct udevice 
> > > >>> *dev)
> > > >>>  const char *property = "regulator-name";
> > > >>>
> > > >>>  uc_pdata = dev_get_uclass_plat(dev);
> > > >>> +   uc_pdata->always_on = dev_read_bool(dev, 
> > > >>> "regulator-always-on");
> > > >>> +   uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
> > > >>>
> > > >>>  /* Regulator's mandatory constraint */
> > > >>>  uc_pdata->name = dev_read_string(dev, property);
> > > >>> @@ -444,13 +446,21 @@ static int regulator_post_bind(struct udevice 
> > > >>> *dev)
> > > >>>  return -EINVAL;
> > > >>>  }
> > > >>>
> > > >>> -   if (regulator_name_is_unique(dev, uc_pdata->name))
> > > >>> -   return 0;
> > > >>> +   if (!regulator_name_is_unique(dev, uc_pdata->name)) {
> > > >>> +   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
> > > >>> + property, dev->name, uc_pdata->name);
> > > >>> +   return -EINVAL;
> > > >>> +   }
> > > >>>
> > > >>> -   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
> > > >>> - property, dev->name, uc_pdata->name);
> > > >>> +   /*
> > > >>> +* In case the regulator has regulator-always-on or
> > > >>> +* regulator-boot-on DT property, trigger probe() to
> > > >>> +* configure its default state during startup.
> > > >>> +*/
> > > >>> +   if (uc_pdata->always_on && uc_pdata->boot_on)
> > > >>> +   dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);
> > > >>>
> > > >>> -   return -EINVAL;
> > > >>> +   return 0;
> > > >>>   }
> > > >>>
> > > >>>   static int regulator_pre_probe(struct udevice *dev)
> > > >>> @@ -473,8 +483,6 @@ static int regulator_pre_probe(struct udevice 
> > > >>> *dev)
> > > >>>  -ENODATA);
> > > >>>  uc_pdata->max_uA = dev_read_u32_default(dev, 
> > > >>> "regulator-max-microamp",
> > > >>>  -ENODATA);
> > > >>> -   uc_pdata->always_on = dev_read_bool(dev, 
> > > >>> "regulator-always-on");
> > > >>> -   uc_pdata->boot_on = 

Re: [PATCH 1/4] power: regulator: Trigger probe of regulators which are always-on or boot-on

2024-06-27 Thread Svyatoslav Ryhel
чт, 27 черв. 2024 р. о 12:26 Simon Glass  пише:
>
> Hi Svyatoslav,
>
> On Thu, 27 Jun 2024 at 10:09, Svyatoslav  wrote:
> >
> >
> >
> > 27 червня 2024 р. 11:48:46 GMT+03:00, Caleb Connolly 
> >  написав(-ла):
> > >
> > >
> > >On 27/06/2024 10:37, Simon Glass wrote:
> > >> Hi Marek,
> > >>
> > >> On Thu, 27 Jun 2024 at 00:57, Marek Vasut  wrote:
> > >>>
> > >>> In case a regulator DT node contains regulator-always-on or 
> > >>> regulator-boot-on
> > >>> property, make sure the regulator gets correctly configured by U-Boot 
> > >>> on start
> > >>> up. Unconditionally probe such regulator drivers. This is a preparatory 
> > >>> patch
> > >>> for introduction of .regulator_post_probe() which would trigger the 
> > >>> regulator
> > >>> configuration.
> > >>>
> > >>> Parsing of regulator-always-on and regulator-boot-on DT property has 
> > >>> been
> > >>> moved to regulator_post_bind() as the information is required early, the
> > >>> rest of the DT parsing has been kept in regulator_pre_probe() to avoid
> > >>> slowing down the boot process.
> > >>>
> > >>> Signed-off-by: Marek Vasut 
> > >>> ---
> > >>> Cc: Ben Wolsieffer 
> > >>> Cc: Caleb Connolly 
> > >>> Cc: Chris Morgan 
> > >>> Cc: Dragan Simic 
> > >>> Cc: Eugen Hristev 
> > >>> Cc: Francesco Dolcini 
> > >>> Cc: Heinrich Schuchardt 
> > >>> Cc: Jaehoon Chung 
> > >>> Cc: Jagan Teki 
> > >>> Cc: Jonas Karlman 
> > >>> Cc: Kever Yang 
> > >>> Cc: Kostya Porotchkin 
> > >>> Cc: Matteo Lisi 
> > >>> Cc: Mattijs Korpershoek 
> > >>> Cc: Max Krummenacher 
> > >>> Cc: Neil Armstrong 
> > >>> Cc: Patrice Chotard 
> > >>> Cc: Patrick Delaunay 
> > >>> Cc: Philipp Tomsich 
> > >>> Cc: Quentin Schulz 
> > >>> Cc: Sam Day 
> > >>> Cc: Simon Glass 
> > >>> Cc: Sumit Garg 
> > >>> Cc: Svyatoslav Ryhel 
> > >>> Cc: Thierry Reding 
> > >>> Cc: Tom Rini 
> > >>> Cc: Volodymyr Babchuk 
> > >>> Cc: u-boot-amlo...@groups.io
> > >>> Cc: u-boot-q...@groups.io
> > >>> Cc: u-b...@dh-electronics.com
> > >>> Cc: u-boot@lists.denx.de
> > >>> Cc: uboot-st...@st-md-mailman.stormreply.com
> > >>> ---
> > >>>   drivers/power/regulator/regulator-uclass.c | 22 +++---
> > >>>   1 file changed, 15 insertions(+), 7 deletions(-)
> > >>>
> > >>> diff --git a/drivers/power/regulator/regulator-uclass.c 
> > >>> b/drivers/power/regulator/regulator-uclass.c
> > >>> index 66fd531da04..ccc4ef33d83 100644
> > >>> --- a/drivers/power/regulator/regulator-uclass.c
> > >>> +++ b/drivers/power/regulator/regulator-uclass.c
> > >>> @@ -433,6 +433,8 @@ static int regulator_post_bind(struct udevice *dev)
> > >>>  const char *property = "regulator-name";
> > >>>
> > >>>  uc_pdata = dev_get_uclass_plat(dev);
> > >>> +   uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
> > >>> +   uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
> > >>>
> > >>>  /* Regulator's mandatory constraint */
> > >>>  uc_pdata->name = dev_read_string(dev, property);
> > >>> @@ -444,13 +446,21 @@ static int regulator_post_bind(struct udevice 
> > >>> *dev)
> > >>>  return -EINVAL;
> > >>>  }
> > >>>
> > >>> -   if (regulator_name_is_unique(dev, uc_pdata->name))
> > >>> -   return 0;
> > >>> +   if (!regulator_name_is_unique(dev, uc_pdata->name)) {
> > >>> +   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
> > >>> + property, dev->name, uc_pdata->name);
> > >>> +   return -EINVAL;
> > >>> +   }
> > >>>
> > >>> -   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
> > >>> - property, dev->name, uc_pdata->name);
> > >>> +   /*
> > >>> +* In case the regulator has regulator-always-on or
> > >>> +* regulator-boot-on DT property, trigger probe() to
> > >>> +* configure its default state during startup.
> > >>> +*/
> > >>> +   if (uc_pdata->always_on && uc_pdata->boot_on)
> > >>> +   dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);
> > >>>
> > >>> -   return -EINVAL;
> > >>> +   return 0;
> > >>>   }
> > >>>
> > >>>   static int regulator_pre_probe(struct udevice *dev)
> > >>> @@ -473,8 +483,6 @@ static int regulator_pre_probe(struct udevice *dev)
> > >>>  -ENODATA);
> > >>>  uc_pdata->max_uA = dev_read_u32_default(dev, 
> > >>> "regulator-max-microamp",
> > >>>  -ENODATA);
> > >>> -   uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
> > >>> -   uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
> > >>>  uc_pdata->ramp_delay = dev_read_u32_default(dev, 
> > >>> "regulator-ramp-delay",
> > >>>  0);
> > >>>  uc_pdata->force_off = dev_read_bool(dev, 
> > >>> "regulator-force-boot-off");
> > >>> --
> > >>> 2.43.0
> > >>>
> > >>
> > >> This is reading a lot of DT stuff very 

Re: [PATCH 1/4] power: regulator: Trigger probe of regulators which are always-on or boot-on

2024-06-27 Thread Simon Glass
Hi Caleb,

On Thu, 27 Jun 2024 at 09:48, Caleb Connolly  wrote:
>
>
>
> On 27/06/2024 10:37, Simon Glass wrote:
> > Hi Marek,
> >
> > On Thu, 27 Jun 2024 at 00:57, Marek Vasut  wrote:
> >>
> >> In case a regulator DT node contains regulator-always-on or 
> >> regulator-boot-on
> >> property, make sure the regulator gets correctly configured by U-Boot on 
> >> start
> >> up. Unconditionally probe such regulator drivers. This is a preparatory 
> >> patch
> >> for introduction of .regulator_post_probe() which would trigger the 
> >> regulator
> >> configuration.
> >>
> >> Parsing of regulator-always-on and regulator-boot-on DT property has been
> >> moved to regulator_post_bind() as the information is required early, the
> >> rest of the DT parsing has been kept in regulator_pre_probe() to avoid
> >> slowing down the boot process.
> >>
> >> Signed-off-by: Marek Vasut 
> >> ---
> >> Cc: Ben Wolsieffer 
> >> Cc: Caleb Connolly 
> >> Cc: Chris Morgan 
> >> Cc: Dragan Simic 
> >> Cc: Eugen Hristev 
> >> Cc: Francesco Dolcini 
> >> Cc: Heinrich Schuchardt 
> >> Cc: Jaehoon Chung 
> >> Cc: Jagan Teki 
> >> Cc: Jonas Karlman 
> >> Cc: Kever Yang 
> >> Cc: Kostya Porotchkin 
> >> Cc: Matteo Lisi 
> >> Cc: Mattijs Korpershoek 
> >> Cc: Max Krummenacher 
> >> Cc: Neil Armstrong 
> >> Cc: Patrice Chotard 
> >> Cc: Patrick Delaunay 
> >> Cc: Philipp Tomsich 
> >> Cc: Quentin Schulz 
> >> Cc: Sam Day 
> >> Cc: Simon Glass 
> >> Cc: Sumit Garg 
> >> Cc: Svyatoslav Ryhel 
> >> Cc: Thierry Reding 
> >> Cc: Tom Rini 
> >> Cc: Volodymyr Babchuk 
> >> Cc: u-boot-amlo...@groups.io
> >> Cc: u-boot-q...@groups.io
> >> Cc: u-b...@dh-electronics.com
> >> Cc: u-boot@lists.denx.de
> >> Cc: uboot-st...@st-md-mailman.stormreply.com
> >> ---
> >>   drivers/power/regulator/regulator-uclass.c | 22 +++---
> >>   1 file changed, 15 insertions(+), 7 deletions(-)
> >>
> >> diff --git a/drivers/power/regulator/regulator-uclass.c 
> >> b/drivers/power/regulator/regulator-uclass.c
> >> index 66fd531da04..ccc4ef33d83 100644
> >> --- a/drivers/power/regulator/regulator-uclass.c
> >> +++ b/drivers/power/regulator/regulator-uclass.c
> >> @@ -433,6 +433,8 @@ static int regulator_post_bind(struct udevice *dev)
> >>  const char *property = "regulator-name";
> >>
> >>  uc_pdata = dev_get_uclass_plat(dev);
> >> +   uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
> >> +   uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
> >>
> >>  /* Regulator's mandatory constraint */
> >>  uc_pdata->name = dev_read_string(dev, property);
> >> @@ -444,13 +446,21 @@ static int regulator_post_bind(struct udevice *dev)
> >>  return -EINVAL;
> >>  }
> >>
> >> -   if (regulator_name_is_unique(dev, uc_pdata->name))
> >> -   return 0;
> >> +   if (!regulator_name_is_unique(dev, uc_pdata->name)) {
> >> +   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
> >> + property, dev->name, uc_pdata->name);
> >> +   return -EINVAL;
> >> +   }
> >>
> >> -   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
> >> - property, dev->name, uc_pdata->name);
> >> +   /*
> >> +* In case the regulator has regulator-always-on or
> >> +* regulator-boot-on DT property, trigger probe() to
> >> +* configure its default state during startup.
> >> +*/
> >> +   if (uc_pdata->always_on && uc_pdata->boot_on)
> >> +   dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);
> >>
> >> -   return -EINVAL;
> >> +   return 0;
> >>   }
> >>
> >>   static int regulator_pre_probe(struct udevice *dev)
> >> @@ -473,8 +483,6 @@ static int regulator_pre_probe(struct udevice *dev)
> >>  -ENODATA);
> >>  uc_pdata->max_uA = dev_read_u32_default(dev, 
> >> "regulator-max-microamp",
> >>  -ENODATA);
> >> -   uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
> >> -   uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
> >>  uc_pdata->ramp_delay = dev_read_u32_default(dev, 
> >> "regulator-ramp-delay",
> >>  0);
> >>  uc_pdata->force_off = dev_read_bool(dev, 
> >> "regulator-force-boot-off");
> >> --
> >> 2.43.0
> >>
> >
> > This is reading a lot of DT stuff very early, which may be slow. It is
> > also reading from the DT in the bind() step which we sometimes have to
> > do, but try to avoid.
>
> Could we set up the livetree pre-bind? What about MMU? On armv8 at least
> this would have a huge impact on performance. I've done some
> measurements and there is at least 1 order of magnitude difference
> between parsing FDT with no caches vs parsing livetree with, it's huge.

That seems like a great idea to me, in general. The fact that SPL sets
up the MMU on armv8 makes it 

Re: [PATCH 1/4] power: regulator: Trigger probe of regulators which are always-on or boot-on

2024-06-27 Thread Simon Glass
Hi Svyatoslav,

On Thu, 27 Jun 2024 at 10:09, Svyatoslav  wrote:
>
>
>
> 27 червня 2024 р. 11:48:46 GMT+03:00, Caleb Connolly 
>  написав(-ла):
> >
> >
> >On 27/06/2024 10:37, Simon Glass wrote:
> >> Hi Marek,
> >>
> >> On Thu, 27 Jun 2024 at 00:57, Marek Vasut  wrote:
> >>>
> >>> In case a regulator DT node contains regulator-always-on or 
> >>> regulator-boot-on
> >>> property, make sure the regulator gets correctly configured by U-Boot on 
> >>> start
> >>> up. Unconditionally probe such regulator drivers. This is a preparatory 
> >>> patch
> >>> for introduction of .regulator_post_probe() which would trigger the 
> >>> regulator
> >>> configuration.
> >>>
> >>> Parsing of regulator-always-on and regulator-boot-on DT property has been
> >>> moved to regulator_post_bind() as the information is required early, the
> >>> rest of the DT parsing has been kept in regulator_pre_probe() to avoid
> >>> slowing down the boot process.
> >>>
> >>> Signed-off-by: Marek Vasut 
> >>> ---
> >>> Cc: Ben Wolsieffer 
> >>> Cc: Caleb Connolly 
> >>> Cc: Chris Morgan 
> >>> Cc: Dragan Simic 
> >>> Cc: Eugen Hristev 
> >>> Cc: Francesco Dolcini 
> >>> Cc: Heinrich Schuchardt 
> >>> Cc: Jaehoon Chung 
> >>> Cc: Jagan Teki 
> >>> Cc: Jonas Karlman 
> >>> Cc: Kever Yang 
> >>> Cc: Kostya Porotchkin 
> >>> Cc: Matteo Lisi 
> >>> Cc: Mattijs Korpershoek 
> >>> Cc: Max Krummenacher 
> >>> Cc: Neil Armstrong 
> >>> Cc: Patrice Chotard 
> >>> Cc: Patrick Delaunay 
> >>> Cc: Philipp Tomsich 
> >>> Cc: Quentin Schulz 
> >>> Cc: Sam Day 
> >>> Cc: Simon Glass 
> >>> Cc: Sumit Garg 
> >>> Cc: Svyatoslav Ryhel 
> >>> Cc: Thierry Reding 
> >>> Cc: Tom Rini 
> >>> Cc: Volodymyr Babchuk 
> >>> Cc: u-boot-amlo...@groups.io
> >>> Cc: u-boot-q...@groups.io
> >>> Cc: u-b...@dh-electronics.com
> >>> Cc: u-boot@lists.denx.de
> >>> Cc: uboot-st...@st-md-mailman.stormreply.com
> >>> ---
> >>>   drivers/power/regulator/regulator-uclass.c | 22 +++---
> >>>   1 file changed, 15 insertions(+), 7 deletions(-)
> >>>
> >>> diff --git a/drivers/power/regulator/regulator-uclass.c 
> >>> b/drivers/power/regulator/regulator-uclass.c
> >>> index 66fd531da04..ccc4ef33d83 100644
> >>> --- a/drivers/power/regulator/regulator-uclass.c
> >>> +++ b/drivers/power/regulator/regulator-uclass.c
> >>> @@ -433,6 +433,8 @@ static int regulator_post_bind(struct udevice *dev)
> >>>  const char *property = "regulator-name";
> >>>
> >>>  uc_pdata = dev_get_uclass_plat(dev);
> >>> +   uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
> >>> +   uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
> >>>
> >>>  /* Regulator's mandatory constraint */
> >>>  uc_pdata->name = dev_read_string(dev, property);
> >>> @@ -444,13 +446,21 @@ static int regulator_post_bind(struct udevice *dev)
> >>>  return -EINVAL;
> >>>  }
> >>>
> >>> -   if (regulator_name_is_unique(dev, uc_pdata->name))
> >>> -   return 0;
> >>> +   if (!regulator_name_is_unique(dev, uc_pdata->name)) {
> >>> +   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
> >>> + property, dev->name, uc_pdata->name);
> >>> +   return -EINVAL;
> >>> +   }
> >>>
> >>> -   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
> >>> - property, dev->name, uc_pdata->name);
> >>> +   /*
> >>> +* In case the regulator has regulator-always-on or
> >>> +* regulator-boot-on DT property, trigger probe() to
> >>> +* configure its default state during startup.
> >>> +*/
> >>> +   if (uc_pdata->always_on && uc_pdata->boot_on)
> >>> +   dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);
> >>>
> >>> -   return -EINVAL;
> >>> +   return 0;
> >>>   }
> >>>
> >>>   static int regulator_pre_probe(struct udevice *dev)
> >>> @@ -473,8 +483,6 @@ static int regulator_pre_probe(struct udevice *dev)
> >>>  -ENODATA);
> >>>  uc_pdata->max_uA = dev_read_u32_default(dev, 
> >>> "regulator-max-microamp",
> >>>  -ENODATA);
> >>> -   uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
> >>> -   uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
> >>>  uc_pdata->ramp_delay = dev_read_u32_default(dev, 
> >>> "regulator-ramp-delay",
> >>>  0);
> >>>  uc_pdata->force_off = dev_read_bool(dev, 
> >>> "regulator-force-boot-off");
> >>> --
> >>> 2.43.0
> >>>
> >>
> >> This is reading a lot of DT stuff very early, which may be slow. It is
> >> also reading from the DT in the bind() step which we sometimes have to
> >> do, but try to avoid.
> >
> >Could we set up the livetree pre-bind? What about MMU? On armv8 at least 
> >this would have a huge impact on performance. I've done some measurements 
> >and there is at least 1 

Re: [PATCH 1/4] power: regulator: Trigger probe of regulators which are always-on or boot-on

2024-06-27 Thread Svyatoslav



27 червня 2024 р. 11:48:46 GMT+03:00, Caleb Connolly 
 написав(-ла):
>
>
>On 27/06/2024 10:37, Simon Glass wrote:
>> Hi Marek,
>> 
>> On Thu, 27 Jun 2024 at 00:57, Marek Vasut  wrote:
>>> 
>>> In case a regulator DT node contains regulator-always-on or 
>>> regulator-boot-on
>>> property, make sure the regulator gets correctly configured by U-Boot on 
>>> start
>>> up. Unconditionally probe such regulator drivers. This is a preparatory 
>>> patch
>>> for introduction of .regulator_post_probe() which would trigger the 
>>> regulator
>>> configuration.
>>> 
>>> Parsing of regulator-always-on and regulator-boot-on DT property has been
>>> moved to regulator_post_bind() as the information is required early, the
>>> rest of the DT parsing has been kept in regulator_pre_probe() to avoid
>>> slowing down the boot process.
>>> 
>>> Signed-off-by: Marek Vasut 
>>> ---
>>> Cc: Ben Wolsieffer 
>>> Cc: Caleb Connolly 
>>> Cc: Chris Morgan 
>>> Cc: Dragan Simic 
>>> Cc: Eugen Hristev 
>>> Cc: Francesco Dolcini 
>>> Cc: Heinrich Schuchardt 
>>> Cc: Jaehoon Chung 
>>> Cc: Jagan Teki 
>>> Cc: Jonas Karlman 
>>> Cc: Kever Yang 
>>> Cc: Kostya Porotchkin 
>>> Cc: Matteo Lisi 
>>> Cc: Mattijs Korpershoek 
>>> Cc: Max Krummenacher 
>>> Cc: Neil Armstrong 
>>> Cc: Patrice Chotard 
>>> Cc: Patrick Delaunay 
>>> Cc: Philipp Tomsich 
>>> Cc: Quentin Schulz 
>>> Cc: Sam Day 
>>> Cc: Simon Glass 
>>> Cc: Sumit Garg 
>>> Cc: Svyatoslav Ryhel 
>>> Cc: Thierry Reding 
>>> Cc: Tom Rini 
>>> Cc: Volodymyr Babchuk 
>>> Cc: u-boot-amlo...@groups.io
>>> Cc: u-boot-q...@groups.io
>>> Cc: u-b...@dh-electronics.com
>>> Cc: u-boot@lists.denx.de
>>> Cc: uboot-st...@st-md-mailman.stormreply.com
>>> ---
>>>   drivers/power/regulator/regulator-uclass.c | 22 +++---
>>>   1 file changed, 15 insertions(+), 7 deletions(-)
>>> 
>>> diff --git a/drivers/power/regulator/regulator-uclass.c 
>>> b/drivers/power/regulator/regulator-uclass.c
>>> index 66fd531da04..ccc4ef33d83 100644
>>> --- a/drivers/power/regulator/regulator-uclass.c
>>> +++ b/drivers/power/regulator/regulator-uclass.c
>>> @@ -433,6 +433,8 @@ static int regulator_post_bind(struct udevice *dev)
>>>  const char *property = "regulator-name";
>>> 
>>>  uc_pdata = dev_get_uclass_plat(dev);
>>> +   uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
>>> +   uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
>>> 
>>>  /* Regulator's mandatory constraint */
>>>  uc_pdata->name = dev_read_string(dev, property);
>>> @@ -444,13 +446,21 @@ static int regulator_post_bind(struct udevice *dev)
>>>  return -EINVAL;
>>>  }
>>> 
>>> -   if (regulator_name_is_unique(dev, uc_pdata->name))
>>> -   return 0;
>>> +   if (!regulator_name_is_unique(dev, uc_pdata->name)) {
>>> +   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
>>> + property, dev->name, uc_pdata->name);
>>> +   return -EINVAL;
>>> +   }
>>> 
>>> -   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
>>> - property, dev->name, uc_pdata->name);
>>> +   /*
>>> +* In case the regulator has regulator-always-on or
>>> +* regulator-boot-on DT property, trigger probe() to
>>> +* configure its default state during startup.
>>> +*/
>>> +   if (uc_pdata->always_on && uc_pdata->boot_on)
>>> +   dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);
>>> 
>>> -   return -EINVAL;
>>> +   return 0;
>>>   }
>>> 
>>>   static int regulator_pre_probe(struct udevice *dev)
>>> @@ -473,8 +483,6 @@ static int regulator_pre_probe(struct udevice *dev)
>>>  -ENODATA);
>>>  uc_pdata->max_uA = dev_read_u32_default(dev, 
>>> "regulator-max-microamp",
>>>  -ENODATA);
>>> -   uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
>>> -   uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
>>>  uc_pdata->ramp_delay = dev_read_u32_default(dev, 
>>> "regulator-ramp-delay",
>>>  0);
>>>  uc_pdata->force_off = dev_read_bool(dev, 
>>> "regulator-force-boot-off");
>>> --
>>> 2.43.0
>>> 
>> 
>> This is reading a lot of DT stuff very early, which may be slow. It is
>> also reading from the DT in the bind() step which we sometimes have to
>> do, but try to avoid.
>
>Could we set up the livetree pre-bind? What about MMU? On armv8 at least this 
>would have a huge impact on performance. I've done some measurements and there 
>is at least 1 order of magnitude difference between parsing FDT with no caches 
>vs parsing livetree with, it's huge.
>> 
>> Also this seems to happen in SPL and again pre-reloc and again in
>> U-Boot post-reloc?

Not so long ago I proposed a similar patchset with the same goal
and I have discovered massive issues with 

Re: [PATCH 1/4] power: regulator: Trigger probe of regulators which are always-on or boot-on

2024-06-27 Thread Caleb Connolly




On 27/06/2024 10:37, Simon Glass wrote:

Hi Marek,

On Thu, 27 Jun 2024 at 00:57, Marek Vasut  wrote:


In case a regulator DT node contains regulator-always-on or regulator-boot-on
property, make sure the regulator gets correctly configured by U-Boot on start
up. Unconditionally probe such regulator drivers. This is a preparatory patch
for introduction of .regulator_post_probe() which would trigger the regulator
configuration.

Parsing of regulator-always-on and regulator-boot-on DT property has been
moved to regulator_post_bind() as the information is required early, the
rest of the DT parsing has been kept in regulator_pre_probe() to avoid
slowing down the boot process.

Signed-off-by: Marek Vasut 
---
Cc: Ben Wolsieffer 
Cc: Caleb Connolly 
Cc: Chris Morgan 
Cc: Dragan Simic 
Cc: Eugen Hristev 
Cc: Francesco Dolcini 
Cc: Heinrich Schuchardt 
Cc: Jaehoon Chung 
Cc: Jagan Teki 
Cc: Jonas Karlman 
Cc: Kever Yang 
Cc: Kostya Porotchkin 
Cc: Matteo Lisi 
Cc: Mattijs Korpershoek 
Cc: Max Krummenacher 
Cc: Neil Armstrong 
Cc: Patrice Chotard 
Cc: Patrick Delaunay 
Cc: Philipp Tomsich 
Cc: Quentin Schulz 
Cc: Sam Day 
Cc: Simon Glass 
Cc: Sumit Garg 
Cc: Svyatoslav Ryhel 
Cc: Thierry Reding 
Cc: Tom Rini 
Cc: Volodymyr Babchuk 
Cc: u-boot-amlo...@groups.io
Cc: u-boot-q...@groups.io
Cc: u-b...@dh-electronics.com
Cc: u-boot@lists.denx.de
Cc: uboot-st...@st-md-mailman.stormreply.com
---
  drivers/power/regulator/regulator-uclass.c | 22 +++---
  1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/power/regulator/regulator-uclass.c 
b/drivers/power/regulator/regulator-uclass.c
index 66fd531da04..ccc4ef33d83 100644
--- a/drivers/power/regulator/regulator-uclass.c
+++ b/drivers/power/regulator/regulator-uclass.c
@@ -433,6 +433,8 @@ static int regulator_post_bind(struct udevice *dev)
 const char *property = "regulator-name";

 uc_pdata = dev_get_uclass_plat(dev);
+   uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
+   uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");

 /* Regulator's mandatory constraint */
 uc_pdata->name = dev_read_string(dev, property);
@@ -444,13 +446,21 @@ static int regulator_post_bind(struct udevice *dev)
 return -EINVAL;
 }

-   if (regulator_name_is_unique(dev, uc_pdata->name))
-   return 0;
+   if (!regulator_name_is_unique(dev, uc_pdata->name)) {
+   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
+ property, dev->name, uc_pdata->name);
+   return -EINVAL;
+   }

-   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
- property, dev->name, uc_pdata->name);
+   /*
+* In case the regulator has regulator-always-on or
+* regulator-boot-on DT property, trigger probe() to
+* configure its default state during startup.
+*/
+   if (uc_pdata->always_on && uc_pdata->boot_on)
+   dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);

-   return -EINVAL;
+   return 0;
  }

  static int regulator_pre_probe(struct udevice *dev)
@@ -473,8 +483,6 @@ static int regulator_pre_probe(struct udevice *dev)
 -ENODATA);
 uc_pdata->max_uA = dev_read_u32_default(dev, "regulator-max-microamp",
 -ENODATA);
-   uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
-   uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
 uc_pdata->ramp_delay = dev_read_u32_default(dev, 
"regulator-ramp-delay",
 0);
 uc_pdata->force_off = dev_read_bool(dev, "regulator-force-boot-off");
--
2.43.0



This is reading a lot of DT stuff very early, which may be slow. It is
also reading from the DT in the bind() step which we sometimes have to
do, but try to avoid.


Could we set up the livetree pre-bind? What about MMU? On armv8 at least 
this would have a huge impact on performance. I've done some 
measurements and there is at least 1 order of magnitude difference 
between parsing FDT with no caches vs parsing livetree with, it's huge.


Also this seems to happen in SPL and again pre-reloc and again in
U-Boot post-reloc?

Should we have a step in the init sequence where we set up the
regulators, by calling regulators_enable_boot_on() ?

Regards,
Simon


--
// Caleb (they/them)


Re: [PATCH 2/4] power: regulator: Convert regulators_enable_boot_on/off() to regulator_post_probe

2024-06-27 Thread Simon Glass
Hi Marek,


On Thu, 27 Jun 2024 at 00:57, Marek Vasut  wrote:
>
> Turn regulators_enable_boot_on() and regulators_enable_boot_off() into
> empty functions. Implement matching functionality in regulator_post_probe()
> instead. The regulator_post_probe() is called for all regulators after they
> probe, and regulators that have regulator-always-on or regulator-boot-on DT
> properties now always probe due to DM_FLAG_PROBE_AFTER_BIND being set on
> such regulators in regulator_post_bind().
>
> Finally, fold regulator_unset() functionality into regulator_autoset().
>
> Signed-off-by: Marek Vasut 
> ---
> Cc: Ben Wolsieffer 
> Cc: Caleb Connolly 
> Cc: Chris Morgan 
> Cc: Dragan Simic 
> Cc: Eugen Hristev 
> Cc: Francesco Dolcini 
> Cc: Heinrich Schuchardt 
> Cc: Jaehoon Chung 
> Cc: Jagan Teki 
> Cc: Jonas Karlman 
> Cc: Kever Yang 
> Cc: Kostya Porotchkin 
> Cc: Matteo Lisi 
> Cc: Mattijs Korpershoek 
> Cc: Max Krummenacher 
> Cc: Neil Armstrong 
> Cc: Patrice Chotard 
> Cc: Patrick Delaunay 
> Cc: Philipp Tomsich 
> Cc: Quentin Schulz 
> Cc: Sam Day 
> Cc: Simon Glass 
> Cc: Sumit Garg 
> Cc: Svyatoslav Ryhel 
> Cc: Thierry Reding 
> Cc: Tom Rini 
> Cc: Volodymyr Babchuk 
> Cc: u-boot-amlo...@groups.io
> Cc: u-boot-q...@groups.io
> Cc: u-b...@dh-electronics.com
> Cc: u-boot@lists.denx.de
> Cc: uboot-st...@st-md-mailman.stormreply.com
> ---
>  drivers/power/regulator/regulator-uclass.c | 60 +++---
>  1 file changed, 19 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/power/regulator/regulator-uclass.c 
> b/drivers/power/regulator/regulator-uclass.c
> index ccc4ef33d83..d52f273042f 100644
> --- a/drivers/power/regulator/regulator-uclass.c
> +++ b/drivers/power/regulator/regulator-uclass.c
> @@ -308,6 +308,11 @@ int regulator_autoset(struct udevice *dev)
> return ret;
> }
>
> +   if (uc_pdata->force_off) {
> +   ret = regulator_set_enable(dev, false);
> +   goto out;
> +   }
> +
> if (!uc_pdata->always_on && !uc_pdata->boot_on) {
> ret = -EMEDIUMTYPE;
> goto out;
> @@ -512,56 +517,28 @@ static int regulator_pre_probe(struct udevice *dev)
> return 0;
>  }
>
> -int regulators_enable_boot_on(bool verbose)
> +static int regulator_post_probe(struct udevice *dev)
>  {
> -   struct udevice *dev;
> -   struct uclass *uc;
> int ret;
>
> -   ret = uclass_get(UCLASS_REGULATOR, );
> -   if (ret)
> +   ret = regulator_autoset(dev);
> +   if (ret && ret != -EMEDIUMTYPE && ret != ENOSYS)
> return ret;
> -   for (uclass_first_device(UCLASS_REGULATOR, );
> -dev;
> -uclass_next_device()) {
> -   ret = regulator_autoset(dev);
> -   if (ret == -EMEDIUMTYPE) {
> -   ret = 0;
> -   continue;
> -   }
> -   if (verbose)
> -   regulator_show(dev, ret);
> -   if (ret == -ENOSYS)
> -   ret = 0;
> -   }
>
> -   return ret;
> +   if (_DEBUG)
> +   regulator_show(dev, ret);
> +
> +   return 0;
>  }
>
> -int regulators_enable_boot_off(bool verbose)
> +int regulators_enable_boot_on(bool verbose)
>  {
> -   struct udevice *dev;
> -   struct uclass *uc;
> -   int ret;
> -
> -   ret = uclass_get(UCLASS_REGULATOR, );
> -   if (ret)
> -   return ret;
> -   for (uclass_first_device(UCLASS_REGULATOR, );
> -dev;
> -uclass_next_device()) {
> -   ret = regulator_unset(dev);
> -   if (ret == -EMEDIUMTYPE) {
> -   ret = 0;
> -   continue;
> -   }
> -   if (verbose)
> -   regulator_show(dev, ret);
> -   if (ret == -ENOSYS)
> -   ret = 0;
> -   }
> +   return 0;
> +}
>
> -   return ret;
> +int regulators_enable_boot_off(bool verbose)
> +{
> +   return 0;
>  }
>
>  UCLASS_DRIVER(regulator) = {
> @@ -569,5 +546,6 @@ UCLASS_DRIVER(regulator) = {
> .name   = "regulator",
> .post_bind  = regulator_post_bind,
> .pre_probe  = regulator_pre_probe,
> +   .post_probe = regulator_post_probe,
> .per_device_plat_auto   = sizeof(struct dm_regulator_uclass_plat),
>  };
> --
> 2.43.0
>


Re: [PATCH 1/4] power: regulator: Trigger probe of regulators which are always-on or boot-on

2024-06-27 Thread Simon Glass
Hi Marek,

On Thu, 27 Jun 2024 at 00:57, Marek Vasut  wrote:
>
> In case a regulator DT node contains regulator-always-on or regulator-boot-on
> property, make sure the regulator gets correctly configured by U-Boot on start
> up. Unconditionally probe such regulator drivers. This is a preparatory patch
> for introduction of .regulator_post_probe() which would trigger the regulator
> configuration.
>
> Parsing of regulator-always-on and regulator-boot-on DT property has been
> moved to regulator_post_bind() as the information is required early, the
> rest of the DT parsing has been kept in regulator_pre_probe() to avoid
> slowing down the boot process.
>
> Signed-off-by: Marek Vasut 
> ---
> Cc: Ben Wolsieffer 
> Cc: Caleb Connolly 
> Cc: Chris Morgan 
> Cc: Dragan Simic 
> Cc: Eugen Hristev 
> Cc: Francesco Dolcini 
> Cc: Heinrich Schuchardt 
> Cc: Jaehoon Chung 
> Cc: Jagan Teki 
> Cc: Jonas Karlman 
> Cc: Kever Yang 
> Cc: Kostya Porotchkin 
> Cc: Matteo Lisi 
> Cc: Mattijs Korpershoek 
> Cc: Max Krummenacher 
> Cc: Neil Armstrong 
> Cc: Patrice Chotard 
> Cc: Patrick Delaunay 
> Cc: Philipp Tomsich 
> Cc: Quentin Schulz 
> Cc: Sam Day 
> Cc: Simon Glass 
> Cc: Sumit Garg 
> Cc: Svyatoslav Ryhel 
> Cc: Thierry Reding 
> Cc: Tom Rini 
> Cc: Volodymyr Babchuk 
> Cc: u-boot-amlo...@groups.io
> Cc: u-boot-q...@groups.io
> Cc: u-b...@dh-electronics.com
> Cc: u-boot@lists.denx.de
> Cc: uboot-st...@st-md-mailman.stormreply.com
> ---
>  drivers/power/regulator/regulator-uclass.c | 22 +++---
>  1 file changed, 15 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/power/regulator/regulator-uclass.c 
> b/drivers/power/regulator/regulator-uclass.c
> index 66fd531da04..ccc4ef33d83 100644
> --- a/drivers/power/regulator/regulator-uclass.c
> +++ b/drivers/power/regulator/regulator-uclass.c
> @@ -433,6 +433,8 @@ static int regulator_post_bind(struct udevice *dev)
> const char *property = "regulator-name";
>
> uc_pdata = dev_get_uclass_plat(dev);
> +   uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
> +   uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
>
> /* Regulator's mandatory constraint */
> uc_pdata->name = dev_read_string(dev, property);
> @@ -444,13 +446,21 @@ static int regulator_post_bind(struct udevice *dev)
> return -EINVAL;
> }
>
> -   if (regulator_name_is_unique(dev, uc_pdata->name))
> -   return 0;
> +   if (!regulator_name_is_unique(dev, uc_pdata->name)) {
> +   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
> + property, dev->name, uc_pdata->name);
> +   return -EINVAL;
> +   }
>
> -   debug("'%s' of dev: '%s', has nonunique value: '%s\n",
> - property, dev->name, uc_pdata->name);
> +   /*
> +* In case the regulator has regulator-always-on or
> +* regulator-boot-on DT property, trigger probe() to
> +* configure its default state during startup.
> +*/
> +   if (uc_pdata->always_on && uc_pdata->boot_on)
> +   dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);
>
> -   return -EINVAL;
> +   return 0;
>  }
>
>  static int regulator_pre_probe(struct udevice *dev)
> @@ -473,8 +483,6 @@ static int regulator_pre_probe(struct udevice *dev)
> -ENODATA);
> uc_pdata->max_uA = dev_read_u32_default(dev, "regulator-max-microamp",
> -ENODATA);
> -   uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
> -   uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
> uc_pdata->ramp_delay = dev_read_u32_default(dev, 
> "regulator-ramp-delay",
> 0);
> uc_pdata->force_off = dev_read_bool(dev, "regulator-force-boot-off");
> --
> 2.43.0
>

This is reading a lot of DT stuff very early, which may be slow. It is
also reading from the DT in the bind() step which we sometimes have to
do, but try to avoid.

Also this seems to happen in SPL and again pre-reloc and again in
U-Boot post-reloc?

Should we have a step in the init sequence where we set up the
regulators, by calling regulators_enable_boot_on() ?

Regards,
Simon


[PATCH] net: ftgmac100: Fixed the cache coherency issues of rx memory

2024-06-27 Thread Jacky Chou
When executing TFTP, the ARP will be replied to after receiving
the ARP. U-boot's ARP routine modifies the data in the receive
packet in response to the ARP packet and then copies it
into the transmit packet.
At this point, the received packet cache is inconsistent.
It is possible that the cache will perform a writeback action to
affect the MAC receiving packets.

Avoid the same problem that occurs in other networking protocols.
In the free_pkt function, ensure cache and memory consistency.

Signed-off-by: Jacky Chou 
---
 drivers/net/ftgmac100.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/net/ftgmac100.c b/drivers/net/ftgmac100.c
index 9b536fd5ab..56854dfab8 100644
--- a/drivers/net/ftgmac100.c
+++ b/drivers/net/ftgmac100.c
@@ -411,6 +411,14 @@ static int ftgmac100_free_pkt(struct udevice *dev, uchar 
*packet, int length)
ulong des_end = des_start +
roundup(sizeof(*curr_des), ARCH_DMA_MINALIGN);
 
+   /*
+* Make sure there are no stale data in write-back over this area, which
+* might get written into the memory while the ftgmac100 also writes
+* into the same memory area.
+*/
+   flush_dcache_range((ulong)net_rx_packets[priv->rx_index],
+  (ulong)net_rx_packets[priv->rx_index] + 
PKTSIZE_ALIGN);
+
/* Release buffer to DMA and flush descriptor */
curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
flush_dcache_range(des_start, des_end);
-- 
2.34.1



Re: [PATCH v1] board: mpfs_icicle: implement board_fdt_blob_setup()

2024-06-27 Thread Simon Glass
Hi Connor,

On Thu, 27 Jun 2024 at 10:38, Conor Dooley  wrote:
>
> On Thu, Jun 27, 2024 at 09:36:49AM +0100, Simon Glass wrote:
> >
> > On Tue, 25 Jun 2024 at 15:34, Tom Rini  wrote:
> > >
> > > On Tue, Jun 25, 2024 at 10:08:06AM +0100, Conor Dooley wrote:
> > >
> > > > The firmware on the Icicle is capable of providing a devicetree in a1 to
> > > > U-Boot, but until now the devicetree has been packaged in a "payload" 
> > > > [1]
> > > > alongside U-Boot (or other bootloaders/RTOSes) and appended to the 
> > > > image.
> > > > The address of this appended devicetree is placed in a1 by the firmware.
> > > > This meant that the mechanism used by OF_SEPARATE to locate the
> > > > devicetree at the end of the image would pick up the one provided by the
> > > > firmware when u-boot-nodtb.bin was in the payload and U-Boot's 
> > > > devicetree
> > > > when u-boot.bin was.
> > > >
> > > > The firmware is now going to be capable of providing a minimal 
> > > > devicetree
> > > > (quite cut down due to severe space constraints), but this devicetree is
> > > > linked into the firmware that runs out of the L2 rather than at the end
> > > > of the U-Boot image. Implement board_fdt_blob_setup() so that this
> > > > devicetree can be optionally used, and the devicetree provided in the
> > > > "payload" can be used without relying on "happening" to implement the
> > > > same strategy as OF_SEPARATE expects in combination with
> > > > u-boot-nodtb.bin. Unlike other RISC-V boards, the firmware provided
> > > > devicetree is only used when OF_BOARD is set, so that the almost
> > > > certainly more complete devicetree in U-Boot will be used unless
> > > > explicitly requested otherwise.
> > > >
> > > > Link: 
> > > > https://github.com/polarfire-soc/hart-software-services/blob/master/tools/hss-payload-generator/README.md
> > > >  [1]
> > > > Signed-off-by: Conor Dooley 
> > > > ---
> > > > CC: Ivan Griffin 
> > > > CC: Padmarao Begari 
> > > > CC: Cyril Jean 
> > > > CC: Tom Rini 
> > > > CC: Conor Dooley 
> > > > CC: u-boot@lists.denx.de
> > > > ---
> > > >  board/microchip/mpfs_icicle/mpfs_icicle.c | 19 +++
> > > >  1 file changed, 19 insertions(+)
> > > >
> > > > diff --git a/board/microchip/mpfs_icicle/mpfs_icicle.c 
> > > > b/board/microchip/mpfs_icicle/mpfs_icicle.c
> > > > index 4d7d843dfa3..2c1f7175f0e 100644
> > > > --- a/board/microchip/mpfs_icicle/mpfs_icicle.c
> > > > +++ b/board/microchip/mpfs_icicle/mpfs_icicle.c
> > > > @@ -9,6 +9,7 @@
> > > >  #include 
> > > >  #include 
> > > >  #include 
> > > > +#include 
> > > >
> > > >  DECLARE_GLOBAL_DATA_PTR;
> > > >
> > > > @@ -50,6 +51,24 @@ static void read_device_serial_number(u8 *response, 
> > > > u8 response_size)
> > > >   response_buf[idx] = readb(MPFS_SYS_SERVICE_MAILBOX + idx);
> > > >  }
> > > >
> > > > +void *board_fdt_blob_setup(int *err)
> > > > +{
> > > > + *err = 0;
> > > > + /*
> > > > +  * The devicetree provided by the previous stage is very minimal 
> > > > due to
> > > > +  * severe space constraints. The firmware performs no fixups etc.
> > > > +  * U-Boot, if providing a devicetree, almost certainly has a 
> > > > better
> > > > +  * more complete one than the firmware so that provided by the 
> > > > firmware
> > > > +  * is ignored for OF_SEPARATE.
> > > > +  */
> > > > + if (IS_ENABLED(CONFIG_OF_BOARD)) {
> > > > + if (gd->arch.firmware_fdt_addr)
> > > > + return (ulong 
> > > > *)(uintptr_t)gd->arch.firmware_fdt_addr;
> > > > + }
> > > > +
> > > > + return (ulong *)_end;
> > > > +}
> > > > +
> > > >  int board_init(void)
> > > >  {
> > > >   /* For now nothing to do here. */
> > >
> > > I'm adding in Simon and Ilias as this touches on one of those frequent
> > > topics about how device trees can/should be passed along to us.
> >
> > The only thing I can think of is implementing bloblist in  the a1 (?)
> > firmware, then passing the DT in that.
>
> a1 is the register that is used on riscv to pass the dtb, I think the
> corresponding thing on arm64 is x0.
>
> Re-reading the firware handoff spec, it's difficult to see what benefits
> it actually provides us when we only ever have a single dtb which the
> firmware does not interact with/use.
> We are super space constrained in the firmware even carving out 4.5 KiB
> for a devicetree blob is a stretch and requires disabling other features
> and ripping out anything in the DT not required for U-Boot to load the OS.
> Even the ~1 KiB mentioned in bloblist.h for handling a bloblist would be a
> challenge.
>
> I think the only way a bloblist could work is if it was created at build
> time and linked into the firmware, since the on-disk format seems pretty
> minimal. Is there tooling for generating a bloblist at build time that I
> could use to check whether or not a bloblist is viable?
> I'd also have to investigate how that would interact with OpenSBI, since
> it's integrated into the 

Re: [PATCH v1 1/1] include: configs: tegra-common-post: make usb first boot target

2024-06-27 Thread Svyatoslav Ryhel
вт, 18 черв. 2024 р. о 17:16 Svyatoslav  пише:
>
>
>
> 18 червня 2024 р. 15:23:09 GMT+03:00, Thierry Reding  
> написав(-ла):
> >On Tue Jun 18, 2024 at 2:00 PM CEST, Svyatoslav Ryhel wrote:
> >> This ensures that the device can boot from a USB device prior to MMC. 
> >> Useful
> >> cases are when installing a new OS from USB while MMC still has a working 
> >> OS
> >> configuration or if the OS configuration is broken in late boot stages
> >> (kernel boots but the system does not start).
> >>
> >> Signed-off-by: Svyatoslav Ryhel 
> >> ---
> >>  include/configs/tegra-common-post.h | 2 +-
> >>  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> >What's the implication of this if no USB mass storage device is found?
> >How does this behave when USB cannot be read or booting from it doesn't
> >work?
> >
> >I vaguely recall that boot order doesn't always proceed, though
> >admittedly I haven't tested all of these edge-cases in a long time.
> >
> >Thierry
>
> If no USB mass storage is found bootflow will continue with the next
> device in the list (mmc1) with co-responding info that booting from
> usb failed. I have tested this on lg p895 which has only mmc0 and
> with asus transformers which have usb, mmc0 and mmc1 in all
> possible configurations. I did not have booting issues whatsoever.
> ATM, transformers use boot order which I have proposed in this
> commit.
>
> Best regards,
> Svyatoslav R.

Thierry,

Since you have not responded to my statement above I assume that
you are fine with applying this change. In case you have any
objections please answer as soon as you can since I am planning to
include it into merge request for the next merge window.

Best regards,
Svyatoslav R.


[PATCH] Proposed changes to dynamic UUIDs v3

2024-06-27 Thread Vincent Stehlé
Here are the changes that I would like to suggest for the "efi:
CapsuleUpdate: support for dynamic UUIDs" v3 patch series:

- Convert from big-endian UUID to little-endian GUID in
  efi_capsule_update_info_gen_ids().

- Fix tmp size and masking in gen_uuid_v5().

- Use UUID_STR_FORMAT_STD in all places where we are dealing with a
  big-endian UUID.

- Update all GUIDs constants in the code and in the tests accordingly. This
  gets rid of the following broken UUIDs:

5af91295-5a99-f62b-80d7-e9574de87170
8ee418dc-7e00-e156-80a7-274fbbc05ba8
935fe837-fac8-4394-c008-737d8852c60d
fd5db83c-12f3-a46b-80a9-e3007c7ff56e
ffd97379-0956-fa94-c003-8bfcf5cc097b

- Also, a few minor modifications here and there.

Signed-off-by: Vincent Stehlé 
Cc: Caleb Connolly 
Cc: Tom Rini 
Cc: Heinrich Schuchardt 
Cc: Ilias Apalodimas 
Cc: Simon Glass 
Cc: Mario Six 
Cc: Alper Nebi Yasak 
Cc: Abdellatif El Khlifi 
Cc: Richard Hughes 
---
 include/sandbox_efi_capsule.h  |  6 +++---
 lib/efi_loader/efi_firmware.c  | 14 +++---
 lib/uuid.c |  8 
 test/lib/uuid.c| 12 ++--
 .../test_efi_capsule/test_capsule_firmware_fit.py  |  4 ++--
 .../test_efi_capsule/test_capsule_firmware_raw.py  |  8 
 .../test_capsule_firmware_signed_fit.py|  2 +-
 .../test_capsule_firmware_signed_raw.py|  4 ++--
 test/py/tests/test_efi_capsule/version.dts |  6 +++---
 tools/.gitignore   |  1 +
 tools/binman/etype/efi_capsule.py  |  2 +-
 tools/binman/ftest.py  |  2 +-
 tools/genguid.c|  7 +++
 13 files changed, 42 insertions(+), 34 deletions(-)

diff --git a/include/sandbox_efi_capsule.h b/include/sandbox_efi_capsule.h
index 25ac496ea24..6f0de5a1e25 100644
--- a/include/sandbox_efi_capsule.h
+++ b/include/sandbox_efi_capsule.h
@@ -6,9 +6,9 @@
 #if !defined(_SANDBOX_EFI_CAPSULE_H_)
 #define _SANDBOX_EFI_CAPSULE_H_
 
-#define SANDBOX_UBOOT_IMAGE_GUID   "fd5db83c-12f3-a46b-80a9-e3007c7ff56e"
-#define SANDBOX_UBOOT_ENV_IMAGE_GUID   "935fe837-fac8-4394-c008-737d8852c60d"
-#define SANDBOX_FIT_IMAGE_GUID "ffd97379-0956-fa94-c003-8bfcf5cc097b"
+#define SANDBOX_UBOOT_IMAGE_GUID   "50980990-5af9-5522-86e2-8f05f4d7313c"
+#define SANDBOX_UBOOT_ENV_IMAGE_GUID   "3554b655-b9f0-5240-ace2-6f34c2f7fcca"
+#define SANDBOX_FIT_IMAGE_GUID "8b38adc7-df0c-5769-8b89-c090ca3d07a7"
 #define SANDBOX_INCORRECT_GUID "058b7d83-50d5-4c47-a195-60d86ad341c4"
 
 #define UBOOT_FIT_IMAGE"u-boot_bin_env.itb"
diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
index a8dafe4f01a..f0d0c3fa972 100644
--- a/lib/efi_loader/efi_firmware.c
+++ b/lib/efi_loader/efi_firmware.c
@@ -258,7 +258,7 @@ void efi_firmware_fill_version_info(struct 
efi_firmware_image_descriptor *image_
 static efi_status_t efi_capsule_update_info_gen_ids(void)
 {
int ret, i;
-   struct uuid namespace;
+   struct uuid namespace, type;
const char *compatible; /* Full array including null bytes */
struct efi_fw_image *fw_array;
 
@@ -269,7 +269,7 @@ static efi_status_t efi_capsule_update_info_gen_ids(void)
return EFI_SUCCESS;
 
ret = uuid_str_to_bin(CONFIG_EFI_CAPSULE_NAMESPACE_UUID,
-   (unsigned char *), UUID_STR_FORMAT_GUID);
+   (unsigned char *), UUID_STR_FORMAT_STD);
if (ret) {
log_debug("%s: CONFIG_EFI_CAPSULE_NAMESPACE_UUID is invalid: 
%d\n", __func__, ret);
return EFI_UNSUPPORTED;
@@ -289,12 +289,20 @@ static efi_status_t efi_capsule_update_info_gen_ids(void)
 
for (i = 0; i < update_info.num_images; i++) {
gen_uuid_v5(,
-   (struct uuid *)_array[i].image_type_id,
+   ,
compatible, strlen(compatible),
fw_array[i].fw_name, 
u16_strsize(fw_array[i].fw_name)
- sizeof(uint16_t),
NULL);
 
+   /* Convert to little-endian GUID. */
+   fw_array[i].image_type_id = (efi_guid_t)EFI_GUID(
+   be32_to_cpu(type.time_low), be16_to_cpu(type.time_mid),
+   be16_to_cpu(type.time_hi_and_version),
+   type.clock_seq_hi_and_reserved, type.clock_seq_low,
+   type.node[0], type.node[1], type.node[2], type.node[3],
+   type.node[4], type.node[5]);
+
log_debug("Image %ls UUID %pUs\n", fw_array[i].fw_name,
  _array[i].image_type_id);
}
diff --git a/lib/uuid.c b/lib/uuid.c
index 89911b06ccc..a8c3a504090 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -391,7 +391,7 @@ void 

[PATCH] board/include: ti/env: j721e.env/ti_common: Fix cpsw0_qsgmii_phyinit

2024-06-27 Thread Siddharth Vadapalli
The command "main_cpsw0_qsgmii_phyinit" has to be run depending on
whether or not the "do_main_cpsw0_qsgmii_phyinit" variable is set.
However, there is no support for the cases where the environment variable
"do_main_cpsw0_qsgmii_phyinit" is updated at runtime. On J721E, the value
of "do_main_cpsw0_qsgmii_phyinit" is updated at runtime.

Fix the existing implementation in order to handle the case where the
value of "do_main_cpsw0_qsgmii_phyinit" is updated at runtime. Do so by
introducing the environment variable "update_do_main_cpsw0_qsgmii_phyinit"
which defaults to setting "do_main_cpsw0_qsgmii_phyinit" to zero, but at
the same time, it allows the board to update the value at runtime.

Fixes: 0d72b0f2f83b ("include: env: ti: ti_common: Run 
main_cpsw0_qsgmii_phyinit conditionally")
Signed-off-by: Siddharth Vadapalli 
---

Hello,

This patch is based on commit
899b088674 Merge patch series "pxe: Add debugging for booting"
of U-Boot's next branch.

Regards,
Siddharth.

 board/ti/j721e/j721e.env | 9 +
 include/env/ti/ti_common.env | 3 ++-
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/board/ti/j721e/j721e.env b/board/ti/j721e/j721e.env
index 38bfd7d496..03d7e81aa8 100644
--- a/board/ti/j721e/j721e.env
+++ b/board/ti/j721e/j721e.env
@@ -29,7 +29,7 @@ bootdir=/boot
 rd_spec=-
 
 #if CONFIG_TARGET_J7200_A72_EVM
-do_main_cpsw0_qsgmii_phyinit=1
+update_do_main_cpsw0_qsgmii_phyinit=setenv do_main_cpsw0_qsgmii_phyinit 1;
 init_main_cpsw0_qsgmii_phy=gpio set gpio@22_17;
gpio clear gpio@22_16
 main_cpsw0_qsgmii_phyinit=
@@ -39,10 +39,11 @@ main_cpsw0_qsgmii_phyinit=
 #elif CONFIG_TARGET_J721E_A72_EVM
 init_main_cpsw0_qsgmii_phy=gpio set gpio@22_17;
gpio clear gpio@22_16
-main_cpsw0_qsgmii_phyinit=
+update_do_main_cpsw0_qsgmii_phyinit=
if test $board_name = J721EX-PM1-SOM || test $board_name = 
J721EX-PM2-SOM || test $board_name = j721e; then
-   do_main_cpsw0_qsgmii_phyinit=1; else
-   do_main_cpsw0_qsgmii_phyinit=0; fi;
+   setenv do_main_cpsw0_qsgmii_phyinit 1; else
+   setenv do_main_cpsw0_qsgmii_phyinit 0; fi;
+main_cpsw0_qsgmii_phyinit=
if test ${do_main_cpsw0_qsgmii_phyinit} -eq 1 && test ${dorprocboot} 
-eq 1 && test ${boot} = mmc; then
run init_main_cpsw0_qsgmii_phy; \
fi;
diff --git a/include/env/ti/ti_common.env b/include/env/ti/ti_common.env
index c5c3642177..d0b3d698a0 100644
--- a/include/env/ti/ti_common.env
+++ b/include/env/ti/ti_common.env
@@ -23,9 +23,10 @@ get_fit_overlaystring=
done;
 get_fit_config=setexpr name_fit_config gsub / _ conf-${fdtfile}
 run_fit=run get_fit_config; bootm 
${addr_fit}#${name_fit_config}${overlaystring}
-do_main_cpsw0_qsgmii_phyinit=0
+update_do_main_cpsw0_qsgmii_phyinit=setenv do_main_cpsw0_qsgmii_phyinit 0;
 bootcmd_ti_mmc=
run findfdt; run init_${boot};
+   run update_do_main_cpsw0_qsgmii_phyinit;
 #if CONFIG_CMD_REMOTEPROC
if test ${do_main_cpsw0_qsgmii_phyinit} -eq 1;
then run main_cpsw0_qsgmii_phyinit;
-- 
2.40.1



Re: [PATCH v1] board: mpfs_icicle: implement board_fdt_blob_setup()

2024-06-27 Thread Conor Dooley
On Thu, Jun 27, 2024 at 09:36:49AM +0100, Simon Glass wrote:
> 
> On Tue, 25 Jun 2024 at 15:34, Tom Rini  wrote:
> >
> > On Tue, Jun 25, 2024 at 10:08:06AM +0100, Conor Dooley wrote:
> >
> > > The firmware on the Icicle is capable of providing a devicetree in a1 to
> > > U-Boot, but until now the devicetree has been packaged in a "payload" [1]
> > > alongside U-Boot (or other bootloaders/RTOSes) and appended to the image.
> > > The address of this appended devicetree is placed in a1 by the firmware.
> > > This meant that the mechanism used by OF_SEPARATE to locate the
> > > devicetree at the end of the image would pick up the one provided by the
> > > firmware when u-boot-nodtb.bin was in the payload and U-Boot's devicetree
> > > when u-boot.bin was.
> > >
> > > The firmware is now going to be capable of providing a minimal devicetree
> > > (quite cut down due to severe space constraints), but this devicetree is
> > > linked into the firmware that runs out of the L2 rather than at the end
> > > of the U-Boot image. Implement board_fdt_blob_setup() so that this
> > > devicetree can be optionally used, and the devicetree provided in the
> > > "payload" can be used without relying on "happening" to implement the
> > > same strategy as OF_SEPARATE expects in combination with
> > > u-boot-nodtb.bin. Unlike other RISC-V boards, the firmware provided
> > > devicetree is only used when OF_BOARD is set, so that the almost
> > > certainly more complete devicetree in U-Boot will be used unless
> > > explicitly requested otherwise.
> > >
> > > Link: 
> > > https://github.com/polarfire-soc/hart-software-services/blob/master/tools/hss-payload-generator/README.md
> > >  [1]
> > > Signed-off-by: Conor Dooley 
> > > ---
> > > CC: Ivan Griffin 
> > > CC: Padmarao Begari 
> > > CC: Cyril Jean 
> > > CC: Tom Rini 
> > > CC: Conor Dooley 
> > > CC: u-boot@lists.denx.de
> > > ---
> > >  board/microchip/mpfs_icicle/mpfs_icicle.c | 19 +++
> > >  1 file changed, 19 insertions(+)
> > >
> > > diff --git a/board/microchip/mpfs_icicle/mpfs_icicle.c 
> > > b/board/microchip/mpfs_icicle/mpfs_icicle.c
> > > index 4d7d843dfa3..2c1f7175f0e 100644
> > > --- a/board/microchip/mpfs_icicle/mpfs_icicle.c
> > > +++ b/board/microchip/mpfs_icicle/mpfs_icicle.c
> > > @@ -9,6 +9,7 @@
> > >  #include 
> > >  #include 
> > >  #include 
> > > +#include 
> > >
> > >  DECLARE_GLOBAL_DATA_PTR;
> > >
> > > @@ -50,6 +51,24 @@ static void read_device_serial_number(u8 *response, u8 
> > > response_size)
> > >   response_buf[idx] = readb(MPFS_SYS_SERVICE_MAILBOX + idx);
> > >  }
> > >
> > > +void *board_fdt_blob_setup(int *err)
> > > +{
> > > + *err = 0;
> > > + /*
> > > +  * The devicetree provided by the previous stage is very minimal 
> > > due to
> > > +  * severe space constraints. The firmware performs no fixups etc.
> > > +  * U-Boot, if providing a devicetree, almost certainly has a better
> > > +  * more complete one than the firmware so that provided by the 
> > > firmware
> > > +  * is ignored for OF_SEPARATE.
> > > +  */
> > > + if (IS_ENABLED(CONFIG_OF_BOARD)) {
> > > + if (gd->arch.firmware_fdt_addr)
> > > + return (ulong 
> > > *)(uintptr_t)gd->arch.firmware_fdt_addr;
> > > + }
> > > +
> > > + return (ulong *)_end;
> > > +}
> > > +
> > >  int board_init(void)
> > >  {
> > >   /* For now nothing to do here. */
> >
> > I'm adding in Simon and Ilias as this touches on one of those frequent
> > topics about how device trees can/should be passed along to us.
> 
> The only thing I can think of is implementing bloblist in  the a1 (?)
> firmware, then passing the DT in that.

a1 is the register that is used on riscv to pass the dtb, I think the
corresponding thing on arm64 is x0.

Re-reading the firware handoff spec, it's difficult to see what benefits
it actually provides us when we only ever have a single dtb which the
firmware does not interact with/use.
We are super space constrained in the firmware even carving out 4.5 KiB
for a devicetree blob is a stretch and requires disabling other features
and ripping out anything in the DT not required for U-Boot to load the OS.
Even the ~1 KiB mentioned in bloblist.h for handling a bloblist would be a
challenge.

I think the only way a bloblist could work is if it was created at build
time and linked into the firmware, since the on-disk format seems pretty
minimal. Is there tooling for generating a bloblist at build time that I
could use to check whether or not a bloblist is viable? 
I'd also have to investigate how that would interact with OpenSBI, since
it's integrated into the firmware and involved with loading U-Boot.

> It seems that you still need to be able to turn that on and off in
> U-Boot though. So far we have not agreed the mechanism to do that, I
> have the same problem, with a pending patch here[1]

It seems your patch is trying to do some runtime determination of
whether to examine the 

Re: [PATCH v5 14/16] rockchip: Avoid #ifdefs in RK3399 SPL

2024-06-27 Thread Simon Glass
Hi Jonas,

On Thu, 27 Jun 2024 at 10:00, Jonas Karlman  wrote:
>
> Hi Simon,
>
> On 2024-06-27 10:02, Simon Glass wrote:
> > Hi Jonas,
> >
> > On Wed, 26 Jun 2024 at 17:16, Jonas Karlman  wrote:
> >>
> >> Hi Simon,
> >>
> >> On 2024-06-26 17:59, Simon Glass wrote:
> >>> The code here is confusing due to large blocks which are #ifdefed out.
> >>> Add a function phase_sdram_init() which returns whether SDRAM init
> >>> should happen in the current phase, using that as needed to control the
> >>> code flow.
> >>>
> >>> This increases code size by about 500 bytes in SPL when the cache is on,
> >>> since it must call the rather large rockchip_sdram_size() function.
> >>>
> >>> - Drop the non-dcache optimisation, since the cache should normally be on
> >>>
> >>> Signed-off-by: Simon Glass 
> >>> ---
> >>>
> >>> Changes in v5:
> >>> - Move setting of pmugrf into the probe() function
> >>>
> >>> Changes in v3:
> >>> - Split out the refactoring into a separate patch
> >>>
> >>>  drivers/ram/rockchip/sdram_rk3399.c | 33 ++---
> >>>  1 file changed, 16 insertions(+), 17 deletions(-)
> >>>
> >>> diff --git a/drivers/ram/rockchip/sdram_rk3399.c 
> >>> b/drivers/ram/rockchip/sdram_rk3399.c
> >>> index 3c4e20f4e80..b259e8e3dd6 100644
> >>> --- a/drivers/ram/rockchip/sdram_rk3399.c
> >>> +++ b/drivers/ram/rockchip/sdram_rk3399.c
> >>
> >> [snip]
> >>
> >>> +/**
> >>> + * phase_sdram_init() - Check if this is the phase where SDRAM init 
> >>> happens
> >>> + *
> >>> + * Returns: true to do SDRAM init in this phase, false to not
> >>> + */
> >>> +static bool phase_sdram_init(void)
> >>> +{
> >>> + return spl_phase() == PHASE_TPL ||
> >>> + (!IS_ENABLED(CONFIG_TPL) && !spl_in_proper());
> >>
> >> This still need to check for !IS_ENABLED(CONFIG_ROCKCHIP_EXTERNAL_TPL)
> >> to be correct, else you must build with both CONFIG_TPL and
> >> CONFIG_ROCKCHIP_EXTERNAL_TPL or the generated SPL will incorrectly try
> >> to initialize DRAM.
> >>
> >> DRAM should only be initialized in TPL or ROCKCHIP_EXTERNAL_TPL,
> >> or if none of them are defined in SPL. All other phases should
> >> just read and report dram size.
> >
> > Thanks for the info.
> >
> > The reason I am finding this hard to understand is that
> > ROCKCHIP_EXTERNAL_TPL does not appear in the code as it is. So I
> > cannot figure out why it needs to be added. Is there a bug in the
> > current code, or does my patch introduce a bug, or...?
>
> The current code does not handle ROCKCHIP_EXTERNAL_TPL and TPL must be
> built to later be replaced with the external TPL blob.
>
> This adds a new helper that states "Check if this is the phase where
> SDRAM init happens", and for this statement to be true it should also
> consider ROCKCHIP_EXTERNAL_TPL or a bugfix patch is later needed for
> this newly added helper.
>
> Adding !IS_ENABLED(CONFIG_ROCKCHIP_EXTERNAL_TPL) should make this
> statement be valid for the foreseeable combinations.
>
> return spl_phase() == PHASE_TPL ||
>(!IS_ENABLED(CONFIG_TPL) &&
> !IS_ENABLED(CONFIG_ROCKCHIP_EXTERNAL_TPL) &&
> !spl_in_proper());
>
> With that it should be possible to have TPL=n and ROCKCHIP_EXTERNAL_TPL=y
> and produce a working SPL.

Thanks very much, I understand it now.

Regards,
Simon


[PATCH v6 8/8] rockchip: Avoid #ifdefs in RK3399 SPL

2024-06-27 Thread Simon Glass
The code here is confusing due to large blocks which are #ifdefed out.
Add a function phase_sdram_init() which returns whether SDRAM init
should happen in the current phase, using that as needed to control the
code flow.

This increases code size by about 500 bytes in SPL when the cache is on,
since it must call the rather large rockchip_sdram_size() function.

- Drop the non-dcache optimisation, since the cache should normally be on

Signed-off-by: Simon Glass 
---

Changes in v6:
Take account of ROCKCHIP_EXTERNAL_TPL in phase_sdram_init()

Changes in v5:
- Move setting of pmugrf into the probe() function

Changes in v3:
- Split out the refactoring into a separate patch

 drivers/ram/rockchip/sdram_rk3399.c | 35 +++--
 1 file changed, 18 insertions(+), 17 deletions(-)

diff --git a/drivers/ram/rockchip/sdram_rk3399.c 
b/drivers/ram/rockchip/sdram_rk3399.c
index bc79c034808..55c0d1d2aed 100644
--- a/drivers/ram/rockchip/sdram_rk3399.c
+++ b/drivers/ram/rockchip/sdram_rk3399.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -63,8 +64,6 @@ struct chan_info {
 };
 
 struct dram_info {
-#if defined(CONFIG_TPL_BUILD) || \
-   (!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD))
u32 pwrup_srefresh_exit[2];
struct chan_info chan[2];
struct clk ddr_clk;
@@ -75,7 +74,6 @@ struct dram_info {
struct rk3399_pmusgrf_regs *pmusgrf;
struct rk3399_ddr_cic_regs *cic;
const struct sdram_rk3399_ops *ops;
-#endif
struct ram_info info;
struct rk3399_pmugrf_regs *pmugrf;
 };
@@ -92,9 +90,6 @@ struct sdram_rk3399_ops {
struct rk3399_sdram_params *params);
 };
 
-#if defined(CONFIG_TPL_BUILD) || \
-   (!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD))
-
 struct rockchip_dmc_plat {
 #if CONFIG_IS_ENABLED(OF_PLATDATA)
struct dtd_rockchip_rk3399_dmc dtplat;
@@ -191,6 +186,19 @@ struct io_setting {
},
 };
 
+/**
+ * phase_sdram_init() - Check if this is the phase where SDRAM init happens
+ *
+ * Returns: true to do SDRAM init in this phase, false to not
+ */
+static bool phase_sdram_init(void)
+{
+   return spl_phase() == PHASE_TPL ||
+   (!IS_ENABLED(CONFIG_TPL) &&
+!IS_ENABLED(CONFIG_ROCKCHIP_EXTERNAL_TPL) &&
+!spl_in_proper());
+}
+
 static struct io_setting *
 lpddr4_get_io_settings(const struct rk3399_sdram_params *params, u32 mr5)
 {
@@ -3024,7 +3032,7 @@ static int rk3399_dmc_of_to_plat(struct udevice *dev)
struct rockchip_dmc_plat *plat = dev_get_plat(dev);
int ret;
 
-   if (!CONFIG_IS_ENABLED(OF_REAL))
+   if (!CONFIG_IS_ENABLED(OF_REAL) || !phase_sdram_init())
return 0;
 
ret = dev_read_u32_array(dev, "rockchip,sdram-params",
@@ -3093,7 +3101,6 @@ static int rk3399_dmc_init(struct udevice *dev)
priv->cic = syscon_get_first_range(ROCKCHIP_SYSCON_CIC);
priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
-   priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
priv->pmusgrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUSGRF);
priv->pmucru = rockchip_get_pmucru();
priv->cru = rockchip_get_cru();
@@ -3138,19 +3145,16 @@ static int rk3399_dmc_init(struct udevice *dev)
 
return 0;
 }
-#endif
 
 static int rk3399_dmc_probe(struct udevice *dev)
 {
struct dram_info *priv = dev_get_priv(dev);
 
-#if defined(CONFIG_TPL_BUILD) || \
-   (!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD))
-   if (rk3399_dmc_init(dev))
-   return 0;
-#endif
priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
debug("%s: pmugrf = %p\n", __func__, priv->pmugrf);
+   if (phase_sdram_init() && rk3399_dmc_init(dev))
+   return 0;
+
priv->info.base = CFG_SYS_SDRAM_BASE;
priv->info.size =
rockchip_sdram_size((phys_addr_t)>pmugrf->os_reg2);
@@ -3181,10 +3185,7 @@ U_BOOT_DRIVER(dmc_rk3399) = {
.id = UCLASS_RAM,
.of_match = rk3399_dmc_ids,
.ops = _dmc_ops,
-#if defined(CONFIG_TPL_BUILD) || \
-   (!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD))
.of_to_plat = rk3399_dmc_of_to_plat,
-#endif
.probe = rk3399_dmc_probe,
.priv_auto  = sizeof(struct dram_info),
 #if defined(CONFIG_TPL_BUILD) || \
-- 
2.34.1



[PATCH v6 7/8] rockchip: Ensure memory size is available in RK3399 SPL

2024-06-27 Thread Simon Glass
At present gd->ram_size is 0 in SPL, meaning that it is not possible to
enable the cache. Correct this by always populating the RAM size
correctly.

This increases code size by about 500 bytes in SPL, since it must call
the rather large rockchip_sdram_size() function.

Signed-off-by: Simon Glass 
Reviewed-by: Quentin Schulz 
---

(no changes since v3)

Changes in v3:
- Cut the patch down to bare bones

Changes in v2:
- Add new patch to correct memory size in SPL

 drivers/ram/rockchip/sdram_rk3399.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/ram/rockchip/sdram_rk3399.c 
b/drivers/ram/rockchip/sdram_rk3399.c
index ef9a1824b2b..bc79c034808 100644
--- a/drivers/ram/rockchip/sdram_rk3399.c
+++ b/drivers/ram/rockchip/sdram_rk3399.c
@@ -3142,19 +3142,19 @@ static int rk3399_dmc_init(struct udevice *dev)
 
 static int rk3399_dmc_probe(struct udevice *dev)
 {
+   struct dram_info *priv = dev_get_priv(dev);
+
 #if defined(CONFIG_TPL_BUILD) || \
(!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD))
if (rk3399_dmc_init(dev))
return 0;
-#else
-   struct dram_info *priv = dev_get_priv(dev);
-
+#endif
priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
debug("%s: pmugrf = %p\n", __func__, priv->pmugrf);
priv->info.base = CFG_SYS_SDRAM_BASE;
priv->info.size =
rockchip_sdram_size((phys_addr_t)>pmugrf->os_reg2);
-#endif
+
return 0;
 }
 
-- 
2.34.1



[PATCH v6 6/8] fdt: Correct condition for bloblist existing

2024-06-27 Thread Simon Glass
On some boards, the bloblist is created in SPL once SDRAM is ready. It
cannot be accessed until that point, so is not available early in SPL.

Add a condition to avoid a hang in this case.

This fixes a hang in chromebook_coral

Fixes: 70fe2385943 ("fdt: Allow the devicetree to come from a bloblist")

Signed-off-by: Simon Glass 
---

(no changes since v3)

Changes in v3:
- Use BLOBLIST instead of OF_BLOBLIST

Changes in v2:
- Use 'phase' instead of 'stage'

 lib/fdtdec.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index b2c59ab3818..e16d1819449 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1669,8 +1669,16 @@ int fdtdec_setup(void)
 {
int ret = -ENOENT;
 
-   /* If allowing a bloblist, check that first */
-   if (CONFIG_IS_ENABLED(BLOBLIST)) {
+   /*
+* If allowing a bloblist, check that first. This would be better
+* handled with an OF_BLOBLIST Kconfig, but that caused far too much
+* argument, so add a hack here, used e.g. by chromebook_coral
+* The necessary test is whether the previous phase passed a bloblist,
+* not whether this phase creates one.
+*/
+   if (CONFIG_IS_ENABLED(BLOBLIST) &&
+   (spl_prev_phase() != PHASE_TPL ||
+!IS_ENABLED(CONFIG_TPL_BLOBLIST))) {
ret = bloblist_maybe_init();
if (!ret) {
gd->fdt_blob = bloblist_find(BLOBLISTT_CONTROL_FDT, 0);
-- 
2.34.1



[PATCH v6 5/8] binman: Keep the efi_capsule input file

2024-06-27 Thread Simon Glass
There is no need to remove input files. It makes it harder to diagnose
failures. Keep the payload file.

There is no test for this condition, but one could be added.

Signed-off-by: Simon Glass 
Acked-by: Sughosh Ganu 
---

(no changes since v4)

Changes in v4:
- Drop Fixes tag

 tools/binman/etype/efi_capsule.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/tools/binman/etype/efi_capsule.py 
b/tools/binman/etype/efi_capsule.py
index 47da5da324b..03e55cbc4d9 100644
--- a/tools/binman/etype/efi_capsule.py
+++ b/tools/binman/etype/efi_capsule.py
@@ -148,7 +148,6 @@ class Entry_efi_capsule(Entry_section):
  self.fw_version,
  self.oem_flags)
 if ret is not None:
-os.remove(payload)
 return tools.read_file(capsule_fname)
 else:
 # Bintool is missing; just use the input data as the output
-- 
2.34.1



[PATCH v6 4/8] binman: Return failure when a usage() message is generated

2024-06-27 Thread Simon Glass
The tool must return an error code when invalid arguments are provided,
otherwise binman has no way of knowing that anything went wrong.

Correct this.

Signed-off-by: Simon Glass 
Fixes: fab430be2f4 ("tools: add mkeficapsule command for UEFI...")
---

(no changes since v1)

 tools/mkeficapsule.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
index c112ae2de8d..f28008a0829 100644
--- a/tools/mkeficapsule.c
+++ b/tools/mkeficapsule.c
@@ -977,7 +977,7 @@ int main(int argc, char **argv)
exit(EXIT_SUCCESS);
default:
print_usage();
-   exit(EXIT_SUCCESS);
+   exit(EXIT_FAILURE);
}
}
 
-- 
2.34.1



[PATCH v6 3/8] binman: Deal with mkeficapsule being missing

2024-06-27 Thread Simon Glass
Tools cannot be assumed to be present. Add a check for this with the
mkeficpasule tool.

Signed-off-by: Simon Glass 
Fixes: b617611b27a ("binman: capsule: Add support for generating...")
---

(no changes since v1)

 tools/binman/etype/efi_capsule.py | 4 
 1 file changed, 4 insertions(+)

diff --git a/tools/binman/etype/efi_capsule.py 
b/tools/binman/etype/efi_capsule.py
index e3203717822..47da5da324b 100644
--- a/tools/binman/etype/efi_capsule.py
+++ b/tools/binman/etype/efi_capsule.py
@@ -150,6 +150,10 @@ class Entry_efi_capsule(Entry_section):
 if ret is not None:
 os.remove(payload)
 return tools.read_file(capsule_fname)
+else:
+# Bintool is missing; just use the input data as the output
+self.record_missing_bintool(self.mkeficapsule)
+return data
 
 def AddBintools(self, btools):
 self.mkeficapsule = self.AddBintool(btools, 'mkeficapsule')
-- 
2.34.1



[PATCH v6 2/8] binman: Collect the version number for mkeficapsule

2024-06-27 Thread Simon Glass
Now that this tool has a version number, collect it.

Signed-off-by: Simon Glass 
---

(no changes since v1)

 tools/binman/btool/mkeficapsule.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/binman/btool/mkeficapsule.py 
b/tools/binman/btool/mkeficapsule.py
index ef1da638df1..f7e5a886849 100644
--- a/tools/binman/btool/mkeficapsule.py
+++ b/tools/binman/btool/mkeficapsule.py
@@ -33,7 +33,8 @@ class Bintoolmkeficapsule(bintool.Bintool):
 commandline, or through a config file.
 """
 def __init__(self, name):
-super().__init__(name, 'mkeficapsule tool for generating capsules')
+super().__init__(name, 'mkeficapsule tool for generating capsules',
+ r'mkeficapsule version (.*)')
 
 def generate_capsule(self, image_index, image_guid, hardware_instance,
  payload, output_fname, priv_key, pub_key,
-- 
2.34.1



[PATCH v6 0/8] Second part of bug-fixes series

2024-06-27 Thread Simon Glass
This consists of some patches split ouf from an earlier series [1].
Apart from the fdt patch they are not needed for the upcoming release.

The FDT patch fixes a boot problem on several Chromebooks.

[1] 
https://patchwork.ozlabs.org/project/uboot/patch/20240626155945.278640-15-...@chromium.org/

Changes in v6:
Take account of ROCKCHIP_EXTERNAL_TPL in phase_sdram_init()

Changes in v5:
- Move setting of pmugrf into the probe() function

Changes in v4:
- Drop Fixes tag

Changes in v3:
- Use BLOBLIST instead of OF_BLOBLIST
- Cut the patch down to bare bones
- Split out the refactoring into a separate patch

Changes in v2:
- Use 'phase' instead of 'stage'
- Add new patch to correct memory size in SPL

Simon Glass (8):
  mkeficapsule: Add a --version argument
  binman: Collect the version number for mkeficapsule
  binman: Deal with mkeficapsule being missing
  binman: Return failure when a usage() message is generated
  binman: Keep the efi_capsule input file
  fdt: Correct condition for bloblist existing
  rockchip: Ensure memory size is available in RK3399 SPL
  rockchip: Avoid #ifdefs in RK3399 SPL

 doc/mkeficapsule.1  |  4 
 drivers/ram/rockchip/sdram_rk3399.c | 37 +++--
 lib/fdtdec.c| 12 --
 tools/binman/btool/mkeficapsule.py  |  3 ++-
 tools/binman/etype/efi_capsule.py   |  5 +++-
 tools/mkeficapsule.c| 10 ++--
 6 files changed, 47 insertions(+), 24 deletions(-)

-- 
2.34.1



[PATCH v6 1/8] mkeficapsule: Add a --version argument

2024-06-27 Thread Simon Glass
Tools should have an option to obtain the version, so add this to the
mkeficapsule tool.

Signed-off-by: Simon Glass 
---

(no changes since v1)

 doc/mkeficapsule.1   | 4 
 tools/mkeficapsule.c | 8 +++-
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1
index c4c2057d5c7..c3d0f21488a 100644
--- a/doc/mkeficapsule.1
+++ b/doc/mkeficapsule.1
@@ -87,6 +87,10 @@ Generate a firmware revert empty capsule
 .BI "-o\fR,\fB --capoemflag "
 Capsule OEM flag, value between 0x to 0x
 
+.TP
+.BR -V ", " --version
+Print version information and exit.
+
 .TP
 .BR -h ", " --help
 Print a help message
diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
index 6a261ff549d..c112ae2de8d 100644
--- a/tools/mkeficapsule.c
+++ b/tools/mkeficapsule.c
@@ -21,6 +21,8 @@
 #include 
 #include 
 
+#include 
+
 #include "eficapsule.h"
 
 static const char *tool_name = "mkeficapsule";
@@ -28,7 +30,7 @@ static const char *tool_name = "mkeficapsule";
 efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
 efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
 
-static const char *opts_short = "g:i:I:v:p:c:m:o:dhARD";
+static const char *opts_short = "g:i:I:v:p:c:m:o:dhARDV";
 
 enum {
CAPSULE_NORMAL_BLOB = 0,
@@ -70,6 +72,7 @@ static void print_usage(void)
"\t-R, --fw-revert  firmware revert capsule, takes no GUID, no 
image blob\n"
"\t-o, --capoemflag Capsule OEM Flag, an integer between 0x 
and 0x\n"
"\t-D, --dump-capsule  dump the contents of the capsule 
headers\n"
+   "\t-V, --version   show version number\n"
"\t-h, --help  print a help message\n",
tool_name);
 }
@@ -969,6 +972,9 @@ int main(int argc, char **argv)
case 'D':
capsule_dump = true;
break;
+   case 'V':
+   printf("mkeficapsule version %s\n", PLAIN_VERSION);
+   exit(EXIT_SUCCESS);
default:
print_usage();
exit(EXIT_SUCCESS);
-- 
2.34.1



Re: [PATCH v5 14/16] rockchip: Avoid #ifdefs in RK3399 SPL

2024-06-27 Thread Jonas Karlman
Hi Simon,

On 2024-06-27 10:02, Simon Glass wrote:
> Hi Jonas,
> 
> On Wed, 26 Jun 2024 at 17:16, Jonas Karlman  wrote:
>>
>> Hi Simon,
>>
>> On 2024-06-26 17:59, Simon Glass wrote:
>>> The code here is confusing due to large blocks which are #ifdefed out.
>>> Add a function phase_sdram_init() which returns whether SDRAM init
>>> should happen in the current phase, using that as needed to control the
>>> code flow.
>>>
>>> This increases code size by about 500 bytes in SPL when the cache is on,
>>> since it must call the rather large rockchip_sdram_size() function.
>>>
>>> - Drop the non-dcache optimisation, since the cache should normally be on
>>>
>>> Signed-off-by: Simon Glass 
>>> ---
>>>
>>> Changes in v5:
>>> - Move setting of pmugrf into the probe() function
>>>
>>> Changes in v3:
>>> - Split out the refactoring into a separate patch
>>>
>>>  drivers/ram/rockchip/sdram_rk3399.c | 33 ++---
>>>  1 file changed, 16 insertions(+), 17 deletions(-)
>>>
>>> diff --git a/drivers/ram/rockchip/sdram_rk3399.c 
>>> b/drivers/ram/rockchip/sdram_rk3399.c
>>> index 3c4e20f4e80..b259e8e3dd6 100644
>>> --- a/drivers/ram/rockchip/sdram_rk3399.c
>>> +++ b/drivers/ram/rockchip/sdram_rk3399.c
>>
>> [snip]
>>
>>> +/**
>>> + * phase_sdram_init() - Check if this is the phase where SDRAM init happens
>>> + *
>>> + * Returns: true to do SDRAM init in this phase, false to not
>>> + */
>>> +static bool phase_sdram_init(void)
>>> +{
>>> + return spl_phase() == PHASE_TPL ||
>>> + (!IS_ENABLED(CONFIG_TPL) && !spl_in_proper());
>>
>> This still need to check for !IS_ENABLED(CONFIG_ROCKCHIP_EXTERNAL_TPL)
>> to be correct, else you must build with both CONFIG_TPL and
>> CONFIG_ROCKCHIP_EXTERNAL_TPL or the generated SPL will incorrectly try
>> to initialize DRAM.
>>
>> DRAM should only be initialized in TPL or ROCKCHIP_EXTERNAL_TPL,
>> or if none of them are defined in SPL. All other phases should
>> just read and report dram size.
> 
> Thanks for the info.
> 
> The reason I am finding this hard to understand is that
> ROCKCHIP_EXTERNAL_TPL does not appear in the code as it is. So I
> cannot figure out why it needs to be added. Is there a bug in the
> current code, or does my patch introduce a bug, or...?

The current code does not handle ROCKCHIP_EXTERNAL_TPL and TPL must be
built to later be replaced with the external TPL blob.

This adds a new helper that states "Check if this is the phase where
SDRAM init happens", and for this statement to be true it should also
consider ROCKCHIP_EXTERNAL_TPL or a bugfix patch is later needed for
this newly added helper.

Adding !IS_ENABLED(CONFIG_ROCKCHIP_EXTERNAL_TPL) should make this
statement be valid for the foreseeable combinations.

return spl_phase() == PHASE_TPL ||
   (!IS_ENABLED(CONFIG_TPL) &&
!IS_ENABLED(CONFIG_ROCKCHIP_EXTERNAL_TPL) &&
!spl_in_proper());

With that it should be possible to have TPL=n and ROCKCHIP_EXTERNAL_TPL=y
and produce a working SPL.

Regards,
Jonas

> 
> Regards,
> Simon



Re: [PATCH v3 08/19] test: Introduce the concept of a role

2024-06-27 Thread Simon Glass
Hi Tom,

On Wed, 26 Jun 2024 at 15:29, Tom Rini  wrote:
>
> On Wed, Jun 26, 2024 at 09:00:33AM +0100, Simon Glass wrote:
> > Hi Tom,
> >
> > On Tue, 25 Jun 2024 at 15:27, Tom Rini  wrote:
> > >
> > > On Tue, Jun 25, 2024 at 01:38:08PM +0100, Simon Glass wrote:
> > > > Hi Tom,
> > > >
> > > > On Mon, 24 Jun 2024 at 19:13, Tom Rini  wrote:
> > > > >
> > > > > On Sun, Jun 23, 2024 at 02:32:02PM -0600, Simon Glass wrote:
> > > > >
> > > > > > In Labgrid there is the concept of a 'role', which is similar to the
> > > > > > U-Boot board ID in U-Boot's pytest subsystem.
> > > > > >
> > > > > > The role indicates both the target and information about the U-Boot
> > > > > > build to use. It can also provide any amount of other configuration.
> > > > > > The information is obtained using the 'labgrid-client query' 
> > > > > > operation.
> > > > > >
> > > > > > Make use of this in tests, so that only the role is required in 
> > > > > > gitlab
> > > > > > and other situations. The board type and other things can be queried
> > > > > > as needed.
> > > > > >
> > > > > > Use a new 'u-boot-test-getrole' script to obtain the requested
> > > > > > information.
> > > > > >
> > > > > > With this it is possible to run lab tests in gitlab with just a 
> > > > > > single
> > > > > > 'ROLE' variable for each board.
> > > > > >
> > > > > > Signed-off-by: Simon Glass 
> > > > > > ---
> > > > > >
> > > > > > (no changes since v1)
> > > > > >
> > > > > >  test/py/conftest.py | 31 +++
> > > > > >  1 file changed, 27 insertions(+), 4 deletions(-)
> > > > > >
> > > > > > diff --git a/test/py/conftest.py b/test/py/conftest.py
> > > > > > index 6547c6922c6..5de8d7b0e23 100644
> > > > > > --- a/test/py/conftest.py
> > > > > > +++ b/test/py/conftest.py
> > > > > > @@ -23,6 +23,7 @@ from pathlib import Path
> > > > > >  import pytest
> > > > > >  import re
> > > > > >  from _pytest.runner import runtestprotocol
> > > > > > +import subprocess
> > > > > >  import sys
> > > > > >
> > > > > >  # Globals: The HTML log file, and the connection to the U-Boot 
> > > > > > console.
> > > > > > @@ -79,6 +80,7 @@ def pytest_addoption(parser):
> > > > > >  parser.addoption('--gdbserver', default=None,
> > > > > >  help='Run sandbox under gdbserver. The argument is the 
> > > > > > channel '+
> > > > > >  'over which gdbserver should communicate, e.g. 
> > > > > > localhost:1234')
> > > > > > +parser.addoption('--role', help='U-Boot board role (for 
> > > > > > Labgrid)')
> > > > > >  parser.addoption('--no-prompt-wait', default=False, 
> > > > > > action='store_true',
> > > > > >  help="Assume that U-Boot is ready and don't wait for a 
> > > > > > prompt")
> > > > > >
> > > > > > @@ -130,12 +132,33 @@ def get_details(config):
> > > > > >  str: Build directory
> > > > > >  str: Source directory
> > > > > >  """
> > > > > > -board_type = config.getoption('board_type')
> > > > > > -board_identity = config.getoption('board_identity')
> > > > > > +role = config.getoption('role')
> > > > > >  build_dir = config.getoption('build_dir')
> > > > > > +if role:
> > > > > > +board_identity = role
> > > > > > +cmd = ['u-boot-test-getrole', role, '--configure']
> > > > > > +env = os.environ.copy()
> > > > > > +if build_dir:
> > > > > > +env['U_BOOT_BUILD_DIR'] = build_dir
> > > > > > +proc = subprocess.run(cmd, capture_output=True, 
> > > > > > encoding='utf-8',
> > > > > > +  env=env)
> > > > > > +if proc.returncode:
> > > > > > +raise ValueError(proc.stderr)
> > > > > > +print('conftest: lab:', proc.stdout)
> > > > > > +vals = {}
> > > > > > +for line in proc.stdout.splitlines():
> > > > > > +item, value = line.split(' ', maxsplit=1)
> > > > > > +k = item.split(':')[-1]
> > > > > > +vals[k] = value
> > > > > > +print('conftest: lab info:', vals)
> > > > > > +board_type, default_build_dir, source_dir = (vals['board'],
> > > > > > +vals['build_dir'], vals['source_dir'])
> > > > > > +else:
> > > > > > +board_type = config.getoption('board_type')
> > > > > > +board_identity = config.getoption('board_identity')
> > > > > >
> > > > > > -source_dir = os.path.dirname(os.path.dirname(TEST_PY_DIR))
> > > > > > -default_build_dir = source_dir + '/build-' + board_type
> > > > > > +source_dir = os.path.dirname(os.path.dirname(TEST_PY_DIR))
> > > > > > +default_build_dir = source_dir + '/build-' + board_type
> > > > > >  if not build_dir:
> > > > > >  build_dir = default_build_dir
> > > > >
> > > > > I'm a little confused here. Why can't we construct "role" from
> > > > > board_type+board_identity and then we have the board
> > > > > conf.${board_type}_${board_identity} file set whatever needs setting 
> > > > > to
> > > > > 

Re: [PATCH 13/14] Update u-boot.cfg to include CFG also

2024-06-27 Thread Simon Glass
Hi Tom,

On Wed, 26 Jun 2024 at 15:07, Tom Rini  wrote:
>
> On Wed, Jun 26, 2024 at 09:00:41AM +0100, Simon Glass wrote:
> > Hi Tom,
> >
> > On Tue, 25 Jun 2024 at 15:14, Tom Rini  wrote:
> > >
> > > On Tue, Jun 25, 2024 at 01:38:04PM +0100, Simon Glass wrote:
> > > > Hi Tom,
> > > >
> > > > On Mon, 24 Jun 2024 at 19:29, Tom Rini  wrote:
> > > > >
> > > > > On Sun, Jun 23, 2024 at 02:30:32PM -0600, Simon Glass wrote:
> > > > >
> > > > > > Some configuration is now in variables with a CFG_ prefix. Add 
> > > > > > these to
> > > > > > the .cfg file so that we can see everything in one place. Sort the
> > > > > > options so they are easier to find and compare.
> > > > > >
> > > > > > Signed-off-by: Simon Glass 
> > > > > > ---
> > > > > >
> > > > > > Changes in v2:
> > > > > > - Add new patch to update u-boot.cfg with CFG_... options
> > > > > >
> > > > > >  scripts/Makefile.autoconf | 2 +-
> > > > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > > > >
> > > > > > diff --git a/scripts/Makefile.autoconf b/scripts/Makefile.autoconf
> > > > > > index b42f9b525fe..65ff11ea508 100644
> > > > > > --- a/scripts/Makefile.autoconf
> > > > > > +++ b/scripts/Makefile.autoconf
> > > > > > @@ -71,7 +71,7 @@ quiet_cmd_autoconf = GEN $@
> > > > > >  quiet_cmd_u_boot_cfg = CFG $@
> > > > > >cmd_u_boot_cfg = \
> > > > > >   $(CPP) $(c_flags) $2 -DDO_DEPS_ONLY -dM include/config.h > 
> > > > > > $@.tmp && { \
> > > > > > - grep 'define CONFIG_' $@.tmp | \
> > > > > > + egrep 'define (CONFIG_|CFG_)' $@.tmp | sort | \
> > > > > >   sed '/define CONFIG_IS_ENABLED(/d;/define 
> > > > > > CONFIG_IF_ENABLED_INT(/d;/define CONFIG_VAL(/d;' > $@; \
> > > > > >   rm $@.tmp;
> > > > > >   \
> > > > > >   } || {
> > > > > >   \
> > > > >
> > > > > I don't like this because whereas "CONFIG_" is enforced to be set only
> > > > > by Kconfig and so always all reliably set and found via a single 
> > > > > header,
> > > > > CFG_ stuff is not.
> > > >
> > > > OK, so how are CFG_ options found? I hit this when trying to find the
> > > > SDRAM size on rockchip 3399 and I could not find any way of figuring
> > > > it out.
> > >
> > > It's just another define, there's no uniformity to it. For some of the
> > > SDRAM values really we need some build time way to grab some information
> > > out of the default device tree.
> >
> > Can you give an example of a board that could use this? I looked at
> > the devicetree for chromebook_kevin and don't see a memory range in
> > ther.
>
> OK, wow, I didn't realize /memory was optional now. But indeed, I don't
> see it in the dtb file. That removes that option then, sadly.

Well, we can still require it, so long as an error is produced if the
property is needed but does not exist.

Regards,
Simon


Re: [PATCH] doc: fit: Make data-size a conditionally mandatory property

2024-06-27 Thread Simon Glass
Hi Bastian,

On Wed, 26 Jun 2024 at 18:37, Bastian Germann  wrote:
>
> Am 26.06.24 um 10:00 schrieb Simon Glass:
> > Can you please add a PR here?
> >
> > https://github.com/open-source-firmware/flat-image-tree
>
> In that copy, the property is already conditionally mandatory.

OK. I think we should figure out how to include the copy in U-Boot at
some point. See [1] for an idea.

Regards,
Simon

[1] 
https://patchwork.ozlabs.org/project/uboot/cover/20240604195256.1820285-1-sam.povi...@amd.com/


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

2024-06-27 Thread Simon Glass
Hi Marek,

On Thu, 27 Jun 2024 at 00:59, Marek Vasut  wrote:
>
> Insert /u-boot, =  property into the U-Boot control DT
> during SPL DTO application process. This can be used by user to inspect
> which DTOs got applied by the SPL and in which order from running U-Boot.
>
> Example:
> ```
> u-boot=> fdt addr $fdtcontroladdr && fdt list /
> Working FDT set to aee9aeb0
> / {
> u-boot,fdt-dto-imx8mp-dhcom-pdk3-overlay-rev100 = <0x0005>;
> u-boot,fdt-dto-imx8mp-dhcom-som-overlay-rev100 = <0x0004>;
> u-boot,fdt-dto-imx8mp-dhcom-pdk-overlay-eth2xfast = <0x0003>;
> u-boot,fdt-dto-imx8mp-dhcom-som-overlay-eth2xfast = <0x0002>;
> ...
> ```
>
> Signed-off-by: Marek Vasut 
> ---
> Cc: Manoj Sai 
> Cc: Sean Anderson 
> Cc: Simon Glass 
> Cc: Suniel Mahesh 
> Cc: Tom Rini 
> Cc: u-b...@dh-electronics.com
> Cc: u-boot@lists.denx.de
> ---
>  common/spl/spl_fit.c | 23 ++-
>  1 file changed, 22 insertions(+), 1 deletion(-)
>
> diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
> index 988125be008..261b72419b1 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
> @@ -450,7 +451,7 @@ static int spl_fit_append_fdt(struct spl_image_info 
> *spl_image,
>
> /* Make room in FDT for changes from the overlay */
> ret = fdt_increase_size(spl_image->fdt_addr,
> -   image_info.size);
> +   image_info.size + 
> strlen(str));

You may also need space for the string terminator (i.e. add 1 more byte).

> if (ret < 0)
> break;
>
> @@ -464,6 +465,26 @@ static int spl_fit_append_fdt(struct spl_image_info 
> *spl_image,
>
> debug("%s: DT overlay %s applied\n", __func__,
>   fit_get_name(ctx->fit, node, NULL));
> +
> +   /*
> +* Insert /u-boot, =  property into
> +* the U-Boot control DT. This can be used by user
> +* to inspect which DTOs got applied by the SPL from
> +* a running U-Boot.
> +*/
> +   snprintf(dtoname, sizeof(dtoname), "u-boot,%s", str);
> +   ret = fdt_setprop_u32(spl_image->fdt_addr, 0, dtoname,
> + index);
> +   if (!ret) {

This means there was no error, right?

> +   /*
> +* The DTO itself was applied, do not treat 
> the
> +* insertion of /u-boot, as an error
> +* so the system can possibly boot somehow.
> +*/
> +   debug("%s: DT overlay %s name not inserted 
> into / node (%d)\n",
> + __func__,
> + fit_get_name(ctx->fit, node, NULL), 
> ret);
> +   }

log_debug()

> }
> free(tmpbuffer);
> if (ret)
> --
> 2.43.0
>

Regards,
Simon


Re: [PATCH v1] board: mpfs_icicle: implement board_fdt_blob_setup()

2024-06-27 Thread Simon Glass
Hi,

On Tue, 25 Jun 2024 at 15:34, Tom Rini  wrote:
>
> On Tue, Jun 25, 2024 at 10:08:06AM +0100, Conor Dooley wrote:
>
> > The firmware on the Icicle is capable of providing a devicetree in a1 to
> > U-Boot, but until now the devicetree has been packaged in a "payload" [1]
> > alongside U-Boot (or other bootloaders/RTOSes) and appended to the image.
> > The address of this appended devicetree is placed in a1 by the firmware.
> > This meant that the mechanism used by OF_SEPARATE to locate the
> > devicetree at the end of the image would pick up the one provided by the
> > firmware when u-boot-nodtb.bin was in the payload and U-Boot's devicetree
> > when u-boot.bin was.
> >
> > The firmware is now going to be capable of providing a minimal devicetree
> > (quite cut down due to severe space constraints), but this devicetree is
> > linked into the firmware that runs out of the L2 rather than at the end
> > of the U-Boot image. Implement board_fdt_blob_setup() so that this
> > devicetree can be optionally used, and the devicetree provided in the
> > "payload" can be used without relying on "happening" to implement the
> > same strategy as OF_SEPARATE expects in combination with
> > u-boot-nodtb.bin. Unlike other RISC-V boards, the firmware provided
> > devicetree is only used when OF_BOARD is set, so that the almost
> > certainly more complete devicetree in U-Boot will be used unless
> > explicitly requested otherwise.
> >
> > Link: 
> > https://github.com/polarfire-soc/hart-software-services/blob/master/tools/hss-payload-generator/README.md
> >  [1]
> > Signed-off-by: Conor Dooley 
> > ---
> > CC: Ivan Griffin 
> > CC: Padmarao Begari 
> > CC: Cyril Jean 
> > CC: Tom Rini 
> > CC: Conor Dooley 
> > CC: u-boot@lists.denx.de
> > ---
> >  board/microchip/mpfs_icicle/mpfs_icicle.c | 19 +++
> >  1 file changed, 19 insertions(+)
> >
> > diff --git a/board/microchip/mpfs_icicle/mpfs_icicle.c 
> > b/board/microchip/mpfs_icicle/mpfs_icicle.c
> > index 4d7d843dfa3..2c1f7175f0e 100644
> > --- a/board/microchip/mpfs_icicle/mpfs_icicle.c
> > +++ b/board/microchip/mpfs_icicle/mpfs_icicle.c
> > @@ -9,6 +9,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >
> >  DECLARE_GLOBAL_DATA_PTR;
> >
> > @@ -50,6 +51,24 @@ static void read_device_serial_number(u8 *response, u8 
> > response_size)
> >   response_buf[idx] = readb(MPFS_SYS_SERVICE_MAILBOX + idx);
> >  }
> >
> > +void *board_fdt_blob_setup(int *err)
> > +{
> > + *err = 0;
> > + /*
> > +  * The devicetree provided by the previous stage is very minimal due 
> > to
> > +  * severe space constraints. The firmware performs no fixups etc.
> > +  * U-Boot, if providing a devicetree, almost certainly has a better
> > +  * more complete one than the firmware so that provided by the 
> > firmware
> > +  * is ignored for OF_SEPARATE.
> > +  */
> > + if (IS_ENABLED(CONFIG_OF_BOARD)) {
> > + if (gd->arch.firmware_fdt_addr)
> > + return (ulong *)(uintptr_t)gd->arch.firmware_fdt_addr;
> > + }
> > +
> > + return (ulong *)_end;
> > +}
> > +
> >  int board_init(void)
> >  {
> >   /* For now nothing to do here. */
>
> I'm adding in Simon and Ilias as this touches on one of those frequent
> topics about how device trees can/should be passed along to us.

The only thing I can think of is implementing bloblist in  the a1 (?)
firmware, then passing the DT in that.

It seems that you still need to be able to turn that on and off in
U-Boot though. So far we have not agreed the mechanism to do that, I
have the same problem, with a pending patch here[1]

Regards,
Simon

[1] 
https://patchwork.ozlabs.org/project/uboot/patch/20240626155945.278640-12-...@chromium.org/


  1   2   >