diff options
author | Ronald Cron <ronald.cron@arm.com> | 2018-06-05 09:31:39 +0200 |
---|---|---|
committer | Ronald Cron <ronald.cron@arm.com> | 2018-06-08 11:46:47 +0200 |
commit | b151958dbb2f37383f4d9a1f7802c36008d9fef2 (patch) | |
tree | fe20ebfb8c10facbfd028edefe601462ae3ee64c /module/scmi_sensor | |
parent | fd3027b6fd17a4a33a685adb73f2acfcae9a2ced (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.h | 164 | ||||
-rw-r--r-- | module/scmi_sensor/src/Makefile | 11 | ||||
-rw-r--r-- | module/scmi_sensor/src/mod_scmi_sensor.c | 462 |
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 = {}; |