Some K3 SoCs like J721S2, J784S4, J722S, AM62X and AM62PX have a HSM
(High Security Module) M4F core in the Wakeup Voltage Domain which could
be used to run secure services like Authentication. Boot flow for HSM M4
core is different than the general purpose M4F cores, and is as below:

1. Request control of HSM M4F remote processor.
2. Assert Reset on the HSM M4F remote processor.
3. For HS devices, Request Secure Entity to Authenticate and Load HSM
   firmware into core's internal SRAM memory region. For GP devices,
   load the unsigned firmware manually.
4. Deassert Reset on the HSM M4F remote processor.
5. Release control of HSM M4F remote processor.

Add a new remoteproc driver to support this boot flow for HSM M4F core.

Signed-off-by: Beleswar Padhi <[email protected]>
---
v3: Changelog:
1. New patch. Add a dedicated remoteproc driver to boot HSM core.

 MAINTAINERS                          |   1 +
 drivers/remoteproc/Kconfig           |  10 ++
 drivers/remoteproc/Makefile          |   1 +
 drivers/remoteproc/ti_k3_hsm_rproc.c | 252 +++++++++++++++++++++++++++
 4 files changed, 264 insertions(+)
 create mode 100644 drivers/remoteproc/ti_k3_hsm_rproc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 6ce0bbce13d..1a11b580a66 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -802,6 +802,7 @@ F:  drivers/phy/ti-pipe3-phy.c
 F:     drivers/ram/k3*
 F:     drivers/ram/k3*/
 F:     drivers/remoteproc/ipu_rproc.c
+F:     drivers/remoteproc/ti_k3_hsm_rproc.c
 F:     drivers/remoteproc/k3_system_controller.c
 F:     drivers/remoteproc/pruc_rpoc.c
 F:     drivers/remoteproc/ti*
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 8056f210abc..5514f092615 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -99,6 +99,16 @@ config REMOTEPROC_TI_K3_M4F
          on various TI K3 family of SoCs through the remote processor
          framework.
 
+config REMOTEPROC_TI_K3_HSM_M4F
+       bool "TI K3 HSM M4F remoteproc support"
+       select REMOTEPROC
+       depends on ARCH_K3
+       depends on TI_SCI_PROTOCOL
+       help
+         Say y here to support TI's HSM M4F remote processor subsystems
+         on various TI K3 family of SoCs through the remote processor
+         framework.
+
 config REMOTEPROC_TI_K3_R5F
        bool "TI K3 R5F remoteproc support"
        select REMOTEPROC
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 7ea8023c50b..d29e1bf9db2 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_REMOTEPROC_STM32_COPRO) += stm32_copro.o
 obj-$(CONFIG_REMOTEPROC_TI_K3_ARM64) += ti_k3_arm64_rproc.o
 obj-$(CONFIG_REMOTEPROC_TI_K3_DSP) += ti_k3_dsp_rproc.o
 obj-$(CONFIG_REMOTEPROC_TI_K3_M4F) += ti_k3_m4_rproc.o
+obj-$(CONFIG_REMOTEPROC_TI_K3_HSM_M4F) += ti_k3_hsm_rproc.o
 obj-$(CONFIG_REMOTEPROC_TI_K3_R5F) += ti_k3_r5f_rproc.o
 obj-$(CONFIG_REMOTEPROC_TI_POWER) += ti_power_proc.o
 obj-$(CONFIG_REMOTEPROC_TI_PRU) += pru_rproc.o
diff --git a/drivers/remoteproc/ti_k3_hsm_rproc.c 
b/drivers/remoteproc/ti_k3_hsm_rproc.c
new file mode 100644
index 00000000000..4c05fef487a
--- /dev/null
+++ b/drivers/remoteproc/ti_k3_hsm_rproc.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Texas Instruments' K3 HSM M4 Remoteproc driver
+ *
+ * Copyright (C) 2025 Texas Instruments Incorporated - http://www.ti.com/
+ *     Beleswar Padhi <[email protected]>
+ */
+
+#include <cpu_func.h>
+#include <dm.h>
+#include <log.h>
+#include <malloc.h>
+#include <remoteproc.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <dm/device_compat.h>
+#include <linux/err.h>
+#include <linux/sizes.h>
+#include <linux/soc/ti/ti_sci_protocol.h>
+#include "ti_sci_proc.h"
+#include <mach/security.h>
+
+#define PROC_BOOT_CTRL_RESET_FLAG_HSM_M4 0x00000001
+
+/**
+ * struct k3_hsm_mem - internal memory structure
+ * @cpu_addr: MPU virtual address of the memory region
+ * @bus_addr: Bus address used to access the memory region
+ * @dev_addr: Device address from remoteproc view
+ * @size: Size of the memory region
+ */
+struct k3_hsm_mem {
+       void __iomem *cpu_addr;
+       phys_addr_t bus_addr;
+       phys_addr_t dev_addr;
+       size_t size;
+};
+
+/**
+ * struct k3_hsm_mem_data - memory definitions for hsm remote core
+ * @name: name for this memory entry
+ * @dev_addr: device address for the memory entry
+ */
+struct k3_hsm_mem_data {
+       const char *name;
+       const u32 dev_addr;
+};
+
+/**
+ * struct k3_hsm_privdata - Structure representing Remote processor data.
+ * @tsp:       Pointer to TISCI proc control handle
+ * @mem:       Array of available memories
+ * @num_mems:  Number of available memories
+ */
+struct k3_hsm_privdata {
+       struct ti_sci_proc tsp;
+       struct k3_hsm_mem *mem;
+       int num_mems;
+};
+
+/**
+ * k3_hsm_load() - Load up the Remote processor image
+ * @dev:       rproc device pointer
+ * @addr:      Address at which image is available
+ * @size:      size of the image
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+static int k3_hsm_load(struct udevice *dev, ulong addr, ulong size)
+{
+       struct k3_hsm_privdata *hsm = dev_get_priv(dev);
+       size_t image_size = size;
+       int ret;
+
+       ret = ti_sci_proc_request(&hsm->tsp);
+       if (ret)
+               return ret;
+
+       ret = ti_sci_proc_set_control(&hsm->tsp,
+                                     PROC_BOOT_CTRL_RESET_FLAG_HSM_M4, 0);
+       if (ret)
+               goto proc_release;
+
+       ti_secure_image_post_process((void *)&addr, &image_size);
+
+       if (image_size == size) {
+               debug("Loading HSM GP binary into SRAM0_0\n");
+               memcpy((void *)hsm->mem[0].cpu_addr, (void *)(u32)addr, size);
+               flush_dcache_range((unsigned long)hsm->mem[0].cpu_addr,
+                                  (unsigned long)(hsm->mem[0].cpu_addr + 
size));
+       }
+
+proc_release:
+       ti_sci_proc_release(&hsm->tsp);
+       return ret;
+}
+
+/**
+ * k3_hsm_start() - Start the remote processor
+ * @dev:       rproc device pointer
+ *
+ * Return: 0 if all went ok, else return appropriate error
+ */
+static int k3_hsm_start(struct udevice *dev)
+{
+       struct k3_hsm_privdata *hsm = dev_get_priv(dev);
+       int ret;
+
+       ret = ti_sci_proc_request(&hsm->tsp);
+       if (ret)
+               return ret;
+
+       ret = ti_sci_proc_set_control(&hsm->tsp, 0,
+                                     PROC_BOOT_CTRL_RESET_FLAG_HSM_M4);
+
+       ti_sci_proc_release(&hsm->tsp);
+
+       return ret;
+}
+
+static int k3_hsm_stop(struct udevice *dev)
+{
+       struct k3_hsm_privdata *hsm = dev_get_priv(dev);
+       int ret;
+
+       ti_sci_proc_request(&hsm->tsp);
+
+       ret = ti_sci_proc_set_control(&hsm->tsp,
+                                     PROC_BOOT_CTRL_RESET_FLAG_HSM_M4, 0);
+
+       ti_sci_proc_release(&hsm->tsp);
+
+       return ret;
+}
+
+static const struct dm_rproc_ops k3_hsm_ops = {
+       .load = k3_hsm_load,
+       .start = k3_hsm_start,
+       .stop = k3_hsm_stop,
+};
+
+static int ti_sci_proc_of_to_priv(struct udevice *dev, struct ti_sci_proc *tsp)
+{
+       u32 ids[2];
+       int ret;
+
+       tsp->sci = ti_sci_get_by_phandle(dev, "ti,sci");
+       if (IS_ERR(tsp->sci)) {
+               dev_err(dev, "ti_sci get failed: %ld\n", PTR_ERR(tsp->sci));
+               return PTR_ERR(tsp->sci);
+       }
+
+       ret = dev_read_u32_array(dev, "ti,sci-proc-ids", ids, 2);
+       if (ret) {
+               dev_err(dev, "Proc IDs not populated %d\n", ret);
+               return ret;
+       }
+
+       tsp->ops = &tsp->sci->ops.proc_ops;
+       tsp->proc_id = ids[0];
+       tsp->host_id = ids[1];
+       tsp->dev_id = dev_read_u32_default(dev, "ti,sci-dev-id",
+                                          TI_SCI_RESOURCE_NULL);
+       if (tsp->dev_id == TI_SCI_RESOURCE_NULL) {
+               dev_err(dev, "Device ID not populated %d\n", ret);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static const struct k3_hsm_mem_data hsm_mems[] = {
+       { .name = "sram0_0", .dev_addr = 0x0 },
+       { .name = "sram0_1", .dev_addr = 0x20000 },
+       { .name = "sram1",   .dev_addr = 0x30000 },
+};
+
+static int k3_hsm_of_get_memories(struct udevice *dev)
+{
+       struct k3_hsm_privdata *hsm = dev_get_priv(dev);
+       int i;
+
+       hsm->num_mems = ARRAY_SIZE(hsm_mems);
+       hsm->mem = calloc(hsm->num_mems, sizeof(*hsm->mem));
+       if (!hsm->mem)
+               return -ENOMEM;
+
+       for (i = 0; i < hsm->num_mems; i++) {
+               hsm->mem[i].bus_addr = dev_read_addr_size_name(dev,
+                                                              hsm_mems[i].name,
+                                                              (fdt_addr_t 
*)&hsm->mem[i].size);
+               if (hsm->mem[i].bus_addr == FDT_ADDR_T_NONE) {
+                       dev_err(dev, "%s bus address not found\n",
+                               hsm_mems[i].name);
+                       return -EINVAL;
+               }
+               hsm->mem[i].cpu_addr = map_physmem(hsm->mem[i].bus_addr,
+                                                  hsm->mem[i].size,
+                                                  MAP_NOCACHE);
+               hsm->mem[i].dev_addr = hsm_mems[i].dev_addr;
+       }
+
+       return 0;
+}
+
+/**
+ * k3_hsm_probe() - Basic probe
+ * @dev:       corresponding k3 remote processor device
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+static int k3_hsm_probe(struct udevice *dev)
+{
+       struct k3_hsm_privdata *hsm;
+       int ret;
+
+       hsm = dev_get_priv(dev);
+
+       ret = ti_sci_proc_of_to_priv(dev, &hsm->tsp);
+       if (ret)
+               return ret;
+
+       ret = k3_hsm_of_get_memories(dev);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int k3_hsm_remove(struct udevice *dev)
+{
+       struct k3_hsm_privdata *hsm = dev_get_priv(dev);
+
+       free(hsm->mem);
+
+       return 0;
+}
+
+static const struct udevice_id k3_hsm_ids[] = {
+       { .compatible = "ti,hsm-m4fss" },
+       {}
+};
+
+U_BOOT_DRIVER(k3_hsm) = {
+       .name = "k3_hsm",
+       .of_match = k3_hsm_ids,
+       .id = UCLASS_REMOTEPROC,
+       .ops = &k3_hsm_ops,
+       .probe = k3_hsm_probe,
+       .remove = k3_hsm_remove,
+       .priv_auto = sizeof(struct k3_hsm_privdata),
+};
-- 
2.34.1

Reply via email to