Re: [PATCH v2 2/4] regmap: Allow providing read/write callbacks through struct regmap_config

2020-01-08 Thread Jean-Jacques Hiblot

Simon,

On 24/12/2019 16:58, Simon Glass wrote:

Hi Jean-Jacques,

On Mon, 16 Dec 2019 at 03:10, Jean-Jacques Hiblot  wrote:

Hi Simon,

On 10/12/2019 16:18, Simon Glass wrote:

Hi Jean-Jacques,

On Tue, 5 Nov 2019 at 04:47, Jean-Jacques Hiblot  wrote:

Some linux drivers provide their own read/write functions to access data
from/of the regmap. Adding support for it.

Signed-off-by: Jean-Jacques Hiblot 

---

Changes in v2:
- Only use custom accessors if {,SPL,TPL}_REGMAP_ACCESSORS is enabled

   drivers/core/Kconfig  | 25 +
   drivers/core/regmap.c | 22 --
   include/regmap.h  | 28 +---
   3 files changed, 70 insertions(+), 5 deletions(-)

Coming back to the discussion on driver model

How do you specify the fields? I would expect that this would be done
in the driver tree? Perhaps in a subnode of the device?

Just to state what I see as the advantages of using a separate device
for access:

- Remove the #ifdef in the regmap struct
- Easy to specify the behaviour in a device-tree node
- Easy to extend as the child device can do what it likes with respect to access

That sure is a better abstraction. However the goal of this patch is
only to use the same API as linux. It allows porting the drivers as-is
and thus reduce the burden of maintenance.

So how do you specify the fields? See my question above.


The fields are filled when creating the regmap.

ex:

static struct regmap_config cfg = {
.reg_write = regmaptest_write,
.reg_read = regmaptest_read,
};
and then
regmap = devm_regmap_init(dev, NULL, , );

You can have a look at the tests in the last patch of the series.

JJ


It is not possible to use a similar API without importing the internal
implementation. Linux's driver model is less homogenous.

Regards,
Simon


Re: [PATCH PATCH v6 00/13] Add support for applications of overlays in SPL

2019-12-23 Thread Jean-Jacques Hiblot

Tom, Simon,

gentle ping on this series. It has been posted for a long time and I did 
not push for it because I was working on other stuff. am654x and J7x  
SOCs will need this kind of feature.


Before sending a version rebased on latest u-boot, I would have liked to 
have your feeling on the series as a whole.


JJ



On 22/10/2019 16:39, Jean-Jacques Hiblot wrote:

The purpose of this series is to provide the SPL with ability to apply
overlays for u-boot.

Our use-case is the support of the daughter boards of the AM65x and J721e
EVMs. In Linux, each board is supported by a unique overlay. The presence
of the boards is detected at runtime, and some useful features (like USB)
are implemented on those daughter boards. Instead of providing multiple
dtbs and fall in a combinatorial pit, we propose to use DT overlays.

On arm, if overlay are supported, this series increases the size of the SPL
by 3.2 kB.

Travis build : https://travis-ci.org/jjhiblot/u-boot/builds/600742163

Changes in v6:
- Instead of matching a overlay by the name of it's node. Try to match it
   first with the description, and then with the node's name. This allows
   to use makeimg to add the overlays to u-boot.img and not use a custom
   SPL_FIT_GENERATOR script

Changes in v5:
- Do not allocate the buffer if not needed (no overlay).
- Add a Kconfig option for the buffer size
- board_get_fit_loadable() returns an error code instead of a NULL string
   in case of failure
-reword commit log

Changes in v4:
- use CONFIG_IS_ENABLED() instead of #idef
- make sure that the temp buffer is freed in all cases
- Use the board driver infrastructure to get the image names from the
board code.
- Remove a patch that passed the board name to the FIT generator. If needed
the generator can get it from elsewhere
- Add a fix to not load the firmware twice (once as a firmware and once as
a loadable)

Changes in v3:
- Add a new config option: SPL_LOAD_FIT_APPLY_OVERLAY. By default, it is
not selected.
- removed the RFC prefix. This work will be needed soon by TI's AM65x
platform. and can probably benefit other modular platforms
- removed the last patch that provided an example of how to use this with
on a DRA76.
- removed the patch that made u-boot.img a symlink to u-boot.itb because
it breaks the build of many platforms (because files required to build the
ITB are missing)
- removed the patch to reduce the footprint of the am335x SPL. (already
merged)
- Made the boot flow more permissive (don't fail immediately if an overlay
is not present) and more verbose when an error occures
- handle the dependencies of the FIT generation in a more generic way
- use a dedicated kconfig option to enable the application of the overlays
by the SPL.

Changes in v2:
- depend on SPL_DM
- update the commit log
- reworked board_fit_get_additionnal_images() and how it used in spl_fit.c
- removed dtbo generation from dtso files and use .dts extension for the
   overlays
- add dynamic allocation usage in a separate patch
- defconfig change for the am335x_evm

Jean-Jacques Hiblot (12):
   spl: fit: don't load the firmware twice
   spl: fit: Make room in the FDT before applying overlays
   spl: fit: allocate a temporary buffer to load the overlays
   spl: fit: Do not fail immediately if an overlay is not available
   spl: fit: be more verbose when an error occurs when applying the
 overlays
   Makefile.lib: include /__symbols__ in dtb if
 SPL_LOAD_FIT_APPLY_OVERLAY is enabled
   spl: fit: constify the output parameter of spl_fit_get_image_name()
   drivers: board: Make the board drivers available in SPL
   drivers: board: Add get_fit_loadable()
   include: board: provide empty stubs when the BOARD option is not
 selected
   dts: Add support for adding DT overlays in u-boot.img
   spl: fit: Allow the board to tell if more images must be loaded from
 FIT

Michal Simek (1):
   spl: fit: Add support for applying DT overlay

  Kconfig  |  18 +
  Makefile |   3 +-
  common/spl/spl_fit.c | 151 ---
  drivers/Makefile |   2 +-
  drivers/board/Kconfig|   3 +
  drivers/board/Makefile   |   2 +-
  drivers/board/board-uclass.c |  11 +++
  dts/Kconfig  |   8 ++
  include/board.h  |  74 +
  scripts/Makefile.lib |   4 +
  10 files changed, 263 insertions(+), 13 deletions(-)



Re: [PATCH v2 2/4] regmap: Allow providing read/write callbacks through struct regmap_config

2019-12-16 Thread Jean-Jacques Hiblot

Hi Simon,

On 10/12/2019 16:18, Simon Glass wrote:

Hi Jean-Jacques,

On Tue, 5 Nov 2019 at 04:47, Jean-Jacques Hiblot  wrote:

Some linux drivers provide their own read/write functions to access data
from/of the regmap. Adding support for it.

Signed-off-by: Jean-Jacques Hiblot 

---

Changes in v2:
- Only use custom accessors if {,SPL,TPL}_REGMAP_ACCESSORS is enabled

  drivers/core/Kconfig  | 25 +
  drivers/core/regmap.c | 22 --
  include/regmap.h  | 28 +---
  3 files changed, 70 insertions(+), 5 deletions(-)

Coming back to the discussion on driver model

How do you specify the fields? I would expect that this would be done
in the driver tree? Perhaps in a subnode of the device?

Just to state what I see as the advantages of using a separate device
for access:

- Remove the #ifdef in the regmap struct
- Easy to specify the behaviour in a device-tree node
- Easy to extend as the child device can do what it likes with respect to access


That sure is a better abstraction. However the goal of this patch is 
only to use the same API as linux. It allows porting the drivers as-is 
and thus reduce the burden of maintenance.


JJ



Disadvantage is that it takes a bit more space.

Regards,
Simon


Re: [U-Boot] [PATCH v3 1/5] dm: clk: add stub for clk_disable_bulk when CONFIG_CLK is desactivated

2019-11-12 Thread Jean-Jacques Hiblot

Hi Patrick,

On 12/11/2019 10:42, Patrick Delaunay wrote:

Add stub for clk_disable_bulk() when CONFIG_CLK is desactivated.

That avoid compilation issue (undefined reference to
`clk_disable_bulk') for code:

clk_disable_bulk(>clks);
clk_release_bulk(>clks);

Signed-off-by: Patrick Delaunay 
---

Changes in v3:
- Add stub for clk_disable_bulk

Changes in v2: None

  include/clk.h | 4 
  1 file changed, 4 insertions(+)

diff --git a/include/clk.h b/include/clk.h
index a5ee53d94a..6f0b0fe4bc 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -379,7 +379,11 @@ int clk_disable(struct clk *clk);
   *by clk_get_bulk().
   * @return zero on success, or -ve error code.
   */
+ #if CONFIG_IS_ENABLED(CLK)
  int clk_disable_bulk(struct clk_bulk *bulk);
+#else
+inline int clk_disable_bulk(struct clk_bulk *bulk) { return 0; }
+#endif


Maybe this could be done for all clk operations ?

JJ

  
  /**

   * clk_is_match - check if two clk's point to the same hardware clock

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v2 3/4] drivers: mux: mmio-based syscon mux controller

2019-11-08 Thread Jean-Jacques Hiblot


On 08/11/2019 13:16, Alexandru Marginean wrote:

Hi JJ,

On 11/5/2019 12:50 PM, Jean-Jacques Hiblot wrote:

This adds a driver for mmio-based syscon multiplexers controlled by
bitfields in a syscon register range.
This is heavily based on the linux mmio-mux driver.

Signed-off-by: Jean-Jacques Hiblot 
---

Changes in v2: None

  drivers/mux/Kconfig  |  15 +
  drivers/mux/Makefile |   1 +
  drivers/mux/mmio.c   | 155 +++
  3 files changed, 171 insertions(+)
  create mode 100644 drivers/mux/mmio.c



do you plan to add support for reg-mux too, for parent devices which are
not syscon?


I haven't planned to work on it. I kept the framework close to the linux 
version, so porting mux drivers from linux shouldn't be hard.


JJ



Thanks!
Alex


___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v1 2/3] drivers: reset: Add a managed API to get reset controllers from the DT

2019-11-05 Thread Jean-Jacques Hiblot


On 05/11/2019 17:42, Simon Goldschmidt wrote:

Am 05.11.2019 um 17:33 schrieb Simon Glass:

Hi Jean-Jacques,

On Mon, 4 Nov 2019 at 08:41, Jean-Jacques Hiblot  
wrote:



On 30/10/2019 02:48, Simon Glass wrote:
On Mon, 30 Sep 2019 at 10:15, Jean-Jacques Hiblot  
wrote:
Add managed functions to get a reset_ctl from the device-tree, 
based on a

name or an index.
Also add a managed functions to get a reset_ctl_bulk (array of 
reset_ctl)

from the device-tree.

When the device is unbound, the reset controllers are automatically
released and the data structure is freed.

Signed-off-by: Jean-Jacques Hiblot 
---

   drivers/reset/reset-uclass.c | 116 +-
   include/reset.h  | 135 
++-

   2 files changed, 247 insertions(+), 4 deletions(-)

Reviewed-by: Simon Glass 

I really don't like these ERR_PTR returns. I suppose they make the
code easier to port, and we can be sure that pointers will not be in
the last 4KB of address space?


It seems rather unlikely because the returned pointer points to actual
RAM allocated from the heap. On most platforms I've worked with, the 
top

of the address space is not dedicated to memory.


Most != all: on socfpga, the internal SRAM is at the end of the 
address spcae. In SPL, this means the last 4K cannot be used.


However, that shouldn't keep us from porting ERR_PTR returns from 
Linux code.




Yes that's my comfort.


If ever the need to fix
this  arises it could done by tweaking the macros to use another unused
address space.


Not easily without doing something platform-specific, as someone else
is currently pushing.


That "someone else" would be me. Sadly, I did not get any response:

https://patchwork.ozlabs.org/project/uboot/list/?series=137880



Alternatively we could use BIT(0) to flag an error since allocations are 
always aligned on 4 or more (sizeof(ulong) or 2*sizeof(size_t))






Regards,
Simon


___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v2 2/4] dm: board: complete the initialization of the muxes in initr_dm()

2019-11-05 Thread Jean-Jacques Hiblot


On 05/11/2019 14:05, Vignesh Raghavendra wrote:

Hi JJ,

On 05/11/19 5:20 PM, Jean-Jacques Hiblot wrote:

This will probe the multiplexer devices that have a "u-boot,mux-autoprobe"
property. As a consequence they will be put in their idle state.

Signed-off-by: Jean-Jacques Hiblot 

---

[...]

diff --git a/drivers/mux/mux-uclass.c b/drivers/mux/mux-uclass.c
index 6aaf4dc964..71392e9e50 100644
--- a/drivers/mux/mux-uclass.c
+++ b/drivers/mux/mux-uclass.c
@@ -262,6 +262,28 @@ int mux_uclass_post_probe(struct udevice *dev)
return 0;
  }
  
+void dm_mux_init(void)

+{
+   struct uclass *uc;
+   struct udevice *dev;
+   int ret;
+
+   ret = uclass_get(UCLASS_MUX, );
+   if (ret < 0) {
+   debug("unable to get MUX uclass\n");
+   return;
+   }
+   uclass_foreach_dev(dev, uc) {
+   if (dev_read_bool(dev, "u-boot,mux-autoprobe")) {
+   ret = device_probe(dev);
+   if (ret)
+   debug("unable to probe device %s\n", dev->name);
+   } else {
+   printf("not found for dev %s\n", dev->name);
+   }

Is "u-boot,mux-autoprobe" a required property? The fact that its in DT
makes me think its optional. If that's the case, above printf() should
be reduced to debug() to avoid confusion


Thanks Vignesh. It was for debug and forgot to remove it.





+   }
+}
+
  UCLASS_DRIVER(mux) = {
.id = UCLASS_MUX,
.name   = "mux",
diff --git a/include/mux.h b/include/mux.h
index 060f71a47c..2467723951 100644
--- a/include/mux.h
+++ b/include/mux.h
@@ -75,6 +75,8 @@ void mux_control_put(struct mux_control *mux);
  
  struct mux_control *devm_mux_control_get(struct udevice *dev,

 const char *mux_name);
+void dm_mux_init(void);
+
  #else
  unsigned int mux_control_states(struct mux_control *mux)
  {


___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v2 0/4] drivers: Add a framework for MUX drivers

2019-11-05 Thread Jean-Jacques Hiblot

Add a new minimalistic subsystem that handles multiplexer controllers.
It provides the same API as Linux and mux drivers should be portable with
a minimum effort.
This series also includes a port of the Linux's mmio-mux driver.

This series relies on a series that extend the regmap [1].

[1] : https://patchwork.ozlabs.org/project/uboot/list/?series=140752

Changes in v2:
- Fixed warning in mux_of_xlate_default()
- Improved documentation
- Fixed SPL build
- insert the mux initialization in init_sequence_r[], just before the
console is initialized as its serial port may be muxed
- moved the definition of dm_mux_init() in this commit
- Call sandbox_set_enable_memio(true) before running the test

Jean-Jacques Hiblot (4):
  drivers: Add a new framework for multiplexer devices
  dm: board: complete the initialization of the muxes in initr_dm()
  drivers: mux: mmio-based syscon mux controller
  test: Add tests for the multiplexer framework

 arch/sandbox/dts/test.dts |  26 +++
 common/board_r.c  |  16 ++
 configs/sandbox_defconfig |   2 +
 drivers/Kconfig   |   2 +
 drivers/Makefile  |   1 +
 drivers/mux/Kconfig   |  22 +++
 drivers/mux/Makefile  |   7 +
 drivers/mux/mmio.c| 155 ++
 drivers/mux/mux-uclass.c  | 292 ++
 include/dm/uclass-id.h|   1 +
 include/dt-bindings/mux/mux.h |  17 ++
 include/mux-internal.h| 103 
 include/mux.h | 115 +
 test/dm/Makefile  |   1 +
 test/dm/mux-mmio.c| 147 +
 15 files changed, 907 insertions(+)
 create mode 100644 drivers/mux/Kconfig
 create mode 100644 drivers/mux/Makefile
 create mode 100644 drivers/mux/mmio.c
 create mode 100644 drivers/mux/mux-uclass.c
 create mode 100644 include/dt-bindings/mux/mux.h
 create mode 100644 include/mux-internal.h
 create mode 100644 include/mux.h
 create mode 100644 test/dm/mux-mmio.c

-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v2 1/4] drivers: Add a new framework for multiplexer devices

2019-11-05 Thread Jean-Jacques Hiblot
Add a new subsystem that handles multiplexer controllers. The API is the
same as in Linux.

Signed-off-by: Jean-Jacques Hiblot 

---

Changes in v2:
- Fixed warning in mux_of_xlate_default()
- Improved documentation
- Fixed SPL build

 drivers/Kconfig   |   2 +
 drivers/Makefile  |   1 +
 drivers/mux/Kconfig   |   7 +
 drivers/mux/Makefile  |   6 +
 drivers/mux/mux-uclass.c  | 270 ++
 include/dm/uclass-id.h|   1 +
 include/dt-bindings/mux/mux.h |  17 +++
 include/mux-internal.h| 103 +
 include/mux.h | 113 ++
 9 files changed, 520 insertions(+)
 create mode 100644 drivers/mux/Kconfig
 create mode 100644 drivers/mux/Makefile
 create mode 100644 drivers/mux/mux-uclass.c
 create mode 100644 include/dt-bindings/mux/mux.h
 create mode 100644 include/mux-internal.h
 create mode 100644 include/mux.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 9d99ce0226..450aa76e82 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -60,6 +60,8 @@ source "drivers/mmc/Kconfig"
 
 source "drivers/mtd/Kconfig"
 
+source "drivers/mux/Kconfig"
+
 source "drivers/net/Kconfig"
 
 source "drivers/nvme/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 0befeddfcb..9d64742580 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_$(SPL_TPL_)INPUT) += input/
 obj-$(CONFIG_$(SPL_TPL_)LED) += led/
 obj-$(CONFIG_$(SPL_TPL_)MMC_SUPPORT) += mmc/
 obj-$(CONFIG_$(SPL_TPL_)NAND_SUPPORT) += mtd/nand/raw/
+obj-$(CONFIG_$(SPL_)MULTIPLEXER) += mux/
 obj-$(CONFIG_$(SPL_TPL_)PCH_SUPPORT) += pch/
 obj-$(CONFIG_$(SPL_TPL_)PCI) += pci/
 obj-$(CONFIG_$(SPL_TPL_)PHY) += phy/
diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
new file mode 100644
index 00..ad0199c058
--- /dev/null
+++ b/drivers/mux/Kconfig
@@ -0,0 +1,7 @@
+menu "Multiplexer drivers"
+
+config MULTIPLEXER
+   bool "Multiplexer Support"
+   depends on DM
+
+endmenu
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
new file mode 100644
index 00..351e4363d3
--- /dev/null
+++ b/drivers/mux/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2019
+# Jean-Jacques Hiblot 
+
+obj-$(CONFIG_$(SPL_)MULTIPLEXER) += mux-uclass.o
diff --git a/drivers/mux/mux-uclass.c b/drivers/mux/mux-uclass.c
new file mode 100644
index 00..6aaf4dc964
--- /dev/null
+++ b/drivers/mux/mux-uclass.c
@@ -0,0 +1,270 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Multiplexer subsystem
+ *
+ * Based on the linux multiplexer framework
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ * Author: Peter Rosin 
+ *
+ * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Jean-Jacques Hiblot 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * The idle-as-is "state" is not an actual state that may be selected, it
+ * only implies that the state should not be changed. So, use that state
+ * as indication that the cached state of the multiplexer is unknown.
+ */
+#define MUX_CACHE_UNKNOWN MUX_IDLE_AS_IS
+
+static inline const struct mux_control_ops *mux_dev_ops(struct udevice *dev)
+{
+   return (const struct mux_control_ops *)dev->driver->ops;
+}
+
+static int mux_control_set(struct mux_control *mux, int state)
+{
+   int ret = mux_dev_ops(mux->dev)->set(mux, state);
+
+   mux->cached_state = ret < 0 ? MUX_CACHE_UNKNOWN : state;
+
+   return ret;
+}
+
+unsigned int mux_control_states(struct mux_control *mux)
+{
+   return mux->states;
+}
+
+static int __mux_control_select(struct mux_control *mux, int state)
+{
+   int ret;
+
+   if (WARN_ON(state < 0 || state >= mux->states))
+   return -EINVAL;
+
+   if (mux->cached_state == state)
+   return 0;
+
+   ret = mux_control_set(mux, state);
+   if (ret >= 0)
+   return 0;
+
+   /* The mux update failed, try to revert if appropriate... */
+   if (mux->idle_state != MUX_IDLE_AS_IS)
+   mux_control_set(mux, mux->idle_state);
+
+   return ret;
+}
+
+int mux_control_select(struct mux_control *mux, unsigned int state)
+{
+   int ret;
+
+   if (mux->in_use)
+   return -EBUSY;
+
+   ret = __mux_control_select(mux, state);
+
+   if (ret < 0)
+   return ret;
+
+   mux->in_use = true;
+
+   return 0;
+}
+
+int mux_control_deselect(struct mux_control *mux)
+{
+   int ret = 0;
+
+   if (mux->idle_state != MUX_IDLE_AS_IS &&
+   mux->idle_state != mux->cached_state)
+   ret = mux_control_set(mux, mux->idle_state);
+
+   mux->in_use = false;
+
+   return ret;
+}
+
+static int mux_of_xlate_default(struct mux_chip *mux_chip,
+   struct ofnode_phan

[U-Boot] [PATCH v2 2/4] dm: board: complete the initialization of the muxes in initr_dm()

2019-11-05 Thread Jean-Jacques Hiblot
This will probe the multiplexer devices that have a "u-boot,mux-autoprobe"
property. As a consequence they will be put in their idle state.

Signed-off-by: Jean-Jacques Hiblot 

---

Changes in v2:
- insert the mux initialization in init_sequence_r[], just before the
console is initialized as its serial port may be muxed
- moved the definition of dm_mux_init() in this commit

 common/board_r.c | 16 
 drivers/mux/mux-uclass.c | 22 ++
 include/mux.h|  2 ++
 3 files changed, 40 insertions(+)

diff --git a/common/board_r.c b/common/board_r.c
index c1ecb06b74..3d410f3504 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -32,6 +32,7 @@
 #include 
 #endif
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -178,6 +179,18 @@ static int initr_serial(void)
return 0;
 }
 
+#if CONFIG_MULTIPLEXER
+static int initr_mux(void)
+{
+   /*
+* Initialize the multiplexer controls to their default state.
+* This must be done early as other drivers may unknowingly rely on it.
+*/
+   dm_mux_init();
+   return 0;
+}
+#endif
+
 #if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_MIPS)
 static int initr_trap(void)
 {
@@ -691,6 +704,9 @@ static init_fnc_t init_sequence_r[] = {
 #endif
 #ifdef CONFIG_EFI_LOADER
efi_memory_init,
+#endif
+#if CONFIG_MULTIPLEXER
+   initr_mux,
 #endif
stdio_init_tables,
initr_serial,
diff --git a/drivers/mux/mux-uclass.c b/drivers/mux/mux-uclass.c
index 6aaf4dc964..71392e9e50 100644
--- a/drivers/mux/mux-uclass.c
+++ b/drivers/mux/mux-uclass.c
@@ -262,6 +262,28 @@ int mux_uclass_post_probe(struct udevice *dev)
return 0;
 }
 
+void dm_mux_init(void)
+{
+   struct uclass *uc;
+   struct udevice *dev;
+   int ret;
+
+   ret = uclass_get(UCLASS_MUX, );
+   if (ret < 0) {
+   debug("unable to get MUX uclass\n");
+   return;
+   }
+   uclass_foreach_dev(dev, uc) {
+   if (dev_read_bool(dev, "u-boot,mux-autoprobe")) {
+   ret = device_probe(dev);
+   if (ret)
+   debug("unable to probe device %s\n", dev->name);
+   } else {
+   printf("not found for dev %s\n", dev->name);
+   }
+   }
+}
+
 UCLASS_DRIVER(mux) = {
.id = UCLASS_MUX,
.name   = "mux",
diff --git a/include/mux.h b/include/mux.h
index 060f71a47c..2467723951 100644
--- a/include/mux.h
+++ b/include/mux.h
@@ -75,6 +75,8 @@ void mux_control_put(struct mux_control *mux);
 
 struct mux_control *devm_mux_control_get(struct udevice *dev,
 const char *mux_name);
+void dm_mux_init(void);
+
 #else
 unsigned int mux_control_states(struct mux_control *mux)
 {
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v2 4/4] test: Add tests for the multiplexer framework

2019-11-05 Thread Jean-Jacques Hiblot
Provide tests to check the behavior of the multiplexer framework.
The test uses a mmio-based multiplexer.

Signed-off-by: Jean-Jacques Hiblot 

---

Changes in v2:
- Call sandbox_set_enable_memio(true) before running the test

 arch/sandbox/dts/test.dts |  26 +++
 configs/sandbox_defconfig |   2 +
 test/dm/Makefile  |   1 +
 test/dm/mux-mmio.c| 147 ++
 4 files changed, 176 insertions(+)
 create mode 100644 test/dm/mux-mmio.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index aa9eaec338..3224a8389c 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1,3 +1,5 @@
+#include 
+
 /dts-v1/;
 
 / {
@@ -93,6 +95,11 @@
<_b 9 0xc 3 2 1>;
int-value = <1234>;
uint-value = <(-1234)>;
+
+   mux-controls = < 0>, < 1>,
+  < 2>, < 3>;
+   mux-control-names = "mux0", "mux1", "mux2", "mux3";
+   mux-syscon = <>;
};
 
junk {
@@ -129,6 +136,9 @@
compatible = "denx,u-boot-fdt-test";
ping-expect = <3>;
ping-add = <3>;
+
+   mux-controls = < 0>;
+   mux-control-names = "mux0";
};
 
phy_provider0: gen_phy@0 {
@@ -665,6 +675,22 @@
0x58 8>;
};
 
+   syscon3: syscon@3 {
+   compatible = "simple-mfd", "syscon";
+   reg = <0x000100 0x10>;
+
+   muxcontroller0: a-mux-controller {
+   compatible = "mmio-mux";
+   #mux-control-cells = <1>;
+
+   mux-reg-masks = <0x0 0x30>, /* 0: reg 0x0, bits 5:4 */
+   <0x3 0x1E>, /* 1: reg 0x3, bits 4:1 */
+   <0x1 0xFF>; /* 2: reg 0x1, bits 7:0 */
+   idle-states = , <0x02>, <0x73>;
+   u-boot,mux-autoprobe;
+   };
+   };
+
timer {
compatible = "sandbox,timer";
clock-frequency = <100>;
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 20ebc68997..2822dd9c74 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -144,6 +144,8 @@ CONFIG_SPI_FLASH_SPANSION=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_SST=y
 CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_MULTIPLEXER=y
+CONFIG_MUX_MMIO=y
 CONFIG_DM_ETH=y
 CONFIG_NVME=y
 CONFIG_PCI=y
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 0c2fd5cb5e..a3fc23e527 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_DM_SPI_FLASH) += sf.o
 obj-$(CONFIG_SMEM) += smem.o
 obj-$(CONFIG_DM_SPI) += spi.o
 obj-y += syscon.o
+obj-$(CONFIG_MUX_MMIO) += mux-mmio.o
 obj-$(CONFIG_DM_USB) += usb.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_REGULATOR) += regulator.o
diff --git a/test/dm/mux-mmio.c b/test/dm/mux-mmio.c
new file mode 100644
index 000000..a3dfd34120
--- /dev/null
+++ b/test/dm/mux-mmio.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Jean-Jacques Hiblot 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* Test that mmio mux work correctly */
+static int dm_test_mux_mmio(struct unit_test_state *uts)
+{
+   struct udevice *dev, *dev_b;
+   struct regmap *map;
+   struct mux_control *ctl0_a, *ctl0_b;
+   struct mux_control *ctl1;
+   struct mux_control *ctl_err;
+   u32 val;
+   int i;
+
+   sandbox_set_enable_memio(true);
+
+   ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, ));
+   ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 1, _b));
+   ut_asserteq_str("a-test", dev->name);
+   ut_asserteq_str("b-test", dev_b->name);
+   map = syscon_regmap_lookup_by_phandle(dev, "mux-syscon");
+   ut_assert(!IS_ERR(map));
+   ut_assert(map);
+
+   /* check default states */
+   ut_assertok(regmap_read(map, 3, ));
+   ut_asserteq(0x02, (val & 0x1E) >> 1);
+   ut_assertok(regmap_read(map, 1, ));
+   ut_asserteq(0x73, (val & 0xFF) >> 0);
+
+   ut_assertok(mux_control_get(dev, "mux0", _a));
+   ut_assertok(mux_control_get(dev, "mux1", ));
+   ut_asserteq(-ERANGE, mux_control_get(dev, "mux3", _err));
+   ut_asserteq(-ENODATA, mux_control_get(dev, "dummy", _err));
+   ut_assertok(mux_control_get(dev_b, "mux0", _b));
+
+   for (i = 0; i < mux_control_states(ctl0_a); i++) {
+  

[U-Boot] [PATCH v2 3/4] drivers: mux: mmio-based syscon mux controller

2019-11-05 Thread Jean-Jacques Hiblot
This adds a driver for mmio-based syscon multiplexers controlled by
bitfields in a syscon register range.
This is heavily based on the linux mmio-mux driver.

Signed-off-by: Jean-Jacques Hiblot 
---

Changes in v2: None

 drivers/mux/Kconfig  |  15 +
 drivers/mux/Makefile |   1 +
 drivers/mux/mmio.c   | 155 +++
 3 files changed, 171 insertions(+)
 create mode 100644 drivers/mux/mmio.c

diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index ad0199c058..bda6a2d9f5 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -4,4 +4,19 @@ config MULTIPLEXER
bool "Multiplexer Support"
depends on DM
 
+
+if MULTIPLEXER
+
+config MUX_MMIO
+   bool "MMIO register bitfield-controlled Multiplexer"
+   depends on MULTIPLEXER && SYSCON
+   help
+ MMIO register bitfield-controlled Multiplexer controller.
+
+ The driver builds multiplexer controllers for bitfields in a syscon
+ register. For N bit wide bitfields, there will be 2^N possible
+ multiplexer states.
+
+endif
+
 endmenu
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index 351e4363d3..78ebf04c7a 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -4,3 +4,4 @@
 # Jean-Jacques Hiblot 
 
 obj-$(CONFIG_$(SPL_)MULTIPLEXER) += mux-uclass.o
+obj-$(CONFIG_$(SPL_)MUX_MMIO) += mmio.o
diff --git a/drivers/mux/mmio.c b/drivers/mux/mmio.c
new file mode 100644
index 00..a9faaeb9fd
--- /dev/null
+++ b/drivers/mux/mmio.c
@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MMIO register bitfield-controlled multiplexer driver
+ * Based on the linux mmio multiplexer driver
+ *
+ * Copyright (C) 2017 Pengutronix, Philipp Zabel 
+ * Copyright (C) 2019 Texas Instrument, Jean-jacques Hiblot 
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int mux_mmio_set(struct mux_control *mux, int state)
+{
+   struct regmap_field **fields = dev_get_priv(mux->dev);
+
+   return regmap_field_write(fields[mux_control_get_index(mux)], state);
+}
+
+static const struct mux_control_ops mux_mmio_ops = {
+   .set = mux_mmio_set,
+};
+
+static const struct udevice_id mmio_mux_of_match[] = {
+   { .compatible = "mmio-mux" },
+   { /* sentinel */ },
+};
+
+static int mmio_mux_probe(struct udevice *dev)
+{
+   struct regmap_field **fields;
+   struct mux_chip *mux_chip = dev_get_uclass_priv(dev);
+   struct regmap *regmap;
+   u32 *mux_reg_masks;
+   u32 *idle_states;
+   int num_fields;
+   int ret;
+   int i;
+
+   regmap = syscon_node_to_regmap(dev_ofnode(dev->parent));
+   if (IS_ERR(regmap)) {
+   ret = PTR_ERR(regmap);
+   dev_err(dev, "failed to get regmap: %d\n", ret);
+   return ret;
+   }
+
+   num_fields = dev_read_size(dev, "mux-reg-masks");
+   if (num_fields < 0) {
+   dev_err(dev, "mux-reg-masks property missing or invalid: %d\n",
+   num_fields);
+   return num_fields;
+   }
+   num_fields /= sizeof(u32);
+   if (num_fields == 0 || num_fields % 2)
+   ret = -EINVAL;
+   num_fields = num_fields / 2;
+
+   ret = mux_alloc_controllers(dev, num_fields);
+   if (ret < 0) {
+   dev_err(dev, "failed to allocate mux controllers: %d\n",
+   ret);
+   return ret;
+   }
+
+   fields = devm_kmalloc(dev, num_fields * sizeof(*fields), __GFP_ZERO);
+   if (!fields)
+   return -ENOMEM;
+   dev->priv = fields;
+
+   mux_reg_masks = devm_kmalloc(dev, num_fields * 2 * sizeof(u32),
+__GFP_ZERO);
+   if (!mux_reg_masks)
+   return -ENOMEM;
+
+   ret = dev_read_u32_array(dev, "mux-reg-masks", mux_reg_masks,
+num_fields * 2);
+   if (ret < 0) {
+   dev_err(dev, "failed to read mux-reg-masks property: %d\n",
+   ret);
+   return ret;
+   }
+
+   idle_states = devm_kmalloc(dev, num_fields * sizeof(u32), __GFP_ZERO);
+   if (!idle_states)
+   return -ENOMEM;
+
+   ret = dev_read_u32_array(dev, "idle-states", idle_states, num_fields);
+   if (ret < 0) {
+   dev_err(dev, "failed to read idle-states property: %d\n",
+   ret);
+   devm_kfree(dev, idle_states);
+   idle_states = NULL;
+   }
+
+   for (i = 0; i < num_fields; i++) {
+   struct mux_control *mux = _chip->mux[i];
+   struct reg_field field;
+   u32 reg, mask;
+   int bits;
+
+   reg = mux_reg_masks[2 * i];
+   mask = mux_reg_masks[2 * i + 1];
+
+  

[U-Boot] [PATCH v2 3/4] regmap: Add support for regmap fields

2019-11-05 Thread Jean-Jacques Hiblot
A regmap field is an abstraction available in Linux. It provides to access
bitfields in a regmap without having to worry about shifts and masks.

Signed-off-by: Jean-Jacques Hiblot 
Reviewed-by: Simon Glass 
---

Changes in v2: None

 drivers/core/regmap.c |  77 ++
 include/regmap.h  | 108 ++
 2 files changed, 185 insertions(+)

diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index 10ae9f918a..905bc0b63d 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -15,6 +15,14 @@
 #include 
 #include 
 
+struct regmap_field {
+   struct regmap *regmap;
+   unsigned int mask;
+   /* lsb */
+   unsigned int shift;
+   unsigned int reg;
+};
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /**
@@ -508,3 +516,72 @@ int regmap_update_bits(struct regmap *map, uint offset, 
uint mask, uint val)
 
return regmap_write(map, offset, reg | (val & mask));
 }
+
+int regmap_field_read(struct regmap_field *field, unsigned int *val)
+{
+   int ret;
+   unsigned int reg_val;
+
+   ret = regmap_read(field->regmap, field->reg, _val);
+   if (ret != 0)
+   return ret;
+
+   reg_val &= field->mask;
+   reg_val >>= field->shift;
+   *val = reg_val;
+
+   return ret;
+}
+
+int regmap_field_write(struct regmap_field *field, unsigned int val)
+{
+   return regmap_update_bits(field->regmap, field->reg, field->mask,
+ val << field->shift);
+}
+
+static void regmap_field_init(struct regmap_field *rm_field,
+ struct regmap *regmap,
+ struct reg_field reg_field)
+{
+   rm_field->regmap = regmap;
+   rm_field->reg = reg_field.reg;
+   rm_field->shift = reg_field.lsb;
+   rm_field->mask = GENMASK(reg_field.msb, reg_field.lsb);
+}
+
+struct regmap_field *devm_regmap_field_alloc(struct udevice *dev,
+struct regmap *regmap,
+struct reg_field reg_field)
+{
+   struct regmap_field *rm_field = devm_kzalloc(dev, sizeof(*rm_field),
+GFP_KERNEL);
+   if (!rm_field)
+   return ERR_PTR(-ENOMEM);
+
+   regmap_field_init(rm_field, regmap, reg_field);
+
+   return rm_field;
+}
+
+void devm_regmap_field_free(struct udevice *dev, struct regmap_field *field)
+{
+   devm_kfree(dev, field);
+}
+
+struct regmap_field *regmap_field_alloc(struct regmap *regmap,
+   struct reg_field reg_field)
+{
+   struct regmap_field *rm_field = kzalloc(sizeof(*rm_field), GFP_KERNEL);
+
+   if (!rm_field)
+   return ERR_PTR(-ENOMEM);
+
+   regmap_field_init(rm_field, regmap, reg_field);
+
+   return rm_field;
+}
+
+void regmap_field_free(struct regmap_field *field)
+{
+   kfree(field);
+}
diff --git a/include/regmap.h b/include/regmap.h
index 730e747d90..8619566a95 100644
--- a/include/regmap.h
+++ b/include/regmap.h
@@ -314,6 +314,43 @@ int regmap_raw_read_range(struct regmap *map, uint 
range_num, uint offset,
regmap_read_poll_timeout_test(map, addr, val, cond, sleep_us, \
  timeout_ms, 0) \
 
+/**
+ * regmap_field_read_poll_timeout - Poll until a condition is met or a timeout
+ * occurs
+ *
+ * @field: Regmap field to read from
+ * @val:   Unsigned integer variable to read the value into
+ * @cond:  Break condition (usually involving @val)
+ * @sleep_us:  Maximum time to sleep between reads in us (0 tight-loops).
+ * @timeout_ms:Timeout in ms, 0 means never timeout
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_field_read
+ * error return value in case of a error read. In the two former cases,
+ * the last read value at @addr is stored in @val.
+ *
+ * This is modelled after the regmap_read_poll_timeout macros in linux but
+ * with millisecond timeout.
+ */
+#define regmap_field_read_poll_timeout(field, val, cond, sleep_us, timeout_ms) 
\
+({ \
+   unsigned long __start = get_timer(0); \
+   int __ret; \
+   for (;;) { \
+   __ret = regmap_field_read((field), &(val)); \
+   if (__ret) \
+   break; \
+   if (cond) \
+   break; \
+   if ((timeout_ms) && get_timer(__start) > (timeout_ms)) { \
+   __ret = regmap_field_read((field), &(val)); \
+   break; \
+   } \
+   if ((sleep_us)) \
+   udelay((sleep_us)); \
+   } \
+   __ret ?: ((cond) ? 0 : -ETIMEDOUT); \
+})
+
 /**
  * regmap_update_bits() - Perform a read/modify/write using a mask
  *
@@ -390,4 +427,75 @@ void *regmap_get_range(struct regmap

[U-Boot] [PATCH v2 4/4] test: dm: Add tests for regmap managed API and regmap fields

2019-11-05 Thread Jean-Jacques Hiblot
The tests rely on a dummy driver to allocate and initialize the regmap
and the regmap fields using the managed API.
The first test checks that the read/write callbacks are used.
The second test checks if regmap fields behave properly (mask and shift
are ok) by peeking into the regmap.

Signed-off-by: Jean-Jacques Hiblot 
Reviewed-by: Simon Glass 

---

Changes in v2: None

 arch/sandbox/dts/test.dts |  13 +++
 test/dm/regmap.c  | 189 ++
 2 files changed, 202 insertions(+)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index fdb08f2111..aa9eaec338 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -889,6 +889,19 @@
mdio: mdio-test {
compatible = "sandbox,mdio";
};
+
+   some_regmapped-bus {
+   #address-cells = <0x1>;
+   #size-cells = <0x1>;
+
+   ranges = <0x0 0x0 0x10>;
+   compatible = "simple-bus";
+
+   regmap-test_0 {
+   reg = <0 0x10>;
+   compatible = "sandbox,regmap_test";
+   };
+   };
 };
 
 #include "sandbox_pmic.dtsi"
diff --git a/test/dm/regmap.c b/test/dm/regmap.c
index 6fd1f20656..1a0dc78019 100644
--- a/test/dm/regmap.c
+++ b/test/dm/regmap.c
@@ -184,3 +184,192 @@ static int dm_test_regmap_poll(struct unit_test_state 
*uts)
 }
 
 DM_TEST(dm_test_regmap_poll, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+struct regmaptest_priv {
+   struct regmap *regmap;
+   struct regmap_field **fields;
+};
+
+#define REGMAP_TEST_BUF_SZ 12
+struct regmaptest_context {
+   unsigned short buffer[REGMAP_TEST_BUF_SZ];
+} ctx;
+
+static int regmaptest_write(void *context, unsigned int reg, unsigned int val)
+{
+   struct regmaptest_context *ctx = context;
+
+   if (reg < ARRAY_SIZE(ctx->buffer)) {
+   ctx->buffer[reg] = val;
+   return 0;
+   }
+   return -ERANGE;
+}
+
+static int regmaptest_read(void *context, unsigned int reg, unsigned int *val)
+{
+   struct regmaptest_context *ctx = context;
+
+   if (reg < ARRAY_SIZE(ctx->buffer)) {
+   *val = ctx->buffer[reg];
+   return 0;
+   }
+
+   return -ERANGE;
+}
+
+static struct regmap_config cfg = {
+   .reg_write = regmaptest_write,
+   .reg_read = regmaptest_read,
+};
+
+static const struct reg_field field_cfgs[] = {
+   {
+   .reg = 0,
+   .lsb = 0,
+   .msb = 6,
+   },
+   {
+   .reg = 1,
+   .lsb = 4,
+   .msb = 12,
+   },
+   {
+   .reg = 1,
+   .lsb = 12,
+   .msb = 15,
+   }
+};
+
+static int remaptest_probe(struct udevice *dev)
+{
+   struct regmaptest_priv *priv = dev_get_priv(dev);
+   struct regmap *regmap;
+   struct regmap_field *field;
+   int i;
+   static const int n = ARRAY_SIZE(field_cfgs);
+
+   regmap = devm_regmap_init(dev, NULL, , );
+   if (IS_ERR(regmap))
+   return PTR_ERR(regmap);
+   priv->regmap = regmap;
+
+   priv->fields = devm_kzalloc(dev, sizeof(struct regmap_field *) * n,
+   GFP_KERNEL);
+   if (!priv->fields)
+   return -ENOMEM;
+
+   for (i = 0 ; i < n; i++) {
+   field = devm_regmap_field_alloc(dev, regmap, field_cfgs[i]);
+   if (IS_ERR(field))
+   return PTR_ERR(field);
+   priv->fields[i] = field;
+   }
+   return 0;
+}
+
+static const struct udevice_id regmaptest_ids[] = {
+   { .compatible = "sandbox,regmap_test" },
+   { }
+};
+
+U_BOOT_DRIVER(regmap_test) = {
+   .name   = "regmaptest_drv",
+   .of_match   = regmaptest_ids,
+   .id = UCLASS_NOP,
+   .probe = remaptest_probe,
+   .priv_auto_alloc_size = sizeof(struct regmaptest_priv),
+};
+
+static int dm_test_devm_regmap(struct unit_test_state *uts)
+{
+   int i = 0;
+   u32 val;
+   u16 pattern[REGMAP_TEST_BUF_SZ];
+   struct udevice *dev;
+   struct regmaptest_priv *priv;
+
+   ut_assertok(uclass_get_device_by_name(UCLASS_NOP, "regmap-test_0",
+ ));
+
+   priv = dev_get_priv(dev);
+
+   srand(get_ticks() + rand());
+   for (i = REGMAP_TEST_BUF_SZ - 1; i >= 0; i--) {
+   pattern[i] = rand() & 0x;
+   ut_assertok(regmap_write(priv->regmap, i, pattern[i]));
+   }
+   for (i = 0; i < REGMAP_TEST_BUF_SZ; i++) {
+   ut_assertok(regmap_read(priv->regmap, i, ));
+   ut_asserteq(val, ctx.buffer[i]);
+   ut_asserteq(val, pattern[i]);
+   }
+
+   ut_asserteq(-ERANGE, regmap_write(priv->regm

[U-Boot] [PATCH v2 2/4] regmap: Allow providing read/write callbacks through struct regmap_config

2019-11-05 Thread Jean-Jacques Hiblot
Some linux drivers provide their own read/write functions to access data
from/of the regmap. Adding support for it.

Signed-off-by: Jean-Jacques Hiblot 

---

Changes in v2:
- Only use custom accessors if {,SPL,TPL}_REGMAP_ACCESSORS is enabled

 drivers/core/Kconfig  | 25 +
 drivers/core/regmap.c | 22 --
 include/regmap.h  | 28 +---
 3 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 3b95b5387b..3d836a63bf 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -129,6 +129,31 @@ config TPL_REGMAP
  support any bus type (I2C, SPI) but so far this only supports
  direct memory access.
 
+config REGMAP_ACCESSORS
+   bool
+   depends on REGMAP
+   default y
+
+config SPL_REGMAP_ACCESSORS
+   bool "Support custom regmap accessors in SPL"
+   depends on SPL_REGMAP
+   help
+ Allow to use a regmap with custom accessors. The acessors are the
+ low-level functions actually performing the read and write
+ operations.
+ This option can be used to access registers that are not
+ memory-mapped.
+
+config TPL_REGMAP_ACCESSORS
+   bool "Support custom regmap accessors in TPL"
+   depends on TPL_REGMAP
+   help
+ Allow to use a regmap with custom accessors. The acessors are the
+ low-level functions actually performing the read and write
+ operations.
+ This option can be used to access registers that are not
+ memory-mapped.
+
 config SYSCON
bool "Support system controllers"
depends on REGMAP
diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index f69ff6d12f..10ae9f918a 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -31,7 +31,11 @@ static struct regmap *regmap_alloc(int count)
if (!map)
return NULL;
map->range_count = count;
-
+#if CONFIG_IS_ENABLED(REGMAP_ACCESSORS)
+   map->bus_context = NULL;
+   map->reg_read = NULL;
+   map->reg_write = NULL;
+#endif
return map;
 }
 
@@ -241,7 +245,11 @@ struct regmap *devm_regmap_init(struct udevice *dev,
rc = regmap_init_mem(dev_ofnode(dev), mapp);
if (rc)
return ERR_PTR(rc);
-
+#if CONFIG_IS_ENABLED(REGMAP_ACCESSORS)
+   (*mapp)->reg_read = config->reg_read;
+   (*mapp)->reg_write = config->reg_write;
+   (*mapp)->bus_context = bus_context;
+#endif
devres_add(dev, mapp);
return *mapp;
 }
@@ -320,6 +328,11 @@ int regmap_raw_read_range(struct regmap *map, uint 
range_num, uint offset,
struct regmap_range *range;
void *ptr;
 
+#if CONFIG_IS_ENABLED(REGMAP_ACCESSORS)
+   if (map->reg_read)
+   return map->reg_read(map->bus_context, offset, valp);
+#endif
+
if (range_num >= map->range_count) {
debug("%s: range index %d larger than range count\n",
  __func__, range_num);
@@ -429,6 +442,11 @@ int regmap_raw_write_range(struct regmap *map, uint 
range_num, uint offset,
struct regmap_range *range;
void *ptr;
 
+#if CONFIG_IS_ENABLED(REGMAP_ACCESSORS)
+   if (map->reg_write)
+   return map->reg_write(map->bus_context, offset,
+ *(unsigned int *)val);
+#endif
if (range_num >= map->range_count) {
debug("%s: range index %d larger than range count\n",
  __func__, range_num);
diff --git a/include/regmap.h b/include/regmap.h
index 624cdd8c98..730e747d90 100644
--- a/include/regmap.h
+++ b/include/regmap.h
@@ -74,16 +74,38 @@ struct regmap_range {
 };
 
 struct regmap_bus;
-struct regmap_config;
+/**
+ * struct regmap_config - a way of accessing hardware/bus registers
+ *
+ * @reg_read:Optional callback that if filled will be used to perform
+ *   all the reads from the registers. Should only be provided for
+ *   devices whose read operation cannot be represented as a simple
+ *   read operation on a bus such as SPI, I2C, etc. Most of the
+ *   devices do not need this.
+ * @reg_write:   Same as above for writing.
+ */
+struct regmap_config {
+   int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
+   int (*reg_write)(void *context, unsigned int reg, unsigned int val);
+};
 
 /**
  * struct regmap - a way of accessing hardware/bus registers
  *
  * @range_count:   Number of ranges available within the map
  * @ranges:Array of ranges
+ * @bus_context:   Data passed to bus-specific callbacks
+ * @reg_read:  Optional callback that if filled will be used to perform
+ * all the reads from the registers.
+ * @reg_write: Same as above for writing.

[U-Boot] [PATCH v2 0/4] regmap: Add a managed API, custom read/write callbacks and support for regmap fields

2019-11-05 Thread Jean-Jacques Hiblot

This is the first of a few series, the goal of which is to facilitate
porting drivers from the linux kernel. Most of the series will be about
adding managed API to existing infrastructure (GPIO, reset, phy,...)

This particular series is about regmaps. It adds the managed API, using
the same API as linux. It also adds support for regmap fields and for
custom read/write callbacks.

Changes in v2:
- Fix comment for devm_regmap_init()
- Fix spelling in commit log
- Only use custom accessors if {,SPL,TPL}_REGMAP_ACCESSORS is enabled

Jean-Jacques Hiblot (4):
  regmap: Add devm_regmap_init()
  regmap: Allow providing read/write callbacks through struct
regmap_config
  regmap: Add support for regmap fields
  test: dm: Add tests for regmap managed API and regmap fields

 arch/sandbox/dts/test.dts |  13 +++
 drivers/core/Kconfig  |  25 +
 drivers/core/regmap.c | 123 -
 include/regmap.h  | 148 +
 test/dm/regmap.c  | 189 ++
 5 files changed, 497 insertions(+), 1 deletion(-)

-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v2 1/4] regmap: Add devm_regmap_init()

2019-11-05 Thread Jean-Jacques Hiblot
Most of new linux drivers are using managed-API to allocate resources. To
ease porting drivers from linux to U-Boot, introduce devm_regmap_init() as
a managed API to get a regmap from the device tree.

Signed-off-by: Jean-Jacques Hiblot 
Reviewed-by: Simon Glass 

---

Changes in v2:
- Fix comment for devm_regmap_init()
- Fix spelling in commit log

 drivers/core/regmap.c | 26 ++
 include/regmap.h  | 18 ++
 2 files changed, 44 insertions(+)

diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index e9e55c9d16..f69ff6d12f 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -219,6 +219,32 @@ int regmap_init_mem(ofnode node, struct regmap **mapp)
 
return 0;
 }
+
+static void devm_regmap_release(struct udevice *dev, void *res)
+{
+   regmap_uninit(*(struct regmap **)res);
+}
+
+struct regmap *devm_regmap_init(struct udevice *dev,
+   const struct regmap_bus *bus,
+   void *bus_context,
+   const struct regmap_config *config)
+{
+   int rc;
+   struct regmap **mapp;
+
+   mapp = devres_alloc(devm_regmap_release, sizeof(struct regmap *),
+   __GFP_ZERO);
+   if (unlikely(!mapp))
+   return ERR_PTR(-ENOMEM);
+
+   rc = regmap_init_mem(dev_ofnode(dev), mapp);
+   if (rc)
+   return ERR_PTR(rc);
+
+   devres_add(dev, mapp);
+   return *mapp;
+}
 #endif
 
 void *regmap_get_range(struct regmap *map, unsigned int range_num)
diff --git a/include/regmap.h b/include/regmap.h
index 9ada1af5ef..624cdd8c98 100644
--- a/include/regmap.h
+++ b/include/regmap.h
@@ -73,6 +73,9 @@ struct regmap_range {
ulong size;
 };
 
+struct regmap_bus;
+struct regmap_config;
+
 /**
  * struct regmap - a way of accessing hardware/bus registers
  *
@@ -333,6 +336,21 @@ int regmap_init_mem_platdata(struct udevice *dev, 
fdt_val_t *reg, int count,
 
 int regmap_init_mem_index(ofnode node, struct regmap **mapp, int index);
 
+/**
+ * devm_regmap_init() - Initialise register map (device managed)
+ *
+ * @dev: Device that will be interacted with
+ * @bus: Bus-specific callbacks to use with device (IGNORED)
+ * @bus_context: Data passed to bus-specific callbacks (IGNORED)
+ * @config: Configuration for register map (IGNORED)
+ *
+ * @Return a valid pointer to a struct regmap or a ERR_PTR() on error.
+ * The structure is automatically freed when the device is unbound
+ */
+struct regmap *devm_regmap_init(struct udevice *dev,
+   const struct regmap_bus *bus,
+   void *bus_context,
+   const struct regmap_config *config);
 /**
  * regmap_get_range() - Obtain the base memory address of a regmap range
  *
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v1 3/4] drivers: mux: mmio-based syscon mux controller

2019-11-04 Thread Jean-Jacques Hiblot

Simon,

On 30/10/2019 02:48, Simon Glass wrote:

On Wed, 2 Oct 2019 at 06:47, Jean-Jacques Hiblot  wrote:

This adds a driver for mmio-based syscon multiplexers controlled by
bitfields in a syscon register range.
This is heavily based on the linux mmio-mux driver.

Signed-off-by: Jean-Jacques Hiblot 
---

  drivers/mux/Kconfig  |  15 +
  drivers/mux/Makefile |   1 +
  drivers/mux/mmio.c   | 155 +++
  3 files changed, 171 insertions(+)
  create mode 100644 drivers/mux/mmio.c

Reviewed-by: Simon Glass 

So much memory allocation! But I suppose it is unavoidable. No way to
use DM's auto-alloc?


I didn't try very hard to reduce the number of allocations to keep the 
code simple.


Part of the trouble comes from the fact that the number of mux_controls 
is read from the DT making it not possible to use the auto-alloc.


With other type of multiplexers (like a I2C or analog-lines multiplexer) 
the number of controls will be fixed and using auto-alloc will be possible.


JJ



Regards,
Simon


___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v1 2/4] dm: board: complete the initialization of the muxes in initr_dm()

2019-11-04 Thread Jean-Jacques Hiblot


On 30/10/2019 02:48, Simon Glass wrote:

Hi Jean-Jacques,

On Wed, 2 Oct 2019 at 06:47, Jean-Jacques Hiblot  wrote:

This will probe the multiplexer devices that have a "u-boot,mux-autoprobe"
property. As a consequence they will be put in their idle state.

Signed-off-by: Jean-Jacques Hiblot 
---

  common/board_r.c | 2 ++
  1 file changed, 2 insertions(+)

I worry this should happen later, or lazily, since at present we don't
actually probe any devices at this point, right?


It has to be done early to make sure that the platform is in the right 
state before most of the drivers are initialized. Some devices may rely 
on it without knowing it. In this way, it is similar to the gpio-hog 
mechanism.


Now, I have no strong opinion on when this should really take place. 
Only it has to be after dm is initialized. Maybe it could be inserted in 
init_sequence_r, after board_init() ?


It should probably be before the serial port is used, just in case 
someone multiplexed the serial port of the console.



JJ




Regards,
Simon


___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v1 1/4] drivers: Add a new framework for multiplexer devices

2019-11-04 Thread Jean-Jacques Hiblot

Hi Simon,

Thank for the review.

On 30/10/2019 02:48, Simon Glass wrote:

Hi Jean-Jacques,

On Wed, 2 Oct 2019 at 06:47, Jean-Jacques Hiblot  wrote:

Add a new subsystem that handles multiplexer controllers. The API is the
same as in Linux.

Signed-off-by: Jean-Jacques Hiblot 
---

  drivers/Kconfig   |   2 +
  drivers/Makefile  |   1 +
  drivers/mux/Kconfig   |   7 +
  drivers/mux/Makefile  |   6 +
  drivers/mux/mux-uclass.c  | 296 ++
  include/dm/uclass-id.h|   1 +
  include/dt-bindings/mux/mux.h |  17 ++
  include/mux-internal.h|  80 +
  include/mux.h | 114 +
  9 files changed, 524 insertions(+)
  create mode 100644 drivers/mux/Kconfig
  create mode 100644 drivers/mux/Makefile
  create mode 100644 drivers/mux/mux-uclass.c
  create mode 100644 include/dt-bindings/mux/mux.h
  create mode 100644 include/mux-internal.h
  create mode 100644 include/mux.h


I feel this needs more documentation. What is a multiplexer?


I'll add a description of what a mux is in include/mux.h




diff --git a/drivers/Kconfig b/drivers/Kconfig
index 350acf81f3..5334974ad4 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -60,6 +60,8 @@ source "drivers/mmc/Kconfig"

  source "drivers/mtd/Kconfig"

+source "drivers/mux/Kconfig"
+
  source "drivers/net/Kconfig"

  source "drivers/nvme/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index a4bb5e4975..f4d71f3b3c 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_$(SPL_TPL_)INPUT) += input/
  obj-$(CONFIG_$(SPL_TPL_)LED) += led/
  obj-$(CONFIG_$(SPL_TPL_)MMC_SUPPORT) += mmc/
  obj-$(CONFIG_$(SPL_TPL_)NAND_SUPPORT) += mtd/nand/raw/
+obj-$(CONFIG_$(SPl_)MULTIPLEXER) += mux/

SPL?

good catch



  obj-$(CONFIG_$(SPL_TPL_)PCH_SUPPORT) += pch/
  obj-$(CONFIG_$(SPL_TPL_)PCI) += pci/
  obj-$(CONFIG_$(SPL_TPL_)PHY) += phy/
diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
new file mode 100644
index 00..ad0199c058
--- /dev/null
+++ b/drivers/mux/Kconfig
@@ -0,0 +1,7 @@
+menu "Multiplexer drivers"
+
+config MULTIPLEXER
+   bool "Multiplexer Support"
+   depends on DM
+
+endmenu
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
new file mode 100644
index 00..351e4363d3
--- /dev/null
+++ b/drivers/mux/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2019
+# Jean-Jacques Hiblot 
+
+obj-$(CONFIG_$(SPL_)MULTIPLEXER) += mux-uclass.o
diff --git a/drivers/mux/mux-uclass.c b/drivers/mux/mux-uclass.c
new file mode 100644
index 00..58998af29c
--- /dev/null
+++ b/drivers/mux/mux-uclass.c
@@ -0,0 +1,296 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Multiplexer subsystem
+ *
+ * Based on the linux multiplexer framework
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ * Author: Peter Rosin 
+ *
+ * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Jean-Jacques Hiblot 
+ */
+
+#include 
+#include 

should go above the dm/device-internal


+#include 
+#include 

Shouldn't need this

+#include 

Shouldn't need this


+#include 
+#include 
+#include 

Shouldn't need this

I'll cleanup the headers in v2.



+#include 
+
+/*
+ * The idle-as-is "state" is not an actual state that may be selected, it
+ * only implies that the state should not be changed. So, use that state
+ * as indication that the cached state of the multiplexer is unknown.
+ */
+#define MUX_CACHE_UNKNOWN MUX_IDLE_AS_IS
+
+static inline const struct mux_control_ops *mux_dev_ops(struct udevice *dev)
+{
+   return (const struct mux_control_ops *)dev->driver->ops;
+}
+
+static int mux_control_set(struct mux_control *mux, int state)
+{
+   int ret = mux_dev_ops(mux->dev)->set(mux, state);
+
+   mux->cached_state = ret < 0 ? MUX_CACHE_UNKNOWN : state;
+
+   return ret;
+}
+
+unsigned int mux_control_states(struct mux_control *mux)
+{
+   return mux->states;
+}
+
+static int __mux_control_select(struct mux_control *mux, int state)
+{
+   int ret;
+
+   if (WARN_ON(state < 0 || state >= mux->states))
+   return -EINVAL;
+
+   if (mux->cached_state == state)
+   return 0;
+
+   ret = mux_control_set(mux, state);
+   if (ret >= 0)
+   return 0;
+
+   /* The mux update failed, try to revert if appropriate... */
+   if (mux->idle_state != MUX_IDLE_AS_IS)
+   mux_control_set(mux, mux->idle_state);
+
+   return ret;
+}
+
+int mux_control_select(struct mux_control *mux, unsigned int state)
+{
+   int ret;
+
+   if (mux->in_use)
+   return -EBUSY;
+
+   ret = __mux_control_select(mux, state);
+
+   if (ret < 0)
+   return ret;
+
+   mux->in_use = true;
+
+   return 0;
+}
+
+int mux_control_deselect(str

Re: [U-Boot] [PATCH v1 3/5] regmap: Allow providing read/write callbacks through struct regmap_config

2019-11-04 Thread Jean-Jacques Hiblot


On 30/10/2019 02:48, Simon Glass wrote:

Hi Jean-Jacques,

On Fri, 27 Sep 2019 at 07:22, Jean-Jacques Hiblot  wrote:

Some linux drivers provide their own read/write functions to access data
from/of the regmap. Adding support for it.

Signed-off-by: Jean-Jacques Hiblot 
---

  drivers/core/regmap.c | 12 
  include/regmap.h  | 26 +++---
  2 files changed, 35 insertions(+), 3 deletions(-)

This increases code size in SPL so should probably be controlled by a Kconfig.

OK.


Also I wonder if regmap should become a uclass if we are adding


I don't see a real value in making a regmap a device. IMO It will just 
make things more complex than needed.


JJ


operations to it?

Regards,
Simon


___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v1 2/3] drivers: reset: Add a managed API to get reset controllers from the DT

2019-11-04 Thread Jean-Jacques Hiblot


On 30/10/2019 02:48, Simon Glass wrote:

On Mon, 30 Sep 2019 at 10:15, Jean-Jacques Hiblot  wrote:

Add managed functions to get a reset_ctl from the device-tree, based on a
name or an index.
Also add a managed functions to get a reset_ctl_bulk (array of reset_ctl)
from the device-tree.

When the device is unbound, the reset controllers are automatically
released and the data structure is freed.

Signed-off-by: Jean-Jacques Hiblot 
---

  drivers/reset/reset-uclass.c | 116 +-
  include/reset.h  | 135 ++-
  2 files changed, 247 insertions(+), 4 deletions(-)

Reviewed-by: Simon Glass 

I really don't like these ERR_PTR returns. I suppose they make the
code easier to port, and we can be sure that pointers will not be in
the last 4KB of address space?


It seems rather unlikely because the returned pointer points to actual 
RAM allocated from the heap. On most platforms I've worked with, the top 
of the address space is not dedicated to memory. If ever the need to fix 
this  arises it could done by tweaking the macros to use another unused 
address space.


JJ



Regards,
Simon


___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH 4/5] dm: regmap: Fix mask in regmap_update_bits()

2019-10-25 Thread Jean-Jacques Hiblot


On 12/10/2019 00:16, Simon Glass wrote:

This function assumes that the 'val' parameter has no masked bits set.
This is not defined by the function prototype though. Fix the function to
mask the value and update the documentation.

Signed-off-by: Simon Glass 
---

  drivers/core/regmap.c | 2 +-
  include/regmap.h  | 3 ++-
  2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index d1d12eef385..e9e55c9d165 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -462,5 +462,5 @@ int regmap_update_bits(struct regmap *map, uint offset, 
uint mask, uint val)
  
  	reg &= ~mask;
  
-	return regmap_write(map, offset, reg | val);

+   return regmap_write(map, offset, reg | (val & mask));
  }
diff --git a/include/regmap.h b/include/regmap.h
index 0854200a9c1..9ada1af5ef0 100644
--- a/include/regmap.h
+++ b/include/regmap.h
@@ -295,7 +295,8 @@ int regmap_raw_read_range(struct regmap *map, uint 
range_num, uint offset,
   * @map:  The map returned by regmap_init_mem*()
   * @offset:   Offset of the memory
   * @mask: Mask to apply to the read value
- * @val:   Value to apply to the value to write
+ * @val:   Value to OR with the read value after masking. Note that any
+ * bits set in @val which are not set in @mask are ignored
   * Return: 0 if OK, -ve on error
   */
  int regmap_update_bits(struct regmap *map, uint offset, uint mask, uint val);


Reviewed-by: Jean-Jacques Hiblot 

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v1 4/4] test: Add tests for the multiplexer framework

2019-10-25 Thread Jean-Jacques Hiblot

Hi Tom,

On 25/10/2019 01:45, Tom Rini wrote:

On Wed, Oct 02, 2019 at 02:47:49PM +0200, Jean-Jacques Hiblot wrote:


Provide tests to check the behavior of the multiplexer framework.
The test uses a mmio-based multiplexer.

Signed-off-by: Jean-Jacques Hiblot 

These tests don't pass (with all of the other series applied as well,
and some warnings fixed up):
_ test_ut[ut_dm_devm_mux_mmio] _

u_boot_console = 
ut_subtest = 'dm devm_mux_mmio'

 def test_ut(u_boot_console, ut_subtest):
 """Execute a "ut" subtest."""
 
 output = u_boot_console.run_command('ut ' + ut_subtest)

   assert output.endswith('Failures: 0')

E   assert False
E+  where False = ('Failures: 0')
E+where  = 'Test: dm_test_devm_mux_mmio: 
mux-mmio.c\r\r\n/builds/u-boot/u-boot/test/dm/mux-mmio.c:110, dm_test_devm_mux_mmio(): "...ux-mmio.c:110, 
dm_test_devm_mux_mmio(): "b-test" = dev_b->name: Expected "b-test", got 
"another-test"\r\r\nFailures: 2'.endswith


There has been some changes in the regmap support for sandbox. I'll 
rebase on top of master and send an updated version.


Thanks

JJ



test/py/tests/test_ut.py:28: AssertionError
- Captured stdout call -
=> ut dm devm_mux_mmio

Test: dm_test_devm_mux_mmio: mux-mmio.c

/builds/u-boot/u-boot/test/dm/mux-mmio.c:110, dm_test_devm_mux_mmio(): "b-test" = dev_b->name: 
Expected "b-test", got "another-test"

Test: dm_test_devm_mux_mmio: mux-mmio.c (flat tree)

/builds/u-boot/u-boot/test/dm/mux-mmio.c:110, dm_test_devm_mux_mmio(): "b-test" = dev_b->name: 
Expected "b-test", got "another-test"

Failures: 2

=>

Finally, clang-7 reports:
/home/trini/u-boot/u-boot/drivers/mux/mux-uclass.c:108:34: warning: variable 
'mux' is uninitialized when used here [-Wuninitialized]
 debug("%s(mux=%p)\n", __func__, mux);
 ^~~
/home/trini/u-boot/u-boot/include/log.h:188:28: note: expanded from macro 
'debug'
 debug_cond(_DEBUG, fmt, ##args)
   ^~~~
/home/trini/u-boot/u-boot/include/log.h:168:41: note: expanded from macro 
'debug_cond'
 log(LOG_CATEGORY, LOGL_DEBUG, fmt, ##args); \
  ^~~~
/home/trini/u-boot/u-boot/include/log.h:139:25: note: expanded from macro 'log'
   pr_fmt(_fmt), ##_args); \
   ^
/home/trini/u-boot/u-boot/drivers/mux/mux-uclass.c:105:25: note: initialize the 
variable 'mux' to silence this warning
 struct mux_control *mux;
^
 = NULL

Thanks!


___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH] usb: composite: add BOS descriptor support to composite framework

2019-10-24 Thread Jean-Jacques Hiblot

+ Vignesh and Roger

On 24/10/2019 13:22, Michal Simek wrote:

po 14. 10. 2019 v 14:52 odesílatel Michal Simek
 napsal:

From: T Karthik Reddy 

To add usb-3.0 support to peripheral device add BOS & SS capability
descriptors to gadget composite framework.

Signed-off-by: T Karthik Reddy 
Signed-off-by: Siva Durga Prasad Paladugu 
Signed-off-by: Michal Simek 
---

  drivers/usb/gadget/composite.c | 61 ++
  include/linux/usb/ch9.h|  3 ++
  include/linux/usb/gadget.h |  9 +
  3 files changed, 67 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index c7e762374752..618a7d5016ee 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -688,6 +688,57 @@ static void composite_setup_complete(struct usb_ep *ep, 
struct usb_request *req)
 req->status, req->actual, req->length);
  }

+static int bos_desc(struct usb_composite_dev *cdev)
+{
+   struct usb_ext_cap_descriptor   *usb_ext;
+   struct usb_bos_descriptor   *bos = cdev->req->buf;
+
+   bos->bLength = USB_DT_BOS_SIZE;
+   bos->bDescriptorType = USB_DT_BOS;
+
+   bos->wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE);
+   bos->bNumDeviceCaps = 0;
+
+   /*
+* A SuperSpeed device shall include the USB2.0 extension descriptor
+* and shall support LPM when operating in USB2.0 HS mode.
+*/
+   usb_ext = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
+   bos->bNumDeviceCaps++;
+   le16_add_cpu(>wTotalLength, USB_DT_USB_EXT_CAP_SIZE);
+   usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE;
+   usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
+   usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT;
+   usb_ext->bmAttributes =
+   cpu_to_le32(USB_LPM_SUPPORT | USB_BESL_SUPPORT);
+
+   /*
+* The Superspeed USB Capability descriptor shall be implemented
+* by all SuperSpeed devices.
+*/
+   if (gadget_is_superspeed(cdev->gadget)) {
+   struct usb_ss_cap_descriptor *ss_cap;
+
+   ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
+   bos->bNumDeviceCaps++;
+   le16_add_cpu(>wTotalLength, USB_DT_USB_SS_CAP_SIZE);
+   ss_cap->bLength = USB_DT_USB_SS_CAP_SIZE;
+   ss_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
+   ss_cap->bDevCapabilityType = USB_SS_CAP_TYPE;
+   ss_cap->bmAttributes = 0; /* LTM is not supported yet */
+   ss_cap->wSpeedSupported =
+   cpu_to_le16(USB_LOW_SPEED_OPERATION |
+   USB_FULL_SPEED_OPERATION |
+   USB_HIGH_SPEED_OPERATION |
+   USB_5GBPS_OPERATION);
+   ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
+   ss_cap->bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT;
+   ss_cap->bU2DevExitLat =
+   cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT);
+   }
+   return le16_to_cpu(bos->wTotalLength);
+}
+
  /*
   * The setup() callback implements all the ep0 functionality that's
   * not handled lower down, in hardware or the hardware driver(like
@@ -776,12 +827,10 @@ composite_setup(struct usb_gadget *gadget, const struct 
usb_ctrlrequest *ctrl)
 value = min(w_length, (u16) value);
 break;
 case USB_DT_BOS:
-   /*
-* The USB compliance test (USB 2.0 Command Verifier)
-* issues this request. We should not run into the
-* default path here. But return for now until
-* the superspeed support is added.
-*/
+   if (gadget_is_superspeed(cdev->gadget))
+   value = bos_desc(cdev);
+   if (value >= 0)
+   value = min(w_length, (u16)value);
 break;
 default:
 goto unknown;
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index 264c9712a33a..989a5fcbd966 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -878,6 +878,9 @@ struct usb_ss_cap_descriptor {  /* Link Power 
Management */
 __le16 bU2DevExitLat;
  } __attribute__((packed));

+#define USB_DEFAULT_U1_DEV_EXIT_LAT 0x01   /* Less then 1 microsec */
+#define USB_DEFAULT_U2_DEV_EXIT_LAT 0x01F4 /* Less then 500 microsec */
+
  #define USB_DT_USB_SS_CAP_SIZE 10

  /*
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 497798a32a87..58bfaddd036a 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -566,6 +566,15 @@ static inline int gadget_is_otg(struct usb_gadget *g)
  #endif
  }


[U-Boot] [PATCH] configs: sei610: khadas-vim3 : disable Gadget support for the DWC3

2019-10-24 Thread Jean-Jacques Hiblot
Those platform use the DWC2 controller for the gadget support and the
DWC3 for host-only operations.

Signed-off-by: Jean-Jacques Hiblot 
---

Applies on u-boot/master.
Fixes build breakage introduced by "usb: dwc3: Kconfig: get rid of obsolete mode
selection"

 configs/khadas-vim3_defconfig | 1 +
 configs/sei610_defconfig  | 1 +
 2 files changed, 2 insertions(+)

diff --git a/configs/khadas-vim3_defconfig b/configs/khadas-vim3_defconfig
index cd37f7840e..81ac42e599 100644
--- a/configs/khadas-vim3_defconfig
+++ b/configs/khadas-vim3_defconfig
@@ -44,6 +44,7 @@ CONFIG_DM_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_GADGET is not set
 CONFIG_USB_DWC3_MESON_G12A=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_VENDOR_NUM=0x1b8e
diff --git a/configs/sei610_defconfig b/configs/sei610_defconfig
index 520a683d2e..1f36722a8e 100644
--- a/configs/sei610_defconfig
+++ b/configs/sei610_defconfig
@@ -62,6 +62,7 @@ CONFIG_DM_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_GADGET is not set
 CONFIG_USB_DWC3_MESON_G12A=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_VENDOR_NUM=0x18d1
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH PATCH v6 00/13] Add support for applications of overlays in SPL

2019-10-22 Thread Jean-Jacques Hiblot

The purpose of this series is to provide the SPL with ability to apply
overlays for u-boot.

Our use-case is the support of the daughter boards of the AM65x and J721e
EVMs. In Linux, each board is supported by a unique overlay. The presence
of the boards is detected at runtime, and some useful features (like USB)
are implemented on those daughter boards. Instead of providing multiple
dtbs and fall in a combinatorial pit, we propose to use DT overlays.

On arm, if overlay are supported, this series increases the size of the SPL
by 3.2 kB.

Travis build : https://travis-ci.org/jjhiblot/u-boot/builds/600742163

Changes in v6:
- Instead of matching a overlay by the name of it's node. Try to match it
  first with the description, and then with the node's name. This allows
  to use makeimg to add the overlays to u-boot.img and not use a custom
  SPL_FIT_GENERATOR script

Changes in v5:
- Do not allocate the buffer if not needed (no overlay).
- Add a Kconfig option for the buffer size
- board_get_fit_loadable() returns an error code instead of a NULL string
  in case of failure
-reword commit log

Changes in v4:
- use CONFIG_IS_ENABLED() instead of #idef
- make sure that the temp buffer is freed in all cases
- Use the board driver infrastructure to get the image names from the
board code.
- Remove a patch that passed the board name to the FIT generator. If needed
the generator can get it from elsewhere
- Add a fix to not load the firmware twice (once as a firmware and once as
a loadable)

Changes in v3:
- Add a new config option: SPL_LOAD_FIT_APPLY_OVERLAY. By default, it is
not selected.
- removed the RFC prefix. This work will be needed soon by TI's AM65x
platform. and can probably benefit other modular platforms
- removed the last patch that provided an example of how to use this with
on a DRA76.
- removed the patch that made u-boot.img a symlink to u-boot.itb because
it breaks the build of many platforms (because files required to build the
ITB are missing)
- removed the patch to reduce the footprint of the am335x SPL. (already
merged)
- Made the boot flow more permissive (don't fail immediately if an overlay
is not present) and more verbose when an error occures
- handle the dependencies of the FIT generation in a more generic way
- use a dedicated kconfig option to enable the application of the overlays
by the SPL.

Changes in v2:
- depend on SPL_DM
- update the commit log
- reworked board_fit_get_additionnal_images() and how it used in spl_fit.c
- removed dtbo generation from dtso files and use .dts extension for the
  overlays
- add dynamic allocation usage in a separate patch
- defconfig change for the am335x_evm

Jean-Jacques Hiblot (12):
  spl: fit: don't load the firmware twice
  spl: fit: Make room in the FDT before applying overlays
  spl: fit: allocate a temporary buffer to load the overlays
  spl: fit: Do not fail immediately if an overlay is not available
  spl: fit: be more verbose when an error occurs when applying the
overlays
  Makefile.lib: include /__symbols__ in dtb if
SPL_LOAD_FIT_APPLY_OVERLAY is enabled
  spl: fit: constify the output parameter of spl_fit_get_image_name()
  drivers: board: Make the board drivers available in SPL
  drivers: board: Add get_fit_loadable()
  include: board: provide empty stubs when the BOARD option is not
selected
  dts: Add support for adding DT overlays in u-boot.img
  spl: fit: Allow the board to tell if more images must be loaded from
FIT

Michal Simek (1):
  spl: fit: Add support for applying DT overlay

 Kconfig  |  18 +
 Makefile |   3 +-
 common/spl/spl_fit.c | 151 ---
 drivers/Makefile |   2 +-
 drivers/board/Kconfig|   3 +
 drivers/board/Makefile   |   2 +-
 drivers/board/board-uclass.c |  11 +++
 dts/Kconfig  |   8 ++
 include/board.h  |  74 +
 scripts/Makefile.lib |   4 +
 10 files changed, 263 insertions(+), 13 deletions(-)

-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH PATCH v6 12/13] dts: Add support for adding DT overlays in u-boot.img

2019-10-22 Thread Jean-Jacques Hiblot
If u-boot.img is a FIT image, CONFIG_OF_OVERLAY_LIST can be used to add
DT overlays to u-boot.img.

Signed-off-by: Jean-Jacques Hiblot 
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 Makefile| 3 ++-
 dts/Kconfig | 8 
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 6fda3268e7..46c5bd4753 100644
--- a/Makefile
+++ b/Makefile
@@ -1262,7 +1262,8 @@ MKIMAGEFLAGS_u-boot.img = -f auto -A $(ARCH) -T firmware 
-C none -O u-boot \
-a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_UBOOT_START) \
-p $(CONFIG_FIT_EXTERNAL_OFFSET) \
-n "U-Boot $(UBOOTRELEASE) for $(BOARD) board" -E \
-   $(patsubst %,-b arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST)))
+   $(patsubst %,-b arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) \
+   $(patsubst %,-b arch/$(ARCH)/dts/%.dtbo,$(subst 
",,$(CONFIG_OF_OVERLAY_LIST)))
 else
 MKIMAGEFLAGS_u-boot.img = -A $(ARCH) -T firmware -C none -O u-boot \
-a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_UBOOT_START) \
diff --git a/dts/Kconfig b/dts/Kconfig
index c9ab66..c150a9b2af 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -130,6 +130,14 @@ config OF_LIST
  device tree files (without the directory or .dtb suffix)
  separated by .
 
+config OF_OVERLAY_LIST
+   string "List of device tree overlays to include for DT control"
+   depends on SPL_LOAD_FIT_APPLY_OVERLAY
+   help
+ This option specifies a list of device tree overlaysto use for DT
+ control. This option can then be used a FIT generator to include
+ the overlays in the FIT image
+
 choice
prompt "SPL OF LIST compression"
depends on MULTI_DTB_FIT
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH PATCH v6 13/13] spl: fit: Allow the board to tell if more images must be loaded from FIT

2019-10-22 Thread Jean-Jacques Hiblot
spl_fit_get_image_name() is used to get the names of the images that the
SPL must load from the FIT. It relies on the content of a property present
in the FIT. The list of images is thus statically defined in the FIT.
With this scheme, it quickly becomes hard to manage combinations of more
than a handful of images.
To address this problem, give the board driver code the opportunity to
add to the list of images. The images from the FIT property are loaded
first, and then the board_get_fit_loadable() is called to get more image
names.

Signed-off-by: Jean-Jacques Hiblot 

---

Changes in v6:
- Instead of matching a overlay by the name of it's node. Try to match it
  first with the description, and then with the node's name. This allows
  to use makeimg to add the overlays to u-boot.img and not use a custom
  SPL_FIT_GENERATOR script

Changes in v5:
-reword commit log

Changes in v4:
- Use the board driver infrastructure to get the image names from the
board code.
- Remove a patch that passed the board name to the FIT generator. If needed
the generator can get it from elsewhere
- Add a fix to not load the firmware twice (once as a firmware and once as
a loadable)

Changes in v3:
- removed the RFC prefix. This work will be needed soon by TI's AM65x
platform. and can probably benefit other modular platforms
- removed the last patch that provided an example of how to use this with
on a DRA76.
- removed the patch that made u-boot.img a symlink to u-boot.itb because
it breaks the build of many platforms (because files required to build the
ITB are missing)
- removed the patch to reduce the footprint of the am335x SPL. (already
merged)
- Made the boot flow more permissive (don't fail immediately if an overlay
is not present) and more verbose when an error occures
- handle the dependencies of the FIT generation in a more generic way
- use a dedicated kconfig option to enable the application of the overlays
by the SPL.

Changes in v2:
- reworked board_fit_get_additionnal_images() and how it used in spl_fit.c
- removed dtbo generation from dtso files and use .dts extension for the
  overlays
- add dynamic allocation usage in a separate patch
- defconfig change for the am335x_evm

 common/spl/spl_fit.c | 65 ++--
 1 file changed, 62 insertions(+), 3 deletions(-)

diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 9001731303..ac69d8312e 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -6,6 +6,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -32,6 +33,29 @@ __weak ulong board_spl_fit_size_align(ulong size)
return size;
 }
 
+static int find_node_from_desc(const void *fit, int node, const char *str)
+{
+   int child;
+
+   if (node < 0)
+   return -EINVAL;
+
+   /* iterate the FIT nodes and find a matching description */
+   for (child = fdt_first_subnode(fit, node); child >= 0;
+child = fdt_next_subnode(fit, child)) {
+   int len;
+   const char *desc = fdt_getprop(fit, child, "description", );
+
+   if (!desc)
+   continue;
+
+   if (!strcmp(desc, str))
+   return child;
+   }
+
+   return -ENOENT;
+}
+
 /**
  * spl_fit_get_image_name(): By using the matching configuration subnode,
  * retrieve the name of an image, specified by a property name and an index
@@ -48,10 +72,12 @@ static int spl_fit_get_image_name(const void *fit, int 
images,
  const char *type, int index,
  const char **outname)
 {
+   struct udevice *board;
const char *name, *str;
__maybe_unused int node;
int conf_node;
int len, i;
+   bool found = true;
 
conf_node = fit_find_config_node(fit);
if (conf_node < 0) {
@@ -77,12 +103,45 @@ static int spl_fit_get_image_name(const void *fit, int 
images,
for (i = 0; i < index; i++) {
str = strchr(str, '\0') + 1;
if (!str || (str - name >= len)) {
-   debug("no string for index %d\n", index);
-   return -E2BIG;
+   found = false;
+   break;
+   }
+   }
+
+   if (!found && !board_get()) {
+   int rc;
+   /*
+* no string in the property for this index. Check if the board
+* level code can supply one.
+*/
+   rc = board_get_fit_loadable(board, index - i - 1, type, );
+   if (rc && rc != -ENOENT)
+   return rc;
+
+   if (!rc) {
+   /*
+* The board provided a name for a loadable.
+* Try to match it against the description properties
+   

[U-Boot] [PATCH PATCH v6 09/13] drivers: board: Make the board drivers available in SPL

2019-10-22 Thread Jean-Jacques Hiblot
Make the board driver available in the SPL too. The board driver is a way
to provide useful information about the board and that can be useful in
the SPL too.

Signed-off-by: Jean-Jacques Hiblot 
Reviewed-by: Simon Glass 

---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2:
- depend on SPL_DM
- update the commit log

 drivers/Makefile   | 2 +-
 drivers/board/Kconfig  | 3 +++
 drivers/board/Makefile | 2 +-
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/Makefile b/drivers/Makefile
index a4bb5e4975..6dd43d4949 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_$(SPL_TPL_)VIRTIO) += virtio/
 obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox/
 obj-$(CONFIG_$(SPL_)REMOTEPROC) += remoteproc/
 obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm/
+obj-$(CONFIG_$(SPL_)BOARD) += board/
 
 ifndef CONFIG_TPL_BUILD
 ifdef CONFIG_SPL_BUILD
@@ -77,7 +78,6 @@ obj-y += ata/
 obj-$(CONFIG_DM_DEMO) += demo/
 obj-$(CONFIG_BIOSEMU) += bios_emulator/
 obj-y += block/
-obj-y += board/
 obj-$(CONFIG_BOOTCOUNT_LIMIT) += bootcount/
 obj-y += cache/
 obj-$(CONFIG_CPU) += cpu/
diff --git a/drivers/board/Kconfig b/drivers/board/Kconfig
index 2a3fc9c049..254f657049 100644
--- a/drivers/board/Kconfig
+++ b/drivers/board/Kconfig
@@ -8,6 +8,9 @@ menuconfig BOARD
 
 if BOARD
 
+config SPL_BOARD
+   depends on SPL_DM
+   bool "Enable board driver support in SPL"
 
 config BOARD_GAZERBEAM
bool "Enable board driver for the Gazerbeam board"
diff --git a/drivers/board/Makefile b/drivers/board/Makefile
index c8dab4fa0b..cc16361755 100644
--- a/drivers/board/Makefile
+++ b/drivers/board/Makefile
@@ -2,6 +2,6 @@
 #
 # (C) Copyright 2017
 # Mario Six,  Guntermann & Drunck GmbH, mario@gdsys.cc
-obj-$(CONFIG_BOARD) += board-uclass.o
+obj-y += board-uclass.o
 obj-$(CONFIG_BOARD_GAZERBEAM) += gazerbeam.o
 obj-$(CONFIG_BOARD_SANDBOX) += sandbox.o
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH PATCH v6 06/13] spl: fit: be more verbose when an error occurs when applying the overlays

2019-10-22 Thread Jean-Jacques Hiblot
There are many ways the overlay application can fail.
2 of them are probably the most common:
- the application itself failed. Usually this is comes from an unresolved
  reference
- DTBO not available in FIT (could be because of a typo)

In both case it is good to be more explicit about the error and at least
show which overlay is failing.

Signed-off-by: Jean-Jacques Hiblot 
Reviewed-by: Simon Glass 
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 common/spl/spl_fit.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 0245dcadb4..5aeb9528fe 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -113,7 +113,7 @@ static int spl_fit_get_image_node(const void *fit, int 
images,
 
node = fdt_subnode_offset(fit, images, str);
if (node < 0) {
-   debug("cannot find image node '%s': %d\n", str, node);
+   pr_err("cannot find image node '%s': %d\n", str, node);
return -EINVAL;
}
 
@@ -359,8 +359,11 @@ static int spl_fit_append_fdt(struct spl_image_info 
*spl_image,
 
ret = fdt_overlay_apply_verbose(spl_image->fdt_addr,
(void 
*)image_info.load_addr);
-   if (ret)
+   if (ret) {
+   pr_err("failed to apply DT overlay %s\n",
+  fit_get_name(fit, node, NULL));
break;
+   }
 
debug("%s: DT overlay %s applied\n", __func__,
  fit_get_name(fit, node, NULL));
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH PATCH v6 04/13] spl: fit: allocate a temporary buffer to load the overlays

2019-10-22 Thread Jean-Jacques Hiblot
If the node describing an overlay does not specify a load address, it will
be loaded at the address previously used.
Fixing it by allocating a temporary buffer that will be used as a
default load address. By default, the size of the buffer is 64kB which
should be plenty for most use cases.

Signed-off-by: Jean-Jacques Hiblot 

---

Changes in v6: None
Changes in v5:
- Do not allocate the buffer if not needed (no overlay).
- Add a Kconfig option for the buffer size

Changes in v4:
- make sure that the temp buffer is freed in all cases

Changes in v3: None
Changes in v2: None

 Kconfig  |  9 +
 common/spl/spl_fit.c | 34 +-
 2 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/Kconfig b/Kconfig
index 518ce7e0d6..417799a700 100644
--- a/Kconfig
+++ b/Kconfig
@@ -438,6 +438,15 @@ config SPL_LOAD_FIT_APPLY_OVERLAY
  also load device-tree overlays from the FIT image an apply them
  over the device tree.
 
+config SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ
+   depends on SPL_LOAD_FIT_APPLY_OVERLAY
+   default 0x1
+   hex "size of temporary buffer used to load the overlays"
+   help
+ The size of the area where the overlays will be loaded and
+ uncompress. Must be at least as large as biggest overlay
+ (uncompressed)
+
 config SPL_LOAD_FIT_FULL
bool "Enable SPL loading U-Boot as a FIT (full fitImage features)"
select SPL_FIT
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 65dd835ecc..e6935c16b7 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -9,11 +9,16 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
+#include 
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#ifndef CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ
+#define CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ (64 * 1024)
+#endif
+
 #ifndef CONFIG_SYS_BOOTM_LEN
 #define CONFIG_SYS_BOOTM_LEN   (64 << 20)
 #endif
@@ -314,33 +319,52 @@ static int spl_fit_append_fdt(struct spl_image_info 
*spl_image,
spl_image->fdt_addr = (void *)image_info.load_addr;
 #if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
if (CONFIG_IS_ENABLED(LOAD_FIT_APPLY_OVERLAY)) {
+   void *tmpbuffer = NULL;
+
for (; ; index++) {
node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP,
  index);
if (node < 0) {
debug("%s: No additional FDT node\n", __func__);
-   return 0;
+   break;
}
 
+   if (!tmpbuffer) {
+   /*
+* allocate memory to store the DT overlay
+* before it is applied. It may not be used
+* depending on how the overlay is stored, so
+* don't fail yet if the allocation failed.
+*/
+   tmpbuffer = 
malloc(CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ);
+   if (!tmpbuffer)
+   debug("%s: unable to allocate space for 
overlays\n",
+ __func__);
+   }
+   image_info.load_addr = (ulong)tmpbuffer;
ret = spl_load_fit_image(info, sector, fit, base_offset,
 node, _info);
if (ret < 0)
-   return ret;
+   break;
 
/* Make room in FDT for changes from the overlay */
ret = fdt_increase_size(spl_image->fdt_addr,
image_info.size);
if (ret < 0)
-   return ret;
+   break;
 
ret = fdt_overlay_apply_verbose(spl_image->fdt_addr,
(void 
*)image_info.load_addr);
if (ret)
-   return ret;
+   break;
 
debug("%s: DT overlay %s applied\n", __func__,
  fit_get_name(fit, node, NULL));
}
+   if (tmpbuffer)
+   free(tmpbuffer);
+   if (ret)
+   return ret;
}
/* Try to make space, so we can inject details on the loadables */
ret = fdt_shrink_to_minimum(spl_image->fdt_addr, 8192);
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH PATCH v6 10/13] drivers: board: Add get_fit_loadable()

2019-10-22 Thread Jean-Jacques Hiblot
This function will be used by the SPL to get the names of images to load
from the FIT. This allows to load different images based on runtime HW
detection.

Signed-off-by: Jean-Jacques Hiblot 

---

Changes in v6: None
Changes in v5:
- board_get_fit_loadable() returns an error code instead of a NULL string
  in case of failure

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/board/board-uclass.c | 11 +++
 include/board.h  | 37 
 2 files changed, 48 insertions(+)

diff --git a/drivers/board/board-uclass.c b/drivers/board/board-uclass.c
index a516ba4962..b5485e9895 100644
--- a/drivers/board/board-uclass.c
+++ b/drivers/board/board-uclass.c
@@ -23,6 +23,17 @@ int board_detect(struct udevice *dev)
return ops->detect(dev);
 }
 
+int board_get_fit_loadable(struct udevice *dev, int index,
+  const char *type, const char **strp)
+{
+   struct board_ops *ops = board_get_ops(dev);
+
+   if (!ops->get_fit_loadable)
+   return -ENOSYS;
+
+   return ops->get_fit_loadable(dev, index, type, strp);
+}
+
 int board_get_bool(struct udevice *dev, int id, bool *val)
 {
struct board_ops *ops = board_get_ops(dev);
diff --git a/include/board.h b/include/board.h
index 9dc78684f8..fd6a486702 100644
--- a/include/board.h
+++ b/include/board.h
@@ -79,6 +79,24 @@ struct board_ops {
 * Return: 0 if OK, -ve on error.
 */
int (*get_str)(struct udevice *dev, int id, size_t size, char *val);
+
+   /**
+* get_fit_loadable - Get the name of an image to load from FIT
+* This function can be used to provide the image names based on runtime
+* detection. A classic use-case would when DTBOs are used to describe
+* additionnal daughter cards.
+*
+* @dev:The board instance to gather the data.
+* @index:  Index of the image. Starts at 0 and gets incremented
+*  after each call to this function.
+* @type:   The type of image. For example, "fdt" for DTBs
+* @strp:   A pointer to string. Untouched if the function fails
+*
+* Return: 0 if OK, -ENOENT if no loadable is available else -ve on
+* error.
+*/
+   int (*get_fit_loadable)(struct udevice *dev, int index,
+   const char *type, const char **strp);
 };
 
 #define board_get_ops(dev) ((struct board_ops *)(dev)->driver->ops)
@@ -137,3 +155,22 @@ int board_get_str(struct udevice *dev, int id, size_t 
size, char *val);
  * Return: 0 if OK, -ve on error.
  */
 int board_get(struct udevice **devp);
+
+/**
+ * board_get_fit_loadable - Get the name of an image to load from FIT
+ * This function can be used to provide the image names based on runtime
+ * detection. A classic use-case would when DTBOs are used to describe
+ * additionnal daughter cards.
+ *
+ * @dev:   The board instance to gather the data.
+ * @index: Index of the image. Starts at 0 and gets incremented
+ * after each call to this function.
+ * @type:  The type of image. For example, "fdt" for DTBs
+ * @strp:  A pointer to string. Untouched if the function fails
+ *
+ *
+ * Return: 0 if OK, -ENOENT if no loadable is available else -ve on
+ * error.
+ */
+int board_get_fit_loadable(struct udevice *dev, int index,
+  const char *type, const char **strp);
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH PATCH v6 02/13] spl: fit: Add support for applying DT overlay

2019-10-22 Thread Jean-Jacques Hiblot
From: Michal Simek 

doc/uImage.FIT/overlay-fdt-boot.txt is describing how to create FIT
image with DT overlays in it.
Add support for this feature to SPL.

Here is the ZynqMP fragment where dtb points to full DT and dtbo is
overlay which should be applied on the top of dtb.
config {
description = "ATF with full u-boot overlay";
firmware = "atf";
loadables = "uboot";
fdt = "dtb", "dtbo";
};

The whole feature depends on OF_LIBFDT_OVERLAY which is adding +4kB code
and 0 for platforms which are not enabling this feature.

Signed-off-by: Michal Simek 
Signed-off-by: Jean-Jacques Hiblot 
Reviewed-by: Simon Glass 

---

Changes in v6: None
Changes in v5: None
Changes in v4:
- use CONFIG_IS_ENABLED() instead of #idef

Changes in v3:
- Add a new config option: SPL_LOAD_FIT_APPLY_OVERLAY. By default, it is
not selected.

Changes in v2: None

 Kconfig  |  9 +
 common/spl/spl_fit.c | 30 +++---
 2 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/Kconfig b/Kconfig
index 66b059f749..518ce7e0d6 100644
--- a/Kconfig
+++ b/Kconfig
@@ -429,6 +429,15 @@ config SPL_LOAD_FIT
  particular it can handle selecting from multiple device tree
  and passing the correct one to U-Boot.
 
+config SPL_LOAD_FIT_APPLY_OVERLAY
+   bool "Enable SPL applying DT overlays from FIT"
+   depends on SPL_LOAD_FIT
+   select OF_LIBFDT_OVERLAY
+   help
+ The device tree is loaded from the FIT image. Allow the SPL is to
+ also load device-tree overlays from the FIT image an apply them
+ over the device tree.
+
 config SPL_LOAD_FIT_FULL
bool "Enable SPL loading U-Boot as a FIT (full fitImage features)"
select SPL_FIT
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 346f9edaa5..39e406b237 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -281,7 +281,7 @@ static int spl_fit_append_fdt(struct spl_image_info 
*spl_image,
  void *fit, int images, ulong base_offset)
 {
struct spl_image_info image_info;
-   int node, ret = 0;
+   int node, ret = 0, index = 0;
 
/*
 * Use the address following the image as target address for the
@@ -290,7 +290,7 @@ static int spl_fit_append_fdt(struct spl_image_info 
*spl_image,
image_info.load_addr = spl_image->load_addr + spl_image->size;
 
/* Figure out which device tree the board wants to use */
-   node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, 0);
+   node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, index++);
if (node < 0) {
debug("%s: cannot find FDT node\n", __func__);
 
@@ -315,8 +315,32 @@ static int spl_fit_append_fdt(struct spl_image_info 
*spl_image,
 #if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
/* Try to make space, so we can inject details on the loadables */
ret = fdt_shrink_to_minimum(spl_image->fdt_addr, 8192);
+   if (ret < 0)
+   return ret;
 #endif
-
+   if (CONFIG_IS_ENABLED(LOAD_FIT_APPLY_OVERLAY)) {
+   for (; ; index++) {
+   node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP,
+ index);
+   if (node < 0) {
+   debug("%s: No additional FDT node\n", __func__);
+   return 0;
+   }
+
+   ret = spl_load_fit_image(info, sector, fit, base_offset,
+node, _info);
+   if (ret < 0)
+   return ret;
+
+   ret = fdt_overlay_apply_verbose(spl_image->fdt_addr,
+   (void 
*)image_info.load_addr);
+   if (ret)
+   return ret;
+
+   debug("%s: DT overlay %s applied\n", __func__,
+ fit_get_name(fit, node, NULL));
+   }
+   }
return ret;
 }
 
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH PATCH v6 07/13] Makefile.lib: include /__symbols__ in dtb if SPL_LOAD_FIT_APPLY_OVERLAY is enabled

2019-10-22 Thread Jean-Jacques Hiblot
In order to apply an overlay to a DTB. The DTB must have been generated
with the option '-@'.

Signed-off-by: Jean-Jacques Hiblot 
Reviewed-by: Simon Glass 
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 scripts/Makefile.lib | 4 
 1 file changed, 4 insertions(+)

diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index ef116e0e0a..6946da6aa4 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -292,6 +292,10 @@ cmd_dt_S_dtb=  
\
 $(obj)/%.dtb.S: $(obj)/%.dtb
$(call cmd,dt_S_dtb)
 
+ifeq ($(CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY),y)
+DTC_FLAGS += -@
+endif
+
 quiet_cmd_dtc = DTC $@
 # Modified for U-Boot
 # Bring in any U-Boot-specific include at the end of the file
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH PATCH v6 01/13] spl: fit: don't load the firmware twice

2019-10-22 Thread Jean-Jacques Hiblot
When u-boot.img is a FIT image generated automatically by mkimage, the
configuration node has the following structure:
conf-1 {
   description = "k3-am654-base-board";
   firmware = "firmware-1";
   loadables = "firmware-1";
   fdt = "fdt-1";
};

The firmware is referenced twice. Once by the 'firmware' property and
once by the 'loadables' property. Currently this result in the firmware
being loaded twice. This is not a big problem but has an impact on the
boot time.
Fixing it by not loading a loadable image if it is also the firmware image.

Signed-off-by: Jean-Jacques Hiblot 
Reviewed-by: Simon Glass 
Tested-by: Andreas Dannenberg 
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 common/spl/spl_fit.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index cbc00a4e7c..346f9edaa5 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -373,6 +373,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
int images, ret;
int base_offset, hsize, align_len = ARCH_DMA_MINALIGN - 1;
int index = 0;
+   int firmware_node;
 
/*
 * For FIT with external data, figure out where the external images
@@ -502,6 +503,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
spl_fit_append_fdt(spl_image, info, sector, fit,
   images, base_offset);
 
+   firmware_node = node;
/* Now check if there are more images for us to load */
for (; ; index++) {
uint8_t os_type = IH_OS_INVALID;
@@ -510,6 +512,14 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
if (node < 0)
break;
 
+   /*
+* if the firmware is also a loadable, skip it because
+* it already has been loaded. This is typically the case with
+* u-boot.img generated by mkimage.
+*/
+   if (firmware_node == node)
+   continue;
+
ret = spl_load_fit_image(info, sector, fit, base_offset, node,
 _info);
if (ret < 0)
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH PATCH v6 08/13] spl: fit: constify the output parameter of spl_fit_get_image_name()

2019-10-22 Thread Jean-Jacques Hiblot
There is no need for it to be non-constant. Making it constant, allows to
return constant string without warning.

Signed-off-by: Jean-Jacques Hiblot 
Reviewed-by: Simon Glass 
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 common/spl/spl_fit.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 5aeb9528fe..9001731303 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -46,7 +46,7 @@ __weak ulong board_spl_fit_size_align(ulong size)
  */
 static int spl_fit_get_image_name(const void *fit, int images,
  const char *type, int index,
- char **outname)
+ const char **outname)
 {
const char *name, *str;
__maybe_unused int node;
@@ -101,7 +101,7 @@ static int spl_fit_get_image_name(const void *fit, int 
images,
 static int spl_fit_get_image_node(const void *fit, int images,
  const char *type, int index)
 {
-   char *str;
+   const char *str;
int err;
int node;
 
@@ -387,7 +387,7 @@ static int spl_fit_record_loadable(const void *fit, int 
images, int index,
 {
int ret = 0;
 #if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
-   char *name;
+   const char *name;
int node;
 
ret = spl_fit_get_image_name(fit, images, "loadables",
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH PATCH v6 11/13] include: board: provide empty stubs when the BOARD option is not selected

2019-10-22 Thread Jean-Jacques Hiblot
Useful to avoid #ifdef throughout the code that uses the board driver API.

Signed-off-by: Jean-Jacques Hiblot 
Reviewed-by: Simon Glass 
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/board.h | 37 +
 1 file changed, 37 insertions(+)

diff --git a/include/board.h b/include/board.h
index fd6a486702..678b652b0a 100644
--- a/include/board.h
+++ b/include/board.h
@@ -31,6 +31,7 @@
  * to read the serial number.
  */
 
+#if CONFIG_IS_ENABLED(BOARD)
 struct board_ops {
/**
 * detect() - Run the hardware info detection procedure for this
@@ -174,3 +175,39 @@ int board_get(struct udevice **devp);
  */
 int board_get_fit_loadable(struct udevice *dev, int index,
   const char *type, const char **strp);
+
+#else
+
+static inline int board_detect(struct udevice *dev)
+{
+   return -ENOSYS;
+}
+
+static inline int board_get_bool(struct udevice *dev, int id, bool *val)
+{
+   return -ENOSYS;
+}
+
+static inline int board_get_int(struct udevice *dev, int id, int *val)
+{
+   return -ENOSYS;
+}
+
+static inline int board_get_str(struct udevice *dev, int id, size_t size,
+   char *val)
+{
+   return -ENOSYS;
+}
+
+static inline int board_get(struct udevice **devp)
+{
+   return -ENOSYS;
+}
+
+static inline int board_get_fit_loadable(struct udevice *dev, int index,
+const char *type, const char **strp)
+{
+   return -ENOSYS;
+}
+
+#endif
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH PATCH v6 03/13] spl: fit: Make room in the FDT before applying overlays

2019-10-22 Thread Jean-Jacques Hiblot
Make room in the FDT before applying the overlay, otherwise it may fail if
the overlay is big. As the exact added size is not known in advance, just
add the size of the overlay.
Move after the end of the application of the overlays, the resize  of the
FDT for the injection of the details on the loadables.

Signed-off-by: Jean-Jacques Hiblot 
Reviewed-by: Simon Glass 
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 common/spl/spl_fit.c | 17 -
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 39e406b237..65dd835ecc 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -313,11 +313,6 @@ static int spl_fit_append_fdt(struct spl_image_info 
*spl_image,
/* Make the load-address of the FDT available for the SPL framework */
spl_image->fdt_addr = (void *)image_info.load_addr;
 #if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
-   /* Try to make space, so we can inject details on the loadables */
-   ret = fdt_shrink_to_minimum(spl_image->fdt_addr, 8192);
-   if (ret < 0)
-   return ret;
-#endif
if (CONFIG_IS_ENABLED(LOAD_FIT_APPLY_OVERLAY)) {
for (; ; index++) {
node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP,
@@ -332,6 +327,12 @@ static int spl_fit_append_fdt(struct spl_image_info 
*spl_image,
if (ret < 0)
return ret;
 
+   /* Make room in FDT for changes from the overlay */
+   ret = fdt_increase_size(spl_image->fdt_addr,
+   image_info.size);
+   if (ret < 0)
+   return ret;
+
ret = fdt_overlay_apply_verbose(spl_image->fdt_addr,
(void 
*)image_info.load_addr);
if (ret)
@@ -341,6 +342,12 @@ static int spl_fit_append_fdt(struct spl_image_info 
*spl_image,
  fit_get_name(fit, node, NULL));
}
}
+   /* Try to make space, so we can inject details on the loadables */
+   ret = fdt_shrink_to_minimum(spl_image->fdt_addr, 8192);
+   if (ret < 0)
+   return ret;
+#endif
+
return ret;
 }
 
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH PATCH v6 05/13] spl: fit: Do not fail immediately if an overlay is not available

2019-10-22 Thread Jean-Jacques Hiblot
If one overlay that must be applied cannot be found in the FIT, the current
implementation stops applying the overlays. Let's make it skip only the
failing overlay instead.

Signed-off-by: Jean-Jacques Hiblot 
Reviewed-by: Simon Glass 
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 common/spl/spl_fit.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index e6935c16b7..0245dcadb4 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -324,9 +324,13 @@ static int spl_fit_append_fdt(struct spl_image_info 
*spl_image,
for (; ; index++) {
node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP,
  index);
-   if (node < 0) {
+   if (node == -E2BIG) {
debug("%s: No additional FDT node\n", __func__);
break;
+   } else if (node < 0) {
+   debug("%s: unable to find FDT node %d\n",
+ __func__, index);
+   continue;
}
 
if (!tmpbuffer) {
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH 1/3] cmd: fru: Add support for FRU commands

2019-10-22 Thread Jean-Jacques Hiblot


On 14/10/2019 15:29, Michal Simek wrote:

From: Siva Durga Prasad Paladugu 

This patch adds support for fru commands "fru capture" and "fru display".
The fru capture parses the FRU table present at an address and stores in a
structure for later use. The fru display prints the content of captured
structured in a readable format.

As of now, it supports only common header and board area of FRU. Also, it
supports only English language code and ASCII8 format.

fru_data variable is placed to data section because fru parser can be
called very early before bss is initialized. And also information needs to
be shared that's why it is exported via header.

Signed-off-by: Siva Durga Prasad Paladugu 
Signed-off-by: Michal Simek 
---

  MAINTAINERS  |   3 +
  cmd/Kconfig  |   8 ++
  cmd/Makefile |   1 +
  cmd/fru.c|  68 +
  common/Makefile  |   1 +
  common/fru_ops.c | 247 +++
  include/fru.h|  64 
  7 files changed, 392 insertions(+)
  create mode 100644 cmd/fru.c
  create mode 100644 common/fru_ops.c
  create mode 100644 include/fru.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 2ef29768555c..420ce26cd0aa 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -404,6 +404,9 @@ M:  Michal Simek 
  S:Maintained
  T:git https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze.git
  F:arch/arm/mach-versal/
+F: cmd/fru.c
+F: common/fru_ops.c
+F: include/fru.h
  N:(?  
  ARM VERSATILE EXPRESS DRIVERS

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 07060c63a7e6..68815e42641e 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1688,6 +1688,14 @@ config CMD_UUID
  The two commands are very similar except for the endianness of the
  output.
  
+config CMD_FRU

+   bool "FRU information for product"
+   help
+ This option enables FRU commands to capture and display FRU
+ information present in the device. The FRU Information is used
+ to primarily to provide "inventory" information about the boards
+ that the FRU Information Device is located on.
+
  endmenu
  
  source "cmd/ti/Kconfig"

diff --git a/cmd/Makefile b/cmd/Makefile
index ac843b4b16ad..f790217dd628 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_DATAFLASH_MMC_SELECT) += dataflash_mmc_mux.o
  obj-$(CONFIG_CMD_DATE) += date.o
  obj-$(CONFIG_CMD_DEMO) += demo.o
  obj-$(CONFIG_CMD_DM) += dm.o
+obj-$(CONFIG_CMD_FRU) += fru.o
  obj-$(CONFIG_CMD_SOUND) += sound.o
  ifdef CONFIG_POST
  obj-$(CONFIG_CMD_DIAG) += diag.o
diff --git a/cmd/fru.c b/cmd/fru.c
new file mode 100644
index ..d5e96cfe8984
--- /dev/null
+++ b/cmd/fru.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2019 Xilinx, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+static int do_fru_capture(cmd_tbl_t *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+   unsigned long addr;
+   char *endp;
+
+   if (argc < cmdtp->maxargs)
+   return CMD_RET_USAGE;
+
+   addr = simple_strtoul(argv[2], , 16);
+   if (*argv[1] == 0 || *endp != 0)
+   return -1;
+
+   return fru_capture(addr);
+}
+
+static int do_fru_display(cmd_tbl_t *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+   fru_display();
+   return CMD_RET_SUCCESS;
+}
+
+static cmd_tbl_t cmd_fru_sub[] = {
+   U_BOOT_CMD_MKENT(capture, 3, 0, do_fru_capture, "", ""),
+   U_BOOT_CMD_MKENT(display, 2, 0, do_fru_display, "", ""),
+};


Why not do the capture in "fru display" itself ? And maybe provide the 
ability to display a FRU read from an EEPROM?



+
+static int do_fru(cmd_tbl_t *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+   cmd_tbl_t *c;
+
+   if (argc < 2)
+   return CMD_RET_USAGE;
+
+   c = find_cmd_tbl(argv[1], _fru_sub[0],
+ARRAY_SIZE(cmd_fru_sub));
+   if (c)
+   return c->cmd(c, flag, argc, argv);
+
+   return CMD_RET_USAGE;
+}
+
+/***/
+#ifdef CONFIG_SYS_LONGHELP
+static char fru_help_text[] =
+   "capture  - Parse and capture FRU table present at address.\n"
+   "fru display - Displays content of FRU table that was captured using\n"
+   "  fru capture command\n"
+   ;
+#endif
+
+U_BOOT_CMD(
+   fru, 3, 1, do_fru,
+   "FRU table info",
+   fru_help_text
+)
diff --git a/common/Makefile b/common/Makefile
index 302d8beaf356..10cbe9a15ea1 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -57,6 +57,7 @@ obj-$(CONFIG_UPDATE_TFTP) += update.o
  obj-$(CONFIG_DFU_TFTP) += update.o
  obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
  obj-$(CONFIG_CMDLINE) += cli_readline.o cli_simple.o
+obj-$(CONFIG_CMD_FRU) += fru_ops.o
  
  endif # !CONFIG_SPL_BUILD
  
diff --git a/common/fru_ops.c b/common/fru_ops.c

new file mode 100644
index 

[U-Boot] [PATCH v2 0/5] clk: Add a managed API and fix clock self-assignment

2019-10-22 Thread Jean-Jacques Hiblot

This is the second of a few series, the goal of which is to facilitate
porting drivers from the linux kernel. Most of the series will be about
adding managed API to existing infrastructure (GPIO, reset, phy,...)

This particular series is about clocks. It adds a managed API, using
the same API as linux. It also fix a use-case where the clock is
initialized (rate and/or mux) when it is probed using the
assigned-clocks-* properties.


Changes in v2:
- Add clk_prepare_enable/clk_disable_unprepare
- remove conflicting implmentations from brcmnand_compat.{c,h}

Jean-Jacques Hiblot (5):
  drivers: clk: Handle gracefully NULL pointers
  drivers: clk: Add a managed API to get clocks from the device-tree
  test: clk: Update tests to also check the managed API
  drivers: clk: Fix using assigned-clocks in the node of the clock it
sets up
  test: clk: test clock self assignment

 arch/sandbox/dts/test.dts |   8 +-
 arch/sandbox/include/asm/clk.h|  33 +
 drivers/clk/clk-uclass.c  | 139 --
 drivers/clk/clk_sandbox.c |  56 +++
 drivers/clk/clk_sandbox_test.c|  66 +++--
 drivers/core/device.c |   2 +-
 .../mtd/nand/raw/brcmnand/brcmnand_compat.c   |  30 
 .../mtd/nand/raw/brcmnand/brcmnand_compat.h   |   4 -
 include/clk.h |  56 ++-
 test/dm/clk.c |  36 -
 10 files changed, 367 insertions(+), 63 deletions(-)

-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v2 4/5] drivers: clk: Fix using assigned-clocks in the node of the clock it sets up

2019-10-22 Thread Jean-Jacques Hiblot
This fixes the case where assigned-clocks is used to define a clock
defaults inside this same clock's node. This is used sometimes to setup a
default parents and/or rate for a clock.

example:
muxed_clock: muxed_clock {
clocks = <_provider 0>, <_provider 1>;
#clock-cells = <0>;
assigned-clocks = <_clock>;
assigned-clock-parents = <_provider 1>;
};

It doesn't work in u-boot because the assigned-clocks are setup *before*
the clock is probed. (clk_set_parent() will likely crash or fail if called
before the device probe function)
Making it work by handling "assigned-clocks" in 2 steps: first before the
clk device is probed, and then after the clk device is probed.

Signed-off-by: Jean-Jacques Hiblot 
---

Changes in v2: None

 drivers/clk/clk-uclass.c | 48 +++-
 drivers/core/device.c|  2 +-
 include/clk.h|  7 --
 3 files changed, 48 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index e7ec6347de..75d618a47b 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -178,7 +178,7 @@ bulk_get_err:
return ret;
 }
 
-static int clk_set_default_parents(struct udevice *dev)
+static int clk_set_default_parents(struct udevice *dev, int stage)
 {
struct clk clk, parent_clk;
int index;
@@ -214,8 +214,18 @@ static int clk_set_default_parents(struct udevice *dev)
return ret;
}
 
-   ret = clk_set_parent(, _clk);
+   /* This is clk provider device trying to reparent itself
+* It cannot be done right now but need to wait after the
+* device is probed
+*/
+   if (stage == 0 && clk.dev == dev)
+   continue;
+
+   if (stage > 0 && clk.dev != dev)
+   /* do not setup twice the parent clocks */
+   continue;
 
+   ret = clk_set_parent(, _clk);
/*
 * Not all drivers may support clock-reparenting (as of now).
 * Ignore errors due to this.
@@ -233,7 +243,7 @@ static int clk_set_default_parents(struct udevice *dev)
return 0;
 }
 
-static int clk_set_default_rates(struct udevice *dev)
+static int clk_set_default_rates(struct udevice *dev, int stage)
 {
struct clk clk;
int index;
@@ -268,7 +278,19 @@ static int clk_set_default_rates(struct udevice *dev)
continue;
}
 
+   /* This is clk provider device trying to program itself
+* It cannot be done right now but need to wait after the
+* device is probed
+*/
+   if (stage == 0 && clk.dev == dev)
+   continue;
+
+   if (stage > 0 && clk.dev != dev)
+   /* do not setup twice the parent clocks */
+   continue;
+
ret = clk_set_rate(, rates[index]);
+
if (ret < 0) {
debug("%s: failed to set rate on clock index %d (%ld) 
for %s\n",
  __func__, index, clk.id, dev_read_name(dev));
@@ -281,7 +303,7 @@ fail:
return ret;
 }
 
-int clk_set_defaults(struct udevice *dev)
+int clk_set_defaults(struct udevice *dev, int stage)
 {
int ret;
 
@@ -294,11 +316,11 @@ int clk_set_defaults(struct udevice *dev)
 
debug("%s(%s)\n", __func__, dev_read_name(dev));
 
-   ret = clk_set_default_parents(dev);
+   ret = clk_set_default_parents(dev, stage);
if (ret)
return ret;
 
-   ret = clk_set_default_rates(dev);
+   ret = clk_set_default_rates(dev, stage);
if (ret < 0)
return ret;
 
@@ -673,7 +695,21 @@ void devm_clk_put(struct udevice *dev, struct clk *clk)
WARN_ON(rc);
 }
 
+int clk_uclass_post_probe(struct udevice *dev)
+{
+   /*
+* when a clock provider is probed. Call clk_set_defaults()
+* also after the device is probed. This takes care of cases
+* where the DT is used to setup default parents and rates
+* using assigned-clocks
+*/
+   clk_set_defaults(dev, 1);
+
+   return 0;
+}
+
 UCLASS_DRIVER(clk) = {
.id = UCLASS_CLK,
.name   = "clk",
+   .post_probe = clk_uclass_post_probe,
 };
diff --git a/drivers/core/device.c b/drivers/core/device.c
index ce66c72e5e..854aa91bbf 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -417,7 +417,7 @@ int device_probe(struct udevice *dev)
 * Process 'assigned-{clocks/clock-parents/clock-rates}'
 * properties
 */
-   ret = clk_set_defaults(dev);
+   ret = clk_set_defaults(dev, 0)

[U-Boot] [PATCH v2 1/5] drivers: clk: Handle gracefully NULL pointers

2019-10-22 Thread Jean-Jacques Hiblot
Prepare the way for a managed CLK API by handling NULL pointers without
crashing nor failing.

Signed-off-by: Jean-Jacques Hiblot 
---

Changes in v2: None

 drivers/clk/clk-uclass.c | 43 +---
 include/clk.h|  2 +-
 2 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 64c181f4ad..dff395fedb 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -349,9 +349,12 @@ int clk_release_all(struct clk *clk, int count)
 
 int clk_request(struct udevice *dev, struct clk *clk)
 {
-   const struct clk_ops *ops = clk_dev_ops(dev);
+   const struct clk_ops *ops;
 
debug("%s(dev=%p, clk=%p)\n", __func__, dev, clk);
+   if (!clk)
+   return 0;
+   ops = clk_dev_ops(dev);
 
clk->dev = dev;
 
@@ -363,9 +366,12 @@ int clk_request(struct udevice *dev, struct clk *clk)
 
 int clk_free(struct clk *clk)
 {
-   const struct clk_ops *ops = clk_dev_ops(clk->dev);
+   const struct clk_ops *ops;
 
debug("%s(clk=%p)\n", __func__, clk);
+   if (!clk)
+   return 0;
+   ops = clk_dev_ops(clk->dev);
 
if (!ops->free)
return 0;
@@ -375,9 +381,12 @@ int clk_free(struct clk *clk)
 
 ulong clk_get_rate(struct clk *clk)
 {
-   const struct clk_ops *ops = clk_dev_ops(clk->dev);
+   const struct clk_ops *ops;
 
debug("%s(clk=%p)\n", __func__, clk);
+   if (!clk)
+   return 0;
+   ops = clk_dev_ops(clk->dev);
 
if (!ops->get_rate)
return -ENOSYS;
@@ -391,6 +400,8 @@ struct clk *clk_get_parent(struct clk *clk)
struct clk *pclk;
 
debug("%s(clk=%p)\n", __func__, clk);
+   if (!clk)
+   return NULL;
 
pdev = dev_get_parent(clk->dev);
pclk = dev_get_clk_ptr(pdev);
@@ -406,6 +417,8 @@ long long clk_get_parent_rate(struct clk *clk)
struct clk *pclk;
 
debug("%s(clk=%p)\n", __func__, clk);
+   if (!clk)
+   return 0;
 
pclk = clk_get_parent(clk);
if (IS_ERR(pclk))
@@ -424,9 +437,12 @@ long long clk_get_parent_rate(struct clk *clk)
 
 ulong clk_set_rate(struct clk *clk, ulong rate)
 {
-   const struct clk_ops *ops = clk_dev_ops(clk->dev);
+   const struct clk_ops *ops;
 
debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate);
+   if (!clk)
+   return 0;
+   ops = clk_dev_ops(clk->dev);
 
if (!ops->set_rate)
return -ENOSYS;
@@ -436,9 +452,12 @@ ulong clk_set_rate(struct clk *clk, ulong rate)
 
 int clk_set_parent(struct clk *clk, struct clk *parent)
 {
-   const struct clk_ops *ops = clk_dev_ops(clk->dev);
+   const struct clk_ops *ops;
 
debug("%s(clk=%p, parent=%p)\n", __func__, clk, parent);
+   if (!clk)
+   return 0;
+   ops = clk_dev_ops(clk->dev);
 
if (!ops->set_parent)
return -ENOSYS;
@@ -448,11 +467,14 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 
 int clk_enable(struct clk *clk)
 {
-   const struct clk_ops *ops = clk_dev_ops(clk->dev);
+   const struct clk_ops *ops;
struct clk *clkp = NULL;
int ret;
 
debug("%s(clk=%p)\n", __func__, clk);
+   if (!clk)
+   return 0;
+   ops = clk_dev_ops(clk->dev);
 
if (CONFIG_IS_ENABLED(CLK_CCF)) {
/* Take id 0 as a non-valid clk, such as dummy */
@@ -505,11 +527,14 @@ int clk_enable_bulk(struct clk_bulk *bulk)
 
 int clk_disable(struct clk *clk)
 {
-   const struct clk_ops *ops = clk_dev_ops(clk->dev);
+   const struct clk_ops *ops;
struct clk *clkp = NULL;
int ret;
 
debug("%s(clk=%p)\n", __func__, clk);
+   if (!clk)
+   return 0;
+   ops = clk_dev_ops(clk->dev);
 
if (CONFIG_IS_ENABLED(CLK_CCF)) {
if (clk->id && !clk_get_by_id(clk->id, )) {
@@ -589,6 +614,10 @@ bool clk_is_match(const struct clk *p, const struct clk *q)
if (p == q)
return true;
 
+   /* trivial case #2: on the clk pointer is NULL */
+   if (!p || !q)
+   return false;
+
/* same device, id and data */
if (p->dev == q->dev && p->id == q->id && p->data == q->data)
return true;
diff --git a/include/clk.h b/include/clk.h
index 18b2e3ca54..6568865d40 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -356,7 +356,7 @@ int soc_clk_dump(void);
  */
 static inline bool clk_valid(struct clk *clk)
 {
-   return !!clk->dev;
+   return clk && !!clk->dev;
 }
 
 /**
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v2 2/5] drivers: clk: Add a managed API to get clocks from the device-tree

2019-10-22 Thread Jean-Jacques Hiblot
Add devm_clk_get(), devm_clk_get_optional() to get clocks from the
device-tree. The clocks is automatically released and the data structure
freed when the device is unbound.
Also add devm_clk_put() to release the clock and free the data structure
manually.

Signed-off-by: Jean-Jacques Hiblot 

---

Changes in v2:
- Add clk_prepare_enable/clk_disable_unprepare
- remove conflicting implmentations from brcmnand_compat.{c,h}

 drivers/clk/clk-uclass.c  | 48 +++
 .../mtd/nand/raw/brcmnand/brcmnand_compat.c   | 30 
 .../mtd/nand/raw/brcmnand/brcmnand_compat.h   |  4 --
 include/clk.h | 47 ++
 4 files changed, 95 insertions(+), 34 deletions(-)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index dff395fedb..e7ec6347de 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -625,6 +625,54 @@ bool clk_is_match(const struct clk *p, const struct clk *q)
return false;
 }
 
+static void devm_clk_release(struct udevice *dev, void *res)
+{
+   clk_free(res);
+}
+
+static int devm_clk_match(struct udevice *dev, void *res, void *data)
+{
+   return res == data;
+}
+
+struct clk *devm_clk_get(struct udevice *dev, const char *id)
+{
+   int rc;
+   struct clk *clk;
+
+   clk = devres_alloc(devm_clk_release, sizeof(struct clk), __GFP_ZERO);
+   if (unlikely(!clk))
+   return ERR_PTR(-ENOMEM);
+
+   rc = clk_get_by_name(dev, id, clk);
+   if (rc)
+   return ERR_PTR(rc);
+
+   devres_add(dev, clk);
+   return clk;
+}
+
+struct clk *devm_clk_get_optional(struct udevice *dev, const char *id)
+{
+   struct clk *clk = devm_clk_get(dev, id);
+
+   if (IS_ERR(clk))
+   return NULL;
+
+   return clk;
+}
+
+void devm_clk_put(struct udevice *dev, struct clk *clk)
+{
+   int rc;
+
+   if (!clk)
+   return;
+
+   rc = devres_release(dev, devm_clk_release, devm_clk_match, clk);
+   WARN_ON(rc);
+}
+
 UCLASS_DRIVER(clk) = {
.id = UCLASS_CLK,
.name   = "clk",
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand_compat.c 
b/drivers/mtd/nand/raw/brcmnand/brcmnand_compat.c
index 96b27e6e5a..883948355c 100644
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand_compat.c
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand_compat.c
@@ -3,36 +3,6 @@
 #include 
 #include "brcmnand_compat.h"
 
-struct clk *devm_clk_get(struct udevice *dev, const char *id)
-{
-   struct clk *clk;
-   int ret;
-
-   clk = devm_kzalloc(dev, sizeof(*clk), GFP_KERNEL);
-   if (!clk) {
-   debug("%s: can't allocate clock\n", __func__);
-   return ERR_PTR(-ENOMEM);
-   }
-
-   ret = clk_get_by_name(dev, id, clk);
-   if (ret < 0) {
-   debug("%s: can't get clock (ret = %d)!\n", __func__, ret);
-   return ERR_PTR(ret);
-   }
-
-   return clk;
-}
-
-int clk_prepare_enable(struct clk *clk)
-{
-   return clk_enable(clk);
-}
-
-void clk_disable_unprepare(struct clk *clk)
-{
-   clk_disable(clk);
-}
-
 static char *devm_kvasprintf(struct udevice *dev, gfp_t gfp, const char *fmt,
 va_list ap)
 {
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand_compat.h 
b/drivers/mtd/nand/raw/brcmnand/brcmnand_compat.h
index 02cab0f828..6f9bec7085 100644
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand_compat.h
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand_compat.h
@@ -6,10 +6,6 @@
 #include 
 #include 
 
-struct clk *devm_clk_get(struct udevice *dev, const char *id);
-int clk_prepare_enable(struct clk *clk);
-void clk_disable_unprepare(struct clk *clk);
-
 char *devm_kasprintf(struct udevice *dev, gfp_t gfp, const char *fmt, ...);
 
 #endif /* __BRCMNAND_COMPAT_H */
diff --git a/include/clk.h b/include/clk.h
index 6568865d40..9be3264113 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -154,6 +154,37 @@ int clk_get_bulk(struct udevice *dev, struct clk_bulk 
*bulk);
  */
 int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk);
 
+/**
+ * devm_clk_get - lookup and obtain a managed reference to a clock producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Returns a struct clk corresponding to the clock producer, or
+ * valid IS_ERR() condition containing errno.  The implementation
+ * uses @dev and @id to determine the clock consumer, and thereby
+ * the clock producer.  (IOW, @id may be identical strings, but
+ * clk_get may return different clock producers depending on @dev.)
+ *
+ * Drivers must assume that the clock source is not enabled.
+ *
+ * devm_clk_get should not be called from within interrupt context.
+ *
+ * The clock will automatically be freed when the device is unbound
+ * from the bus.
+ */
+struct clk *devm_clk_get(struct udevice *dev, const char *id);
+
+/**
+ * devm_clk_get_optional -

[U-Boot] [PATCH v2 3/5] test: clk: Update tests to also check the managed API

2019-10-22 Thread Jean-Jacques Hiblot
Add a few more clocks the clk_sandbox clock provider and get them using
the managed API.
Make sure they are released when the device is removed.

Signed-off-by: Jean-Jacques Hiblot 
---

Changes in v2: None

 arch/sandbox/dts/test.dts  |  6 ++--
 arch/sandbox/include/asm/clk.h | 33 +
 drivers/clk/clk_sandbox.c  | 34 ++
 drivers/clk/clk_sandbox_test.c | 66 +-
 test/dm/clk.c  | 36 ++-
 5 files changed, 163 insertions(+), 12 deletions(-)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 5d9ab3724f..0ee86a74ed 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -232,8 +232,10 @@
compatible = "sandbox,clk-test";
clocks = <_fixed>,
 <_sandbox 1>,
-<_sandbox 0>;
-   clock-names = "fixed", "i2c", "spi";
+<_sandbox 0>,
+<_sandbox 3>,
+<_sandbox 2>;
+   clock-names = "fixed", "i2c", "spi", "uart2", "uart1";
};
 
ccf: clk-ccf {
diff --git a/arch/sandbox/include/asm/clk.h b/arch/sandbox/include/asm/clk.h
index 2b1c49f783..1573e4a134 100644
--- a/arch/sandbox/include/asm/clk.h
+++ b/arch/sandbox/include/asm/clk.h
@@ -19,6 +19,8 @@ struct udevice;
 enum sandbox_clk_id {
SANDBOX_CLK_ID_SPI,
SANDBOX_CLK_ID_I2C,
+   SANDBOX_CLK_ID_UART1,
+   SANDBOX_CLK_ID_UART2,
 
SANDBOX_CLK_ID_COUNT,
 };
@@ -33,10 +35,15 @@ enum sandbox_clk_test_id {
SANDBOX_CLK_TEST_ID_FIXED,
SANDBOX_CLK_TEST_ID_SPI,
SANDBOX_CLK_TEST_ID_I2C,
+   SANDBOX_CLK_TEST_ID_DEVM1,
+   SANDBOX_CLK_TEST_ID_DEVM2,
+   SANDBOX_CLK_TEST_ID_DEVM_NULL,
 
SANDBOX_CLK_TEST_ID_COUNT,
 };
 
+#define SANDBOX_CLK_TEST_NON_DEVM_COUNT SANDBOX_CLK_TEST_ID_DEVM1
+
 /**
  * sandbox_clk_query_rate - Query the current rate of a sandbox clock.
  *
@@ -53,6 +60,14 @@ ulong sandbox_clk_query_rate(struct udevice *dev, int id);
  * @return:The rate of the clock.
  */
 int sandbox_clk_query_enable(struct udevice *dev, int id);
+/**
+ * sandbox_clk_query_requested - Query the requested state of a sandbox clock.
+ *
+ * @dev:   The sandbox clock provider device.
+ * @id:The clock to query.
+ * @return:The rate of the clock.
+ */
+int sandbox_clk_query_requested(struct udevice *dev, int id);
 
 /**
  * sandbox_clk_test_get - Ask the sandbox clock test device to request its
@@ -62,6 +77,16 @@ int sandbox_clk_query_enable(struct udevice *dev, int id);
  * @return:0 if OK, or a negative error code.
  */
 int sandbox_clk_test_get(struct udevice *dev);
+
+/**
+ * sandbox_clk_test_devm_get - Ask the sandbox clock test device to request its
+ * clocks using the managed API.
+ *
+ * @dev:   The sandbox clock test (client) devivce.
+ * @return:0 if OK, or a negative error code.
+ */
+int sandbox_clk_test_devm_get(struct udevice *dev);
+
 /**
  * sandbox_clk_test_get_bulk - Ask the sandbox clock test device to request its
  * clocks with the bulk clk API.
@@ -146,5 +171,13 @@ int sandbox_clk_test_release_bulk(struct udevice *dev);
  * @return:0 if OK, or a negative error code.
  */
 int sandbox_clk_test_valid(struct udevice *dev);
+/**
+ * sandbox_clk_test_valid - Ask the sandbox clock test device to check its
+ * clocks are valid.
+ *
+ * @dev:   The sandbox clock test (client) devivce.
+ * @return:0 if OK, or a negative error code.
+ */
+struct clk *sandbox_clk_test_get_devm_clk(struct udevice *dev, int id);
 
 #endif
diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c
index 1d5cbb589a..d152fd7e5b 100644
--- a/drivers/clk/clk_sandbox.c
+++ b/drivers/clk/clk_sandbox.c
@@ -12,6 +12,7 @@
 struct sandbox_clk_priv {
ulong rate[SANDBOX_CLK_ID_COUNT];
bool enabled[SANDBOX_CLK_ID_COUNT];
+   bool requested[SANDBOX_CLK_ID_COUNT];
 };
 
 static ulong sandbox_clk_get_rate(struct clk *clk)
@@ -65,11 +66,35 @@ static int sandbox_clk_disable(struct clk *clk)
return 0;
 }
 
+static int sandbox_clk_request(struct clk *clk)
+{
+   struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
+
+   if (clk->id >= SANDBOX_CLK_ID_COUNT)
+   return -EINVAL;
+
+   priv->requested[clk->id] = true;
+   return 0;
+}
+
+static int sandbox_clk_free(struct clk *clk)
+{
+   struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
+
+   if (clk->id >= SANDBOX_CLK_ID_COUNT)
+   return -EINVAL;
+
+   priv->requested[clk->id] = false;
+   return 0;
+}
+
 static struct clk_ops sandbox_clk_ops = {
.get_rate   = sandbox_clk_get_rate,
.set_rate   = sandbox_clk_set_rate,
.enable = 

[U-Boot] [PATCH v2 5/5] test: clk: test clock self assignment

2019-10-22 Thread Jean-Jacques Hiblot
Make sure that the clock self-assignment works by having a clock of
clk-sbox be configured automatically when clk-sbox is probed.

Signed-off-by: Jean-Jacques Hiblot 

---

Changes in v2: None

 arch/sandbox/dts/test.dts |  2 ++
 drivers/clk/clk_sandbox.c | 22 ++
 test/dm/clk.c |  4 ++--
 3 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 0ee86a74ed..c118125169 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -226,6 +226,8 @@
clk_sandbox: clk-sbox {
compatible = "sandbox,clk";
#clock-cells = <1>;
+   assigned-clocks = <_sandbox 3>;
+   assigned-clock-rates = <321>;
};
 
clk-test {
diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c
index d152fd7e5b..de6b2f7c82 100644
--- a/drivers/clk/clk_sandbox.c
+++ b/drivers/clk/clk_sandbox.c
@@ -10,6 +10,7 @@
 #include 
 
 struct sandbox_clk_priv {
+   bool probed;
ulong rate[SANDBOX_CLK_ID_COUNT];
bool enabled[SANDBOX_CLK_ID_COUNT];
bool requested[SANDBOX_CLK_ID_COUNT];
@@ -19,6 +20,9 @@ static ulong sandbox_clk_get_rate(struct clk *clk)
 {
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
 
+   if (!priv->probed)
+   return -ENODEV;
+
if (clk->id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
 
@@ -30,6 +34,9 @@ static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
ulong old_rate;
 
+   if (!priv->probed)
+   return -ENODEV;
+
if (clk->id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
 
@@ -46,6 +53,9 @@ static int sandbox_clk_enable(struct clk *clk)
 {
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
 
+   if (!priv->probed)
+   return -ENODEV;
+
if (clk->id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
 
@@ -58,6 +68,9 @@ static int sandbox_clk_disable(struct clk *clk)
 {
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
 
+   if (!priv->probed)
+   return -ENODEV;
+
if (clk->id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
 
@@ -97,6 +110,14 @@ static struct clk_ops sandbox_clk_ops = {
.free   = sandbox_clk_free,
 };
 
+static int sandbox_clk_probe(struct udevice *dev)
+{
+   struct sandbox_clk_priv *priv = dev_get_priv(dev);
+
+   priv->probed = true;
+   return 0;
+}
+
 static const struct udevice_id sandbox_clk_ids[] = {
{ .compatible = "sandbox,clk" },
{ }
@@ -107,6 +128,7 @@ U_BOOT_DRIVER(clk_sandbox) = {
.id = UCLASS_CLK,
.of_match   = sandbox_clk_ids,
.ops= _clk_ops,
+   .probe  = sandbox_clk_probe,
.priv_auto_alloc_size = sizeof(struct sandbox_clk_priv),
 };
 
diff --git a/test/dm/clk.c b/test/dm/clk.c
index 3ad0ad8ca3..31335a543f 100644
--- a/test/dm/clk.c
+++ b/test/dm/clk.c
@@ -74,8 +74,8 @@ static int dm_test_clk(struct unit_test_state *uts)
 SANDBOX_CLK_TEST_ID_SPI));
ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
 SANDBOX_CLK_TEST_ID_I2C));
-   ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
-SANDBOX_CLK_TEST_ID_DEVM1));
+   ut_asserteq(321, sandbox_clk_test_get_rate(dev_test,
+  SANDBOX_CLK_TEST_ID_DEVM1));
ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
 SANDBOX_CLK_TEST_ID_DEVM2));
 
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v1 1/3] drivers: gpio: Handle gracefully NULL pointers

2019-10-22 Thread Jean-Jacques Hiblot


On 22/10/2019 00:53, Simon Glass wrote:

Hi Jean-Jacques,

On Mon, 21 Oct 2019 at 01:45, Jean-Jacques Hiblot  wrote:


On 18/10/2019 22:38, Simon Glass wrote:

Hi Jean-Jacques,

On Tue, 1 Oct 2019 at 05:51, Jean-Jacques Hiblot  wrote:

Prepare the way for a managed GPIO API by handling NULL pointers without
crashing nor failing.
VALIDATE_DESC() and validate_desc() come straight from Linux.

Signed-off-by: Jean-Jacques Hiblot 
---

   drivers/gpio/gpio-uclass.c | 66 --
   include/asm-generic/gpio.h |  2 +-
   2 files changed, 57 insertions(+), 11 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 01cfa2f788..63c10f438b 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -18,6 +18,33 @@

   DECLARE_GLOBAL_DATA_PTR;

+/*
+ * This descriptor validation needs to be inserted verbatim into each
+ * function taking a descriptor, so we need to use a preprocessor
+ * macro to avoid endless duplication. If the desc is NULL it is an
+ * optional GPIO and calls should just bail out.
+ */
+static int validate_desc(const struct gpio_desc *desc, const char *func)
+{
+   if (!desc)
+   return 0;
+   if (IS_ERR(desc)) {
+   pr_warn("%s: invalid GPIO (errorpointer)\n", func);
+   return PTR_ERR(desc);
+   }
+   if (!desc->dev) {
+   pr_warn("%s: invalid GPIO (no device)\n", func);
+   return -EINVAL;
+   }
+   return 1;
+}
+
+#define VALIDATE_DESC(desc) do { \
+   int __valid = validate_desc(desc, __func__); \
+   if (__valid <= 0) \
+   return __valid; \
+   } while (0)

This adds to code size so should be behind a CONFIG I think.

I'm not sure we really want to keep this out. Most of the added code
size, will be about the error messages. I would rather remove them (or
use a debug() or warn_non_spl()

You should probably do that anyway.

But these checks do add to code size, and we should be careful not to
have unnecessary checks in the final firmware. We can enable them
during development, but don't want the code bloated with lots of
pointless checks.


I see, but I don't agree that this is pointless. It allows for optional 
GPIO support.


Practically speaking, in u-boot, that will probably be used only by the 
users of the managed API: devm_gpiod_get_optional() and 
devm_gpiod_get_index_optional()






+
   /**
I't the implicit return that I am not keen on. Is it needed? I don't
see that sort of thing in U-Boot at present.


Well it bothered me too at first when I looked at how it was done in 
linux. But I got used to it pretty quickly :)


I'll remove this in the v2


Thanks for the review.


JJ



Regards,
Simon


___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v2] fdt: Fix alignment issue when reading 64-bits properties from fdt

2019-10-22 Thread Jean-Jacques Hiblot
The FDT specification [0] gives a requirement of aligning properties on
32-bits. Make sure that the compiler is aware of this constraint when
accessing 64-bits properties.

[0]: 
https://github.com/devicetree-org/devicetree-specification/blob/master/source/flattened-format.rst

Signed-off-by: Jean-Jacques Hiblot 
---

Here is a portion of the disassembly of ofnode_read_u64(). It show the effect
of the patch on ARM64.

with the classic fdt64_t type. GCC emits LDR (load register)
  34:   54000109b.ls54   // b.plast
  38:   f940ldr x0, [x0]
  3c:   dac00c00rev x0, x0

with the unaligned_fdt64_t type. GCC emits LDP (Load Pair of registers)
  34:   54000129b.ls58   // b.plast
  38:   2941ldp w1, w0, [x0]
  3c:   aa008020orr x0, x1, x0, lsl #32
  40:   dac00c00rev x0, x0
  

 common/fdt_support.c   | 2 +-
 drivers/core/ofnode.c  | 2 +-
 include/linux/libfdt_env.h | 1 +
 lib/fdtdec.c   | 2 +-
 4 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/common/fdt_support.c b/common/fdt_support.c
index baf7924ff6..6834399039 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -1566,7 +1566,7 @@ static int fdt_read_prop(const fdt32_t *prop, int 
prop_len, int cell_off,
 uint64_t *val, int cells)
 {
const fdt32_t *prop32 = [cell_off];
-   const fdt64_t *prop64 = (const fdt64_t *)[cell_off];
+   const unaligned_fdt64_t *prop64 = (const fdt64_t *)[cell_off];
 
if ((cell_off + cells) > prop_len)
return -FDT_ERR_NOSPACE;
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 297f0a0c7c..8f0eab2ca6 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -57,7 +57,7 @@ int ofnode_read_s32_default(ofnode node, const char 
*propname, s32 def)
 
 int ofnode_read_u64(ofnode node, const char *propname, u64 *outp)
 {
-   const fdt64_t *cell;
+   const unaligned_fdt64_t *cell;
int len;
 
assert(ofnode_valid(node));
diff --git a/include/linux/libfdt_env.h b/include/linux/libfdt_env.h
index e2bf79c7ee..e49fcd72bd 100644
--- a/include/linux/libfdt_env.h
+++ b/include/linux/libfdt_env.h
@@ -16,6 +16,7 @@
 typedef __be16 fdt16_t;
 typedef __be32 fdt32_t;
 typedef __be64 fdt64_t;
+typedef __be64 unaligned_fdt64_t __aligned(4);
 
 #define fdt32_to_cpu(x) be32_to_cpu(x)
 #define cpu_to_fdt32(x) cpu_to_be32(x)
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 17736ce665..125d9dbf26 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -242,7 +242,7 @@ int fdtdec_get_pci_bar32(struct udevice *dev, struct 
fdt_pci_addr *addr,
 uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name,
   uint64_t default_val)
 {
-   const uint64_t *cell64;
+   const unaligned_fdt64_t *cell64;
int length;
 
cell64 = fdt_getprop(blob, node, prop_name, );
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH] fdt: Fix alignment issue when reading 64-bits properties

2019-10-22 Thread Jean-Jacques Hiblot

Hi Simon,

On 22/10/2019 01:46, Simon Glass wrote:

Hi Jean-Jacques,

On Mon, 21 Oct 2019 at 06:50, Jean-Jacques Hiblot  wrote:

The FDT specification [0] gives a requirement of aligning properties on
32-bits. Make sure that the compiler is aware of this constraint when
accessing 64-bits properties.

[0]: 
https://github.com/devicetree-org/devicetree-specification/blob/master/source/flattened-format.rst

Signed-off-by: Jean-Jacques Hiblot 
---
  common/fdt_support.c  | 2 +-
  drivers/core/ofnode.c | 2 +-
  lib/fdtdec.c  | 2 +-
  3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/common/fdt_support.c b/common/fdt_support.c
index baf7924ff6..d14cf7f61a 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -1566,7 +1566,7 @@ static int fdt_read_prop(const fdt32_t *prop, int 
prop_len, int cell_off,
  uint64_t *val, int cells)
  {
 const fdt32_t *prop32 = [cell_off];
-   const fdt64_t *prop64 = (const fdt64_t *)[cell_off];
+   const fdt64_t *prop64 __aligned(4) = (const fdt64_t *)[cell_off];

Excuse my ignorance, but what does this actually mean? That the
pointer points to something that is aligned?


Well it should have made the compiler assume that the address is aligned 
on 32-bits not 64-bits. But I see now that it doesn't. As I didn't see 
the issue anymore iI thought it worked, but it just was my DTB not 
exposing the issue anymore.


Anyway I'll send a v2 with the effective changes.

Thanks.

JJ


Regards,
Simon


___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH] fdt: Fix alignment issue when reading 64-bits properties

2019-10-21 Thread Jean-Jacques Hiblot
The FDT specification [0] gives a requirement of aligning properties on
32-bits. Make sure that the compiler is aware of this constraint when
accessing 64-bits properties.

[0]: 
https://github.com/devicetree-org/devicetree-specification/blob/master/source/flattened-format.rst

Signed-off-by: Jean-Jacques Hiblot 
---
 common/fdt_support.c  | 2 +-
 drivers/core/ofnode.c | 2 +-
 lib/fdtdec.c  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/common/fdt_support.c b/common/fdt_support.c
index baf7924ff6..d14cf7f61a 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -1566,7 +1566,7 @@ static int fdt_read_prop(const fdt32_t *prop, int 
prop_len, int cell_off,
 uint64_t *val, int cells)
 {
const fdt32_t *prop32 = [cell_off];
-   const fdt64_t *prop64 = (const fdt64_t *)[cell_off];
+   const fdt64_t *prop64 __aligned(4) = (const fdt64_t *)[cell_off];
 
if ((cell_off + cells) > prop_len)
return -FDT_ERR_NOSPACE;
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 297f0a0c7c..6bd4235029 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -57,7 +57,7 @@ int ofnode_read_s32_default(ofnode node, const char 
*propname, s32 def)
 
 int ofnode_read_u64(ofnode node, const char *propname, u64 *outp)
 {
-   const fdt64_t *cell;
+   const fdt64_t *cell __aligned(4);
int len;
 
assert(ofnode_valid(node));
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 17736ce665..77a54b6433 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -242,7 +242,7 @@ int fdtdec_get_pci_bar32(struct udevice *dev, struct 
fdt_pci_addr *addr,
 uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name,
   uint64_t default_val)
 {
-   const uint64_t *cell64;
+   const uint64_t *cell64 __aligned(4);
int length;
 
cell64 = fdt_getprop(blob, node, prop_name, );
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v1 1/3] drivers: gpio: Handle gracefully NULL pointers

2019-10-21 Thread Jean-Jacques Hiblot


On 18/10/2019 22:38, Simon Glass wrote:

Hi Jean-Jacques,

On Tue, 1 Oct 2019 at 05:51, Jean-Jacques Hiblot  wrote:

Prepare the way for a managed GPIO API by handling NULL pointers without
crashing nor failing.
VALIDATE_DESC() and validate_desc() come straight from Linux.

Signed-off-by: Jean-Jacques Hiblot 
---

  drivers/gpio/gpio-uclass.c | 66 --
  include/asm-generic/gpio.h |  2 +-
  2 files changed, 57 insertions(+), 11 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 01cfa2f788..63c10f438b 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -18,6 +18,33 @@

  DECLARE_GLOBAL_DATA_PTR;

+/*
+ * This descriptor validation needs to be inserted verbatim into each
+ * function taking a descriptor, so we need to use a preprocessor
+ * macro to avoid endless duplication. If the desc is NULL it is an
+ * optional GPIO and calls should just bail out.
+ */
+static int validate_desc(const struct gpio_desc *desc, const char *func)
+{
+   if (!desc)
+   return 0;
+   if (IS_ERR(desc)) {
+   pr_warn("%s: invalid GPIO (errorpointer)\n", func);
+   return PTR_ERR(desc);
+   }
+   if (!desc->dev) {
+   pr_warn("%s: invalid GPIO (no device)\n", func);
+   return -EINVAL;
+   }
+   return 1;
+}
+
+#define VALIDATE_DESC(desc) do { \
+   int __valid = validate_desc(desc, __func__); \
+   if (__valid <= 0) \
+   return __valid; \
+   } while (0)

This adds to code size so should be behind a CONFIG I think.
I'm not sure we really want to keep this out. Most of the added code 
size, will be about the error messages. I would rather remove them (or 
use a debug() or warn_non_spl()

+
  /**
   * gpio_to_device() - Convert global GPIO number to device, number
   *
@@ -269,11 +296,14 @@ int gpio_hog_lookup_name(const char *name, struct 
gpio_desc **desc)

  int dm_gpio_request(struct gpio_desc *desc, const char *label)
  {
-   struct udevice *dev = desc->dev;
+   struct udevice *dev;
 struct gpio_dev_priv *uc_priv;
 char *str;
 int ret;

+   VALIDATE_DESC(desc);
+   dev = desc->dev;
+
 uc_priv = dev_get_uclass_priv(dev);
 if (uc_priv->name[desc->offset])
 return -EBUSY;
@@ -400,6 +430,8 @@ static int check_reserved(const struct gpio_desc *desc, 
const char *func)
  {
 struct gpio_dev_priv *uc_priv;

+   VALIDATE_DESC(desc);
+
 if (!dm_gpio_is_valid(desc))
 return -ENOENT;

@@ -468,6 +500,8 @@ int dm_gpio_get_value(const struct gpio_desc *desc)
 int value;
 int ret;

+   VALIDATE_DESC(desc);
+
 ret = check_reserved(desc, "get_value");
 if (ret)
 return ret;
@@ -481,6 +515,8 @@ int dm_gpio_set_value(const struct gpio_desc *desc, int 
value)
  {
 int ret;

+   VALIDATE_DESC(desc);
+
 ret = check_reserved(desc, "set_value");
 if (ret)
 return ret;
@@ -493,9 +529,12 @@ int dm_gpio_set_value(const struct gpio_desc *desc, int 
value)

  int dm_gpio_get_open_drain(struct gpio_desc *desc)
  {
-   struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
+   struct dm_gpio_ops *ops;
 int ret;

+   VALIDATE_DESC(desc);
+   ops = gpio_get_ops(desc->dev);
+
 ret = check_reserved(desc, "get_open_drain");
 if (ret)
 return ret;
@@ -508,9 +547,12 @@ int dm_gpio_get_open_drain(struct gpio_desc *desc)

  int dm_gpio_set_open_drain(struct gpio_desc *desc, int value)
  {
-   struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
+   struct dm_gpio_ops *ops;
 int ret;

+   VALIDATE_DESC(desc);
+   ops = gpio_get_ops(desc->dev);
+
 ret = check_reserved(desc, "set_open_drain");
 if (ret)
 return ret;
@@ -525,10 +567,14 @@ int dm_gpio_set_open_drain(struct gpio_desc *desc, int 
value)

  int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
  {
-   struct udevice *dev = desc->dev;
-   struct dm_gpio_ops *ops = gpio_get_ops(dev);
+   struct udevice *dev;
+   struct dm_gpio_ops *ops;
 int ret;

+   VALIDATE_DESC(desc);
+   dev = desc->dev;
+   ops = gpio_get_ops(dev);
+
 ret = check_reserved(desc, "set_dir");
 if (ret)
 return ret;
@@ -570,7 +616,6 @@ int dm_gpio_set_dir(struct gpio_desc *desc)
  int gpio_get_value(unsigned gpio)
  {
 int ret;
-

unrelated change?


 struct gpio_desc desc;

 ret = gpio_to_device(gpio, );
@@ -933,6 +978,8 @@ int gpio_get_list_count(struct udevice *dev, const char 
*list_name)

  int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc)
  {
+   VALIDATE_DESC(desc);
+
 /* For now, we don't do any ch

Re: [U-Boot] [PULL] u-boot-usb/master

2019-10-15 Thread Jean-Jacques Hiblot


On 15/10/2019 11:36, Jean-Jacques Hiblot wrote:

Hi Marek,

On 15/10/2019 03:01, Marek Vasut wrote:

On 10/15/19 2:59 AM, Tom Rini wrote:

On Tue, Oct 15, 2019 at 01:34:57AM +0200, Marek Vasut wrote:

The following changes since commit 
44fb0d6c9f5147a41c710032869e5e01b3c9e310:


   Merge tag 'xilinx-for-v2020.01' of
https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze (2019-10-09
16:22:03 -0400)

are available in the Git repository at:

   git://git.denx.de/u-boot-usb.git master

for you to fetch changes up to 
3cf0f7a8d485e4bf969628f5658e075084b2f013:


   usb: ehci-mx6: Fix bus enumeration for iMX7 SoCs (2019-10-12 
13:07:32

+0200)


NAK.  From: https://gitlab.denx.de/u-boot/u-boot/-/jobs/19870
sei510 rock64-rk3328 u200 odroid-n2 fail due to:
+drivers/usb/gadget/udc/built-in.o: In function 
`usb_gadget_register_driver':
+drivers/usb/gadget/udc/udc-core.c:325: multiple definition of 
`usb_gadget_register_driver'
+drivers/usb/gadget/built-in.o:drivers/usb/gadget/dwc2_udc_otg.c:238: 
first defined here
+drivers/usb/gadget/udc/built-in.o: In function 
`usb_gadget_unregister_driver':
+drivers/usb/gadget/udc/udc-core.c:334: multiple definition of 
`usb_gadget_unregister_driver'
+drivers/usb/gadget/built-in.o:drivers/usb/gadget/dwc2_udc_otg.c:287: 
first defined here

Sigh, +CC Jean.


Looks like v3 has been merged instead of the latest v4 which has the 
changes in defconfig to prevent this.


v4: https://patchwork.ozlabs.org/project/uboot/list/?series=130132

v3: https://patchwork.ozlabs.org/project/uboot/list/?series=116460=*

Changes in v4:
- removed patches already merged (DWC3 fixes)
- update more defconfigs (u200, sei510, rock64-rk332 and odroid-n2)
- Fix the test of the USB_DWC3_GADGET option. IS_ENABLED() requires the
  whole option name including the 'CONFIG_' prefix

JJ



Travis build with v4 rebased on top of u-boot-usb/master (minus the v3 
patches): https://travis-ci.org/jjhiblot/u-boot/jobs/598065745







___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PULL] u-boot-usb/master

2019-10-15 Thread Jean-Jacques Hiblot

Hi Marek,

On 15/10/2019 03:01, Marek Vasut wrote:

On 10/15/19 2:59 AM, Tom Rini wrote:

On Tue, Oct 15, 2019 at 01:34:57AM +0200, Marek Vasut wrote:


The following changes since commit 44fb0d6c9f5147a41c710032869e5e01b3c9e310:

   Merge tag 'xilinx-for-v2020.01' of
https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze (2019-10-09
16:22:03 -0400)

are available in the Git repository at:

   git://git.denx.de/u-boot-usb.git master

for you to fetch changes up to 3cf0f7a8d485e4bf969628f5658e075084b2f013:

   usb: ehci-mx6: Fix bus enumeration for iMX7 SoCs (2019-10-12 13:07:32
+0200)


NAK.  From: https://gitlab.denx.de/u-boot/u-boot/-/jobs/19870
sei510 rock64-rk3328 u200 odroid-n2 fail due to:
+drivers/usb/gadget/udc/built-in.o: In function `usb_gadget_register_driver':
+drivers/usb/gadget/udc/udc-core.c:325: multiple definition of 
`usb_gadget_register_driver'
+drivers/usb/gadget/built-in.o:drivers/usb/gadget/dwc2_udc_otg.c:238: first 
defined here
+drivers/usb/gadget/udc/built-in.o: In function `usb_gadget_unregister_driver':
+drivers/usb/gadget/udc/udc-core.c:334: multiple definition of 
`usb_gadget_unregister_driver'
+drivers/usb/gadget/built-in.o:drivers/usb/gadget/dwc2_udc_otg.c:287: first 
defined here

Sigh, +CC Jean.


Looks like v3 has been merged instead of the latest v4 which has the 
changes in defconfig to prevent this.


v4: https://patchwork.ozlabs.org/project/uboot/list/?series=130132

v3: https://patchwork.ozlabs.org/project/uboot/list/?series=116460=*

Changes in v4:
- removed patches already merged (DWC3 fixes)
- update more defconfigs (u200, sei510, rock64-rk332 and odroid-n2)
- Fix the test of the USB_DWC3_GADGET option. IS_ENABLED() requires the
  whole option name including the 'CONFIG_' prefix

JJ




___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH 0/8] usb: Add support for Cadence USB controller driver

2019-10-11 Thread Jean-Jacques Hiblot


On 01/10/2019 13:56, Vignesh Raghavendra wrote:

This series adds support for Cadence USB Host and Gadget controller
drivers. This is borrowed directly from Linux kernel v5.4-rc1.
Driver as such supports both 3.0 and 2.0 speeds. But USB 3.0 requires a
PHY driver which will be added in a separate follow series

Patch 7 adds TI wrapper driver for Cadence USB controller.

Both host and device mode has been tested on TI's J721e SoC. DFU, UMS
and fastboot gadgets have been tested.

Complete series (+ DT nodes required for J721e) can be found here:
https://github.com/r-vignesh/u-boot.git branch: usb

Regards
Vignesh

Sherry Sun (1):
   usb: udc: Introduce ->udc_set_speed() method

Vignesh Raghavendra (7):
   list: import list_first_entry_or_null()
   bitmaps: import for_each_set_bit() macro
   usb: gadget: Add match_ep() op to usb_gadget_ops
   usb: Add Cadence USB3 host and gadget driver
   usb: cdns3: gadget: Implement udc_set_speed() callback
   usb: cdns3: Add TI wrapper driver for CDNS USB3 controller
   usb: gadget: Add gadget_is_cdns3() macro

  Makefile  |1 +
  drivers/usb/Kconfig   |2 +
  drivers/usb/cdns3/Kconfig |   58 +
  drivers/usb/cdns3/Makefile|   11 +
  drivers/usb/cdns3/cdns3-ti.c  |  193 ++
  drivers/usb/cdns3/core.c  |  498 ++
  drivers/usb/cdns3/core.h  |  108 ++
  drivers/usb/cdns3/debug.h |  162 ++
  drivers/usb/cdns3/drd.c   |  301 
  drivers/usb/cdns3/drd.h   |  166 ++
  drivers/usb/cdns3/ep0.c   |  910 ++
  drivers/usb/cdns3/gadget-export.h |   28 +
  drivers/usb/cdns3/gadget.c| 2760 +
  drivers/usb/cdns3/gadget.h| 1338 ++
  drivers/usb/cdns3/host-export.h   |   28 +
  drivers/usb/cdns3/host.c  |   55 +
  drivers/usb/cdns3/trace.c |   11 +
  drivers/usb/cdns3/trace.h |   26 +
  drivers/usb/gadget/epautoconf.c   |3 +
  drivers/usb/gadget/gadget_chips.h |8 +
  drivers/usb/gadget/udc/udc-core.c |   23 +
  include/linux/bitmap.h|   61 +
  include/linux/list.h  |   14 +
  include/linux/usb/gadget.h|   25 +
  scripts/Makefile.spl  |1 +
  25 files changed, 6791 insertions(+)
  create mode 100644 drivers/usb/cdns3/Kconfig
  create mode 100644 drivers/usb/cdns3/Makefile
  create mode 100644 drivers/usb/cdns3/cdns3-ti.c
  create mode 100644 drivers/usb/cdns3/core.c
  create mode 100644 drivers/usb/cdns3/core.h
  create mode 100644 drivers/usb/cdns3/debug.h
  create mode 100644 drivers/usb/cdns3/drd.c
  create mode 100644 drivers/usb/cdns3/drd.h
  create mode 100644 drivers/usb/cdns3/ep0.c
  create mode 100644 drivers/usb/cdns3/gadget-export.h
  create mode 100644 drivers/usb/cdns3/gadget.c
  create mode 100644 drivers/usb/cdns3/gadget.h
  create mode 100644 drivers/usb/cdns3/host-export.h
  create mode 100644 drivers/usb/cdns3/host.c
  create mode 100644 drivers/usb/cdns3/trace.c
  create mode 100644 drivers/usb/cdns3/trace.h


I tested the series for Host and device operations on  with a J721e-evm.

As expected, USB3 is not yet supported on the J721e because the driver 
for the USB3 phy is not there yet.


Tested-by: Jean-Jacques Hiblot 

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [RESEND PATCH v1 1/3] ARM: dts: dra7: Add usb peripheral nodes in spl

2019-10-09 Thread Jean-Jacques Hiblot
From: Faiz Abbas 

Add usb peripheral and usb phy nodes in spl to enable SPL_DFU bootmode.

Signed-off-by: Faiz Abbas 
Signed-off-by: Jean-Jacques Hiblot 
---

 arch/arm/dts/dra7-evm-u-boot.dtsi   | 17 +
 arch/arm/dts/dra71-evm-u-boot.dtsi  | 17 +
 arch/arm/dts/dra72-evm-revc-u-boot.dtsi | 17 +
 arch/arm/dts/dra72-evm-u-boot.dtsi  | 23 +++
 arch/arm/dts/dra76-evm-u-boot.dtsi  | 17 +
 arch/arm/dts/omap5-u-boot.dtsi  |  1 +
 6 files changed, 92 insertions(+)
 create mode 100644 arch/arm/dts/dra72-evm-u-boot.dtsi

diff --git a/arch/arm/dts/dra7-evm-u-boot.dtsi 
b/arch/arm/dts/dra7-evm-u-boot.dtsi
index badaebc76f..f06c701dbd 100644
--- a/arch/arm/dts/dra7-evm-u-boot.dtsi
+++ b/arch/arm/dts/dra7-evm-u-boot.dtsi
@@ -32,3 +32,20 @@
 _iodelay_hs200_rev20_conf {
u-boot,dm-spl;
 };
+
+_dwc3_1 {
+   u-boot,dm-spl;
+};
+
+ {
+   u-boot,dm-spl;
+   dr_mode = "peripheral";
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/dra71-evm-u-boot.dtsi 
b/arch/arm/dts/dra71-evm-u-boot.dtsi
index f9da15f1c7..b56d4fc9d8 100644
--- a/arch/arm/dts/dra71-evm-u-boot.dtsi
+++ b/arch/arm/dts/dra71-evm-u-boot.dtsi
@@ -44,3 +44,20 @@
 _iodelay_hs200_rev20_conf {
u-boot,dm-spl;
 };
+
+_dwc3_1 {
+   u-boot,dm-spl;
+};
+
+ {
+   u-boot,dm-spl;
+   dr_mode = "peripheral";
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/dra72-evm-revc-u-boot.dtsi 
b/arch/arm/dts/dra72-evm-revc-u-boot.dtsi
index f9da15f1c7..b56d4fc9d8 100644
--- a/arch/arm/dts/dra72-evm-revc-u-boot.dtsi
+++ b/arch/arm/dts/dra72-evm-revc-u-boot.dtsi
@@ -44,3 +44,20 @@
 _iodelay_hs200_rev20_conf {
u-boot,dm-spl;
 };
+
+_dwc3_1 {
+   u-boot,dm-spl;
+};
+
+ {
+   u-boot,dm-spl;
+   dr_mode = "peripheral";
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/dra72-evm-u-boot.dtsi 
b/arch/arm/dts/dra72-evm-u-boot.dtsi
new file mode 100644
index 00..6c868f75d1
--- /dev/null
+++ b/arch/arm/dts/dra72-evm-u-boot.dtsi
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include "omap5-u-boot.dtsi"
+
+_dwc3_1 {
+   u-boot,dm-spl;
+};
+
+ {
+   u-boot,dm-spl;
+   dr_mode = "peripheral";
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/dra76-evm-u-boot.dtsi 
b/arch/arm/dts/dra76-evm-u-boot.dtsi
index f651f404e0..a4dfbe7e60 100644
--- a/arch/arm/dts/dra76-evm-u-boot.dtsi
+++ b/arch/arm/dts/dra76-evm-u-boot.dtsi
@@ -24,3 +24,20 @@
 _iodelay_hs200_conf {
u-boot,dm-spl;
 };
+
+_dwc3_1 {
+   u-boot,dm-spl;
+};
+
+ {
+   u-boot,dm-spl;
+   dr_mode = "peripheral";
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/omap5-u-boot.dtsi b/arch/arm/dts/omap5-u-boot.dtsi
index 1b1d765fae..39071e223d 100644
--- a/arch/arm/dts/omap5-u-boot.dtsi
+++ b/arch/arm/dts/omap5-u-boot.dtsi
@@ -22,6 +22,7 @@
 
ocp2scp@4a08 {
compatible = "ti,omap-ocp2scp", "simple-bus";
+   u-boot,dm-spl;
};
 
ocp2scp@4a09 {
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [RESEND PATCH v1 0/3] Add support for DFU boot to DRA7-based EVMs

2019-10-09 Thread Jean-Jacques Hiblot

The purpose of this series is to provide the SPL with ability to boot
u-boot from DFU.
The DRA7x can download the SPL over the USB1 port when configured in
the USB peripheral boot mode. Details on how this can be acheived with
the EVMs can found here http://www.ti.com/lit/an/sprac33/sprac33.pdf
Once the SPL is loaded, u-boot can be downloaded on the same USB1 port
through DFU.

This boot flow has been tested on DRA7-evm, DRA72-evm-rec, DRA71-evm and
DRA76-evm

changes since first sent:
- rebased on top of u-boot/master


Faiz Abbas (3):
  ARM: dts: dra7: Add usb peripheral nodes in spl
  configs: dra7xx_evm: Add Kconfigs for SPL_DFU bootmode
  configs: dra7xx_evm: Increase the size of SPL_MULTI_DTB_FIT

 arch/arm/dts/dra7-evm-u-boot.dtsi   | 17 +
 arch/arm/dts/dra71-evm-u-boot.dtsi  | 17 +
 arch/arm/dts/dra72-evm-revc-u-boot.dtsi | 17 +
 arch/arm/dts/dra72-evm-u-boot.dtsi  | 23 +++
 arch/arm/dts/dra76-evm-u-boot.dtsi  | 17 +
 arch/arm/dts/omap5-u-boot.dtsi  |  1 +
 configs/dra7xx_evm_defconfig|  8 +++-
 configs/dra7xx_hs_evm_defconfig |  8 +++-
 8 files changed, 106 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/dts/dra72-evm-u-boot.dtsi

-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [RESEND PATCH v1 3/3] configs: dra7xx_evm: Increase the size of SPL_MULTI_DTB_FIT

2019-10-09 Thread Jean-Jacques Hiblot
From: Faiz Abbas 

Expand SPL_MULTI_DTB_FIT to accommodate usb peripheral nodes being
added to support SPL_DFU bootmode.

Signed-off-by: Faiz Abbas 

Signed-off-by: Jean-Jacques Hiblot 
---

 configs/dra7xx_evm_defconfig| 2 +-
 configs/dra7xx_hs_evm_defconfig | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/configs/dra7xx_evm_defconfig b/configs/dra7xx_evm_defconfig
index a09d0733ca..88d160d0b5 100644
--- a/configs/dra7xx_evm_defconfig
+++ b/configs/dra7xx_evm_defconfig
@@ -42,7 +42,7 @@ CONFIG_SPL_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="dra7-evm"
 CONFIG_OF_LIST="dra7-evm dra72-evm dra72-evm-revc dra71-evm dra76-evm"
 CONFIG_SPL_MULTI_DTB_FIT=y
-CONFIG_SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ=0x9000
+CONFIG_SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ=0xA000
 CONFIG_OF_SPL_REMOVE_PROPS="clocks clock-names interrupt-parent"
 # CONFIG_ENV_IS_IN_FAT is not set
 CONFIG_ENV_IS_IN_MMC=y
diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig
index e2f0476f9e..ca904d8d2d 100644
--- a/configs/dra7xx_hs_evm_defconfig
+++ b/configs/dra7xx_hs_evm_defconfig
@@ -45,7 +45,7 @@ CONFIG_SPL_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="dra7-evm"
 CONFIG_OF_LIST="dra7-evm dra72-evm dra72-evm-revc dra71-evm dra76-evm"
 CONFIG_SPL_MULTI_DTB_FIT=y
-CONFIG_SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ=0x9000
+CONFIG_SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ=0xA000
 CONFIG_OF_SPL_REMOVE_PROPS="clocks clock-names interrupt-parent"
 # CONFIG_ENV_IS_IN_FAT is not set
 CONFIG_ENV_IS_IN_MMC=y
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [RESEND PATCH v1 2/3] configs: dra7xx_evm: Add Kconfigs for SPL_DFU bootmode

2019-10-09 Thread Jean-Jacques Hiblot
From: Faiz Abbas 

Enable configs for supporting SPL_DFU bootmode.

Signed-off-by: Faiz Abbas 
Signed-off-by: Jean-Jacques Hiblot 
---

 configs/dra7xx_evm_defconfig| 6 ++
 configs/dra7xx_hs_evm_defconfig | 6 ++
 2 files changed, 12 insertions(+)

diff --git a/configs/dra7xx_evm_defconfig b/configs/dra7xx_evm_defconfig
index 868030d34c..a09d0733ca 100644
--- a/configs/dra7xx_evm_defconfig
+++ b/configs/dra7xx_evm_defconfig
@@ -25,8 +25,11 @@ CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_SPL_DMA_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
+CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_SPI_LOAD=y
 CONFIG_SYS_SPI_U_BOOT_OFFS=0x4
+CONFIG_SPL_USB_GADGET=y
+CONFIG_SPL_DFU=y
 CONFIG_CMD_SPL=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_NAND=y
@@ -85,6 +88,7 @@ CONFIG_MII=y
 CONFIG_DRIVER_TI_CPSW=y
 CONFIG_SPL_PHY=y
 CONFIG_PIPE3_PHY=y
+CONFIG_SPL_PIPE3_PHY=y
 CONFIG_OMAP_USB2_PHY=y
 CONFIG_PMIC_PALMAS=y
 CONFIG_PMIC_LP873X=y
@@ -107,7 +111,9 @@ CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GADGET=y
+CONFIG_USB_DWC3_OMAP=y
 CONFIG_USB_DWC3_GENERIC=y
+CONFIG_USB_DWC3_PHY_OMAP=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
 CONFIG_USB_GADGET_VENDOR_NUM=0x0451
diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig
index 7a5c3e72d4..e2f0476f9e 100644
--- a/configs/dra7xx_hs_evm_defconfig
+++ b/configs/dra7xx_hs_evm_defconfig
@@ -30,8 +30,11 @@ CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_SPL_DMA_SUPPORT=y
 # CONFIG_SPL_NAND_SUPPORT is not set
+CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_SPI_LOAD=y
 CONFIG_SYS_SPI_U_BOOT_OFFS=0x4
+CONFIG_SPL_USB_GADGET=y
+CONFIG_SPL_DFU=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_NAND=y
 CONFIG_CMD_MTDPARTS=y
@@ -88,6 +91,7 @@ CONFIG_MII=y
 CONFIG_DRIVER_TI_CPSW=y
 CONFIG_SPL_PHY=y
 CONFIG_PIPE3_PHY=y
+CONFIG_SPL_PIPE3_PHY=y
 CONFIG_OMAP_USB2_PHY=y
 CONFIG_PMIC_PALMAS=y
 CONFIG_PMIC_LP873X=y
@@ -110,7 +114,9 @@ CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GADGET=y
+CONFIG_USB_DWC3_OMAP=y
 CONFIG_USB_DWC3_GENERIC=y
+CONFIG_USB_DWC3_PHY_OMAP=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
 CONFIG_USB_GADGET_VENDOR_NUM=0x0451
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v5 10/15] Makefile: Query the SPL Fit Generator for its dependencies

2019-10-09 Thread Jean-Jacques Hiblot


On 07/10/2019 18:02, Tom Rini wrote:

On Mon, Oct 07, 2019 at 11:43:07AM +0200, Jean-Jacques Hiblot wrote:

On 06/10/2019 19:12, Tom Rini wrote:

On Sun, Oct 06, 2019 at 04:57:29PM +, Auer, Lukas wrote:

Hi Jean-Jacques,

On Fri, 2019-09-20 at 17:28 +0200, Jean-Jacques Hiblot wrote:

To reduce the complexity of the Makefile, let the generator tell what its
dependencies are. For this purpose use the "--deps" option.


We recently added a generic FIT generator script for RISC-V, located at
arch/riscv/lib/mkimage_fit_opensbi.sh . Can you add the --deps option
to that script as well? It does not have any dependencies, so it can be
handled the same way as in the i.MX and sunxi FIT generator scripts.

Can we please work on generalizing these scripts and either using
binman, updating binman as needed or coming up with a POSIX SH tool that
can do what needs doing?  Thanks!

Maybe it can be done. But we would need to know first what the needs are.

In may case, all I need is to bundle at build time a set of DTB overlays
with u-boot.bin and some DTBs.

For this binman is overkill, using dtc is enough, though I guess binman can
be used instead.

OK, and in this case we're talking about tools/k3_fit_atf.sh which is
based on board/sunxi/mksunxi_fit_atf.sh ?  That's two similar but not
quite just mergable POSIX SH tools.  If we end up with an intermediate
state of having tools/generators/ with a number of $(soc)_fit_atf.sh
scripts that'll start to make it clearer what is/isn't the same.  Maybe
we won't have a single tool, but if it's at least make it clearer where
things belong and we can get consistency.  Thanks!


I see your point. This patch is not essential for this series, so I'll 
drop this for the time being and try to come up with a better solution 
when adding SPL overlay support for AM6/J7.


JJ





___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v5 10/15] Makefile: Query the SPL Fit Generator for its dependencies

2019-10-07 Thread Jean-Jacques Hiblot


On 06/10/2019 19:12, Tom Rini wrote:

On Sun, Oct 06, 2019 at 04:57:29PM +, Auer, Lukas wrote:

Hi Jean-Jacques,

On Fri, 2019-09-20 at 17:28 +0200, Jean-Jacques Hiblot wrote:

To reduce the complexity of the Makefile, let the generator tell what its
dependencies are. For this purpose use the "--deps" option.


We recently added a generic FIT generator script for RISC-V, located at
arch/riscv/lib/mkimage_fit_opensbi.sh . Can you add the --deps option
to that script as well? It does not have any dependencies, so it can be
handled the same way as in the i.MX and sunxi FIT generator scripts.

Can we please work on generalizing these scripts and either using
binman, updating binman as needed or coming up with a POSIX SH tool that
can do what needs doing?  Thanks!


Maybe it can be done. But we would need to know first what the needs are.

In may case, all I need is to bundle at build time a set of DTB overlays 
with u-boot.bin and some DTBs.


For this binman is overkill, using dtc is enough, though I guess binman 
can be used instead.


JJ




___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 4/4] test: Add tests for the multiplexer framework

2019-10-02 Thread Jean-Jacques Hiblot
Provide tests to check the behavior of the multiplexer framework.
The test uses a mmio-based multiplexer.

Signed-off-by: Jean-Jacques Hiblot 

---

 arch/sandbox/dts/test.dts |  26 +++
 configs/sandbox_defconfig |   2 +
 test/dm/Makefile  |   1 +
 test/dm/mux-mmio.c| 143 ++
 4 files changed, 172 insertions(+)
 create mode 100644 test/dm/mux-mmio.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 044895586a..a502dc8bd7 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1,3 +1,5 @@
+#include 
+
 /dts-v1/;
 
 / {
@@ -89,6 +91,11 @@
<_b 9 0xc 3 2 1>;
int-value = <1234>;
uint-value = <(-1234)>;
+
+   mux-controls = < 0>, < 1>,
+  < 2>, < 3>;
+   mux-control-names = "mux0", "mux1", "mux2", "mux3";
+   mux-syscon = <>;
};
 
junk {
@@ -125,6 +132,9 @@
compatible = "denx,u-boot-fdt-test";
ping-expect = <3>;
ping-add = <3>;
+
+   mux-controls = < 0>;
+   mux-control-names = "mux0";
};
 
phy_provider0: gen_phy@0 {
@@ -640,6 +650,22 @@
0x58 8>;
};
 
+   syscon3: syscon@3 {
+   compatible = "simple-mfd", "syscon";
+   reg = <0x000100 0x10>;
+
+   muxcontroller0: a-mux-controller {
+   compatible = "mmio-mux";
+   #mux-control-cells = <1>;
+
+   mux-reg-masks = <0x0 0x30>, /* 0: reg 0x0, bits 5:4 */
+   <0x3 0x1E>, /* 1: reg 0x3, bits 4:1 */
+   <0x1 0xFF>; /* 2: reg 0x1, bits 7:0 */
+   idle-states = , <0x02>, <0x73>;
+   u-boot,mux-autoprobe;
+   };
+   };
+
timer {
compatible = "sandbox,timer";
clock-frequency = <100>;
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index f77b9e8a7d..aa5d89dfc2 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -143,6 +143,8 @@ CONFIG_SPI_FLASH_SPANSION=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_SST=y
 CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_MULTIPLEXER=y
+CONFIG_MUX_MMIO=y
 CONFIG_DM_ETH=y
 CONFIG_NVME=y
 CONFIG_PCI=y
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 55a7940053..5fedcb8a7a 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_DM_SPI_FLASH) += sf.o
 obj-$(CONFIG_SMEM) += smem.o
 obj-$(CONFIG_DM_SPI) += spi.o
 obj-y += syscon.o
+obj-$(CONFIG_MUX_MMIO) += mux-mmio.o
 obj-$(CONFIG_DM_USB) += usb.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_REGULATOR) += regulator.o
diff --git a/test/dm/mux-mmio.c b/test/dm/mux-mmio.c
new file mode 100644
index 000000..8a19281614
--- /dev/null
+++ b/test/dm/mux-mmio.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Jean-Jacques Hiblot 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* Test that mmio mux work correctly */
+static int dm_test_mux_mmio(struct unit_test_state *uts)
+{
+   struct udevice *dev, *dev_b;
+   struct regmap *map;
+   struct mux_control *ctl0_a, *ctl0_b;
+   struct mux_control *ctl1;
+   struct mux_control *ctl_err;
+   u32 val;
+   int i;
+
+   ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, ));
+   ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 1, _b));
+   ut_asserteq_str("a-test", dev->name);
+   ut_asserteq_str("b-test", dev_b->name);
+   map = syscon_regmap_lookup_by_phandle(dev, "mux-syscon");
+   ut_assert(!IS_ERR(map));
+   ut_assert(map);
+
+   /* check default states */
+   ut_assertok(regmap_read(map, 3, ));
+   ut_asserteq(0x02, (val & 0x1E) >> 1);
+   ut_assertok(regmap_read(map, 1, ));
+   ut_asserteq(0x73, (val & 0xFF) >> 0);
+
+   ut_assertok(mux_control_get(dev, "mux0", _a));
+   ut_assertok(mux_control_get(dev, "mux1", ));
+   ut_asserteq(-ERANGE, mux_control_get(dev, "mux3", _err));
+   ut_asserteq(-ENODATA, mux_control_get(dev, "dummy", _err));
+   ut_assertok(mux_control_get(dev_b, "mux0", _b));
+
+   for (i = 0; i < mux_control_states(ctl0_a); i++) {
+   /* select a new state and verify the value in the regmap */
+   ut_assertok(mux_control_select(c

[U-Boot] [PATCH v1 1/4] drivers: Add a new framework for multiplexer devices

2019-10-02 Thread Jean-Jacques Hiblot
Add a new subsystem that handles multiplexer controllers. The API is the
same as in Linux.

Signed-off-by: Jean-Jacques Hiblot 
---

 drivers/Kconfig   |   2 +
 drivers/Makefile  |   1 +
 drivers/mux/Kconfig   |   7 +
 drivers/mux/Makefile  |   6 +
 drivers/mux/mux-uclass.c  | 296 ++
 include/dm/uclass-id.h|   1 +
 include/dt-bindings/mux/mux.h |  17 ++
 include/mux-internal.h|  80 +
 include/mux.h | 114 +
 9 files changed, 524 insertions(+)
 create mode 100644 drivers/mux/Kconfig
 create mode 100644 drivers/mux/Makefile
 create mode 100644 drivers/mux/mux-uclass.c
 create mode 100644 include/dt-bindings/mux/mux.h
 create mode 100644 include/mux-internal.h
 create mode 100644 include/mux.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 350acf81f3..5334974ad4 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -60,6 +60,8 @@ source "drivers/mmc/Kconfig"
 
 source "drivers/mtd/Kconfig"
 
+source "drivers/mux/Kconfig"
+
 source "drivers/net/Kconfig"
 
 source "drivers/nvme/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index a4bb5e4975..f4d71f3b3c 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_$(SPL_TPL_)INPUT) += input/
 obj-$(CONFIG_$(SPL_TPL_)LED) += led/
 obj-$(CONFIG_$(SPL_TPL_)MMC_SUPPORT) += mmc/
 obj-$(CONFIG_$(SPL_TPL_)NAND_SUPPORT) += mtd/nand/raw/
+obj-$(CONFIG_$(SPl_)MULTIPLEXER) += mux/
 obj-$(CONFIG_$(SPL_TPL_)PCH_SUPPORT) += pch/
 obj-$(CONFIG_$(SPL_TPL_)PCI) += pci/
 obj-$(CONFIG_$(SPL_TPL_)PHY) += phy/
diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
new file mode 100644
index 00..ad0199c058
--- /dev/null
+++ b/drivers/mux/Kconfig
@@ -0,0 +1,7 @@
+menu "Multiplexer drivers"
+
+config MULTIPLEXER
+   bool "Multiplexer Support"
+   depends on DM
+
+endmenu
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
new file mode 100644
index 00..351e4363d3
--- /dev/null
+++ b/drivers/mux/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2019
+# Jean-Jacques Hiblot 
+
+obj-$(CONFIG_$(SPL_)MULTIPLEXER) += mux-uclass.o
diff --git a/drivers/mux/mux-uclass.c b/drivers/mux/mux-uclass.c
new file mode 100644
index 00..58998af29c
--- /dev/null
+++ b/drivers/mux/mux-uclass.c
@@ -0,0 +1,296 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Multiplexer subsystem
+ *
+ * Based on the linux multiplexer framework
+ *
+ * Copyright (C) 2017 Axentia Technologies AB
+ * Author: Peter Rosin 
+ *
+ * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Jean-Jacques Hiblot 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * The idle-as-is "state" is not an actual state that may be selected, it
+ * only implies that the state should not be changed. So, use that state
+ * as indication that the cached state of the multiplexer is unknown.
+ */
+#define MUX_CACHE_UNKNOWN MUX_IDLE_AS_IS
+
+static inline const struct mux_control_ops *mux_dev_ops(struct udevice *dev)
+{
+   return (const struct mux_control_ops *)dev->driver->ops;
+}
+
+static int mux_control_set(struct mux_control *mux, int state)
+{
+   int ret = mux_dev_ops(mux->dev)->set(mux, state);
+
+   mux->cached_state = ret < 0 ? MUX_CACHE_UNKNOWN : state;
+
+   return ret;
+}
+
+unsigned int mux_control_states(struct mux_control *mux)
+{
+   return mux->states;
+}
+
+static int __mux_control_select(struct mux_control *mux, int state)
+{
+   int ret;
+
+   if (WARN_ON(state < 0 || state >= mux->states))
+   return -EINVAL;
+
+   if (mux->cached_state == state)
+   return 0;
+
+   ret = mux_control_set(mux, state);
+   if (ret >= 0)
+   return 0;
+
+   /* The mux update failed, try to revert if appropriate... */
+   if (mux->idle_state != MUX_IDLE_AS_IS)
+   mux_control_set(mux, mux->idle_state);
+
+   return ret;
+}
+
+int mux_control_select(struct mux_control *mux, unsigned int state)
+{
+   int ret;
+
+   if (mux->in_use)
+   return -EBUSY;
+
+   ret = __mux_control_select(mux, state);
+
+   if (ret < 0)
+   return ret;
+
+   mux->in_use = true;
+
+   return 0;
+}
+
+int mux_control_deselect(struct mux_control *mux)
+{
+   int ret = 0;
+
+   if (mux->idle_state != MUX_IDLE_AS_IS &&
+   mux->idle_state != mux->cached_state)
+   ret = mux_control_set(mux, mux->idle_state);
+
+   mux->in_use = false;
+
+   return ret;
+}
+
+static int mux_of_xlate_default(struct mux_chip *mux_chip,
+   struct ofnode_phandle_args *args,
+   struct 

[U-Boot] [PATCH v1 2/4] dm: board: complete the initialization of the muxes in initr_dm()

2019-10-02 Thread Jean-Jacques Hiblot
This will probe the multiplexer devices that have a "u-boot,mux-autoprobe"
property. As a consequence they will be put in their idle state.

Signed-off-by: Jean-Jacques Hiblot 
---

 common/board_r.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/common/board_r.c b/common/board_r.c
index d6fb5047a2..92a4e2c150 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -32,6 +32,7 @@
 #include 
 #endif
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -310,6 +311,7 @@ static int initr_dm(void)
if (ret)
return ret;
 #endif
+   dm_mux_init();
 
return 0;
 }
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 0/4] drivers: Add a framework for MUX drivers

2019-10-02 Thread Jean-Jacques Hiblot

Add a new minimalistic subsystem that handles multiplexer controllers.
It provides the same API as Linux and mux drivers should be portable with
a minimum effort.
This series also includes a port of the Linux's mmio-mux driver.

This series relies on 2 other series [1] and [2] posted earlier.

[1] : https://patchwork.ozlabs.org/project/uboot/list/?series=132923
[2] : https://patchwork.ozlabs.org/project/uboot/list/?series=133713


Jean-Jacques Hiblot (4):
  drivers: Add a new framework for multiplexer devices
  dm: board: complete the initialization of the muxes in initr_dm()
  drivers: mux: mmio-based syscon mux controller
  test: Add tests for the multiplexer framework

 arch/sandbox/dts/test.dts |  26 +++
 common/board_r.c  |   2 +
 configs/sandbox_defconfig |   2 +
 drivers/Kconfig   |   2 +
 drivers/Makefile  |   1 +
 drivers/mux/Kconfig   |  22 +++
 drivers/mux/Makefile  |   7 +
 drivers/mux/mmio.c| 155 ++
 drivers/mux/mux-uclass.c  | 296 ++
 include/dm/uclass-id.h|   1 +
 include/dt-bindings/mux/mux.h |  17 ++
 include/mux-internal.h|  80 +
 include/mux.h | 114 +
 test/dm/Makefile  |   1 +
 test/dm/mux-mmio.c| 143 
 15 files changed, 869 insertions(+)
 create mode 100644 drivers/mux/Kconfig
 create mode 100644 drivers/mux/Makefile
 create mode 100644 drivers/mux/mmio.c
 create mode 100644 drivers/mux/mux-uclass.c
 create mode 100644 include/dt-bindings/mux/mux.h
 create mode 100644 include/mux-internal.h
 create mode 100644 include/mux.h
 create mode 100644 test/dm/mux-mmio.c

-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 3/4] drivers: mux: mmio-based syscon mux controller

2019-10-02 Thread Jean-Jacques Hiblot
This adds a driver for mmio-based syscon multiplexers controlled by
bitfields in a syscon register range.
This is heavily based on the linux mmio-mux driver.

Signed-off-by: Jean-Jacques Hiblot 
---

 drivers/mux/Kconfig  |  15 +
 drivers/mux/Makefile |   1 +
 drivers/mux/mmio.c   | 155 +++
 3 files changed, 171 insertions(+)
 create mode 100644 drivers/mux/mmio.c

diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index ad0199c058..bda6a2d9f5 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -4,4 +4,19 @@ config MULTIPLEXER
bool "Multiplexer Support"
depends on DM
 
+
+if MULTIPLEXER
+
+config MUX_MMIO
+   bool "MMIO register bitfield-controlled Multiplexer"
+   depends on MULTIPLEXER && SYSCON
+   help
+ MMIO register bitfield-controlled Multiplexer controller.
+
+ The driver builds multiplexer controllers for bitfields in a syscon
+ register. For N bit wide bitfields, there will be 2^N possible
+ multiplexer states.
+
+endif
+
 endmenu
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index 351e4363d3..78ebf04c7a 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -4,3 +4,4 @@
 # Jean-Jacques Hiblot 
 
 obj-$(CONFIG_$(SPL_)MULTIPLEXER) += mux-uclass.o
+obj-$(CONFIG_$(SPL_)MUX_MMIO) += mmio.o
diff --git a/drivers/mux/mmio.c b/drivers/mux/mmio.c
new file mode 100644
index 00..a9faaeb9fd
--- /dev/null
+++ b/drivers/mux/mmio.c
@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MMIO register bitfield-controlled multiplexer driver
+ * Based on the linux mmio multiplexer driver
+ *
+ * Copyright (C) 2017 Pengutronix, Philipp Zabel 
+ * Copyright (C) 2019 Texas Instrument, Jean-jacques Hiblot 
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int mux_mmio_set(struct mux_control *mux, int state)
+{
+   struct regmap_field **fields = dev_get_priv(mux->dev);
+
+   return regmap_field_write(fields[mux_control_get_index(mux)], state);
+}
+
+static const struct mux_control_ops mux_mmio_ops = {
+   .set = mux_mmio_set,
+};
+
+static const struct udevice_id mmio_mux_of_match[] = {
+   { .compatible = "mmio-mux" },
+   { /* sentinel */ },
+};
+
+static int mmio_mux_probe(struct udevice *dev)
+{
+   struct regmap_field **fields;
+   struct mux_chip *mux_chip = dev_get_uclass_priv(dev);
+   struct regmap *regmap;
+   u32 *mux_reg_masks;
+   u32 *idle_states;
+   int num_fields;
+   int ret;
+   int i;
+
+   regmap = syscon_node_to_regmap(dev_ofnode(dev->parent));
+   if (IS_ERR(regmap)) {
+   ret = PTR_ERR(regmap);
+   dev_err(dev, "failed to get regmap: %d\n", ret);
+   return ret;
+   }
+
+   num_fields = dev_read_size(dev, "mux-reg-masks");
+   if (num_fields < 0) {
+   dev_err(dev, "mux-reg-masks property missing or invalid: %d\n",
+   num_fields);
+   return num_fields;
+   }
+   num_fields /= sizeof(u32);
+   if (num_fields == 0 || num_fields % 2)
+   ret = -EINVAL;
+   num_fields = num_fields / 2;
+
+   ret = mux_alloc_controllers(dev, num_fields);
+   if (ret < 0) {
+   dev_err(dev, "failed to allocate mux controllers: %d\n",
+   ret);
+   return ret;
+   }
+
+   fields = devm_kmalloc(dev, num_fields * sizeof(*fields), __GFP_ZERO);
+   if (!fields)
+   return -ENOMEM;
+   dev->priv = fields;
+
+   mux_reg_masks = devm_kmalloc(dev, num_fields * 2 * sizeof(u32),
+__GFP_ZERO);
+   if (!mux_reg_masks)
+   return -ENOMEM;
+
+   ret = dev_read_u32_array(dev, "mux-reg-masks", mux_reg_masks,
+num_fields * 2);
+   if (ret < 0) {
+   dev_err(dev, "failed to read mux-reg-masks property: %d\n",
+   ret);
+   return ret;
+   }
+
+   idle_states = devm_kmalloc(dev, num_fields * sizeof(u32), __GFP_ZERO);
+   if (!idle_states)
+   return -ENOMEM;
+
+   ret = dev_read_u32_array(dev, "idle-states", idle_states, num_fields);
+   if (ret < 0) {
+   dev_err(dev, "failed to read idle-states property: %d\n",
+   ret);
+   devm_kfree(dev, idle_states);
+   idle_states = NULL;
+   }
+
+   for (i = 0; i < num_fields; i++) {
+   struct mux_control *mux = _chip->mux[i];
+   struct reg_field field;
+   u32 reg, mask;
+   int bits;
+
+   reg = mux_reg_masks[2 * i];
+   mask = mux_reg_masks[2 * i + 1];
+
+   field.reg = reg;

[U-Boot] [PATCH v1 0/2] sandbox: Fixes the regmap tests

2019-10-02 Thread Jean-Jacques Hiblot
The sandbox architecture does not implement the writeX nor readX functions.
This prevents testing properly the regmaps and the other stuff relying on
it.


Jean-Jacques Hiblot (2):
  arch: sandbox: Provide working writeX/readX functions
  test: regmap: check the values read from the regmap

 arch/sandbox/include/asm/io.h | 18 +-
 test/dm/regmap.c  | 15 ---
 2 files changed, 21 insertions(+), 12 deletions(-)

-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 1/2] arch: sandbox: Provide working writeX/readX functions

2019-10-02 Thread Jean-Jacques Hiblot
Those functions are used by the regmap core. Without them regmaps are
not working on sandbox.
The implementation is taken from arch/x86/include/asm/io.h.

Signed-off-by: Jean-Jacques Hiblot 
---

 arch/sandbox/include/asm/io.h | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h
index 2a350a826c..504aac0691 100644
--- a/arch/sandbox/include/asm/io.h
+++ b/arch/sandbox/include/asm/io.h
@@ -38,18 +38,18 @@ static inline void unmap_sysmem(const void *vaddr)
 /* Map from a pointer to our RAM buffer */
 phys_addr_t map_to_sysmem(const void *ptr);
 
-/* Define nops for sandbox I/O access */
-#define readb(addr) ((void)addr, 0)
-#define readw(addr) ((void)addr, 0)
-#define readl(addr) ((void)addr, 0)
+#define readb(addr) (*(volatile u8 *)(uintptr_t)(addr))
+#define readw(addr) (*(volatile u16 *)(uintptr_t)(addr))
+#define readl(addr) (*(volatile u32 *)(uintptr_t)(addr))
 #ifdef CONFIG_SANDBOX64
-#define readq(addr) ((void)addr, 0)
+#define readq(addr) (*(volatile u64 *)(uintptr_t)(addr))
 #endif
-#define writeb(v, addr) ((void)addr)
-#define writew(v, addr) ((void)addr)
-#define writel(v, addr) ((void)addr)
+
+#define writeb(b, addr) (*(volatile u8 *)(addr) = (b))
+#define writew(b, addr) (*(volatile u16 *)(addr) = (b))
+#define writel(b, addr) (*(volatile u32 *)(addr) = (b))
 #ifdef CONFIG_SANDBOX64
-#define writeq(v, addr) ((void)addr)
+#define writeq(b, addr) (*(volatile u64 *)(addr) = (b))
 #endif
 
 /*
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 2/2] test: regmap: check the values read from the regmap

2019-10-02 Thread Jean-Jacques Hiblot
The test did reads after writes but didn't check the value.
It probably was because the sandbox didn't implement the writeX/readX
functions.

Signed-off-by: Jean-Jacques Hiblot 

---

 test/dm/regmap.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/test/dm/regmap.c b/test/dm/regmap.c
index 82de295cb8..4cde0d1866 100644
--- a/test/dm/regmap.c
+++ b/test/dm/regmap.c
@@ -104,13 +104,19 @@ static int dm_test_regmap_rw(struct unit_test_state *uts)
ut_assertok_ptr(map);
 
ut_assertok(regmap_write(map, 0, 0xcacafafa));
-   ut_assertok(regmap_write(map, 3, 0x55aa2211));
+   ut_assertok(regmap_write(map, 5, 0x55aa2211));
 
ut_assertok(regmap_read(map, 0, ));
-   ut_assertok(regmap_read(map, 3, ));
+   ut_asserteq(0xcacafafa, reg);
+   ut_assertok(regmap_read(map, 5, ));
+   ut_asserteq(0x55aa2211, reg);
 
ut_assertok(regmap_update_bits(map, 0, 0xff00ff00, 0x55aa2211));
-   ut_assertok(regmap_update_bits(map, 3, 0x00ff00ff, 0xcacafada));
+   ut_assertok(regmap_read(map, 0, ));
+   ut_asserteq(0x55ca22fa, reg);
+   ut_assertok(regmap_update_bits(map, 5, 0x00ff00ff, 0xcacafada));
+   ut_assertok(regmap_read(map, 5, ));
+   ut_asserteq(0x55ca22da, reg);
 
return 0;
 }
@@ -138,7 +144,9 @@ static int dm_test_regmap_getset(struct unit_test_state 
*uts)
regmap_set(map, struct layout, val3, 0x55aa2211);
 
ut_assertok(regmap_get(map, struct layout, val0, ));
+   ut_asserteq(0xcacafafa, reg);
ut_assertok(regmap_get(map, struct layout, val3, ));
+   ut_asserteq(0x55aa2211, reg);
 
return 0;
 }
@@ -159,6 +167,7 @@ static int dm_test_regmap_poll(struct unit_test_state *uts)
 
start = get_timer(0);
 
+   ut_assertok(regmap_write(map, 0, 0x0));
ut_asserteq(-ETIMEDOUT,
regmap_read_poll_timeout_test(map, 0, reg,
  (reg == 0xcacafafa),
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH] drivers: phy: Handle gracefully NULL pointers

2019-10-01 Thread Jean-Jacques Hiblot
For some controllers PHYs can be optional. Handling NULL pointers without
crashing nor failing, makes it easy to handle optional PHYs.

Signed-off-by: Jean-Jacques Hiblot 
---
 drivers/phy/phy-uclass.c | 30 +-
 include/generic-phy.h|  2 +-
 2 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c
index a0ac30aa71..e201a90c8c 100644
--- a/drivers/phy/phy-uclass.c
+++ b/drivers/phy/phy-uclass.c
@@ -108,35 +108,55 @@ int generic_phy_get_by_name(struct udevice *dev, const 
char *phy_name,
 
 int generic_phy_init(struct phy *phy)
 {
-   struct phy_ops const *ops = phy_dev_ops(phy->dev);
+   struct phy_ops const *ops;
+
+   if (!phy)
+   return 0;
+   ops = phy_dev_ops(phy->dev);
 
return ops->init ? ops->init(phy) : 0;
 }
 
 int generic_phy_reset(struct phy *phy)
 {
-   struct phy_ops const *ops = phy_dev_ops(phy->dev);
+   struct phy_ops const *ops;
+
+   if (!phy)
+   return 0;
+   ops = phy_dev_ops(phy->dev);
 
return ops->reset ? ops->reset(phy) : 0;
 }
 
 int generic_phy_exit(struct phy *phy)
 {
-   struct phy_ops const *ops = phy_dev_ops(phy->dev);
+   struct phy_ops const *ops;
+
+   if (!phy)
+   return 0;
+   ops = phy_dev_ops(phy->dev);
 
return ops->exit ? ops->exit(phy) : 0;
 }
 
 int generic_phy_power_on(struct phy *phy)
 {
-   struct phy_ops const *ops = phy_dev_ops(phy->dev);
+   struct phy_ops const *ops;
+
+   if (!phy)
+   return 0;
+   ops = phy_dev_ops(phy->dev);
 
return ops->power_on ? ops->power_on(phy) : 0;
 }
 
 int generic_phy_power_off(struct phy *phy)
 {
-   struct phy_ops const *ops = phy_dev_ops(phy->dev);
+   struct phy_ops const *ops;
+
+   if (!phy)
+   return 0;
+   ops = phy_dev_ops(phy->dev);
 
return ops->power_off ? ops->power_off(phy) : 0;
 }
diff --git a/include/generic-phy.h b/include/generic-phy.h
index 947c582f68..95caf58341 100644
--- a/include/generic-phy.h
+++ b/include/generic-phy.h
@@ -270,7 +270,7 @@ static inline int generic_phy_get_by_name(struct udevice 
*user, const char *phy_
  */
 static inline bool generic_phy_valid(struct phy *phy)
 {
-   return phy->dev != NULL;
+   return phy && phy->dev;
 }
 
 #endif /*__GENERIC_PHY_H */
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 3/3] test: gpio: Add tests for the managed API

2019-10-01 Thread Jean-Jacques Hiblot
Add a test to verify that GPIOs can be acquired/released using the managed
API. Also check that the GPIOs are released when the consumer device is
removed.

Signed-off-by: Jean-Jacques Hiblot 

---

 arch/sandbox/dts/test.dts |  10 
 test/dm/gpio.c| 102 ++
 2 files changed, 112 insertions(+)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 27b0baab27..f9aaef1eed 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -87,10 +87,20 @@
test2-gpios = <_a 1>, <_a 4>, <_b 6 1 3 2 1>,
<_b 7 2 3 2 1>, <_b 8 4 3 2 1>,
<_b 9 0xc 3 2 1>;
+   test3-gpios = <_a 14>, <_b 4 1 3 2 1>;
+   test4-gpios = <_a 19>;
+
int-value = <1234>;
uint-value = <(-1234)>;
};
 
+   another-test {
+   reg = <0 2>;
+   compatible = "denx,u-boot-fdt-test";
+   test3-gpios = <_a 14>, <_b 4 1 3 2 1>;
+   test4-gpios = <_a 19>;
+   };
+
junk {
reg = <1 1>;
compatible = "not,compatible";
diff --git a/test/dm/gpio.c b/test/dm/gpio.c
index bb4b20cea9..10653bcb41 100644
--- a/test/dm/gpio.c
+++ b/test/dm/gpio.c
@@ -6,6 +6,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -247,3 +248,104 @@ static int dm_test_gpio_phandles(struct unit_test_state 
*uts)
return 0;
 }
 DM_TEST(dm_test_gpio_phandles, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test that we can get/release GPIOs using managed API */
+static int dm_test_gpio_devm(struct unit_test_state *uts)
+{
+   static const u32 flags = GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE;
+   struct gpio_desc *desc1, *desc2, *desc3, *desc_err;
+   struct udevice *dev;
+   struct udevice *dev2;
+
+   ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "a-test",
+ ));
+   ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "another-test",
+ ));
+
+   /* Get 3 GPIOs from 'a-test' dev */
+   desc1 = devm_gpiod_get_index(dev, "test3", 0, flags);
+   ut_assert(!IS_ERR(desc1));
+   desc2 = devm_gpiod_get_index(dev, "test3", 1, flags);
+   ut_assert(!IS_ERR(desc2));
+   desc3 = devm_gpiod_get_index_optional(dev, "test4", 0, flags);
+   ut_assert(!IS_ERR(desc3));
+   ut_assert(desc3);
+
+   /*
+* Try get the same 3 GPIOs from 'a-test' and 'another-test' devices.
+* check that it fails
+*/
+   desc_err = devm_gpiod_get_index(dev, "test3", 0, flags);
+   ut_asserteq(-EBUSY, PTR_ERR(desc_err));
+   desc_err = devm_gpiod_get_index(dev2, "test3", 0, flags);
+   ut_asserteq(-EBUSY, PTR_ERR(desc_err));
+   desc_err = devm_gpiod_get_index(dev, "test3", 1, flags);
+   ut_asserteq(-EBUSY, PTR_ERR(desc_err));
+   desc_err = devm_gpiod_get_index(dev2, "test3", 1, flags);
+   ut_asserteq(-EBUSY, PTR_ERR(desc_err));
+   desc_err = devm_gpiod_get_index_optional(dev, "test4", 0, flags);
+   ut_asserteq_ptr(NULL, desc_err);
+   desc_err = devm_gpiod_get_index_optional(dev2, "test4", 0, flags);
+   ut_asserteq_ptr(NULL, desc_err);
+
+   /* Try get GPIOs outside of the list */
+   desc_err = devm_gpiod_get_index(dev, "test3", 2, flags);
+   ut_assert(IS_ERR(desc_err));
+   desc_err = devm_gpiod_get_index_optional(dev, "test4", 1, flags);
+   ut_asserteq_ptr(NULL, desc_err);
+
+   /* Manipulate the GPIOs */
+   ut_assertok(dm_gpio_set_value(desc1, 1));
+   ut_asserteq(1, dm_gpio_get_value(desc1));
+   ut_assertok(dm_gpio_set_value(desc1, 0));
+   ut_asserteq(0, dm_gpio_get_value(desc1));
+
+   ut_assertok(dm_gpio_set_value(desc2, 1));
+   ut_asserteq(1, dm_gpio_get_value(desc2));
+   ut_assertok(dm_gpio_set_value(desc2, 0));
+   ut_asserteq(0, dm_gpio_get_value(desc2));
+
+   ut_assertok(dm_gpio_set_value(desc3, 1));
+   ut_asserteq(1, dm_gpio_get_value(desc3));
+   ut_assertok(dm_gpio_set_value(desc3, 0));
+   ut_asserteq(0, dm_gpio_get_value(desc3));
+
+   /* Check that the GPIO cannot be owned by more than one device */
+   desc_err = devm_gpiod_get_index(dev2, "test3", 0, flags);
+   ut_asserteq(-EBUSY, PTR_ERR(desc_err));
+   desc_err = devm_gpiod_get_index(dev2, "test3", 1, flags);
+   ut_asserteq(-EBUSY, PTR_ERR(desc_err));
+   desc_err = devm_gpiod_get_index_optional(dev2, "test4", 0, flags);
+   ut_asserteq_ptr(NULL, desc_err);
+
+   /*
+* Release one GPIO and ch

[U-Boot] [PATCH v1 1/3] drivers: gpio: Handle gracefully NULL pointers

2019-10-01 Thread Jean-Jacques Hiblot
Prepare the way for a managed GPIO API by handling NULL pointers without
crashing nor failing.
VALIDATE_DESC() and validate_desc() come straight from Linux.

Signed-off-by: Jean-Jacques Hiblot 
---

 drivers/gpio/gpio-uclass.c | 66 --
 include/asm-generic/gpio.h |  2 +-
 2 files changed, 57 insertions(+), 11 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 01cfa2f788..63c10f438b 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -18,6 +18,33 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/*
+ * This descriptor validation needs to be inserted verbatim into each
+ * function taking a descriptor, so we need to use a preprocessor
+ * macro to avoid endless duplication. If the desc is NULL it is an
+ * optional GPIO and calls should just bail out.
+ */
+static int validate_desc(const struct gpio_desc *desc, const char *func)
+{
+   if (!desc)
+   return 0;
+   if (IS_ERR(desc)) {
+   pr_warn("%s: invalid GPIO (errorpointer)\n", func);
+   return PTR_ERR(desc);
+   }
+   if (!desc->dev) {
+   pr_warn("%s: invalid GPIO (no device)\n", func);
+   return -EINVAL;
+   }
+   return 1;
+}
+
+#define VALIDATE_DESC(desc) do { \
+   int __valid = validate_desc(desc, __func__); \
+   if (__valid <= 0) \
+   return __valid; \
+   } while (0)
+
 /**
  * gpio_to_device() - Convert global GPIO number to device, number
  *
@@ -269,11 +296,14 @@ int gpio_hog_lookup_name(const char *name, struct 
gpio_desc **desc)
 
 int dm_gpio_request(struct gpio_desc *desc, const char *label)
 {
-   struct udevice *dev = desc->dev;
+   struct udevice *dev;
struct gpio_dev_priv *uc_priv;
char *str;
int ret;
 
+   VALIDATE_DESC(desc);
+   dev = desc->dev;
+
uc_priv = dev_get_uclass_priv(dev);
if (uc_priv->name[desc->offset])
return -EBUSY;
@@ -400,6 +430,8 @@ static int check_reserved(const struct gpio_desc *desc, 
const char *func)
 {
struct gpio_dev_priv *uc_priv;
 
+   VALIDATE_DESC(desc);
+
if (!dm_gpio_is_valid(desc))
return -ENOENT;
 
@@ -468,6 +500,8 @@ int dm_gpio_get_value(const struct gpio_desc *desc)
int value;
int ret;
 
+   VALIDATE_DESC(desc);
+
ret = check_reserved(desc, "get_value");
if (ret)
return ret;
@@ -481,6 +515,8 @@ int dm_gpio_set_value(const struct gpio_desc *desc, int 
value)
 {
int ret;
 
+   VALIDATE_DESC(desc);
+
ret = check_reserved(desc, "set_value");
if (ret)
return ret;
@@ -493,9 +529,12 @@ int dm_gpio_set_value(const struct gpio_desc *desc, int 
value)
 
 int dm_gpio_get_open_drain(struct gpio_desc *desc)
 {
-   struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
+   struct dm_gpio_ops *ops;
int ret;
 
+   VALIDATE_DESC(desc);
+   ops = gpio_get_ops(desc->dev);
+
ret = check_reserved(desc, "get_open_drain");
if (ret)
return ret;
@@ -508,9 +547,12 @@ int dm_gpio_get_open_drain(struct gpio_desc *desc)
 
 int dm_gpio_set_open_drain(struct gpio_desc *desc, int value)
 {
-   struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
+   struct dm_gpio_ops *ops;
int ret;
 
+   VALIDATE_DESC(desc);
+   ops = gpio_get_ops(desc->dev);
+
ret = check_reserved(desc, "set_open_drain");
if (ret)
return ret;
@@ -525,10 +567,14 @@ int dm_gpio_set_open_drain(struct gpio_desc *desc, int 
value)
 
 int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
 {
-   struct udevice *dev = desc->dev;
-   struct dm_gpio_ops *ops = gpio_get_ops(dev);
+   struct udevice *dev;
+   struct dm_gpio_ops *ops;
int ret;
 
+   VALIDATE_DESC(desc);
+   dev = desc->dev;
+   ops = gpio_get_ops(dev);
+
ret = check_reserved(desc, "set_dir");
if (ret)
return ret;
@@ -570,7 +616,6 @@ int dm_gpio_set_dir(struct gpio_desc *desc)
 int gpio_get_value(unsigned gpio)
 {
int ret;
-
struct gpio_desc desc;
 
ret = gpio_to_device(gpio, );
@@ -933,6 +978,8 @@ int gpio_get_list_count(struct udevice *dev, const char 
*list_name)
 
 int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc)
 {
+   VALIDATE_DESC(desc);
+
/* For now, we don't do any checking of dev */
return _dm_gpio_free(desc->dev, desc->offset);
 }
@@ -981,12 +1028,11 @@ static int gpio_renumber(struct udevice *removed_dev)
 
 int gpio_get_number(const struct gpio_desc *desc)
 {
-   struct udevice *dev = desc->dev;
struct gpio_dev_priv *uc_priv;
 
-   if (!dev)
-   return -1;
-   uc_priv = dev->uclass_priv;
+   VALIDATE_DESC(desc);

[U-Boot] [PATCH v1 2/3] drivers: gpio: Add a managed API to get a GPIO from the device-tree

2019-10-01 Thread Jean-Jacques Hiblot
Add managed functions to get a gpio from the devce-tree, based on a
property name (minus the '-gpios' suffix) and optionally an index.

When the device is unbound, the GPIO is automatically released and the
data structure is freed.

Signed-off-by: Jean-Jacques Hiblot 
---

 drivers/gpio/gpio-uclass.c | 68 ++
 include/asm-generic/gpio.h | 47 ++
 2 files changed, 115 insertions(+)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 63c10f438b..6563809306 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -1077,6 +1077,74 @@ int gpio_dev_request_index(struct udevice *dev, const 
char *nodename,
 flags, 0, dev);
 }
 
+static void devm_gpiod_release(struct udevice *dev, void *res)
+{
+   dm_gpio_free(dev, res);
+}
+
+static int devm_gpiod_match(struct udevice *dev, void *res, void *data)
+{
+   return res == data;
+}
+
+struct gpio_desc *devm_gpiod_get_index(struct udevice *dev, const char *id,
+  unsigned int index, int flags)
+{
+   int rc;
+   struct gpio_desc *desc;
+   char *propname;
+   static const char suffix[] = "-gpios";
+
+   propname = malloc(strlen(id) + sizeof(suffix));
+   if (!propname) {
+   rc = -ENOMEM;
+   goto end;
+   }
+
+   strcpy(propname, id);
+   strcat(propname, suffix);
+
+   desc = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc),
+   __GFP_ZERO);
+   if (unlikely(!desc)) {
+   rc = -ENOMEM;
+   goto end;
+   }
+
+   rc = gpio_request_by_name(dev, propname, index, desc, flags);
+
+end:
+   if (propname)
+   free(propname);
+
+   if (rc)
+   return ERR_PTR(rc);
+
+   devres_add(dev, desc);
+   return desc;
+}
+
+struct gpio_desc *devm_gpiod_get_index_optional(struct udevice *dev,
+   const char *id,
+   unsigned int index,
+   int flags)
+{
+   struct gpio_desc *desc = devm_gpiod_get_index(dev, id, index, flags);
+
+   if (IS_ERR(desc))
+   return NULL;
+
+   return desc;
+}
+
+void devm_gpiod_put(struct udevice *dev, struct gpio_desc *desc)
+{
+   int rc;
+
+   rc = devres_release(dev, devm_gpiod_release, devm_gpiod_match, desc);
+   WARN_ON(rc);
+}
+
 static int gpio_post_bind(struct udevice *dev)
 {
struct udevice *child;
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index ba669b65a9..af0122f304 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -657,4 +657,51 @@ int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong 
flags);
  */
 int gpio_get_number(const struct gpio_desc *desc);
 
+/**
+ * devm_gpiod_get_index - Resource-managed gpiod_get()
+ * @dev:   GPIO consumer
+ * @con_id:function within the GPIO consumer
+ * @index: index of the GPIO to obtain in the consumer
+ * @flags: optional GPIO initialization flags
+ *
+ * Managed gpiod_get(). GPIO descriptors returned from this function are
+ * automatically disposed on driver detach.
+ * Return the GPIO descriptor corresponding to the function con_id of device
+ * dev, -ENOENT if no GPIO has been assigned to the requested function, or
+ * another IS_ERR() code if an error occurred while trying to acquire the GPIO.
+ */
+struct gpio_desc *devm_gpiod_get_index(struct udevice *dev, const char *id,
+  unsigned int index, int flags);
+
+#define devm_gpiod_get(dev, id, flags) devm_gpiod_get_index(dev, id, 0, flags)
+/**
+ * gpiod_get_optional - obtain an optional GPIO for a given GPIO function
+ * @dev: GPIO consumer, can be NULL for system-global GPIOs
+ * @con_id: function within the GPIO consumer
+ * @index: index of the GPIO to obtain in the consumer
+ * @flags: optional GPIO initialization flags
+ *
+ * This is equivalent to devm_gpiod_get(), except that when no GPIO was
+ * assigned to the requested function it will return NULL. This is convenient
+ * for drivers that need to handle optional GPIOs.
+ */
+struct gpio_desc *devm_gpiod_get_index_optional(struct udevice *dev,
+   const char *id,
+   unsigned int index,
+   int flags);
+
+#define devm_gpiod_get_optional(dev, id, flags) \
+   devm_gpiod_get_index_optional(dev, id, 0, flags)
+
+/**
+ * devm_gpiod_put - Resource-managed gpiod_put()
+ * @dev:   GPIO consumer
+ * @desc:  GPIO descriptor to dispose of
+ *
+ * Dispose of a GPIO descriptor obtained with devm_gpiod_get() or
+ * devm_gpiod_get_index(). Normally this function will not be called as the 
GPIO
+ * will be disposed of by the resource 

[U-Boot] [PATCH v1 0/3] gpio: Add a managed API

2019-10-01 Thread Jean-Jacques Hiblot

This is the 4th of a few series, the goal of which is to facilitate
porting drivers from the linux kernel. Most of the series will be about
adding managed API to existing infrastructure (GPIO, reset, phy,...)

This particular series is about GPIOs. It adds a managed API using the
API as Linux. To make it 100% compatible with linux, there is a small
deviation from u-boot's way of naming the gpio lists: the managed
equivalent of gpio_request_by_name(..,"blabla-gpios", ...) is
devm_gpiod_get_index(..., "blabla", ...)


Jean-Jacques Hiblot (3):
  drivers: gpio: Handle gracefully NULL pointers
  drivers: gpio: Add a managed API to get a GPIO from the device-tree
  test: gpio: Add tests for the managed API

 arch/sandbox/dts/test.dts  |  10 +++
 drivers/gpio/gpio-uclass.c | 134 ++---
 include/asm-generic/gpio.h |  49 +-
 test/dm/gpio.c | 102 
 4 files changed, 284 insertions(+), 11 deletions(-)

-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 3/3] test: reset: Add tests for the managed API

2019-09-30 Thread Jean-Jacques Hiblot
The tests are basically the same as for the regular API. Except that
the reset are initialized using the managed API, and no freed manually.

Signed-off-by: Jean-Jacques Hiblot 

---

 arch/sandbox/include/asm/reset.h   |  1 +
 drivers/reset/sandbox-reset-test.c | 50 ++---
 drivers/reset/sandbox-reset.c  | 19 ++
 test/dm/reset.c| 59 ++
 4 files changed, 123 insertions(+), 6 deletions(-)

diff --git a/arch/sandbox/include/asm/reset.h b/arch/sandbox/include/asm/reset.h
index c4205eabef..a0065b96ad 100644
--- a/arch/sandbox/include/asm/reset.h
+++ b/arch/sandbox/include/asm/reset.h
@@ -11,6 +11,7 @@
 struct udevice;
 
 int sandbox_reset_query(struct udevice *dev, unsigned long id);
+int sandbox_reset_is_requested(struct udevice *dev, unsigned long id);
 
 int sandbox_reset_test_get(struct udevice *dev);
 int sandbox_reset_test_get_bulk(struct udevice *dev);
diff --git a/drivers/reset/sandbox-reset-test.c 
b/drivers/reset/sandbox-reset-test.c
index 95ce2ca117..e6e976ea11 100644
--- a/drivers/reset/sandbox-reset-test.c
+++ b/drivers/reset/sandbox-reset-test.c
@@ -12,62 +12,100 @@
 struct sandbox_reset_test {
struct reset_ctl ctl;
struct reset_ctl_bulk bulk;
+
+   struct reset_ctl *ctlp;
+   struct reset_ctl_bulk *bulkp;
 };
 
 int sandbox_reset_test_get(struct udevice *dev)
 {
struct sandbox_reset_test *sbrt = dev_get_priv(dev);
 
+   sbrt->ctlp = >ctl;
return reset_get_by_name(dev, "test", >ctl);
 }
 
+int sandbox_reset_test_get_devm(struct udevice *dev)
+{
+   struct sandbox_reset_test *sbrt = dev_get_priv(dev);
+   struct reset_ctl *r;
+
+   r = devm_reset_control_get(dev, "not-a-valid-reset-ctl");
+   if (!IS_ERR(r))
+   return -EINVAL;
+
+   r = devm_reset_control_get_optional(dev, "not-a-valid-reset-ctl");
+   if (r)
+   return -EINVAL;
+
+   sbrt->ctlp = devm_reset_control_get(dev, "test");
+   if (IS_ERR(sbrt->ctlp))
+   return PTR_ERR(sbrt->ctlp);
+
+   return 0;
+}
+
 int sandbox_reset_test_get_bulk(struct udevice *dev)
 {
struct sandbox_reset_test *sbrt = dev_get_priv(dev);
 
+   sbrt->bulkp = >bulk;
return reset_get_bulk(dev, >bulk);
 }
 
+int sandbox_reset_test_get_bulk_devm(struct udevice *dev)
+{
+   struct sandbox_reset_test *sbrt = dev_get_priv(dev);
+   struct reset_ctl_bulk *r;
+
+   r = devm_reset_bulk_get_optional(dev);
+   if (IS_ERR(r))
+   return PTR_ERR(r);
+
+   sbrt->bulkp = r;
+   return 0;
+}
+
 int sandbox_reset_test_assert(struct udevice *dev)
 {
struct sandbox_reset_test *sbrt = dev_get_priv(dev);
 
-   return reset_assert(>ctl);
+   return reset_assert(sbrt->ctlp);
 }
 
 int sandbox_reset_test_assert_bulk(struct udevice *dev)
 {
struct sandbox_reset_test *sbrt = dev_get_priv(dev);
 
-   return reset_assert_bulk(>bulk);
+   return reset_assert_bulk(sbrt->bulkp);
 }
 
 int sandbox_reset_test_deassert(struct udevice *dev)
 {
struct sandbox_reset_test *sbrt = dev_get_priv(dev);
 
-   return reset_deassert(>ctl);
+   return reset_deassert(sbrt->ctlp);
 }
 
 int sandbox_reset_test_deassert_bulk(struct udevice *dev)
 {
struct sandbox_reset_test *sbrt = dev_get_priv(dev);
 
-   return reset_deassert_bulk(>bulk);
+   return reset_deassert_bulk(sbrt->bulkp);
 }
 
 int sandbox_reset_test_free(struct udevice *dev)
 {
struct sandbox_reset_test *sbrt = dev_get_priv(dev);
 
-   return reset_free(>ctl);
+   return reset_free(sbrt->ctlp);
 }
 
 int sandbox_reset_test_release_bulk(struct udevice *dev)
 {
struct sandbox_reset_test *sbrt = dev_get_priv(dev);
 
-   return reset_release_bulk(>bulk);
+   return reset_release_bulk(sbrt->bulkp);
 }
 
 static const struct udevice_id sandbox_reset_test_ids[] = {
diff --git a/drivers/reset/sandbox-reset.c b/drivers/reset/sandbox-reset.c
index 40f2654d8e..2b5ae88187 100644
--- a/drivers/reset/sandbox-reset.c
+++ b/drivers/reset/sandbox-reset.c
@@ -13,6 +13,7 @@
 
 struct sandbox_reset_signal {
bool asserted;
+   bool requested;
 };
 
 struct sandbox_reset {
@@ -21,18 +22,24 @@ struct sandbox_reset {
 
 static int sandbox_reset_request(struct reset_ctl *reset_ctl)
 {
+   struct sandbox_reset *sbr = dev_get_priv(reset_ctl->dev);
+
debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 
if (reset_ctl->id >= SANDBOX_RESET_SIGNALS)
return -EINVAL;
 
+   sbr->signals[reset_ctl->id].requested = true;
return 0;
 }
 
 static int sandbox_reset_free(struct reset_ctl *reset_ctl)
 {
+   struct sandbox_reset *sbr = dev_get_priv(reset_ctl->dev);
+
debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 
+   sbr->s

[U-Boot] [PATCH v1 1/3] drivers: reset: Handle gracefully NULL pointers

2019-09-30 Thread Jean-Jacques Hiblot
Prepare the way for a managed reset API by handling NULL pointers without
crashing nor failing.

Signed-off-by: Jean-Jacques Hiblot 
---

 drivers/reset/reset-uclass.c | 30 +-
 1 file changed, 17 insertions(+), 13 deletions(-)

diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c
index ee1a423ffb..1cfcc8b367 100644
--- a/drivers/reset/reset-uclass.c
+++ b/drivers/reset/reset-uclass.c
@@ -9,9 +9,12 @@
 #include 
 #include 
 
-static inline struct reset_ops *reset_dev_ops(struct udevice *dev)
+struct reset_ops nop_reset_ops = {
+};
+
+static inline struct reset_ops *reset_dev_ops(struct reset_ctl *r)
 {
-   return (struct reset_ops *)dev->driver->ops;
+   return r ? (struct reset_ops *)r->dev->driver->ops : _reset_ops;
 }
 
 static int reset_of_xlate_default(struct reset_ctl *reset_ctl,
@@ -50,9 +53,10 @@ static int reset_get_by_index_tail(int ret, ofnode node,
debug("%s %d\n", ofnode_get_name(args->node), args->args[0]);
return ret;
}
-   ops = reset_dev_ops(dev_reset);
 
reset_ctl->dev = dev_reset;
+   ops = reset_dev_ops(reset_ctl);
+
if (ops->of_xlate)
ret = ops->of_xlate(reset_ctl, args);
else
@@ -151,29 +155,29 @@ int reset_get_by_name(struct udevice *dev, const char 
*name,
 
 int reset_request(struct reset_ctl *reset_ctl)
 {
-   struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
+   struct reset_ops *ops = reset_dev_ops(reset_ctl);
 
debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 
-   return ops->request(reset_ctl);
+   return ops->request ? ops->request(reset_ctl) : 0;
 }
 
 int reset_free(struct reset_ctl *reset_ctl)
 {
-   struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
+   struct reset_ops *ops = reset_dev_ops(reset_ctl);
 
debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 
-   return ops->free(reset_ctl);
+   return ops->free ? ops->free(reset_ctl) : 0;
 }
 
 int reset_assert(struct reset_ctl *reset_ctl)
 {
-   struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
+   struct reset_ops *ops = reset_dev_ops(reset_ctl);
 
debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 
-   return ops->rst_assert(reset_ctl);
+   return ops->rst_assert ? ops->rst_assert(reset_ctl) : 0;
 }
 
 int reset_assert_bulk(struct reset_ctl_bulk *bulk)
@@ -191,11 +195,11 @@ int reset_assert_bulk(struct reset_ctl_bulk *bulk)
 
 int reset_deassert(struct reset_ctl *reset_ctl)
 {
-   struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
+   struct reset_ops *ops = reset_dev_ops(reset_ctl);
 
debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 
-   return ops->rst_deassert(reset_ctl);
+   return ops->rst_deassert ? ops->rst_deassert(reset_ctl) : 0;
 }
 
 int reset_deassert_bulk(struct reset_ctl_bulk *bulk)
@@ -213,11 +217,11 @@ int reset_deassert_bulk(struct reset_ctl_bulk *bulk)
 
 int reset_status(struct reset_ctl *reset_ctl)
 {
-   struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
+   struct reset_ops *ops = reset_dev_ops(reset_ctl);
 
debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 
-   return ops->rst_status(reset_ctl);
+   return ops->rst_status ? ops->rst_status(reset_ctl) : 0;
 }
 
 int reset_release_all(struct reset_ctl *reset_ctl, int count)
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 2/3] drivers: reset: Add a managed API to get reset controllers from the DT

2019-09-30 Thread Jean-Jacques Hiblot
Add managed functions to get a reset_ctl from the device-tree, based on a
name or an index.
Also add a managed functions to get a reset_ctl_bulk (array of reset_ctl)
from the device-tree.

When the device is unbound, the reset controllers are automatically
released and the data structure is freed.

Signed-off-by: Jean-Jacques Hiblot 
---

 drivers/reset/reset-uclass.c | 116 +-
 include/reset.h  | 135 ++-
 2 files changed, 247 insertions(+), 4 deletions(-)

diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c
index 1cfcc8b367..ae8395a5e9 100644
--- a/drivers/reset/reset-uclass.c
+++ b/drivers/reset/reset-uclass.c
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct reset_ops nop_reset_ops = {
 };
@@ -101,13 +102,14 @@ int reset_get_by_index_nodev(ofnode node, int index,
   index > 0, reset_ctl);
 }
 
-int reset_get_bulk(struct udevice *dev, struct reset_ctl_bulk *bulk)
+static int __reset_get_bulk(struct udevice *dev, ofnode node,
+   struct reset_ctl_bulk *bulk)
 {
int i, ret, err, count;

bulk->count = 0;
 
-   count = dev_count_phandle_with_args(dev, "resets", "#reset-cells");
+   count = ofnode_count_phandle_with_args(node, "resets", "#reset-cells");
if (count < 1)
return count;
 
@@ -117,7 +119,7 @@ int reset_get_bulk(struct udevice *dev, struct 
reset_ctl_bulk *bulk)
return -ENOMEM;
 
for (i = 0; i < count; i++) {
-   ret = reset_get_by_index(dev, i, >resets[i]);
+   ret = reset_get_by_index_nodev(node, i, >resets[i]);
if (ret < 0)
goto bulk_get_err;
 
@@ -135,6 +137,11 @@ bulk_get_err:
return ret;
 }
 
+int reset_get_bulk(struct udevice *dev, struct reset_ctl_bulk *bulk)
+{
+   return __reset_get_bulk(dev, dev_ofnode(dev), bulk);
+}
+
 int reset_get_by_name(struct udevice *dev, const char *name,
 struct reset_ctl *reset_ctl)
 {
@@ -247,6 +254,109 @@ int reset_release_all(struct reset_ctl *reset_ctl, int 
count)
return 0;
 }
 
+static void devm_reset_release(struct udevice *dev, void *res)
+{
+   reset_free(res);
+}
+
+struct reset_ctl *devm_reset_control_get_by_index(struct udevice *dev,
+ int index)
+{
+   int rc;
+   struct reset_ctl *reset_ctl;
+
+   reset_ctl = devres_alloc(devm_reset_release, sizeof(struct reset_ctl),
+__GFP_ZERO);
+   if (unlikely(!reset_ctl))
+   return ERR_PTR(-ENOMEM);
+
+   rc = reset_get_by_index(dev, index, reset_ctl);
+   if (rc)
+   return ERR_PTR(rc);
+
+   devres_add(dev, reset_ctl);
+   return reset_ctl;
+}
+
+struct reset_ctl *devm_reset_control_get(struct udevice *dev, const char *id)
+{
+   int rc;
+   struct reset_ctl *reset_ctl;
+
+   reset_ctl = devres_alloc(devm_reset_release, sizeof(struct reset_ctl),
+__GFP_ZERO);
+   if (unlikely(!reset_ctl))
+   return ERR_PTR(-ENOMEM);
+
+   rc = reset_get_by_name(dev, id, reset_ctl);
+   if (rc)
+   return ERR_PTR(rc);
+
+   devres_add(dev, reset_ctl);
+   return reset_ctl;
+}
+
+struct reset_ctl *devm_reset_control_get_optional(struct udevice *dev,
+ const char *id)
+{
+   struct reset_ctl *r = devm_reset_control_get(dev, id);
+
+   if (IS_ERR(r))
+   return NULL;
+
+   return r;
+}
+
+static void devm_reset_bulk_release(struct udevice *dev, void *res)
+{
+   struct reset_ctl_bulk *bulk = res;
+
+   reset_release_all(bulk->resets, bulk->count);
+}
+
+struct reset_ctl_bulk *devm_reset_bulk_get_by_node(struct udevice *dev,
+  ofnode node)
+{
+   int rc;
+   struct reset_ctl_bulk *bulk;
+
+   bulk = devres_alloc(devm_reset_bulk_release,
+   sizeof(struct reset_ctl_bulk),
+   __GFP_ZERO);
+   if (unlikely(!bulk))
+   return ERR_PTR(-ENOMEM);
+
+   rc = __reset_get_bulk(dev, node, bulk);
+   if (rc)
+   return ERR_PTR(rc);
+
+   devres_add(dev, bulk);
+   return bulk;
+}
+
+struct reset_ctl_bulk *devm_reset_bulk_get_optional_by_node(struct udevice 
*dev,
+   ofnode node)
+{
+   struct reset_ctl_bulk *bulk;
+
+   bulk = devm_reset_bulk_get_by_node(dev, node);
+
+   if (IS_ERR(bulk))
+   return NULL;
+
+   return bulk;
+}
+
+struct reset_ctl_bulk *devm_reset_bulk_get(struct udevice *dev)
+{
+   return devm_reset_bulk_get_by_node(dev, dev_ofnode(dev));
+}
+
+stru

[U-Boot] [PATCH v1 0/3] reset: Add a managed API

2019-09-30 Thread Jean-Jacques Hiblot

This is the 3rd of a few series, the goal of which is to facilitate
porting drivers from the linux kernel. Most of the series will be about
adding managed API to existing infrastructure (GPIO, reset, phy,...)

This particular series is about reset controllers. It adds a managed API,
close to that of linux. The main difference is that bulk and reset_ctl
are handled with different functions.


Jean-Jacques Hiblot (3):
  drivers: reset: Handle gracefully NULL pointers
  drivers: reset: Add a managed API to get reset controllers from the DT
  test: reset: Add tests for the managed API

 arch/sandbox/include/asm/reset.h   |   1 +
 drivers/reset/reset-uclass.c   | 146 +
 drivers/reset/sandbox-reset-test.c |  50 --
 drivers/reset/sandbox-reset.c  |  19 
 include/reset.h| 135 +-
 test/dm/reset.c|  59 
 6 files changed, 387 insertions(+), 23 deletions(-)

-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 4/5] drivers: clk: Fix using assigned-clocks in the node of the clock it sets up

2019-09-30 Thread Jean-Jacques Hiblot
This fixes the case where assigned-clocks is used to define a clock
defaults inside this same clock's node. This is used sometimes to setup a
default parents and/or rate for a clock.

example:
muxed_clock: muxed_clock {
clocks = <_provider 0>, <_provider 1>;
#clock-cells = <0>;
assigned-clocks = <_clock>;
assigned-clock-parents = <_provider 1>;
};

It doesn't work in u-boot because the assigned-clocks are setup *before*
the clock is probed. (clk_set_parent() will likely crash or fail if called
before the device probe function)
Making it work by handling "assigned-clocks" in 2 steps: first before the
clk device is probed, and then after the clk device is probed.

Signed-off-by: Jean-Jacques Hiblot 
---

 drivers/clk/clk-uclass.c | 48 +++-
 drivers/core/device.c|  2 +-
 include/clk.h|  7 --
 3 files changed, 48 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index e7ec6347de..75d618a47b 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -178,7 +178,7 @@ bulk_get_err:
return ret;
 }
 
-static int clk_set_default_parents(struct udevice *dev)
+static int clk_set_default_parents(struct udevice *dev, int stage)
 {
struct clk clk, parent_clk;
int index;
@@ -214,8 +214,18 @@ static int clk_set_default_parents(struct udevice *dev)
return ret;
}
 
-   ret = clk_set_parent(, _clk);
+   /* This is clk provider device trying to reparent itself
+* It cannot be done right now but need to wait after the
+* device is probed
+*/
+   if (stage == 0 && clk.dev == dev)
+   continue;
+
+   if (stage > 0 && clk.dev != dev)
+   /* do not setup twice the parent clocks */
+   continue;
 
+   ret = clk_set_parent(, _clk);
/*
 * Not all drivers may support clock-reparenting (as of now).
 * Ignore errors due to this.
@@ -233,7 +243,7 @@ static int clk_set_default_parents(struct udevice *dev)
return 0;
 }
 
-static int clk_set_default_rates(struct udevice *dev)
+static int clk_set_default_rates(struct udevice *dev, int stage)
 {
struct clk clk;
int index;
@@ -268,7 +278,19 @@ static int clk_set_default_rates(struct udevice *dev)
continue;
}
 
+   /* This is clk provider device trying to program itself
+* It cannot be done right now but need to wait after the
+* device is probed
+*/
+   if (stage == 0 && clk.dev == dev)
+   continue;
+
+   if (stage > 0 && clk.dev != dev)
+   /* do not setup twice the parent clocks */
+   continue;
+
ret = clk_set_rate(, rates[index]);
+
if (ret < 0) {
debug("%s: failed to set rate on clock index %d (%ld) 
for %s\n",
  __func__, index, clk.id, dev_read_name(dev));
@@ -281,7 +303,7 @@ fail:
return ret;
 }
 
-int clk_set_defaults(struct udevice *dev)
+int clk_set_defaults(struct udevice *dev, int stage)
 {
int ret;
 
@@ -294,11 +316,11 @@ int clk_set_defaults(struct udevice *dev)
 
debug("%s(%s)\n", __func__, dev_read_name(dev));
 
-   ret = clk_set_default_parents(dev);
+   ret = clk_set_default_parents(dev, stage);
if (ret)
return ret;
 
-   ret = clk_set_default_rates(dev);
+   ret = clk_set_default_rates(dev, stage);
if (ret < 0)
return ret;
 
@@ -673,7 +695,21 @@ void devm_clk_put(struct udevice *dev, struct clk *clk)
WARN_ON(rc);
 }
 
+int clk_uclass_post_probe(struct udevice *dev)
+{
+   /*
+* when a clock provider is probed. Call clk_set_defaults()
+* also after the device is probed. This takes care of cases
+* where the DT is used to setup default parents and rates
+* using assigned-clocks
+*/
+   clk_set_defaults(dev, 1);
+
+   return 0;
+}
+
 UCLASS_DRIVER(clk) = {
.id = UCLASS_CLK,
.name   = "clk",
+   .post_probe = clk_uclass_post_probe,
 };
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 05dadf98f9..cbcbb1b15d 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -416,7 +416,7 @@ int device_probe(struct udevice *dev)
 * Process 'assigned-{clocks/clock-parents/clock-rates}'
 * properties
 */
-   ret = clk_set_defaults(dev);
+   ret = clk_set_defaults(dev, 0);
   

[U-Boot] [PATCH v1 5/5] test: clk: test clock self assignment

2019-09-30 Thread Jean-Jacques Hiblot
Make sure that the clock self-assignment works by having a clock of
clk-sbox be configured automatically when clk-sbox is probed.

Signed-off-by: Jean-Jacques Hiblot 

---

 arch/sandbox/dts/test.dts |  2 ++
 drivers/clk/clk_sandbox.c | 22 ++
 test/dm/clk.c |  4 ++--
 3 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 25c238d8e5..0917255476 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -222,6 +222,8 @@
clk_sandbox: clk-sbox {
compatible = "sandbox,clk";
#clock-cells = <1>;
+   assigned-clocks = <_sandbox 3>;
+   assigned-clock-rates = <321>;
};
 
clk-test {
diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c
index d152fd7e5b..de6b2f7c82 100644
--- a/drivers/clk/clk_sandbox.c
+++ b/drivers/clk/clk_sandbox.c
@@ -10,6 +10,7 @@
 #include 
 
 struct sandbox_clk_priv {
+   bool probed;
ulong rate[SANDBOX_CLK_ID_COUNT];
bool enabled[SANDBOX_CLK_ID_COUNT];
bool requested[SANDBOX_CLK_ID_COUNT];
@@ -19,6 +20,9 @@ static ulong sandbox_clk_get_rate(struct clk *clk)
 {
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
 
+   if (!priv->probed)
+   return -ENODEV;
+
if (clk->id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
 
@@ -30,6 +34,9 @@ static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
ulong old_rate;
 
+   if (!priv->probed)
+   return -ENODEV;
+
if (clk->id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
 
@@ -46,6 +53,9 @@ static int sandbox_clk_enable(struct clk *clk)
 {
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
 
+   if (!priv->probed)
+   return -ENODEV;
+
if (clk->id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
 
@@ -58,6 +68,9 @@ static int sandbox_clk_disable(struct clk *clk)
 {
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
 
+   if (!priv->probed)
+   return -ENODEV;
+
if (clk->id >= SANDBOX_CLK_ID_COUNT)
return -EINVAL;
 
@@ -97,6 +110,14 @@ static struct clk_ops sandbox_clk_ops = {
.free   = sandbox_clk_free,
 };
 
+static int sandbox_clk_probe(struct udevice *dev)
+{
+   struct sandbox_clk_priv *priv = dev_get_priv(dev);
+
+   priv->probed = true;
+   return 0;
+}
+
 static const struct udevice_id sandbox_clk_ids[] = {
{ .compatible = "sandbox,clk" },
{ }
@@ -107,6 +128,7 @@ U_BOOT_DRIVER(clk_sandbox) = {
.id = UCLASS_CLK,
.of_match   = sandbox_clk_ids,
.ops= _clk_ops,
+   .probe  = sandbox_clk_probe,
.priv_auto_alloc_size = sizeof(struct sandbox_clk_priv),
 };
 
diff --git a/test/dm/clk.c b/test/dm/clk.c
index 3ad0ad8ca3..31335a543f 100644
--- a/test/dm/clk.c
+++ b/test/dm/clk.c
@@ -74,8 +74,8 @@ static int dm_test_clk(struct unit_test_state *uts)
 SANDBOX_CLK_TEST_ID_SPI));
ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
 SANDBOX_CLK_TEST_ID_I2C));
-   ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
-SANDBOX_CLK_TEST_ID_DEVM1));
+   ut_asserteq(321, sandbox_clk_test_get_rate(dev_test,
+  SANDBOX_CLK_TEST_ID_DEVM1));
ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
 SANDBOX_CLK_TEST_ID_DEVM2));
 
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 1/5] drivers: clk: Handle gracefully NULL pointers

2019-09-30 Thread Jean-Jacques Hiblot
Prepare the way for a managed CLK API by handling NULL pointers without
crashing nor failing.

Signed-off-by: Jean-Jacques Hiblot 
---

 drivers/clk/clk-uclass.c | 43 +---
 include/clk.h|  2 +-
 2 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 64c181f4ad..dff395fedb 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -349,9 +349,12 @@ int clk_release_all(struct clk *clk, int count)
 
 int clk_request(struct udevice *dev, struct clk *clk)
 {
-   const struct clk_ops *ops = clk_dev_ops(dev);
+   const struct clk_ops *ops;
 
debug("%s(dev=%p, clk=%p)\n", __func__, dev, clk);
+   if (!clk)
+   return 0;
+   ops = clk_dev_ops(dev);
 
clk->dev = dev;
 
@@ -363,9 +366,12 @@ int clk_request(struct udevice *dev, struct clk *clk)
 
 int clk_free(struct clk *clk)
 {
-   const struct clk_ops *ops = clk_dev_ops(clk->dev);
+   const struct clk_ops *ops;
 
debug("%s(clk=%p)\n", __func__, clk);
+   if (!clk)
+   return 0;
+   ops = clk_dev_ops(clk->dev);
 
if (!ops->free)
return 0;
@@ -375,9 +381,12 @@ int clk_free(struct clk *clk)
 
 ulong clk_get_rate(struct clk *clk)
 {
-   const struct clk_ops *ops = clk_dev_ops(clk->dev);
+   const struct clk_ops *ops;
 
debug("%s(clk=%p)\n", __func__, clk);
+   if (!clk)
+   return 0;
+   ops = clk_dev_ops(clk->dev);
 
if (!ops->get_rate)
return -ENOSYS;
@@ -391,6 +400,8 @@ struct clk *clk_get_parent(struct clk *clk)
struct clk *pclk;
 
debug("%s(clk=%p)\n", __func__, clk);
+   if (!clk)
+   return NULL;
 
pdev = dev_get_parent(clk->dev);
pclk = dev_get_clk_ptr(pdev);
@@ -406,6 +417,8 @@ long long clk_get_parent_rate(struct clk *clk)
struct clk *pclk;
 
debug("%s(clk=%p)\n", __func__, clk);
+   if (!clk)
+   return 0;
 
pclk = clk_get_parent(clk);
if (IS_ERR(pclk))
@@ -424,9 +437,12 @@ long long clk_get_parent_rate(struct clk *clk)
 
 ulong clk_set_rate(struct clk *clk, ulong rate)
 {
-   const struct clk_ops *ops = clk_dev_ops(clk->dev);
+   const struct clk_ops *ops;
 
debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate);
+   if (!clk)
+   return 0;
+   ops = clk_dev_ops(clk->dev);
 
if (!ops->set_rate)
return -ENOSYS;
@@ -436,9 +452,12 @@ ulong clk_set_rate(struct clk *clk, ulong rate)
 
 int clk_set_parent(struct clk *clk, struct clk *parent)
 {
-   const struct clk_ops *ops = clk_dev_ops(clk->dev);
+   const struct clk_ops *ops;
 
debug("%s(clk=%p, parent=%p)\n", __func__, clk, parent);
+   if (!clk)
+   return 0;
+   ops = clk_dev_ops(clk->dev);
 
if (!ops->set_parent)
return -ENOSYS;
@@ -448,11 +467,14 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 
 int clk_enable(struct clk *clk)
 {
-   const struct clk_ops *ops = clk_dev_ops(clk->dev);
+   const struct clk_ops *ops;
struct clk *clkp = NULL;
int ret;
 
debug("%s(clk=%p)\n", __func__, clk);
+   if (!clk)
+   return 0;
+   ops = clk_dev_ops(clk->dev);
 
if (CONFIG_IS_ENABLED(CLK_CCF)) {
/* Take id 0 as a non-valid clk, such as dummy */
@@ -505,11 +527,14 @@ int clk_enable_bulk(struct clk_bulk *bulk)
 
 int clk_disable(struct clk *clk)
 {
-   const struct clk_ops *ops = clk_dev_ops(clk->dev);
+   const struct clk_ops *ops;
struct clk *clkp = NULL;
int ret;
 
debug("%s(clk=%p)\n", __func__, clk);
+   if (!clk)
+   return 0;
+   ops = clk_dev_ops(clk->dev);
 
if (CONFIG_IS_ENABLED(CLK_CCF)) {
if (clk->id && !clk_get_by_id(clk->id, )) {
@@ -589,6 +614,10 @@ bool clk_is_match(const struct clk *p, const struct clk *q)
if (p == q)
return true;
 
+   /* trivial case #2: on the clk pointer is NULL */
+   if (!p || !q)
+   return false;
+
/* same device, id and data */
if (p->dev == q->dev && p->id == q->id && p->data == q->data)
return true;
diff --git a/include/clk.h b/include/clk.h
index 18b2e3ca54..6568865d40 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -356,7 +356,7 @@ int soc_clk_dump(void);
  */
 static inline bool clk_valid(struct clk *clk)
 {
-   return !!clk->dev;
+   return clk && !!clk->dev;
 }
 
 /**
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 0/5] clk: Add a managed API and fix clock self-assignment

2019-09-30 Thread Jean-Jacques Hiblot

This is the second of a few series, the goal of which is to facilitate
porting drivers from the linux kernel. Most of the series will be about
adding managed API to existing infrastructure (GPIO, reset, phy,...)

This particular series is about clocks. It adds a managed API, using
the same API as linux. It also fix a use-case where the clock is
initialized (rate and/or mux) when it is probed using the
assigned-clocks-* properties.

JJ

Jean-Jacques Hiblot (5):
  drivers: clk: Handle gracefully NULL pointers
  drivers: clk: Add a managed API to get clocks from the device-tree
  test: clk: Update tests to also check the managed API
  drivers: clk: Fix using assigned-clocks in the node of the clock it
sets up
  test: clk: test clock self assignment

 arch/sandbox/dts/test.dts  |   8 +-
 arch/sandbox/include/asm/clk.h |  33 
 drivers/clk/clk-uclass.c   | 139 ++---
 drivers/clk/clk_sandbox.c  |  56 +
 drivers/clk/clk_sandbox_test.c |  66 +---
 drivers/core/device.c  |   2 +-
 include/clk.h  |  53 -
 test/dm/clk.c  |  36 -
 8 files changed, 364 insertions(+), 29 deletions(-)

-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 2/5] drivers: clk: Add a managed API to get clocks from the device-tree

2019-09-30 Thread Jean-Jacques Hiblot
Add devm_clk_get(), devm_clk_get_optional() to get clocks from the
device-tree. The clocks is automatically released and the data structure
freed when the device is unbound.
Also add devm_clk_put() to release the clock and free the data structure
manually.

Signed-off-by: Jean-Jacques Hiblot 
---

 drivers/clk/clk-uclass.c | 48 
 include/clk.h| 44 
 2 files changed, 92 insertions(+)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index dff395fedb..e7ec6347de 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -625,6 +625,54 @@ bool clk_is_match(const struct clk *p, const struct clk *q)
return false;
 }
 
+static void devm_clk_release(struct udevice *dev, void *res)
+{
+   clk_free(res);
+}
+
+static int devm_clk_match(struct udevice *dev, void *res, void *data)
+{
+   return res == data;
+}
+
+struct clk *devm_clk_get(struct udevice *dev, const char *id)
+{
+   int rc;
+   struct clk *clk;
+
+   clk = devres_alloc(devm_clk_release, sizeof(struct clk), __GFP_ZERO);
+   if (unlikely(!clk))
+   return ERR_PTR(-ENOMEM);
+
+   rc = clk_get_by_name(dev, id, clk);
+   if (rc)
+   return ERR_PTR(rc);
+
+   devres_add(dev, clk);
+   return clk;
+}
+
+struct clk *devm_clk_get_optional(struct udevice *dev, const char *id)
+{
+   struct clk *clk = devm_clk_get(dev, id);
+
+   if (IS_ERR(clk))
+   return NULL;
+
+   return clk;
+}
+
+void devm_clk_put(struct udevice *dev, struct clk *clk)
+{
+   int rc;
+
+   if (!clk)
+   return;
+
+   rc = devres_release(dev, devm_clk_release, devm_clk_match, clk);
+   WARN_ON(rc);
+}
+
 UCLASS_DRIVER(clk) = {
.id = UCLASS_CLK,
.name   = "clk",
diff --git a/include/clk.h b/include/clk.h
index 6568865d40..6c5bf8ad67 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -154,6 +154,37 @@ int clk_get_bulk(struct udevice *dev, struct clk_bulk 
*bulk);
  */
 int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk);
 
+/**
+ * devm_clk_get - lookup and obtain a managed reference to a clock producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Returns a struct clk corresponding to the clock producer, or
+ * valid IS_ERR() condition containing errno.  The implementation
+ * uses @dev and @id to determine the clock consumer, and thereby
+ * the clock producer.  (IOW, @id may be identical strings, but
+ * clk_get may return different clock producers depending on @dev.)
+ *
+ * Drivers must assume that the clock source is not enabled.
+ *
+ * devm_clk_get should not be called from within interrupt context.
+ *
+ * The clock will automatically be freed when the device is unbound
+ * from the bus.
+ */
+struct clk *devm_clk_get(struct udevice *dev, const char *id);
+
+/**
+ * devm_clk_get_optional - lookup and obtain a managed reference to an optional
+ *clock producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Behaves the same as devm_clk_get() except where there is no clock producer.
+ * In this case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *devm_clk_get_optional(struct udevice *dev, const char *id);
+
 /**
  * clk_release_all() - Disable (turn off)/Free an array of previously
  * requested clocks.
@@ -168,6 +199,19 @@ int clk_get_by_name(struct udevice *dev, const char *name, 
struct clk *clk);
  */
 int clk_release_all(struct clk *clk, int count);
 
+/**
+ * devm_clk_put- "free" a managed clock source
+ * @dev: device used to acquire the clock
+ * @clk: clock source acquired with devm_clk_get()
+ *
+ * Note: drivers must ensure that all clk_enable calls made on this
+ * clock source are balanced by clk_disable calls prior to calling
+ * this function.
+ *
+ * clk_put should not be called from within interrupt context.
+ */
+void devm_clk_put(struct udevice *dev, struct clk *clk);
+
 #else
 static inline int clk_get_by_index(struct udevice *dev, int index,
   struct clk *clk)
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 3/5] test: clk: Update tests to also check the managed API

2019-09-30 Thread Jean-Jacques Hiblot
Add a few more clocks the clk_sandbox clock provider and get them using
the managed API.
Make sure they are released when the device is removed.

Signed-off-by: Jean-Jacques Hiblot 
---

 arch/sandbox/dts/test.dts  |  6 ++--
 arch/sandbox/include/asm/clk.h | 33 +
 drivers/clk/clk_sandbox.c  | 34 ++
 drivers/clk/clk_sandbox_test.c | 66 +-
 test/dm/clk.c  | 36 ++-
 5 files changed, 163 insertions(+), 12 deletions(-)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 27b0baab27..25c238d8e5 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -228,8 +228,10 @@
compatible = "sandbox,clk-test";
clocks = <_fixed>,
 <_sandbox 1>,
-<_sandbox 0>;
-   clock-names = "fixed", "i2c", "spi";
+<_sandbox 0>,
+<_sandbox 3>,
+<_sandbox 2>;
+   clock-names = "fixed", "i2c", "spi", "uart2", "uart1";
};
 
ccf: clk-ccf {
diff --git a/arch/sandbox/include/asm/clk.h b/arch/sandbox/include/asm/clk.h
index 2b1c49f783..1573e4a134 100644
--- a/arch/sandbox/include/asm/clk.h
+++ b/arch/sandbox/include/asm/clk.h
@@ -19,6 +19,8 @@ struct udevice;
 enum sandbox_clk_id {
SANDBOX_CLK_ID_SPI,
SANDBOX_CLK_ID_I2C,
+   SANDBOX_CLK_ID_UART1,
+   SANDBOX_CLK_ID_UART2,
 
SANDBOX_CLK_ID_COUNT,
 };
@@ -33,10 +35,15 @@ enum sandbox_clk_test_id {
SANDBOX_CLK_TEST_ID_FIXED,
SANDBOX_CLK_TEST_ID_SPI,
SANDBOX_CLK_TEST_ID_I2C,
+   SANDBOX_CLK_TEST_ID_DEVM1,
+   SANDBOX_CLK_TEST_ID_DEVM2,
+   SANDBOX_CLK_TEST_ID_DEVM_NULL,
 
SANDBOX_CLK_TEST_ID_COUNT,
 };
 
+#define SANDBOX_CLK_TEST_NON_DEVM_COUNT SANDBOX_CLK_TEST_ID_DEVM1
+
 /**
  * sandbox_clk_query_rate - Query the current rate of a sandbox clock.
  *
@@ -53,6 +60,14 @@ ulong sandbox_clk_query_rate(struct udevice *dev, int id);
  * @return:The rate of the clock.
  */
 int sandbox_clk_query_enable(struct udevice *dev, int id);
+/**
+ * sandbox_clk_query_requested - Query the requested state of a sandbox clock.
+ *
+ * @dev:   The sandbox clock provider device.
+ * @id:The clock to query.
+ * @return:The rate of the clock.
+ */
+int sandbox_clk_query_requested(struct udevice *dev, int id);
 
 /**
  * sandbox_clk_test_get - Ask the sandbox clock test device to request its
@@ -62,6 +77,16 @@ int sandbox_clk_query_enable(struct udevice *dev, int id);
  * @return:0 if OK, or a negative error code.
  */
 int sandbox_clk_test_get(struct udevice *dev);
+
+/**
+ * sandbox_clk_test_devm_get - Ask the sandbox clock test device to request its
+ * clocks using the managed API.
+ *
+ * @dev:   The sandbox clock test (client) devivce.
+ * @return:0 if OK, or a negative error code.
+ */
+int sandbox_clk_test_devm_get(struct udevice *dev);
+
 /**
  * sandbox_clk_test_get_bulk - Ask the sandbox clock test device to request its
  * clocks with the bulk clk API.
@@ -146,5 +171,13 @@ int sandbox_clk_test_release_bulk(struct udevice *dev);
  * @return:0 if OK, or a negative error code.
  */
 int sandbox_clk_test_valid(struct udevice *dev);
+/**
+ * sandbox_clk_test_valid - Ask the sandbox clock test device to check its
+ * clocks are valid.
+ *
+ * @dev:   The sandbox clock test (client) devivce.
+ * @return:0 if OK, or a negative error code.
+ */
+struct clk *sandbox_clk_test_get_devm_clk(struct udevice *dev, int id);
 
 #endif
diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c
index 1d5cbb589a..d152fd7e5b 100644
--- a/drivers/clk/clk_sandbox.c
+++ b/drivers/clk/clk_sandbox.c
@@ -12,6 +12,7 @@
 struct sandbox_clk_priv {
ulong rate[SANDBOX_CLK_ID_COUNT];
bool enabled[SANDBOX_CLK_ID_COUNT];
+   bool requested[SANDBOX_CLK_ID_COUNT];
 };
 
 static ulong sandbox_clk_get_rate(struct clk *clk)
@@ -65,11 +66,35 @@ static int sandbox_clk_disable(struct clk *clk)
return 0;
 }
 
+static int sandbox_clk_request(struct clk *clk)
+{
+   struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
+
+   if (clk->id >= SANDBOX_CLK_ID_COUNT)
+   return -EINVAL;
+
+   priv->requested[clk->id] = true;
+   return 0;
+}
+
+static int sandbox_clk_free(struct clk *clk)
+{
+   struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
+
+   if (clk->id >= SANDBOX_CLK_ID_COUNT)
+   return -EINVAL;
+
+   priv->requested[clk->id] = false;
+   return 0;
+}
+
 static struct clk_ops sandbox_clk_ops = {
.get_rate   = sandbox_clk_get_rate,
.set_rate   = sandbox_clk_set_rate,
.enable = sandbox_clk_enable,

[U-Boot] [PATCH v1 3/5] regmap: Allow providing read/write callbacks through struct regmap_config

2019-09-27 Thread Jean-Jacques Hiblot
Some linux drivers provide their own read/write functions to access data
from/of the regmap. Adding support for it.

Signed-off-by: Jean-Jacques Hiblot 
---

 drivers/core/regmap.c | 12 
 include/regmap.h  | 26 +++---
 2 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index f69ff6d12f..486eea7bd4 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -31,6 +31,9 @@ static struct regmap *regmap_alloc(int count)
if (!map)
return NULL;
map->range_count = count;
+   map->bus_context = NULL;
+   map->reg_read = NULL;
+   map->reg_write = NULL;
 
return map;
 }
@@ -241,6 +244,9 @@ struct regmap *devm_regmap_init(struct udevice *dev,
rc = regmap_init_mem(dev_ofnode(dev), mapp);
if (rc)
return ERR_PTR(rc);
+   (*mapp)->reg_read = config->reg_read;
+   (*mapp)->reg_write = config->reg_write;
+   (*mapp)->bus_context = bus_context;
 
devres_add(dev, mapp);
return *mapp;
@@ -320,6 +326,9 @@ int regmap_raw_read_range(struct regmap *map, uint 
range_num, uint offset,
struct regmap_range *range;
void *ptr;
 
+   if (map->reg_read)
+   return map->reg_read(map->bus_context, offset, valp);
+
if (range_num >= map->range_count) {
debug("%s: range index %d larger than range count\n",
  __func__, range_num);
@@ -429,6 +438,9 @@ int regmap_raw_write_range(struct regmap *map, uint 
range_num, uint offset,
struct regmap_range *range;
void *ptr;
 
+   if (map->reg_write)
+   return map->reg_write(map->bus_context, offset,
+ *(unsigned int *)val);
if (range_num >= map->range_count) {
debug("%s: range index %d larger than range count\n",
  __func__, range_num);
diff --git a/include/regmap.h b/include/regmap.h
index 63a362d86d..cc0adf568b 100644
--- a/include/regmap.h
+++ b/include/regmap.h
@@ -74,16 +74,36 @@ struct regmap_range {
 };
 
 struct regmap_bus;
-struct regmap_config;
+/**
+ * struct regmap_config - a way of accessing hardware/bus registers
+ *
+ * @reg_read:Optional callback that if filled will be used to perform
+ *   all the reads from the registers. Should only be provided for
+ *   devices whose read operation cannot be represented as a simple
+ *   read operation on a bus such as SPI, I2C, etc. Most of the
+ *   devices do not need this.
+ * @reg_write:   Same as above for writing.
+ */
+struct regmap_config {
+   int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
+   int (*reg_write)(void *context, unsigned int reg, unsigned int val);
+};
 
 /**
  * struct regmap - a way of accessing hardware/bus registers
  *
  * @range_count:   Number of ranges available within the map
  * @ranges:Array of ranges
+ * @bus_context:   Data passed to bus-specific callbacks
+ * @reg_read:  Optional callback that if filled will be used to perform
+ * all the reads from the registers.
+ * @reg_write: Same as above for writing.
  */
 struct regmap {
enum regmap_endianness_t endianness;
+   void *bus_context;
+   int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
+   int (*reg_write)(void *context, unsigned int reg, unsigned int val);
int range_count;
struct regmap_range ranges[0];
 };
@@ -340,8 +360,8 @@ int regmap_init_mem_index(ofnode node, struct regmap 
**mapp, int index);
  *
  * @dev: Device that will be interacted with
  * @bus: Bus-specific callbacks to use with device (IGNORED)
- * @bus_context: Data passed to bus-specific callbacks (IGNORED)
- * @config: Configuration for register map (IGNORED)
+ * @bus_context: Data passed to bus-specific callbacks
+ * @config: Configuration for register map
  *
  * The return value will be an ERR_PTR() on error or a valid pointer to
  * a struct regmap.
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 5/5] test: dm: Add tests for regmap managed API and regmap fields

2019-09-27 Thread Jean-Jacques Hiblot
The tests rely on a dummy driver to allocate and initialize the regmap
and the regmap fields using the managed API.
The first test checks that the read/write callbacks are used.
The second test checks if regmap fields behave properly (mask and shift
are ok) by peeking into the regmap.

Signed-off-by: Jean-Jacques Hiblot 

---

 arch/sandbox/dts/test.dts |  13 +++
 test/dm/regmap.c  | 189 ++
 2 files changed, 202 insertions(+)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 27b0baab27..044895586a 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -862,6 +862,19 @@
mdio: mdio-test {
compatible = "sandbox,mdio";
};
+
+   some_regmapped-bus {
+   #address-cells = <0x1>;
+   #size-cells = <0x1>;
+
+   ranges = <0x0 0x0 0x10>;
+   compatible = "simple-bus";
+
+   regmap-test_0 {
+   reg = <0 0x10>;
+   compatible = "sandbox,regmap_test";
+   };
+   };
 };
 
 #include "sandbox_pmic.dtsi"
diff --git a/test/dm/regmap.c b/test/dm/regmap.c
index 82de295cb8..29159ccf41 100644
--- a/test/dm/regmap.c
+++ b/test/dm/regmap.c
@@ -171,3 +171,192 @@ static int dm_test_regmap_poll(struct unit_test_state 
*uts)
 }
 
 DM_TEST(dm_test_regmap_poll, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+struct regmaptest_priv {
+   struct regmap *regmap;
+   struct regmap_field **fields;
+};
+
+#define REGMAP_TEST_BUF_SZ 12
+struct regmaptest_context {
+   unsigned short buffer[REGMAP_TEST_BUF_SZ];
+} ctx;
+
+static int regmaptest_write(void *context, unsigned int reg, unsigned int val)
+{
+   struct regmaptest_context *ctx = context;
+
+   if (reg < ARRAY_SIZE(ctx->buffer)) {
+   ctx->buffer[reg] = val;
+   return 0;
+   }
+   return -ERANGE;
+}
+
+static int regmaptest_read(void *context, unsigned int reg, unsigned int *val)
+{
+   struct regmaptest_context *ctx = context;
+
+   if (reg < ARRAY_SIZE(ctx->buffer)) {
+   *val = ctx->buffer[reg];
+   return 0;
+   }
+
+   return -ERANGE;
+}
+
+static struct regmap_config cfg = {
+   .reg_write = regmaptest_write,
+   .reg_read = regmaptest_read,
+};
+
+static const struct reg_field field_cfgs[] = {
+   {
+   .reg = 0,
+   .lsb = 0,
+   .msb = 6,
+   },
+   {
+   .reg = 1,
+   .lsb = 4,
+   .msb = 12,
+   },
+   {
+   .reg = 1,
+   .lsb = 12,
+   .msb = 15,
+   }
+};
+
+static int remaptest_probe(struct udevice *dev)
+{
+   struct regmaptest_priv *priv = dev_get_priv(dev);
+   struct regmap *regmap;
+   struct regmap_field *field;
+   int i;
+   static const int n = ARRAY_SIZE(field_cfgs);
+
+   regmap = devm_regmap_init(dev, NULL, , );
+   if (IS_ERR(regmap))
+   return PTR_ERR(regmap);
+   priv->regmap = regmap;
+
+   priv->fields = devm_kzalloc(dev, sizeof(struct regmap_field *) * n,
+   GFP_KERNEL);
+   if (!priv->fields)
+   return -ENOMEM;
+
+   for (i = 0 ; i < n; i++) {
+   field = devm_regmap_field_alloc(dev, regmap, field_cfgs[i]);
+   if (IS_ERR(field))
+   return PTR_ERR(field);
+   priv->fields[i] = field;
+   }
+   return 0;
+}
+
+static const struct udevice_id regmaptest_ids[] = {
+   { .compatible = "sandbox,regmap_test" },
+   { }
+};
+
+U_BOOT_DRIVER(regmap_test) = {
+   .name   = "regmaptest_drv",
+   .of_match   = regmaptest_ids,
+   .id = UCLASS_NOP,
+   .probe = remaptest_probe,
+   .priv_auto_alloc_size = sizeof(struct regmaptest_priv),
+};
+
+static int dm_test_devm_regmap(struct unit_test_state *uts)
+{
+   int i = 0;
+   u32 val;
+   u16 pattern[REGMAP_TEST_BUF_SZ];
+   struct udevice *dev;
+   struct regmaptest_priv *priv;
+
+   ut_assertok(uclass_get_device_by_name(UCLASS_NOP, "regmap-test_0",
+ ));
+
+   priv = dev_get_priv(dev);
+
+   srand(get_ticks() + rand());
+   for (i = REGMAP_TEST_BUF_SZ - 1; i >= 0; i--) {
+   pattern[i] = rand() & 0x;
+   ut_assertok(regmap_write(priv->regmap, i, pattern[i]));
+   }
+   for (i = 0; i < REGMAP_TEST_BUF_SZ; i++) {
+   ut_assertok(regmap_read(priv->regmap, i, ));
+   ut_asserteq(val, ctx.buffer[i]);
+   ut_asserteq(val, pattern[i]);
+   }
+
+   ut_asserteq(-ERANGE, regmap_write(priv->regmap, REGMAP_TEST_BUF_SZ,
+ 

[U-Boot] [PATCH v1 4/5] regmap: Add support for regmap fields

2019-09-27 Thread Jean-Jacques Hiblot
A regmap field is an abstraction available in Linux. It provides to access
bitfields in a regmap without having to worry about shifts and masks.

Signed-off-by: Jean-Jacques Hiblot 
---

 drivers/core/regmap.c |  77 ++
 include/regmap.h  | 108 ++
 2 files changed, 185 insertions(+)

diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index 486eea7bd4..96ac1db9b0 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -15,6 +15,14 @@
 #include 
 #include 
 
+struct regmap_field {
+   struct regmap *regmap;
+   unsigned int mask;
+   /* lsb */
+   unsigned int shift;
+   unsigned int reg;
+};
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /**
@@ -502,3 +510,72 @@ int regmap_update_bits(struct regmap *map, uint offset, 
uint mask, uint val)
 
return regmap_write(map, offset, reg | (val & mask));
 }
+
+int regmap_field_read(struct regmap_field *field, unsigned int *val)
+{
+   int ret;
+   unsigned int reg_val;
+
+   ret = regmap_read(field->regmap, field->reg, _val);
+   if (ret != 0)
+   return ret;
+
+   reg_val &= field->mask;
+   reg_val >>= field->shift;
+   *val = reg_val;
+
+   return ret;
+}
+
+int regmap_field_write(struct regmap_field *field, unsigned int val)
+{
+   return regmap_update_bits(field->regmap, field->reg, field->mask,
+ val << field->shift);
+}
+
+static void regmap_field_init(struct regmap_field *rm_field,
+ struct regmap *regmap,
+ struct reg_field reg_field)
+{
+   rm_field->regmap = regmap;
+   rm_field->reg = reg_field.reg;
+   rm_field->shift = reg_field.lsb;
+   rm_field->mask = GENMASK(reg_field.msb, reg_field.lsb);
+}
+
+struct regmap_field *devm_regmap_field_alloc(struct udevice *dev,
+struct regmap *regmap,
+struct reg_field reg_field)
+{
+   struct regmap_field *rm_field = devm_kzalloc(dev, sizeof(*rm_field),
+GFP_KERNEL);
+   if (!rm_field)
+   return ERR_PTR(-ENOMEM);
+
+   regmap_field_init(rm_field, regmap, reg_field);
+
+   return rm_field;
+}
+
+void devm_regmap_field_free(struct udevice *dev, struct regmap_field *field)
+{
+   devm_kfree(dev, field);
+}
+
+struct regmap_field *regmap_field_alloc(struct regmap *regmap,
+   struct reg_field reg_field)
+{
+   struct regmap_field *rm_field = kzalloc(sizeof(*rm_field), GFP_KERNEL);
+
+   if (!rm_field)
+   return ERR_PTR(-ENOMEM);
+
+   regmap_field_init(rm_field, regmap, reg_field);
+
+   return rm_field;
+}
+
+void regmap_field_free(struct regmap_field *field)
+{
+   kfree(field);
+}
diff --git a/include/regmap.h b/include/regmap.h
index cc0adf568b..c1a9c8f548 100644
--- a/include/regmap.h
+++ b/include/regmap.h
@@ -312,6 +312,43 @@ int regmap_raw_read_range(struct regmap *map, uint 
range_num, uint offset,
regmap_read_poll_timeout_test(map, addr, val, cond, sleep_us, \
  timeout_ms, 0) \
 
+/**
+ * regmap_field_read_poll_timeout - Poll until a condition is met or a timeout
+ * occurs
+ *
+ * @field: Regmap field to read from
+ * @val:   Unsigned integer variable to read the value into
+ * @cond:  Break condition (usually involving @val)
+ * @sleep_us:  Maximum time to sleep between reads in us (0 tight-loops).
+ * @timeout_ms:Timeout in ms, 0 means never timeout
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_field_read
+ * error return value in case of a error read. In the two former cases,
+ * the last read value at @addr is stored in @val.
+ *
+ * This is modelled after the regmap_read_poll_timeout macros in linux but
+ * with millisecond timeout.
+ */
+#define regmap_field_read_poll_timeout(field, val, cond, sleep_us, timeout_ms) 
\
+({ \
+   unsigned long __start = get_timer(0); \
+   int __ret; \
+   for (;;) { \
+   __ret = regmap_field_read((field), &(val)); \
+   if (__ret) \
+   break; \
+   if (cond) \
+   break; \
+   if ((timeout_ms) && get_timer(__start) > (timeout_ms)) { \
+   __ret = regmap_field_read((field), &(val)); \
+   break; \
+   } \
+   if ((sleep_us)) \
+   udelay((sleep_us)); \
+   } \
+   __ret ?: ((cond) ? 0 : -ETIMEDOUT); \
+})
+
 /**
  * regmap_update_bits() - Perform a read/modify/write using a mask
  *
@@ -388,4 +425,75 @@ void *regmap_get_range(struct regmap *map, unsigned int 
range_num);
  */
 int regmap_uninit(st

[U-Boot] [PATCH v1 2/5] regmap: Add devm_regmap_init()

2019-09-27 Thread Jean-Jacques Hiblot
Most of new linux drivers are using managed-API to allocate resources. To
ease porting drivers from linux to u-boot, introduce devm_regmap_init() as
a managed API to get a regmap from the device tree.

Signed-off-by: Jean-Jacques Hiblot 
---

 drivers/core/regmap.c | 26 ++
 include/regmap.h  | 19 +++
 2 files changed, 45 insertions(+)

diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index e9e55c9d16..f69ff6d12f 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -219,6 +219,32 @@ int regmap_init_mem(ofnode node, struct regmap **mapp)
 
return 0;
 }
+
+static void devm_regmap_release(struct udevice *dev, void *res)
+{
+   regmap_uninit(*(struct regmap **)res);
+}
+
+struct regmap *devm_regmap_init(struct udevice *dev,
+   const struct regmap_bus *bus,
+   void *bus_context,
+   const struct regmap_config *config)
+{
+   int rc;
+   struct regmap **mapp;
+
+   mapp = devres_alloc(devm_regmap_release, sizeof(struct regmap *),
+   __GFP_ZERO);
+   if (unlikely(!mapp))
+   return ERR_PTR(-ENOMEM);
+
+   rc = regmap_init_mem(dev_ofnode(dev), mapp);
+   if (rc)
+   return ERR_PTR(rc);
+
+   devres_add(dev, mapp);
+   return *mapp;
+}
 #endif
 
 void *regmap_get_range(struct regmap *map, unsigned int range_num)
diff --git a/include/regmap.h b/include/regmap.h
index 0854200a9c..63a362d86d 100644
--- a/include/regmap.h
+++ b/include/regmap.h
@@ -73,6 +73,9 @@ struct regmap_range {
ulong size;
 };
 
+struct regmap_bus;
+struct regmap_config;
+
 /**
  * struct regmap - a way of accessing hardware/bus registers
  *
@@ -332,6 +335,22 @@ int regmap_init_mem_platdata(struct udevice *dev, 
fdt_val_t *reg, int count,
 
 int regmap_init_mem_index(ofnode node, struct regmap **mapp, int index);
 
+/**
+ * devm_regmap_init() - Initialise register map (device managed)
+ *
+ * @dev: Device that will be interacted with
+ * @bus: Bus-specific callbacks to use with device (IGNORED)
+ * @bus_context: Data passed to bus-specific callbacks (IGNORED)
+ * @config: Configuration for register map (IGNORED)
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer to
+ * a struct regmap.
+ * The structure is automatically freed when the device is unbound
+ */
+struct regmap *devm_regmap_init(struct udevice *dev,
+   const struct regmap_bus *bus,
+   void *bus_context,
+   const struct regmap_config *config);
 /**
  * regmap_get_range() - Obtain the base memory address of a regmap range
  *
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 0/5] regmap: Add a managed API, custom read/write callbacks and support for regmap fields

2019-09-27 Thread Jean-Jacques Hiblot
This is the first of a few series, the goal of which is to facilitate
porting drivers from the linux kernel. Most of the series will be about
adding managed API to existing infrastructure (GPIO, reset, phy,...)

This particular series is about regmaps. It adds the managed API, using
the same API as linux. It also adds support for regmap fields and for
custom read/write callbacks.


Jean-Jacques Hiblot (5):
  regmap: Fix potential overflow in regmap_update_bits()
  regmap: Add devm_regmap_init()
  regmap: Allow providing read/write callbacks through struct
regmap_config
  regmap: Add support for regmap fields
  test: dm: Add tests for regmap managed API and regmap fields

 arch/sandbox/dts/test.dts |  13 +++
 drivers/core/regmap.c | 117 ++-
 include/regmap.h  | 147 +
 test/dm/regmap.c  | 189 ++
 4 files changed, 465 insertions(+), 1 deletion(-)

-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 1/5] regmap: Fix potential overflow in regmap_update_bits()

2019-09-27 Thread Jean-Jacques Hiblot
Mask the value to write so that it cannot affect the bits outside of the
mask

Signed-off-by: Jean-Jacques Hiblot 
---

 drivers/core/regmap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index d1d12eef38..e9e55c9d16 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -462,5 +462,5 @@ int regmap_update_bits(struct regmap *map, uint offset, 
uint mask, uint val)
 
reg &= ~mask;
 
-   return regmap_write(map, offset, reg | val);
+   return regmap_write(map, offset, reg | (val & mask));
 }
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH] dm: device: Fix typo in the non-DEVRES version of devm_kmalloc_array()

2019-09-26 Thread Jean-Jacques Hiblot
When DEVRES is not set, devm_kmalloc_array() is spelled
devm_kmaloc_array() (with one 'l' only).
Fixing it so that the name is the same with and without DEVRES.

Signed-off-by: Jean-Jacques Hiblot 
---
 include/dm/device.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/dm/device.h b/include/dm/device.h
index 27a6d7b9fd..9e34204b13 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -927,8 +927,8 @@ static inline void *devm_kzalloc(struct udevice *dev, 
size_t size, gfp_t gfp)
return kzalloc(size, gfp);
 }
 
-static inline void *devm_kmaloc_array(struct udevice *dev,
- size_t n, size_t size, gfp_t flags)
+static inline void *devm_kmalloc_array(struct udevice *dev,
+  size_t n, size_t size, gfp_t flags)
 {
/* TODO: add kmalloc_array() to linux/compat.h */
if (size != 0 && n > SIZE_MAX / size)
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH] clk: Fix error check in clk_set_default_parents()

2019-09-26 Thread Jean-Jacques Hiblot
According to the documentation in clk.h, clk_set_parent() return the new
rate of the clock or a negative error code.

Signed-off-by: Jean-Jacques Hiblot 
---
 drivers/clk/clk-uclass.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 64c181f4ad..bf1adc09ab 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -223,7 +223,7 @@ static int clk_set_default_parents(struct udevice *dev)
if (ret == -ENOSYS)
continue;
 
-   if (ret) {
+   if (ret < 0) {
debug("%s: failed to reparent clock %d for %s\n",
  __func__, index, dev_read_name(dev));
return ret;
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 0/3] Add support for DFU boot to DRA7-based EVMs

2019-09-24 Thread Jean-Jacques Hiblot
The purpose of this series is to provide the SPL with ability to boot
u-boot from DFU.
The DRA7x can download the SPL over the USB1 port when configured in
the USB peripheral boot mode. Details on how this can be acheived with
the EVMs can found here http://www.ti.com/lit/an/sprac33/sprac33.pdf
Once the SPL is loaded, u-boot can be downloaded on the same USB1 port
through DFU.

This boot flow has been tested on DRA7-evm, DRA72-evm-rec, DRA71-evm and
DRA76-evm

Faiz Abbas (3):
  ARM: dts: dra7: Add usb peripheral nodes in spl
  configs: dra7xx_evm: Add Kconfigs for SPL_DFU bootmode
  configs: dra7xx_evm: Increase the size of SPL_MULTI_DTB_FIT

 arch/arm/dts/dra7-evm-u-boot.dtsi   | 17 +
 arch/arm/dts/dra71-evm-u-boot.dtsi  | 17 +
 arch/arm/dts/dra72-evm-revc-u-boot.dtsi | 17 +
 arch/arm/dts/dra72-evm-u-boot.dtsi  | 23 +++
 arch/arm/dts/dra76-evm-u-boot.dtsi  | 17 +
 arch/arm/dts/omap5-u-boot.dtsi  |  1 +
 configs/dra7xx_evm_defconfig|  8 +++-
 configs/dra7xx_hs_evm_defconfig |  8 +++-
 8 files changed, 106 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/dts/dra72-evm-u-boot.dtsi

-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 1/3] ARM: dts: dra7: Add usb peripheral nodes in spl

2019-09-24 Thread Jean-Jacques Hiblot
From: Faiz Abbas 

Add usb peripheral and usb phy nodes in spl to enable SPL_DFU bootmode.

Signed-off-by: Faiz Abbas 
Signed-off-by: Jean-Jacques Hiblot 
---

 arch/arm/dts/dra7-evm-u-boot.dtsi   | 17 +
 arch/arm/dts/dra71-evm-u-boot.dtsi  | 17 +
 arch/arm/dts/dra72-evm-revc-u-boot.dtsi | 17 +
 arch/arm/dts/dra72-evm-u-boot.dtsi  | 23 +++
 arch/arm/dts/dra76-evm-u-boot.dtsi  | 17 +
 arch/arm/dts/omap5-u-boot.dtsi  |  1 +
 6 files changed, 92 insertions(+)
 create mode 100644 arch/arm/dts/dra72-evm-u-boot.dtsi

diff --git a/arch/arm/dts/dra7-evm-u-boot.dtsi 
b/arch/arm/dts/dra7-evm-u-boot.dtsi
index badaebc76f..f06c701dbd 100644
--- a/arch/arm/dts/dra7-evm-u-boot.dtsi
+++ b/arch/arm/dts/dra7-evm-u-boot.dtsi
@@ -32,3 +32,20 @@
 _iodelay_hs200_rev20_conf {
u-boot,dm-spl;
 };
+
+_dwc3_1 {
+   u-boot,dm-spl;
+};
+
+ {
+   u-boot,dm-spl;
+   dr_mode = "peripheral";
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/dra71-evm-u-boot.dtsi 
b/arch/arm/dts/dra71-evm-u-boot.dtsi
index f9da15f1c7..b56d4fc9d8 100644
--- a/arch/arm/dts/dra71-evm-u-boot.dtsi
+++ b/arch/arm/dts/dra71-evm-u-boot.dtsi
@@ -44,3 +44,20 @@
 _iodelay_hs200_rev20_conf {
u-boot,dm-spl;
 };
+
+_dwc3_1 {
+   u-boot,dm-spl;
+};
+
+ {
+   u-boot,dm-spl;
+   dr_mode = "peripheral";
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/dra72-evm-revc-u-boot.dtsi 
b/arch/arm/dts/dra72-evm-revc-u-boot.dtsi
index f9da15f1c7..b56d4fc9d8 100644
--- a/arch/arm/dts/dra72-evm-revc-u-boot.dtsi
+++ b/arch/arm/dts/dra72-evm-revc-u-boot.dtsi
@@ -44,3 +44,20 @@
 _iodelay_hs200_rev20_conf {
u-boot,dm-spl;
 };
+
+_dwc3_1 {
+   u-boot,dm-spl;
+};
+
+ {
+   u-boot,dm-spl;
+   dr_mode = "peripheral";
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/dra72-evm-u-boot.dtsi 
b/arch/arm/dts/dra72-evm-u-boot.dtsi
new file mode 100644
index 00..6c868f75d1
--- /dev/null
+++ b/arch/arm/dts/dra72-evm-u-boot.dtsi
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include "omap5-u-boot.dtsi"
+
+_dwc3_1 {
+   u-boot,dm-spl;
+};
+
+ {
+   u-boot,dm-spl;
+   dr_mode = "peripheral";
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/dra76-evm-u-boot.dtsi 
b/arch/arm/dts/dra76-evm-u-boot.dtsi
index f651f404e0..a4dfbe7e60 100644
--- a/arch/arm/dts/dra76-evm-u-boot.dtsi
+++ b/arch/arm/dts/dra76-evm-u-boot.dtsi
@@ -24,3 +24,20 @@
 _iodelay_hs200_conf {
u-boot,dm-spl;
 };
+
+_dwc3_1 {
+   u-boot,dm-spl;
+};
+
+ {
+   u-boot,dm-spl;
+   dr_mode = "peripheral";
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
+
+_phy1 {
+   u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/omap5-u-boot.dtsi b/arch/arm/dts/omap5-u-boot.dtsi
index 1b1d765fae..39071e223d 100644
--- a/arch/arm/dts/omap5-u-boot.dtsi
+++ b/arch/arm/dts/omap5-u-boot.dtsi
@@ -22,6 +22,7 @@
 
ocp2scp@4a08 {
compatible = "ti,omap-ocp2scp", "simple-bus";
+   u-boot,dm-spl;
};
 
ocp2scp@4a09 {
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 3/3] configs: dra7xx_evm: Increase the size of SPL_MULTI_DTB_FIT

2019-09-24 Thread Jean-Jacques Hiblot
From: Faiz Abbas 

Expand SPL_MULTI_DTB_FIT to accommodate usb peripheral nodes being
added to support SPL_DFU bootmode.

Signed-off-by: Faiz Abbas 

Signed-off-by: Jean-Jacques Hiblot 
---

 configs/dra7xx_evm_defconfig| 2 +-
 configs/dra7xx_hs_evm_defconfig | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/configs/dra7xx_evm_defconfig b/configs/dra7xx_evm_defconfig
index 15dd0e879d..57a542db88 100644
--- a/configs/dra7xx_evm_defconfig
+++ b/configs/dra7xx_evm_defconfig
@@ -42,7 +42,7 @@ CONFIG_SPL_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="dra7-evm"
 CONFIG_OF_LIST="dra7-evm dra72-evm dra72-evm-revc dra71-evm dra76-evm"
 CONFIG_SPL_MULTI_DTB_FIT=y
-CONFIG_SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ=0x9000
+CONFIG_SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ=0xA000
 CONFIG_OF_SPL_REMOVE_PROPS="clocks clock-names interrupt-parent"
 # CONFIG_ENV_IS_IN_FAT is not set
 CONFIG_ENV_IS_IN_MMC=y
diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig
index e2f0476f9e..ca904d8d2d 100644
--- a/configs/dra7xx_hs_evm_defconfig
+++ b/configs/dra7xx_hs_evm_defconfig
@@ -45,7 +45,7 @@ CONFIG_SPL_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="dra7-evm"
 CONFIG_OF_LIST="dra7-evm dra72-evm dra72-evm-revc dra71-evm dra76-evm"
 CONFIG_SPL_MULTI_DTB_FIT=y
-CONFIG_SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ=0x9000
+CONFIG_SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ=0xA000
 CONFIG_OF_SPL_REMOVE_PROPS="clocks clock-names interrupt-parent"
 # CONFIG_ENV_IS_IN_FAT is not set
 CONFIG_ENV_IS_IN_MMC=y
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1 2/3] configs: dra7xx_evm: Add Kconfigs for SPL_DFU bootmode

2019-09-24 Thread Jean-Jacques Hiblot
From: Faiz Abbas 

Enable configs for supporting SPL_DFU bootmode.

Signed-off-by: Faiz Abbas 
Signed-off-by: Jean-Jacques Hiblot 
---

 configs/dra7xx_evm_defconfig| 6 ++
 configs/dra7xx_hs_evm_defconfig | 6 ++
 2 files changed, 12 insertions(+)

diff --git a/configs/dra7xx_evm_defconfig b/configs/dra7xx_evm_defconfig
index ad8868e512..15dd0e879d 100644
--- a/configs/dra7xx_evm_defconfig
+++ b/configs/dra7xx_evm_defconfig
@@ -25,8 +25,11 @@ CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_SPL_DMA_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
+CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_SPI_LOAD=y
 CONFIG_SYS_SPI_U_BOOT_OFFS=0x4
+CONFIG_SPL_USB_GADGET=y
+CONFIG_SPL_DFU=y
 CONFIG_CMD_SPL=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_NAND=y
@@ -85,6 +88,7 @@ CONFIG_MII=y
 CONFIG_DRIVER_TI_CPSW=y
 CONFIG_SPL_PHY=y
 CONFIG_PIPE3_PHY=y
+CONFIG_SPL_PIPE3_PHY=y
 CONFIG_OMAP_USB2_PHY=y
 CONFIG_PMIC_PALMAS=y
 CONFIG_PMIC_LP873X=y
@@ -107,7 +111,9 @@ CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GADGET=y
+CONFIG_USB_DWC3_OMAP=y
 CONFIG_USB_DWC3_GENERIC=y
+CONFIG_USB_DWC3_PHY_OMAP=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
 CONFIG_USB_GADGET_VENDOR_NUM=0x0451
diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig
index 7a5c3e72d4..e2f0476f9e 100644
--- a/configs/dra7xx_hs_evm_defconfig
+++ b/configs/dra7xx_hs_evm_defconfig
@@ -30,8 +30,11 @@ CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_SPL_DMA_SUPPORT=y
 # CONFIG_SPL_NAND_SUPPORT is not set
+CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_SPI_LOAD=y
 CONFIG_SYS_SPI_U_BOOT_OFFS=0x4
+CONFIG_SPL_USB_GADGET=y
+CONFIG_SPL_DFU=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_NAND=y
 CONFIG_CMD_MTDPARTS=y
@@ -88,6 +91,7 @@ CONFIG_MII=y
 CONFIG_DRIVER_TI_CPSW=y
 CONFIG_SPL_PHY=y
 CONFIG_PIPE3_PHY=y
+CONFIG_SPL_PIPE3_PHY=y
 CONFIG_OMAP_USB2_PHY=y
 CONFIG_PMIC_PALMAS=y
 CONFIG_PMIC_LP873X=y
@@ -110,7 +114,9 @@ CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GADGET=y
+CONFIG_USB_DWC3_OMAP=y
 CONFIG_USB_DWC3_GENERIC=y
+CONFIG_USB_DWC3_PHY_OMAP=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
 CONFIG_USB_GADGET_VENDOR_NUM=0x0451
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] FDT: alignment of 64-bits integers

2019-09-20 Thread Jean-Jacques Hiblot

Hi Simon,

while working with the FDT in the SPL, I came across an alignment issue. 
I have seen 64-bits integers not aligned on a 64-bit boundary, although 
is doesn't happen very often. According to the FDT spec, the requirement 
is to be aligned on 32-bits, so it is OK.


However on ARM64, until the cache is enabled, it is not possible to 
access 64-bits integers not aligned on a 64-bits boundary. This issue 
has been discussed here : 
http://u-boot.10912.n7.nabble.com/memcpy-memset-on-arm64-platforms-td353928.html#a354348


I have a patch for this but I am not sure, this is the right approach:

diff --git a/include/linux/libfdt_env.h b/include/linux/libfdt_env.h
index e2bf79c7ee..b6b7176a8a 100644
--- a/include/linux/libfdt_env.h
+++ b/include/linux/libfdt_env.h
@@ -15,7 +15,7 @@

 typedef __be16 fdt16_t;
 typedef __be32 fdt32_t;
-typedef __be64 fdt64_t;
+typedef __be64 fdt64_t __aligned(4);

The trouble with this patch is that for every fdt64_t the access will be 
aligned on 32-bits, inducing an overall performance penalty.


 The other approach will be to fix the problem where it happens. So far 
I had the issue only ofnode_read_u64() because that is what the driver I 
worked with is using.


What do you think?


Thanks,

JJ




___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v5 00/15] Add support for applications of overlays in SPL

2019-09-20 Thread Jean-Jacques Hiblot
The purpose of this series is to provide the SPL with ability to apply
overlays for u-boot.

Our use-case is the support of the daughter boards of the AM65x EVM. In
Linux, each board is supported by a unique overlay. The presence of the
boards is detected at runtime, and some useful features (like USB) are
implemented on those daughter boards. Instead of providing multiple dtbs
and fall in a combinatorial pit, we propose to use DT overlays.

Patch #2 "spl: fit: Add support for applying DT overlay" has been posted
a few weeks ago by Michal Simek.
Patch #3 to #6 amend Michal's patch.
Patch #7 to #9 are simple fixes for the Makefile
Patch #10 is used to reduce the complexity of the Makefile by having FIT
generator scripts provide their dependencies
Patch #12-#13 allow to use the board driver in SPL
Patch #14-#15 adds a way to dynamically select the DT overlays. That is
were we would use HW detection to select the required overlays. In that
case, the board driver code tells what overlay it needs (it gives the
name of the node).

On arm, if overlay are supported, this series increases the size of the SPL
by 3.2 kB.

Travis build : https://travis-ci.org/jjhiblot/u-boot/builds/567779404

Changes in v5:
- Do not allocate the buffer if not needed (no overlay).
- Add a Kconfig option for the buffer size
- board_get_fit_loadable() returns an error code instead of a NULL string
  in case of failure
- reword some commit logs

Changes in v4:
- use CONFIG_IS_ENABLED() instead of #idef
- make sure that the temp buffer is freed in all cases
- Use the board driver infrastructure to get the image names from the
board code.
- Remove a patch that passed the board name to the FIT generator. If needed
the generator can get it from elsewhere
- Add a fix to not load the firmware twice (once as a firmware and once as
a loadable)

Changes in v3:
- Add a new config option: SPL_LOAD_FIT_APPLY_OVERLAY. By default, it is
not selected.
- removed the RFC prefix. This work will be needed soon by TI's AM65x
platform. and can probably benefit other modular platforms
- removed the last patch that provided an example of how to use this with
on a DRA76.
- removed the patch that made u-boot.img a symlink to u-boot.itb because
it breaks the build of many platforms (because files required to build the
ITB are missing)
- removed the patch to reduce the footprint of the am335x SPL. (already
merged)
- Made the boot flow more permissive (don't fail immediately if an overlay
is not present) and more verbose when an error occures
- handle the dependencies of the FIT generation in a more generic way
- use a dedicated kconfig option to enable the application of the overlays
by the SPL.

Changes in v2:
- depend on SPL_DM
- update the commit log
- reworked board_fit_get_additionnal_images() and how it used in spl_fit.c
- removed dtbo generation from dtso files and use .dts extension for the
  overlays
- add dynamic allocation usage in a separate patch
- defconfig change for the am335x_evm

Jean-Jacques Hiblot (14):
  spl: fit: don't load the firmware twice
  spl: fit: Make room in the FDT before applying overlays
  spl: fit: allocate a temporary buffer to load the overlays
  spl: fit: Do not fail immediately if an overlay is not available
  spl: fit: be more verbose when an error occurs when applying the
overlays
  Makefile.lib: include /__symbols__ in dtb if
SPL_LOAD_FIT_APPLY_OVERLAY is enabled
  Makefile: Fix tests for CONFIG_SPL_LOAD_FIT and
CONFIG_SPL_FIT_GENERATOR
  Makefile: Fix u-boot.itb generation when building outside the source
tree
  Makefile: Query the SPL Fit Generator for its dependencies
  spl: fit: constify the output parameter of spl_fit_get_image_name()
  drivers: board: Make the board drivers available in SPL
  drivers: board: Add get_fit_loadable()
  include: board: provide empty stubs when the BOARD option is not
selected
  spl: fit: Allow the board to tell if more images must be loaded from
FIT

Michal Simek (1):
  spl: fit: Add support for applying DT overlay

 Kconfig   |  18 +++
 Makefile  |  23 ++--
 arch/arm/mach-imx/mkimage_fit_atf.sh  |   5 +
 arch/arm/mach-rockchip/make_fit_atf.py|   7 ++
 board/sunxi/mksunxi_fit_atf.sh|   4 +
 .../lion_rk3368/fit_spl_atf.its   |   6 +-
 .../puma_rk3399/fit_spl_atf.sh|   6 +
 common/spl/spl_fit.c  | 113 --
 drivers/Makefile  |   2 +-
 drivers/board/Kconfig |   3 +
 drivers/board/Makefile|   2 +-
 drivers/board/board-uclass.c  |  11 ++
 include/board.h   |  74 
 scripts/Makefile.lib  |   4 +
 14 files changed, 251 insertions(+), 27 deletions(-)

-- 
2.17.1

___
U-Boot mailing list
U-Boot@lis

[U-Boot] [PATCH v5 15/15] spl: fit: Allow the board to tell if more images must be loaded from FIT

2019-09-20 Thread Jean-Jacques Hiblot
spl_fit_get_image_name() is used to get the names of the images that the
SPL must load from the FIT. It relies on the content of a property present
in the FIT. The list of images is thus statically defined in the FIT.
With this scheme, it quickly becomes hard to manage combinations of more
than a handful of images.
To address this problem, give the board driver code the opportunity to
add to the list of images. The images from the FIT property are loaded
first, and then the board_get_fit_loadable() is called to get more image
names.

Signed-off-by: Jean-Jacques Hiblot 

---

Changes in v5:
- reword commit log

Changes in v4:
- Use the board driver infrastructure to get the image names from the
board code.
- Remove a patch that passed the board name to the FIT generator. If needed
the generator can get it from elsewhere
- Add a fix to not load the firmware twice (once as a firmware and once as
a loadable)

Changes in v3:
- removed the RFC prefix. This work will be needed soon by TI's AM65x
platform. and can probably benefit other modular platforms
- removed the last patch that provided an example of how to use this with
on a DRA76.
- removed the patch that made u-boot.img a symlink to u-boot.itb because
it breaks the build of many platforms (because files required to build the
ITB are missing)
- removed the patch to reduce the footprint of the am335x SPL. (already
merged)
- Made the boot flow more permissive (don't fail immediately if an overlay
is not present) and more verbose when an error occures
- handle the dependencies of the FIT generation in a more generic way
- use a dedicated kconfig option to enable the application of the overlays
by the SPL.

Changes in v2:
- reworked board_fit_get_additionnal_images() and how it used in spl_fit.c
- removed dtbo generation from dtso files and use .dts extension for the
  overlays
- add dynamic allocation usage in a separate patch
- defconfig change for the am335x_evm

 common/spl/spl_fit.c | 27 ---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index d761cd821f..af8096988f 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -6,6 +6,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -48,10 +49,12 @@ static int spl_fit_get_image_name(const void *fit, int 
images,
  const char *type, int index,
  const char **outname)
 {
+   struct udevice *board;
const char *name, *str;
__maybe_unused int node;
int conf_node;
int len, i;
+   bool found = true;
 
conf_node = fit_find_config_node(fit);
if (conf_node < 0) {
@@ -77,12 +80,30 @@ static int spl_fit_get_image_name(const void *fit, int 
images,
for (i = 0; i < index; i++) {
str = strchr(str, '\0') + 1;
if (!str || (str - name >= len)) {
-   debug("no string for index %d\n", index);
-   return -E2BIG;
+   found = false;
+   break;
}
}
 
-   *outname = (char *)str;
+   if (!found && !board_get()) {
+   int rc;
+   /*
+* no string in the property for this index. Check if the board
+* level code can supply one.
+*/
+   rc = board_get_fit_loadable(board, index - i - 1, type, );
+   if (rc && rc != -ENOENT)
+   return rc;
+   if (!rc)
+   found = true;
+   }
+
+   if (!found) {
+   debug("no string for index %d\n", index);
+   return -E2BIG;
+   }
+
+   *outname = str;
return 0;
 }
 
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v5 07/15] Makefile.lib: include /__symbols__ in dtb if SPL_LOAD_FIT_APPLY_OVERLAY is enabled

2019-09-20 Thread Jean-Jacques Hiblot
In order to apply an overlay to a DTB. The DTB must have been generated
with the option '-@'.

Signed-off-by: Jean-Jacques Hiblot 
Reviewed-by: Simon Glass 
---

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 scripts/Makefile.lib | 4 
 1 file changed, 4 insertions(+)

diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index ef116e0e0a..6946da6aa4 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -292,6 +292,10 @@ cmd_dt_S_dtb=  
\
 $(obj)/%.dtb.S: $(obj)/%.dtb
$(call cmd,dt_S_dtb)
 
+ifeq ($(CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY),y)
+DTC_FLAGS += -@
+endif
+
 quiet_cmd_dtc = DTC $@
 # Modified for U-Boot
 # Bring in any U-Boot-specific include at the end of the file
-- 
2.17.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


  1   2   3   4   5   6   7   8   9   10   >