aboutsummaryrefslogtreecommitdiff
path: root/module/scmi_sensor
diff options
context:
space:
mode:
authorRonald Cron <ronald.cron@arm.com>2018-06-05 09:31:39 +0200
committerRonald Cron <ronald.cron@arm.com>2018-06-08 11:46:47 +0200
commitb151958dbb2f37383f4d9a1f7802c36008d9fef2 (patch)
treefe20ebfb8c10facbfd028edefe601462ae3ee64c /module/scmi_sensor
parentfd3027b6fd17a4a33a685adb73f2acfcae9a2ced (diff)
Add support for SGM-775
Co-authored-by: Filipe Rinaldi <filipe.rinaldi@arm.com> Co-authored-by: Paul Beesley <paul.beesley@arm.com> Co-authored-by: Chris Kay <chris.kay@arm.com> Co-authored-by: Elieva Pignat <elieva.pignat@arm.com> Co-authored-by: Pedro Custodio <pedro.krewinkelcustodio@arm.com> Change-Id: Ic7524ad58a7c15d5b055e88a9719b2feee437f1d Signed-off-by: Ronald Cron <ronald.cron@arm.com>
Diffstat (limited to 'module/scmi_sensor')
-rw-r--r--module/scmi_sensor/include/internal/scmi_sensor.h164
-rw-r--r--module/scmi_sensor/src/Makefile11
-rw-r--r--module/scmi_sensor/src/mod_scmi_sensor.c462
3 files changed, 637 insertions, 0 deletions
diff --git a/module/scmi_sensor/include/internal/scmi_sensor.h b/module/scmi_sensor/include/internal/scmi_sensor.h
new file mode 100644
index 00000000..d89e3ff0
--- /dev/null
+++ b/module/scmi_sensor/include/internal/scmi_sensor.h
@@ -0,0 +1,164 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Description:
+ * System Control and Management Interface (SCMI) support.
+ */
+
+#ifndef SCMI_SENSOR_H
+#define SCMI_SENSOR_H
+
+/*!
+ * \addtogroup GroupModules Modules
+ * @{
+ */
+
+/*!
+ * \defgroup GroupSCMI_PERF SCMI Sensor Management Protocol
+ * @{
+ */
+
+#define SCMI_PROTOCOL_ID_SENSOR UINT32_C(0x15)
+#define SCMI_PROTOCOL_VERSION_SENSOR UINT32_C(0x10000)
+
+/*
+ * Identifiers of the SCMI Sensor Management Protocol commands
+ */
+enum scmi_sensor_command_id {
+ SCMI_SENSOR_DESCRIPTION_GET = 0x003,
+ SCMI_SENSOR_CONFIG_SET = 0x004,
+ SCMI_SENSOR_TRIP_POINT_SET = 0x005,
+ SCMI_SENSOR_READING_GET = 0x006,
+};
+
+/*
+ * PROTOCOL_ATTRIBUTES
+ */
+
+struct __attribute((packed)) scmi_sensor_protocol_attributes_p2a {
+ int32_t status;
+ uint32_t attributes;
+ uint32_t sensor_reg_address_low;
+ uint32_t sensor_reg_address_high;
+ uint32_t sensor_reg_len;
+};
+
+/*
+ * SENSOR_READING_GET
+ */
+
+#define SCMI_SENSOR_PROTOCOL_READING_GET_ASYNC_FLAG_MASK (1 << 0)
+
+struct __attribute((packed)) scmi_sensor_protocol_reading_get_a2p {
+ uint32_t sensor_id;
+ uint32_t flags;
+};
+
+struct __attribute((packed)) scmi_sensor_protocol_reading_get_p2a {
+ int32_t status;
+ uint32_t sensor_value_low;
+ uint32_t sensor_value_high;
+};
+
+/*
+ * SENSOR_DESCRIPTION_GET
+ */
+
+ #define SCMI_SENSOR_DESCS_MAX(MAILBOX_SIZE) \
+ ((sizeof(struct scmi_sensor_protocol_description_get_p2a) < MAILBOX_SIZE) \
+ ? ((MAILBOX_SIZE - \
+ sizeof(struct scmi_sensor_protocol_description_get_p2a)) \
+ / sizeof(struct scmi_sensor_desc)) \
+ : 0)
+
+#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_TYPE_POS 0
+#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_POS 11
+#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_POS 22
+#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_INTERVAL_POS 27
+
+#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_TYPE_MASK \
+ (UINT32_C(0xFF) << SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_TYPE_POS)
+#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MASK \
+ (UINT32_C(0x1F) << SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_POS)
+#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_MASK \
+ (UINT32_C(0x1F) \
+ << SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_POS)
+#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_INTERVAL_MASK \
+ (UINT32_C(0x1F) << SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_INTERVAL_POS)
+
+#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MAX \
+ (int32_t)(SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MASK >> 1)
+#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MIN \
+ (-(SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MAX + 1))
+
+#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_MAX \
+ (int32_t)(SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_INTERVAL_MASK >> 1)
+#define SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_MIN \
+ (-(SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_MAX + 1))
+
+#define SCMI_SENSOR_DESC_ATTRIBUTES_HIGH(SENSOR_TYPE, UNIT_MULTIPLIER, \
+ UPDATE_MULTIPLIER, UPDATE_INTERVAL) \
+ ( \
+ (((SENSOR_TYPE) << \
+ SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_TYPE_POS) & \
+ SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_TYPE_MASK) | \
+ (((UNIT_MULTIPLIER) << \
+ SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_POS) & \
+ SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MASK) | \
+ (((UPDATE_MULTIPLIER) << \
+ SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_POS) & \
+ SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_MASK) | \
+ (((UPDATE_INTERVAL) << \
+ SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_INTERVAL_POS) & \
+ SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_INTERVAL_MASK) \
+ )
+
+#define SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_DESCS_POS 0
+#define SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_REMAINING_DESCS_POS 16
+
+#define SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_DESCS_MASK \
+ (UINT32_C(0xFFF) << SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_DESCS_POS)
+#define SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_REMAINING_DESCS_MASK \
+ (UINT32_C(0xFFFF) << SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_REMAINING_DESCS_POS)
+
+#define SCMI_SENSOR_NUM_SENSOR_FLAGS(NUM_DESCS, NUM_REMAINING_DESCS) \
+ ( \
+ (((NUM_DESCS) << \
+ SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_DESCS_POS) & \
+ SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_DESCS_MASK) | \
+ (((NUM_REMAINING_DESCS) << \
+ SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_REMAINING_DESCS_POS) & \
+ SCMI_SENSOR_NUM_SENSOR_FLAGS_NUM_REMAINING_DESCS_MASK) \
+ )
+
+#define SCMI_SENSOR_NAME_LEN 16
+
+struct __attribute((packed)) scmi_sensor_desc {
+ uint32_t sensor_id;
+ uint32_t sensor_attributes_low;
+ uint32_t sensor_attributes_high;
+ char sensor_name[SCMI_SENSOR_NAME_LEN];
+};
+
+struct __attribute((packed)) scmi_sensor_protocol_description_get_a2p {
+ uint32_t desc_index;
+};
+
+struct __attribute((packed)) scmi_sensor_protocol_description_get_p2a {
+ int32_t status;
+ uint32_t num_sensor_flags;
+ struct scmi_sensor_desc sensor_desc[];
+};
+
+/*!
+ * @}
+ */
+
+/*!
+ * @}
+ */
+
+#endif /* SCMI_SENSOR_H */
diff --git a/module/scmi_sensor/src/Makefile b/module/scmi_sensor/src/Makefile
new file mode 100644
index 00000000..a177d28e
--- /dev/null
+++ b/module/scmi_sensor/src/Makefile
@@ -0,0 +1,11 @@
+#
+# Arm SCP/MCP Software
+# Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BS_LIB_NAME := SCMI Sensor Protocol
+BS_LIB_SOURCES := mod_scmi_sensor.c
+
+include $(BS_DIR)/lib.mk
diff --git a/module/scmi_sensor/src/mod_scmi_sensor.c b/module/scmi_sensor/src/mod_scmi_sensor.c
new file mode 100644
index 00000000..0822563d
--- /dev/null
+++ b/module/scmi_sensor/src/mod_scmi_sensor.c
@@ -0,0 +1,462 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Description:
+ * SCMI sensor management protocol support.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <fwk_element.h>
+#include <fwk_errno.h>
+#include <fwk_id.h>
+#include <fwk_macros.h>
+#include <fwk_module.h>
+#include <fwk_module_idx.h>
+#include <internal/scmi.h>
+#include <internal/scmi_sensor.h>
+#include <mod_sensor.h>
+#include <mod_scmi.h>
+
+struct scmi_sensor_ctx {
+ unsigned int sensor_count;
+ const struct mod_scmi_from_protocol_api *scmi_api;
+ const struct mod_sensor_api *sensor_api;
+};
+
+static int scmi_sensor_protocol_version_handler(fwk_id_t service_id,
+ const uint32_t *payload);
+static int scmi_sensor_protocol_attributes_handler(fwk_id_t service_id,
+ const uint32_t *payload);
+static int scmi_sensor_protocol_msg_attributes_handler(fwk_id_t service_id,
+ const uint32_t *payload);
+static int scmi_sensor_protocol_desc_get_handler(fwk_id_t service_id,
+ const uint32_t *payload);
+static int scmi_sensor_reading_get_handler(fwk_id_t service_id,
+ const uint32_t *payload);
+
+/*
+ * Internal variables.
+ */
+static struct scmi_sensor_ctx scmi_sensor_ctx;
+
+static int (*handler_table[])(fwk_id_t, const uint32_t *) = {
+ [SCMI_PROTOCOL_VERSION] =
+ scmi_sensor_protocol_version_handler,
+ [SCMI_PROTOCOL_ATTRIBUTES] =
+ scmi_sensor_protocol_attributes_handler,
+ [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] =
+ scmi_sensor_protocol_msg_attributes_handler,
+ [SCMI_SENSOR_DESCRIPTION_GET] =
+ scmi_sensor_protocol_desc_get_handler,
+ [SCMI_SENSOR_READING_GET] = scmi_sensor_reading_get_handler
+};
+
+static unsigned int payload_size_table[] = {
+ [SCMI_PROTOCOL_VERSION] = 0,
+ [SCMI_PROTOCOL_ATTRIBUTES] = 0,
+ [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] =
+ sizeof(struct scmi_protocol_message_attributes_a2p),
+ [SCMI_SENSOR_DESCRIPTION_GET] =
+ sizeof(struct scmi_sensor_protocol_description_get_a2p),
+ [SCMI_SENSOR_READING_GET] =
+ sizeof(struct scmi_sensor_protocol_reading_get_a2p),
+};
+
+/*
+ * Sensor management protocol implementation
+ */
+static int scmi_sensor_protocol_version_handler(fwk_id_t service_id,
+ const uint32_t *payload)
+{
+ struct scmi_protocol_version_p2a return_values = {
+ .status = SCMI_SUCCESS,
+ .version = SCMI_PROTOCOL_VERSION_SENSOR,
+ };
+
+ scmi_sensor_ctx.scmi_api->respond(service_id, &return_values,
+ sizeof(return_values));
+
+ return FWK_SUCCESS;
+}
+
+static int scmi_sensor_protocol_attributes_handler(fwk_id_t service_id,
+ const uint32_t *payload)
+{
+ struct scmi_sensor_protocol_attributes_p2a return_values = {
+ .status = SCMI_SUCCESS,
+ .attributes = scmi_sensor_ctx.sensor_count,
+ .sensor_reg_len = 0, /* Unsupported */
+ };
+
+ scmi_sensor_ctx.scmi_api->respond(service_id, &return_values,
+ sizeof(return_values));
+
+ return FWK_SUCCESS;
+}
+
+static int scmi_sensor_protocol_msg_attributes_handler(fwk_id_t service_id,
+ const uint32_t *payload)
+{
+ const struct scmi_protocol_message_attributes_a2p *parameters;
+ struct scmi_protocol_message_attributes_p2a return_values;
+
+ parameters = (const struct scmi_protocol_message_attributes_a2p *)
+ payload;
+
+ if ((parameters->message_id < FWK_ARRAY_SIZE(handler_table)) &&
+ (handler_table[parameters->message_id] != NULL)) {
+ return_values = (struct scmi_protocol_message_attributes_p2a) {
+ .status = SCMI_SUCCESS,
+ /* All commands have an attributes value of 0 */
+ .attributes = 0,
+ };
+ } else
+ return_values.status = SCMI_NOT_FOUND;
+
+ scmi_sensor_ctx.scmi_api->respond(service_id, &return_values,
+ (return_values.status == SCMI_SUCCESS) ?
+ sizeof(return_values) : sizeof(return_values.status));
+
+ return FWK_SUCCESS;
+}
+
+static int scmi_sensor_protocol_desc_get_handler(fwk_id_t service_id,
+ const uint32_t *payload)
+{
+ int status;
+ size_t payload_size;
+ size_t max_payload_size;
+ const struct scmi_sensor_protocol_description_get_a2p *parameters =
+ (const struct scmi_sensor_protocol_description_get_a2p *)payload;
+ struct scmi_sensor_desc desc = {};
+ unsigned int num_descs, desc_index, desc_index_max;
+ struct mod_sensor_info sensor_info;
+ struct scmi_sensor_protocol_description_get_p2a return_values = {
+ .status = SCMI_GENERIC_ERROR,
+ };
+ fwk_id_t sensor_id;
+
+ payload_size = sizeof(return_values);
+
+ status = scmi_sensor_ctx.scmi_api->get_max_payload_size(service_id,
+ &max_payload_size);
+ if (status != FWK_SUCCESS)
+ goto exit;
+
+ if (SCMI_SENSOR_DESCS_MAX(max_payload_size) == 0) {
+ /* Can't even fit one sensor description in the payload */
+ assert(false);
+ status = FWK_E_SIZE;
+ goto exit;
+ }
+
+ parameters =
+ (const struct scmi_sensor_protocol_description_get_a2p *)payload;
+ desc_index = parameters->desc_index;
+
+ if (desc_index >= scmi_sensor_ctx.sensor_count) {
+ return_values.status = SCMI_INVALID_PARAMETERS;
+ goto exit;
+ }
+
+ num_descs = FWK_MIN(SCMI_SENSOR_DESCS_MAX(max_payload_size),
+ (scmi_sensor_ctx.sensor_count - desc_index));
+ desc_index_max = (desc_index + num_descs - 1);
+
+ for (; desc_index <= desc_index_max; ++desc_index,
+ payload_size += sizeof(desc)) {
+
+ desc = (struct scmi_sensor_desc) {
+ .sensor_id = desc_index,
+ .sensor_attributes_low = 0, /* None supported */
+ };
+
+ sensor_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_SENSOR, desc_index);
+ if (!fwk_module_is_valid_element_id(sensor_id)) {
+ /* domain_idx did not map to a sensor device */
+ assert(false);
+ return_values.status = SCMI_NOT_FOUND;
+ goto exit;
+ }
+
+ status = scmi_sensor_ctx.sensor_api->get_info(sensor_id, &sensor_info);
+ if (status != FWK_SUCCESS) {
+ /* Unable to get sensor info */
+ assert(false);
+ goto exit;
+ }
+
+ if (sensor_info.type >= MOD_SENSOR_TYPE_COUNT) {
+ /* Invalid sensor type */
+ assert(false);
+ goto exit;
+ }
+
+ if ((sensor_info.unit_multiplier <
+ SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MIN) ||
+ (sensor_info.unit_multiplier >
+ SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UNIT_MULTIPLIER_MAX)) {
+
+ /* Sensor unit multiplier out of range */
+ assert(false);
+ goto exit;
+ }
+
+ if ((sensor_info.update_interval_multiplier <
+ SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_MIN) ||
+ (sensor_info.update_interval_multiplier >
+ SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_MULTIPLIER_MAX)) {
+
+ /* Sensor update interval multiplier is out of range */
+ assert(false);
+ goto exit;
+ }
+
+ if (sensor_info.update_interval >=
+ SCMI_SENSOR_DESC_ATTRS_HIGH_SENSOR_UPDATE_INTERVAL_MASK) {
+
+ /* Update interval is too big to fit in it's mask */
+ assert(false);
+ goto exit;
+ }
+
+ desc.sensor_attributes_high =
+ SCMI_SENSOR_DESC_ATTRIBUTES_HIGH(sensor_info.type,
+ sensor_info.unit_multiplier,
+ (uint32_t)sensor_info.update_interval_multiplier,
+ (uint32_t)sensor_info.update_interval);
+
+ /*
+ * Copy sensor name into description struct. Copy n-1 chars to ensure a
+ * NULL terminator at the end. (struct has been zeroed out)
+ */
+ strncpy(desc.sensor_name, sensor_info.name,
+ sizeof(desc.sensor_name) - 1);
+
+ status = scmi_sensor_ctx.scmi_api->write_payload(service_id,
+ payload_size, &desc, sizeof(struct scmi_sensor_desc));
+ if (status != FWK_SUCCESS) {
+ /* Failed to write sensor description into message payload */
+ assert(false);
+ goto exit;
+ }
+ }
+
+ return_values = (struct scmi_sensor_protocol_description_get_p2a) {
+ .status = SCMI_SUCCESS,
+ .num_sensor_flags = SCMI_SENSOR_NUM_SENSOR_FLAGS(num_descs,
+ (scmi_sensor_ctx.sensor_count - desc_index_max - 1))
+ };
+
+ status = scmi_sensor_ctx.scmi_api->write_payload(service_id, 0,
+ &return_values, sizeof(return_values));
+ if (status != FWK_SUCCESS)
+ return_values.status = SCMI_GENERIC_ERROR;
+
+exit:
+ scmi_sensor_ctx.scmi_api->respond(service_id,
+ (return_values.status == SCMI_SUCCESS) ?
+ NULL : &return_values.status,
+ (return_values.status == SCMI_SUCCESS) ?
+ payload_size : sizeof(return_values.status));
+
+ return status;
+}
+
+static int scmi_sensor_reading_get_handler(fwk_id_t service_id,
+ const uint32_t *payload)
+{
+ const struct scmi_sensor_protocol_reading_get_a2p *parameters;
+ struct scmi_sensor_protocol_reading_get_p2a return_values;
+ uint64_t sensor_value;
+ uint32_t flags;
+ fwk_id_t sensor_id;
+ int status;
+
+ parameters = (const struct scmi_sensor_protocol_reading_get_a2p *)payload;
+ return_values.status = SCMI_GENERIC_ERROR;
+
+ if (parameters->sensor_id >= scmi_sensor_ctx.sensor_count) {
+ /* Sensor does not exist */
+ status = FWK_SUCCESS;
+ return_values.status = SCMI_NOT_FOUND;
+ goto exit;
+ }
+
+ /* Reject asynchronous read requests for now */
+ flags = parameters->flags;
+ if (flags & SCMI_SENSOR_PROTOCOL_READING_GET_ASYNC_FLAG_MASK) {
+ return_values.status = SCMI_NOT_SUPPORTED;
+ status = FWK_SUCCESS;
+ goto exit;
+ }
+
+ sensor_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_SENSOR,
+ parameters->sensor_id);
+
+ status = scmi_sensor_ctx.sensor_api->get_value(sensor_id, &sensor_value);
+ if (status == FWK_SUCCESS) {
+ return_values = (struct scmi_sensor_protocol_reading_get_p2a) {
+ .status = SCMI_SUCCESS,
+ .sensor_value_low = (uint32_t)sensor_value,
+ .sensor_value_high = (uint32_t)(sensor_value >> 32),
+ };
+ } else if (status == FWK_E_PWRSTATE) {
+ /* The sensor is currently unpowered */
+ status = FWK_SUCCESS;
+ return_values.status = SCMI_HARDWARE_ERROR;
+ } else {
+ /* Unable to read sensor */
+ assert(false);
+ }
+
+exit:
+ scmi_sensor_ctx.scmi_api->respond(service_id, &return_values,
+ (return_values.status == SCMI_SUCCESS) ?
+ sizeof(return_values) : sizeof(return_values.status));
+
+ return status;
+}
+
+/*
+ * SCMI module -> SCMI sensor module interface
+ */
+static int scmi_sensor_get_scmi_protocol_id(fwk_id_t protocol_id,
+ uint8_t *scmi_protocol_id)
+{
+ int status;
+
+ status = fwk_module_check_call(protocol_id);
+ if (status != FWK_SUCCESS)
+ return status;
+
+ *scmi_protocol_id = SCMI_PROTOCOL_ID_SENSOR;
+
+ return FWK_SUCCESS;
+}
+
+static int scmi_sensor_message_handler(fwk_id_t protocol_id,
+ fwk_id_t service_id,
+ const uint32_t *payload,
+ size_t payload_size,
+ unsigned int message_id)
+{
+ int status;
+ int32_t return_value;
+
+ status = fwk_module_check_call(protocol_id);
+ if (status != FWK_SUCCESS)
+ return status;
+
+ static_assert(FWK_ARRAY_SIZE(handler_table) ==
+ FWK_ARRAY_SIZE(payload_size_table),
+ "[SCMI] Sensor management protocol table sizes not consistent");
+ assert(payload != NULL);
+
+ if (message_id >= FWK_ARRAY_SIZE(handler_table)) {
+ return_value = SCMI_NOT_SUPPORTED;
+ goto error;
+ }
+
+ if (payload_size != payload_size_table[message_id]) {
+ /* Incorrect payload size or message is not supported */
+ return_value = SCMI_PROTOCOL_ERROR;
+ goto error;
+ }
+
+ return handler_table[message_id](service_id, payload);
+
+error:
+ scmi_sensor_ctx.scmi_api->respond(service_id, &return_value,
+ sizeof(return_value));
+ return FWK_SUCCESS;
+}
+
+static struct mod_scmi_to_protocol_api scmi_sensor_mod_scmi_to_protocol_api = {
+ .get_scmi_protocol_id = scmi_sensor_get_scmi_protocol_id,
+ .message_handler = scmi_sensor_message_handler
+};
+
+/*
+ * Framework interface
+ */
+static int scmi_sensor_init(fwk_id_t module_id,
+ unsigned int element_count,
+ const void *unused)
+{
+ if (element_count != 0) {
+ /* This module should not have any elements */
+ assert(false);
+ return FWK_E_SUPPORT;
+ }
+
+ scmi_sensor_ctx.sensor_count = fwk_module_get_element_count(
+ FWK_ID_MODULE(FWK_MODULE_IDX_SENSOR));
+ if (scmi_sensor_ctx.sensor_count == 0)
+ return FWK_E_SUPPORT;
+
+ /* SCMI protocol uses a 16 bit number to store the number of sensors.
+ * So expose no more than 0xFFFF number of sensors. */
+ if (scmi_sensor_ctx.sensor_count > UINT16_MAX)
+ scmi_sensor_ctx.sensor_count = UINT16_MAX;
+
+ return FWK_SUCCESS;
+}
+
+static int scmi_sensor_bind(fwk_id_t id, unsigned int round)
+{
+ int status;
+
+ if (round == 1)
+ return FWK_SUCCESS;
+
+ status = fwk_module_bind(FWK_ID_MODULE(FWK_MODULE_IDX_SCMI),
+ FWK_ID_API(FWK_MODULE_IDX_SCMI,
+ MOD_SCMI_API_IDX_PROTOCOL),
+ &scmi_sensor_ctx.scmi_api);
+ if (status != FWK_SUCCESS) {
+ /* Failed to bind to SCMI module */
+ assert(false);
+ return status;
+ }
+
+ status = fwk_module_bind(FWK_ID_MODULE(FWK_MODULE_IDX_SENSOR),
+ FWK_ID_API(FWK_MODULE_IDX_SENSOR, 0),
+ &scmi_sensor_ctx.sensor_api);
+ if (status != FWK_SUCCESS) {
+ /* Failed to bind to sensor module */
+ assert(false);
+ return status;
+ }
+
+ return FWK_SUCCESS;
+}
+
+static int scmi_sensor_process_bind_request(fwk_id_t source_id,
+ fwk_id_t target_id,
+ fwk_id_t api_id,
+ const void **api)
+{
+ if (!fwk_id_is_equal(source_id, FWK_ID_MODULE(FWK_MODULE_IDX_SCMI)))
+ return FWK_E_ACCESS;
+
+ *api = &scmi_sensor_mod_scmi_to_protocol_api;
+
+ return FWK_SUCCESS;
+}
+
+const struct fwk_module module_scmi_sensor = {
+ .name = "SCMI sensor management",
+ .api_count = 1,
+ .type = FWK_MODULE_TYPE_PROTOCOL,
+ .init = scmi_sensor_init,
+ .bind = scmi_sensor_bind,
+ .process_bind_request = scmi_sensor_process_bind_request,
+};
+
+/* No elements, no module configuration data */
+struct fwk_module_config config_scmi_sensor = {};