summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorHarrison Mutai <harrison.mutai@arm.com>2026-07-31 08:36:38 +0000
committerTrustedFirmware Code Review <review@review.trustedfirmware.org>2026-07-31 08:36:38 +0000
commit92d930f35917c39042b8cf43423c695cc2e2589a (patch)
tree32f1a9a2b6315d51076ad1abfd1db98a3d6d4805 /drivers
parent994af9e0606a3f5f225bd8c75d5bc9264668fd0c (diff)
parent456e76541e31d908afef6eda64191654fd546c1c (diff)
downloadarm-trusted-firmware-92d930f35917c39042b8cf43423c695cc2e2589a.tar.gz
arm-trusted-firmware-92d930f35917c39042b8cf43423c695cc2e2589a.zip
Merge changes Ib7bbee3a,Iad97a8e6,I559b1a76,Id06acacc,I73c48adb into integration
* changes: feat(lemans_evk): enable RPMh driver feat(qti): add RPMh command service driver feat(lemans_evk): enable power utils driver feat(qti): add power utils (vlvl <-> hlvl) driver feat(qti): add aux data APIs to CMD DB driver
Diffstat (limited to 'drivers')
-rw-r--r--drivers/qti/cmd_db/cmd_db.c60
-rw-r--r--drivers/qti/pwr_utils/pwr_utils.c158
-rw-r--r--drivers/qti/pwr_utils/pwr_utils.mk16
-rw-r--r--drivers/qti/rpmh/lemans/rsc_regs.h91
-rw-r--r--drivers/qti/rpmh/rpmh.mk18
-rw-r--r--drivers/qti/rpmh/rpmh_client.c228
6 files changed, 566 insertions, 5 deletions
diff --git a/drivers/qti/cmd_db/cmd_db.c b/drivers/qti/cmd_db/cmd_db.c
index 3c01e1976..fc44f8657 100644
--- a/drivers/qti/cmd_db/cmd_db.c
+++ b/drivers/qti/cmd_db/cmd_db.c
@@ -85,7 +85,14 @@ static uint64_t res_id_to_u64(const char *res_id)
return val;
}
-uint32_t cmd_db_query_addr(const char *res_id)
+/*
+ * Look up a resource entry by its identifier string. On success returns a
+ * pointer to the matching entry and, if @info_out is non-NULL, the owning
+ * slave ID info block. Returns NULL when the resource is not found.
+ */
+static const struct cmd_db_entry *cmd_db_find_entry(
+ const char *res_id,
+ const struct cmd_db_slv_id_info **info_out)
{
uint64_t key;
unsigned int slv;
@@ -94,12 +101,12 @@ uint32_t cmd_db_query_addr(const char *res_id)
const struct cmd_db_entry *entry;
if (res_id == NULL) {
- return 0U;
+ return NULL;
}
if (g_cmd_db == NULL) {
if (cmd_db_init() != 0) {
- return 0U;
+ return NULL;
}
}
@@ -119,10 +126,53 @@ uint32_t cmd_db_query_addr(const char *res_id)
idx * sizeof(struct cmd_db_entry));
if (entry->res_id == key) {
- return entry->addr;
+ if (info_out != NULL) {
+ *info_out = info;
+ }
+ return entry;
}
}
}
- return 0U;
+ return NULL;
+}
+
+uint32_t cmd_db_query_addr(const char *res_id)
+{
+ const struct cmd_db_entry *entry = cmd_db_find_entry(res_id, NULL);
+
+ return (entry != NULL) ? entry->addr : 0U;
+}
+
+uint32_t cmd_db_query_len(const char *res_id)
+{
+ const struct cmd_db_entry *entry = cmd_db_find_entry(res_id, NULL);
+
+ return (entry != NULL) ? (uint32_t)entry->len : 0U;
+}
+
+int cmd_db_query_aux_data(const char *res_id, uint8_t *len, uint8_t *data)
+{
+ const struct cmd_db_slv_id_info *info = NULL;
+ const struct cmd_db_entry *entry;
+ const uint8_t *src;
+ uint32_t copy_len;
+
+ if ((len == NULL) || (data == NULL)) {
+ return -1;
+ }
+
+ entry = cmd_db_find_entry(res_id, &info);
+ if ((entry == NULL) || (entry->len == 0U)) {
+ return -1;
+ }
+
+ /* Copy back at most what the caller's buffer can hold */
+ copy_len = (*len < entry->len) ? (uint32_t)*len : (uint32_t)entry->len;
+
+ src = g_cmd_db->data + info->data_offset + entry->offset;
+ memcpy(data, src, copy_len);
+
+ *len = (uint8_t)copy_len;
+ return 0;
}
diff --git a/drivers/qti/pwr_utils/pwr_utils.c b/drivers/qti/pwr_utils/pwr_utils.c
new file mode 100644
index 000000000..cd7d1790d
--- /dev/null
+++ b/drivers/qti/pwr_utils/pwr_utils.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2026, Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * pwr_utils.c
+ *
+ * Implements the APIs to convert SW corners/levels (vlvl) to HW corners/levels
+ * (hlvl) and vice versa, using the per-resource aux data stored in the RPMh
+ * command DB.
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <drivers/qti/cmd_db/cmd_db.h>
+#include <drivers/qti/pwr_utils/pwr_utils.h>
+#include <lib/utils_def.h>
+
+/* Max aux data length (in bytes) supported per resource. */
+#define MAX_AUX_DATA_LEN 32U
+
+/* Describes the supported vlvl<->hlvl mapping for a single rail resource. */
+struct pwr_utils_lvl_res {
+ const char *name; /* resource name, e.g. "cx.lvl", "mx.lvl" */
+ uint16_t *vlvls; /* supported vlvls, indexed by hlvl */
+ size_t count; /* number of valid entries in vlvls */
+};
+
+/*
+ * Target specific rail resources.
+ *
+ * This information would normally live in a dedicated target file or devcfg,
+ * but the power utils are meant to be light on code footprint, so it is kept
+ * here. Targets that share the same set of rail resources can share this list.
+ */
+static struct pwr_utils_lvl_res resource_list[] = {
+ {"cx.lvl", NULL, 0},
+ {"mx.lvl", NULL, 0},
+ {"ebi.lvl", NULL, 0},
+ {"lcx.lvl", NULL, 0},
+ {"lmx.lvl", NULL, 0},
+ {"gfx.lvl", NULL, 0},
+ {"mss.lvl", NULL, 0},
+ {"ddr.lvl", NULL, 0},
+ {"xo.lvl", NULL, 0},
+ {"mmcx.lvl", NULL, 0},
+};
+
+/* Backing store for the per-resource vlvl tables (no malloc available). */
+static uint16_t lvl_buf[512];
+
+static bool valid_resource_idx(int resource_idx)
+{
+ return (resource_idx >= 0) &&
+ ((size_t)resource_idx < ARRAY_SIZE(resource_list));
+}
+
+void qti_pwr_utils_init(void)
+{
+ size_t used = 0U;
+ size_t i;
+
+ for (i = 0U; i < ARRAY_SIZE(resource_list); i++) {
+ struct pwr_utils_lvl_res *res = &resource_list[i];
+ uint32_t data_len = cmd_db_query_len(res->name);
+ uint8_t aux_len = (uint8_t)data_len;
+ size_t avail, j;
+
+ /* No aux data: leave vlvls NULL and count 0. */
+ if (data_len == 0U) {
+ continue;
+ }
+
+ assert(data_len <= MAX_AUX_DATA_LEN);
+
+ /* Carve the resource's table out of the static buffer. */
+ assert((used + (data_len / sizeof(uint16_t))) <=
+ ARRAY_SIZE(lvl_buf));
+ res->vlvls = &lvl_buf[used];
+
+ cmd_db_query_aux_data(res->name, &aux_len,
+ (uint8_t *)res->vlvls);
+ assert(data_len == (uint32_t)aux_len);
+
+ /*
+ * Count the valid levels. A zero entry past index 0 marks the
+ * end of the table.
+ */
+ avail = data_len / sizeof(uint16_t);
+ for (j = 0U; j < avail; j++) {
+ if ((j != 0U) && (res->vlvls[j] == 0U)) {
+ break;
+ }
+ }
+
+ res->count = j;
+ used += avail;
+ }
+}
+
+int pwr_utils_lvl_resource_idx(const char *res_name)
+{
+ size_t i;
+
+ if (res_name == NULL) {
+ return -1;
+ }
+
+ for (i = 0U; i < ARRAY_SIZE(resource_list); i++) {
+ if (strcmp(resource_list[i].name, res_name) == 0) {
+ return (int)i;
+ }
+ }
+
+ return -1; /* Resource not found */
+}
+
+static int pwr_utils_hlvl(int resource_idx, int vlvl, int *mapped_vlvl)
+{
+ const struct pwr_utils_lvl_res *res;
+ int discard;
+ size_t i;
+
+ if (mapped_vlvl == NULL) {
+ mapped_vlvl = &discard;
+ }
+
+ if (!valid_resource_idx(resource_idx) || (vlvl < 0)) {
+ *mapped_vlvl = RAIL_VOLTAGE_LEVEL_INVALID;
+ return -1;
+ }
+
+ res = &resource_list[resource_idx];
+
+ /* Return the first hlvl whose vlvl meets or exceeds the request. */
+ for (i = 0U; i < res->count; i++) {
+ if (res->vlvls[i] >= vlvl) {
+ *mapped_vlvl = res->vlvls[i];
+ return (int)i;
+ }
+ }
+
+ /* Requested vlvl exceeds the max supported vlvl for this resource. */
+ *mapped_vlvl = RAIL_VOLTAGE_LEVEL_OVERLIMIT;
+ return -1;
+}
+
+int pwr_utils_hlvl_named_resource(const char *resource, int vlvl,
+ int *mapped_vlvl)
+{
+ /* pwr_utils_hlvl() validates the index, so no check is needed here. */
+ return pwr_utils_hlvl(pwr_utils_lvl_resource_idx(resource), vlvl,
+ mapped_vlvl);
+}
diff --git a/drivers/qti/pwr_utils/pwr_utils.mk b/drivers/qti/pwr_utils/pwr_utils.mk
new file mode 100644
index 000000000..dd5033716
--- /dev/null
+++ b/drivers/qti/pwr_utils/pwr_utils.mk
@@ -0,0 +1,16 @@
+#
+# Copyright (c) 2026, Qualcomm Technologies, Inc. and/or its subsidiaries.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Power utils (vlvl <-> hlvl) driver
+#
+
+$(eval $(call add_define,QTI_PWR_UTILS_ENABLED))
+
+PWR_UTILS_DRV_PATH := drivers/qti/pwr_utils
+CMD_DB_DRV_PATH := drivers/qti/cmd_db
+
+BL31_SOURCES += \
+ $(PWR_UTILS_DRV_PATH)/pwr_utils.c \
+ $(CMD_DB_DRV_PATH)/cmd_db.c
diff --git a/drivers/qti/rpmh/lemans/rsc_regs.h b/drivers/qti/rpmh/lemans/rsc_regs.h
new file mode 100644
index 000000000..5933a3c5b
--- /dev/null
+++ b/drivers/qti/rpmh/lemans/rsc_regs.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2026, Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * RSC (Resource State Coordinator) register definitions for the lemans
+ * (qcs9075) APSS RPMh controller, DRV0 (TZ) view.
+ */
+
+#ifndef RSC_REGS_H
+#define RSC_REGS_H
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+#include <platform_def.h>
+
+/*
+ * APSS RSC register base. Derived from the HW description:
+ * APSS_RSC_RSCC_RSCC_RSC_REG_BASE = QTI_APSS_HM_BASE + 0x00a00000
+ */
+#define RSC_REG_BASE (QTI_APSS_HM_BASE + 0x00a00000U)
+
+/* Per-DRV AMC-mode IRQ registers (DRV0). */
+#define RSC_AMC_IRQ_ENABLE_OFF 0xd00U
+#define RSC_AMC_IRQ_STATUS_OFF 0xd04U
+#define RSC_AMC_IRQ_CLEAR_OFF 0xd08U
+
+/* Per-TCS register block within DRV0. */
+#define RSC_TCS_STRIDE 0x2a0U
+#define RSC_TCS_BASE_OFF 0xd10U
+
+#define RSC_TCS_CMD_WAIT_FOR_CMPL_OFF 0x00U
+#define RSC_TCS_CONTROL_OFF 0x04U
+#define RSC_TCS_STATUS_OFF 0x08U
+#define RSC_TCS_CMD_ENABLE_OFF 0x0cU
+
+/* CONTROL register fields. */
+#define RSC_TCS_CONTROL_AMC_MODE_TRIGGER BIT(24)
+#define RSC_TCS_CONTROL_AMC_MODE_EN BIT(16)
+
+/* STATUS register fields. */
+#define RSC_TCS_STATUS_CONTROLLER_IDLE BIT(0)
+
+/* Per-command register block within a TCS. */
+#define RSC_CMD_STRIDE 0x14U
+#define RSC_CMD_BASE_OFF 0xd30U
+
+#define RSC_CMD_MSGID_OFF 0x00U
+#define RSC_CMD_ADDR_OFF 0x04U
+#define RSC_CMD_DATA_OFF 0x08U
+#define RSC_CMD_STATUS_OFF 0x0cU
+#define RSC_CMD_RESP_DATA_OFF 0x10U
+
+/* MSGID register fields. */
+#define RSC_CMD_MSGID_READ_OR_WRITE BIT(16)
+#define RSC_CMD_MSGID_RES_REQ BIT(8)
+#define RSC_CMD_MSGID_MSG_LENGTH_SHFT 0U
+#define RSC_CMD_MSGID_MSG_LENGTH_MASK 0xfU
+
+/* ADDR register fields. */
+#define RSC_CMD_ADDR_SLV_ID_SHFT 16U
+#define RSC_CMD_ADDR_SLV_ID_MASK 0x7U
+#define RSC_CMD_ADDR_OFFSET_SHFT 0U
+#define RSC_CMD_ADDR_OFFSET_MASK 0xffffU
+
+/* CMD STATUS register fields. */
+#define RSC_CMD_STATUS_COMPLETED BIT(16)
+#define RSC_CMD_STATUS_ISSUED BIT(8)
+#define RSC_CMD_STATUS_TRIGGERED BIT(0)
+
+/* Each RPMh command transfers a single 32-bit word (encoded as 8 bytes). */
+#define RSC_CMD_DATA_LEN 8U
+
+/* Split a {slave-id, offset} resource address. */
+#define RSC_SLAVE_ID(addr) (((addr) >> 16) & RSC_CMD_ADDR_SLV_ID_MASK)
+#define RSC_OFFSET(addr) ((addr) & RSC_CMD_ADDR_OFFSET_MASK)
+
+/* Address helpers (DRV0). */
+#define RSC_DRV0_REG(off) \
+ ((uintptr_t)RSC_REG_BASE + (uint32_t)(off))
+
+#define RSC_TCS_REG(tcs, off) \
+ RSC_DRV0_REG(RSC_TCS_BASE_OFF + (RSC_TCS_STRIDE * (uint32_t)(tcs)) + \
+ (uint32_t)(off))
+
+#define RSC_CMD_REG(tcs, cmd, off) \
+ RSC_DRV0_REG(RSC_CMD_BASE_OFF + (RSC_TCS_STRIDE * (uint32_t)(tcs)) + \
+ (RSC_CMD_STRIDE * (uint32_t)(cmd)) + (uint32_t)(off))
+
+#endif /* RSC_REGS_H */
diff --git a/drivers/qti/rpmh/rpmh.mk b/drivers/qti/rpmh/rpmh.mk
new file mode 100644
index 000000000..52fcd593f
--- /dev/null
+++ b/drivers/qti/rpmh/rpmh.mk
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2026, Qualcomm Technologies, Inc. and/or its subsidiaries.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# RPMh (Resource Power Manager hardened) command service driver
+#
+
+$(eval $(call add_define,QTI_RPMH_ENABLED))
+
+RPMH_DRV_PATH := drivers/qti/rpmh
+
+PLAT_INCLUDES += \
+ -I$(RPMH_DRV_PATH) \
+ -I$(RPMH_DRV_PATH)/$(CHIPSET)
+
+BL31_SOURCES += \
+ $(RPMH_DRV_PATH)/rpmh_client.c
diff --git a/drivers/qti/rpmh/rpmh_client.c b/drivers/qti/rpmh/rpmh_client.c
new file mode 100644
index 000000000..d4225c661
--- /dev/null
+++ b/drivers/qti/rpmh/rpmh_client.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2026, Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * RPMh command service for the QTI APSS RSC, TZ DRV.
+ *
+ * The TZ DRV issues all of its commands as ACTIVE-set AMCs (Active Mode
+ * Commands). Unlike the full multi-client RPMh driver, BL31 runs single
+ * threaded and issues commands synchronously: a command set is programmed
+ * into a TCS, the AMC is triggered, and the issuing call polls the AMC
+ * finished interrupt status before returning. Sleep/wake sets are not
+ * supported on the TZ DRV.
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <drivers/qti/rpmh/rpmh_client.h>
+#include <lib/spinlock.h>
+
+#include "rsc_regs.h"
+
+/*
+ * TZ DRV TCS configuration (matches the RPMh DRV config):
+ * - 4 TCSs total, the first two are AMC TCSs.
+ * We use the first AMC TCS for synchronous ACTIVE requests.
+ */
+#define RPMH_TZ_NUM_TCS 4U
+#define RPMH_TZ_AMC_TCS 0U
+
+/* AMC completion poll bound; the AMC normally completes in microseconds. */
+#define RPMH_AMC_POLL_COUNT 1000000U
+
+struct rpmh_client {
+ uint32_t drv_id;
+ const char *name;
+ uint32_t next_req_id;
+ bool in_use;
+};
+
+static struct rpmh_client rpmh_clients[RSC_DRV_TZ + 1U];
+static spinlock_t rpmh_lock;
+static bool rpmh_initialized;
+
+void rpmh_client_init(void)
+{
+ rpmh_initialized = true;
+}
+
+struct rpmh_client *rpmh_create_handle(uint32_t drv_id,
+ const char *client_name)
+{
+ struct rpmh_client *client;
+
+ assert(rpmh_initialized);
+
+ /* Only the TZ DRV is driven from TF-A. */
+ if (drv_id != RSC_DRV_TZ) {
+ return NULL;
+ }
+
+ client = &rpmh_clients[drv_id];
+ client->drv_id = drv_id;
+ client->name = client_name;
+ client->next_req_id = 1U;
+ client->in_use = true;
+
+ return client;
+}
+
+static bool rpmh_tcs_is_idle(uint32_t tcs)
+{
+ uint32_t status = mmio_read_32(RSC_TCS_REG(tcs, RSC_TCS_STATUS_OFF));
+
+ return (status & RSC_TCS_STATUS_CONTROLLER_IDLE) != 0U;
+}
+
+static void rpmh_setup_cmd(uint32_t tcs, uint32_t cmd,
+ const struct rpmh_command *info)
+{
+ uint32_t msgid;
+ uint32_t addr;
+
+ /* Write request: always set the read/write bit for a write. */
+ msgid = RSC_CMD_MSGID_READ_OR_WRITE;
+ if (info->completion) {
+ msgid |= RSC_CMD_MSGID_RES_REQ;
+ }
+ msgid |= (RSC_CMD_DATA_LEN & RSC_CMD_MSGID_MSG_LENGTH_MASK) <<
+ RSC_CMD_MSGID_MSG_LENGTH_SHFT;
+
+ addr = (RSC_SLAVE_ID(info->address) << RSC_CMD_ADDR_SLV_ID_SHFT) |
+ (RSC_OFFSET(info->address) << RSC_CMD_ADDR_OFFSET_SHFT);
+
+ mmio_write_32(RSC_CMD_REG(tcs, cmd, RSC_CMD_MSGID_OFF), msgid);
+ mmio_write_32(RSC_CMD_REG(tcs, cmd, RSC_CMD_ADDR_OFF), addr);
+ mmio_write_32(RSC_CMD_REG(tcs, cmd, RSC_CMD_DATA_OFF), info->data);
+}
+
+/*
+ * Program the AMC TCS with the given command set, trigger it and poll until
+ * the AMC has finished. Returns the request id assigned to the command set.
+ */
+static uint32_t rpmh_send_amc(struct rpmh_client *client,
+ const struct rpmh_command_set *cmd_set)
+{
+ uint32_t tcs = RPMH_TZ_AMC_TCS;
+ uint32_t cmd_en_mask = 0U;
+ uint32_t wait_mask = 0U;
+ uint32_t req_id;
+ uint32_t poll;
+ uint32_t i;
+
+ assert(cmd_set->num_commands > 0U);
+ assert(cmd_set->num_commands <= IMAGE_TCS_SIZE);
+
+ /* TZ DRV only supports active requests. */
+ assert(cmd_set->set == RPMH_SET_ACTIVE);
+
+ spin_lock(&rpmh_lock);
+
+ /* The TCS must be idle before reprogramming it. */
+ for (poll = 0U; poll < RPMH_AMC_POLL_COUNT; poll++) {
+ if (rpmh_tcs_is_idle(tcs)) {
+ break;
+ }
+ }
+ if (poll == RPMH_AMC_POLL_COUNT) {
+ ERROR("RPMh: TCS %u not idle\n", tcs);
+ panic();
+ }
+
+ for (i = 0U; i < cmd_set->num_commands; i++) {
+ rpmh_setup_cmd(tcs, i, &cmd_set->commands[i]);
+ cmd_en_mask |= BIT(i);
+ if (cmd_set->commands[i].completion) {
+ wait_mask |= BIT(i);
+ }
+ }
+
+ /* Program completion dependencies and enabled commands. */
+ mmio_write_32(RSC_TCS_REG(tcs, RSC_TCS_CMD_WAIT_FOR_CMPL_OFF),
+ wait_mask);
+ mmio_write_32(RSC_TCS_REG(tcs, RSC_TCS_CMD_ENABLE_OFF), cmd_en_mask);
+
+ /* Clear and enable the AMC finished interrupt for this TCS. */
+ mmio_write_32(RSC_DRV0_REG(RSC_AMC_IRQ_CLEAR_OFF), BIT(tcs));
+ mmio_setbits_32(RSC_DRV0_REG(RSC_AMC_IRQ_ENABLE_OFF), BIT(tcs));
+
+ /* Trigger the AMC: set AMC mode then pulse the trigger bit. */
+ mmio_clrsetbits_32(RSC_TCS_REG(tcs, RSC_TCS_CONTROL_OFF),
+ RSC_TCS_CONTROL_AMC_MODE_TRIGGER,
+ RSC_TCS_CONTROL_AMC_MODE_EN);
+ mmio_setbits_32(RSC_TCS_REG(tcs, RSC_TCS_CONTROL_OFF),
+ RSC_TCS_CONTROL_AMC_MODE_TRIGGER);
+
+ /* Poll for AMC completion. */
+ for (poll = 0U; poll < RPMH_AMC_POLL_COUNT; poll++) {
+ uint32_t irq = mmio_read_32(RSC_DRV0_REG(RSC_AMC_IRQ_STATUS_OFF));
+
+ if ((irq & BIT(tcs)) != 0U) {
+ break;
+ }
+ }
+ if (poll == RPMH_AMC_POLL_COUNT) {
+ ERROR("RPMh: AMC on TCS %u did not complete\n", tcs);
+ panic();
+ }
+
+ /* Clear the AMC finished interrupt and disable AMC mode. */
+ mmio_write_32(RSC_DRV0_REG(RSC_AMC_IRQ_CLEAR_OFF), BIT(tcs));
+ mmio_clrbits_32(RSC_TCS_REG(tcs, RSC_TCS_CONTROL_OFF),
+ RSC_TCS_CONTROL_AMC_MODE_EN);
+
+ req_id = client->next_req_id++;
+
+ spin_unlock(&rpmh_lock);
+
+ return req_id;
+}
+
+uint32_t rpmh_issue_command_set(struct rpmh_client *handle,
+ struct rpmh_command_set *command_set)
+{
+ assert(handle != NULL);
+ assert(command_set != NULL);
+
+ return rpmh_send_amc(handle, command_set);
+}
+
+uint32_t rpmh_issue_command(struct rpmh_client *handle, enum rpmh_set set,
+ bool completion, uint32_t address, uint32_t data)
+{
+ struct rpmh_command_set cmd_set = {
+ .set = set,
+ .num_commands = 1U,
+ .commands[0] = {
+ .address = address,
+ .data = data,
+ .completion = completion,
+ },
+ };
+
+ assert(handle != NULL);
+
+ return rpmh_send_amc(handle, &cmd_set);
+}
+
+/*
+ * Commands are issued synchronously, so by the time a request id has been
+ * returned the corresponding AMC has already finished. The barrier APIs are
+ * therefore no-ops kept for interface compatibility.
+ */
+void rpmh_barrier_single(struct rpmh_client *handle, uint32_t req_id)
+{
+ assert(handle != NULL);
+ (void)req_id;
+}
+
+void rpmh_barrier_all(struct rpmh_client *handle, uint32_t req_id)
+{
+ assert(handle != NULL);
+ (void)req_id;
+}