[PATCH v1 0/2] Introduce Meson SM driver

2023-07-06 Thread Alexey Romanov
Hello!

This patchset adds Meson Secure Monitor driver, which export following
generic API:

- sm_call_read()
- sm_call_write()
- sm_call()

Also, now use this new API in arch/arm/mach-meson/sm.c helper functions.

Alexey Romanov (2):
  drivers: firmware: introduce Meson Secure Monitor driver
  asm/arch: mach-meson: use secure monitor driver

 arch/arm/mach-meson/Kconfig   |   1 +
 arch/arm/mach-meson/sm.c  | 161 +-
 drivers/firmware/Kconfig  |  10 ++
 drivers/firmware/Makefile |   1 +
 drivers/firmware/meson/Kconfig|   6 +
 drivers/firmware/meson/Makefile   |   3 +
 drivers/firmware/meson/meson_sm.c | 217 ++
 include/meson/sm_handle.h |  38 ++
 8 files changed, 373 insertions(+), 64 deletions(-)
 create mode 100644 drivers/firmware/meson/Kconfig
 create mode 100644 drivers/firmware/meson/Makefile
 create mode 100644 drivers/firmware/meson/meson_sm.c
 create mode 100644 include/meson/sm_handle.h

-- 
2.38.1



[PATCH v1 1/2] drivers: firmware: introduce Meson Secure Monitor driver

2023-07-06 Thread Alexey Romanov
At the moment, only smc API is a set of functions in
arch/arm/mach-meson/sm.c. This approach is hard to configure
and also doesn't contain any generic API for calling smc.

This patch add Meson SM driver with generic API (struct meson_sm_ops):

- sm_call()
- sm_call_write()
- sm_call_read()

A typical driver usage example is shown here:

1. uclass_get_device_by_driver(UCLASS_FIRMWARE, "secure-monitor", &dev);
2. handle = meson_sm_get_handle(dev);
3. handle->ops.sm_call(dev, cmd, ...);

Signed-off-by: Alexey Romanov 
---
 arch/arm/mach-meson/Kconfig   |   1 +
 drivers/firmware/Kconfig  |  10 ++
 drivers/firmware/Makefile |   1 +
 drivers/firmware/meson/Kconfig|   6 +
 drivers/firmware/meson/Makefile   |   3 +
 drivers/firmware/meson/meson_sm.c | 217 ++
 include/meson/sm_handle.h |  38 ++
 7 files changed, 276 insertions(+)
 create mode 100644 drivers/firmware/meson/Kconfig
 create mode 100644 drivers/firmware/meson/Makefile
 create mode 100644 drivers/firmware/meson/meson_sm.c
 create mode 100644 include/meson/sm_handle.h

diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig
index 669ca09a00a..b8746d27f63 100644
--- a/arch/arm/mach-meson/Kconfig
+++ b/arch/arm/mach-meson/Kconfig
@@ -11,6 +11,7 @@ config MESON64_COMMON
select PWRSEQ
select MMC_PWRSEQ
select BOARD_LATE_INIT
+   select MESON_FIRMWARE
imply CMD_DM
 
 config MESON_GX
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index eae1c8ddc9f..17b70fdea6d 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -37,6 +37,15 @@ config ZYNQMP_FIRMWARE
  Say yes to enable ZynqMP firmware interface driver.
  If in doubt, say N.
 
+config MESON_FIRMWARE
+   bool "Meson Firmware interface"
+   select FIRMWARE
+   help
+ This option enables Meson firmware interface,
+ which is used by different drivers to communicate
+ with the firmware for various platform management
+ services.
+
 config ARM_SMCCC_FEATURES
bool "Arm SMCCC features discovery"
depends on ARM_PSCI_FW
@@ -45,4 +54,5 @@ config ARM_SMCCC_FEATURES
  the PSCI driver is always probed and binds dirvers registered to the 
Arm SMCCC
  services if any and reported as supported by the SMCCC firmware.
 
+source "drivers/firmware/meson/Kconfig"
 source "drivers/firmware/scmi/Kconfig"
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 7ce83d72bd3..a6300be27ad 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_TI_SCI_PROTOCOL)   += ti_sci.o
 obj-$(CONFIG_SANDBOX)  += firmware-sandbox.o
 obj-$(CONFIG_ZYNQMP_FIRMWARE)  += firmware-zynqmp.o
 obj-$(CONFIG_SCMI_FIRMWARE)+= scmi/
+obj-$(CONFIG_MESON_FIRMWARE)   += meson/
diff --git a/drivers/firmware/meson/Kconfig b/drivers/firmware/meson/Kconfig
new file mode 100644
index 000..0fd4f3251e1
--- /dev/null
+++ b/drivers/firmware/meson/Kconfig
@@ -0,0 +1,6 @@
+config MESON_SM
+   bool "Amlogic Secure Monitor driver"
+   depends on ARCH_MESON
+   default y
+   help
+ Say y here to enable the Amlogic secure monitor driver.
diff --git a/drivers/firmware/meson/Makefile b/drivers/firmware/meson/Makefile
new file mode 100644
index 000..b5d26f150b0
--- /dev/null
+++ b/drivers/firmware/meson/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_MESON_SM) +=  meson_sm.o
diff --git a/drivers/firmware/meson/meson_sm.c 
b/drivers/firmware/meson/meson_sm.c
new file mode 100644
index 000..28eacb89810
--- /dev/null
+++ b/drivers/firmware/meson/meson_sm.c
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct meson_sm_cmd {
+   u32 smc_id;
+};
+
+#define SET_CMD(index, id) \
+   [index] = { \
+   .smc_id = id,   \
+   }
+
+struct meson_sm_data {
+   u32 cmd_get_shmem_in;
+   u32 cmd_get_shmem_out;
+   unsigned int shmem_size;
+   struct meson_sm_cmd cmd[];
+};
+
+struct meson_sm_priv {
+   void *sm_shmem_in;
+   void *sm_shmem_out;
+   struct meson_sm_handle handle;
+   const struct meson_sm_data *data;
+};
+
+static unsigned long __meson_sm_call(u32 cmd, u32 arg0, u32 arg1, u32 arg2,
+   u32 arg3, u32 arg4)
+{
+   struct pt_regs r;
+
+   r.regs[0] = cmd;
+   r.regs[1] = arg0;
+   r.regs[2] = arg1;
+   r.regs[3] = arg2;
+   r.regs[4] = arg3;
+   r.regs[5] = arg4;
+
+   smc_call(&r);
+
+   return r.regs[0];
+};
+
+static u32 meson_sm_get_cmd(const struct meson_sm_data *data,
+

[PATCH v1 2/2] asm/arch: mach-meson: use secure monitor driver

2023-07-06 Thread Alexey Romanov
Now we have to use UCLASS_FIRMWARE meson secure monitor driver
instead of raw smc_call() function call.

Signed-off-by: Alexey Romanov 
---
 arch/arm/mach-meson/sm.c | 161 +++
 1 file changed, 97 insertions(+), 64 deletions(-)

diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c
index d600c64d0be..347ff448f79 100644
--- a/arch/arm/mach-meson/sm.c
+++ b/arch/arm/mach-meson/sm.c
@@ -16,72 +16,74 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
-#define FN_GET_SHARE_MEM_INPUT_BASE0x8220
-#define FN_GET_SHARE_MEM_OUTPUT_BASE   0x8221
-#define FN_EFUSE_READ  0x8230
-#define FN_EFUSE_WRITE 0x8231
-#define FN_CHIP_ID 0x8244
-#define FN_PWRDM_SET   0x8293
-
-static void *shmem_input;
-static void *shmem_output;
-
-static void meson_init_shmem(void)
+static inline struct udevice *meson_get_sm_device(void)
 {
-   struct pt_regs regs;
-
-   if (shmem_input && shmem_output)
-   return;
+   struct udevice *dev;
+   int err;
 
-   regs.regs[0] = FN_GET_SHARE_MEM_INPUT_BASE;
-   smc_call(®s);
-   shmem_input = (void *)regs.regs[0];
-
-   regs.regs[0] = FN_GET_SHARE_MEM_OUTPUT_BASE;
-   smc_call(®s);
-   shmem_output = (void *)regs.regs[0];
+   err = uclass_get_device_by_name(UCLASS_FIRMWARE, "secure-monitor", 
&dev);
+   if (err) {
+   pr_err("Mesom SM device not found\n");
+   return ERR_PTR(err);
+   }
 
-   debug("Secure Monitor shmem: 0x%p 0x%p\n", shmem_input, shmem_output);
+   return dev;
 }
 
 ssize_t meson_sm_read_efuse(uintptr_t offset, void *buffer, size_t size)
 {
-   struct pt_regs regs;
-
-   meson_init_shmem();
-
-   regs.regs[0] = FN_EFUSE_READ;
-   regs.regs[1] = offset;
-   regs.regs[2] = size;
-
-   smc_call(®s);
-
-   if (regs.regs[0] == 0)
-   return -1;
+   struct meson_sm_handle *handle;
+   struct udevice *dev;
+   int err;
+
+   dev = meson_get_sm_device();
+   if (IS_ERR(dev))
+   return PTR_ERR(dev);
+
+   handle = meson_sm_get_handle(dev);
+   if (IS_ERR(handle)) {
+   pr_err("Failed to get Meson SM handle\n");
+   return PTR_ERR(handle);
+   }
 
-   memcpy(buffer, shmem_output, min(size, regs.regs[0]));
+   err = handle->ops.sm_call_read(dev, buffer, size,
+   MESON_SMC_CMD_EFUSE_READ, offset, size);
+   if (err < 0) {
+   pr_err("Failed to read efuse memory (%d)\n", err);
+   return err;
+   }
 
-   return regs.regs[0];
+   return err;
 }
 
 ssize_t meson_sm_write_efuse(uintptr_t offset, void *buffer, size_t size)
 {
-   struct pt_regs regs;
-
-   meson_init_shmem();
-
-memcpy(shmem_input, buffer, size);
-
-   regs.regs[0] = FN_EFUSE_WRITE;
-   regs.regs[1] = offset;
-   regs.regs[2] = size;
+   struct meson_sm_handle *handle;
+   struct udevice *dev;
+   int err;
+
+   dev = meson_get_sm_device();
+   if (IS_ERR(dev))
+   return PTR_ERR(dev);
+
+   handle = meson_sm_get_handle(dev);
+   if (IS_ERR(handle)) {
+   pr_err("Failed to get Meson SM handle\n");
+   return PTR_ERR(handle);
+   }
 
-   smc_call(®s);
+   err = handle->ops.sm_call_write(dev, buffer, size,
+   MESON_SMC_CMD_EFUSE_WRITE, offset, size);
+   if (err < 0) {
+   pr_err("Failed to write efuse memory (%d)\n", err);
+   return err;
+   }
 
-   return regs.regs[0];
+   return err;
 }
 
 #define SM_CHIP_ID_LENGTH  119
@@ -90,18 +92,35 @@ ssize_t meson_sm_write_efuse(uintptr_t offset, void 
*buffer, size_t size)
 
 int meson_sm_get_serial(void *buffer, size_t size)
 {
-   struct pt_regs regs;
-
-   meson_init_shmem();
+   struct meson_sm_handle *handle;
+   struct udevice *dev;
+   u8 *id_buffer;
+   int err;
+
+   dev = meson_get_sm_device();
+   if (IS_ERR(dev))
+   return PTR_ERR(dev);
+
+   handle = meson_sm_get_handle(dev);
+   if (IS_ERR(handle)) {
+   pr_err("Failed to get Meson SM handle\n");
+   return PTR_ERR(handle);
+   }
 
-   regs.regs[0] = FN_CHIP_ID;
-   regs.regs[1] = 0;
-   regs.regs[2] = 0;
+   id_buffer = malloc(sizeof(u8) * SM_CHIP_ID_LENGTH);
+   if (!id_buffer)
+   return -ENOMEM;
 
-   smc_call(®s);
+   err = handle->ops.sm_call_read(dev, id_buffer, SM_CHIP_ID_LENGTH,
+   MESON_SMC_CMD_CHIP_ID_GET, 0, 0);
+   if (err < 0) {
+   pr_err("Failed to read serial number (%d)\n", err);
+   free(id_buffer);
+   return err;

Re: [PATCH v1 1/2] drivers: firmware: introduce Meson Secure Monitor driver

2023-07-07 Thread Alexey Romanov
Hello, Simon!

On Thu, Jul 06, 2023 at 09:58:02AM -0600, Simon Glass wrote:
> Hi Alexey,
> 
> On Thu, 6 Jul 2023 at 14:16, Alexey Romanov  wrote:
> >
> > At the moment, only smc API is a set of functions in
> > arch/arm/mach-meson/sm.c. This approach is hard to configure
> > and also doesni't contain any generic API for calling smc.
> >
> > This patch add Meson SM driver with generic API (struct meson_sm_ops):
> >
> > - sm_call()
> > - sm_call_write()
> > - sm_call_read()
> >
> > A typical driver usage example is shown here:
> >
> > 1. uclass_get_device_by_driver(UCLASS_FIRMWARE, "secure-monitor", &dev);
> > 2. handle = meson_sm_get_handle(dev);
> > 3. handle->ops.sm_call(dev, cmd, ...);
> >
> > Signed-off-by: Alexey Romanov 
> > ---
> >  arch/arm/mach-meson/Kconfig   |   1 +
> >  drivers/firmware/Kconfig  |  10 ++
> >  drivers/firmware/Makefile |   1 +
> >  drivers/firmware/meson/Kconfig|   6 +
> >  drivers/firmware/meson/Makefile   |   3 +
> >  drivers/firmware/meson/meson_sm.c | 217 ++
> >  include/meson/sm_handle.h |  38 ++
> >  7 files changed, 276 insertions(+)
> >  create mode 100644 drivers/firmware/meson/Kconfig
> >  create mode 100644 drivers/firmware/meson/Makefile
> >  create mode 100644 drivers/firmware/meson/meson_sm.c
> >  create mode 100644 include/meson/sm_handle.h
> 
> Please can you use the remoteproc uclass for this and add a proper driver?
> 

I don't see it architecturally well. Can you explain please?

This driver is just ARM SMC fw interface. There seems to be nothing to
do here for remoteproc uclass. 

> Regards,
> SImon

-- 
Thank you,
Alexey

Re: [PATCH v1 1/2] drivers: firmware: introduce Meson Secure Monitor driver

2023-07-10 Thread Alexey Romanov


Hello!

On Fri, Jul 07, 2023 at 11:35:47AM -0600, Simon Glass wrote:
> Hi Alexey,
> 
> On Fri, 7 Jul 2023 at 09:43, Alexey Romanov  wrote:
> >
> > Hello, Simon!
> >
> > On Thu, Jul 06, 2023 at 09:58:02AM -0600, Simon Glass wrote:
> > > Hi Alexey,
> > >
> > > On Thu, 6 Jul 2023 at 14:16, Alexey Romanov  
> > > wrote:
> > > >
> > > > At the moment, only smc API is a set of functions in
> > > > arch/arm/mach-meson/sm.c. This approach is hard to configure
> > > > and also doesni't contain any generic API for calling smc.
> > > >
> > > > This patch add Meson SM driver with generic API (struct meson_sm_ops):
> > > >
> > > > - sm_call()
> > > > - sm_call_write()
> > > > - sm_call_read()
> > > >
> > > > A typical driver usage example is shown here:
> > > >
> > > > 1. uclass_get_device_by_driver(UCLASS_FIRMWARE, "secure-monitor", &dev);
> > > > 2. handle = meson_sm_get_handle(dev);
> > > > 3. handle->ops.sm_call(dev, cmd, ...);
> > > >
> > > > Signed-off-by: Alexey Romanov 
> > > > ---
> > > >  arch/arm/mach-meson/Kconfig   |   1 +
> > > >  drivers/firmware/Kconfig  |  10 ++
> > > >  drivers/firmware/Makefile |   1 +
> > > >  drivers/firmware/meson/Kconfig|   6 +
> > > >  drivers/firmware/meson/Makefile   |   3 +
> > > >  drivers/firmware/meson/meson_sm.c | 217 ++
> > > >  include/meson/sm_handle.h |  38 ++
> > > >  7 files changed, 276 insertions(+)
> > > >  create mode 100644 drivers/firmware/meson/Kconfig
> > > >  create mode 100644 drivers/firmware/meson/Makefile
> > > >  create mode 100644 drivers/firmware/meson/meson_sm.c
> > > >  create mode 100644 include/meson/sm_handle.h
> > >
> > > Please can you use the remoteproc uclass for this and add a proper driver?
> > >
> >
> > I don't see it architecturally well. Can you explain please?
> >
> > This driver is just ARM SMC fw interface. There seems to be nothing to
> > do here for remoteproc uclass.
> 
> Well you seem to be implementing a remote CPU interface, which is what
> remoteproc is for. How does Linux do this?

The main idea of the patchset is to abstract the smc calls (which run on
the same CPU) and make a request to the firmware that runs on a higher
EL. UCLASS_REMOTEPROC may give the impression that we are
interacting with another CPU, although this is not the case.

Also, UCLASS_REMOTEPROC requires two mandatory interfaces: load() and
start(), and I don't even know how to apply my current changes to them.

My implementation is very close to the Linux implementation, they
also use the firmware driver without remoteproc:

https://elixir.bootlin.com/linux/latest/source/drivers/firmware/meson/meson_sm.c

I spoke to Neil on IRC and he said UCLASS_FIRMWARE for such driver is
OK.

> 
> Also there is a pending series on FFA - is that related? It uses smc
> from what I can tell.

Not entirely clear, my changes don't seem to be related to this
patchset.

> 
> Regards,
> Simon

-- 
Thank you,
Alexey

Re: [PATCH v1 1/2] drivers: firmware: introduce Meson Secure Monitor driver

2023-07-11 Thread Alexey Romanov
Hi Simon,

On Mon, Jul 10, 2023 at 01:45:53PM -0600, Simon Glass wrote:
> Hi Alexey,
> 
> On Mon, 10 Jul 2023 at 02:34, Alexey Romanov  wrote:
> >
> >
> > Hello!
> >
> > On Fri, Jul 07, 2023 at 11:35:47AM -0600, Simon Glass wrote:
> > > Hi Alexey,
> > >
> > > On Fri, 7 Jul 2023 at 09:43, Alexey Romanov  
> > > wrote:
> > > >
> > > > Hello, Simon!
> > > >
> > > > On Thu, Jul 06, 2023 at 09:58:02AM -0600, Simon Glass wrote:
> > > > > Hi Alexey,
> > > > >
> > > > > On Thu, 6 Jul 2023 at 14:16, Alexey Romanov 
> > > > >  wrote:
> > > > > >
> > > > > > At the moment, only smc API is a set of functions in
> > > > > > arch/arm/mach-meson/sm.c. This approach is hard to configure
> > > > > > and also doesni't contain any generic API for calling smc.
> > > > > >
> > > > > > This patch add Meson SM driver with generic API (struct 
> > > > > > meson_sm_ops):
> > > > > >
> > > > > > - sm_call()
> > > > > > - sm_call_write()
> > > > > > - sm_call_read()
> > > > > >
> > > > > > A typical driver usage example is shown here:
> > > > > >
> > > > > > 1. uclass_get_device_by_driver(UCLASS_FIRMWARE, "secure-monitor", 
> > > > > > &dev);
> > > > > > 2. handle = meson_sm_get_handle(dev);
> > > > > > 3. handle->ops.sm_call(dev, cmd, ...);
> > > > > >
> > > > > > Signed-off-by: Alexey Romanov 
> > > > > > ---
> > > > > >  arch/arm/mach-meson/Kconfig   |   1 +
> > > > > >  drivers/firmware/Kconfig  |  10 ++
> > > > > >  drivers/firmware/Makefile |   1 +
> > > > > >  drivers/firmware/meson/Kconfig|   6 +
> > > > > >  drivers/firmware/meson/Makefile   |   3 +
> > > > > >  drivers/firmware/meson/meson_sm.c | 217 
> > > > > > ++
> > > > > >  include/meson/sm_handle.h |  38 ++
> > > > > >  7 files changed, 276 insertions(+)
> > > > > >  create mode 100644 drivers/firmware/meson/Kconfig
> > > > > >  create mode 100644 drivers/firmware/meson/Makefile
> > > > > >  create mode 100644 drivers/firmware/meson/meson_sm.c
> > > > > >  create mode 100644 include/meson/sm_handle.h
> > > > >
> > > > > Please can you use the remoteproc uclass for this and add a proper 
> > > > > driver?
> > > > >
> > > >
> > > > I don't see it architecturally well. Can you explain please?
> > > >
> > > > This driver is just ARM SMC fw interface. There seems to be nothing to
> > > > do here for remoteproc uclass.
> > >
> > > Well you seem to be implementing a remote CPU interface, which is what
> > > remoteproc is for. How does Linux do this?
> >
> > The main idea of the patchset is to abstract the smc calls (which run on
> > the same CPU) and make a request to the firmware that runs on a higher
> > EL. UCLASS_REMOTEPROC may give the impression that we are
> > interacting with another CPU, although this is not the case.
> >
> > Also, UCLASS_REMOTEPROC requires two mandatory interfaces: load() and
> > start(), and I don't even know how to apply my current changes to them.
> 
> You can return -ENOSYS if not implemented.
> 
> >
> > My implementation is very close to the Linux implementation, they
> > also use the firmware driver without remoteproc:
> >
> > https://elixir.bootlin.com/linux/latest/source/drivers/firmware/meson/meson_sm.c
> 
> Yes that seems like it doesn't use any common infra. I don't think it
> is a great model for U-Boot though.
> 
> >
> > I spoke to Neil on IRC and he said UCLASS_FIRMWARE for such driver is
> > OK.
> >
> > >
> > > Also there is a pending series on FFA - is that related? It uses smc
> > > from what I can tell.
> >
> > Not entirely clear, my changes don't seem to be related to this
> > patchset.
> 
> So perhaps this needs a new UCLASS_SMC? I see various other SMC calls
> in U-Boot but no one has taken the initiative to think about this in
> terms of driver model.

What will be the feature of this uclass? If it's just us adding a new
uclass with a different name... Don't know if that makes amy sense?
Then the difference between UCLASS_SMC and UCLASS_FIRMWARE will be only
in the name.

> 
> It might just need one operation, to make a call, passing a regs
> struct, perhaps? The uclass would presumably be ARM-specific.
> 
> I really don't think this is UCLASS_FIRMWARE. That seems to be for
> loading firmware. It doesn't even have a firmware.h header.

I see what drivers/firmware/psci.c is UCLASS_FIRMWARE and also use
smc_call() function. Or firmware-zynqmo.c. In this case, we then have to
convert them to UCLASS_SMC in the same way? 

It seemed to me that UCLASS_FIRMWARE is a SoC(arch)-specific driver
that can work with any interface.

> 
> Also instead of:
> 
> 1. uclass_get_device_by_driver(UCLASS_FIRMWARE, "secure-monitor", &dev);
> 
> use:
> 
> ret = uclass_first_device_err(UCLASS_SMC, &dev)
> 
> using device tree to find the device.
> 
> Regards,
> Simon

-- 
Thank you,
Alexey

[PATCH v3 0/1] hwrng: meson - add support for S4

2023-10-12 Thread Alexey Romanov
Hello!

This patch adds support for Meson S4 series
hardware number generator using new algo.

V2:

- Sync with Linux version.

V3:

- Fix compiler warning "makes pointer from integer without a cast"

Alexey Romanov (1):
  drivers: rng: add support for Meson S4

 drivers/rng/meson-rng.c | 72 -
 1 file changed, 71 insertions(+), 1 deletion(-)

-- 
2.25.1



[PATCH v3 1/1] drivers: rng: add support for Meson S4

2023-10-12 Thread Alexey Romanov
For some Amlogic SOC's, mechanism to obtain random number
has been changed. For example, S4 now uses status bit waiting algo.

Signed-off-by: Alexey Romanov 
---
 drivers/rng/meson-rng.c | 72 -
 1 file changed, 71 insertions(+), 1 deletion(-)

diff --git a/drivers/rng/meson-rng.c b/drivers/rng/meson-rng.c
index e0a1e8c7e0..fd2988e91b 100644
--- a/drivers/rng/meson-rng.c
+++ b/drivers/rng/meson-rng.c
@@ -10,10 +10,23 @@
 #include 
 #include 
 #include 
+#include 
+
+#define RNG_DATA   0x00
+#define RNG_S4_DATA0x08
+#define RNG_S4_CFG 0x00
+
+#define RUN_BITBIT(0)
+#define SEED_READY_STS_BIT BIT(31)
+
+struct meson_rng_priv {
+   u32 (*read)(fdt_addr_t base);
+};
 
 struct meson_rng_plat {
fdt_addr_t base;
struct clk clk;
+   struct meson_rng_priv *priv;
 };
 
 /**
@@ -27,10 +40,11 @@ struct meson_rng_plat {
 static int meson_rng_read(struct udevice *dev, void *data, size_t len)
 {
struct meson_rng_plat *pdata = dev_get_plat(dev);
+   struct meson_rng_priv *priv = pdata->priv;
char *buffer = (char *)data;
 
while (len) {
-   u32 rand = readl(pdata->base);
+   u32 rand = priv->read(pdata->base);
size_t step;
 
if (len >= 4)
@@ -44,6 +58,47 @@ static int meson_rng_read(struct udevice *dev, void *data, 
size_t len)
return 0;
 }
 
+static int meson_rng_wait_status(void __iomem *cfg_addr, int bit)
+{
+   u32 status = 0;
+   int ret;
+
+   ret = readl_relaxed_poll_timeout(cfg_addr,
+status, !(status & bit),
+1);
+   if (ret)
+   return -EBUSY;
+
+   return 0;
+}
+
+static u32 meson_common_rng_read(fdt_addr_t base)
+{
+   return readl(base);
+}
+
+static u32 meson_s4_rng_read(fdt_addr_t base)
+{
+   void __iomem *cfg_addr = (void *)base + RNG_S4_CFG;
+   int err;
+
+   writel_relaxed(readl_relaxed(cfg_addr) | SEED_READY_STS_BIT, cfg_addr);
+
+   err = meson_rng_wait_status(cfg_addr, SEED_READY_STS_BIT);
+   if (err) {
+   pr_err("Seed isn't ready, try again\n");
+   return err;
+   }
+
+   err = meson_rng_wait_status(cfg_addr, RUN_BIT);
+   if (err) {
+   pr_err("Can't get random number, try again\n");
+   return err;
+   }
+
+   return readl_relaxed(base + RNG_S4_DATA);
+}
+
 /**
  * meson_rng_probe() - probe rng device
  *
@@ -59,6 +114,8 @@ static int meson_rng_probe(struct udevice *dev)
if (err)
return err;
 
+   pdata->priv = (struct meson_rng_priv *)dev_get_driver_data(dev);
+
return 0;
 }
 
@@ -102,9 +159,22 @@ static const struct dm_rng_ops meson_rng_ops = {
.read = meson_rng_read,
 };
 
+static const struct meson_rng_priv meson_rng_priv = {
+   .read = meson_common_rng_read,
+};
+
+static const struct meson_rng_priv meson_rng_priv_s4 = {
+   .read = meson_s4_rng_read,
+};
+
 static const struct udevice_id meson_rng_match[] = {
{
.compatible = "amlogic,meson-rng",
+   .data = (ulong)&meson_rng_priv,
+   },
+   {
+   .compatible = "amlogic,meson-s4-rng",
+   .data = (ulong)&meson_rng_priv_s4,
},
{},
 };
-- 
2.25.1



[PATCH v1] drivers: don't compile Secure Monitor UCLASS unconditionally

2023-10-13 Thread Alexey Romanov
It makes no sense to compile Secure Monitor unconditionally.
For example, this break the SPL build on boards with a small
allowed SPL image size.

Fixes: 126fbbefd89e ("drivers: introduce Secure Monitor uclass")

Signed-off-by: Alexey Romanov 
---
 drivers/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/Makefile b/drivers/Makefile
index b7bd3633b1..1a768fed2b 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_$(SPL_TPL_)VIRTIO) += virtio/
 obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox/
 obj-$(CONFIG_$(SPL_)REMOTEPROC) += remoteproc/
 obj-$(CONFIG_$(SPL_)SYSINFO) += sysinfo/
+obj-$(CONFIG_$(SPL_TPL_)SM) += sm/
 obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm/
 obj-$(CONFIG_XEN) += xen/
 obj-$(CONFIG_$(SPL_)FPGA) += fpga/
@@ -124,4 +125,3 @@ obj-$(CONFIG_DM_RNG) += rng/
 endif
 
 obj-y += soc/
-obj-y += sm/
-- 
2.25.1



[PATCH v1] rng: add dm_rng_read_default() helper

2023-11-01 Thread Alexey Romanov
Add dm_rng_read_default() function, which obtain a series
of random bytes. In some cases, such function would be
useful because it allows the caller to abstract away from
RNG device.

Signed-off-by: Alexey Romanov 
---
 drivers/rng/rng-uclass.c | 20 
 include/rng.h| 10 ++
 2 files changed, 30 insertions(+)

diff --git a/drivers/rng/rng-uclass.c b/drivers/rng/rng-uclass.c
index 53108e1b31..3a8fb7d276 100644
--- a/drivers/rng/rng-uclass.c
+++ b/drivers/rng/rng-uclass.c
@@ -19,6 +19,26 @@ int dm_rng_read(struct udevice *dev, void *buffer, size_t 
size)
return ops->read(dev, buffer, size);
 }
 
+int dm_rng_read_default(void *buffer, size_t size)
+{
+   struct udevice *rng;
+   int ret;
+
+   ret = uclass_get_device(UCLASS_RNG, 0, &rng);
+   if (ret) {
+   pr_err("Can't get RNG device (%d)\n", ret);
+   return ret;
+   }
+
+   ret = dm_rng_read(rng, buffer, size);
+   if (ret) {
+   pr_err("Can't read from RNG device (%d)\n", ret);
+   return ret;
+   }
+
+   return 0;
+}
+
 UCLASS_DRIVER(rng) = {
.name = "rng",
.id = UCLASS_RNG,
diff --git a/include/rng.h b/include/rng.h
index 37af554363..5537daae88 100644
--- a/include/rng.h
+++ b/include/rng.h
@@ -20,6 +20,16 @@ struct udevice;
  */
 int dm_rng_read(struct udevice *dev, void *buffer, size_t size);
 
+/**
+ * dm_rng_read_default() - same as dm_rng_read(), except that caller
+ * don't need to pass an argument with RNG udevice.
+ * @buffer:input buffer to put the read random seed into
+ * @size:  number of bytes of random seed read
+ *
+ * Return: 0 if OK, -ve on error
+ */
+int dm_rng_read_default(void *buffer, size_t size);
+
 /**
  * struct dm_rng_ops - operations for the hwrng uclass
  *
-- 
2.25.1



[PATCH v1 0/2] Meson A1: fix USB and NAND stack

2023-11-01 Thread Alexey Romanov
Hello!

After a recent sync device tree with the Linux Kernel,
some drivers broke. These patchset will fix that.

Alexey Romanov (1):
  clk: a1: add new clocks for USB stack

Dmitry Rokosov (1):
  drivers: sm: bind child sm devices in the device tree

 drivers/clk/meson/a1.c | 6 ++
 drivers/sm/meson-sm.c  | 1 +
 2 files changed, 7 insertions(+)

-- 
2.25.1



[PATCH v1 1/2] clk: a1: add new clocks for USB stack

2023-11-01 Thread Alexey Romanov
Since we sync device tree with Linux, we have to add this
clock definition for USB stack.

Signed-off-by: Alexey Romanov 
---
 drivers/clk/meson/a1.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/clk/meson/a1.c b/drivers/clk/meson/a1.c
index 1075ba7333..d0f5bb3753 100644
--- a/drivers/clk/meson/a1.c
+++ b/drivers/clk/meson/a1.c
@@ -241,6 +241,12 @@ static const struct meson_clk_info *meson_clocks[] = {
[CLKID_USB_PHY_IN] = CLK_GATE("usb_phy_in", A1_SYS_OSCIN_CTRL, 2,
EXTERNAL_XTAL
),
+   [CLKID_USB_CTRL_IN] = CLK_GATE("usb_ctrl_in", A1_SYS_OSCIN_CTRL, 3,
+   EXTERNAL_XTAL
+   ),
+   [CLKID_USB_CTRL] = CLK_GATE("usb_ctrl", A1_SYS_CLK_EN0, 28,
+   CLKID_SYS
+   ),
[CLKID_USB_PHY] = CLK_GATE("usb_phy", A1_SYS_CLK_EN0, 27,
CLKID_SYS
),
-- 
2.25.1



[PATCH v1 2/2] drivers: sm: bind child sm devices in the device tree

2023-11-01 Thread Alexey Romanov
From: Dmitry Rokosov 

One well-known sm child device that provides secure power control is the
Secure Power Controller. This device utilizes SMC calls to communicate
with power domains on the secure monitor side.

Signed-off-by: Dmitry Rokosov 
Signed-off-by: Alexey Romanov 
---
 drivers/sm/meson-sm.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/sm/meson-sm.c b/drivers/sm/meson-sm.c
index faef369f35..1dd1584855 100644
--- a/drivers/sm/meson-sm.c
+++ b/drivers/sm/meson-sm.c
@@ -194,6 +194,7 @@ U_BOOT_DRIVER(meson_sm) = {
.id = UCLASS_SM,
.of_match = meson_sm_ids,
.probe = meson_sm_probe,
+   .bind = dm_scan_fdt_dev,
.priv_auto = sizeof(struct meson_sm_priv),
.ops = &sm_ops,
 };
-- 
2.25.1



[PATCH v2 0/2] Add dm_rng_read_default() helper

2023-11-02 Thread Alexey Romanov
Hello!

This patchset adds dm_rng_read_default() helper function, 
that selects the first rng device and uses it to obtain
random bytes.

V2:

- Move platform_get_rng_device() to rng-uclass.c. 
- Re-implement it to get first successfully probed device.
- Use it in dm_rng_read_default().

Alexey Romanov (2):
  rng: move platform_get_rng_device() to rng-uclass.c
  rng: add dm_rng_read_default() helper

 drivers/rng/rng-uclass.c | 34 ++
 include/efi_rng.h|  2 --
 include/rng.h| 21 +
 lib/efi_loader/efi_rng.c | 27 ---
 4 files changed, 55 insertions(+), 29 deletions(-)

-- 
2.30.1



[PATCH v2 2/2] rng: add dm_rng_read_default() helper

2023-11-02 Thread Alexey Romanov
Add dm_rng_read_default() function, which obtain a series
of random bytes. In some cases, such function would be
useful because it allows the caller to abstract away from
RNG device.

Signed-off-by: Alexey Romanov 
---
 drivers/rng/rng-uclass.c | 18 ++
 include/rng.h| 10 ++
 2 files changed, 28 insertions(+)

diff --git a/drivers/rng/rng-uclass.c b/drivers/rng/rng-uclass.c
index d7236b9335..e298623e1d 100644
--- a/drivers/rng/rng-uclass.c
+++ b/drivers/rng/rng-uclass.c
@@ -35,6 +35,24 @@ int dm_rng_read(struct udevice *dev, void *buffer, size_t 
size)
return ops->read(dev, buffer, size);
 }
 
+int dm_rng_read_default(void *buffer, size_t size)
+{
+   struct udevice *rng;
+   int ret;
+
+   ret = platform_get_rng_device(&rng);
+   if (ret)
+   return ret;
+
+   ret = dm_rng_read(rng, buffer, size);
+   if (ret) {
+   pr_err("Can't read from RNG device (%d)\n", ret);
+   return ret;
+   }
+
+   return 0;
+}
+
 UCLASS_DRIVER(rng) = {
.name = "rng",
.id = UCLASS_RNG,
diff --git a/include/rng.h b/include/rng.h
index 255c85d3e8..6412fedad2 100644
--- a/include/rng.h
+++ b/include/rng.h
@@ -20,6 +20,16 @@ struct udevice;
  */
 int dm_rng_read(struct udevice *dev, void *buffer, size_t size);
 
+/**
+ * dm_rng_read_default() - same as dm_rng_read(), except that caller
+ * don't need to pass an argument with RNG udevice.
+ * @buffer:input buffer to put the read random seed into
+ * @size:  number of bytes of random seed read
+ *
+ * Return: 0 if OK, -ve on error
+ */
+int dm_rng_read_default(void *buffer, size_t size);
+
 /**
  * platform_get_rng_device() - retrieve random number generator
  *
-- 
2.30.1



[PATCH v2 1/2] rng: move platform_get_rng_device() to rng-uclass.c

2023-11-02 Thread Alexey Romanov
The correct declaration place for platform_get_rng_device()
function is here. Also, this function is re-implemented to provide
the first successfully probed RNG device.

Signed-off-by: Alexey Romanov 
---
 drivers/rng/rng-uclass.c | 16 
 include/efi_rng.h|  2 --
 include/rng.h| 11 +++
 lib/efi_loader/efi_rng.c | 27 ---
 4 files changed, 27 insertions(+), 29 deletions(-)

diff --git a/drivers/rng/rng-uclass.c b/drivers/rng/rng-uclass.c
index 53108e1b31..d7236b9335 100644
--- a/drivers/rng/rng-uclass.c
+++ b/drivers/rng/rng-uclass.c
@@ -9,6 +9,22 @@
 #include 
 #include 
 
+int platform_get_rng_device(struct udevice **dev)
+{
+   int ret;
+   struct udevice *devp;
+
+   ret = uclass_first_device_check(UCLASS_RNG, &devp);
+   if (ret) {
+   pr_err("Unable to get RNG device (%d)\n", ret);
+   return -ENODEV;
+   }
+
+   *dev = devp;
+
+   return 0;
+}
+
 int dm_rng_read(struct udevice *dev, void *buffer, size_t size)
 {
const struct dm_rng_ops *ops = device_get_ops(dev);
diff --git a/include/efi_rng.h b/include/efi_rng.h
index 3c622381cb..f22e54adb0 100644
--- a/include/efi_rng.h
+++ b/include/efi_rng.h
@@ -23,6 +23,4 @@ struct efi_rng_protocol {
   efi_uintn_t rng_value_length, uint8_t 
*rng_value);
 };
 
-efi_status_t platform_get_rng_device(struct udevice **dev);
-
 #endif /* _EFI_RNG_H_ */
diff --git a/include/rng.h b/include/rng.h
index 37af554363..255c85d3e8 100644
--- a/include/rng.h
+++ b/include/rng.h
@@ -20,6 +20,17 @@ struct udevice;
  */
 int dm_rng_read(struct udevice *dev, void *buffer, size_t size);
 
+/**
+ * platform_get_rng_device() - retrieve random number generator
+ *
+ * This function retrieves the first udevice implementing a hardware
+ * random number generator. Device is already probed.
+ *
+ * @dev:   udevice
+ * Return: status code
+ */
+int platform_get_rng_device(struct udevice **dev);
+
 /**
  * struct dm_rng_ops - operations for the hwrng uclass
  *
diff --git a/lib/efi_loader/efi_rng.c b/lib/efi_loader/efi_rng.c
index bb11d8d0e0..0d8bf770f5 100644
--- a/lib/efi_loader/efi_rng.c
+++ b/lib/efi_loader/efi_rng.c
@@ -17,33 +17,6 @@ DECLARE_GLOBAL_DATA_PTR;
 
 const efi_guid_t efi_guid_rng_protocol = EFI_RNG_PROTOCOL_GUID;
 
-/**
- * platform_get_rng_device() - retrieve random number generator
- *
- * This function retrieves the udevice implementing a hardware random
- * number generator.
- *
- * This function may be overridden if special initialization is needed.
- *
- * @dev:   udevice
- * Return: status code
- */
-__weak efi_status_t platform_get_rng_device(struct udevice **dev)
-{
-   int ret;
-   struct udevice *devp;
-
-   ret = uclass_get_device(UCLASS_RNG, 0, &devp);
-   if (ret) {
-   debug("Unable to get rng device\n");
-   return EFI_DEVICE_ERROR;
-   }
-
-   *dev = devp;
-
-   return EFI_SUCCESS;
-}
-
 /**
  * rng_getinfo() - get information about random number generation
  *
-- 
2.30.1



Re: [PATCH v1 1/2] drivers: firmware: introduce Meson Secure Monitor driver

2023-08-22 Thread Alexey Romanov
Hi,

On Tue, Aug 22, 2023 at 10:24:23AM +0200, neil.armstr...@linaro.org wrote:
> On 21/08/2023 21:11, Simon Glass wrote:
> > Hi Neil,
> > 
> > On Mon, 21 Aug 2023 at 03:16, neil.armstr...@linaro.org
> >  wrote:
> > > 
> > > Hi,
> > > 
> > > On 16/07/2023 01:40, Simon Glass wrote:
> > > > Hi,
> > > > 
> > > > On Thu, 13 Jul 2023 at 23:30, AKASHI Takahiro
> > > >  wrote:
> > > > > 
> > > > > On Tue, Jul 11, 2023 at 01:13:29PM -0600, Simon Glass wrote:
> > > > > > +AKASHI Takahiro
> > > > > 
> > > > > Me?
> > > > 
> > > > Yes, I'm asking for your help to try to clean this stuff up.
> > > 
> > > The thread is long and hard to answer directly, but as AKASHI
> > > said there's no point to add a SMC class since it's only the message
> > > passing instruction, and there's no point using remoteproc since the
> > > firmware runs on a separate secure state of the same CPU.
> > > 
> > > And I don't see how we can actually define a finite set of ops because
> > > none of the secure firmware interfaces has even similar functions.
> > > 
> > > So a new UCLASS for each firmware interface should be added, not sure
> > > this is scalable or required since those firmwares are mainly SoC or
> > > vendor specific, except the PSCI or other ARM specific interfaces of 
> > > course.
> > > 
> > > So I think UCLASS_FIRMWARE is good enough since it avoids using 
> > > UCLASS_MISC,
> > > but it should be probably documented somewhere that the ops are 
> > > implementation
> > > defined.
> > 
> > Yes it needs docs...but what exactly is the 'firmware' uclass? I
> > assumed it was for loading firmware into a device, but it seems that
> > it is something else?
> 
> Nop, it's based on the same "firmware" naming as Linux, which is an interface
> with a system control firmware like PSCI, SCPI... not to interact with 
> loadable
> co-processors.
> 
> Systems do have multiple interfaces implemented like PSCI, SCPI, OPTEE and 
> other
> vendor specific ones like Alexey is changing, all via the same instruction 
> call.
> 
> > 
> > Perhaps we should have a UCLASS_SVC (supervisor call) or something
> > like that, rather than continuing with firmware?

You propose to create UCLASS with an interface consisting of functions
of something like: ->smc_call(), ->hvc_call()? In this case, it seems
ARM specific.

Or UCLASS with only one callback, different for different archs, which
will call the hypervisor or something like that. In my understanding, 
this add-on are redundant.

I still think UCLASS firmware is the best fit for my Secure Monitor
implementation at the moment.

> 
> I have no opinion on that, I don't think the call type is significant here.
> 
> Neil
> 
> > 
> > [..]
> > 
> > Regards,
> > Simon
> 

-- 
Thank you,
Alexey

Re: [PATCH v1 1/2] drivers: firmware: introduce Meson Secure Monitor driver

2023-08-24 Thread Alexey Romanov
Hi Simon,

On Tue, Aug 22, 2023 at 12:56:32PM -0600, Simon Glass wrote:
> Hi Alexey,
> 
> On Tue, 22 Aug 2023 at 06:59, Alexey Romanov
>  wrote:
> >
> > Hi,
> >
> > On Tue, Aug 22, 2023 at 10:24:23AM +0200, neil.armstr...@linaro.org wrote:
> > > On 21/08/2023 21:11, Simon Glass wrote:
> > > > Hi Neil,
> > > >
> > > > On Mon, 21 Aug 2023 at 03:16, neil.armstr...@linaro.org
> > > >  wrote:
> > > > >
> > > > > Hi,
> > > > >
> > > > > On 16/07/2023 01:40, Simon Glass wrote:
> > > > > > Hi,
> > > > > >
> > > > > > On Thu, 13 Jul 2023 at 23:30, AKASHI Takahiro
> > > > > >  wrote:
> > > > > > >
> > > > > > > On Tue, Jul 11, 2023 at 01:13:29PM -0600, Simon Glass wrote:
> > > > > > > > +AKASHI Takahiro
> > > > > > >
> > > > > > > Me?
> > > > > >
> > > > > > Yes, I'm asking for your help to try to clean this stuff up.
> > > > >
> > > > > The thread is long and hard to answer directly, but as AKASHI
> > > > > said there's no point to add a SMC class since it's only the message
> > > > > passing instruction, and there's no point using remoteproc since the
> > > > > firmware runs on a separate secure state of the same CPU.
> > > > >
> > > > > And I don't see how we can actually define a finite set of ops because
> > > > > none of the secure firmware interfaces has even similar functions.
> > > > >
> > > > > So a new UCLASS for each firmware interface should be added, not sure
> > > > > this is scalable or required since those firmwares are mainly SoC or
> > > > > vendor specific, except the PSCI or other ARM specific interfaces of 
> > > > > course.
> > > > >
> > > > > So I think UCLASS_FIRMWARE is good enough since it avoids using 
> > > > > UCLASS_MISC,
> > > > > but it should be probably documented somewhere that the ops are 
> > > > > implementation
> > > > > defined.
> > > >
> > > > Yes it needs docs...but what exactly is the 'firmware' uclass? I
> > > > assumed it was for loading firmware into a device, but it seems that
> > > > it is something else?
> > >
> > > Nop, it's based on the same "firmware" naming as Linux, which is an 
> > > interface
> > > with a system control firmware like PSCI, SCPI... not to interact with 
> > > loadable
> > > co-processors.
> > >
> > > Systems do have multiple interfaces implemented like PSCI, SCPI, OPTEE 
> > > and other
> > > vendor specific ones like Alexey is changing, all via the same 
> > > instruction call.
> > >
> > > >
> > > > Perhaps we should have a UCLASS_SVC (supervisor call) or something
> > > > like that, rather than continuing with firmware?
> >
> > You propose to create UCLASS with an interface consisting of functions
> > of something like: ->smc_call(), ->hvc_call()? In this case, it seems
> > ARM specific.
> 
> Yes, but we have a lot of arch-specific interfaces.
> 
> >
> > Or UCLASS with only one callback, different for different archs, which
> > will call the hypervisor or something like that. In my understanding,
> > this add-on are redundant.
> 
> OK.
> 
> >
> > I still think UCLASS firmware is the best fit for my Secure Monitor
> > implementation at the moment.
> 
> How about you create a UCLASS_MESON_SM then?
> 
> I don't really like the idea of a uclass with no standard API. One
> goal is to help people understand things and can't see that helping.

OK. Will do it in v2.

> 
> >
> > >
> > > I have no opinion on that, I don't think the call type is significant 
> > > here.
> > >
> > > Neil
> > >
> > > >
> > > > [..]
> > > >
> > > > Regards,
> > > > Simon
> > >
> >
> > --
> > Thank you,
> > Alexey
> 
> Regards,
> Simon

-- 
Thank you,
Alexey

[PATCH v2 0/8] Add SM uclass and Meson SM driver

2023-09-11 Thread Alexey Romanov
Hello!

At the moment, there is no single general approach to using
secure monitor in U-Boot, there is only the smc_call() function,
over which everyone builds their own add-ons. This patchset
is designed to solve this problem by adding a new uclass -
SM_UCLASS. This UCLASS export following generic API:

1. sm_call() - generic SMC call to the secure-monitor
2. sm_call_read() - retrieve data from secure-monitor
3. sm_call_write() - send data to secure-monitor

In the future, it is necessary to completely get rid of raw
smc_call() calls, replacing them with the use of SM_UCLASS
based drivers.

V2:

- Add SM UCLASS
- Add SM sandbox driver
- Add test for sandbox driver
- Meson Secure Monitor driver now based on SM_UCLASS
- Fix include order in arch/arm/mach-meson/sm.c

Also, during the discussion in V1 of this patchset, it was
discussed to create MESON_SM_UCLASS, but I considered such
a uclass to be too arch-specific. That's why I suggest
SM_UCLASS, which is not so arch-specific: secure monitor can
used for whole ARM devices, not only for Amlogic SoC's.

Alexey Romanov (8):
  drivers: introduce Secure Monitor uclass
  sandbox: add sandobx sm uclass driver
  sandbox: dts: add meson secure monitor node
  sandbox: add tests for UCLASS_SM
  sandbox: defconfig: enable CONFIG_SM option
  drivers: introduce Meson Secure Monitor driver
  arch: meson: sm: set correct order of the includes
  arch: meson: use secure monitor driver

 MAINTAINERS |   1 +
 arch/arm/mach-meson/Kconfig |   1 +
 arch/arm/mach-meson/sm.c| 116 +++--
 arch/sandbox/dts/test.dts   |   4 +
 configs/sandbox_defconfig   |   1 +
 drivers/Kconfig |   2 +
 drivers/Makefile|   1 +
 drivers/sm/Kconfig  |   9 ++
 drivers/sm/Makefile |   5 +
 drivers/sm/meson-sm.c   | 198 
 drivers/sm/sandbox-sm.c |  76 ++
 drivers/sm/sm-uclass.c  |  55 ++
 include/dm/uclass-id.h  |   1 +
 include/meson/sm.h  |  19 
 include/sandbox-sm.h|  18 
 include/sm-uclass.h |  72 +
 include/sm.h|  67 
 test/dm/Makefile|   1 +
 test/dm/sm.c|  65 
 19 files changed, 656 insertions(+), 56 deletions(-)
 create mode 100644 drivers/sm/Kconfig
 create mode 100644 drivers/sm/Makefile
 create mode 100644 drivers/sm/meson-sm.c
 create mode 100644 drivers/sm/sandbox-sm.c
 create mode 100644 drivers/sm/sm-uclass.c
 create mode 100644 include/meson/sm.h
 create mode 100644 include/sandbox-sm.h
 create mode 100644 include/sm-uclass.h
 create mode 100644 include/sm.h
 create mode 100644 test/dm/sm.c

-- 
2.25.1



[PATCH v2 1/8] drivers: introduce Secure Monitor uclass

2023-09-11 Thread Alexey Romanov
At the moment, we don't have a common API for working with
SM, only the smc_call() function. This approach is not generic
and difficult to configure and maintain.

This patch adds UCLASS_SM with the generic API:

- sm_call()
- sm_call_write()
- sm_call_read()

These functions operate with struct pt_regs, which describes
Secure Monitor arguments.

Signed-off-by: Alexey Romanov 
---
 drivers/Kconfig|  2 ++
 drivers/Makefile   |  1 +
 drivers/sm/Kconfig |  2 ++
 drivers/sm/Makefile|  3 ++
 drivers/sm/sm-uclass.c | 55 
 include/dm/uclass-id.h |  1 +
 include/sm-uclass.h| 72 ++
 include/sm.h   | 67 +++
 8 files changed, 203 insertions(+)
 create mode 100644 drivers/sm/Kconfig
 create mode 100644 drivers/sm/Makefile
 create mode 100644 drivers/sm/sm-uclass.c
 create mode 100644 include/sm-uclass.h
 create mode 100644 include/sm.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 75ac149d31..72e6405322 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -112,6 +112,8 @@ source "drivers/scsi/Kconfig"
 
 source "drivers/serial/Kconfig"
 
+source "drivers/sm/Kconfig"
+
 source "drivers/smem/Kconfig"
 
 source "drivers/sound/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 6f1de58e00..b7bd3633b1 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -124,3 +124,4 @@ obj-$(CONFIG_DM_RNG) += rng/
 endif
 
 obj-y += soc/
+obj-y += sm/
diff --git a/drivers/sm/Kconfig b/drivers/sm/Kconfig
new file mode 100644
index 00..6cc6d55578
--- /dev/null
+++ b/drivers/sm/Kconfig
@@ -0,0 +1,2 @@
+config SM
+   bool "Enable Secure Monitor driver support"
diff --git a/drivers/sm/Makefile b/drivers/sm/Makefile
new file mode 100644
index 00..9f4683ba06
--- /dev/null
+++ b/drivers/sm/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += sm-uclass.o
diff --git a/drivers/sm/sm-uclass.c b/drivers/sm/sm-uclass.c
new file mode 100644
index 00..78af857026
--- /dev/null
+++ b/drivers/sm/sm-uclass.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov 
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+static const struct sm_ops *get_sm_ops(struct udevice *dev)
+{
+   return (const struct sm_ops *)dev->driver->ops;
+}
+
+int sm_call(struct udevice *dev, u32 cmd, s32 *ret, struct pt_regs *args)
+{
+   const struct sm_ops *ops = get_sm_ops(dev);
+
+   if (ops->sm_call)
+   return ops->sm_call(dev, cmd, ret, args);
+
+   return -EPROTONOSUPPORT;
+}
+
+int sm_call_read(struct udevice *dev, void *buffer, size_t size,
+u32 cmd, struct pt_regs *args)
+{
+   const struct sm_ops *ops = get_sm_ops(dev);
+
+   if (ops->sm_call_read)
+   return ops->sm_call_read(dev, buffer, size, cmd,
+args);
+
+   return -EPROTONOSUPPORT;
+}
+
+int sm_call_write(struct udevice *dev, void *buffer, size_t size,
+  u32 cmd, struct pt_regs *args)
+{
+   const struct sm_ops *ops = get_sm_ops(dev);
+
+   if (ops->sm_call_write)
+   return ops->sm_call_write(dev, buffer, size, cmd,
+ args);
+
+   return -EPROTONOSUPPORT;
+}
+
+UCLASS_DRIVER(sm) = {
+   .name   = "sm",
+   .id = UCLASS_SM,
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 376f741cc2..545c9352a8 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -80,6 +80,7 @@ enum uclass_id {
UCLASS_MDIO,/* MDIO bus */
UCLASS_MDIO_MUX,/* MDIO MUX/switch */
UCLASS_MEMORY,  /* Memory Controller device */
+   UCLASS_SM,  /* Secure Monitor driver */
UCLASS_MISC,/* Miscellaneous device */
UCLASS_MMC, /* SD / MMC card or chip */
UCLASS_MOD_EXP, /* RSA Mod Exp device */
diff --git a/include/sm-uclass.h b/include/sm-uclass.h
new file mode 100644
index 00..c114484044
--- /dev/null
+++ b/include/sm-uclass.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov 
+ */
+
+#ifndef __SM_UCLASS_H__
+#define __SM_UCLASS_H__
+
+#include 
+#include 
+
+struct udevice;
+
+/**
+ * struct sm_ops - The functions that a SM driver must implement.
+ *
+ * @sm_call: Request a secure monitor call with specified command.
+ *
+ * @sm_call_read: Request a secure monitor call and retrieve data
+ * from secure-monitor (depends on specified command).
+ *
+ * @sm_call_write: Request a secure monitor call and send data
+ * to secure-monitor (depends on specified command).
+ *
+ * The individual methods are described more

[PATCH v2 2/8] sandbox: add sandobx sm uclass driver

2023-09-11 Thread Alexey Romanov
This patch adds sandbox secure monitor driver.

Signed-off-by: Alexey Romanov 
---
 drivers/sm/Makefile |  1 +
 drivers/sm/sandbox-sm.c | 76 +
 include/sandbox-sm.h| 18 ++
 3 files changed, 95 insertions(+)
 create mode 100644 drivers/sm/sandbox-sm.c
 create mode 100644 include/sandbox-sm.h

diff --git a/drivers/sm/Makefile b/drivers/sm/Makefile
index 9f4683ba06..af5f475c2b 100644
--- a/drivers/sm/Makefile
+++ b/drivers/sm/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
 obj-y += sm-uclass.o
+obj-$(CONFIG_SANDBOX) += sandbox-sm.o
diff --git a/drivers/sm/sandbox-sm.c b/drivers/sm/sandbox-sm.c
new file mode 100644
index 00..109ddb2af5
--- /dev/null
+++ b/drivers/sm/sandbox-sm.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static u8 test_buffer[SZ_4K];
+
+static int sandbox_sm_call(struct udevice *dev, u32 cmd_index, s32 *smc_ret,
+  struct pt_regs *args)
+{
+   if (cmd_index >= SANDBOX_SMC_CMD_COUNT)
+   return -EINVAL;
+
+   if (smc_ret)
+   *smc_ret = 0;
+
+   return 0;
+}
+
+static int sandbox_sm_call_read(struct udevice *dev, void *buffer, size_t size,
+   u32 cmd_index, struct pt_regs *args)
+{
+   if (cmd_index >= SANDBOX_SMC_CMD_COUNT || !buffer)
+   return -EINVAL;
+
+   if (size > sizeof(test_buffer))
+   return -EINVAL;
+
+   memcpy(buffer, test_buffer, size);
+
+   return size;
+}
+
+static int sandbox_sm_call_write(struct udevice *dev, void *buffer, size_t 
size,
+u32 cmd_index, struct pt_regs *args)
+{
+   if (cmd_index >= SANDBOX_SMC_CMD_COUNT || !buffer)
+   return -EINVAL;
+
+   if (size > sizeof(test_buffer))
+   return -EINVAL;
+
+   memcpy(test_buffer, buffer, size);
+
+   return size;
+}
+
+static const struct udevice_id sandbox_sm_ids[] = {
+   {
+   .compatible = "sandbox,sm",
+   },
+   {},
+};
+
+static const struct sm_ops sandbox_sm_ops = {
+   .sm_call = sandbox_sm_call,
+   .sm_call_read = sandbox_sm_call_read,
+   .sm_call_write = sandbox_sm_call_write,
+};
+
+U_BOOT_DRIVER(sm) = {
+   .name = "sm",
+   .id = UCLASS_SM,
+   .of_match = sandbox_sm_ids,
+   .ops = &sandbox_sm_ops,
+};
diff --git a/include/sandbox-sm.h b/include/sandbox-sm.h
new file mode 100644
index 00..91c30d501d
--- /dev/null
+++ b/include/sandbox-sm.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov 
+ */
+
+#ifndef __SANDBOX_SM_H__
+#define __SANDBOX_SM_H__
+
+enum sandbox_smc_cmd {
+   SANDBOX_SMC_CMD_READ_MEM,
+   SANDBOX_SMC_CMD_WRITE_MEM,
+   SANDBOX_SMC_CMD_COMMON,
+   SANDBOX_SMC_CMD_COUNT,
+};
+
+#endif
-- 
2.25.1



[PATCH v2 3/8] sandbox: dts: add meson secure monitor node

2023-09-11 Thread Alexey Romanov
We need this to test UCLASS_SM.

Signed-off-by: Alexey Romanov 
---
 arch/sandbox/dts/test.dts | 4 
 1 file changed, 4 insertions(+)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index dffe10adbf..4475aa58a6 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -693,6 +693,10 @@
};
};
};
+
+   sm: secure-monitor {
+   compatible = "sandbox,sm";
+   };
};
 
fpga {
-- 
2.25.1



[PATCH v2 4/8] sandbox: add tests for UCLASS_SM

2023-09-11 Thread Alexey Romanov
This patchs adds simple tests for Secure Monitor uclass.

Signed-off-by: Alexey Romanov 
---
 test/dm/Makefile |  1 +
 test/dm/sm.c | 65 
 2 files changed, 66 insertions(+)
 create mode 100644 test/dm/sm.c

diff --git a/test/dm/Makefile b/test/dm/Makefile
index 7a79b6e1a2..30550a62ad 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -107,6 +107,7 @@ obj-$(CONFIG_DM_SPI) += spi.o
 obj-$(CONFIG_SPMI) += spmi.o
 obj-y += syscon.o
 obj-$(CONFIG_RESET_SYSCON) += syscon-reset.o
+obj-$(CONFIG_SM) += sm.o
 obj-$(CONFIG_SYSINFO) += sysinfo.o
 obj-$(CONFIG_SYSINFO_GPIO) += sysinfo-gpio.o
 obj-$(CONFIG_UT_DM) += tag.o
diff --git a/test/dm/sm.c b/test/dm/sm.c
new file mode 100644
index 00..7ebb0c9c85
--- /dev/null
+++ b/test/dm/sm.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int dm_test_sm(struct unit_test_state *uts)
+{
+   struct udevice *dev;
+   struct pt_regs regs;
+   char buffer[128] = { 0 };
+   char test_string[] = "secure-monitor";
+   int ret, val;
+
+   ut_assertok(uclass_get_device_by_name(UCLASS_SM,
+   "secure-monitor", &dev));
+
+   ret = sm_call(dev, SANDBOX_SMC_CMD_COUNT, NULL, ®s);
+   ut_asserteq(ret, -EINVAL);
+
+   ret = sm_call(dev, SANDBOX_SMC_CMD_COMMON, &val, ®s);
+   ut_asserteq(ret, 0);
+   ut_asserteq(val, 0);
+
+   ret = sm_call_write(dev, buffer, sizeof(buffer),
+   SANDBOX_SMC_CMD_COUNT, ®s);
+   ut_asserteq(ret, -EINVAL);
+
+   ret = sm_call_write(dev, buffer, SZ_4K + 1,
+   SANDBOX_SMC_CMD_WRITE_MEM, ®s);
+   ut_asserteq(ret, -EINVAL);
+
+   ret = sm_call_write(dev, buffer, sizeof(buffer),
+   SANDBOX_SMC_CMD_COUNT, ®s);
+   ut_asserteq(ret, -EINVAL);
+
+   ret = sm_call_write(dev, buffer, SZ_4K + 1,
+   SANDBOX_SMC_CMD_READ_MEM, ®s);
+   ut_asserteq(ret, -EINVAL);
+
+   ret = sm_call_write(dev, test_string, sizeof(test_string),
+   SANDBOX_SMC_CMD_WRITE_MEM, ®s);
+   ut_asserteq(ret, sizeof(test_string));
+
+   ret = sm_call_read(dev, buffer, sizeof(buffer),
+   SANDBOX_SMC_CMD_READ_MEM, ®s);
+   ut_asserteq(ret, sizeof(buffer));
+
+   ut_asserteq_str(buffer, test_string);
+
+   return 0;
+}
+
+DM_TEST(dm_test_sm, UT_TESTF_SCAN_FDT);
-- 
2.25.1



[PATCH v2 5/8] sandbox: defconfig: enable CONFIG_SM option

2023-09-11 Thread Alexey Romanov
We use this option for test UCLASS_SM.

Signed-off-by: Alexey Romanov 
---
 configs/sandbox_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index be46cae7aa..0745a4ecca 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -270,6 +270,7 @@ CONFIG_RTC_RV8803=y
 CONFIG_SCSI=y
 CONFIG_DM_SCSI=y
 CONFIG_SANDBOX_SERIAL=y
+CONFIG_SM=y
 CONFIG_SMEM=y
 CONFIG_SANDBOX_SMEM=y
 CONFIG_SOUND=y
-- 
2.25.1



[PATCH v2 7/8] arch: meson: sm: set correct order of the includes

2023-09-11 Thread Alexey Romanov
The common.h header should always be first, followed
by other headers in order, then headers with directories,
then local files.

Signed-off-by: Alexey Romanov 
---
 arch/arm/mach-meson/sm.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c
index d600c64d0b..b5dd6c6d39 100644
--- a/arch/arm/mach-meson/sm.c
+++ b/arch/arm/mach-meson/sm.c
@@ -6,7 +6,10 @@
  */
 
 #include 
+#include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -14,10 +17,7 @@
 #include 
 #include 
 #include 
-#include 
 #include 
-#include 
-#include 
 
 #define FN_GET_SHARE_MEM_INPUT_BASE0x8220
 #define FN_GET_SHARE_MEM_OUTPUT_BASE   0x8221
-- 
2.25.1



[PATCH v2 6/8] drivers: introduce Meson Secure Monitor driver

2023-09-11 Thread Alexey Romanov
This patch adds an implementation of the Meson Secure Monitor
driver based on UCLASS_SM.

Signed-off-by: Alexey Romanov 
---
 MAINTAINERS   |   1 +
 drivers/sm/Kconfig|   7 ++
 drivers/sm/Makefile   |   1 +
 drivers/sm/meson-sm.c | 198 ++
 include/meson/sm.h|  19 
 5 files changed, 226 insertions(+)
 create mode 100644 drivers/sm/meson-sm.c
 create mode 100644 include/meson/sm.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 6c64427782..bdc364fd4c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -158,6 +158,7 @@ F:  drivers/net/phy/meson-gxl.c
 F: drivers/adc/meson-saradc.c
 F: drivers/phy/meson*
 F: drivers/mmc/meson_gx_mmc.c
+F: drivers/sm/meson-sm.c
 F: drivers/spi/meson_spifc.c
 F: drivers/pinctrl/meson/
 F: drivers/power/domain/meson-gx-pwrc-vpu.c
diff --git a/drivers/sm/Kconfig b/drivers/sm/Kconfig
index 6cc6d55578..b4cc3f768e 100644
--- a/drivers/sm/Kconfig
+++ b/drivers/sm/Kconfig
@@ -1,2 +1,9 @@
 config SM
bool "Enable Secure Monitor driver support"
+
+config MESON_SM
+   bool "Amlogic Secure Monitor driver"
+   depends on SM
+   default n
+   help
+ Say y here to enable the Amlogic secure monitor driver.
diff --git a/drivers/sm/Makefile b/drivers/sm/Makefile
index af5f475c2b..da81ee898a 100644
--- a/drivers/sm/Makefile
+++ b/drivers/sm/Makefile
@@ -2,3 +2,4 @@
 
 obj-y += sm-uclass.o
 obj-$(CONFIG_SANDBOX) += sandbox-sm.o
+obj-$(CONFIG_MESON_SM) += meson-sm.o
diff --git a/drivers/sm/meson-sm.c b/drivers/sm/meson-sm.c
new file mode 100644
index 00..25adaf4560
--- /dev/null
+++ b/drivers/sm/meson-sm.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct meson_sm_cmd {
+   u32 smc_id;
+};
+
+#define SET_CMD(index, id) \
+   [index] = { \
+   .smc_id = (id), \
+   }
+
+struct meson_sm_data {
+   u32 cmd_get_shmem_in;
+   u32 cmd_get_shmem_out;
+   unsigned int shmem_size;
+   struct meson_sm_cmd cmd[];
+};
+
+struct meson_sm_priv {
+   void *sm_shmem_in;
+   void *sm_shmem_out;
+   const struct meson_sm_data *data;
+};
+
+static unsigned long __meson_sm_call(u32 cmd, const struct pt_regs *args)
+{
+   struct pt_regs r = *args;
+
+   r.regs[0] = cmd;
+   smc_call(&r);
+
+   return r.regs[0];
+};
+
+static u32 meson_sm_get_cmd(const struct meson_sm_data *data,
+   u32 cmd_index)
+{
+   struct meson_sm_cmd cmd;
+
+   if (cmd_index >= MESON_SMC_CMD_COUNT)
+   return 0;
+
+   cmd = data->cmd[cmd_index];
+   return cmd.smc_id;
+}
+
+static int meson_sm_call(struct udevice *dev, u32 cmd_index, s32 *retval,
+struct pt_regs *args)
+{
+   struct meson_sm_priv *priv = dev_get_priv(dev);
+   u32 cmd, ret;
+
+   cmd = meson_sm_get_cmd(priv->data, cmd_index);
+   if (!cmd)
+   return -ENOENT;
+
+   ret = __meson_sm_call(cmd, args);
+   if (retval)
+   *retval = ret;
+
+   return 0;
+}
+
+static int meson_sm_call_read(struct udevice *dev, void *buffer, size_t size,
+ u32 cmd_index, struct pt_regs *args)
+{
+   struct meson_sm_priv *priv = dev_get_priv(dev);
+   s32 nbytes;
+   int ret;
+
+   if (!buffer || size > priv->data->shmem_size)
+   return -EINVAL;
+
+   ret = meson_sm_call(dev, cmd_index, &nbytes, args);
+   if (ret)
+   return ret;
+
+   if (nbytes < 0 || nbytes > size)
+   return -ENOBUFS;
+
+   /* In some cases (for example GET_CHIP_ID command),
+* SMC doesn't return the number of bytes read, even
+* though the bytes were actually read into sm_shmem_out.
+* So this check is needed.
+*/
+   ret = nbytes;
+   if (!nbytes)
+   nbytes = size;
+
+   memcpy(buffer, priv->sm_shmem_out, nbytes);
+
+   return ret;
+}
+
+static int meson_sm_call_write(struct udevice *dev, void *buffer, size_t size,
+  u32 cmd_index, struct pt_regs *args)
+{
+   struct meson_sm_priv *priv = dev_get_priv(dev);
+   s32 nbytes;
+   int ret;
+
+   if (!buffer || size > priv->data->shmem_size)
+   return -EINVAL;
+
+   memcpy(priv->sm_shmem_in, buffer, size);
+
+   ret = meson_sm_call(dev, cmd_index, &nbytes, args);
+   if (ret)
+   return ret;
+
+   if (nbytes <= 0 || nbytes > size)
+   return -EIO;
+
+   return nbytes;
+}
+
+static int meson_sm_probe(struct udevice *dev)
+{
+   struct meson_sm_priv *priv = dev_get_priv(dev);

[PATCH v2 8/8] arch: meson: use secure monitor driver

2023-09-11 Thread Alexey Romanov
Now we have to use UCLASS_SM driver instead of
raw smc_call() function call.

Signed-off-by: Alexey Romanov 
---
 arch/arm/mach-meson/Kconfig |   1 +
 arch/arm/mach-meson/sm.c| 110 +++-
 2 files changed, 58 insertions(+), 53 deletions(-)

diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig
index 669ca09a00..d6c8905806 100644
--- a/arch/arm/mach-meson/Kconfig
+++ b/arch/arm/mach-meson/Kconfig
@@ -11,6 +11,7 @@ config MESON64_COMMON
select PWRSEQ
select MMC_PWRSEQ
select BOARD_LATE_INIT
+   select MESON_SM
imply CMD_DM
 
 config MESON_GX
diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c
index b5dd6c6d39..0c60aa8695 100644
--- a/arch/arm/mach-meson/sm.c
+++ b/arch/arm/mach-meson/sm.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -18,70 +19,62 @@
 #include 
 #include 
 #include 
+#include 
 
-#define FN_GET_SHARE_MEM_INPUT_BASE0x8220
-#define FN_GET_SHARE_MEM_OUTPUT_BASE   0x8221
-#define FN_EFUSE_READ  0x8230
-#define FN_EFUSE_WRITE 0x8231
-#define FN_CHIP_ID 0x8244
-#define FN_PWRDM_SET   0x8293
-
-static void *shmem_input;
-static void *shmem_output;
-
-static void meson_init_shmem(void)
+static inline struct udevice *meson_get_sm_device(void)
 {
-   struct pt_regs regs;
-
-   if (shmem_input && shmem_output)
-   return;
+   struct udevice *dev;
+   int err;
 
-   regs.regs[0] = FN_GET_SHARE_MEM_INPUT_BASE;
-   smc_call(®s);
-   shmem_input = (void *)regs.regs[0];
-
-   regs.regs[0] = FN_GET_SHARE_MEM_OUTPUT_BASE;
-   smc_call(®s);
-   shmem_output = (void *)regs.regs[0];
+   err = uclass_get_device_by_name(UCLASS_SM, "secure-monitor", &dev);
+   if (err) {
+   pr_err("Mesom SM device not found\n");
+   return ERR_PTR(err);
+   }
 
-   debug("Secure Monitor shmem: 0x%p 0x%p\n", shmem_input, shmem_output);
+   return dev;
 }
 
 ssize_t meson_sm_read_efuse(uintptr_t offset, void *buffer, size_t size)
 {
-   struct pt_regs regs;
+   struct udevice *dev;
+   struct pt_regs regs = { 0 };
+   int err;
 
-   meson_init_shmem();
+   dev = meson_get_sm_device();
+   if (IS_ERR(dev))
+   return PTR_ERR(dev);
 
-   regs.regs[0] = FN_EFUSE_READ;
regs.regs[1] = offset;
regs.regs[2] = size;
 
-   smc_call(®s);
+   err = sm_call_read(dev, buffer, size,
+  MESON_SMC_CMD_EFUSE_READ, ®s);
+   if (err < 0)
+   pr_err("Failed to read efuse memory (%d)\n", err);
 
-   if (regs.regs[0] == 0)
-   return -1;
-
-   memcpy(buffer, shmem_output, min(size, regs.regs[0]));
-
-   return regs.regs[0];
+   return err;
 }
 
 ssize_t meson_sm_write_efuse(uintptr_t offset, void *buffer, size_t size)
 {
-   struct pt_regs regs;
-
-   meson_init_shmem();
+   struct udevice *dev;
+   struct pt_regs regs = { 0 };
+   int err;
 
-memcpy(shmem_input, buffer, size);
+   dev = meson_get_sm_device();
+   if (IS_ERR(dev))
+   return PTR_ERR(dev);
 
-   regs.regs[0] = FN_EFUSE_WRITE;
regs.regs[1] = offset;
regs.regs[2] = size;
 
-   smc_call(®s);
+   err = sm_call_write(dev, buffer, size,
+   MESON_SMC_CMD_EFUSE_WRITE, ®s);
+   if (err < 0)
+   pr_err("Failed to write efuse memory (%d)\n", err);
 
-   return regs.regs[0];
+   return err;
 }
 
 #define SM_CHIP_ID_LENGTH  119
@@ -90,18 +83,21 @@ ssize_t meson_sm_write_efuse(uintptr_t offset, void 
*buffer, size_t size)
 
 int meson_sm_get_serial(void *buffer, size_t size)
 {
-   struct pt_regs regs;
+   struct udevice *dev;
+   struct pt_regs regs = { 0 };
+   u8 id_buffer[SM_CHIP_ID_LENGTH];
+   int err;
 
-   meson_init_shmem();
+   dev = meson_get_sm_device();
+   if (IS_ERR(dev))
+   return PTR_ERR(dev);
 
-   regs.regs[0] = FN_CHIP_ID;
-   regs.regs[1] = 0;
-   regs.regs[2] = 0;
+   err = sm_call_read(dev, id_buffer, SM_CHIP_ID_LENGTH,
+  MESON_SMC_CMD_CHIP_ID_GET, ®s);
+   if (err < 0)
+   pr_err("Failed to read serial number (%d)\n", err);
 
-   smc_call(®s);
-
-   memcpy(buffer, shmem_output + SM_CHIP_ID_OFFSET,
-  min_t(size_t, size, SM_CHIP_ID_SIZE));
+   memcpy(buffer, id_buffer + SM_CHIP_ID_OFFSET, size);
 
return 0;
 }
@@ -141,13 +137,21 @@ int meson_sm_get_reboot_reason(void)
 
 int meson_sm_pwrdm_set(size_t index, int cmd)
 {
-   struct pt_regs regs;
+   struct udevice *dev;
+   struct pt_regs regs = { 0 };
+   int err;
+
+   dev = meson_get_sm_device();
+ 

Re: [PATCH v1 1/2] meson-a1: dts: add hw rng node

2023-09-15 Thread Alexey Romanov
Hi Neil,

On Thu, Jun 22, 2023 at 06:19:33PM +0200, neil.armstr...@linaro.org wrote:
> On 21/06/2023 15:29, Alexey Romanov wrote:
> > Add support for hardware random number generator
> > of Amlogic Meson SoCs.
> > 
> > Signed-off-by: Alexey Romanov 
> > ---
> >   arch/arm/dts/meson-a1.dtsi | 5 +
> >   1 file changed, 5 insertions(+)
> > 
> > diff --git a/arch/arm/dts/meson-a1.dtsi b/arch/arm/dts/meson-a1.dtsi
> > index f3560cbc3a4..1f57c137384 100644
> > --- a/arch/arm/dts/meson-a1.dtsi
> > +++ b/arch/arm/dts/meson-a1.dtsi
> > @@ -140,6 +140,11 @@
> > clock-names = "xtal", "pclk", "baud";
> > status = "disabled";
> > };
> > +
> > +   hwrng: rng@5118 {
> > +   compatible = "amlogic,meson-rng";
> > +   reg = <0x0 0x5118 0x0 0x4>;
> > +   };
> > };
> > gic: interrupt-controller@ff901000 {
> 
> Weird, you introduced amlogic,meson-rng-s4 previously but you don't use it 
> here ?

This is A1 (not S4).

> 
> Anyway please add those to Linux first, them sync the DT to u-boot afterwards,


Applied into v6.7/arm64-dt here:

https://lore.kernel.org/all/20230823213630.12936-13-ddroko...@sberdevices.ru/

> 
> Thanks,
> Neil

-- 
Thank you,
Alexey

Re: [PATCH v1 2/2] meson-a1: dts: add ao secure node

2023-09-15 Thread Alexey Romanov
Hi Neil, 

On Wed, Jun 21, 2023 at 04:29:53PM +0300, Alexey Romanov wrote:
> ao-secure node can be used to get information about the board,
> so, for example, using show_board_info() we can get following
> information for board with Meson A1 SoC:
> 
> SoC: Amlogic Meson A1 (A113L) Revision 2c:a (1:a)
> 
> Signed-off-by: Alexey Romanov 
> ---
>  arch/arm/dts/meson-a1.dtsi | 6 ++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/arch/arm/dts/meson-a1.dtsi b/arch/arm/dts/meson-a1.dtsi
> index 1f57c137384..149cc0e23a3 100644
> --- a/arch/arm/dts/meson-a1.dtsi
> +++ b/arch/arm/dts/meson-a1.dtsi
> @@ -145,6 +145,12 @@
>   compatible = "amlogic,meson-rng";
>   reg = <0x0 0x5118 0x0 0x4>;
>   };
> +
> + sec_AO: ao-secure@5a20 {
> + compatible = "amlogic,meson-gx-ao-secure", 
> "syscon";
> + reg = <0x0 0x5a20 0x0 0x140>;
> + amlogic,has-chip-id;
> + };
>   };
>  
>   gic: interrupt-controller@ff901000 {
> -- 
> 2.38.1
>

Applied into v6.7/arm64-dt here:

https://lore.kernel.org/all/20230823213630.12936-14-ddroko...@sberdevices.ru/

-- 
Thank you,
Alexey

[PATCH v3 1/8] drivers: introduce Secure Monitor uclass

2023-09-21 Thread Alexey Romanov
At the moment, we don't have a common API for working with
SM, only the smc_call() function. This approach is not generic
and difficult to configure and maintain.

This patch adds UCLASS_SM with the generic API:

- sm_call()
- sm_call_write()
- sm_call_read()

These functions operate with struct pt_regs, which describes
Secure Monitor arguments.

Signed-off-by: Alexey Romanov 
Reviewed-by: Simon Glass 
---
 drivers/Kconfig|  2 ++
 drivers/Makefile   |  1 +
 drivers/sm/Kconfig |  2 ++
 drivers/sm/Makefile|  3 ++
 drivers/sm/sm-uclass.c | 55 
 include/dm/uclass-id.h |  1 +
 include/sm-uclass.h| 72 ++
 include/sm.h   | 67 +++
 8 files changed, 203 insertions(+)
 create mode 100644 drivers/sm/Kconfig
 create mode 100644 drivers/sm/Makefile
 create mode 100644 drivers/sm/sm-uclass.c
 create mode 100644 include/sm-uclass.h
 create mode 100644 include/sm.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 75ac149d31..72e6405322 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -112,6 +112,8 @@ source "drivers/scsi/Kconfig"
 
 source "drivers/serial/Kconfig"
 
+source "drivers/sm/Kconfig"
+
 source "drivers/smem/Kconfig"
 
 source "drivers/sound/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 6f1de58e00..b7bd3633b1 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -124,3 +124,4 @@ obj-$(CONFIG_DM_RNG) += rng/
 endif
 
 obj-y += soc/
+obj-y += sm/
diff --git a/drivers/sm/Kconfig b/drivers/sm/Kconfig
new file mode 100644
index 00..6cc6d55578
--- /dev/null
+++ b/drivers/sm/Kconfig
@@ -0,0 +1,2 @@
+config SM
+   bool "Enable Secure Monitor driver support"
diff --git a/drivers/sm/Makefile b/drivers/sm/Makefile
new file mode 100644
index 00..9f4683ba06
--- /dev/null
+++ b/drivers/sm/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += sm-uclass.o
diff --git a/drivers/sm/sm-uclass.c b/drivers/sm/sm-uclass.c
new file mode 100644
index 00..6a8b702629
--- /dev/null
+++ b/drivers/sm/sm-uclass.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov 
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+static const struct sm_ops *get_sm_ops(struct udevice *dev)
+{
+   return (const struct sm_ops *)dev->driver->ops;
+}
+
+int sm_call(struct udevice *dev, u32 cmd, s32 *ret, struct pt_regs *args)
+{
+   const struct sm_ops *ops = get_sm_ops(dev);
+
+   if (ops->sm_call)
+   return ops->sm_call(dev, cmd, ret, args);
+
+   return -ENOSYS;
+}
+
+int sm_call_read(struct udevice *dev, void *buffer, size_t size,
+u32 cmd, struct pt_regs *args)
+{
+   const struct sm_ops *ops = get_sm_ops(dev);
+
+   if (ops->sm_call_read)
+   return ops->sm_call_read(dev, buffer, size, cmd,
+args);
+
+   return -ENOSYS;
+}
+
+int sm_call_write(struct udevice *dev, void *buffer, size_t size,
+  u32 cmd, struct pt_regs *args)
+{
+   const struct sm_ops *ops = get_sm_ops(dev);
+
+   if (ops->sm_call_write)
+   return ops->sm_call_write(dev, buffer, size, cmd,
+ args);
+
+   return -ENOSYS;
+}
+
+UCLASS_DRIVER(sm) = {
+   .name   = "sm",
+   .id = UCLASS_SM,
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 376f741cc2..545c9352a8 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -80,6 +80,7 @@ enum uclass_id {
UCLASS_MDIO,/* MDIO bus */
UCLASS_MDIO_MUX,/* MDIO MUX/switch */
UCLASS_MEMORY,  /* Memory Controller device */
+   UCLASS_SM,  /* Secure Monitor driver */
UCLASS_MISC,/* Miscellaneous device */
UCLASS_MMC, /* SD / MMC card or chip */
UCLASS_MOD_EXP, /* RSA Mod Exp device */
diff --git a/include/sm-uclass.h b/include/sm-uclass.h
new file mode 100644
index 00..c114484044
--- /dev/null
+++ b/include/sm-uclass.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov 
+ */
+
+#ifndef __SM_UCLASS_H__
+#define __SM_UCLASS_H__
+
+#include 
+#include 
+
+struct udevice;
+
+/**
+ * struct sm_ops - The functions that a SM driver must implement.
+ *
+ * @sm_call: Request a secure monitor call with specified command.
+ *
+ * @sm_call_read: Request a secure monitor call and retrieve data
+ * from secure-monitor (depends on specified command).
+ *
+ * @sm_call_write: Request a secure monitor call and send data
+ * to secure-monitor (depends on specified command).
+ *
+ * The individual methods are described more

[PATCH v3 0/8] Add SM uclass and Meson SM driver

2023-09-21 Thread Alexey Romanov
Hello!

At the moment, there is no single general approach to using
secure monitor in U-Boot, there is only the smc_call() function,
over which everyone builds their own add-ons. This patchset
is designed to solve this problem by adding a new uclass -
SM_UCLASS. This UCLASS export following generic API:

1. sm_call() - generic SMC call to the secure-monitor
2. sm_call_read() - retrieve data from secure-monitor
3. sm_call_write() - send data to secure-monitor

In the future, it is necessary to completely get rid of raw
smc_call() calls, replacing them with the use of SM_UCLASS
based drivers.

V2:

- Add SM UCLASS
- Add SM sandbox driver
- Add test for sandbox driver
- Meson Secure Monitor driver now based on SM_UCLASS
- Fix include order in arch/arm/mach-meson/sm.c

Also, during the discussion in V1 of this patchset, it was
discussed to create MESON_SM_UCLASS, but I considered such
a uclass to be too arch-specific. That's why I suggest
SM_UCLASS, which is not so arch-specific: secure monitor can
used for whole ARM devices, not only for Amlogic SoC's.

V3:

- Fix typos in commit messages
- Use uclass_first_device_err() instead of uclass_get_device_by_name()
- Return -ENOSYS instead of -EPROTONOSUPPORT if SM_UCLASS option not
implemented

Alexey Romanov (8):
  drivers: introduce Secure Monitor uclass
  sandbox: add sandbox sm uclass driver
  sandbox: dts: add meson secure monitor node
  sandbox: add tests for UCLASS_SM
  sandbox: defconfig: enable CONFIG_SM option
  drivers: introduce Meson Secure Monitor driver
  arch: meson: sm: set correct order of the includes
  arch: meson: use secure monitor driver

 MAINTAINERS |   1 +
 arch/arm/mach-meson/Kconfig |   1 +
 arch/arm/mach-meson/sm.c| 116 +++--
 arch/sandbox/dts/test.dts   |   4 +
 configs/sandbox_defconfig   |   1 +
 drivers/Kconfig |   2 +
 drivers/Makefile|   1 +
 drivers/sm/Kconfig  |   9 ++
 drivers/sm/Makefile |   5 +
 drivers/sm/meson-sm.c   | 198 
 drivers/sm/sandbox-sm.c |  76 ++
 drivers/sm/sm-uclass.c  |  55 ++
 include/dm/uclass-id.h  |   1 +
 include/meson/sm.h  |  19 
 include/sandbox-sm.h|  18 
 include/sm-uclass.h |  72 +
 include/sm.h|  67 
 test/dm/Makefile|   1 +
 test/dm/sm.c|  65 
 19 files changed, 656 insertions(+), 56 deletions(-)
 create mode 100644 drivers/sm/Kconfig
 create mode 100644 drivers/sm/Makefile
 create mode 100644 drivers/sm/meson-sm.c
 create mode 100644 drivers/sm/sandbox-sm.c
 create mode 100644 drivers/sm/sm-uclass.c
 create mode 100644 include/meson/sm.h
 create mode 100644 include/sandbox-sm.h
 create mode 100644 include/sm-uclass.h
 create mode 100644 include/sm.h
 create mode 100644 test/dm/sm.c

-- 
2.25.1



[PATCH v3 2/8] sandbox: add sandbox sm uclass driver

2023-09-21 Thread Alexey Romanov
This patch adds sandbox secure monitor driver.

Signed-off-by: Alexey Romanov 
Reviewed-by: Simon Glass 
---
 drivers/sm/Makefile |  1 +
 drivers/sm/sandbox-sm.c | 76 +
 include/sandbox-sm.h| 18 ++
 3 files changed, 95 insertions(+)
 create mode 100644 drivers/sm/sandbox-sm.c
 create mode 100644 include/sandbox-sm.h

diff --git a/drivers/sm/Makefile b/drivers/sm/Makefile
index 9f4683ba06..af5f475c2b 100644
--- a/drivers/sm/Makefile
+++ b/drivers/sm/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
 obj-y += sm-uclass.o
+obj-$(CONFIG_SANDBOX) += sandbox-sm.o
diff --git a/drivers/sm/sandbox-sm.c b/drivers/sm/sandbox-sm.c
new file mode 100644
index 00..109ddb2af5
--- /dev/null
+++ b/drivers/sm/sandbox-sm.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static u8 test_buffer[SZ_4K];
+
+static int sandbox_sm_call(struct udevice *dev, u32 cmd_index, s32 *smc_ret,
+  struct pt_regs *args)
+{
+   if (cmd_index >= SANDBOX_SMC_CMD_COUNT)
+   return -EINVAL;
+
+   if (smc_ret)
+   *smc_ret = 0;
+
+   return 0;
+}
+
+static int sandbox_sm_call_read(struct udevice *dev, void *buffer, size_t size,
+   u32 cmd_index, struct pt_regs *args)
+{
+   if (cmd_index >= SANDBOX_SMC_CMD_COUNT || !buffer)
+   return -EINVAL;
+
+   if (size > sizeof(test_buffer))
+   return -EINVAL;
+
+   memcpy(buffer, test_buffer, size);
+
+   return size;
+}
+
+static int sandbox_sm_call_write(struct udevice *dev, void *buffer, size_t 
size,
+u32 cmd_index, struct pt_regs *args)
+{
+   if (cmd_index >= SANDBOX_SMC_CMD_COUNT || !buffer)
+   return -EINVAL;
+
+   if (size > sizeof(test_buffer))
+   return -EINVAL;
+
+   memcpy(test_buffer, buffer, size);
+
+   return size;
+}
+
+static const struct udevice_id sandbox_sm_ids[] = {
+   {
+   .compatible = "sandbox,sm",
+   },
+   {},
+};
+
+static const struct sm_ops sandbox_sm_ops = {
+   .sm_call = sandbox_sm_call,
+   .sm_call_read = sandbox_sm_call_read,
+   .sm_call_write = sandbox_sm_call_write,
+};
+
+U_BOOT_DRIVER(sm) = {
+   .name = "sm",
+   .id = UCLASS_SM,
+   .of_match = sandbox_sm_ids,
+   .ops = &sandbox_sm_ops,
+};
diff --git a/include/sandbox-sm.h b/include/sandbox-sm.h
new file mode 100644
index 00..91c30d501d
--- /dev/null
+++ b/include/sandbox-sm.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov 
+ */
+
+#ifndef __SANDBOX_SM_H__
+#define __SANDBOX_SM_H__
+
+enum sandbox_smc_cmd {
+   SANDBOX_SMC_CMD_READ_MEM,
+   SANDBOX_SMC_CMD_WRITE_MEM,
+   SANDBOX_SMC_CMD_COMMON,
+   SANDBOX_SMC_CMD_COUNT,
+};
+
+#endif
-- 
2.25.1



[PATCH v3 3/8] sandbox: dts: add meson secure monitor node

2023-09-21 Thread Alexey Romanov
We need this to test UCLASS_SM.

Signed-off-by: Alexey Romanov 
Reviewed-by: Simon Glass 
---
 arch/sandbox/dts/test.dts | 4 
 1 file changed, 4 insertions(+)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index dffe10adbf..4475aa58a6 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -693,6 +693,10 @@
};
};
};
+
+   sm: secure-monitor {
+   compatible = "sandbox,sm";
+   };
};
 
fpga {
-- 
2.25.1



[PATCH v3 4/8] sandbox: add tests for UCLASS_SM

2023-09-21 Thread Alexey Romanov
This patchs adds simple tests for Secure Monitor uclass.

Signed-off-by: Alexey Romanov 
Reviewed-by: Simon Glass 
---
 test/dm/Makefile |  1 +
 test/dm/sm.c | 65 
 2 files changed, 66 insertions(+)
 create mode 100644 test/dm/sm.c

diff --git a/test/dm/Makefile b/test/dm/Makefile
index 7a79b6e1a2..30550a62ad 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -107,6 +107,7 @@ obj-$(CONFIG_DM_SPI) += spi.o
 obj-$(CONFIG_SPMI) += spmi.o
 obj-y += syscon.o
 obj-$(CONFIG_RESET_SYSCON) += syscon-reset.o
+obj-$(CONFIG_SM) += sm.o
 obj-$(CONFIG_SYSINFO) += sysinfo.o
 obj-$(CONFIG_SYSINFO_GPIO) += sysinfo-gpio.o
 obj-$(CONFIG_UT_DM) += tag.o
diff --git a/test/dm/sm.c b/test/dm/sm.c
new file mode 100644
index 00..7ebb0c9c85
--- /dev/null
+++ b/test/dm/sm.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int dm_test_sm(struct unit_test_state *uts)
+{
+   struct udevice *dev;
+   struct pt_regs regs;
+   char buffer[128] = { 0 };
+   char test_string[] = "secure-monitor";
+   int ret, val;
+
+   ut_assertok(uclass_get_device_by_name(UCLASS_SM,
+   "secure-monitor", &dev));
+
+   ret = sm_call(dev, SANDBOX_SMC_CMD_COUNT, NULL, ®s);
+   ut_asserteq(ret, -EINVAL);
+
+   ret = sm_call(dev, SANDBOX_SMC_CMD_COMMON, &val, ®s);
+   ut_asserteq(ret, 0);
+   ut_asserteq(val, 0);
+
+   ret = sm_call_write(dev, buffer, sizeof(buffer),
+   SANDBOX_SMC_CMD_COUNT, ®s);
+   ut_asserteq(ret, -EINVAL);
+
+   ret = sm_call_write(dev, buffer, SZ_4K + 1,
+   SANDBOX_SMC_CMD_WRITE_MEM, ®s);
+   ut_asserteq(ret, -EINVAL);
+
+   ret = sm_call_write(dev, buffer, sizeof(buffer),
+   SANDBOX_SMC_CMD_COUNT, ®s);
+   ut_asserteq(ret, -EINVAL);
+
+   ret = sm_call_write(dev, buffer, SZ_4K + 1,
+   SANDBOX_SMC_CMD_READ_MEM, ®s);
+   ut_asserteq(ret, -EINVAL);
+
+   ret = sm_call_write(dev, test_string, sizeof(test_string),
+   SANDBOX_SMC_CMD_WRITE_MEM, ®s);
+   ut_asserteq(ret, sizeof(test_string));
+
+   ret = sm_call_read(dev, buffer, sizeof(buffer),
+   SANDBOX_SMC_CMD_READ_MEM, ®s);
+   ut_asserteq(ret, sizeof(buffer));
+
+   ut_asserteq_str(buffer, test_string);
+
+   return 0;
+}
+
+DM_TEST(dm_test_sm, UT_TESTF_SCAN_FDT);
-- 
2.25.1



[PATCH v3 5/8] sandbox: defconfig: enable CONFIG_SM option

2023-09-21 Thread Alexey Romanov
We use this option to test UCLASS_SM.

Signed-off-by: Alexey Romanov 
Reviewed-by: Simon Glass 
---
 configs/sandbox_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index be46cae7aa..0745a4ecca 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -270,6 +270,7 @@ CONFIG_RTC_RV8803=y
 CONFIG_SCSI=y
 CONFIG_DM_SCSI=y
 CONFIG_SANDBOX_SERIAL=y
+CONFIG_SM=y
 CONFIG_SMEM=y
 CONFIG_SANDBOX_SMEM=y
 CONFIG_SOUND=y
-- 
2.25.1



[PATCH v3 6/8] drivers: introduce Meson Secure Monitor driver

2023-09-21 Thread Alexey Romanov
This patch adds an implementation of the Meson Secure Monitor
driver based on UCLASS_SM.

Signed-off-by: Alexey Romanov 
Reviewed-by: Simon Glass 
---
 MAINTAINERS   |   1 +
 drivers/sm/Kconfig|   7 ++
 drivers/sm/Makefile   |   1 +
 drivers/sm/meson-sm.c | 198 ++
 include/meson/sm.h|  19 
 5 files changed, 226 insertions(+)
 create mode 100644 drivers/sm/meson-sm.c
 create mode 100644 include/meson/sm.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 6c64427782..bdc364fd4c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -158,6 +158,7 @@ F:  drivers/net/phy/meson-gxl.c
 F: drivers/adc/meson-saradc.c
 F: drivers/phy/meson*
 F: drivers/mmc/meson_gx_mmc.c
+F: drivers/sm/meson-sm.c
 F: drivers/spi/meson_spifc.c
 F: drivers/pinctrl/meson/
 F: drivers/power/domain/meson-gx-pwrc-vpu.c
diff --git a/drivers/sm/Kconfig b/drivers/sm/Kconfig
index 6cc6d55578..b4cc3f768e 100644
--- a/drivers/sm/Kconfig
+++ b/drivers/sm/Kconfig
@@ -1,2 +1,9 @@
 config SM
bool "Enable Secure Monitor driver support"
+
+config MESON_SM
+   bool "Amlogic Secure Monitor driver"
+   depends on SM
+   default n
+   help
+ Say y here to enable the Amlogic secure monitor driver.
diff --git a/drivers/sm/Makefile b/drivers/sm/Makefile
index af5f475c2b..da81ee898a 100644
--- a/drivers/sm/Makefile
+++ b/drivers/sm/Makefile
@@ -2,3 +2,4 @@
 
 obj-y += sm-uclass.o
 obj-$(CONFIG_SANDBOX) += sandbox-sm.o
+obj-$(CONFIG_MESON_SM) += meson-sm.o
diff --git a/drivers/sm/meson-sm.c b/drivers/sm/meson-sm.c
new file mode 100644
index 00..25adaf4560
--- /dev/null
+++ b/drivers/sm/meson-sm.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct meson_sm_cmd {
+   u32 smc_id;
+};
+
+#define SET_CMD(index, id) \
+   [index] = { \
+   .smc_id = (id), \
+   }
+
+struct meson_sm_data {
+   u32 cmd_get_shmem_in;
+   u32 cmd_get_shmem_out;
+   unsigned int shmem_size;
+   struct meson_sm_cmd cmd[];
+};
+
+struct meson_sm_priv {
+   void *sm_shmem_in;
+   void *sm_shmem_out;
+   const struct meson_sm_data *data;
+};
+
+static unsigned long __meson_sm_call(u32 cmd, const struct pt_regs *args)
+{
+   struct pt_regs r = *args;
+
+   r.regs[0] = cmd;
+   smc_call(&r);
+
+   return r.regs[0];
+};
+
+static u32 meson_sm_get_cmd(const struct meson_sm_data *data,
+   u32 cmd_index)
+{
+   struct meson_sm_cmd cmd;
+
+   if (cmd_index >= MESON_SMC_CMD_COUNT)
+   return 0;
+
+   cmd = data->cmd[cmd_index];
+   return cmd.smc_id;
+}
+
+static int meson_sm_call(struct udevice *dev, u32 cmd_index, s32 *retval,
+struct pt_regs *args)
+{
+   struct meson_sm_priv *priv = dev_get_priv(dev);
+   u32 cmd, ret;
+
+   cmd = meson_sm_get_cmd(priv->data, cmd_index);
+   if (!cmd)
+   return -ENOENT;
+
+   ret = __meson_sm_call(cmd, args);
+   if (retval)
+   *retval = ret;
+
+   return 0;
+}
+
+static int meson_sm_call_read(struct udevice *dev, void *buffer, size_t size,
+ u32 cmd_index, struct pt_regs *args)
+{
+   struct meson_sm_priv *priv = dev_get_priv(dev);
+   s32 nbytes;
+   int ret;
+
+   if (!buffer || size > priv->data->shmem_size)
+   return -EINVAL;
+
+   ret = meson_sm_call(dev, cmd_index, &nbytes, args);
+   if (ret)
+   return ret;
+
+   if (nbytes < 0 || nbytes > size)
+   return -ENOBUFS;
+
+   /* In some cases (for example GET_CHIP_ID command),
+* SMC doesn't return the number of bytes read, even
+* though the bytes were actually read into sm_shmem_out.
+* So this check is needed.
+*/
+   ret = nbytes;
+   if (!nbytes)
+   nbytes = size;
+
+   memcpy(buffer, priv->sm_shmem_out, nbytes);
+
+   return ret;
+}
+
+static int meson_sm_call_write(struct udevice *dev, void *buffer, size_t size,
+  u32 cmd_index, struct pt_regs *args)
+{
+   struct meson_sm_priv *priv = dev_get_priv(dev);
+   s32 nbytes;
+   int ret;
+
+   if (!buffer || size > priv->data->shmem_size)
+   return -EINVAL;
+
+   memcpy(priv->sm_shmem_in, buffer, size);
+
+   ret = meson_sm_call(dev, cmd_index, &nbytes, args);
+   if (ret)
+   return ret;
+
+   if (nbytes <= 0 || nbytes > size)
+   return -EIO;
+
+   return nbytes;
+}
+
+static int meson_sm_probe(struct udevice *dev)
+{
+   struct meson_sm_priv *p

[PATCH v3 7/8] arch: meson: sm: set correct order of the includes

2023-09-21 Thread Alexey Romanov
The common.h header should always be first, followed
by other headers in order, then headers with directories,
then local files.

Signed-off-by: Alexey Romanov 
Reviewed-by: Simon Glass 
---
 arch/arm/mach-meson/sm.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c
index d600c64d0b..b5dd6c6d39 100644
--- a/arch/arm/mach-meson/sm.c
+++ b/arch/arm/mach-meson/sm.c
@@ -6,7 +6,10 @@
  */
 
 #include 
+#include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -14,10 +17,7 @@
 #include 
 #include 
 #include 
-#include 
 #include 
-#include 
-#include 
 
 #define FN_GET_SHARE_MEM_INPUT_BASE0x8220
 #define FN_GET_SHARE_MEM_OUTPUT_BASE   0x8221
-- 
2.25.1



[PATCH v3 8/8] arch: meson: use secure monitor driver

2023-09-21 Thread Alexey Romanov
Now we have to use UCLASS_SM driver instead of
raw smc_call() function call.

Signed-off-by: Alexey Romanov 
Reviewed-by: Simon Glass 
---
 arch/arm/mach-meson/Kconfig |   1 +
 arch/arm/mach-meson/sm.c| 110 +++-
 2 files changed, 58 insertions(+), 53 deletions(-)

diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig
index 669ca09a00..d6c8905806 100644
--- a/arch/arm/mach-meson/Kconfig
+++ b/arch/arm/mach-meson/Kconfig
@@ -11,6 +11,7 @@ config MESON64_COMMON
select PWRSEQ
select MMC_PWRSEQ
select BOARD_LATE_INIT
+   select MESON_SM
imply CMD_DM
 
 config MESON_GX
diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c
index b5dd6c6d39..914fd11c98 100644
--- a/arch/arm/mach-meson/sm.c
+++ b/arch/arm/mach-meson/sm.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -18,70 +19,62 @@
 #include 
 #include 
 #include 
+#include 
 
-#define FN_GET_SHARE_MEM_INPUT_BASE0x8220
-#define FN_GET_SHARE_MEM_OUTPUT_BASE   0x8221
-#define FN_EFUSE_READ  0x8230
-#define FN_EFUSE_WRITE 0x8231
-#define FN_CHIP_ID 0x8244
-#define FN_PWRDM_SET   0x8293
-
-static void *shmem_input;
-static void *shmem_output;
-
-static void meson_init_shmem(void)
+static inline struct udevice *meson_get_sm_device(void)
 {
-   struct pt_regs regs;
-
-   if (shmem_input && shmem_output)
-   return;
+   struct udevice *dev;
+   int err;
 
-   regs.regs[0] = FN_GET_SHARE_MEM_INPUT_BASE;
-   smc_call(®s);
-   shmem_input = (void *)regs.regs[0];
-
-   regs.regs[0] = FN_GET_SHARE_MEM_OUTPUT_BASE;
-   smc_call(®s);
-   shmem_output = (void *)regs.regs[0];
+   err = uclass_first_device_err(UCLASS_SM, &dev);
+   if (err) {
+   pr_err("Mesom SM device not found\n");
+   return ERR_PTR(err);
+   }
 
-   debug("Secure Monitor shmem: 0x%p 0x%p\n", shmem_input, shmem_output);
+   return dev;
 }
 
 ssize_t meson_sm_read_efuse(uintptr_t offset, void *buffer, size_t size)
 {
-   struct pt_regs regs;
+   struct udevice *dev;
+   struct pt_regs regs = { 0 };
+   int err;
 
-   meson_init_shmem();
+   dev = meson_get_sm_device();
+   if (IS_ERR(dev))
+   return PTR_ERR(dev);
 
-   regs.regs[0] = FN_EFUSE_READ;
regs.regs[1] = offset;
regs.regs[2] = size;
 
-   smc_call(®s);
+   err = sm_call_read(dev, buffer, size,
+  MESON_SMC_CMD_EFUSE_READ, ®s);
+   if (err < 0)
+   pr_err("Failed to read efuse memory (%d)\n", err);
 
-   if (regs.regs[0] == 0)
-   return -1;
-
-   memcpy(buffer, shmem_output, min(size, regs.regs[0]));
-
-   return regs.regs[0];
+   return err;
 }
 
 ssize_t meson_sm_write_efuse(uintptr_t offset, void *buffer, size_t size)
 {
-   struct pt_regs regs;
-
-   meson_init_shmem();
+   struct udevice *dev;
+   struct pt_regs regs = { 0 };
+   int err;
 
-memcpy(shmem_input, buffer, size);
+   dev = meson_get_sm_device();
+   if (IS_ERR(dev))
+   return PTR_ERR(dev);
 
-   regs.regs[0] = FN_EFUSE_WRITE;
regs.regs[1] = offset;
regs.regs[2] = size;
 
-   smc_call(®s);
+   err = sm_call_write(dev, buffer, size,
+   MESON_SMC_CMD_EFUSE_WRITE, ®s);
+   if (err < 0)
+   pr_err("Failed to write efuse memory (%d)\n", err);
 
-   return regs.regs[0];
+   return err;
 }
 
 #define SM_CHIP_ID_LENGTH  119
@@ -90,18 +83,21 @@ ssize_t meson_sm_write_efuse(uintptr_t offset, void 
*buffer, size_t size)
 
 int meson_sm_get_serial(void *buffer, size_t size)
 {
-   struct pt_regs regs;
+   struct udevice *dev;
+   struct pt_regs regs = { 0 };
+   u8 id_buffer[SM_CHIP_ID_LENGTH];
+   int err;
 
-   meson_init_shmem();
+   dev = meson_get_sm_device();
+   if (IS_ERR(dev))
+   return PTR_ERR(dev);
 
-   regs.regs[0] = FN_CHIP_ID;
-   regs.regs[1] = 0;
-   regs.regs[2] = 0;
+   err = sm_call_read(dev, id_buffer, SM_CHIP_ID_LENGTH,
+  MESON_SMC_CMD_CHIP_ID_GET, ®s);
+   if (err < 0)
+   pr_err("Failed to read serial number (%d)\n", err);
 
-   smc_call(®s);
-
-   memcpy(buffer, shmem_output + SM_CHIP_ID_OFFSET,
-  min_t(size_t, size, SM_CHIP_ID_SIZE));
+   memcpy(buffer, id_buffer + SM_CHIP_ID_OFFSET, size);
 
return 0;
 }
@@ -141,13 +137,21 @@ int meson_sm_get_reboot_reason(void)
 
 int meson_sm_pwrdm_set(size_t index, int cmd)
 {
-   struct pt_regs regs;
+   struct udevice *dev;
+   struct pt_regs regs = { 0 };
+   int err;
+
+   dev = meson_get_s

[PATCH v1 0/8] Support USB for Meson A1

2023-10-02 Thread Alexey Romanov
Hello!

This patchset adds USB stack support for Amlogic A1 SoC's
series. Made reset / phy / dwc3 drivers more flexible and
added support for A1 board.

Alexey Romanov (7):
  dt-bindings: reset: add Meson A1 reset bindings
  reset: add support for Amlogic A1 family
  phy: get rid of raw hex values
  phy: move clk enable/disable in init/exit
  phy: support Amlogic A1 family
  dwc3: add support for Amlogic A1 family
  arch: a1: introduce USB initialization functionality

Igor Prusov (1):
  a1: clk: Add missing CLKID_USB_PHY_IN gate

 arch/arm/mach-meson/board-a1.c|  89 +++
 drivers/clk/meson/a1.c|   3 +
 drivers/phy/Kconfig   |   2 +-
 drivers/phy/meson-g12a-usb2.c | 233 --
 drivers/reset/reset-meson.c   |  42 +++-
 drivers/usb/dwc3/dwc3-meson-g12a.c|  73 +-
 .../reset/amlogic,meson-a1-reset.h|  76 ++
 7 files changed, 484 insertions(+), 34 deletions(-)
 create mode 100644 include/dt-bindings/reset/amlogic,meson-a1-reset.h

-- 
2.25.1



[PATCH v1 2/8] reset: add support for Amlogic A1 family

2023-10-02 Thread Alexey Romanov
This patch adds reset support for the Amlogic A1 family.
We add the structure meson_reset_drvdata, which in the future
will allow this driver to be used for other families by declaring
only the correct parameters reg_count and level_offset.

Signed-off-by: Alexey Romanov 
---
 drivers/reset/reset-meson.c | 42 +++--
 1 file changed, 36 insertions(+), 6 deletions(-)

diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c
index 64bc696f13..9d0c8b354f 100644
--- a/drivers/reset/reset-meson.c
+++ b/drivers/reset/reset-meson.c
@@ -13,18 +13,26 @@
 #include 
 #include 
 #include 
+#include 
 
-#define REG_COUNT  8
 #define BITS_PER_REG   32
-#define LEVEL_OFFSET   0x7c
+
+struct meson_reset_drvdata {
+   unsigned int reg_count;
+   unsigned int level_offset;
+};
 
 struct meson_reset_priv {
struct regmap *regmap;
+   struct meson_reset_drvdata *drvdata;
 };
 
 static int meson_reset_request(struct reset_ctl *reset_ctl)
 {
-   if (reset_ctl->id > (REG_COUNT * BITS_PER_REG))
+   struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+   struct meson_reset_drvdata *data = priv->drvdata;
+
+   if (reset_ctl->id > (data->reg_count * BITS_PER_REG))
return -EINVAL;
 
return 0;
@@ -33,9 +41,10 @@ static int meson_reset_request(struct reset_ctl *reset_ctl)
 static int meson_reset_level(struct reset_ctl *reset_ctl, bool assert)
 {
struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+   struct meson_reset_drvdata *data = priv->drvdata;
uint bank = reset_ctl->id / BITS_PER_REG;
uint offset = reset_ctl->id % BITS_PER_REG;
-   uint reg_offset = LEVEL_OFFSET + (bank << 2);
+   uint reg_offset = data->level_offset + (bank << 2);
uint val;
 
regmap_read(priv->regmap, reg_offset, &val);
@@ -64,15 +73,36 @@ struct reset_ops meson_reset_ops = {
.rst_deassert = meson_reset_deassert,
 };
 
+static const struct meson_reset_drvdata meson_gxbb_data = {
+   .reg_count = 8,
+   .level_offset = 0x7c,
+};
+
+static const struct meson_reset_drvdata meson_a1_data = {
+   .reg_count = 3,
+   .level_offset = 0x40,
+};
+
 static const struct udevice_id meson_reset_ids[] = {
-   { .compatible = "amlogic,meson-gxbb-reset" },
-   { .compatible = "amlogic,meson-axg-reset" },
+   {
+   .compatible = "amlogic,meson-gxbb-reset",
+   .data = (ulong)&meson_gxbb_data,
+   },
+   {
+   .compatible = "amlogic,meson-axg-reset",
+   .data = (ulong)&meson_gxbb_data,
+   },
+   {
+   .compatible = "amlogic,meson-a1-reset",
+   .data = (ulong)&meson_a1_data,
+   },
{ }
 };
 
 static int meson_reset_probe(struct udevice *dev)
 {
struct meson_reset_priv *priv = dev_get_priv(dev);
+   priv->drvdata = (struct meson_reset_drvdata *)dev_get_driver_data(dev);
 
return regmap_init_mem(dev_ofnode(dev), &priv->regmap);
 }
-- 
2.25.1



[PATCH v1 1/8] dt-bindings: reset: add Meson A1 reset bindings

2023-10-02 Thread Alexey Romanov
Get this from Linux 6.6-rc3.

Signed-off-by: Alexey Romanov 
---
 .../reset/amlogic,meson-a1-reset.h| 76 +++
 1 file changed, 76 insertions(+)
 create mode 100644 include/dt-bindings/reset/amlogic,meson-a1-reset.h

diff --git a/include/dt-bindings/reset/amlogic,meson-a1-reset.h 
b/include/dt-bindings/reset/amlogic,meson-a1-reset.h
new file mode 100644
index 00..2c749c655e
--- /dev/null
+++ b/include/dt-bindings/reset/amlogic,meson-a1-reset.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ * Author: Xingyu Chen 
+ *
+ * Copyright (c) 2023, SberDevices, Inc.
+ * Author: Alexey Romanov 
+ */
+
+#ifndef _DT_BINDINGS_AMLOGIC_MESON_A1_RESET_H
+#define _DT_BINDINGS_AMLOGIC_MESON_A1_RESET_H
+
+/* RESET0  */
+/* 0   */
+#define RESET_AM2AXI_VAD   1
+/* 2-3 */
+#define RESET_PSRAM4
+#define RESET_PAD_CTRL 5
+/* 6   */
+#define RESET_TEMP_SENSOR  7
+#define RESET_AM2AXI_DEV   8
+/* 9   */
+#define RESET_SPICC_A  10
+#define RESET_MSR_CLK  11
+#define RESET_AUDIO12
+#define RESET_ANALOG_CTRL  13
+#define RESET_SAR_ADC  14
+#define RESET_AUDIO_VAD15
+#define RESET_CEC  16
+#define RESET_PWM_EF   17
+#define RESET_PWM_CD   18
+#define RESET_PWM_AB   19
+/* 20  */
+#define RESET_IR_CTRL  21
+#define RESET_I2C_S_A  22
+/* 23  */
+#define RESET_I2C_M_D  24
+#define RESET_I2C_M_C  25
+#define RESET_I2C_M_B  26
+#define RESET_I2C_M_A  27
+#define RESET_I2C_PROD_AHB 28
+#define RESET_I2C_PROD 29
+/* 30-31   */
+
+/* RESET1  */
+#define RESET_ACODEC   32
+#define RESET_DMA  33
+#define RESET_SD_EMMC_A34
+/* 35  */
+#define RESET_USBCTRL  36
+/* 37  */
+#define RESET_USBPHY   38
+/* 39-41   */
+#define RESET_RSA  42
+#define RESET_DMC  43
+/* 44  */
+#define RESET_IRQ_CTRL 45
+/* 46  */
+#define RESET_NIC_VAD  47
+#define RESET_NIC_AXI  48
+#define RESET_RAMA 49
+#define RESET_RAMB 50
+/* 51-52   */
+#define RESET_ROM  53
+#define RESET_SPIFC54
+#define RESET_GIC  55
+#define RESET_UART_C   56
+#define RESET_UART_B   57
+#define RESET_UART_A   58
+#define RESET_OSC_RING 59
+/* 60-63   */
+
+/* RESET2  */
+/* 64-95   */
+
+#endif
-- 
2.25.1



[PATCH v1 4/8] phy: move clk enable/disable in init/exit

2023-10-02 Thread Alexey Romanov
It is better to place clk_enable() in phy_meson_g12a_usb2_init()
and clk_disable() in phy_meson_g12a_usb2_exit().

For more detailed information, please see comments in the review of
a similar driver in the Linux Kernel:

https://lore.kernel.org/all/CAFBinCCEhobbyKHuKDWzTYCQWgNT1-e8=7hmhq1mvt6cueo...@mail.gmail.com/

Signed-off-by: Alexey Romanov 
---
 drivers/phy/meson-g12a-usb2.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/phy/meson-g12a-usb2.c b/drivers/phy/meson-g12a-usb2.c
index 2e366b16ae..7b028784a0 100644
--- a/drivers/phy/meson-g12a-usb2.c
+++ b/drivers/phy/meson-g12a-usb2.c
@@ -160,6 +160,14 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
int ret;
 
+#if CONFIG_IS_ENABLED(CLK)
+   ret = clk_enable(&priv->clk);
+   if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
+   pr_err("failed to enable PHY clock\n");
+   return ret;
+   }
+#endif
+
ret = reset_assert(&priv->reset);
udelay(1);
ret |= reset_deassert(&priv->reset);
@@ -252,6 +260,10 @@ static int phy_meson_g12a_usb2_exit(struct phy *phy)
struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
int ret;
 
+#if CONFIG_IS_ENABLED(CLK)
+   clk_disable(&priv->clk);
+#endif
+
ret = reset_assert(&priv->reset);
if (ret)
return ret;
@@ -289,13 +301,6 @@ int meson_g12a_usb2_phy_probe(struct udevice *dev)
ret = clk_get_by_index(dev, 0, &priv->clk);
if (ret < 0)
return ret;
-
-   ret = clk_enable(&priv->clk);
-   if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
-   pr_err("failed to enable PHY clock\n");
-   clk_free(&priv->clk);
-   return ret;
-   }
 #endif
 
return 0;
-- 
2.25.1



[PATCH v1 6/8] a1: clk: Add missing CLKID_USB_PHY_IN gate

2023-10-02 Thread Alexey Romanov
From: Igor Prusov 

We use this clock in dwc3 driver.

Signed-off-by: Igor Prusov 
---
 drivers/clk/meson/a1.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/clk/meson/a1.c b/drivers/clk/meson/a1.c
index 3aec42f33b..1540e1875b 100644
--- a/drivers/clk/meson/a1.c
+++ b/drivers/clk/meson/a1.c
@@ -238,6 +238,9 @@ static const struct meson_clk_info *meson_clocks[] = {
[CLKID_FIXPLL_IN] = CLK_GATE("fixpll_in", A1_SYS_OSCIN_CTRL, 1,
EXTERNAL_XTAL
),
+   [CLKID_USB_PHY_IN] = CLK_GATE("usb_phy_in", A1_SYS_OSCIN_CTRL, 2,
+   EXTERNAL_XTAL
+   ),
[CLKID_SARADC] = CLK_GATE("saradc", A1_SAR_ADC_CLK_CTR, 8,
-ENOENT
),
-- 
2.25.1



[PATCH v1 3/8] phy: get rid of raw hex values

2023-10-02 Thread Alexey Romanov
It is better to use defines instead of write raw
hex values in regmap.

Signed-off-by: Alexey Romanov 
---
 drivers/phy/meson-g12a-usb2.c | 161 --
 1 file changed, 153 insertions(+), 8 deletions(-)

diff --git a/drivers/phy/meson-g12a-usb2.c b/drivers/phy/meson-g12a-usb2.c
index 650b88bd18..2e366b16ae 100644
--- a/drivers/phy/meson-g12a-usb2.c
+++ b/drivers/phy/meson-g12a-usb2.c
@@ -23,12 +23,28 @@
 
 #include 
 #include 
+#include 
 
 #define PHY_CTRL_R00x0
 #define PHY_CTRL_R10x4
 #define PHY_CTRL_R20x8
+
 #define PHY_CTRL_R30xc
+   #define PHY_CTRL_R3_SQUELCH_REF GENMASK(1, 0)
+   #define PHY_CTRL_R3_HSDIC_REF   GENMASK(3, 2)
+   #define PHY_CTRL_R3_DISC_THRESH GENMASK(7, 4)
+
 #define PHY_CTRL_R40x10
+   #define PHY_CTRL_R4_CALIB_CODE_7_0  GENMASK(7, 0)
+   #define PHY_CTRL_R4_CALIB_CODE_15_8 GENMASK(15, 8)
+   #define PHY_CTRL_R4_CALIB_CODE_23_16GENMASK(23, 16)
+   #define PHY_CTRL_R4_I_C2L_CAL_ENBIT(24)
+   #define PHY_CTRL_R4_I_C2L_CAL_RESET_N   BIT(25)
+   #define PHY_CTRL_R4_I_C2L_CAL_DONE  BIT(26)
+   #define PHY_CTRL_R4_TEST_BYPASS_MODE_EN BIT(27)
+   #define PHY_CTRL_R4_I_C2L_BIAS_TRIM_1_0 GENMASK(29, 28)
+   #define PHY_CTRL_R4_I_C2L_BIAS_TRIM_3_2 GENMASK(31, 30)
+
 #define PHY_CTRL_R50x14
 #define PHY_CTRL_R60x18
 #define PHY_CTRL_R70x1c
@@ -37,15 +53,93 @@
 #define PHY_CTRL_R10   0x28
 #define PHY_CTRL_R11   0x2c
 #define PHY_CTRL_R12   0x30
+
 #define PHY_CTRL_R13   0x34
+   #define PHY_CTRL_R13_CUSTOM_PATTERN_19  GENMASK(7, 0)
+   #define PHY_CTRL_R13_LOAD_STAT  BIT(14)
+   #define PHY_CTRL_R13_UPDATE_PMA_SIGNALS BIT(15)
+   #define PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET GENMASK(20, 16)
+   #define PHY_CTRL_R13_CLEAR_HOLD_HS_DISCONNECT   BIT(21)
+   #define PHY_CTRL_R13_BYPASS_HOST_DISCONNECT_VAL BIT(22)
+   #define PHY_CTRL_R13_BYPASS_HOST_DISCONNECT_EN  BIT(23)
+   #define PHY_CTRL_R13_I_C2L_HS_ENBIT(24)
+   #define PHY_CTRL_R13_I_C2L_FS_ENBIT(25)
+   #define PHY_CTRL_R13_I_C2L_LS_ENBIT(26)
+   #define PHY_CTRL_R13_I_C2L_HS_OEBIT(27)
+   #define PHY_CTRL_R13_I_C2L_FS_OEBIT(28)
+   #define PHY_CTRL_R13_I_C2L_HS_RX_EN BIT(29)
+   #define PHY_CTRL_R13_I_C2L_FSLS_RX_EN   BIT(30)
+
 #define PHY_CTRL_R14   0x38
 #define PHY_CTRL_R15   0x3c
+
 #define PHY_CTRL_R16   0x40
+   #define PHY_CTRL_R16_MPLL_M GENMASK(8, 0)
+   #define PHY_CTRL_R16_MPLL_N GENMASK(14, 10)
+   #define PHY_CTRL_R16_MPLL_TDC_MODE  BIT(20)
+   #define PHY_CTRL_R16_MPLL_SDM_ENBIT(21)
+   #define PHY_CTRL_R16_MPLL_LOAD  BIT(22)
+   #define PHY_CTRL_R16_MPLL_DCO_SDM_ENBIT(23)
+   #define PHY_CTRL_R16_MPLL_LOCK_LONG GENMASK(25, 24)
+   #define PHY_CTRL_R16_MPLL_LOCK_FBIT(26)
+   #define PHY_CTRL_R16_MPLL_FAST_LOCK BIT(27)
+   #define PHY_CTRL_R16_MPLL_ENBIT(28)
+   #define PHY_CTRL_R16_MPLL_RESET BIT(29)
+   #define PHY_CTRL_R16_MPLL_LOCK  BIT(30)
+   #define PHY_CTRL_R16_MPLL_LOCK_DIG  BIT(31)
+
 #define PHY_CTRL_R17   0x44
+   #define PHY_CTRL_R17_MPLL_FRAC_IN   GENMASK(13, 0)
+   #define PHY_CTRL_R17_MPLL_FIX_ENBIT(16)
+   #define PHY_CTRL_R17_MPLL_LAMBDA1   GENMASK(19, 17)
+   #define PHY_CTRL_R17_MPLL_LAMBDA0   GENMASK(22, 20)
+   #define PHY_CTRL_R17_MPLL_FILTER_MODE   BIT(23)
+   #define PHY_CTRL_R17_MPLL_FILTER_PVT2   GENMASK(27, 24)
+   #define

[PATCH v1 5/8] phy: support Amlogic A1 family

2023-10-02 Thread Alexey Romanov
Setting G12A and A1 is similar, so we can use G12A phy
driver with little changes.

Signed-off-by: Alexey Romanov 
---
 drivers/phy/Kconfig   |  2 +-
 drivers/phy/meson-g12a-usb2.c | 77 ---
 2 files changed, 64 insertions(+), 15 deletions(-)

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index cf4d5908d7..60be62907d 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -190,7 +190,7 @@ config MESON_GXL_USB_PHY
 
 config MESON_G12A_USB_PHY
bool "Amlogic Meson G12A USB PHYs"
-   depends on PHY && ARCH_MESON && MESON_G12A
+   depends on PHY && ARCH_MESON && (MESON_G12A || MESON_A1)
imply REGMAP
help
  This is the generic phy driver for the Amlogic Meson G12A
diff --git a/drivers/phy/meson-g12a-usb2.c b/drivers/phy/meson-g12a-usb2.c
index 7b028784a0..c1b9baa7b7 100644
--- a/drivers/phy/meson-g12a-usb2.c
+++ b/drivers/phy/meson-g12a-usb2.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -146,18 +147,28 @@
 #define RESET_COMPLETE_TIME1000
 #define PLL_RESET_COMPLETE_TIME100
 
+enum meson_soc_id {
+   MESON_SOC_A1,
+   MESON_SOC_G12A,
+};
+
 struct phy_meson_g12a_usb2_priv {
struct regmap   *regmap;
 #if CONFIG_IS_ENABLED(CLK)
struct clk  clk;
 #endif
struct reset_ctlreset;
+#if CONFIG_IS_ENABLED(POWER_DOMAIN)
+   struct power_domain pwrdm;
+#endif
+   int soc_id;
 };
 
 static int phy_meson_g12a_usb2_init(struct phy *phy)
 {
struct udevice *dev = phy->dev;
struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
+   u32 value;
int ret;
 
 #if CONFIG_IS_ENABLED(CLK)
@@ -196,8 +207,7 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
FIELD_PREP(PHY_CTRL_R17_MPLL_FILTER_PVT2, 2) |
FIELD_PREP(PHY_CTRL_R17_MPLL_FILTER_PVT1, 9));
 
-   regmap_write(priv->regmap, PHY_CTRL_R18,
-   FIELD_PREP(PHY_CTRL_R18_MPLL_LKW_SEL, 1) |
+   value = FIELD_PREP(PHY_CTRL_R18_MPLL_LKW_SEL, 1) |
FIELD_PREP(PHY_CTRL_R18_MPLL_LK_W, 9) |
FIELD_PREP(PHY_CTRL_R18_MPLL_LK_S, 0x27) |
FIELD_PREP(PHY_CTRL_R18_MPLL_PFD_GAIN, 1) |
@@ -209,6 +219,11 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
FIELD_PREP(PHY_CTRL_R18_MPLL_ADJ_LDO, 1) |
PHY_CTRL_R18_MPLL_ACG_RANGE;
 
+   if (priv->soc_id == MESON_SOC_A1)
+   value |= PHY_CTRL_R18_MPLL_DCO_CLK_SEL;
+
+   regmap_write(priv->regmap, PHY_CTRL_R18, value);
+
udelay(PLL_RESET_COMPLETE_TIME);
 
/* UnReset PLL */
@@ -231,13 +246,19 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
FIELD_PREP(PHY_CTRL_R20_USB2_BGR_VREF_4_0, 0) |
FIELD_PREP(PHY_CTRL_R20_USB2_BGR_DBG_1_0, 0));
 
-   regmap_write(priv->regmap, PHY_CTRL_R4,
-   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_7_0, 0xf) |
-   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_15_8, 0xf) |
-   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_23_16, 0xf) |
-   PHY_CTRL_R4_TEST_BYPASS_MODE_EN |
-   FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_1_0, 0) |
-   FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_3_2, 0));
+   if (priv->soc_id == MESON_SOC_G12A)
+   regmap_write(priv->regmap, PHY_CTRL_R4,
+   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_7_0, 0xf) |
+   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_15_8, 0xf) |
+   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_23_16, 0xf) |
+   PHY_CTRL_R4_TEST_BYPASS_MODE_EN |
+   FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_1_0, 0) |
+   FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_3_2, 0));
+   else if (priv->soc_id == MESON_SOC_A1)
+   regmap_write(priv->regmap, PHY_CTRL_R21,
+   PHY_CTRL_R21_USB2_CAL_ACK_EN |
+   PHY_CTRL_R21_USB2_TX_STRG_PD |
+   FIELD_PREP(PHY_CTRL_R21_USB2_OTG_ACA_TRIM_1_0, 2));
 
/* Tuning Disconnect Threshold */
regmap_write(priv->regmap, PHY_CTRL_R3,
@@ -246,10 +267,15 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
FIELD_PREP(PHY_CTRL_R3_DISC_THRESH, 3));
 
/* Analog Settings */
-   regmap_write(priv->regmap, PHY_CTRL_R14, 0);
-   regmap_write(priv->regmap, PHY_CTRL_R13,
-   PHY_CTRL_R13_UPDATE_PMA_SIGNALS |
-   FIELD_PREP(PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET, 7));
+   if (priv->soc_id == MESON_SOC_G12A) {
+   regmap_write(priv->regmap, PHY_CTRL_R14, 0);
+   regmap_write(priv->regmap, PHY_CTRL_R13,
+   PHY_CTRL_R13_UPDATE_PMA_SIGNALS |
+   FIELD_PREP(PH

[PATCH v1 7/8] dwc3: add support for Amlogic A1 family

2023-10-02 Thread Alexey Romanov
Now the driver supports also A1 phy layer.

Signed-off-by: Alexey Romanov 
---
 drivers/usb/dwc3/dwc3-meson-g12a.c | 73 ++
 1 file changed, 63 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c 
b/drivers/usb/dwc3/dwc3-meson-g12a.c
index 90418ddc1d..550e6682a2 100644
--- a/drivers/usb/dwc3/dwc3-meson-g12a.c
+++ b/drivers/usb/dwc3/dwc3-meson-g12a.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* USB2 Ports Control Registers */
 
@@ -102,10 +103,22 @@ enum {
PHY_COUNT,
 };
 
-static const char *phy_names[PHY_COUNT] = {
+static const char *const dwc3_meson_g12a_phy_names[] = {
"usb2-phy0", "usb2-phy1", "usb3-phy0",
 };
 
+static const char *const dwc3_meson_a1_phy_names[] = {
+   "usb2-phy0", "usb2-phy1"
+};
+
+struct dwc3_meson_g12a;
+
+struct dwc3_meson_g12a_drvdata {
+   const char *const *phy_names;
+   unsigned int phy_cnt;
+   int (*clk_init)(struct dwc3_meson_g12a *priv);
+};
+
 struct dwc3_meson_g12a {
struct udevice  *dev;
struct regmap   *regmap;
@@ -119,6 +132,7 @@ struct dwc3_meson_g12a {
 #if CONFIG_IS_ENABLED(DM_REGULATOR)
struct udevice  *vbus_supply;
 #endif
+   struct dwc3_meson_g12a_drvdata *drvdata;
 };
 
 #define U2P_REG_SIZE   0x20
@@ -293,10 +307,11 @@ int dwc3_meson_g12a_force_mode(struct udevice *dev, enum 
usb_dr_mode mode)
 
 static int dwc3_meson_g12a_get_phys(struct dwc3_meson_g12a *priv)
 {
+   struct dwc3_meson_g12a_drvdata *data = priv->drvdata;
int i, ret;
 
-   for (i = 0 ; i < PHY_COUNT ; ++i) {
-   ret = generic_phy_get_by_name(priv->dev, phy_names[i],
+   for (i = 0 ; i < data->phy_cnt; ++i) {
+   ret = generic_phy_get_by_name(priv->dev, data->phy_names[i],
  &priv->phys[i]);
if (ret == -ENOENT || ret == -ENODATA)
continue;
@@ -354,18 +369,36 @@ static int dwc3_meson_g12a_clk_init(struct 
dwc3_meson_g12a *priv)
return 0;
 }
 
+static int dwc3_meson_a1_clk_init(struct dwc3_meson_g12a *priv)
+{
+   int ret;
+
+   ret = clk_get_by_name(priv->dev, "usb_bus", &priv->clk);
+   if (ret)
+   return ret;
+
+   ret = clk_enable(&priv->clk);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
 static int dwc3_meson_g12a_probe(struct udevice *dev)
 {
struct dwc3_meson_g12a *priv = dev_get_plat(dev);
+   struct dwc3_meson_g12a_drvdata *data =
+   (struct dwc3_meson_g12a_drvdata *)dev_get_driver_data(dev);
int ret, i;
 
+   priv->drvdata = data;
priv->dev = dev;
 
ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
if (ret)
return ret;
 
-   ret = dwc3_meson_g12a_clk_init(priv);
+   ret = data->clk_init(priv);
if (ret)
return ret;
 
@@ -398,7 +431,7 @@ static int dwc3_meson_g12a_probe(struct udevice *dev)
if (ret)
return ret;
 
-   for (i = 0 ; i < PHY_COUNT ; ++i) {
+   for (i = 0 ; i < data->phy_cnt; ++i) {
if (!priv->phys[i].dev)
continue;
 
@@ -407,7 +440,7 @@ static int dwc3_meson_g12a_probe(struct udevice *dev)
goto err_phy_init;
}
 
-   for (i = 0; i < PHY_COUNT; ++i) {
+   for (i = 0; i < data->phy_cnt; ++i) {
if (!priv->phys[i].dev)
continue;
 
@@ -419,7 +452,7 @@ static int dwc3_meson_g12a_probe(struct udevice *dev)
return 0;
 
 err_phy_init:
-   for (i = 0 ; i < PHY_COUNT ; ++i) {
+   for (i = 0 ; i < data->phy_cnt ; ++i) {
if (!priv->phys[i].dev)
continue;
 
@@ -432,20 +465,21 @@ err_phy_init:
 static int dwc3_meson_g12a_remove(struct udevice *dev)
 {
struct dwc3_meson_g12a *priv = dev_get_plat(dev);
+   struct dwc3_meson_g12a_drvdata *data = priv->drvdata;
int i;
 
reset_release_all(&priv->reset, 1);
 
clk_release_all(&priv->clk, 1);
 
-   for (i = 0; i < PHY_COUNT; ++i) {
+   for (i = 0; i < data->phy_cnt; ++i) {
if (!priv->phys[i].dev)
continue;
 
 generic_phy_power_off(&priv->phys[i]);
}
 
-   for (i = 0 ; i < PHY_COUNT ; ++i) {
+   for (i = 0 ; i < data->phy_cnt; ++i) {
if (!priv->phys[i].dev)
continue;
 
@@ -455,8 +489,27 @@ static int dwc3_meson_g12a_remove(struct udevice *dev)
return dm_scan_fdt_dev(dev);
 }
 
+static const struct dwc3_meson_g12a_drvdata meson_g12a_drvdata = {
+   .phy_names = dwc3_meson_g12a_

[PATCH v1 8/8] arch: a1: introduce USB initialization functionality

2023-10-02 Thread Alexey Romanov
This is entrypoint for USB stack initialization. Function
board_usb_init will be called from cmd/fastboot.c code.

Signed-off-by: Alexey Romanov 
---
 arch/arm/mach-meson/board-a1.c | 89 ++
 1 file changed, 89 insertions(+)

diff --git a/arch/arm/mach-meson/board-a1.c b/arch/arm/mach-meson/board-a1.c
index 967bb67182..781d5cfb33 100644
--- a/arch/arm/mach-meson/board-a1.c
+++ b/arch/arm/mach-meson/board-a1.c
@@ -4,12 +4,17 @@
  */
 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 
 phys_size_t get_effective_memsize(void)
 {
@@ -57,3 +62,87 @@ static struct mm_region a1_mem_map[] = {
 };
 
 struct mm_region *mem_map = a1_mem_map;
+
+#if CONFIG_IS_ENABLED(USB_DWC3_MESON_G12A) && \
+   CONFIG_IS_ENABLED(USB_GADGET_DWC2_OTG)
+
+static struct dwc2_plat_otg_data meson_a1_dwc2_data;
+
+int board_usb_init(int index, enum usb_init_type init)
+{
+   int node, dwc2_node;
+   const void *blob = gd->fdt_blob;
+   struct udevice *dev;
+   int ret;
+
+   node = fdt_node_offset_by_compatible(blob, -1,
+"amlogic,meson-a1-usb-ctrl");
+   if (node < 0) {
+   pr_err("not found usb-control node\n");
+   return -ENODEV;
+   }
+
+   if (!fdtdec_get_is_enabled(blob, node)) {
+   pr_err("usb is disabled in the device tree\n");
+   return -ENODEV;
+   }
+
+   ret = uclass_get_device_by_of_offset(UCLASS_SIMPLE_BUS, node, &dev);
+   if (ret) {
+   pr_err("not found usb-control device\n");
+   return ret;
+   }
+
+   dwc2_node = fdt_node_offset_by_compatible(blob, node,
+ "amlogic,meson-a1-usb");
+   if (dwc2_node < 0) {
+   pr_err("not found dwc2 node\n");
+   return -ENODEV;
+   }
+
+   if (!fdtdec_get_is_enabled(blob, dwc2_node)) {
+   pr_err("dwc2 is disabled in the device tree\n");
+   return -ENODEV;
+   }
+
+   meson_a1_dwc2_data.regs_otg = fdtdec_get_addr(blob, dwc2_node, "reg");
+   if (meson_a1_dwc2_data.regs_otg == FDT_ADDR_T_NONE) {
+   pr_err("can't get base address\n");
+   return -ENODATA;
+   }
+
+   meson_a1_dwc2_data.rx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
+   "g-rx-fifo-size", 0);
+   if (meson_a1_dwc2_data.rx_fifo_sz < 0) {
+   pr_err("failed to get g-rx-fifo-size value\n");
+   return -ENODATA;
+   }
+
+   meson_a1_dwc2_data.np_tx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
+   "g-np-tx-fifo-size", 0);
+   if (meson_a1_dwc2_data.np_tx_fifo_sz < 0) {
+   pr_err("failed to get g-np-tx-fifo-size value\n");
+   return -ENODATA;
+   }
+
+   meson_a1_dwc2_data.tx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
+   "g-tx-fifo-size", 0);
+   if (meson_a1_dwc2_data.tx_fifo_sz < 0) {
+   pr_err("failed to get g-tx-fifo-size value\n");
+   return -ENODATA;
+   }
+
+   ret = dwc3_meson_g12a_force_mode(dev, USB_DR_MODE_PERIPHERAL);
+   if (ret) {
+   pr_err("failed to force usb mode to peripheral\n");
+   return ret;
+   }
+
+   return dwc2_udc_probe(&meson_a1_dwc2_data);
+}
+
+int board_usb_cleanup(int index, enum usb_init_type init)
+{
+   return 0;
+}
+#endif
-- 
2.25.1



[PATCH v2 0/8] Support USB for Meson A1

2023-10-03 Thread Alexey Romanov
Hello!

This patchset adds USB stack support for Amlogic A1 SoC's
series. Made reset / phy / dwc3 drivers more flexible and
added support for A1 board.

V2:

- Made power domain for PHY optional.
- Add missing CLKID_USB_PHY gate.
- Drop patch with USB stack initialization in board-a1.c.
Instead of, enable CONFIG_DM_USB_GADGET for AD401 board.
- Support A1 in g12a_child_pre_probe/post_remove functions
in dwc3 driver.


Alexey Romanov (7):
  dt-bindings: reset: add Meson A1 reset bindings
  reset: add support for Amlogic A1 family
  phy: get rid of raw hex values
  phy: move clk enable/disable in init/exit
  phy: support Amlogic A1 family
  dwc3: add support for Amlogic A1 family
  ad401: enable USB stack

Igor Prusov (1):
  a1: clk: Add missing USB_PHY_IN and USB_PHY gates

 configs/ad401_defconfig   |   3 +
 drivers/clk/meson/a1.c|   6 +
 drivers/phy/Kconfig   |   2 +-
 drivers/phy/meson-g12a-usb2.c | 235 --
 drivers/reset/reset-meson.c   |  42 +++-
 drivers/usb/dwc3/dwc3-meson-g12a.c|  73 +-
 .../reset/amlogic,meson-a1-reset.h|  76 ++
 7 files changed, 403 insertions(+), 34 deletions(-)
 create mode 100644 include/dt-bindings/reset/amlogic,meson-a1-reset.h

-- 
2.25.1



[PATCH v2 1/8] dt-bindings: reset: add Meson A1 reset bindings

2023-10-03 Thread Alexey Romanov
Get this from Linux 6.6-rc3.

Signed-off-by: Alexey Romanov 
Reviewed-by: Neil Armstrong 
---
 .../reset/amlogic,meson-a1-reset.h| 76 +++
 1 file changed, 76 insertions(+)
 create mode 100644 include/dt-bindings/reset/amlogic,meson-a1-reset.h

diff --git a/include/dt-bindings/reset/amlogic,meson-a1-reset.h 
b/include/dt-bindings/reset/amlogic,meson-a1-reset.h
new file mode 100644
index 00..2c749c655e
--- /dev/null
+++ b/include/dt-bindings/reset/amlogic,meson-a1-reset.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ * Author: Xingyu Chen 
+ *
+ * Copyright (c) 2023, SberDevices, Inc.
+ * Author: Alexey Romanov 
+ */
+
+#ifndef _DT_BINDINGS_AMLOGIC_MESON_A1_RESET_H
+#define _DT_BINDINGS_AMLOGIC_MESON_A1_RESET_H
+
+/* RESET0  */
+/* 0   */
+#define RESET_AM2AXI_VAD   1
+/* 2-3 */
+#define RESET_PSRAM4
+#define RESET_PAD_CTRL 5
+/* 6   */
+#define RESET_TEMP_SENSOR  7
+#define RESET_AM2AXI_DEV   8
+/* 9   */
+#define RESET_SPICC_A  10
+#define RESET_MSR_CLK  11
+#define RESET_AUDIO12
+#define RESET_ANALOG_CTRL  13
+#define RESET_SAR_ADC  14
+#define RESET_AUDIO_VAD15
+#define RESET_CEC  16
+#define RESET_PWM_EF   17
+#define RESET_PWM_CD   18
+#define RESET_PWM_AB   19
+/* 20  */
+#define RESET_IR_CTRL  21
+#define RESET_I2C_S_A  22
+/* 23  */
+#define RESET_I2C_M_D  24
+#define RESET_I2C_M_C  25
+#define RESET_I2C_M_B  26
+#define RESET_I2C_M_A  27
+#define RESET_I2C_PROD_AHB 28
+#define RESET_I2C_PROD 29
+/* 30-31   */
+
+/* RESET1  */
+#define RESET_ACODEC   32
+#define RESET_DMA  33
+#define RESET_SD_EMMC_A34
+/* 35  */
+#define RESET_USBCTRL  36
+/* 37  */
+#define RESET_USBPHY   38
+/* 39-41   */
+#define RESET_RSA  42
+#define RESET_DMC  43
+/* 44  */
+#define RESET_IRQ_CTRL 45
+/* 46  */
+#define RESET_NIC_VAD  47
+#define RESET_NIC_AXI  48
+#define RESET_RAMA 49
+#define RESET_RAMB 50
+/* 51-52   */
+#define RESET_ROM  53
+#define RESET_SPIFC54
+#define RESET_GIC  55
+#define RESET_UART_C   56
+#define RESET_UART_B   57
+#define RESET_UART_A   58
+#define RESET_OSC_RING 59
+/* 60-63   */
+
+/* RESET2  */
+/* 64-95   */
+
+#endif
-- 
2.25.1



[PATCH v2 2/8] reset: add support for Amlogic A1 family

2023-10-03 Thread Alexey Romanov
This patch adds reset support for the Amlogic A1 family.
We add the structure meson_reset_drvdata, which in the future
will allow this driver to be used for other families by declaring
only the correct parameters reg_count and level_offset.

Signed-off-by: Alexey Romanov 
Reviewed-by: Neil Armstrong 
---
 drivers/reset/reset-meson.c | 42 +++--
 1 file changed, 36 insertions(+), 6 deletions(-)

diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c
index 64bc696f13..9d0c8b354f 100644
--- a/drivers/reset/reset-meson.c
+++ b/drivers/reset/reset-meson.c
@@ -13,18 +13,26 @@
 #include 
 #include 
 #include 
+#include 
 
-#define REG_COUNT  8
 #define BITS_PER_REG   32
-#define LEVEL_OFFSET   0x7c
+
+struct meson_reset_drvdata {
+   unsigned int reg_count;
+   unsigned int level_offset;
+};
 
 struct meson_reset_priv {
struct regmap *regmap;
+   struct meson_reset_drvdata *drvdata;
 };
 
 static int meson_reset_request(struct reset_ctl *reset_ctl)
 {
-   if (reset_ctl->id > (REG_COUNT * BITS_PER_REG))
+   struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+   struct meson_reset_drvdata *data = priv->drvdata;
+
+   if (reset_ctl->id > (data->reg_count * BITS_PER_REG))
return -EINVAL;
 
return 0;
@@ -33,9 +41,10 @@ static int meson_reset_request(struct reset_ctl *reset_ctl)
 static int meson_reset_level(struct reset_ctl *reset_ctl, bool assert)
 {
struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+   struct meson_reset_drvdata *data = priv->drvdata;
uint bank = reset_ctl->id / BITS_PER_REG;
uint offset = reset_ctl->id % BITS_PER_REG;
-   uint reg_offset = LEVEL_OFFSET + (bank << 2);
+   uint reg_offset = data->level_offset + (bank << 2);
uint val;
 
regmap_read(priv->regmap, reg_offset, &val);
@@ -64,15 +73,36 @@ struct reset_ops meson_reset_ops = {
.rst_deassert = meson_reset_deassert,
 };
 
+static const struct meson_reset_drvdata meson_gxbb_data = {
+   .reg_count = 8,
+   .level_offset = 0x7c,
+};
+
+static const struct meson_reset_drvdata meson_a1_data = {
+   .reg_count = 3,
+   .level_offset = 0x40,
+};
+
 static const struct udevice_id meson_reset_ids[] = {
-   { .compatible = "amlogic,meson-gxbb-reset" },
-   { .compatible = "amlogic,meson-axg-reset" },
+   {
+   .compatible = "amlogic,meson-gxbb-reset",
+   .data = (ulong)&meson_gxbb_data,
+   },
+   {
+   .compatible = "amlogic,meson-axg-reset",
+   .data = (ulong)&meson_gxbb_data,
+   },
+   {
+   .compatible = "amlogic,meson-a1-reset",
+   .data = (ulong)&meson_a1_data,
+   },
{ }
 };
 
 static int meson_reset_probe(struct udevice *dev)
 {
struct meson_reset_priv *priv = dev_get_priv(dev);
+   priv->drvdata = (struct meson_reset_drvdata *)dev_get_driver_data(dev);
 
return regmap_init_mem(dev_ofnode(dev), &priv->regmap);
 }
-- 
2.25.1



[PATCH v2 3/8] phy: get rid of raw hex values

2023-10-03 Thread Alexey Romanov
It is better to use defines instead of write raw
hex values in regmap.

Signed-off-by: Alexey Romanov 
Reviewed-by: Neil Armstrong 
---
 drivers/phy/meson-g12a-usb2.c | 161 --
 1 file changed, 153 insertions(+), 8 deletions(-)

diff --git a/drivers/phy/meson-g12a-usb2.c b/drivers/phy/meson-g12a-usb2.c
index 650b88bd18..2e366b16ae 100644
--- a/drivers/phy/meson-g12a-usb2.c
+++ b/drivers/phy/meson-g12a-usb2.c
@@ -23,12 +23,28 @@
 
 #include 
 #include 
+#include 
 
 #define PHY_CTRL_R00x0
 #define PHY_CTRL_R10x4
 #define PHY_CTRL_R20x8
+
 #define PHY_CTRL_R30xc
+   #define PHY_CTRL_R3_SQUELCH_REF GENMASK(1, 0)
+   #define PHY_CTRL_R3_HSDIC_REF   GENMASK(3, 2)
+   #define PHY_CTRL_R3_DISC_THRESH GENMASK(7, 4)
+
 #define PHY_CTRL_R40x10
+   #define PHY_CTRL_R4_CALIB_CODE_7_0  GENMASK(7, 0)
+   #define PHY_CTRL_R4_CALIB_CODE_15_8 GENMASK(15, 8)
+   #define PHY_CTRL_R4_CALIB_CODE_23_16GENMASK(23, 16)
+   #define PHY_CTRL_R4_I_C2L_CAL_ENBIT(24)
+   #define PHY_CTRL_R4_I_C2L_CAL_RESET_N   BIT(25)
+   #define PHY_CTRL_R4_I_C2L_CAL_DONE  BIT(26)
+   #define PHY_CTRL_R4_TEST_BYPASS_MODE_EN BIT(27)
+   #define PHY_CTRL_R4_I_C2L_BIAS_TRIM_1_0 GENMASK(29, 28)
+   #define PHY_CTRL_R4_I_C2L_BIAS_TRIM_3_2 GENMASK(31, 30)
+
 #define PHY_CTRL_R50x14
 #define PHY_CTRL_R60x18
 #define PHY_CTRL_R70x1c
@@ -37,15 +53,93 @@
 #define PHY_CTRL_R10   0x28
 #define PHY_CTRL_R11   0x2c
 #define PHY_CTRL_R12   0x30
+
 #define PHY_CTRL_R13   0x34
+   #define PHY_CTRL_R13_CUSTOM_PATTERN_19  GENMASK(7, 0)
+   #define PHY_CTRL_R13_LOAD_STAT  BIT(14)
+   #define PHY_CTRL_R13_UPDATE_PMA_SIGNALS BIT(15)
+   #define PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET GENMASK(20, 16)
+   #define PHY_CTRL_R13_CLEAR_HOLD_HS_DISCONNECT   BIT(21)
+   #define PHY_CTRL_R13_BYPASS_HOST_DISCONNECT_VAL BIT(22)
+   #define PHY_CTRL_R13_BYPASS_HOST_DISCONNECT_EN  BIT(23)
+   #define PHY_CTRL_R13_I_C2L_HS_ENBIT(24)
+   #define PHY_CTRL_R13_I_C2L_FS_ENBIT(25)
+   #define PHY_CTRL_R13_I_C2L_LS_ENBIT(26)
+   #define PHY_CTRL_R13_I_C2L_HS_OEBIT(27)
+   #define PHY_CTRL_R13_I_C2L_FS_OEBIT(28)
+   #define PHY_CTRL_R13_I_C2L_HS_RX_EN BIT(29)
+   #define PHY_CTRL_R13_I_C2L_FSLS_RX_EN   BIT(30)
+
 #define PHY_CTRL_R14   0x38
 #define PHY_CTRL_R15   0x3c
+
 #define PHY_CTRL_R16   0x40
+   #define PHY_CTRL_R16_MPLL_M GENMASK(8, 0)
+   #define PHY_CTRL_R16_MPLL_N GENMASK(14, 10)
+   #define PHY_CTRL_R16_MPLL_TDC_MODE  BIT(20)
+   #define PHY_CTRL_R16_MPLL_SDM_ENBIT(21)
+   #define PHY_CTRL_R16_MPLL_LOAD  BIT(22)
+   #define PHY_CTRL_R16_MPLL_DCO_SDM_ENBIT(23)
+   #define PHY_CTRL_R16_MPLL_LOCK_LONG GENMASK(25, 24)
+   #define PHY_CTRL_R16_MPLL_LOCK_FBIT(26)
+   #define PHY_CTRL_R16_MPLL_FAST_LOCK BIT(27)
+   #define PHY_CTRL_R16_MPLL_ENBIT(28)
+   #define PHY_CTRL_R16_MPLL_RESET BIT(29)
+   #define PHY_CTRL_R16_MPLL_LOCK  BIT(30)
+   #define PHY_CTRL_R16_MPLL_LOCK_DIG  BIT(31)
+
 #define PHY_CTRL_R17   0x44
+   #define PHY_CTRL_R17_MPLL_FRAC_IN   GENMASK(13, 0)
+   #define PHY_CTRL_R17_MPLL_FIX_ENBIT(16)
+   #define PHY_CTRL_R17_MPLL_LAMBDA1   GENMASK(19, 17)
+   #define PHY_CTRL_R17_MPLL_LAMBDA0   GENMASK(22, 20)
+   #define PHY_CTRL_R17_MPLL_FILTER_MODE   BIT(23)
+   #define PHY_CTRL_R17_MPLL_FILTER_PVT2   GENMASK(27, 24

[PATCH v2 5/8] phy: support Amlogic A1 family

2023-10-03 Thread Alexey Romanov
Setting G12A and A1 is similar, so we can use G12A phy
driver with little changes.

Signed-off-by: Alexey Romanov 
---
 drivers/phy/Kconfig   |  2 +-
 drivers/phy/meson-g12a-usb2.c | 79 ---
 2 files changed, 66 insertions(+), 15 deletions(-)

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index cf4d5908d7..60be62907d 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -190,7 +190,7 @@ config MESON_GXL_USB_PHY
 
 config MESON_G12A_USB_PHY
bool "Amlogic Meson G12A USB PHYs"
-   depends on PHY && ARCH_MESON && MESON_G12A
+   depends on PHY && ARCH_MESON && (MESON_G12A || MESON_A1)
imply REGMAP
help
  This is the generic phy driver for the Amlogic Meson G12A
diff --git a/drivers/phy/meson-g12a-usb2.c b/drivers/phy/meson-g12a-usb2.c
index 7b028784a0..90053dbea3 100644
--- a/drivers/phy/meson-g12a-usb2.c
+++ b/drivers/phy/meson-g12a-usb2.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -146,18 +147,28 @@
 #define RESET_COMPLETE_TIME1000
 #define PLL_RESET_COMPLETE_TIME100
 
+enum meson_soc_id {
+   MESON_SOC_A1,
+   MESON_SOC_G12A,
+};
+
 struct phy_meson_g12a_usb2_priv {
struct regmap   *regmap;
 #if CONFIG_IS_ENABLED(CLK)
struct clk  clk;
 #endif
struct reset_ctlreset;
+#if CONFIG_IS_ENABLED(POWER_DOMAIN)
+   struct power_domain pwrdm;
+#endif
+   int soc_id;
 };
 
 static int phy_meson_g12a_usb2_init(struct phy *phy)
 {
struct udevice *dev = phy->dev;
struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
+   u32 value;
int ret;
 
 #if CONFIG_IS_ENABLED(CLK)
@@ -196,8 +207,7 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
FIELD_PREP(PHY_CTRL_R17_MPLL_FILTER_PVT2, 2) |
FIELD_PREP(PHY_CTRL_R17_MPLL_FILTER_PVT1, 9));
 
-   regmap_write(priv->regmap, PHY_CTRL_R18,
-   FIELD_PREP(PHY_CTRL_R18_MPLL_LKW_SEL, 1) |
+   value = FIELD_PREP(PHY_CTRL_R18_MPLL_LKW_SEL, 1) |
FIELD_PREP(PHY_CTRL_R18_MPLL_LK_W, 9) |
FIELD_PREP(PHY_CTRL_R18_MPLL_LK_S, 0x27) |
FIELD_PREP(PHY_CTRL_R18_MPLL_PFD_GAIN, 1) |
@@ -209,6 +219,11 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
FIELD_PREP(PHY_CTRL_R18_MPLL_ADJ_LDO, 1) |
PHY_CTRL_R18_MPLL_ACG_RANGE;
 
+   if (priv->soc_id == MESON_SOC_A1)
+   value |= PHY_CTRL_R18_MPLL_DCO_CLK_SEL;
+
+   regmap_write(priv->regmap, PHY_CTRL_R18, value);
+
udelay(PLL_RESET_COMPLETE_TIME);
 
/* UnReset PLL */
@@ -231,13 +246,19 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
FIELD_PREP(PHY_CTRL_R20_USB2_BGR_VREF_4_0, 0) |
FIELD_PREP(PHY_CTRL_R20_USB2_BGR_DBG_1_0, 0));
 
-   regmap_write(priv->regmap, PHY_CTRL_R4,
-   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_7_0, 0xf) |
-   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_15_8, 0xf) |
-   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_23_16, 0xf) |
-   PHY_CTRL_R4_TEST_BYPASS_MODE_EN |
-   FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_1_0, 0) |
-   FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_3_2, 0));
+   if (priv->soc_id == MESON_SOC_G12A)
+   regmap_write(priv->regmap, PHY_CTRL_R4,
+   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_7_0, 0xf) |
+   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_15_8, 0xf) |
+   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_23_16, 0xf) |
+   PHY_CTRL_R4_TEST_BYPASS_MODE_EN |
+   FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_1_0, 0) |
+   FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_3_2, 0));
+   else if (priv->soc_id == MESON_SOC_A1)
+   regmap_write(priv->regmap, PHY_CTRL_R21,
+   PHY_CTRL_R21_USB2_CAL_ACK_EN |
+   PHY_CTRL_R21_USB2_TX_STRG_PD |
+   FIELD_PREP(PHY_CTRL_R21_USB2_OTG_ACA_TRIM_1_0, 2));
 
/* Tuning Disconnect Threshold */
regmap_write(priv->regmap, PHY_CTRL_R3,
@@ -246,10 +267,15 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
FIELD_PREP(PHY_CTRL_R3_DISC_THRESH, 3));
 
/* Analog Settings */
-   regmap_write(priv->regmap, PHY_CTRL_R14, 0);
-   regmap_write(priv->regmap, PHY_CTRL_R13,
-   PHY_CTRL_R13_UPDATE_PMA_SIGNALS |
-   FIELD_PREP(PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET, 7));
+   if (priv->soc_id == MESON_SOC_G12A) {
+   regmap_write(priv->regmap, PHY_CTRL_R14, 0);
+   regmap_write(priv->regmap, PHY_CTRL_R13,
+   PHY_CTRL_R13_UPDATE_PMA_SIGNALS |
+   FIELD_PREP(PH

[PATCH v2 4/8] phy: move clk enable/disable in init/exit

2023-10-03 Thread Alexey Romanov
It is better to place clk_enable() in phy_meson_g12a_usb2_init()
and clk_disable() in phy_meson_g12a_usb2_exit().

For more detailed information, please see comments in the review of
a similar driver in the Linux Kernel:

https://lore.kernel.org/all/CAFBinCCEhobbyKHuKDWzTYCQWgNT1-e8=7hmhq1mvt6cueo...@mail.gmail.com/

Signed-off-by: Alexey Romanov 
Reviewed-by: Neil Armstrong 
---
 drivers/phy/meson-g12a-usb2.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/phy/meson-g12a-usb2.c b/drivers/phy/meson-g12a-usb2.c
index 2e366b16ae..7b028784a0 100644
--- a/drivers/phy/meson-g12a-usb2.c
+++ b/drivers/phy/meson-g12a-usb2.c
@@ -160,6 +160,14 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
int ret;
 
+#if CONFIG_IS_ENABLED(CLK)
+   ret = clk_enable(&priv->clk);
+   if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
+   pr_err("failed to enable PHY clock\n");
+   return ret;
+   }
+#endif
+
ret = reset_assert(&priv->reset);
udelay(1);
ret |= reset_deassert(&priv->reset);
@@ -252,6 +260,10 @@ static int phy_meson_g12a_usb2_exit(struct phy *phy)
struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
int ret;
 
+#if CONFIG_IS_ENABLED(CLK)
+   clk_disable(&priv->clk);
+#endif
+
ret = reset_assert(&priv->reset);
if (ret)
return ret;
@@ -289,13 +301,6 @@ int meson_g12a_usb2_phy_probe(struct udevice *dev)
ret = clk_get_by_index(dev, 0, &priv->clk);
if (ret < 0)
return ret;
-
-   ret = clk_enable(&priv->clk);
-   if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
-   pr_err("failed to enable PHY clock\n");
-   clk_free(&priv->clk);
-   return ret;
-   }
 #endif
 
return 0;
-- 
2.25.1



[PATCH v2 8/8] ad401: enable USB stack

2023-10-03 Thread Alexey Romanov
Currently we have all drivers for use USB stack on A1-series
SoC's. Let's enable USB options for the Amlogic AD401 reference A1
SoC board.

Signed-off-by: Alexey Romanov 
---
 configs/ad401_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/configs/ad401_defconfig b/configs/ad401_defconfig
index 529e553bac..b02ff47b7a 100644
--- a/configs/ad401_defconfig
+++ b/configs/ad401_defconfig
@@ -51,4 +51,7 @@ CONFIG_DEBUG_UART_SKIP_INIT=y
 CONFIG_MESON_SERIAL=y
 CONFIG_SPI=y
 CONFIG_DM_SPI=y
+CONFIG_USB=y
+CONFIG_DM_USB_GADGET=y
+CONFIG_USB_GADGET=y
 CONFIG_WDT=y
-- 
2.25.1



[PATCH v2 6/8] a1: clk: Add missing USB_PHY_IN and USB_PHY gates

2023-10-03 Thread Alexey Romanov
From: Igor Prusov 

We use this clocks in dwc3 driver.

Signed-off-by: Igor Prusov 
Signed-off-by: Alexey Romanov 
---
 drivers/clk/meson/a1.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/clk/meson/a1.c b/drivers/clk/meson/a1.c
index 3aec42f33b..1075ba7333 100644
--- a/drivers/clk/meson/a1.c
+++ b/drivers/clk/meson/a1.c
@@ -238,6 +238,12 @@ static const struct meson_clk_info *meson_clocks[] = {
[CLKID_FIXPLL_IN] = CLK_GATE("fixpll_in", A1_SYS_OSCIN_CTRL, 1,
EXTERNAL_XTAL
),
+   [CLKID_USB_PHY_IN] = CLK_GATE("usb_phy_in", A1_SYS_OSCIN_CTRL, 2,
+   EXTERNAL_XTAL
+   ),
+   [CLKID_USB_PHY] = CLK_GATE("usb_phy", A1_SYS_CLK_EN0, 27,
+   CLKID_SYS
+   ),
[CLKID_SARADC] = CLK_GATE("saradc", A1_SAR_ADC_CLK_CTR, 8,
-ENOENT
),
-- 
2.25.1



[PATCH v2 7/8] dwc3: add support for Amlogic A1 family

2023-10-03 Thread Alexey Romanov
Now the driver supports also A1 phy layer.

Signed-off-by: Alexey Romanov 
Reviewed-by: Neil Armstrong 
---
 drivers/usb/dwc3/dwc3-meson-g12a.c | 73 ++
 1 file changed, 63 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c 
b/drivers/usb/dwc3/dwc3-meson-g12a.c
index 195670e4ca..5433ac0dca 100644
--- a/drivers/usb/dwc3/dwc3-meson-g12a.c
+++ b/drivers/usb/dwc3/dwc3-meson-g12a.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* USB2 Ports Control Registers */
 
@@ -102,10 +103,22 @@ enum {
PHY_COUNT,
 };
 
-static const char *phy_names[PHY_COUNT] = {
+static const char *const dwc3_meson_g12a_phy_names[] = {
"usb2-phy0", "usb2-phy1", "usb3-phy0",
 };
 
+static const char *const dwc3_meson_a1_phy_names[] = {
+   "usb2-phy0", "usb2-phy1"
+};
+
+struct dwc3_meson_g12a;
+
+struct dwc3_meson_g12a_drvdata {
+   const char *const *phy_names;
+   unsigned int phy_cnt;
+   int (*clk_init)(struct dwc3_meson_g12a *priv);
+};
+
 struct dwc3_meson_g12a {
struct udevice  *dev;
struct regmap   *regmap;
@@ -119,6 +132,7 @@ struct dwc3_meson_g12a {
 #if CONFIG_IS_ENABLED(DM_REGULATOR)
struct udevice  *vbus_supply;
 #endif
+   struct dwc3_meson_g12a_drvdata *drvdata;
 };
 
 #define U2P_REG_SIZE   0x20
@@ -293,10 +307,11 @@ int dwc3_meson_g12a_force_mode(struct udevice *dev, enum 
usb_dr_mode mode)
 
 static int dwc3_meson_g12a_get_phys(struct dwc3_meson_g12a *priv)
 {
+   struct dwc3_meson_g12a_drvdata *data = priv->drvdata;
int i, ret;
 
-   for (i = 0 ; i < PHY_COUNT ; ++i) {
-   ret = generic_phy_get_by_name(priv->dev, phy_names[i],
+   for (i = 0 ; i < data->phy_cnt; ++i) {
+   ret = generic_phy_get_by_name(priv->dev, data->phy_names[i],
  &priv->phys[i]);
if (ret == -ENOENT || ret == -ENODATA)
continue;
@@ -354,18 +369,36 @@ static int dwc3_meson_g12a_clk_init(struct 
dwc3_meson_g12a *priv)
return 0;
 }
 
+static int dwc3_meson_a1_clk_init(struct dwc3_meson_g12a *priv)
+{
+   int ret;
+
+   ret = clk_get_by_name(priv->dev, "usb_bus", &priv->clk);
+   if (ret)
+   return ret;
+
+   ret = clk_enable(&priv->clk);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
 static int dwc3_meson_g12a_probe(struct udevice *dev)
 {
struct dwc3_meson_g12a *priv = dev_get_plat(dev);
+   struct dwc3_meson_g12a_drvdata *data =
+   (struct dwc3_meson_g12a_drvdata *)dev_get_driver_data(dev);
int ret, i;
 
+   priv->drvdata = data;
priv->dev = dev;
 
ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
if (ret)
return ret;
 
-   ret = dwc3_meson_g12a_clk_init(priv);
+   ret = data->clk_init(priv);
if (ret)
return ret;
 
@@ -398,7 +431,7 @@ static int dwc3_meson_g12a_probe(struct udevice *dev)
if (ret)
return ret;
 
-   for (i = 0 ; i < PHY_COUNT ; ++i) {
+   for (i = 0 ; i < data->phy_cnt; ++i) {
if (!priv->phys[i].dev)
continue;
 
@@ -407,7 +440,7 @@ static int dwc3_meson_g12a_probe(struct udevice *dev)
goto err_phy_init;
}
 
-   for (i = 0; i < PHY_COUNT; ++i) {
+   for (i = 0; i < data->phy_cnt; ++i) {
if (!priv->phys[i].dev)
continue;
 
@@ -419,7 +452,7 @@ static int dwc3_meson_g12a_probe(struct udevice *dev)
return 0;
 
 err_phy_init:
-   for (i = 0 ; i < PHY_COUNT ; ++i) {
+   for (i = 0 ; i < data->phy_cnt ; ++i) {
if (!priv->phys[i].dev)
continue;
 
@@ -432,20 +465,21 @@ err_phy_init:
 static int dwc3_meson_g12a_remove(struct udevice *dev)
 {
struct dwc3_meson_g12a *priv = dev_get_plat(dev);
+   struct dwc3_meson_g12a_drvdata *data = priv->drvdata;
int i;
 
reset_release_all(&priv->reset, 1);
 
clk_release_all(&priv->clk, 1);
 
-   for (i = 0; i < PHY_COUNT; ++i) {
+   for (i = 0; i < data->phy_cnt; ++i) {
if (!priv->phys[i].dev)
continue;
 
 generic_phy_power_off(&priv->phys[i]);
}
 
-   for (i = 0 ; i < PHY_COUNT ; ++i) {
+   for (i = 0 ; i < data->phy_cnt; ++i) {
if (!priv->phys[i].dev)
continue;
 
@@ -461,11 +495,20 @@ static const struct dwc3_meson_g12a_drvdata 
meson_g12a_drvdata = {
.clk_init = dwc3_meson_g12a_clk_init,
 };
 
+static const struct dwc

[PATCH v1] drivers: sm: fix build warning

2023-10-05 Thread Alexey Romanov
This fixes following warning during u-boot build:
WARNING: unmet direct dependencies detected for MESON_SM
  Depends on [n]: SM [=n]
  Selected by [y]:
  - MESON64_COMMON [=y] && ARM [=y] && ARCH_MESON [=y]

Fixes: 9849712e7655 ("drivers: introduce Meson Secure Monitor driver")

Signed-off-by: Alexey Romanov 
Signed-off-by: Igor Prusov 
---
 drivers/sm/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/sm/Kconfig b/drivers/sm/Kconfig
index b4cc3f768e..f0987275d2 100644
--- a/drivers/sm/Kconfig
+++ b/drivers/sm/Kconfig
@@ -3,7 +3,7 @@ config SM
 
 config MESON_SM
bool "Amlogic Secure Monitor driver"
-   depends on SM
+   select SM
default n
help
  Say y here to enable the Amlogic secure monitor driver.
-- 
2.25.1



[PATCH v3 0/8] Support USB for Meson A1

2023-10-05 Thread Alexey Romanov
Hello!

This patchset adds USB stack support for Amlogic A1 SoC's
series. Made reset / phy / dwc3 drivers more flexible and
added support for A1 board.

V2:

- Made power domain for PHY optional.
- Add missing CLKID_USB_PHY gate.
- Drop patch with USB stack initialization in board-a1.c.
Instead of, enable CONFIG_DM_USB_GADGET for AD401 board.
- Support A1 in g12a_child_pre_probe/post_remove functions
in dwc3 driver.

V3:

- Rebased over latests Amlogic U-Boot branch.

Alexey Romanov (7):
  dt-bindings: reset: add Meson A1 reset bindings
  reset: add support for Amlogic A1 family
  phy: get rid of raw hex values
  phy: move clk enable/disable in init/exit
  phy: support Amlogic A1 family
  dwc3: add support for Amlogic A1 family
  ad401: enable USB stack

Igor Prusov (1):
  a1: clk: Add missing USB_PHY_IN and USB_PHY gates

 configs/ad401_defconfig   |   3 +
 drivers/clk/meson/a1.c|   6 +
 drivers/phy/Kconfig   |   2 +-
 drivers/phy/meson-g12a-usb2.c | 235 --
 drivers/reset/reset-meson.c   |  42 +++-
 drivers/usb/dwc3/dwc3-meson-g12a.c|  79 +-
 .../reset/amlogic,meson-a1-reset.h|  76 ++
 7 files changed, 409 insertions(+), 34 deletions(-)
 create mode 100644 include/dt-bindings/reset/amlogic,meson-a1-reset.h

-- 
2.25.1



[PATCH v3 1/8] dt-bindings: reset: add Meson A1 reset bindings

2023-10-05 Thread Alexey Romanov
Get this from Linux 6.6-rc3.

Signed-off-by: Alexey Romanov 
Reviewed-by: Neil Armstrong 
---
 .../reset/amlogic,meson-a1-reset.h| 76 +++
 1 file changed, 76 insertions(+)
 create mode 100644 include/dt-bindings/reset/amlogic,meson-a1-reset.h

diff --git a/include/dt-bindings/reset/amlogic,meson-a1-reset.h 
b/include/dt-bindings/reset/amlogic,meson-a1-reset.h
new file mode 100644
index 00..2c749c655e
--- /dev/null
+++ b/include/dt-bindings/reset/amlogic,meson-a1-reset.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ * Author: Xingyu Chen 
+ *
+ * Copyright (c) 2023, SberDevices, Inc.
+ * Author: Alexey Romanov 
+ */
+
+#ifndef _DT_BINDINGS_AMLOGIC_MESON_A1_RESET_H
+#define _DT_BINDINGS_AMLOGIC_MESON_A1_RESET_H
+
+/* RESET0  */
+/* 0   */
+#define RESET_AM2AXI_VAD   1
+/* 2-3 */
+#define RESET_PSRAM4
+#define RESET_PAD_CTRL 5
+/* 6   */
+#define RESET_TEMP_SENSOR  7
+#define RESET_AM2AXI_DEV   8
+/* 9   */
+#define RESET_SPICC_A  10
+#define RESET_MSR_CLK  11
+#define RESET_AUDIO12
+#define RESET_ANALOG_CTRL  13
+#define RESET_SAR_ADC  14
+#define RESET_AUDIO_VAD15
+#define RESET_CEC  16
+#define RESET_PWM_EF   17
+#define RESET_PWM_CD   18
+#define RESET_PWM_AB   19
+/* 20  */
+#define RESET_IR_CTRL  21
+#define RESET_I2C_S_A  22
+/* 23  */
+#define RESET_I2C_M_D  24
+#define RESET_I2C_M_C  25
+#define RESET_I2C_M_B  26
+#define RESET_I2C_M_A  27
+#define RESET_I2C_PROD_AHB 28
+#define RESET_I2C_PROD 29
+/* 30-31   */
+
+/* RESET1  */
+#define RESET_ACODEC   32
+#define RESET_DMA  33
+#define RESET_SD_EMMC_A34
+/* 35  */
+#define RESET_USBCTRL  36
+/* 37  */
+#define RESET_USBPHY   38
+/* 39-41   */
+#define RESET_RSA  42
+#define RESET_DMC  43
+/* 44  */
+#define RESET_IRQ_CTRL 45
+/* 46  */
+#define RESET_NIC_VAD  47
+#define RESET_NIC_AXI  48
+#define RESET_RAMA 49
+#define RESET_RAMB 50
+/* 51-52   */
+#define RESET_ROM  53
+#define RESET_SPIFC54
+#define RESET_GIC  55
+#define RESET_UART_C   56
+#define RESET_UART_B   57
+#define RESET_UART_A   58
+#define RESET_OSC_RING 59
+/* 60-63   */
+
+/* RESET2  */
+/* 64-95   */
+
+#endif
-- 
2.25.1



[PATCH v3 2/8] reset: add support for Amlogic A1 family

2023-10-05 Thread Alexey Romanov
This patch adds reset support for the Amlogic A1 family.
We add the structure meson_reset_drvdata, which in the future
will allow this driver to be used for other families by declaring
only the correct parameters reg_count and level_offset.

Signed-off-by: Alexey Romanov 
Reviewed-by: Neil Armstrong 
---
 drivers/reset/reset-meson.c | 42 +++--
 1 file changed, 36 insertions(+), 6 deletions(-)

diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c
index 64bc696f13..9d0c8b354f 100644
--- a/drivers/reset/reset-meson.c
+++ b/drivers/reset/reset-meson.c
@@ -13,18 +13,26 @@
 #include 
 #include 
 #include 
+#include 
 
-#define REG_COUNT  8
 #define BITS_PER_REG   32
-#define LEVEL_OFFSET   0x7c
+
+struct meson_reset_drvdata {
+   unsigned int reg_count;
+   unsigned int level_offset;
+};
 
 struct meson_reset_priv {
struct regmap *regmap;
+   struct meson_reset_drvdata *drvdata;
 };
 
 static int meson_reset_request(struct reset_ctl *reset_ctl)
 {
-   if (reset_ctl->id > (REG_COUNT * BITS_PER_REG))
+   struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+   struct meson_reset_drvdata *data = priv->drvdata;
+
+   if (reset_ctl->id > (data->reg_count * BITS_PER_REG))
return -EINVAL;
 
return 0;
@@ -33,9 +41,10 @@ static int meson_reset_request(struct reset_ctl *reset_ctl)
 static int meson_reset_level(struct reset_ctl *reset_ctl, bool assert)
 {
struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+   struct meson_reset_drvdata *data = priv->drvdata;
uint bank = reset_ctl->id / BITS_PER_REG;
uint offset = reset_ctl->id % BITS_PER_REG;
-   uint reg_offset = LEVEL_OFFSET + (bank << 2);
+   uint reg_offset = data->level_offset + (bank << 2);
uint val;
 
regmap_read(priv->regmap, reg_offset, &val);
@@ -64,15 +73,36 @@ struct reset_ops meson_reset_ops = {
.rst_deassert = meson_reset_deassert,
 };
 
+static const struct meson_reset_drvdata meson_gxbb_data = {
+   .reg_count = 8,
+   .level_offset = 0x7c,
+};
+
+static const struct meson_reset_drvdata meson_a1_data = {
+   .reg_count = 3,
+   .level_offset = 0x40,
+};
+
 static const struct udevice_id meson_reset_ids[] = {
-   { .compatible = "amlogic,meson-gxbb-reset" },
-   { .compatible = "amlogic,meson-axg-reset" },
+   {
+   .compatible = "amlogic,meson-gxbb-reset",
+   .data = (ulong)&meson_gxbb_data,
+   },
+   {
+   .compatible = "amlogic,meson-axg-reset",
+   .data = (ulong)&meson_gxbb_data,
+   },
+   {
+   .compatible = "amlogic,meson-a1-reset",
+   .data = (ulong)&meson_a1_data,
+   },
{ }
 };
 
 static int meson_reset_probe(struct udevice *dev)
 {
struct meson_reset_priv *priv = dev_get_priv(dev);
+   priv->drvdata = (struct meson_reset_drvdata *)dev_get_driver_data(dev);
 
return regmap_init_mem(dev_ofnode(dev), &priv->regmap);
 }
-- 
2.25.1



[PATCH v3 4/8] phy: move clk enable/disable in init/exit

2023-10-05 Thread Alexey Romanov
It is better to place clk_enable() in phy_meson_g12a_usb2_init()
and clk_disable() in phy_meson_g12a_usb2_exit().

For more detailed information, please see comments in the review of
a similar driver in the Linux Kernel:

https://lore.kernel.org/all/CAFBinCCEhobbyKHuKDWzTYCQWgNT1-e8=7hmhq1mvt6cueo...@mail.gmail.com/

Signed-off-by: Alexey Romanov 
Reviewed-by: Neil Armstrong 
---
 drivers/phy/meson-g12a-usb2.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/phy/meson-g12a-usb2.c b/drivers/phy/meson-g12a-usb2.c
index a803b6796c..2ea0498f86 100644
--- a/drivers/phy/meson-g12a-usb2.c
+++ b/drivers/phy/meson-g12a-usb2.c
@@ -161,6 +161,14 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
int ret;
 
+#if CONFIG_IS_ENABLED(CLK)
+   ret = clk_enable(&priv->clk);
+   if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
+   pr_err("failed to enable PHY clock\n");
+   return ret;
+   }
+#endif
+
ret = reset_assert(&priv->reset);
udelay(1);
ret |= reset_deassert(&priv->reset);
@@ -253,6 +261,10 @@ static int phy_meson_g12a_usb2_exit(struct phy *phy)
struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
int ret;
 
+#if CONFIG_IS_ENABLED(CLK)
+   clk_disable(&priv->clk);
+#endif
+
ret = reset_assert(&priv->reset);
if (ret)
return ret;
@@ -290,13 +302,6 @@ int meson_g12a_usb2_phy_probe(struct udevice *dev)
ret = clk_get_by_index(dev, 0, &priv->clk);
if (ret < 0)
return ret;
-
-   ret = clk_enable(&priv->clk);
-   if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
-   pr_err("failed to enable PHY clock\n");
-   clk_free(&priv->clk);
-   return ret;
-   }
 #endif
 
return 0;
-- 
2.25.1



[PATCH v3 3/8] phy: get rid of raw hex values

2023-10-05 Thread Alexey Romanov
It is better to use defines instead of write raw
hex values in regmap.

Signed-off-by: Alexey Romanov 
Reviewed-by: Neil Armstrong 
---
 drivers/phy/meson-g12a-usb2.c | 161 --
 1 file changed, 153 insertions(+), 8 deletions(-)

diff --git a/drivers/phy/meson-g12a-usb2.c b/drivers/phy/meson-g12a-usb2.c
index 8b24322515..a803b6796c 100644
--- a/drivers/phy/meson-g12a-usb2.c
+++ b/drivers/phy/meson-g12a-usb2.c
@@ -24,12 +24,28 @@
 
 #include 
 #include 
+#include 
 
 #define PHY_CTRL_R00x0
 #define PHY_CTRL_R10x4
 #define PHY_CTRL_R20x8
+
 #define PHY_CTRL_R30xc
+   #define PHY_CTRL_R3_SQUELCH_REF GENMASK(1, 0)
+   #define PHY_CTRL_R3_HSDIC_REF   GENMASK(3, 2)
+   #define PHY_CTRL_R3_DISC_THRESH GENMASK(7, 4)
+
 #define PHY_CTRL_R40x10
+   #define PHY_CTRL_R4_CALIB_CODE_7_0  GENMASK(7, 0)
+   #define PHY_CTRL_R4_CALIB_CODE_15_8 GENMASK(15, 8)
+   #define PHY_CTRL_R4_CALIB_CODE_23_16GENMASK(23, 16)
+   #define PHY_CTRL_R4_I_C2L_CAL_ENBIT(24)
+   #define PHY_CTRL_R4_I_C2L_CAL_RESET_N   BIT(25)
+   #define PHY_CTRL_R4_I_C2L_CAL_DONE  BIT(26)
+   #define PHY_CTRL_R4_TEST_BYPASS_MODE_EN BIT(27)
+   #define PHY_CTRL_R4_I_C2L_BIAS_TRIM_1_0 GENMASK(29, 28)
+   #define PHY_CTRL_R4_I_C2L_BIAS_TRIM_3_2 GENMASK(31, 30)
+
 #define PHY_CTRL_R50x14
 #define PHY_CTRL_R60x18
 #define PHY_CTRL_R70x1c
@@ -38,15 +54,93 @@
 #define PHY_CTRL_R10   0x28
 #define PHY_CTRL_R11   0x2c
 #define PHY_CTRL_R12   0x30
+
 #define PHY_CTRL_R13   0x34
+   #define PHY_CTRL_R13_CUSTOM_PATTERN_19  GENMASK(7, 0)
+   #define PHY_CTRL_R13_LOAD_STAT  BIT(14)
+   #define PHY_CTRL_R13_UPDATE_PMA_SIGNALS BIT(15)
+   #define PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET GENMASK(20, 16)
+   #define PHY_CTRL_R13_CLEAR_HOLD_HS_DISCONNECT   BIT(21)
+   #define PHY_CTRL_R13_BYPASS_HOST_DISCONNECT_VAL BIT(22)
+   #define PHY_CTRL_R13_BYPASS_HOST_DISCONNECT_EN  BIT(23)
+   #define PHY_CTRL_R13_I_C2L_HS_ENBIT(24)
+   #define PHY_CTRL_R13_I_C2L_FS_ENBIT(25)
+   #define PHY_CTRL_R13_I_C2L_LS_ENBIT(26)
+   #define PHY_CTRL_R13_I_C2L_HS_OEBIT(27)
+   #define PHY_CTRL_R13_I_C2L_FS_OEBIT(28)
+   #define PHY_CTRL_R13_I_C2L_HS_RX_EN BIT(29)
+   #define PHY_CTRL_R13_I_C2L_FSLS_RX_EN   BIT(30)
+
 #define PHY_CTRL_R14   0x38
 #define PHY_CTRL_R15   0x3c
+
 #define PHY_CTRL_R16   0x40
+   #define PHY_CTRL_R16_MPLL_M GENMASK(8, 0)
+   #define PHY_CTRL_R16_MPLL_N GENMASK(14, 10)
+   #define PHY_CTRL_R16_MPLL_TDC_MODE  BIT(20)
+   #define PHY_CTRL_R16_MPLL_SDM_ENBIT(21)
+   #define PHY_CTRL_R16_MPLL_LOAD  BIT(22)
+   #define PHY_CTRL_R16_MPLL_DCO_SDM_ENBIT(23)
+   #define PHY_CTRL_R16_MPLL_LOCK_LONG GENMASK(25, 24)
+   #define PHY_CTRL_R16_MPLL_LOCK_FBIT(26)
+   #define PHY_CTRL_R16_MPLL_FAST_LOCK BIT(27)
+   #define PHY_CTRL_R16_MPLL_ENBIT(28)
+   #define PHY_CTRL_R16_MPLL_RESET BIT(29)
+   #define PHY_CTRL_R16_MPLL_LOCK  BIT(30)
+   #define PHY_CTRL_R16_MPLL_LOCK_DIG  BIT(31)
+
 #define PHY_CTRL_R17   0x44
+   #define PHY_CTRL_R17_MPLL_FRAC_IN   GENMASK(13, 0)
+   #define PHY_CTRL_R17_MPLL_FIX_ENBIT(16)
+   #define PHY_CTRL_R17_MPLL_LAMBDA1   GENMASK(19, 17)
+   #define PHY_CTRL_R17_MPLL_LAMBDA0   GENMASK(22, 20)
+   #define PHY_CTRL_R17_MPLL_FILTER_MODE   BIT(23)
+   #define PHY_CTRL_R17_MPLL_FILTER_PVT2   GENMASK(27, 24

[PATCH v3 6/8] a1: clk: Add missing USB_PHY_IN and USB_PHY gates

2023-10-05 Thread Alexey Romanov
From: Igor Prusov 

We use this clocks in dwc3 driver.

Signed-off-by: Igor Prusov 
Signed-off-by: Alexey Romanov 
Reviewed-by: Neil Armstrong 
---
 drivers/clk/meson/a1.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/clk/meson/a1.c b/drivers/clk/meson/a1.c
index 3aec42f33b..1075ba7333 100644
--- a/drivers/clk/meson/a1.c
+++ b/drivers/clk/meson/a1.c
@@ -238,6 +238,12 @@ static const struct meson_clk_info *meson_clocks[] = {
[CLKID_FIXPLL_IN] = CLK_GATE("fixpll_in", A1_SYS_OSCIN_CTRL, 1,
EXTERNAL_XTAL
),
+   [CLKID_USB_PHY_IN] = CLK_GATE("usb_phy_in", A1_SYS_OSCIN_CTRL, 2,
+   EXTERNAL_XTAL
+   ),
+   [CLKID_USB_PHY] = CLK_GATE("usb_phy", A1_SYS_CLK_EN0, 27,
+   CLKID_SYS
+   ),
[CLKID_SARADC] = CLK_GATE("saradc", A1_SAR_ADC_CLK_CTR, 8,
-ENOENT
),
-- 
2.25.1



[PATCH v3 5/8] phy: support Amlogic A1 family

2023-10-05 Thread Alexey Romanov
Setting G12A and A1 is similar, so we can use G12A phy
driver with little changes.

Signed-off-by: Alexey Romanov 
Reviewed-by: Neil Armstrong 
---
 drivers/phy/Kconfig   |  2 +-
 drivers/phy/meson-g12a-usb2.c | 79 ---
 2 files changed, 66 insertions(+), 15 deletions(-)

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 8ac5769ed9..60138beca4 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -200,7 +200,7 @@ config MESON_GXL_USB_PHY
 
 config MESON_G12A_USB_PHY
bool "Amlogic Meson G12A USB PHYs"
-   depends on PHY && ARCH_MESON && MESON_G12A
+   depends on PHY && ARCH_MESON && (MESON_G12A || MESON_A1)
imply REGMAP
help
  This is the generic phy driver for the Amlogic Meson G12A
diff --git a/drivers/phy/meson-g12a-usb2.c b/drivers/phy/meson-g12a-usb2.c
index 2ea0498f86..4ba3992bda 100644
--- a/drivers/phy/meson-g12a-usb2.c
+++ b/drivers/phy/meson-g12a-usb2.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -147,18 +148,28 @@
 #define RESET_COMPLETE_TIME1000
 #define PLL_RESET_COMPLETE_TIME100
 
+enum meson_soc_id {
+   MESON_SOC_A1,
+   MESON_SOC_G12A,
+};
+
 struct phy_meson_g12a_usb2_priv {
struct regmap   *regmap;
 #if CONFIG_IS_ENABLED(CLK)
struct clk  clk;
 #endif
struct reset_ctlreset;
+#if CONFIG_IS_ENABLED(POWER_DOMAIN)
+   struct power_domain pwrdm;
+#endif
+   int soc_id;
 };
 
 static int phy_meson_g12a_usb2_init(struct phy *phy)
 {
struct udevice *dev = phy->dev;
struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
+   u32 value;
int ret;
 
 #if CONFIG_IS_ENABLED(CLK)
@@ -197,8 +208,7 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
FIELD_PREP(PHY_CTRL_R17_MPLL_FILTER_PVT2, 2) |
FIELD_PREP(PHY_CTRL_R17_MPLL_FILTER_PVT1, 9));
 
-   regmap_write(priv->regmap, PHY_CTRL_R18,
-   FIELD_PREP(PHY_CTRL_R18_MPLL_LKW_SEL, 1) |
+   value = FIELD_PREP(PHY_CTRL_R18_MPLL_LKW_SEL, 1) |
FIELD_PREP(PHY_CTRL_R18_MPLL_LK_W, 9) |
FIELD_PREP(PHY_CTRL_R18_MPLL_LK_S, 0x27) |
FIELD_PREP(PHY_CTRL_R18_MPLL_PFD_GAIN, 1) |
@@ -210,6 +220,11 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
FIELD_PREP(PHY_CTRL_R18_MPLL_ADJ_LDO, 1) |
PHY_CTRL_R18_MPLL_ACG_RANGE;
 
+   if (priv->soc_id == MESON_SOC_A1)
+   value |= PHY_CTRL_R18_MPLL_DCO_CLK_SEL;
+
+   regmap_write(priv->regmap, PHY_CTRL_R18, value);
+
udelay(PLL_RESET_COMPLETE_TIME);
 
/* UnReset PLL */
@@ -232,13 +247,19 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
FIELD_PREP(PHY_CTRL_R20_USB2_BGR_VREF_4_0, 0) |
FIELD_PREP(PHY_CTRL_R20_USB2_BGR_DBG_1_0, 0));
 
-   regmap_write(priv->regmap, PHY_CTRL_R4,
-   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_7_0, 0xf) |
-   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_15_8, 0xf) |
-   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_23_16, 0xf) |
-   PHY_CTRL_R4_TEST_BYPASS_MODE_EN |
-   FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_1_0, 0) |
-   FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_3_2, 0));
+   if (priv->soc_id == MESON_SOC_G12A)
+   regmap_write(priv->regmap, PHY_CTRL_R4,
+   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_7_0, 0xf) |
+   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_15_8, 0xf) |
+   FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_23_16, 0xf) |
+   PHY_CTRL_R4_TEST_BYPASS_MODE_EN |
+   FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_1_0, 0) |
+   FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_3_2, 0));
+   else if (priv->soc_id == MESON_SOC_A1)
+   regmap_write(priv->regmap, PHY_CTRL_R21,
+   PHY_CTRL_R21_USB2_CAL_ACK_EN |
+   PHY_CTRL_R21_USB2_TX_STRG_PD |
+   FIELD_PREP(PHY_CTRL_R21_USB2_OTG_ACA_TRIM_1_0, 2));
 
/* Tuning Disconnect Threshold */
regmap_write(priv->regmap, PHY_CTRL_R3,
@@ -247,10 +268,15 @@ static int phy_meson_g12a_usb2_init(struct phy *phy)
FIELD_PREP(PHY_CTRL_R3_DISC_THRESH, 3));
 
/* Analog Settings */
-   regmap_write(priv->regmap, PHY_CTRL_R14, 0);
-   regmap_write(priv->regmap, PHY_CTRL_R13,
-   PHY_CTRL_R13_UPDATE_PMA_SIGNALS |
-   FIELD_PREP(PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET, 7));
+   if (priv->soc_id == MESON_SOC_G12A) {
+   regmap_write(priv->regmap, PHY_CTRL_R14, 0);
+   regmap_write(priv->regmap, PHY_CTRL_R13,
+   PHY_CTRL_R13_UPDATE_PMA_SIGNALS |
+  

[PATCH v3 8/8] ad401: enable USB stack

2023-10-05 Thread Alexey Romanov
Currently we have all drivers for use USB stack on A1-series
SoC's. Let's enable USB options for the Amlogic AD401 reference A1
SoC board.

Signed-off-by: Alexey Romanov 
Reviewed-by: Neil Armstrong 
---
 configs/ad401_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/configs/ad401_defconfig b/configs/ad401_defconfig
index 31752cc7f5..b9aca3ab0d 100644
--- a/configs/ad401_defconfig
+++ b/configs/ad401_defconfig
@@ -51,4 +51,7 @@ CONFIG_DEBUG_UART_SKIP_INIT=y
 CONFIG_MESON_SERIAL=y
 CONFIG_SPI=y
 CONFIG_DM_SPI=y
+CONFIG_USB=y
+CONFIG_DM_USB_GADGET=y
+CONFIG_USB_GADGET=y
 CONFIG_WDT=y
-- 
2.25.1



[PATCH v3 7/8] dwc3: add support for Amlogic A1 family

2023-10-05 Thread Alexey Romanov
Now the driver supports also A1 phy layer.

Signed-off-by: Alexey Romanov 
Reviewed-by: Neil Armstrong 
---
 drivers/usb/dwc3/dwc3-meson-g12a.c | 79 ++
 1 file changed, 69 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c 
b/drivers/usb/dwc3/dwc3-meson-g12a.c
index dc5a976f71..e0356e653f 100644
--- a/drivers/usb/dwc3/dwc3-meson-g12a.c
+++ b/drivers/usb/dwc3/dwc3-meson-g12a.c
@@ -29,6 +29,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* USB2 Ports Control Registers */
 
@@ -103,10 +104,22 @@ enum {
PHY_COUNT,
 };
 
-static const char *phy_names[PHY_COUNT] = {
+static const char *const dwc3_meson_g12a_phy_names[] = {
"usb2-phy0", "usb2-phy1", "usb3-phy0",
 };
 
+static const char *const dwc3_meson_a1_phy_names[] = {
+   "usb2-phy0", "usb2-phy1"
+};
+
+struct dwc3_meson_g12a;
+
+struct dwc3_meson_g12a_drvdata {
+   const char *const *phy_names;
+   unsigned int phy_cnt;
+   int (*clk_init)(struct dwc3_meson_g12a *priv);
+};
+
 struct dwc3_meson_g12a {
struct udevice  *dev;
struct regmap   *regmap;
@@ -120,6 +133,7 @@ struct dwc3_meson_g12a {
 #if CONFIG_IS_ENABLED(DM_REGULATOR)
struct udevice  *vbus_supply;
 #endif
+   struct dwc3_meson_g12a_drvdata *drvdata;
 };
 
 #define U2P_REG_SIZE   0x20
@@ -294,10 +308,11 @@ int dwc3_meson_g12a_force_mode(struct udevice *dev, enum 
usb_dr_mode mode)
 
 static int dwc3_meson_g12a_get_phys(struct dwc3_meson_g12a *priv)
 {
+   struct dwc3_meson_g12a_drvdata *data = priv->drvdata;
int i, ret;
 
-   for (i = 0 ; i < PHY_COUNT ; ++i) {
-   ret = generic_phy_get_by_name(priv->dev, phy_names[i],
+   for (i = 0 ; i < data->phy_cnt; ++i) {
+   ret = generic_phy_get_by_name(priv->dev, data->phy_names[i],
  &priv->phys[i]);
if (ret == -ENOENT || ret == -ENODATA)
continue;
@@ -355,18 +370,36 @@ static int dwc3_meson_g12a_clk_init(struct 
dwc3_meson_g12a *priv)
return 0;
 }
 
+static int dwc3_meson_a1_clk_init(struct dwc3_meson_g12a *priv)
+{
+   int ret;
+
+   ret = clk_get_by_name(priv->dev, "usb_bus", &priv->clk);
+   if (ret)
+   return ret;
+
+   ret = clk_enable(&priv->clk);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
 static int dwc3_meson_g12a_probe(struct udevice *dev)
 {
struct dwc3_meson_g12a *priv = dev_get_plat(dev);
+   struct dwc3_meson_g12a_drvdata *data =
+   (struct dwc3_meson_g12a_drvdata *)dev_get_driver_data(dev);
int ret, i;
 
+   priv->drvdata = data;
priv->dev = dev;
 
ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
if (ret)
return ret;
 
-   ret = dwc3_meson_g12a_clk_init(priv);
+   ret = data->clk_init(priv);
if (ret)
return ret;
 
@@ -399,7 +432,7 @@ static int dwc3_meson_g12a_probe(struct udevice *dev)
if (ret)
return ret;
 
-   for (i = 0 ; i < PHY_COUNT ; ++i) {
+   for (i = 0 ; i < data->phy_cnt; ++i) {
if (!priv->phys[i].dev)
continue;
 
@@ -408,7 +441,7 @@ static int dwc3_meson_g12a_probe(struct udevice *dev)
goto err_phy_init;
}
 
-   for (i = 0; i < PHY_COUNT; ++i) {
+   for (i = 0; i < data->phy_cnt; ++i) {
if (!priv->phys[i].dev)
continue;
 
@@ -420,7 +453,7 @@ static int dwc3_meson_g12a_probe(struct udevice *dev)
return 0;
 
 err_phy_init:
-   for (i = 0 ; i < PHY_COUNT ; ++i) {
+   for (i = 0 ; i < data->phy_cnt ; ++i) {
if (!priv->phys[i].dev)
continue;
 
@@ -433,20 +466,21 @@ err_phy_init:
 static int dwc3_meson_g12a_remove(struct udevice *dev)
 {
struct dwc3_meson_g12a *priv = dev_get_plat(dev);
+   struct dwc3_meson_g12a_drvdata *data = priv->drvdata;
int i;
 
reset_release_all(&priv->reset, 1);
 
clk_release_all(&priv->clk, 1);
 
-   for (i = 0; i < PHY_COUNT; ++i) {
+   for (i = 0; i < data->phy_cnt; ++i) {
if (!priv->phys[i].dev)
continue;
 
 generic_phy_power_off(&priv->phys[i]);
}
 
-   for (i = 0 ; i < PHY_COUNT ; ++i) {
+   for (i = 0 ; i < data->phy_cnt; ++i) {
if (!priv->phys[i].dev)
continue;
 
@@ -456,11 +490,26 @@ static int dwc3_meson_g12a_remove(struct udevice *dev)
return dm_scan_fdt_dev(dev);
 }
 
+static const struct dwc3_meson_g12a_drvdata meson_g12a_drvdata =

[PATCH v2 1/2] meson-a1: dts: add hw rng node

2023-10-10 Thread Alexey Romanov
Add support for hardware random number generator
of Amlogic Meson SoCs.

Signed-off-by: Alexey Romanov 
---
 arch/arm/dts/meson-a1.dtsi | 5 +
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/dts/meson-a1.dtsi b/arch/arm/dts/meson-a1.dtsi
index 6509329b85..e6e72d4004 100644
--- a/arch/arm/dts/meson-a1.dtsi
+++ b/arch/arm/dts/meson-a1.dtsi
@@ -124,6 +124,11 @@
clock-names = "xtal", "pclk", "baud";
status = "disabled";
};
+
+   hwrng: rng@5118 {
+   compatible = "amlogic,meson-rng";
+   reg = <0x0 0x5118 0x0 0x4>;
+   };
};
 
gic: interrupt-controller@ff901000 {
-- 
2.25.1



[PATCH v2 2/2] meson-a1: dts: add ao secure node

2023-10-10 Thread Alexey Romanov
ao-secure node can be used to get information about the board,
so, for example, using show_board_info() we can get following
information for board with Meson A1 SoC:

SoC: Amlogic Meson A1 (A113L) Revision 2c:a (1:a)

Signed-off-by: Alexey Romanov 
---
 arch/arm/dts/meson-a1.dtsi | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/dts/meson-a1.dtsi b/arch/arm/dts/meson-a1.dtsi
index e6e72d4004..e3a42c5b24 100644
--- a/arch/arm/dts/meson-a1.dtsi
+++ b/arch/arm/dts/meson-a1.dtsi
@@ -129,6 +129,12 @@
compatible = "amlogic,meson-rng";
reg = <0x0 0x5118 0x0 0x4>;
};
+
+   sec_AO: ao-secure@5a20 {
+   compatible = "amlogic,meson-gx-ao-secure", 
"syscon";
+   reg = <0x0 0x5a20 0x0 0x140>;
+   amlogic,has-chip-id;
+   };
};
 
gic: interrupt-controller@ff901000 {
-- 
2.25.1



[PATCH v2 0/2] Meson A1: add HW RNG and AO Secure nodes

2023-10-10 Thread Alexey Romanov
Hello!

This patchest adds HW RNG and AO Secure definition
in device tree for Amlogic A1-series.

V2:

- Rebased over latest amlogic U-Boot branch.

Alexey Romanov (2):
  meson-a1: dts: add hw rng node
  meson-a1: dts: add ao secure node

 arch/arm/dts/meson-a1.dtsi | 11 +++
 1 file changed, 11 insertions(+)

-- 
2.25.1



[PATCH v2 0/1] hwrng: meson - add support for S4

2023-10-10 Thread Alexey Romanov
Hello! 

This patch adds support for Meson S4 series 
hardware number generator using new algo.

V2:

- Sync with Linux version.

Alexey Romanov (1):
  drivers: rng: add support for Meson S4

 drivers/rng/meson-rng.c | 72 -
 1 file changed, 71 insertions(+), 1 deletion(-)

-- 
2.25.1



[PATCH v2 1/1] drivers: rng: add support for Meson S4

2023-10-10 Thread Alexey Romanov
For some Amlogic SOC's, mechanism to obtain random number
has been changed. For example, S4 now uses status bit waiting algo.

Signed-off-by: Alexey Romanov 
---
 drivers/rng/meson-rng.c | 72 -
 1 file changed, 71 insertions(+), 1 deletion(-)

diff --git a/drivers/rng/meson-rng.c b/drivers/rng/meson-rng.c
index e0a1e8c7e0..ba60325b94 100644
--- a/drivers/rng/meson-rng.c
+++ b/drivers/rng/meson-rng.c
@@ -10,10 +10,23 @@
 #include 
 #include 
 #include 
+#include 
+
+#define RNG_DATA   0x00
+#define RNG_S4_DATA0x08
+#define RNG_S4_CFG 0x00
+
+#define RUN_BITBIT(0)
+#define SEED_READY_STS_BIT BIT(31)
+
+struct meson_rng_priv {
+   u32 (*read)(fdt_addr_t base);
+};
 
 struct meson_rng_plat {
fdt_addr_t base;
struct clk clk;
+   struct meson_rng_priv *priv;
 };
 
 /**
@@ -27,10 +40,11 @@ struct meson_rng_plat {
 static int meson_rng_read(struct udevice *dev, void *data, size_t len)
 {
struct meson_rng_plat *pdata = dev_get_plat(dev);
+   struct meson_rng_priv *priv = pdata->priv;
char *buffer = (char *)data;
 
while (len) {
-   u32 rand = readl(pdata->base);
+   u32 rand = priv->read(pdata->base);
size_t step;
 
if (len >= 4)
@@ -44,6 +58,47 @@ static int meson_rng_read(struct udevice *dev, void *data, 
size_t len)
return 0;
 }
 
+static int meson_rng_wait_status(void __iomem *cfg_addr, int bit)
+{
+   u32 status = 0;
+   int ret;
+
+   ret = readl_relaxed_poll_timeout(cfg_addr,
+status, !(status & bit),
+1);
+   if (ret)
+   return -EBUSY;
+
+   return 0;
+}
+
+static u32 meson_common_rng_read(fdt_addr_t base)
+{
+   return readl(base);
+}
+
+static u32 meson_s4_rng_read(fdt_addr_t base)
+{
+   void __iomem *cfg_addr = (void *)base + RNG_S4_CFG;
+   int err;
+
+   writel_relaxed(readl_relaxed(cfg_addr) | SEED_READY_STS_BIT, cfg_addr);
+
+   err = meson_rng_wait_status(cfg_addr, SEED_READY_STS_BIT);
+   if (err) {
+   pr_err("Seed isn't ready, try again\n");
+   return err;
+   }
+
+   err = meson_rng_wait_status(cfg_addr, RUN_BIT);
+   if (err) {
+   pr_err("Can't get random number, try again\n");
+   return err;
+   }
+
+   return readl_relaxed(base + RNG_S4_DATA);
+}
+
 /**
  * meson_rng_probe() - probe rng device
  *
@@ -59,6 +114,8 @@ static int meson_rng_probe(struct udevice *dev)
if (err)
return err;
 
+   pdata->priv = dev_get_driver_data(dev);
+
return 0;
 }
 
@@ -102,9 +159,22 @@ static const struct dm_rng_ops meson_rng_ops = {
.read = meson_rng_read,
 };
 
+static const struct meson_rng_priv meson_rng_priv = {
+   .read = meson_common_rng_read,
+};
+
+static const struct meson_rng_priv meson_rng_priv_s4 = {
+   .read = meson_s4_rng_read,
+};
+
 static const struct udevice_id meson_rng_match[] = {
{
.compatible = "amlogic,meson-rng",
+   .data = (ulong)&meson_rng_priv,
+   },
+   {
+   .compatible = "amlogic,meson-s4-rng",
+   .data = (ulong)&meson_rng_priv_s4,
},
{},
 };
-- 
2.25.1



[PATCH v1 0/3] Meson Secure PWRC Driver

2023-05-22 Thread Alexey Romanov
Hello!

This patch set adds support (driver and sm functions) for working with
power domain controller using secure monitor for Amlogic A1-series.
Additionally, in the future, the driver can be used for other Amlgoic
SoC series, such as S4.

Alexey Romanov (3):
  arch/arm: meson: sm: introduce power domain functions
  drivers: meson: introduce secure power controller driver
  arch/arm64: meson-a1: dts: move pwrc node to bus

 arch/arm/dts/meson-a1.dtsi |  12 +-
 arch/arm/include/asm/arch-meson/sm.h   |  30 
 arch/arm/mach-meson/sm.c   |  14 ++
 drivers/power/domain/Kconfig   |   7 +
 drivers/power/domain/Makefile  |   1 +
 drivers/power/domain/meson-secure-pwrc.c   | 160 +
 include/dt-bindings/power/meson-a1-power.h |  32 +
 7 files changed, 250 insertions(+), 6 deletions(-)
 create mode 100644 drivers/power/domain/meson-secure-pwrc.c
 create mode 100644 include/dt-bindings/power/meson-a1-power.h

-- 
2.38.1



[PATCH v1 1/3] arch/arm: meson: sm: introduce power domain functions

2023-05-22 Thread Alexey Romanov
This commit adds functions to manage secure power domain for
Amlogic SoC's using smc functionality.

Signed-off-by: Alexey Romanov 
---
 arch/arm/include/asm/arch-meson/sm.h | 30 
 arch/arm/mach-meson/sm.c | 14 +
 2 files changed, 44 insertions(+)

diff --git a/arch/arm/include/asm/arch-meson/sm.h 
b/arch/arm/include/asm/arch-meson/sm.h
index 53b75176493..4b1d564bc48 100644
--- a/arch/arm/include/asm/arch-meson/sm.h
+++ b/arch/arm/include/asm/arch-meson/sm.h
@@ -58,4 +58,34 @@ enum {
  */
 int meson_sm_get_reboot_reason(void);
 
+#define PWRDM_OFF 0
+#define PWRDM_ON 1
+
+/**
+ * meson_sm_pwrdm_set - do command at specified power domain.
+ *
+ * @index: power domain index.
+ * @cmd: command index.
+ * @return: zero on success or error code on failure.
+ */
+int meson_sm_pwrdm_set(size_t index, int cmd);
+
+/**
+ * meson_sm_pwrdm_off - disable specified power domain.
+ *
+ * @index: power domain index.
+ * @return: zero on success or error code on failure.
+ */
+#define meson_sm_pwrdm_off(index) \
+   meson_sm_pwrdm_set(index, PWRDM_OFF)
+
+/**
+ * meson_sm_pwrdm_on - enable specified power domain.
+ *
+ * @index: power domain index.
+ * @return: zero on success or error code on failure.
+ */
+#define meson_sm_pwrdm_on(index) \
+   meson_sm_pwrdm_set(index, PWRDM_ON)
+
 #endif /* __MESON_SM_H__ */
diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c
index f2ca7e76932..d600c64d0be 100644
--- a/arch/arm/mach-meson/sm.c
+++ b/arch/arm/mach-meson/sm.c
@@ -24,6 +24,7 @@
 #define FN_EFUSE_READ  0x8230
 #define FN_EFUSE_WRITE 0x8231
 #define FN_CHIP_ID 0x8244
+#define FN_PWRDM_SET   0x8293
 
 static void *shmem_input;
 static void *shmem_output;
@@ -137,3 +138,16 @@ int meson_sm_get_reboot_reason(void)
/* The SMC call is not used, we directly use AO_SEC_SD_CFG15 */
return FIELD_GET(REBOOT_REASON_MASK, reason);
 }
+
+int meson_sm_pwrdm_set(size_t index, int cmd)
+{
+   struct pt_regs regs;
+
+   regs.regs[0] = FN_PWRDM_SET;
+   regs.regs[1] = index;
+   regs.regs[2] = cmd;
+
+   smc_call(®s);
+
+   return regs.regs[0];
+}
-- 
2.38.1



[PATCH v1 2/3] drivers: meson: introduce secure power controller driver

2023-05-22 Thread Alexey Romanov
This patch adds Power controller driver support for Amlogic
A1 family using secure monitor calls. The power domains register
only can access in secure world.

Signed-off-by: Alexey Romanov 
---
 drivers/power/domain/Kconfig   |   7 +
 drivers/power/domain/Makefile  |   1 +
 drivers/power/domain/meson-secure-pwrc.c   | 160 +
 include/dt-bindings/power/meson-a1-power.h |  32 +
 4 files changed, 200 insertions(+)
 create mode 100644 drivers/power/domain/meson-secure-pwrc.c
 create mode 100644 include/dt-bindings/power/meson-a1-power.h

diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
index 7e1b8c072fa..411c210756a 100644
--- a/drivers/power/domain/Kconfig
+++ b/drivers/power/domain/Kconfig
@@ -68,6 +68,13 @@ config MESON_EE_POWER_DOMAIN
  Enable support for manipulating Amlogic Meson Everything-Else power
  domains.
 
+config MESON_SECURE_POWER_DOMAIN
+   bool "Enable Amlogic Secure power domain driver"
+   depends on POWER_DOMAIN && ARCH_MESON && MESON_A1
+   help
+ Enable support for manipulating Amlogic Meson Secure power domains.
+ Support for Amlogic A1 series.
+
 config SANDBOX_POWER_DOMAIN
bool "Enable the sandbox power domain test driver"
depends on POWER_DOMAIN && SANDBOX
diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
index e6244776216..aa5a4ba57cd 100644
--- a/drivers/power/domain/Makefile
+++ b/drivers/power/domain/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_IMX8MP_HSIOMIX_BLKCTRL) += imx8mp-hsiomix.o
 obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o
 obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o
 obj-$(CONFIG_MESON_EE_POWER_DOMAIN) += meson-ee-pwrc.o
+obj-$(CONFIG_MESON_SECURE_POWER_DOMAIN) += meson-secure-pwrc.o
 obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o
 obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain-test.o
 obj-$(CONFIG_TEGRA186_POWER_DOMAIN) += tegra186-power-domain.o
diff --git a/drivers/power/domain/meson-secure-pwrc.c 
b/drivers/power/domain/meson-secure-pwrc.c
new file mode 100644
index 000..f70f8e02423
--- /dev/null
+++ b/drivers/power/domain/meson-secure-pwrc.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ * Author: Alexey Romanov 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct meson_secure_pwrc_domain_desc {
+   char *name;
+   size_t index;
+};
+
+struct meson_secure_pwrc_domain_data {
+   unsigned int count;
+   struct meson_secure_pwrc_domain_desc *domains;
+};
+
+struct meson_secure_pwrc_priv {
+   const struct meson_secure_pwrc_domain_data *data;
+};
+
+static int meson_secure_pwrc_on(struct power_domain *power_domain)
+{
+   struct meson_secure_pwrc_priv *priv = dev_get_priv(power_domain->dev);
+   struct meson_secure_pwrc_domain_desc *pwrc_domain;
+   int err;
+
+   pwrc_domain = &priv->data->domains[power_domain->id];
+
+   err = meson_sm_pwrdm_on(pwrc_domain->index);
+   if (err) {
+   pr_err("meson_sm_pwrdm_on() failed (%d)\n", err);
+   return err;
+   }
+
+   pr_debug("enable %s power domain\n", pwrc_domain->name);
+
+   return 0;
+}
+
+static int meson_secure_pwrc_off(struct power_domain *power_domain)
+{
+   struct meson_secure_pwrc_priv *priv = dev_get_priv(power_domain->dev);
+   struct meson_secure_pwrc_domain_desc *pwrc_domain;
+   int err;
+
+   pwrc_domain = &priv->data->domains[power_domain->id];
+
+   err = meson_sm_pwrdm_off(pwrc_domain->index);
+   if (err) {
+   pr_err("meson_sm_pwrdm_off() failed (%d)\n", err);
+   return err;
+   }
+
+   pr_debug("disable %s power domain\n", pwrc_domain->name);
+
+   return 0;
+}
+
+static int meson_secure_pwrc_of_xlate(struct power_domain *power_domain,
+ struct ofnode_phandle_args *args)
+{
+   struct meson_secure_pwrc_priv *priv = dev_get_priv(power_domain->dev);
+   struct meson_secure_pwrc_domain_desc *pwrc_domain;
+
+   if (args->args_count < 1) {
+   pr_err("invalid args count: %d\n", args->args_count);
+   return -EINVAL;
+   }
+
+   power_domain->id = args->args[0];
+
+   if (power_domain->id >= priv->data->count) {
+   pr_err("domain with ID=%lu is invalid\n", power_domain->id);
+   return -EINVAL;
+   }
+
+   pwrc_domain = &priv->data->domains[power_domain->id];
+
+   if (!pwrc_domain->name) {
+   pr_err("domain with ID=%lu is invalid\n", power_domain->id);
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
+#define SEC_PD(__n

[PATCH v1 3/3] arch/arm64: meson-a1: dts: move pwrc node to bus

2023-05-22 Thread Alexey Romanov
This is necessary so that pwrc can be used together with
peripherals when described in a bus node. For example,
in the future, this will be USB.

Signed-off-by: Alexey Romanov 
---
 arch/arm/dts/meson-a1.dtsi | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/dts/meson-a1.dtsi b/arch/arm/dts/meson-a1.dtsi
index 9776b2d8798..f3560cbc3a4 100644
--- a/arch/arm/dts/meson-a1.dtsi
+++ b/arch/arm/dts/meson-a1.dtsi
@@ -65,12 +65,6 @@
 
sm: secure-monitor {
compatible = "amlogic,meson-gxbb-sm";
-
-   pwrc: power-controller {
-   compatible = "amlogic,meson-a1-pwrc";
-   #power-domain-cells = <1>;
-   status = "okay";
-   };
};
 
soc {
@@ -161,6 +155,12 @@
#address-cells = <0>;
};
 
+   pwrc: power-controller {
+   compatible = "amlogic,meson-a1-pwrc";
+   #power-domain-cells = <1>;
+   status = "okay";
+   };
+
usb: usb@fe004400 {
compatible = "amlogic,meson-a1-usb-ctrl";
reg = <0x0 0xfe004400 0x0 0xa0>;
-- 
2.38.1



Re: [PATCH v1 1/2] drivers: firmware: introduce Meson Secure Monitor driver

2023-08-08 Thread Alexey Romanov
Hi Neil,

I would like to know your opinion before I change the patches.

On Sat, Jul 15, 2023 at 05:40:53PM -0600, Simon Glass wrote:
> Hi,
> 
> On Thu, 13 Jul 2023 at 23:30, AKASHI Takahiro
>  wrote:
> >
> > On Tue, Jul 11, 2023 at 01:13:29PM -0600, Simon Glass wrote:
> > > +AKASHI Takahiro
> >
> > Me?
> 
> Yes, I'm asking for your help to try to clean this stuff up.
> 
> >
> > > Hi Alexey,
> > >
> > > On Tue, 11 Jul 2023 at 04:25, Alexey Romanov  
> > > wrote:
> > > >
> > > > Hi Simon,
> > > >
> > > > On Mon, Jul 10, 2023 at 01:45:53PM -0600, Simon Glass wrote:
> > > > > Hi Alexey,
> > > > >
> > > > > On Mon, 10 Jul 2023 at 02:34, Alexey Romanov 
> > > > >  wrote:
> > > > > >
> > > > > >
> > > > > > Hello!
> > > > > >
> > > > > > On Fri, Jul 07, 2023 at 11:35:47AM -0600, Simon Glass wrote:
> > > > > > > Hi Alexey,
> > > > > > >
> > > > > > > On Fri, 7 Jul 2023 at 09:43, Alexey Romanov 
> > > > > > >  wrote:
> > > > > > > >
> > > > > > > > Hello, Simon!
> > > > > > > >
> > > > > > > > On Thu, Jul 06, 2023 at 09:58:02AM -0600, Simon Glass wrote:
> > > > > > > > > Hi Alexey,
> > > > > > > > >
> > > > > > > > > On Thu, 6 Jul 2023 at 14:16, Alexey Romanov 
> > > > > > > > >  wrote:
> > > > > > > > > >
> > > > > > > > > > At the moment, only smc API is a set of functions in
> > > > > > > > > > arch/arm/mach-meson/sm.c. This approach is hard to configure
> > > > > > > > > > and also doesni't contain any generic API for calling smc.
> > > > > > > > > >
> > > > > > > > > > This patch add Meson SM driver with generic API (struct 
> > > > > > > > > > meson_sm_ops):
> > > > > > > > > >
> > > > > > > > > > - sm_call()
> > > > > > > > > > - sm_call_write()
> > > > > > > > > > - sm_call_read()
> > > > > > > > > >
> > > > > > > > > > A typical driver usage example is shown here:
> > > > > > > > > >
> > > > > > > > > > 1. uclass_get_device_by_driver(UCLASS_FIRMWARE, 
> > > > > > > > > > "secure-monitor", &dev);
> > > > > > > > > > 2. handle = meson_sm_get_handle(dev);
> > > > > > > > > > 3. handle->ops.sm_call(dev, cmd, ...);
> > > > > > > > > >
> > > > > > > > > > Signed-off-by: Alexey Romanov 
> > > > > > > > > > ---
> > > > > > > > > >  arch/arm/mach-meson/Kconfig   |   1 +
> > > > > > > > > >  drivers/firmware/Kconfig  |  10 ++
> > > > > > > > > >  drivers/firmware/Makefile |   1 +
> > > > > > > > > >  drivers/firmware/meson/Kconfig|   6 +
> > > > > > > > > >  drivers/firmware/meson/Makefile   |   3 +
> > > > > > > > > >  drivers/firmware/meson/meson_sm.c | 217 
> > > > > > > > > > ++
> > > > > > > > > >  include/meson/sm_handle.h |  38 ++
> > > > > > > > > >  7 files changed, 276 insertions(+)
> > > > > > > > > >  create mode 100644 drivers/firmware/meson/Kconfig
> > > > > > > > > >  create mode 100644 drivers/firmware/meson/Makefile
> > > > > > > > > >  create mode 100644 drivers/firmware/meson/meson_sm.c
> > > > > > > > > >  create mode 100644 include/meson/sm_handle.h
> > > > > > > > >
> > > > > > > > > Please can you use the remoteproc uclass for this and add a 
> > > > > > > > > proper driver?
> > > > > > > > >
> > > > > > > >
> > > > > > > > I don't see it architectural

Re: [PATCH v1] arch/arm: sm: introduce efusedump command

2022-12-13 Thread Alexey Romanov
Hello!

On Mon, Dec 12, 2022 at 11:08:34AM -0500, Tom Rini wrote:
> On Fri, Dec 09, 2022 at 03:52:04PM +0300, Alexey Romanov wrote:
> 
> > Using this command user can print efuse memory:
> > 
> > $ sm efusedump 0 10
> >   : ff 00 31 00 00 ff 66 00 00 00  ..1...f...
> > 
> > Signed-off-by: Alexey Romanov 
> > ---
> >  arch/arm/mach-meson/sm.c | 36 +++-
> >  1 file changed, 35 insertions(+), 1 deletion(-)
> 
> This needs to be moved done under cmd/ somewhere, perhaps cmd/meson/
> 
> -- 
> Tom


Do you mean it must be moved by a different patchset? From my point of view, 
your comment is totally right, because arch dependent commands are located at 
cmd/ARCH path. But I'm afraid my patchset is just about new helper command. 

Anyway, I can send a new different patchset with refactoring suggested by you. 
But, please, comment out some words about new efuse command if possible.

-- 
Thank you,
Alexey

[PATCH v2 0/3] arch-meson: introduce efusedump command

2022-12-13 Thread Alexey Romanov
Keeping the commands code in an arch/ is not correct. This patchset
moves the meson smc commands from arch/arm/mach-meson to cmd/meson
folder and also adds a new 'efusedump' command with which user can 
print efuse memory.

Alexey Romanov (3):
  asm/arch-meson: add missing meson_sm_write_efuse signature
  arm/mach-meson: move smc commands in cmd/meson
  cmd/arm: meson: sm: introduce efusedump command

 MAINTAINERS  |   1 +
 arch/arm/include/asm/arch-meson/sm.h |   2 +
 arch/arm/mach-meson/sm.c | 144 -
 cmd/Kconfig  |   7 +
 cmd/Makefile |   3 +
 cmd/meson/Makefile   |   5 +
 cmd/meson/sm.c   | 187 +++
 7 files changed, 205 insertions(+), 144 deletions(-)
 create mode 100644 cmd/meson/Makefile
 create mode 100644 cmd/meson/sm.c

-- 
2.25.1



[PATCH v2 1/3] asm/arch-meson: add missing meson_sm_write_efuse signature

2022-12-13 Thread Alexey Romanov
This function can be used by other modules.

Signed-off-by: Alexey Romanov 
---
 arch/arm/include/asm/arch-meson/sm.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/include/asm/arch-meson/sm.h 
b/arch/arm/include/asm/arch-meson/sm.h
index f3ae46a6d6b..b68edf842e4 100644
--- a/arch/arm/include/asm/arch-meson/sm.h
+++ b/arch/arm/include/asm/arch-meson/sm.h
@@ -8,6 +8,8 @@
 
 ssize_t meson_sm_read_efuse(uintptr_t offset, void *buffer, size_t size);
 
+ssize_t meson_sm_write_efuse(uintptr_t offset, void *buffer, size_t size);
+
 #define SM_SERIAL_SIZE 12
 
 int meson_sm_get_serial(void *buffer, size_t size);
-- 
2.25.1



[PATCH v2 3/3] cmd/arm: meson: sm: introduce efusedump command

2022-12-13 Thread Alexey Romanov
Using this command user can print efuse memory:

$ sm efusedump 0 10
  : ff 00 31 00 00 ff 66 00 00 00  ..1...f...

Signed-off-by: Alexey Romanov 
---
 cmd/meson/sm.c | 35 ++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/cmd/meson/sm.c b/cmd/meson/sm.c
index 1a3a2c7920a..9493f4fd846 100644
--- a/cmd/meson/sm.c
+++ b/cmd/meson/sm.c
@@ -117,11 +117,43 @@ static int do_efuse_write(struct cmd_tbl *cmdtp, int 
flag, int argc,
return CMD_RET_SUCCESS;
 }
 
+static int do_efuse_dump(struct cmd_tbl *cmdtp, int flag, int argc,
+   char *const argv[])
+{
+   ulong offset, size;
+   u8 *buffer;
+   int ret;
+
+   if (argc != 3)
+   return CMD_RET_USAGE;
+
+   offset = simple_strtoul(argv[1], NULL, 0);
+   size = simple_strtoul(argv[2], NULL, 0);
+   buffer = malloc(size);
+   if (!buffer) {
+   pr_err("Failed to allocate %lu bytes\n", size);
+   return CMD_RET_FAILURE;
+   }
+
+   ret = meson_sm_read_efuse(offset, (void *)buffer, size);
+   if (ret != size) {
+   ret = CMD_RET_FAILURE;
+   goto free_buffer;
+   }
+
+   print_buffer(0, buffer, 1, size, 0);
+
+free_buffer:
+   free(buffer);
+   return ret;
+}
+
 static struct cmd_tbl cmd_sm_sub[] = {
U_BOOT_CMD_MKENT(serial, 2, 1, do_sm_serial, "", ""),
U_BOOT_CMD_MKENT(reboot_reason, 1, 1, do_sm_reboot_reason, "", ""),
U_BOOT_CMD_MKENT(efuseread, 4, 1, do_efuse_read, "", ""),
U_BOOT_CMD_MKENT(efusewrite, 4, 0, do_efuse_write, "", ""),
+   U_BOOT_CMD_MKENT(efusedump, 3, 1, do_efuse_dump, "", ""),
 };
 
 static int do_sm(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -150,5 +182,6 @@ U_BOOT_CMD(
"serial  - read chip unique id to memory address\n"
"sm reboot_reason [name] - get reboot reason and store to environment\n"
"sm efuseread- read efuse to memory 
address\n"
-   "sm efusewrite- write into efuse from memory 
address"
+   "sm efusewrite- write into efuse from memory 
address\n"
+   "sm efusedump   - dump efuse data range to console"
 );
-- 
2.25.1



[PATCH v2 2/3] arm/mach-meson: move smc commands in cmd/meson

2022-12-13 Thread Alexey Romanov
It is incorrect to keep commands in the arch/ folder.

Signed-off-by: Alexey Romanov 
---
 MAINTAINERS  |   1 +
 arch/arm/mach-meson/sm.c | 144 
 cmd/Kconfig  |   7 ++
 cmd/Makefile |   3 +
 cmd/meson/Makefile   |   5 ++
 cmd/meson/sm.c   | 154 +++
 6 files changed, 170 insertions(+), 144 deletions(-)
 create mode 100644 cmd/meson/Makefile
 create mode 100644 cmd/meson/sm.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 7f27ff4c20f..7a5460d4922 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -149,6 +149,7 @@ L:  u-boot-amlo...@groups.io
 T: git https://source.denx.de/u-boot/custodians/u-boot-amlogic.git
 F: arch/arm/mach-meson/
 F: arch/arm/include/asm/arch-meson/
+F: cmd/meson/
 F: drivers/clk/meson/
 F: drivers/serial/serial_meson.c
 F: drivers/reset/reset-meson.c
diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c
index d6eb910689f..f2ca7e76932 100644
--- a/arch/arm/mach-meson/sm.c
+++ b/arch/arm/mach-meson/sm.c
@@ -6,8 +6,6 @@
  */
 
 #include 
-#include 
-#include 
 #include 
 #include 
 #include 
@@ -139,145 +137,3 @@ int meson_sm_get_reboot_reason(void)
/* The SMC call is not used, we directly use AO_SEC_SD_CFG15 */
return FIELD_GET(REBOOT_REASON_MASK, reason);
 }
-
-static int do_sm_serial(struct cmd_tbl *cmdtp, int flag, int argc,
-   char *const argv[])
-{
-   ulong address;
-   int ret;
-
-   if (argc < 2)
-   return CMD_RET_USAGE;
-
-   address = simple_strtoul(argv[1], NULL, 0);
-
-   ret = meson_sm_get_serial((void *)address, SM_CHIP_ID_SIZE);
-   if (ret)
-   return CMD_RET_FAILURE;
-
-   return CMD_RET_SUCCESS;
-}
-
-#define MAX_REBOOT_REASONS 14
-
-static const char *reboot_reasons[MAX_REBOOT_REASONS] = {
-   [REBOOT_REASON_COLD] = "cold_boot",
-   [REBOOT_REASON_NORMAL] = "normal",
-   [REBOOT_REASON_RECOVERY] = "recovery",
-   [REBOOT_REASON_UPDATE] = "update",
-   [REBOOT_REASON_FASTBOOT] = "fastboot",
-   [REBOOT_REASON_SUSPEND_OFF] = "suspend_off",
-   [REBOOT_REASON_HIBERNATE] = "hibernate",
-   [REBOOT_REASON_BOOTLOADER] = "bootloader",
-   [REBOOT_REASON_SHUTDOWN_REBOOT] = "shutdown_reboot",
-   [REBOOT_REASON_RPMBP] = "rpmbp",
-   [REBOOT_REASON_CRASH_DUMP] = "crash_dump",
-   [REBOOT_REASON_KERNEL_PANIC] = "kernel_panic",
-   [REBOOT_REASON_WATCHDOG_REBOOT] = "watchdog_reboot",
-};
-
-static int do_sm_reboot_reason(struct cmd_tbl *cmdtp, int flag, int argc,
-  char *const argv[])
-{
-   const char *reason_str;
-   char *destarg = NULL;
-   int reason;
-
-   if (argc > 1)
-   destarg = argv[1];
-
-   reason = meson_sm_get_reboot_reason();
-   if (reason < 0)
-   return CMD_RET_FAILURE;
-
-   if (reason >= MAX_REBOOT_REASONS ||
-   !reboot_reasons[reason])
-   reason_str = "unknown";
-   else
-   reason_str = reboot_reasons[reason];
-
-   if (destarg)
-   env_set(destarg, reason_str);
-   else
-   printf("reboot reason: %s (%x)\n", reason_str, reason);
-
-   return CMD_RET_SUCCESS;
-}
-
-static int do_efuse_read(struct cmd_tbl *cmdtp, int flag, int argc,
-   char *const argv[])
-{
-   ulong address, offset, size;
-   int ret;
-
-   if (argc < 4)
-   return CMD_RET_USAGE;
-
-offset = simple_strtoul(argv[1], NULL, 0);
-size = simple_strtoul(argv[2], NULL, 0);
-
-address = simple_strtoul(argv[3], NULL, 0);
-
-   ret = meson_sm_read_efuse(offset, (void *)address, size);
-   if (ret != size)
-   return CMD_RET_FAILURE;
-
-   return CMD_RET_SUCCESS;
-}
-
-static int do_efuse_write(struct cmd_tbl *cmdtp, int flag, int argc,
-   char *const argv[])
-{
-   ulong address, offset, size;
-   int ret;
-
-   if (argc < 4)
-   return CMD_RET_USAGE;
-
-offset = simple_strtoul(argv[1], NULL, 0);
-size = simple_strtoul(argv[2], NULL, 0);
-
-address = simple_strtoul(argv[3], NULL, 0);
-
-   ret = meson_sm_write_efuse(offset, (void *)address, size);
-   if (ret != size)
-   return CMD_RET_FAILURE;
-
-   return CMD_RET_SUCCESS;
-}
-
-static struct cmd_tbl cmd_sm_sub[] = {
-   U_BOOT_CMD_MKENT(serial, 2, 1, do_sm_serial, "", ""),
-   U_BOOT_CMD_MKENT(reboot_reason, 1, 1, do_sm_reboot_reason, "", ""),
-   U_BOOT_CMD_MKENT(efuseread, 4, 1, do_efuse_read, "", ""),
-   U_BOOT_CMD_MKENT(efusewrite, 4, 0, do_efuse_write, "", "

Re: [PATCH v2 2/3] arm/mach-meson: move smc commands in cmd/meson

2022-12-14 Thread Alexey Romanov
On Wed, Dec 14, 2022 at 11:33:35AM +0100, Mattijs Korpershoek wrote:
> On Tue, Dec 13, 2022 at 21:31, Alexey Romanov  
> wrote:
> 
> > It is incorrect to keep commands in the arch/ folder.
> >
> > Signed-off-by: Alexey Romanov 
> > ---
> >  MAINTAINERS  |   1 +
> >  arch/arm/mach-meson/sm.c | 144 
> >  cmd/Kconfig  |   7 ++
> >  cmd/Makefile |   3 +
> >  cmd/meson/Makefile   |   5 ++
> >  cmd/meson/sm.c   | 154 +++
> >  6 files changed, 170 insertions(+), 144 deletions(-)
> >  create mode 100644 cmd/meson/Makefile
> >  create mode 100644 cmd/meson/sm.c
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 7f27ff4c20f..7a5460d4922 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -149,6 +149,7 @@ L:  u-boot-amlo...@groups.io
> >  T: git https://source.denx.de/u-boot/custodians/u-boot-amlogic.git
> >  F: arch/arm/mach-meson/
> >  F: arch/arm/include/asm/arch-meson/
> > +F: cmd/meson/
> >  F: drivers/clk/meson/
> >  F: drivers/serial/serial_meson.c
> >  F: drivers/reset/reset-meson.c
> > diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c
> > index d6eb910689f..f2ca7e76932 100644
> > --- a/arch/arm/mach-meson/sm.c
> > +++ b/arch/arm/mach-meson/sm.c
> > @@ -6,8 +6,6 @@
> >   */
> >  
> >  #include 
> > -#include 
> > -#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -139,145 +137,3 @@ int meson_sm_get_reboot_reason(void)
> > /* The SMC call is not used, we directly use AO_SEC_SD_CFG15 */
> > return FIELD_GET(REBOOT_REASON_MASK, reason);
> >  }
> > -
> > -static int do_sm_serial(struct cmd_tbl *cmdtp, int flag, int argc,
> > -   char *const argv[])
> > -{
> > -   ulong address;
> > -   int ret;
> > -
> > -   if (argc < 2)
> > -   return CMD_RET_USAGE;
> > -
> > -   address = simple_strtoul(argv[1], NULL, 0);
> > -
> > -   ret = meson_sm_get_serial((void *)address, SM_CHIP_ID_SIZE);
> > -   if (ret)
> > -   return CMD_RET_FAILURE;
> > -
> > -   return CMD_RET_SUCCESS;
> > -}
> > -
> > -#define MAX_REBOOT_REASONS 14
> > -
> > -static const char *reboot_reasons[MAX_REBOOT_REASONS] = {
> > -   [REBOOT_REASON_COLD] = "cold_boot",
> > -   [REBOOT_REASON_NORMAL] = "normal",
> > -   [REBOOT_REASON_RECOVERY] = "recovery",
> > -   [REBOOT_REASON_UPDATE] = "update",
> > -   [REBOOT_REASON_FASTBOOT] = "fastboot",
> > -   [REBOOT_REASON_SUSPEND_OFF] = "suspend_off",
> > -   [REBOOT_REASON_HIBERNATE] = "hibernate",
> > -   [REBOOT_REASON_BOOTLOADER] = "bootloader",
> > -   [REBOOT_REASON_SHUTDOWN_REBOOT] = "shutdown_reboot",
> > -   [REBOOT_REASON_RPMBP] = "rpmbp",
> > -   [REBOOT_REASON_CRASH_DUMP] = "crash_dump",
> > -   [REBOOT_REASON_KERNEL_PANIC] = "kernel_panic",
> > -   [REBOOT_REASON_WATCHDOG_REBOOT] = "watchdog_reboot",
> > -};
> > -
> > -static int do_sm_reboot_reason(struct cmd_tbl *cmdtp, int flag, int argc,
> > -  char *const argv[])
> > -{
> > -   const char *reason_str;
> > -   char *destarg = NULL;
> > -   int reason;
> > -
> > -   if (argc > 1)
> > -   destarg = argv[1];
> > -
> > -   reason = meson_sm_get_reboot_reason();
> > -   if (reason < 0)
> > -   return CMD_RET_FAILURE;
> > -
> > -   if (reason >= MAX_REBOOT_REASONS ||
> > -   !reboot_reasons[reason])
> > -   reason_str = "unknown";
> > -   else
> > -   reason_str = reboot_reasons[reason];
> > -
> > -   if (destarg)
> > -   env_set(destarg, reason_str);
> > -   else
> > -   printf("reboot reason: %s (%x)\n", reason_str, reason);
> > -
> > -   return CMD_RET_SUCCESS;
> > -}
> > -
> > -static int do_efuse_read(struct cmd_tbl *cmdtp, int flag, int argc,
> > -   char *const argv[])
> > -{
> > -   ulong address, offset, size;
> > -   int ret;
> > -
> > -   if (argc < 4)
> > -   return CMD_RET_USAGE;
> > -
> > -offset = simple_strtoul(argv[1], NULL, 0);
> > -size = simple_strtoul(argv[2], NULL, 0);
> > -
> > -address = simple_strtoul(argv[3], NULL, 

Re: [PATCH v2 1/3] asm/arch-meson: add missing meson_sm_write_efuse signature

2022-12-14 Thread Alexey Romanov
Hello!

On Tue, Dec 13, 2022 at 08:39:46PM -0800, Simon Glass wrote:
> Hi Alexey,
> 
> On Tue, 13 Dec 2022 at 10:32, Alexey Romanov  wrote:
> >
> > This function can be used by other modules.
> >
> > Signed-off-by: Alexey Romanov 
> > ---
> >  arch/arm/include/asm/arch-meson/sm.h | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/arch/arm/include/asm/arch-meson/sm.h 
> > b/arch/arm/include/asm/arch-meson/sm.h
> > index f3ae46a6d6b..b68edf842e4 100644
> > --- a/arch/arm/include/asm/arch-meson/sm.h
> > +++ b/arch/arm/include/asm/arch-meson/sm.h
> > @@ -8,6 +8,8 @@
> >
> >  ssize_t meson_sm_read_efuse(uintptr_t offset, void *buffer, size_t size);
> >
> > +ssize_t meson_sm_write_efuse(uintptr_t offset, void *buffer, size_t size);
> > +
> >  #define SM_SERIAL_SIZE 12
> >
> >  int meson_sm_get_serial(void *buffer, size_t size);
> > --
> > 2.25.1
> >
> 
> Should add function comments.
> 
> Also, you might consider adding a uclass for this. It seems like an
> important use case that is not handled right now.
> 
> Regards,
> Simon

I'm afraid we can't generalize sm API for each arch types. It's very close to 
Secure Monitor 
vendor implementation and can provide various APIs for different purposes.

-- 
Thank you,
Alexey

Re: [PATCH v2 0/3] arch-meson: introduce efusedump command

2022-12-14 Thread Alexey Romanov
Hello!

On Tue, Dec 13, 2022 at 08:39:43PM -0800, Simon Glass wrote:
> Hi Alexey,
> 
> On Tue, 13 Dec 2022 at 10:31, Alexey Romanov  wrote:
> >
> > Keeping the commands code in an arch/ is not correct. This patchset
> > moves the meson smc commands from arch/arm/mach-meson to cmd/meson
> > folder and also adds a new 'efusedump' command with which user can
> > print efuse memory.
> >
> > Alexey Romanov (3):
> >   asm/arch-meson: add missing meson_sm_write_efuse signature
> >   arm/mach-meson: move smc commands in cmd/meson
> >   cmd/arm: meson: sm: introduce efusedump command
> >
> >  MAINTAINERS  |   1 +
> >  arch/arm/include/asm/arch-meson/sm.h |   2 +
> >  arch/arm/mach-meson/sm.c | 144 -
> >  cmd/Kconfig  |   7 +
> >  cmd/Makefile |   3 +
> >  cmd/meson/Makefile   |   5 +
> >  cmd/meson/sm.c   | 187 +++
> >  7 files changed, 205 insertions(+), 144 deletions(-)
> >  create mode 100644 cmd/meson/Makefile
> >  create mode 100644 cmd/meson/sm.c
> >
> > --
> > 2.25.1
> >
> 
> It might be a good time to add some documentation in doc/usage/cmd/meson ?
> 
> Regards,
> Simon

Yeah, I'll add docs in v3 patchest.

-- 
Thank you,
Alexey

[PATCH v3 0/5] arch-meson: introduce efusedump command

2022-12-22 Thread Alexey Romanov
Keeping the commands code in an arch/ is not correct. This patchset
moves the meson smc commands from arch/arm/mach-meson to cmd/meson
folder and also adds a new 'efusedump' command with which user can 
print efuse memory.

Alexey Romanov (5):
  asm/arch-meson: add missing meson_sm_write_efuse signature
  arm/mach-meson: move smc commands in cmd/meson
  doc/usage: cmd: documentation for meson/sm command
  cmd/arm: meson: sm: introduce efusedump command
  doc/usage: cmd: sm: documentation efusedump cmd

 MAINTAINERS  |   1 +
 arch/arm/include/asm/arch-meson/sm.h |  28 
 arch/arm/mach-meson/sm.c | 144 
 cmd/Kconfig  |   7 +
 cmd/Makefile |   3 +
 cmd/meson/Makefile   |   5 +
 cmd/meson/sm.c   | 190 +++
 doc/usage/cmd/sm.rst |  48 +++
 8 files changed, 282 insertions(+), 144 deletions(-)
 create mode 100644 cmd/meson/Makefile
 create mode 100644 cmd/meson/sm.c
 create mode 100644 doc/usage/cmd/sm.rst

-- 
2.25.1



[PATCH v3 1/5] asm/arch-meson: add missing meson_sm_write_efuse signature

2022-12-22 Thread Alexey Romanov
This function can be used by other modules. Also add comments.

Signed-off-by: Alexey Romanov 
---
 arch/arm/include/asm/arch-meson/sm.h | 28 
 1 file changed, 28 insertions(+)

diff --git a/arch/arm/include/asm/arch-meson/sm.h 
b/arch/arm/include/asm/arch-meson/sm.h
index f3ae46a6d6b..53b75176493 100644
--- a/arch/arm/include/asm/arch-meson/sm.h
+++ b/arch/arm/include/asm/arch-meson/sm.h
@@ -6,10 +6,35 @@
 #ifndef __MESON_SM_H__
 #define __MESON_SM_H__
 
+/**
+ * meson_sm_read_efuse - read efuse memory into buffer
+ *
+ * @offset: offset from the start efuse memory
+ * @buffer: pointer to buffer
+ * @size: number of bytes to read
+ * @return: number of bytes read
+ */
 ssize_t meson_sm_read_efuse(uintptr_t offset, void *buffer, size_t size);
 
+/**
+ * meson_sm_write_efuse - write into efuse memory from buffer
+ *
+ * @offset: offset from the start efuse memory
+ * @buffer: pointer to buffer
+ * @size: number of bytes to write
+ * @return: number of bytes written
+ */
+ssize_t meson_sm_write_efuse(uintptr_t offset, void *buffer, size_t size);
+
 #define SM_SERIAL_SIZE 12
 
+/**
+ * meson_sm_get_serial - read chip unique id into buffer
+ *
+ * @buffer: pointer to buffer
+ * @size: buffer size.
+ * @return: zero on success or -errno on failure
+ */
 int meson_sm_get_serial(void *buffer, size_t size);
 
 enum {
@@ -28,6 +53,9 @@ enum {
REBOOT_REASON_WATCHDOG_REBOOT = 13,
 };
 
+/**
+ * meson_sm_get_reboot_reason - get reboot reason
+ */
 int meson_sm_get_reboot_reason(void);
 
 #endif /* __MESON_SM_H__ */
-- 
2.25.1



[PATCH v3 2/5] arm/mach-meson: move smc commands in cmd/meson

2022-12-22 Thread Alexey Romanov
It is incorrect to keep commands in the arch/ folder.

Signed-off-by: Alexey Romanov 
Reviewed-by: Mattijs Korpershoek 
---
 MAINTAINERS  |   1 +
 arch/arm/mach-meson/sm.c | 144 
 cmd/Kconfig  |   7 ++
 cmd/Makefile |   3 +
 cmd/meson/Makefile   |   5 ++
 cmd/meson/sm.c   | 156 +++
 6 files changed, 172 insertions(+), 144 deletions(-)
 create mode 100644 cmd/meson/Makefile
 create mode 100644 cmd/meson/sm.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 7f27ff4c20f..7a5460d4922 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -149,6 +149,7 @@ L:  u-boot-amlo...@groups.io
 T: git https://source.denx.de/u-boot/custodians/u-boot-amlogic.git
 F: arch/arm/mach-meson/
 F: arch/arm/include/asm/arch-meson/
+F: cmd/meson/
 F: drivers/clk/meson/
 F: drivers/serial/serial_meson.c
 F: drivers/reset/reset-meson.c
diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c
index d6eb910689f..f2ca7e76932 100644
--- a/arch/arm/mach-meson/sm.c
+++ b/arch/arm/mach-meson/sm.c
@@ -6,8 +6,6 @@
  */
 
 #include 
-#include 
-#include 
 #include 
 #include 
 #include 
@@ -139,145 +137,3 @@ int meson_sm_get_reboot_reason(void)
/* The SMC call is not used, we directly use AO_SEC_SD_CFG15 */
return FIELD_GET(REBOOT_REASON_MASK, reason);
 }
-
-static int do_sm_serial(struct cmd_tbl *cmdtp, int flag, int argc,
-   char *const argv[])
-{
-   ulong address;
-   int ret;
-
-   if (argc < 2)
-   return CMD_RET_USAGE;
-
-   address = simple_strtoul(argv[1], NULL, 0);
-
-   ret = meson_sm_get_serial((void *)address, SM_CHIP_ID_SIZE);
-   if (ret)
-   return CMD_RET_FAILURE;
-
-   return CMD_RET_SUCCESS;
-}
-
-#define MAX_REBOOT_REASONS 14
-
-static const char *reboot_reasons[MAX_REBOOT_REASONS] = {
-   [REBOOT_REASON_COLD] = "cold_boot",
-   [REBOOT_REASON_NORMAL] = "normal",
-   [REBOOT_REASON_RECOVERY] = "recovery",
-   [REBOOT_REASON_UPDATE] = "update",
-   [REBOOT_REASON_FASTBOOT] = "fastboot",
-   [REBOOT_REASON_SUSPEND_OFF] = "suspend_off",
-   [REBOOT_REASON_HIBERNATE] = "hibernate",
-   [REBOOT_REASON_BOOTLOADER] = "bootloader",
-   [REBOOT_REASON_SHUTDOWN_REBOOT] = "shutdown_reboot",
-   [REBOOT_REASON_RPMBP] = "rpmbp",
-   [REBOOT_REASON_CRASH_DUMP] = "crash_dump",
-   [REBOOT_REASON_KERNEL_PANIC] = "kernel_panic",
-   [REBOOT_REASON_WATCHDOG_REBOOT] = "watchdog_reboot",
-};
-
-static int do_sm_reboot_reason(struct cmd_tbl *cmdtp, int flag, int argc,
-  char *const argv[])
-{
-   const char *reason_str;
-   char *destarg = NULL;
-   int reason;
-
-   if (argc > 1)
-   destarg = argv[1];
-
-   reason = meson_sm_get_reboot_reason();
-   if (reason < 0)
-   return CMD_RET_FAILURE;
-
-   if (reason >= MAX_REBOOT_REASONS ||
-   !reboot_reasons[reason])
-   reason_str = "unknown";
-   else
-   reason_str = reboot_reasons[reason];
-
-   if (destarg)
-   env_set(destarg, reason_str);
-   else
-   printf("reboot reason: %s (%x)\n", reason_str, reason);
-
-   return CMD_RET_SUCCESS;
-}
-
-static int do_efuse_read(struct cmd_tbl *cmdtp, int flag, int argc,
-   char *const argv[])
-{
-   ulong address, offset, size;
-   int ret;
-
-   if (argc < 4)
-   return CMD_RET_USAGE;
-
-offset = simple_strtoul(argv[1], NULL, 0);
-size = simple_strtoul(argv[2], NULL, 0);
-
-address = simple_strtoul(argv[3], NULL, 0);
-
-   ret = meson_sm_read_efuse(offset, (void *)address, size);
-   if (ret != size)
-   return CMD_RET_FAILURE;
-
-   return CMD_RET_SUCCESS;
-}
-
-static int do_efuse_write(struct cmd_tbl *cmdtp, int flag, int argc,
-   char *const argv[])
-{
-   ulong address, offset, size;
-   int ret;
-
-   if (argc < 4)
-   return CMD_RET_USAGE;
-
-offset = simple_strtoul(argv[1], NULL, 0);
-size = simple_strtoul(argv[2], NULL, 0);
-
-address = simple_strtoul(argv[3], NULL, 0);
-
-   ret = meson_sm_write_efuse(offset, (void *)address, size);
-   if (ret != size)
-   return CMD_RET_FAILURE;
-
-   return CMD_RET_SUCCESS;
-}
-
-static struct cmd_tbl cmd_sm_sub[] = {
-   U_BOOT_CMD_MKENT(serial, 2, 1, do_sm_serial, "", ""),
-   U_BOOT_CMD_MKENT(reboot_reason, 1, 1, do_sm_reboot_reason, "", ""),
-   U_BOOT_CMD_MKENT(efuseread, 4, 1, do_efuse_read, "", ""),
-   U_BOOT_CMD_MKENT(efusewrit

[PATCH v3 3/5] doc/usage: cmd: documentation for meson/sm command

2022-12-22 Thread Alexey Romanov
Signed-off-by: Alexey Romanov 
---
 doc/usage/cmd/sm.rst | 44 
 1 file changed, 44 insertions(+)
 create mode 100644 doc/usage/cmd/sm.rst

diff --git a/doc/usage/cmd/sm.rst b/doc/usage/cmd/sm.rst
new file mode 100644
index 000..3a70c137ec9
--- /dev/null
+++ b/doc/usage/cmd/sm.rst
@@ -0,0 +1,44 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+Meson Security Monitor command
+==
+
+Synopis
+---
+
+::
+
+sm serial 
+sm reboot_reason [name]
+sm efuseread   
+sm efusewrite   
+sm efusedump  
+
+Description
+---
+
+The sm command is used to request services from the secure monitor. User
+can call secure monitor to request special TEE function, for example chip
+serial number info, reboot reason, etc.
+
+sm serial
+  Retrieve chip unique serial number from sm and write it to memory on
+  appropriate address.
+
+sm reboot_reason
+  Print reboot reason to the console, if parameter [name] isn't specified.
+  If parameter specified, set reboot reason string to environment variable
+  with this name.
+
+sm efuseread
+  Read  bytes starting from  from efuse memory bank and write
+  result to the address .
+
+sm efusewrite
+  Write into efuse memory bank, starting from , the  bytes
+  of data, located at address .
+
+Configuration
+-
+
+To use the sm command you must specify CONFIG_CMD_MESON=y
-- 
2.25.1



[PATCH v3 4/5] cmd/arm: meson: sm: introduce efusedump command

2022-12-22 Thread Alexey Romanov
Using this command user can print efuse memory:

$ sm efusedump 0 10
  : ff 00 31 00 00 ff 66 00 00 00  ..1...f...

Signed-off-by: Alexey Romanov 
Reviewed-by: Mattijs Korpershoek 
---
 cmd/meson/sm.c | 36 +++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/cmd/meson/sm.c b/cmd/meson/sm.c
index c2b57707258..d5eb1d6c084 100644
--- a/cmd/meson/sm.c
+++ b/cmd/meson/sm.c
@@ -5,6 +5,7 @@
  * Author: Beniamino Galvani 
  * Author: Vyacheslav Bocharov 
  * Author: Neil Armstrong 
+ * Author: Alexey Romanov 
  */
 
 #include 
@@ -119,11 +120,43 @@ static int do_efuse_write(struct cmd_tbl *cmdtp, int 
flag, int argc,
return CMD_RET_SUCCESS;
 }
 
+static int do_efuse_dump(struct cmd_tbl *cmdtp, int flag, int argc,
+   char *const argv[])
+{
+   ulong offset, size;
+   u8 *buffer;
+   int ret;
+
+   if (argc != 3)
+   return CMD_RET_USAGE;
+
+   offset = simple_strtoul(argv[1], NULL, 0);
+   size = simple_strtoul(argv[2], NULL, 0);
+   buffer = malloc(size);
+   if (!buffer) {
+   pr_err("Failed to allocate %lu bytes\n", size);
+   return CMD_RET_FAILURE;
+   }
+
+   ret = meson_sm_read_efuse(offset, (void *)buffer, size);
+   if (ret != size) {
+   ret = CMD_RET_FAILURE;
+   goto free_buffer;
+   }
+
+   print_buffer(0, buffer, 1, size, 0);
+
+free_buffer:
+   free(buffer);
+   return ret;
+}
+
 static struct cmd_tbl cmd_sm_sub[] = {
U_BOOT_CMD_MKENT(serial, 2, 1, do_sm_serial, "", ""),
U_BOOT_CMD_MKENT(reboot_reason, 1, 1, do_sm_reboot_reason, "", ""),
U_BOOT_CMD_MKENT(efuseread, 4, 1, do_efuse_read, "", ""),
U_BOOT_CMD_MKENT(efusewrite, 4, 0, do_efuse_write, "", ""),
+   U_BOOT_CMD_MKENT(efusedump, 3, 1, do_efuse_dump, "", ""),
 };
 
 static int do_sm(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -152,5 +185,6 @@ U_BOOT_CMD(
"serial  - read chip unique id to memory address\n"
"sm reboot_reason [name] - get reboot reason and store to environment\n"
"sm efuseread- read efuse to memory 
address\n"
-   "sm efusewrite- write into efuse from memory 
address"
+   "sm efusewrite- write into efuse from memory 
address\n"
+   "sm efusedump   - dump efuse data range to console"
 );
-- 
2.25.1



[PATCH v3 5/5] doc/usage: cmd: sm: documentation efusedump cmd

2022-12-22 Thread Alexey Romanov
Signed-off-by: Alexey Romanov 
---
 doc/usage/cmd/sm.rst | 4 
 1 file changed, 4 insertions(+)

diff --git a/doc/usage/cmd/sm.rst b/doc/usage/cmd/sm.rst
index 3a70c137ec9..beb53b3f46d 100644
--- a/doc/usage/cmd/sm.rst
+++ b/doc/usage/cmd/sm.rst
@@ -38,6 +38,10 @@ sm efusewrite
   Write into efuse memory bank, starting from , the  bytes
   of data, located at address .
 
+sm efusedump
+  Read  bytes starting from  from efuse memory bank and print
+  them to the console.
+
 Configuration
 -
 
-- 
2.25.1



[PATCH v4 0/5] arch-meson: introduce efusedump command

2023-01-10 Thread Alexey Romanov
Keeping the commands code in an arch/ is not correct. This patchset
moves the meson smc commands from arch/arm/mach-meson to cmd/meson
folder and also adds a new 'efusedump' command with which user can 
print efuse memory.

Alexey Romanov (5):
  asm/arch-meson: add missing meson_sm_write_efuse signature
  arm/mach-meson: move smc commands in cmd/meson
  doc/usage: cmd: documentation for meson/sm command
  cmd/arm: meson: sm: introduce efusedump command
  doc/usage: cmd: sm: documentation efusedump cmd

 MAINTAINERS  |   1 +
 arch/arm/include/asm/arch-meson/sm.h |  28 
 arch/arm/mach-meson/sm.c | 144 
 cmd/Kconfig  |   7 +
 cmd/Makefile |   3 +
 cmd/meson/Makefile   |   5 +
 cmd/meson/sm.c   | 190 +++
 doc/usage/cmd/sm.rst |  48 +++
 doc/usage/index.rst  |   1 +
 9 files changed, 283 insertions(+), 144 deletions(-)
 create mode 100644 cmd/meson/Makefile
 create mode 100644 cmd/meson/sm.c
 create mode 100644 doc/usage/cmd/sm.rst

-- 
2.25.1



[PATCH v4 1/5] asm/arch-meson: add missing meson_sm_write_efuse signature

2023-01-10 Thread Alexey Romanov
This function can be used by other modules. Also add comments.

Signed-off-by: Alexey Romanov 
Reviewed-by: Neil Armstrong 
---
 arch/arm/include/asm/arch-meson/sm.h | 28 
 1 file changed, 28 insertions(+)

diff --git a/arch/arm/include/asm/arch-meson/sm.h 
b/arch/arm/include/asm/arch-meson/sm.h
index f3ae46a6d6b..53b75176493 100644
--- a/arch/arm/include/asm/arch-meson/sm.h
+++ b/arch/arm/include/asm/arch-meson/sm.h
@@ -6,10 +6,35 @@
 #ifndef __MESON_SM_H__
 #define __MESON_SM_H__
 
+/**
+ * meson_sm_read_efuse - read efuse memory into buffer
+ *
+ * @offset: offset from the start efuse memory
+ * @buffer: pointer to buffer
+ * @size: number of bytes to read
+ * @return: number of bytes read
+ */
 ssize_t meson_sm_read_efuse(uintptr_t offset, void *buffer, size_t size);
 
+/**
+ * meson_sm_write_efuse - write into efuse memory from buffer
+ *
+ * @offset: offset from the start efuse memory
+ * @buffer: pointer to buffer
+ * @size: number of bytes to write
+ * @return: number of bytes written
+ */
+ssize_t meson_sm_write_efuse(uintptr_t offset, void *buffer, size_t size);
+
 #define SM_SERIAL_SIZE 12
 
+/**
+ * meson_sm_get_serial - read chip unique id into buffer
+ *
+ * @buffer: pointer to buffer
+ * @size: buffer size.
+ * @return: zero on success or -errno on failure
+ */
 int meson_sm_get_serial(void *buffer, size_t size);
 
 enum {
@@ -28,6 +53,9 @@ enum {
REBOOT_REASON_WATCHDOG_REBOOT = 13,
 };
 
+/**
+ * meson_sm_get_reboot_reason - get reboot reason
+ */
 int meson_sm_get_reboot_reason(void);
 
 #endif /* __MESON_SM_H__ */
-- 
2.25.1



[PATCH v4 2/5] arm/mach-meson: move smc commands in cmd/meson

2023-01-10 Thread Alexey Romanov
It is incorrect to keep commands in the arch/ folder.

Signed-off-by: Alexey Romanov 
Reviewed-by: Mattijs Korpershoek 
Reviewed-by: Neil Armstrong 
---
 MAINTAINERS  |   1 +
 arch/arm/mach-meson/sm.c | 144 
 cmd/Kconfig  |   7 ++
 cmd/Makefile |   3 +
 cmd/meson/Makefile   |   5 ++
 cmd/meson/sm.c   | 156 +++
 6 files changed, 172 insertions(+), 144 deletions(-)
 create mode 100644 cmd/meson/Makefile
 create mode 100644 cmd/meson/sm.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 7f27ff4c20f..7a5460d4922 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -149,6 +149,7 @@ L:  u-boot-amlo...@groups.io
 T: git https://source.denx.de/u-boot/custodians/u-boot-amlogic.git
 F: arch/arm/mach-meson/
 F: arch/arm/include/asm/arch-meson/
+F: cmd/meson/
 F: drivers/clk/meson/
 F: drivers/serial/serial_meson.c
 F: drivers/reset/reset-meson.c
diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c
index d6eb910689f..f2ca7e76932 100644
--- a/arch/arm/mach-meson/sm.c
+++ b/arch/arm/mach-meson/sm.c
@@ -6,8 +6,6 @@
  */
 
 #include 
-#include 
-#include 
 #include 
 #include 
 #include 
@@ -139,145 +137,3 @@ int meson_sm_get_reboot_reason(void)
/* The SMC call is not used, we directly use AO_SEC_SD_CFG15 */
return FIELD_GET(REBOOT_REASON_MASK, reason);
 }
-
-static int do_sm_serial(struct cmd_tbl *cmdtp, int flag, int argc,
-   char *const argv[])
-{
-   ulong address;
-   int ret;
-
-   if (argc < 2)
-   return CMD_RET_USAGE;
-
-   address = simple_strtoul(argv[1], NULL, 0);
-
-   ret = meson_sm_get_serial((void *)address, SM_CHIP_ID_SIZE);
-   if (ret)
-   return CMD_RET_FAILURE;
-
-   return CMD_RET_SUCCESS;
-}
-
-#define MAX_REBOOT_REASONS 14
-
-static const char *reboot_reasons[MAX_REBOOT_REASONS] = {
-   [REBOOT_REASON_COLD] = "cold_boot",
-   [REBOOT_REASON_NORMAL] = "normal",
-   [REBOOT_REASON_RECOVERY] = "recovery",
-   [REBOOT_REASON_UPDATE] = "update",
-   [REBOOT_REASON_FASTBOOT] = "fastboot",
-   [REBOOT_REASON_SUSPEND_OFF] = "suspend_off",
-   [REBOOT_REASON_HIBERNATE] = "hibernate",
-   [REBOOT_REASON_BOOTLOADER] = "bootloader",
-   [REBOOT_REASON_SHUTDOWN_REBOOT] = "shutdown_reboot",
-   [REBOOT_REASON_RPMBP] = "rpmbp",
-   [REBOOT_REASON_CRASH_DUMP] = "crash_dump",
-   [REBOOT_REASON_KERNEL_PANIC] = "kernel_panic",
-   [REBOOT_REASON_WATCHDOG_REBOOT] = "watchdog_reboot",
-};
-
-static int do_sm_reboot_reason(struct cmd_tbl *cmdtp, int flag, int argc,
-  char *const argv[])
-{
-   const char *reason_str;
-   char *destarg = NULL;
-   int reason;
-
-   if (argc > 1)
-   destarg = argv[1];
-
-   reason = meson_sm_get_reboot_reason();
-   if (reason < 0)
-   return CMD_RET_FAILURE;
-
-   if (reason >= MAX_REBOOT_REASONS ||
-   !reboot_reasons[reason])
-   reason_str = "unknown";
-   else
-   reason_str = reboot_reasons[reason];
-
-   if (destarg)
-   env_set(destarg, reason_str);
-   else
-   printf("reboot reason: %s (%x)\n", reason_str, reason);
-
-   return CMD_RET_SUCCESS;
-}
-
-static int do_efuse_read(struct cmd_tbl *cmdtp, int flag, int argc,
-   char *const argv[])
-{
-   ulong address, offset, size;
-   int ret;
-
-   if (argc < 4)
-   return CMD_RET_USAGE;
-
-offset = simple_strtoul(argv[1], NULL, 0);
-size = simple_strtoul(argv[2], NULL, 0);
-
-address = simple_strtoul(argv[3], NULL, 0);
-
-   ret = meson_sm_read_efuse(offset, (void *)address, size);
-   if (ret != size)
-   return CMD_RET_FAILURE;
-
-   return CMD_RET_SUCCESS;
-}
-
-static int do_efuse_write(struct cmd_tbl *cmdtp, int flag, int argc,
-   char *const argv[])
-{
-   ulong address, offset, size;
-   int ret;
-
-   if (argc < 4)
-   return CMD_RET_USAGE;
-
-offset = simple_strtoul(argv[1], NULL, 0);
-size = simple_strtoul(argv[2], NULL, 0);
-
-address = simple_strtoul(argv[3], NULL, 0);
-
-   ret = meson_sm_write_efuse(offset, (void *)address, size);
-   if (ret != size)
-   return CMD_RET_FAILURE;
-
-   return CMD_RET_SUCCESS;
-}
-
-static struct cmd_tbl cmd_sm_sub[] = {
-   U_BOOT_CMD_MKENT(serial, 2, 1, do_sm_serial, "", ""),
-   U_BOOT_CMD_MKENT(reboot_reason, 1, 1, do_sm_reboot_reason, "", ""),
-   U_BOOT_CMD_MKENT(efuseread, 4, 1, do_efuse_read, "", ""),
-   U_BOOT_CMD_M

[PATCH v4 3/5] doc/usage: cmd: documentation for meson/sm command

2023-01-10 Thread Alexey Romanov
Added docs for Meson Security Monitor command.

Signed-off-by: Alexey Romanov 
---
 doc/usage/cmd/sm.rst | 44 
 doc/usage/index.rst  |  1 +
 2 files changed, 45 insertions(+)
 create mode 100644 doc/usage/cmd/sm.rst

diff --git a/doc/usage/cmd/sm.rst b/doc/usage/cmd/sm.rst
new file mode 100644
index 000..c41227f4b3b
--- /dev/null
+++ b/doc/usage/cmd/sm.rst
@@ -0,0 +1,44 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+sm command
+==
+
+Synopis
+---
+
+::
+
+sm serial 
+sm reboot_reason [name]
+sm efuseread   
+sm efusewrite   
+sm efusedump  
+
+Description
+---
+
+The sm command is used to request services from the secure monitor. User
+can call secure monitor to request special TEE function, for example chip
+serial number info, reboot reason, etc.
+
+sm serial
+  Retrieve chip unique serial number from sm and write it to memory on
+  appropriate address.
+
+sm reboot_reason
+  Print reboot reason to the console, if parameter [name] isn't specified.
+  If parameter specified, set reboot reason string to environment variable
+  with this name.
+
+sm efuseread
+  Read  bytes starting from  from efuse memory bank and write
+  result to the address .
+
+sm efusewrite
+  Write into efuse memory bank, starting from , the  bytes
+  of data, located at address .
+
+Configuration
+-
+
+To use the sm command you must specify CONFIG_CMD_MESON=y
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 770418434ad..e34b98dae24 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -61,6 +61,7 @@ Shell commands
cmd/true
cmd/ums
cmd/wdt
+   cmd/sm
 
 Booting OS
 --
-- 
2.25.1



[PATCH v4 5/5] doc/usage: cmd: sm: documentation efusedump cmd

2023-01-10 Thread Alexey Romanov
Added docs about sm efusedump command, that reads bytes
from efuse memory bank and print them to the console.

Signed-off-by: Alexey Romanov 
Reviewed-by: Neil Armstrong 
---
 doc/usage/cmd/sm.rst | 4 
 1 file changed, 4 insertions(+)

diff --git a/doc/usage/cmd/sm.rst b/doc/usage/cmd/sm.rst
index c41227f4b3b..f6524a1c2e3 100644
--- a/doc/usage/cmd/sm.rst
+++ b/doc/usage/cmd/sm.rst
@@ -38,6 +38,10 @@ sm efusewrite
   Write into efuse memory bank, starting from , the  bytes
   of data, located at address .
 
+sm efusedump
+  Read  bytes starting from  from efuse memory bank and print
+  them to the console.
+
 Configuration
 -
 
-- 
2.25.1



[PATCH v4 4/5] cmd/arm: meson: sm: introduce efusedump command

2023-01-10 Thread Alexey Romanov
Using this command user can print efuse memory:

$ sm efusedump 0 10
  : ff 00 31 00 00 ff 66 00 00 00  ..1...f...

Signed-off-by: Alexey Romanov 
Reviewed-by: Mattijs Korpershoek 
Reviewed-by: Neil Armstrong 
---
 cmd/meson/sm.c | 36 +++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/cmd/meson/sm.c b/cmd/meson/sm.c
index c2b57707258..d5eb1d6c084 100644
--- a/cmd/meson/sm.c
+++ b/cmd/meson/sm.c
@@ -5,6 +5,7 @@
  * Author: Beniamino Galvani 
  * Author: Vyacheslav Bocharov 
  * Author: Neil Armstrong 
+ * Author: Alexey Romanov 
  */
 
 #include 
@@ -119,11 +120,43 @@ static int do_efuse_write(struct cmd_tbl *cmdtp, int 
flag, int argc,
return CMD_RET_SUCCESS;
 }
 
+static int do_efuse_dump(struct cmd_tbl *cmdtp, int flag, int argc,
+   char *const argv[])
+{
+   ulong offset, size;
+   u8 *buffer;
+   int ret;
+
+   if (argc != 3)
+   return CMD_RET_USAGE;
+
+   offset = simple_strtoul(argv[1], NULL, 0);
+   size = simple_strtoul(argv[2], NULL, 0);
+   buffer = malloc(size);
+   if (!buffer) {
+   pr_err("Failed to allocate %lu bytes\n", size);
+   return CMD_RET_FAILURE;
+   }
+
+   ret = meson_sm_read_efuse(offset, (void *)buffer, size);
+   if (ret != size) {
+   ret = CMD_RET_FAILURE;
+   goto free_buffer;
+   }
+
+   print_buffer(0, buffer, 1, size, 0);
+
+free_buffer:
+   free(buffer);
+   return ret;
+}
+
 static struct cmd_tbl cmd_sm_sub[] = {
U_BOOT_CMD_MKENT(serial, 2, 1, do_sm_serial, "", ""),
U_BOOT_CMD_MKENT(reboot_reason, 1, 1, do_sm_reboot_reason, "", ""),
U_BOOT_CMD_MKENT(efuseread, 4, 1, do_efuse_read, "", ""),
U_BOOT_CMD_MKENT(efusewrite, 4, 0, do_efuse_write, "", ""),
+   U_BOOT_CMD_MKENT(efusedump, 3, 1, do_efuse_dump, "", ""),
 };
 
 static int do_sm(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -152,5 +185,6 @@ U_BOOT_CMD(
"serial  - read chip unique id to memory address\n"
"sm reboot_reason [name] - get reboot reason and store to environment\n"
"sm efuseread- read efuse to memory 
address\n"
-   "sm efusewrite- write into efuse from memory 
address"
+   "sm efusewrite- write into efuse from memory 
address\n"
+   "sm efusedump   - dump efuse data range to console"
 );
-- 
2.25.1



Re: [PATCH v1] android_ab: don't ignore ab_control_store return code

2023-12-13 Thread Alexey Romanov
Hello!

Really sorry for the noise, but please, take a look at my patch :)

On Tue, Nov 28, 2023 at 02:26:34PM +0300, Alexey Romanov wrote:
> ab_control_store() can return an error if writing to disk fails.
> In this case, we have to pass the error code to the caller.
> 
> Signed-off-by: Alexey Romanov 
> ---
>  boot/android_ab.c | 18 --
>  1 file changed, 16 insertions(+), 2 deletions(-)
> 
> diff --git a/boot/android_ab.c b/boot/android_ab.c
> index 73b55c196c..5a3152dd53 100644
> --- a/boot/android_ab.c
> +++ b/boot/android_ab.c
> @@ -337,7 +337,15 @@ int ab_select_slot(struct blk_desc *dev_desc, struct 
> disk_partition *part_info,
>  
>   if (store_needed) {
>   abc->crc32_le = ab_control_compute_crc(abc);
> - ab_control_store(dev_desc, part_info, abc, 0);
> + ret = ab_control_store(dev_desc, part_info, abc, 0);
> + if (ret < 0) {
> +#if ANDROID_AB_BACKUP_OFFSET
> + free(backup_abc);
> +#endif
> + free(abc);
> + log_err("ANDROID: failed to store boot control block: 
> %d\n", ret);
> + return ret;
> + }
>   }
>  
>  #if ANDROID_AB_BACKUP_OFFSET
> @@ -346,8 +354,14 @@ int ab_select_slot(struct blk_desc *dev_desc, struct 
> disk_partition *part_info,
>* to the backup offset
>*/
>   if (memcmp(backup_abc, abc, sizeof(*abc)) != 0) {
> - ab_control_store(dev_desc, part_info, abc,
> + ret = ab_control_store(dev_desc, part_info, abc,
>ANDROID_AB_BACKUP_OFFSET);
> + if (ret < 0) {
> + free(backup_abc);
> + free(abc);
> + log_err("ANDROID: failed to store boot control block: 
> %d\n", ret);
> + return ret;
> + }
>   }
>   free(backup_abc);
>  #endif
> -- 
> 2.39.2
> 

-- 
Thank you,
Alexey

[PATCH v2] android_ab: don't ignore ab_control_store return code

2023-12-25 Thread Alexey Romanov
ab_control_store() can return an error if writing to disk fails.
In this case, we have to pass the error code to the caller.

Signed-off-by: Alexey Romanov 
Reviewed-by: Mattijs Korpershoek 
---
 boot/android_ab.c | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/boot/android_ab.c b/boot/android_ab.c
index 73b55c196c..af3c375e07 100644
--- a/boot/android_ab.c
+++ b/boot/android_ab.c
@@ -337,7 +337,14 @@ int ab_select_slot(struct blk_desc *dev_desc, struct 
disk_partition *part_info,
 
if (store_needed) {
abc->crc32_le = ab_control_compute_crc(abc);
-   ab_control_store(dev_desc, part_info, abc, 0);
+   ret = ab_control_store(dev_desc, part_info, abc, 0);
+   if (ret < 0) {
+#if ANDROID_AB_BACKUP_OFFSET
+   free(backup_abc);
+#endif
+   free(abc);
+   return ret;
+   }
}
 
 #if ANDROID_AB_BACKUP_OFFSET
@@ -346,8 +353,13 @@ int ab_select_slot(struct blk_desc *dev_desc, struct 
disk_partition *part_info,
 * to the backup offset
 */
if (memcmp(backup_abc, abc, sizeof(*abc)) != 0) {
-   ab_control_store(dev_desc, part_info, abc,
+   ret = ab_control_store(dev_desc, part_info, abc,
 ANDROID_AB_BACKUP_OFFSET);
+   if (ret < 0) {
+   free(backup_abc);
+   free(abc);
+   return ret;
+   }
}
free(backup_abc);
 #endif
-- 
2.39.2



[PATCH v1] arch: meson: add helper for boot partitition flashing

2023-12-28 Thread Alexey Romanov
Amlogic uses its own scheme for flashing bootloader
partition. This patch adds helper function that can
be used by Amlogic BootROM and custom protocols.

Signed-off-by: Alexey Romanov 
---
 arch/arm/include/asm/arch-meson/nand.h |  88 
 arch/arm/mach-meson/Kconfig|  16 +++
 arch/arm/mach-meson/Makefile   |   2 +-
 arch/arm/mach-meson/nand.c | 133 +
 4 files changed, 238 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/include/asm/arch-meson/nand.h
 create mode 100644 arch/arm/mach-meson/nand.c

diff --git a/arch/arm/include/asm/arch-meson/nand.h 
b/arch/arm/include/asm/arch-meson/nand.h
new file mode 100644
index 00..5297d79dd6
--- /dev/null
+++ b/arch/arm/include/asm/arch-meson/nand.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2023 SaluteDevices, Inc.
+ */
+
+#ifndef __MESON_NAND_H__
+#define __MESON_NAND_H__
+
+#include 
+
+#define BOOT_LOADER "bootloader"
+#define BOOT_BL2"bl2"
+#define BOOT_SPL"spl"
+#define BOOT_TPL"tpl"
+#define BOOT_FIP"fip"
+
+#define BL2_COPY_NUM(CONFIG_MESON_BL2_COPY_NUM)
+#define TPL_COPY_NUM(CONFIG_MESON_TPL_COPY_NUM)
+#define BOOT_TOTAL_PAGES1024
+#define TPL_SIZE_PER_COPY   0x20
+#define BL2_SIZE(64 * 1024)
+
+struct meson_spi_nand_info_page {
+   char magic[8];  /* Magic header of info page. */
+   /* Info page version, +1 when you update this struct. */
+   u8 version; /* 1 for now. */
+   u8 mode;/* 1 discrete, 0 compact. */
+   u8 bl2_num; /* bl2 copy number. */
+   u8 fip_num; /* fip copy number. */
+   union {
+   struct {
+   u8 rd_max;  /* spi nand max read io. */
+   u8 oob_offset;  /* User bytes offset. */
+   u8 planes_per_lun;
+   u8 rsv;
+   u32 fip_start;  /* Start pages. */
+   u32 fip_pages;  /* Pages per fip. */
+   u32 page_size;  /* spi nand page size (bytes). */
+   u32 page_per_blk;   /* Page number per block. */
+   u32 oob_size;   /* Valid oob size (bytes). */
+   u32 bbt_start;  /* BBT start pages. */
+   u32 bbt_valid;  /* BBT valid offset pages. */
+   u32 bbt_size;   /* BBT occupied bytes. */
+   } __packed spinand; /* spi nand. */
+   struct {
+   u32 reserved;
+   } emmc;
+   } dev;
+} __packed;
+
+/**
+ * meson_bootloader_copy_num - get bootloader numbers of copies
+ *
+ * @part_name: partition name
+ * @return: number of copies of the specified bootloader partition
+ */
+int meson_bootloader_copy_num(const char *part_name);
+
+/**
+ * meson_bootloader_copy_size - get bootloader copy size in bytes
+ *
+ * @mtd: nand mtd instance
+ * @part_name: partition name
+ * @return: bootloader partition (fox example, BL2) copy size in bytes
+ */
+int meson_bootloader_copy_size(struct mtd_info *mtd, const char *part_name);
+
+/**
+ * meson_bootloader_write_info_pages - write bootloader metadata to nand
+ *
+ * @return: zero on success or error code on failure.
+ */
+int meson_bootloader_write_info_pages(void);
+
+/**
+ * meson_bootloader_write_bl2 - write bl2 to nand
+ *
+ * @mtd: nand mtd instance
+ * @buff: buffer to read from
+ * @offset: offset in flash
+ * @size: buffer length
+ * @flags: flags modifying the behaviour of the write to NAND
+ * @return: zero on success or error code on failure
+ */
+int meson_bootloader_write_bl2(struct mtd_info *mtd, void *buff, u32 offset,
+  size_t size, int flags);
+
+#endif
diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig
index d6c8905806..7b75ed9a2b 100644
--- a/arch/arm/mach-meson/Kconfig
+++ b/arch/arm/mach-meson/Kconfig
@@ -96,4 +96,20 @@ config SYS_CONFIG_NAME
  Based on this option include/configs/.h header
  will be used for board configuration.
 
+config MESON_BL2_COPY_NUM
+   depends on ADNL || FASTBOOT_FLASH
+   int "Number of BL2 copies written to storage"
+   default 0
+   help
+   The ADNL / fastboot protocol writes several copies of BL2 
bootloader
+   during firmware update process.
+
+config MESON_TPL_COPY_NUM
+   depends on ADNL || FASTBOOT_FLASH
+   int "Number of TPL copies written to storage"
+   default 0
+   help
+   The ADNL / fastboot protocol writes several copies of TPL 
bootloader
+   during firmware update process.
+
 endif
diff --git a/arch/arm/mach-meson/Makefile b/arch/arm/mach-meson/Makefile
index 535b0878b9..460626bca9 100644
--- a/arch/arm/mach-meson/Makefile

[PATCH v1] fastboot: introduce 'oem board' subcommand

2023-12-28 Thread Alexey Romanov
Currently, fastboot protocol in U-Boot has no opportunity
to execute vendor custom code with verifed boot. This patch
introduce new fastboot subcommand fastboot oem board:,
which allow to run custom oem_board function.

Default implementation is __weak. Vendor must redefine it in
board/ folder with his own logic.

For example, some vendors have their custom nand/emmc partition
flashing or erasing. Here some typical command for such use cases:

- flashing:

  $ fastboot stage bootloader.img
  $ fastboot oem board:write_bootloader

- erasing:

  $ fastboot oem board:erase_env

Signed-off-by: Alexey Romanov 
---
 drivers/fastboot/Kconfig  |  7 +++
 drivers/fastboot/fb_command.c | 15 +++
 include/fastboot.h|  1 +
 3 files changed, 23 insertions(+)

diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
index 3cfeea4837..4c955cabab 100644
--- a/drivers/fastboot/Kconfig
+++ b/drivers/fastboot/Kconfig
@@ -241,6 +241,13 @@ config FASTBOOT_OEM_RUN
  this feature if you are using verified boot, as it will allow an
  attacker to bypass any restrictions you have in place.
 
+config FASTBOOT_OEM_BOARD
+   bool "Enable the 'oem board' command"
+   help
+ This extends the fastboot protocol with an "oem board" command. This
+ command allows running vendor custom code defined in board/ files.
+ Otherwise, it will do nothing and send fastboot fail.
+
 endif # FASTBOOT
 
 endmenu
diff --git a/drivers/fastboot/fb_command.c b/drivers/fastboot/fb_command.c
index 71cfaec6e9..4d2b451f46 100644
--- a/drivers/fastboot/fb_command.c
+++ b/drivers/fastboot/fb_command.c
@@ -39,6 +39,7 @@ static void reboot_recovery(char *, char *);
 static void oem_format(char *, char *);
 static void oem_partconf(char *, char *);
 static void oem_bootbus(char *, char *);
+static void oem_board(char *, char *);
 static void run_ucmd(char *, char *);
 static void run_acmd(char *, char *);
 
@@ -106,6 +107,10 @@ static const struct {
.command = "oem run",
.dispatch = CONFIG_IS_ENABLED(FASTBOOT_OEM_RUN, (run_ucmd), 
(NULL))
},
+   [FASTBOOT_COMMAND_OEM_BOARD] = {
+   .command = "oem board",
+   .dispatch = CONFIG_IS_ENABLED(FASTBOOT_OEM_BOARD, (oem_board), 
(NULL))
+   },
[FASTBOOT_COMMAND_UCMD] = {
.command = "UCmd",
.dispatch = CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT, (run_ucmd), 
(NULL))
@@ -489,3 +494,13 @@ static void __maybe_unused oem_bootbus(char 
*cmd_parameter, char *response)
else
fastboot_okay(NULL, response);
 }
+
+void __weak fastboot_oem_board(char *cmd_parameter, void *data, u32 size, char 
*response)
+{
+   fastboot_fail("oem board function not defined", response);
+}
+
+static void __maybe_unused oem_board(char *cmd_parameter, char *response)
+{
+   fastboot_oem_board(cmd_parameter, fastboot_buf_addr, image_size, 
response);
+}
diff --git a/include/fastboot.h b/include/fastboot.h
index 296451f89d..06c1f26b6c 100644
--- a/include/fastboot.h
+++ b/include/fastboot.h
@@ -37,6 +37,7 @@ enum {
FASTBOOT_COMMAND_OEM_PARTCONF,
FASTBOOT_COMMAND_OEM_BOOTBUS,
FASTBOOT_COMMAND_OEM_RUN,
+   FASTBOOT_COMMAND_OEM_BOARD,
FASTBOOT_COMMAND_ACMD,
FASTBOOT_COMMAND_UCMD,
FASTBOOT_COMMAND_COUNT
-- 
2.30.1



  1   2   3   >