diff --git a/doc/config.dxy b/doc/config.dxy index 136b1f271d915bac28bd6848f3b0f42fe628f5a5..2365e3183810d3bfd1bff0be17510088357aed83 100644 --- a/doc/config.dxy +++ b/doc/config.dxy @@ -121,6 +121,7 @@ INPUT = $(TOP_DIR)/readme.md \ $(DOC_DIR)/framework.md \ $(DOC_DIR)/cmsis.md \ $(DOC_DIR)/glossary.md \ + $(DOC_DIR)/deferred_response_architecture.md \ $(FWK_DIR)/include \ $(FWK_DIR)/test/fwk_test.h \ $(MODULE_INCLUDES) \ diff --git a/doc/deferred_response_architecture.md b/doc/deferred_response_architecture.md new file mode 100644 index 0000000000000000000000000000000000000000..7f7991bdc0daccdb62887b5d4b58365359cd86d1 --- /dev/null +++ b/doc/deferred_response_architecture.md @@ -0,0 +1,135 @@ +Deferred Response Architecture +============================== + +# Overview {#deferred_response_architecture_overview} + +This document describes at high level the typical interactions between the +following actors: +- A client requesting some data/operations from a module. +- A HAL module defining an interface to request operations. +- A driver interacting with the hardware and bound to the HAL. +This document particularly focuses on the interactions when the requests are +deferred and thus acknowledged as pending. + +# Architecture {#deferred_response_architecture_architecture} + +## Client-HAL Interaction {#deferred_response_architecture_client_hal} + +A call to an HAL API can be handled asynchronously by the HAL module. The call +to the HAL API returns with one of the following status code: +- FWK_SUCCESS: the requested operation has completed. The data requested, if +any, is available. +- FWK_PENDING: the call has been acknowledged and the response to the request +will be sent subsequently via a *HAL_module_event_id_request* response event. +In this case, the client must handle the response event. +- FWK_E_X: the request failed. + +## Driver-HAL Interaction {#deferred_response_architecture_driver_hal} + +When the HAL calls the driver, it acts in different manners depending on the +status returned by the driver: +- FWK_SUCCESS: the driver has successfully completed the request and the +value/operation has completed immediately. The HAL returns the data, if any, to +the client. +- FWK_PENDING: the driver has deferred the requested operation and will provide +the response later through the *driver_response_api*. In this case, the HAL +sends an *HAL_module_event_id_request* event to itself, the response of which +will be sent to the client when the operation will be completed. +- FWK_E_X: the request failed. + +## Note {#deferred_response_architecture_note} + +A call to an HAL API is done as part of the processing of an event by a given +entity and, when processing pending requests, this entity is the target of the +response event. In order for the client to receive the response event, the +client is required to call the HAL API within the context of processing an event +targeting itself. In other words, the caller may be required to send an event +targeting itself first and then call the HAL module when processing such event. + +# Flow {#deferred_response_architecture_flow} + +Below is a typical execution flow for a call to the HAL when the driver defers +the requested operation. + + Client HAL Module Driver Driver ISR + + | | | | + | | | | + +++ get/set | | | + | +--------------->+++ | | + | | | | get/set | | + | | | +--------------->+++ | + | | | | | | | + | | | +<---------------+++ | + | | | | PENDING | | + | | | +-----+ | | + | | | | | | | + | | | +<----+ PE1 | | + | | | | | | + | +<---------------+++ | | + +++ PENDING | | | + | | | | + | E1>>>>>>+++ | | + | | | | | + | +++ | | + | | | DRV_RESP +++ + | +++<----------------------------------+ | + | | | | | | + | | +-----+ | | | + | | | | | | | + | | +<----+ PE2 | | | + | | | | | | + | +++---------------------------------->+ | + | | | +++ + | | | | + | E2>>>>>>+++ | | + | | +-----+ | | + | | | | | | + | | +<----+ PE3 | | + | +++ | | + | | | | + +++<<<<< : Direct call/return API + >>>>>> : Asynchronous call via the event interface + + EVENTS CORRESPONDENCE + PE1 > > > E1 + PE2 > > > E2 + PE3 > > > RE + +A client calls *get/set* HAL module API which calls directly the driver. + +The driver cannot do the operation immediately, it returns FWK_PENDING. + +The HAL module sends a *REQUEST* event (PE1) to itself and returns FWK_PENDING +to the client. The request event contains all the information needed for the +deferred response. + +The HAL receives and processes the *REQUEST* event E1, and it stores the event's +cookie and delays its response. + +When the requested *get/set* operation is completed, the driver calls the +*driver_response_api* providing the result of operation. +In this call, the driver sends a *REQUEST_COMPLETE* event (PE2) for the HAL +to defer post-processing and to provide the result of the operation. + +Then, the HAL module receives and processes the *REQUEST_COMPLETE* event E2, +retrieving the result of the operation from the event E2's parameters. At the +same time the HAL get back the response event that was delayed, and sends the +event (PE3) containing the result of the operation. + +Finally, the client receives and processes the *HAL_module_event_id_request* +response event RE sent by the HAL module. diff --git a/framework/src/fwk_module.c b/framework/src/fwk_module.c index c01b1de89eb04fb5aa464d6ceb8061beaff2008e..f42b1a29ec3fc402805ed4200cb7f3cfe1c49a91 100644 --- a/framework/src/fwk_module.c +++ b/framework/src/fwk_module.c @@ -607,7 +607,8 @@ const char *fwk_module_get_name(fwk_id_t id) const void *fwk_module_get_data(fwk_id_t id) { - if (fwk_module_is_valid_element_id(id)) + if (fwk_module_is_valid_element_id(id) || + fwk_module_is_valid_sub_element_id(id)) return __fwk_module_get_element_ctx(id)->desc->data; else if (fwk_module_is_valid_module_id(id)) return __fwk_module_get_ctx(id)->config->data; diff --git a/framework/test/test_fwk_module.c b/framework/test/test_fwk_module.c index f31ed664e02a7c791a34da5d6cad594bed8b65bf..a3f00c4d8843ec1987a111f5e0731d5b4fe3292c 100644 --- a/framework/test/test_fwk_module.c +++ b/framework/test/test_fwk_module.c @@ -969,8 +969,19 @@ static void test_fwk_module_get_data(void) assert(result != NULL); assert(result == (void *)(&config_elem0)); - /* Invalid ID */ - id = FWK_ID_ELEMENT(0xEF, 0xDBE); + /* Valid sub-element ID */ + id = SUB_ELEM0_ID; + result = fwk_module_get_data(id); + assert(result != NULL); + assert(result == (void *)(&config_elem0)); + + /* Invalid element ID */ + id = FWK_ID_ELEMENT(0xEF, 0xDBE); + result = fwk_module_get_data(id); + assert(result == NULL); + + /* Invalid sub-element ID */ + id = FWK_ID_SUB_ELEMENT(0xDE, 0xAA7, 9); result = fwk_module_get_data(id); assert(result == NULL); } diff --git a/module/scmi_sensor/include/internal/scmi_sensor.h b/module/scmi_sensor/include/internal/scmi_sensor.h index 5bf1c20e863faf1bd464ff9e6becca898802e16a..f6bac17d7b62175414a45f1a7cdafc5fe40b67d6 100644 --- a/module/scmi_sensor/include/internal/scmi_sensor.h +++ b/module/scmi_sensor/include/internal/scmi_sensor.h @@ -153,6 +153,12 @@ struct __attribute((packed)) scmi_sensor_protocol_description_get_p2a { struct scmi_sensor_desc sensor_desc[]; }; +/* Event indices */ +enum scmi_sensor_api_idx { + SCMI_SENSOR_EVENT_IDX_REQUEST, + SCMI_SENSOR_EVENT_IDX_COUNT, +}; + /*! * @} */ diff --git a/module/scmi_sensor/src/mod_scmi_sensor.c b/module/scmi_sensor/src/mod_scmi_sensor.c index afe9211ea8760c6581ea1d8405324b53f77e861d..14f7d156b4cb6af6fb604bf17868d7ce015e613b 100644 --- a/module/scmi_sensor/src/mod_scmi_sensor.c +++ b/module/scmi_sensor/src/mod_scmi_sensor.c @@ -13,18 +13,36 @@ #include #include #include +#include #include #include #include +#include #include #include -#include #include +#include + +struct sensor_operations { + /* + * Service identifier currently requesting operation from this sensor. + * A 'none' value means that there is no pending request. + */ + fwk_id_t service_id; +}; struct scmi_sensor_ctx { + /* Number of sensors */ unsigned int sensor_count; + + /* SCMI protocol module to SCMI module API */ const struct mod_scmi_from_protocol_api *scmi_api; + + /* Sensor module API */ const struct mod_sensor_api *sensor_api; + + /* Pointer to a table of sensor operations */ + struct sensor_operations *sensor_ops_table; }; static int scmi_sensor_protocol_version_handler(fwk_id_t service_id, @@ -38,6 +56,14 @@ static int scmi_sensor_protocol_desc_get_handler(fwk_id_t service_id, static int scmi_sensor_reading_get_handler(fwk_id_t service_id, const uint32_t *payload); +struct scmi_sensor_event_parameters { + fwk_id_t sensor_id; +}; + +static const fwk_id_t mod_scmi_sensor_event_id_get_request = + FWK_ID_EVENT_INIT(FWK_MODULE_IDX_SCMI_SENSOR, + SCMI_SENSOR_EVENT_IDX_REQUEST); + /* * Internal variables. */ @@ -66,6 +92,35 @@ static unsigned int payload_size_table[] = { sizeof(struct scmi_sensor_protocol_reading_get_a2p), }; +/* + * Static helper for responding to SCMI. + */ +static void scmi_sensor_respond( + struct scmi_sensor_protocol_reading_get_p2a *return_values, + fwk_id_t sensor_id) +{ + unsigned int sensor_idx; + fwk_id_t service_id; + + /* + * The service identifier used for the response is retrieved from the + * sensor operations table. + */ + sensor_idx = fwk_id_get_element_idx(sensor_id); + service_id = scmi_sensor_ctx.sensor_ops_table[sensor_idx].service_id; + + scmi_sensor_ctx.scmi_api->respond(service_id, + return_values, + (return_values->status == SCMI_SUCCESS) ? + sizeof(*return_values) : sizeof(return_values->status)); + + /* + * Set the service identifier to 'none' to indicate the sensor is + * available again. + */ + scmi_sensor_ctx.sensor_ops_table[sensor_idx].service_id = FWK_ID_NONE; +} + /* * Sensor management protocol implementation */ @@ -273,9 +328,9 @@ static int scmi_sensor_reading_get_handler(fwk_id_t service_id, { const struct scmi_sensor_protocol_reading_get_a2p *parameters; struct scmi_sensor_protocol_reading_get_p2a return_values; - uint64_t sensor_value; + struct scmi_sensor_event_parameters *params; + unsigned int sensor_idx; uint32_t flags; - fwk_id_t sensor_id; int status; parameters = (const struct scmi_sensor_protocol_reading_get_a2p *)payload; @@ -296,25 +351,40 @@ static int scmi_sensor_reading_get_handler(fwk_id_t service_id, goto exit; } - sensor_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_SENSOR, - parameters->sensor_id); + sensor_idx = 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 */ + /* Check if there is already a request pending for this sensor */ + if (!fwk_id_is_equal( + scmi_sensor_ctx.sensor_ops_table[sensor_idx].service_id, + FWK_ID_NONE)){ + return_values.status = SCMI_BUSY; status = FWK_SUCCESS; - return_values.status = SCMI_HARDWARE_ERROR; - } else { - /* Unable to read sensor */ - assert(false); + + goto exit; } + /* The get_value request is processed within the event being generated */ + struct fwk_event event = { + .target_id = fwk_module_id_scmi_sensor, + .id = mod_scmi_sensor_event_id_get_request, + }; + + params = (struct scmi_sensor_event_parameters *)event.params; + params->sensor_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_SENSOR, + sensor_idx); + + status = fwk_thread_put_event(&event); + if (status != FWK_SUCCESS) { + return_values.status = SCMI_GENERIC_ERROR; + + goto exit; + } + + /* Store service identifier to indicate there is a pending request */ + scmi_sensor_ctx.sensor_ops_table[sensor_idx].service_id = service_id; + + return FWK_SUCCESS; + exit: scmi_sensor_ctx.scmi_api->respond(service_id, &return_values, (return_values.status == SCMI_SUCCESS) ? @@ -405,6 +475,17 @@ static int scmi_sensor_init(fwk_id_t module_id, if (scmi_sensor_ctx.sensor_count > UINT16_MAX) scmi_sensor_ctx.sensor_count = UINT16_MAX; + /* Allocate a table for the sensors state */ + scmi_sensor_ctx.sensor_ops_table = + fwk_mm_calloc(scmi_sensor_ctx.sensor_count, + sizeof(struct sensor_operations)); + if (scmi_sensor_ctx.sensor_ops_table == NULL) + return FWK_E_NOMEM; + + /* Initialize the service identifier for each sensor to 'available' */ + for (unsigned int i = 0; i < scmi_sensor_ctx.sensor_count; i++) + scmi_sensor_ctx.sensor_ops_table[i].service_id = FWK_ID_NONE; + return FWK_SUCCESS; } @@ -426,7 +507,7 @@ static int scmi_sensor_bind(fwk_id_t id, unsigned int round) } status = fwk_module_bind(FWK_ID_MODULE(FWK_MODULE_IDX_SENSOR), - FWK_ID_API(FWK_MODULE_IDX_SENSOR, 0), + mod_sensor_api_id_sensor, &scmi_sensor_ctx.sensor_api); if (status != FWK_SUCCESS) { /* Failed to bind to sensor module */ @@ -450,13 +531,71 @@ static int scmi_sensor_process_bind_request(fwk_id_t source_id, return FWK_SUCCESS; } +static int scmi_sensor_process_event(const struct fwk_event *event, + struct fwk_event *resp_event) +{ + int status; + uint64_t sensor_value; + struct scmi_sensor_event_parameters *params; + struct scmi_sensor_protocol_reading_get_p2a return_values; + + /* Request event to sensor HAL */ + if (fwk_id_is_equal(event->id, mod_scmi_sensor_event_id_get_request)) { + params = (struct scmi_sensor_event_parameters *)event->params; + + status = scmi_sensor_ctx.sensor_api->get_value(params->sensor_id, + &sensor_value); + if (status == FWK_SUCCESS) { + /* Sensor value is ready */ + 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), + }; + + scmi_sensor_respond(&return_values, params->sensor_id); + + return status; + } else if (status == FWK_PENDING) { + /* Sensor value will be provided through a response event */ + return FWK_SUCCESS; + } else { + return_values = (struct scmi_sensor_protocol_reading_get_p2a) { + .status = SCMI_HARDWARE_ERROR, + }; + + scmi_sensor_respond(&return_values, params->sensor_id); + + return FWK_E_PANIC; + } + } + + /* Response event from sensor HAL */ + if (fwk_id_is_equal(event->id, mod_sensor_event_id_read_request)) { + struct mod_sensor_event_params *params = + (struct mod_sensor_event_params *)event->params; + + return_values = (struct scmi_sensor_protocol_reading_get_p2a) { + .status = SCMI_SUCCESS, + .sensor_value_low = (uint32_t)params->value, + .sensor_value_high = (uint32_t)(params->value >> 32), + }; + + scmi_sensor_respond(&return_values, event->source_id); + } + + return FWK_SUCCESS; +} + const struct fwk_module module_scmi_sensor = { .name = "SCMI sensor management", .api_count = 1, + .event_count = SCMI_SENSOR_EVENT_IDX_COUNT, .type = FWK_MODULE_TYPE_PROTOCOL, .init = scmi_sensor_init, .bind = scmi_sensor_bind, .process_bind_request = scmi_sensor_process_bind_request, + .process_event = scmi_sensor_process_event, }; /* No elements, no module configuration data */ diff --git a/module/sensor/include/mod_sensor.h b/module/sensor/include/mod_sensor.h index 92d79f0a82cc04e2ff7e067e002f1f133a74ded4..ca85c978d59d27571eaf4a8df720245ea4b25d0f 100644 --- a/module/sensor/include/mod_sensor.h +++ b/module/sensor/include/mod_sensor.h @@ -8,9 +8,10 @@ #ifndef MOD_SENSOR_H #define MOD_SENSOR_H -#include -#include #include +#include +#include +#include /*! * \addtogroup GroupModules Modules @@ -159,9 +160,11 @@ struct mod_sensor_info { * \details Configuration structure for individual sensors. */ struct mod_sensor_dev_config { - /*! Module or element id of the driver */ + /*! Module or element identifier of the driver */ fwk_id_t driver_id; + /*! API identifier of the driver */ + fwk_id_t driver_api_id; }; /*! @@ -171,20 +174,20 @@ struct mod_sensor_dev_config { */ struct mod_sensor_driver_api { /*! - * \brief Read sensor value. - * - * \details Synchronously read current sensor value. + * \brief Get sensor value. * * \param id Specific sensor device id. - * \param[out] value The sensor value. + * \param[out] value Sensor value. * + * \retval FWK_PENDING The request is pending. The driver will provide the + * requested value later through the driver response API. * \retval FWK_SUCCESS Value was read successfully. * \return One of the standard framework error codes. */ int (*get_value)(fwk_id_t id, uint64_t *value); /*! - * \brief Read sensor information. + * \brief Get sensor information. * * \param id Specific sensor device id. * \param[out] info The sensor information. @@ -202,13 +205,17 @@ struct mod_sensor_api { /*! * \brief Read sensor value. * - * \details Synchronously read current sensor value. + * \details Read current sensor value. * * \param id Specific sensor device id. * \param[out] value The sensor value. * * \retval FWK_SUCCESS Operation succeeded. * \retval FWK_E_DEVICE Driver error. + * \retval FWK_E_BUSY At least one reading of the sensor value is already + * on-going. + * \retval FWK_PENDING The request is pending. The requested value will be + * provided via a response event. * \return One of the standard framework error codes. */ int (*get_value)(fwk_id_t id, uint64_t *value); @@ -228,6 +235,93 @@ struct mod_sensor_api { int (*get_info)(fwk_id_t id, struct mod_sensor_info *info); }; +/*! + * \brief Driver response parameters. + */ +struct mod_sensor_driver_resp_params { + /*! Status of the requested operation */ + int status; + + /*! Value requested */ + uint64_t value; +}; + +/*! + * \brief Driver response API. + * + * \details API used by the driver to notify the HAL when a pending request + * has completed. + */ +struct mod_sensor_driver_response_api { + /*! + * \brief Inform the completion of a sensor reading. + * + * \param id Specific sensor device identifier. + * \param[out] response The response data structure. + */ + void (*reading_complete)(fwk_id_t id, + struct mod_sensor_driver_resp_params *response); +}; + +/*! + * \brief API indices. + */ +enum mod_sensor_api_idx { + /*! + * \brief Driver API index. + * + * \note This API implements the ::mod_sensor_api interface. + */ + MOD_SENSOR_API_IDX_SENSOR, + + /*! + * \brief Driver response API. + */ + MOD_SENSOR_API_IDX_DRIVER_RESPONSE, + + /*! + * \brief Number of defined APIs. + */ + MOD_SENSOR_API_IDX_COUNT, +}; + +/*! + * \brief Module API identifier. + */ +static const fwk_id_t mod_sensor_api_id_sensor = + FWK_ID_API_INIT(FWK_MODULE_IDX_SENSOR, MOD_SENSOR_API_IDX_SENSOR); + +/*! + * \brief Driver input API identifier. + */ +static const fwk_id_t mod_sensor_api_id_driver_response = + FWK_ID_API_INIT(FWK_MODULE_IDX_SENSOR, MOD_SENSOR_API_IDX_DRIVER_RESPONSE); + +/*! + * \brief Shared event parameters. + */ +struct mod_sensor_event_params { + /*! Sensor value */ + uint64_t value; + + /*! Status of the response event */ + int status; +}; + +/*! + * Sensor module read request event index + */ +#define MOD_SENSOR_EVENT_IDX_READ_REQUEST 0 + + /*! + * \brief Read request event identifier. + * + * \details Clients which expect to receive a response event from this module + * should use this identifier to properly identify the response. + */ +static const fwk_id_t mod_sensor_event_id_read_request = + FWK_ID_EVENT_INIT(FWK_MODULE_IDX_SENSOR, MOD_SENSOR_EVENT_IDX_READ_REQUEST); + /*! * @} */ diff --git a/module/sensor/src/mod_sensor.c b/module/sensor/src/mod_sensor.c index dd11683f8a0424981d51ca6abebba37a038ea34a..1206ce79d08d308cdf9b31df9ce49b4468d043e4 100644 --- a/module/sensor/src/mod_sensor.c +++ b/module/sensor/src/mod_sensor.c @@ -12,12 +12,8 @@ #include #include #include -#include - -struct sensor_dev_ctx { - struct mod_sensor_dev_config *config; - struct mod_sensor_driver_api *driver_api; -}; +#include +#include static struct sensor_dev_ctx *ctx_table; @@ -49,16 +45,40 @@ static int get_value(fwk_id_t id, uint64_t *value) { int status; struct sensor_dev_ctx *ctx; + struct fwk_event req; status = get_ctx_if_valid_call(id, value, &ctx); if (status != FWK_SUCCESS) return status; + /* Concurrent readings are not supported */ + if (ctx->read_busy) + return FWK_E_BUSY; + status = ctx->driver_api->get_value(ctx->config->driver_id, value); - if (!fwk_expect(status == FWK_SUCCESS)) + if (status == FWK_PENDING) { + req = (struct fwk_event) { + .target_id = id, + .id = mod_sensor_event_id_read_request, + .response_requested = true, + }; + + status = fwk_thread_put_event(&req); + if (status == FWK_SUCCESS) { + ctx->read_busy = true; + + /* + * We return FWK_PENDING here to indicate to the caller that the + * result of the request is pending and will arrive later through + * an event. + */ + return FWK_PENDING; + } else + return status; + } else if (status == FWK_SUCCESS) + return FWK_SUCCESS; + else return FWK_E_DEVICE; - - return FWK_SUCCESS; } static int get_info(fwk_id_t id, struct mod_sensor_info *info) @@ -82,6 +102,40 @@ static struct mod_sensor_api sensor_api = { .get_info = get_info, }; +/* + * Driver response API. + */ +static void reading_complete(fwk_id_t dev_id, + struct mod_sensor_driver_resp_params *response) +{ + int status; + struct fwk_event event; + struct sensor_dev_ctx *ctx; + struct mod_sensor_event_params *event_params = + (struct mod_sensor_event_params *)event.params; + + status = get_ctx_if_valid_call(dev_id, response, &ctx); + + event = (struct fwk_event) { + .id = mod_sensor_event_id_read_complete, + .source_id = ctx->config->driver_id, + .target_id = dev_id, + }; + + if (status == FWK_SUCCESS) { + event_params->status = response->status; + event_params->value = response->value; + } else + event_params->status = FWK_E_DEVICE; + + status = fwk_thread_put_event(&event); + fwk_assert(status == FWK_SUCCESS); +} + +static struct mod_sensor_driver_response_api sensor_driver_response_api = { + .reading_complete = reading_complete, +}; + /* * Framework handlers */ @@ -89,7 +143,7 @@ static int sensor_init(fwk_id_t module_id, unsigned int element_count, const void *unused) { - ctx_table = fwk_mm_alloc(element_count, sizeof(ctx_table[0])); + ctx_table = fwk_mm_calloc(element_count, sizeof(ctx_table[0])); if (ctx_table == NULL) return FWK_E_NOMEM; @@ -130,7 +184,7 @@ static int sensor_bind(fwk_id_t id, unsigned int round) /* Bind to driver */ status = fwk_module_bind(ctx->config->driver_id, - FWK_ID_API(fwk_id_get_module_idx(ctx->config->driver_id), 0), + ctx->config->driver_api_id, &driver); if (status != FWK_SUCCESS) return status; @@ -146,20 +200,90 @@ static int sensor_bind(fwk_id_t id, unsigned int round) static int sensor_process_bind_request(fwk_id_t source_id, fwk_id_t target_id, - fwk_id_t api_type, + fwk_id_t api_id, const void **api) { - *api = &sensor_api; - return FWK_SUCCESS; + struct sensor_dev_ctx *ctx; + fwk_id_t driver_id; + + if (fwk_id_is_equal(api_id, mod_sensor_api_id_sensor)) { + *api = &sensor_api; + + return FWK_SUCCESS; + } + + if (fwk_id_is_equal(api_id, mod_sensor_api_id_driver_response)) { + if (!fwk_id_is_type(target_id, FWK_ID_TYPE_ELEMENT)) + return FWK_E_PARAM; + + ctx = ctx_table + fwk_id_get_element_idx(target_id); + driver_id = ctx->config->driver_id; + + /* Allow element to sub-element binding */ + if ((fwk_id_get_module_idx(driver_id) == + fwk_id_get_module_idx(source_id)) && + (fwk_id_get_element_idx(driver_id) == + fwk_id_get_element_idx(source_id))) { + + *api = &sensor_driver_response_api; + + return FWK_SUCCESS; + } else + return FWK_E_ACCESS; + } + + return FWK_E_PARAM; +} + +static int sensor_process_event(const struct fwk_event *event, + struct fwk_event *resp_event) +{ + int status; + struct sensor_dev_ctx *ctx; + struct fwk_event read_req_event; + struct mod_sensor_event_params *event_params = + (struct mod_sensor_event_params *)(event->params); + struct mod_sensor_event_params *resp_params = + (struct mod_sensor_event_params *)(read_req_event.params); + + if (!fwk_module_is_valid_element_id(event->target_id)) + return FWK_E_PARAM; + + ctx = ctx_table + fwk_id_get_element_idx(event->target_id); + + switch (fwk_id_get_event_idx(event->id)) { + + case SENSOR_EVENT_IDX_READ_REQUEST: + ctx->cookie = event->cookie; + resp_event->is_delayed_response = true; + + return FWK_SUCCESS; + + case SENSOR_EVENT_IDX_READ_COMPLETE: + ctx->read_busy = false; + + status = fwk_thread_get_delayed_response(event->target_id, + ctx->cookie, + &read_req_event); + if (status != FWK_SUCCESS) + return status; + + *resp_params = *event_params; + return fwk_thread_put_event(&read_req_event); + + default: + return FWK_E_PARAM; + } } const struct fwk_module module_sensor = { .name = "SENSOR", - .api_count = 1, - .event_count = 0, + .api_count = MOD_SENSOR_API_IDX_COUNT, + .event_count = SENSOR_EVENT_IDX_COUNT, .type = FWK_MODULE_TYPE_HAL, .init = sensor_init, .element_init = sensor_dev_init, .bind = sensor_bind, .process_bind_request = sensor_process_bind_request, + .process_event = sensor_process_event, }; diff --git a/module/sensor/src/sensor.h b/module/sensor/src/sensor.h new file mode 100644 index 0000000000000000000000000000000000000000..bd5df49d945892d2ba2e2d032e8e3fcb2ed80907 --- /dev/null +++ b/module/sensor/src/sensor.h @@ -0,0 +1,51 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SENSOR_H +#define SENSOR_H + +#include +#include +#include + +/*! + * \cond + * @{ + */ + +/* + * Sensor element context + */ +struct sensor_dev_ctx { + struct mod_sensor_dev_config *config; + struct mod_sensor_driver_api *driver_api; + uint32_t cookie; + bool read_busy; +}; + +/* + * Sensor event indexes + */ +enum mod_sensor_event_idx { + SENSOR_EVENT_IDX_READ_REQUEST = MOD_SENSOR_EVENT_IDX_READ_REQUEST, + SENSOR_EVENT_IDX_READ_COMPLETE, + SENSOR_EVENT_IDX_COUNT +}; + +/* + * Event identifiers + */ +static const fwk_id_t mod_sensor_event_id_read_complete = + FWK_ID_EVENT_INIT(FWK_MODULE_IDX_SENSOR, + SENSOR_EVENT_IDX_READ_COMPLETE); + +/*! + * \endcond + * @} + */ + +#endif /* SENSOR_H */ diff --git a/product/juno/module/juno_adc/include/mod_juno_adc.h b/product/juno/module/juno_adc/include/mod_juno_adc.h new file mode 100644 index 0000000000000000000000000000000000000000..dc7322d18bff9223381cfad78a31bceb98c7ee15 --- /dev/null +++ b/product/juno/module/juno_adc/include/mod_juno_adc.h @@ -0,0 +1,88 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Juno ADC Driver + */ + +#ifndef MOD_JUNO_ADC_H +#define MOD_JUNO_ADC_H + +#include +#include + +/*! + * \ingroup GroupJunoModule + * \defgroup GroupADC ADC Sensor Driver + * \{ + */ + +/*! + * \brief ADC Type indices. + */ +enum juno_adc_sensor_type { + /*! Current type ADC */ + ADC_TYPE_CURRENT = 0, + /*! Voltage type ADC */ + ADC_TYPE_VOLT, + /*! Power type ADC */ + ADC_TYPE_POWER, + /*! Energy type ADC */ + ADC_TYPE_ENERGY, + /*! Max number of ADC type */ + ADC_TYPE_COUNT +}; + +/*! + * \brief ADC Device Type indices. + */ +enum juno_adc_dev_type { + /*! ADC for the SYS device */ + ADC_DEV_SYS = 0, + /*! ADC for the big cpu */ + ADC_DEV_BIG, + /* ADC for the LITTLE cpu */ + ADC_DEV_LITTLE, + /*! ADC for the GPU */ + ADC_DEV_GPU, + /*! Number of ADC devices */ + ADC_DEV_TYPE_COUNT +}; + +/*! + * \brief Element configuration. + */ +struct mod_juno_adc_dev_config { + /*! Type of ADC */ + enum juno_adc_sensor_type type; + + /*! Type of device */ + enum juno_adc_dev_type dev_type; + + /*! Auxiliary sensor information */ + struct mod_sensor_info *info; +}; + +/*! + * \brief Juno ADC API indices. + */ +enum mod_juno_adc_api_idx { + MOD_JUNO_ADC_API_IDX_DRIVER, + MOD_JUNO_ADC_API_IDX_COUNT, +}; + +/*! + * \brief Juno ADC API identifier. + */ +static const fwk_id_t mod_juno_adc_api_id_driver = + FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC, + MOD_JUNO_ADC_API_IDX_DRIVER); + +/*! + * \} + */ + +#endif /* MOD_JUNO_ADC_H */ diff --git a/product/juno/module/juno_adc/src/Makefile b/product/juno/module/juno_adc/src/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b8de15b15c3180ae944c600eeb3b1c701f973dee --- /dev/null +++ b/product/juno/module/juno_adc/src/Makefile @@ -0,0 +1,11 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := Juno ADC +BS_LIB_SOURCES += mod_juno_adc.c + +include $(BS_DIR)/lib.mk diff --git a/product/juno/module/juno_adc/src/juno_adc.h b/product/juno/module/juno_adc/src/juno_adc.h new file mode 100644 index 0000000000000000000000000000000000000000..6cab41ad283ef66a4a8ce13ea73d5ffa86e60dd2 --- /dev/null +++ b/product/juno/module/juno_adc/src/juno_adc.h @@ -0,0 +1,31 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef JUNO_ADC_H +#define JUNO_ADC_H + +/* Coefficients for ADC values */ +#define ADC_VOLT_CONST 1622 +#define ADC_CURRENT_CONST1 381 +#define ADC_CURRENT_CONST2 761 +#define ADC_POWER_CONST1 617402 +#define ADC_POWER_CONST2 1234803 +#define ADC_ENERGY_CONST1 617402 +#define ADC_ENERGY_CONST2 1234803 + +/* Field masks for the ADC values */ +#define JUNO_ADC_SYS_REG_AMPS_MASK UINT32_C(0x00000FFF) +#define JUNO_ADC_SYS_REG_VOLT_MASK UINT32_C(0x00000FFF) +#define JUNO_ADC_SYS_REG_POWER_MASK UINT32_C(0x00FFFFFF) + +/* Multiplying factors */ +#define JUNO_ADC_AMPS_MULTIPLIER 1000 +#define JUNO_ADC_VOLT_MULTIPLIER 1000 +#define JUNO_ADC_WATTS_MULTIPLIER (1000 * 1000) +#define JUNO_ADC_JOULE_MULTIPLIER 100 + +#endif /* JUNO_ADC_H */ diff --git a/product/juno/module/juno_adc/src/mod_juno_adc.c b/product/juno/module/juno_adc/src/mod_juno_adc.c new file mode 100644 index 0000000000000000000000000000000000000000..6616a5a307577abf8186b226a838ba9cbb9946fa --- /dev/null +++ b/product/juno/module/juno_adc/src/mod_juno_adc.c @@ -0,0 +1,210 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Juno ADC Driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct mod_log_api *log_api; + +/* + * ADC driver API functions. + */ +static int get_value(fwk_id_t id, uint64_t *value) +{ + int status; + uint32_t adc_value; + uint64_t adc_quantity; + enum juno_adc_dev_type dev_type; + + status = fwk_module_check_call(id); + if (status != FWK_SUCCESS) + return status; + + fwk_assert(fwk_module_is_valid_sub_element_id(id)); + fwk_assert(value != NULL); + + dev_type = fwk_id_get_sub_element_idx(id); + + switch (fwk_id_get_element_idx(id)) { + case ADC_TYPE_CURRENT: + adc_value = V2M_SYS_REGS->ADC_CURRENT[dev_type] & + JUNO_ADC_SYS_REG_AMPS_MASK; + + adc_quantity = ((uint64_t)adc_value) * JUNO_ADC_AMPS_MULTIPLIER; + + if ((dev_type == ADC_DEV_BIG) || (dev_type == ADC_DEV_GPU)) + adc_quantity /= ADC_CURRENT_CONST1; + else + adc_quantity /= ADC_CURRENT_CONST2; + + *value = adc_quantity; + + log_api->log(MOD_LOG_GROUP_INFO, + "[ADC] Current 0x%lx mA\n", adc_quantity); + + return FWK_SUCCESS; + + case ADC_TYPE_VOLT: + adc_value = V2M_SYS_REGS->ADC_VOLT[dev_type] & + JUNO_ADC_SYS_REG_VOLT_MASK; + + adc_quantity = (((uint64_t)adc_value) * JUNO_ADC_VOLT_MULTIPLIER) + / ADC_VOLT_CONST; + *value = adc_quantity; + + log_api->log(MOD_LOG_GROUP_INFO, + "[ADC] Voltage 0x%lx mV\n", adc_quantity); + + return FWK_SUCCESS; + + case ADC_TYPE_POWER: + adc_value = V2M_SYS_REGS->ADC_POWER[dev_type] & + JUNO_ADC_SYS_REG_POWER_MASK; + + adc_quantity = ((uint64_t)adc_value) * JUNO_ADC_WATTS_MULTIPLIER; + + if ((dev_type == ADC_DEV_BIG) || (dev_type == ADC_DEV_GPU)) + adc_quantity /= ADC_POWER_CONST1; + else + adc_quantity /= ADC_POWER_CONST2; + + *value = adc_quantity; + + log_api->log(MOD_LOG_GROUP_INFO, + "[ADC] Power 0x%lx uW\n", adc_quantity); + + return FWK_SUCCESS; + + case ADC_TYPE_ENERGY: + adc_quantity = V2M_SYS_REGS->ADC_ENERGY[dev_type] * + JUNO_ADC_JOULE_MULTIPLIER; + + if ((dev_type == ADC_DEV_BIG) || (dev_type == ADC_DEV_GPU)) + adc_quantity /= ADC_ENERGY_CONST1; + else + adc_quantity /= ADC_ENERGY_CONST2; + + *value = adc_quantity; + + log_api->log(MOD_LOG_GROUP_INFO, + "[ADC] Energy 0x%lx uJ\n", adc_quantity); + + return FWK_SUCCESS; + + default: + return FWK_E_PARAM; + } +} + +static int get_info(fwk_id_t id, struct mod_sensor_info *info) +{ + int status; + const struct mod_juno_adc_dev_config *config; + + status = fwk_module_check_call(id); + if (status != FWK_SUCCESS) + return status; + + fwk_assert(fwk_module_is_valid_sub_element_id(id)); + + config = fwk_module_get_data(id); + + if (!fwk_expect(config->info != NULL)) + return FWK_E_DATA; + + fwk_assert(info != NULL); + + *info = *(config->info); + + return FWK_SUCCESS; +} + +static const struct mod_sensor_driver_api adc_sensor_api = { + .get_value = get_value, + .get_info = get_info, +}; + +/* + * Framework handlers. + */ +static int juno_adc_init(fwk_id_t module_id, + unsigned int element_count, + const void *data) +{ + if (!fwk_expect(element_count > 0)) + return FWK_E_DATA; + + return FWK_SUCCESS; +} + +static int juno_adc_element_init(fwk_id_t element_id, + unsigned int sub_element_count, + const void *data) +{ + return FWK_SUCCESS; +} + +static int juno_adc_bind(fwk_id_t id, unsigned int round) +{ + int status; + + /* Nothing to do in the second round of calls */ + if (round > 0) + return FWK_SUCCESS; + + /* Nothing to do in case of elements */ + if (!fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) + return FWK_SUCCESS; + + status = fwk_module_bind(fwk_module_id_log, MOD_LOG_API_ID, &log_api); + if (status != FWK_SUCCESS) + return status; + + return FWK_SUCCESS; +} + +static int juno_adc_process_bind_request(fwk_id_t source_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + if (!fwk_module_is_valid_sub_element_id(target_id)) + return FWK_E_ACCESS; + + if (fwk_id_get_module_idx(source_id) != + fwk_id_get_module_idx(fwk_module_id_sensor)) + return FWK_E_ACCESS; + + if (!fwk_id_is_equal(api_id, mod_juno_adc_api_id_driver)) + return FWK_E_ACCESS; + + *api = &adc_sensor_api; + + return FWK_SUCCESS; +} + +const struct fwk_module module_juno_adc = { + .name = "Juno ADC Driver", + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = MOD_JUNO_ADC_API_IDX_COUNT, + .init = juno_adc_init, + .bind = juno_adc_bind, + .element_init = juno_adc_element_init, + .process_bind_request = juno_adc_process_bind_request +}; diff --git a/product/juno/module/juno_system/src/mod_juno_system.c b/product/juno/module/juno_system/src/mod_juno_system.c index 243535fa43be64f6c966764e7658ed08a46adcfa..2df08da649d163da66dfd10d361b4fcdc01827fa 100644 --- a/product/juno/module/juno_system/src/mod_juno_system.c +++ b/product/juno/module/juno_system/src/mod_juno_system.c @@ -104,8 +104,14 @@ static int juno_system_module_init(fwk_id_t module_id, unsigned int element_count, const void *data) { + int status; + fwk_assert(element_count == 0); + status = juno_id_get_platform(&juno_system_ctx.platform_id); + if (!fwk_expect(status == FWK_SUCCESS)) + return FWK_E_PANIC; + return FWK_SUCCESS; } @@ -116,14 +122,19 @@ static int juno_system_bind(fwk_id_t id, unsigned int round) if (round > 0) return FWK_SUCCESS; - status = fwk_module_bind(fwk_module_id_juno_xrp7724, - mod_juno_xrp7724_api_id_system_mode, &juno_system_ctx.juno_xrp7724_api); + status = fwk_module_bind(fwk_module_id_sds, + FWK_ID_API(FWK_MODULE_IDX_SDS, 0), + &juno_system_ctx.sds_api); if (status != FWK_SUCCESS) return FWK_E_HANDLER; - return fwk_module_bind(fwk_module_id_sds, - FWK_ID_API(FWK_MODULE_IDX_SDS, 0), - &juno_system_ctx.sds_api); + if (juno_system_ctx.platform_id != JUNO_IDX_PLATFORM_RTL) + return FWK_SUCCESS; + else { + return fwk_module_bind(fwk_module_id_juno_xrp7724, + mod_juno_xrp7724_api_id_system_mode, + &juno_system_ctx.juno_xrp7724_api); + } } static int juno_system_process_bind_request(fwk_id_t source_id, @@ -141,10 +152,6 @@ static int juno_system_start(fwk_id_t id) int status; unsigned int i; - status = juno_id_get_platform(&juno_system_ctx.platform_id); - if (!fwk_expect(status == FWK_SUCCESS)) - return FWK_E_PANIC; - /* * Subscribe to these SCMI channels in order to know when they have all * initialized. diff --git a/product/juno/module/juno_xrp7724/include/mod_juno_xrp7724.h b/product/juno/module/juno_xrp7724/include/mod_juno_xrp7724.h index 344fe58fba5879e5bb02d942bf67c7f98f123d4f..13de7a28c3fae8ee7d11a62ada130782a7753fa7 100644 --- a/product/juno/module/juno_xrp7724/include/mod_juno_xrp7724.h +++ b/product/juno/module/juno_xrp7724/include/mod_juno_xrp7724.h @@ -22,7 +22,7 @@ */ /*! - * \brief Module configuration + * \brief Module configuration. */ struct mod_juno_xrp7724_config { /*! Slave address of the I2C device */ @@ -38,17 +38,31 @@ struct mod_juno_xrp7724_config { }; /*! - * \brief Element type + * \brief Element type. */ enum mod_juno_xrp7724_element_type { MOD_JUNO_XRP7724_ELEMENT_TYPE_GPIO, + MOD_JUNO_XRP7724_ELEMENT_TYPE_SENSOR, MOD_JUNO_XRP7724_ELEMENT_TYPE_COUNT, }; /*! - * \brief Element configuration + * \brief Element configuration. */ struct mod_juno_xrp7724_dev_config { + /*! Identifier of the element for the driver response */ + fwk_id_t driver_response_id; + + /*! Identifier of the driver response API */ + fwk_id_t driver_response_api_id; + + /*! + * \brief Sensor information. + * + * \note Only provided for a sensor element + */ + struct mod_sensor_info *sensor_info; + /*! Element type */ enum mod_juno_xrp7724_element_type type; }; @@ -74,6 +88,7 @@ struct mod_juno_xrp7724_api_system_mode { /*! Index of the available APIs */ enum mod_juno_xrp7724_api_idx { + MOD_JUNO_XRP7724_API_IDX_SENSOR, MOD_JUNO_XRP7724_API_IDX_SYSTEM_MODE, MOD_JUNO_XRP7724_API_IDX_COUNT, }; @@ -82,6 +97,10 @@ enum mod_juno_xrp7724_api_idx { static const fwk_id_t mod_juno_xrp7724_api_id_system_mode = FWK_ID_API_INIT( FWK_MODULE_IDX_JUNO_XRP7724, MOD_JUNO_XRP7724_API_IDX_SYSTEM_MODE); +/*! Identifier of the sensor driver API */ +static const fwk_id_t mod_juno_xrp7724_api_id_sensor = FWK_ID_API_INIT( + FWK_MODULE_IDX_JUNO_XRP7724, MOD_JUNO_XRP7724_API_IDX_SENSOR); + /*! * \} */ diff --git a/product/juno/module/juno_xrp7724/src/mod_juno_xrp7724.c b/product/juno/module/juno_xrp7724/src/mod_juno_xrp7724.c index ca7f5cf5eb652086faf1c4554201811b1605ce7f..5dbd46ceb32410514cb7656291e9a4ae4bb920df 100644 --- a/product/juno/module/juno_xrp7724/src/mod_juno_xrp7724.c +++ b/product/juno/module/juno_xrp7724/src/mod_juno_xrp7724.c @@ -14,10 +14,14 @@ #include #include #include +#include #include +#include -/* Maximal required length for the I2C transmissions */ +/* Maximum required length for the I2C transmissions */ #define TRANSMIT_DATA_MAX 3 +/* Maximum required length for the I2C receptions */ +#define RECEIVE_DATA_MAX 2 #define GPIO_DELAY_US 3000 @@ -28,6 +32,13 @@ /* I2C transmission length to set a GPIO */ #define GPIO_WRITE_TRANSMIT_LENGTH 3 +/* I2C transmission and reception length to read the sensor value */ +#define SENSOR_WRITE_LENGTH 1 +#define SENSOR_READ_LENGTH 2 + +/* Read temperature command */ +#define SENSOR_READ_TEMP 0x15 + enum juno_xrp7724_event_idx { JUNO_XRP7724_EVENT_IDX_REQUEST, JUNO_XRP7724_EVENT_IDX_COUNT @@ -41,17 +52,27 @@ enum juno_xrp7724_gpio_request { JUNO_XRP7724_GPIO_REQUEST_DONE, }; +enum juno_xrp7724_sensor_request { + JUNO_XRP7724_SENSOR_REQUEST_IDLE, + JUNO_XRP7724_SENSOR_REQUEST_READ_VALUE, + JUNO_XRP7724_SENSOR_REQUEST_CONVERT_VALUE, +}; + struct juno_xrp7724_ctx { const struct mod_juno_xrp7724_config *config; + const struct mod_sensor_driver_response_api *sensor_driver_response_api; const struct mod_i2c_api *i2c_api; const struct mod_timer_api *timer_api; enum juno_xrp7724_gpio_request gpio_request; + enum juno_xrp7724_sensor_request sensor_request; + bool driver_skipped; }; struct juno_xrp7724_dev_ctx { const struct mod_juno_xrp7724_dev_config *config; uint32_t cookie; uint8_t transmit_data[TRANSMIT_DATA_MAX]; + uint8_t receive_data[RECEIVE_DATA_MAX]; }; static const fwk_id_t juno_xrp7724_event_id_request = @@ -85,10 +106,15 @@ static int set_gpio(fwk_id_t id, struct juno_xrp7724_dev_ctx *ctx) return FWK_SUCCESS; } +/* Helper function for the sensor API */ +static uint64_t temperature_to_millidegree_celsius(uint16_t temp) +{ + return (temp * 5000ULL) - 272150; +} + /* * Functions for the system mode API */ - static void juno_xrp7724_shutdown(void) { int status; @@ -140,6 +166,69 @@ static const struct mod_juno_xrp7724_api_system_mode system_mode_api = { .reset = juno_xrp7724_reset, }; +/* + * Driver functions for the sensor API + */ +static int juno_xrp7724_sensor_get_value(fwk_id_t id, uint64_t *value) +{ + int status; + struct fwk_event event; + struct juno_xrp7724_dev_ctx *ctx; + + fwk_assert(fwk_module_is_valid_element_id(id)); + + status = fwk_module_check_call(id); + if (status != FWK_SUCCESS) + return status; + + if (module_ctx.sensor_request != JUNO_XRP7724_SENSOR_REQUEST_IDLE) + return FWK_E_BUSY; + + ctx = &ctx_table[fwk_id_get_element_idx(id)]; + fwk_assert(ctx->config->type == MOD_JUNO_XRP7724_ELEMENT_TYPE_SENSOR); + + event = (struct fwk_event) { + .target_id = id, + .id = juno_xrp7724_event_id_request, + }; + + module_ctx.sensor_request = JUNO_XRP7724_SENSOR_REQUEST_READ_VALUE; + + status = fwk_thread_put_event(&event); + if (status != FWK_SUCCESS) { + module_ctx.sensor_request = JUNO_XRP7724_SENSOR_REQUEST_IDLE; + return status; + } + + return FWK_PENDING; +} + +static int juno_xrp7724_sensor_get_info(fwk_id_t id, + struct mod_sensor_info *info) +{ + int status; + const struct juno_xrp7724_dev_ctx *ctx; + + fwk_assert(fwk_module_is_valid_element_id(id)); + fwk_assert(info != NULL); + + status = fwk_module_check_call(id); + if (status != FWK_SUCCESS) + return status; + + ctx = &ctx_table[fwk_id_get_element_idx(id)]; + fwk_assert(ctx->config->type == MOD_JUNO_XRP7724_ELEMENT_TYPE_SENSOR); + + *info = *(ctx->config->sensor_info); + + return FWK_SUCCESS; +} + +static const struct mod_sensor_driver_api sensor_driver_api = { + .get_value = juno_xrp7724_sensor_get_value, + .get_info = juno_xrp7724_sensor_get_info, +}; + /* * Framework handlers */ @@ -147,16 +236,27 @@ static int juno_xrp7724_init(fwk_id_t module_id, unsigned int element_count, const void *data) { + int status; + enum juno_idx_platform platform_id; + fwk_assert(data != NULL); module_ctx.config = (struct mod_juno_xrp7724_config *)data; ctx_table = fwk_mm_calloc(element_count, sizeof(struct juno_xrp7724_dev_ctx)); - if (ctx_table == NULL) return FWK_E_NOMEM; + status = juno_id_get_platform(&platform_id); + if (!fwk_expect(status == FWK_SUCCESS)) + return FWK_E_PANIC; + + if (platform_id == JUNO_IDX_PLATFORM_FVP) { + /* XRP7724 hardware is only available in the board */ + module_ctx.driver_skipped = true; + } + return FWK_SUCCESS; } @@ -171,6 +271,11 @@ static int juno_xrp7724_element_init(fwk_id_t element_id, ctx = ctx_table + fwk_id_get_element_idx(element_id); ctx->config = (struct mod_juno_xrp7724_dev_config *)data; + if (ctx->config->type == MOD_JUNO_XRP7724_ELEMENT_TYPE_SENSOR) { + if (ctx->config->sensor_info == NULL) + return FWK_E_DATA; + } + return FWK_SUCCESS; } @@ -178,9 +283,10 @@ static int juno_xrp7724_bind(fwk_id_t id, unsigned int round) { int status; const struct mod_juno_xrp7724_config *config = module_ctx.config; + struct juno_xrp7724_dev_ctx *ctx; - /* Only bind in first round of calls */ - if (round > 0) + /* Only bind in first round of calls and if the driver is available */ + if ((round > 0) || (module_ctx.driver_skipped)) return FWK_SUCCESS; if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) { @@ -197,6 +303,18 @@ static int juno_xrp7724_bind(fwk_id_t id, unsigned int round) &module_ctx.timer_api); if (status != FWK_SUCCESS) return FWK_E_HANDLER; + + return FWK_SUCCESS; + } + + ctx = &ctx_table[fwk_id_get_element_idx(id)]; + + if (ctx->config->type == MOD_JUNO_XRP7724_ELEMENT_TYPE_SENSOR) { + status = fwk_module_bind(ctx->config->driver_response_id, + ctx->config->driver_response_api_id, + &module_ctx.sensor_driver_response_api); + if (status != FWK_SUCCESS) + return FWK_E_HANDLER; } return FWK_SUCCESS; @@ -207,8 +325,13 @@ static int juno_xrp7724_process_bind_request(fwk_id_t source_id, fwk_id_t api_id, const void **api) { + if (module_ctx.driver_skipped) + return FWK_E_ACCESS; + if (fwk_id_is_equal(api_id, mod_juno_xrp7724_api_id_system_mode)) *api = &system_mode_api; + else if (fwk_id_is_equal(api_id, mod_juno_xrp7724_api_id_sensor)) + *api = &sensor_driver_api; else return FWK_E_PARAM; @@ -312,6 +435,61 @@ static int juno_xrp7724_gpio_process_request(fwk_id_t id, int response_status) return fwk_thread_put_event(&resp_event); } +static int juno_xrp7724_sensor_process_request(fwk_id_t id, int status) +{ + struct juno_xrp7724_dev_ctx *ctx; + uint64_t temp = 0; + int request_status = status; + struct mod_sensor_driver_resp_params resp_params; + const struct mod_juno_xrp7724_config *module_config = module_ctx.config; + + ctx = &ctx_table[fwk_id_get_element_idx(id)]; + + switch (module_ctx.sensor_request) { + case JUNO_XRP7724_SENSOR_REQUEST_READ_VALUE: + module_ctx.sensor_request = JUNO_XRP7724_SENSOR_REQUEST_CONVERT_VALUE; + + ctx->transmit_data[0] = SENSOR_READ_TEMP; + + request_status = + module_ctx.i2c_api->transmit_then_receive_as_master( + module_config->i2c_hal_id, module_config->slave_address, + ctx->transmit_data, ctx->receive_data, SENSOR_WRITE_LENGTH, + SENSOR_READ_LENGTH); + if (request_status == FWK_SUCCESS) + return FWK_SUCCESS; + + break; + + case JUNO_XRP7724_SENSOR_REQUEST_CONVERT_VALUE: + /* + * The request_status parameter contains the I2C transaction status. + * The conversion is done if the read of the sensor value has been + * successful. + */ + if (request_status == FWK_SUCCESS) { + temp = temperature_to_millidegree_celsius( + ((uint16_t)ctx->receive_data[0] << 8) | ctx->receive_data[1]); + } + + break; + + default: + request_status = FWK_E_PARAM; + } + + module_ctx.sensor_request = JUNO_XRP7724_SENSOR_REQUEST_IDLE; + + resp_params.status = request_status; + resp_params.value = temp; + + module_ctx.sensor_driver_response_api->reading_complete( + ctx->config->driver_response_id, + &resp_params); + + return FWK_SUCCESS; +} + /* * This function is called when a request event is received for the XRP7724 and * when an I2C transaction is completed. @@ -341,6 +519,11 @@ static int juno_xrp7724_process_event(const struct fwk_event *event, } return FWK_SUCCESS; + + case MOD_JUNO_XRP7724_ELEMENT_TYPE_SENSOR: + return juno_xrp7724_sensor_process_request(event->target_id, + param->status); + default: return FWK_E_PARAM; } diff --git a/product/juno/scp_ramfw/config_juno_adc.c b/product/juno/scp_ramfw/config_juno_adc.c new file mode 100644 index 0000000000000000000000000000000000000000..b2e0f6d5e797f6b61a8f93a712848e0c913994ba --- /dev/null +++ b/product/juno/scp_ramfw/config_juno_adc.c @@ -0,0 +1,65 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +static const struct fwk_element adc_juno_element_table[] = { + [ADC_TYPE_CURRENT] = { + .name = "ADC Current", + .sub_element_count = ADC_DEV_TYPE_COUNT, + .data = &((struct mod_juno_adc_dev_config) { + .info = &((struct mod_sensor_info) { + .type = MOD_SENSOR_TYPE_AMPS, + .unit_multiplier = -3, + }), + }), + }, + [ADC_TYPE_VOLT] = { + .name = "ADC Voltage", + .sub_element_count = ADC_DEV_TYPE_COUNT, + .data = &((struct mod_juno_adc_dev_config) { + .info = &((struct mod_sensor_info) { + .type = MOD_SENSOR_TYPE_VOLTS, + .unit_multiplier = -3, + }), + }), + }, + [ADC_TYPE_POWER] = { + .name = "ADC Power", + .sub_element_count = ADC_DEV_TYPE_COUNT, + .data = &((struct mod_juno_adc_dev_config) { + .info = &((struct mod_sensor_info) { + .type = MOD_SENSOR_TYPE_WATTS, + .unit_multiplier = -6, + }), + }), + }, + [ADC_TYPE_ENERGY] = { + .name = "ADC Energy", + .sub_element_count = ADC_DEV_TYPE_COUNT, + .data = &((struct mod_juno_adc_dev_config) { + .info = &((struct mod_sensor_info) { + .type = MOD_SENSOR_TYPE_JOULES, + .unit_multiplier = -6, + }), + }), + }, + [ADC_TYPE_COUNT] = { 0 }, +}; + +static const struct fwk_element *get_adc_juno_element_table(fwk_id_t id) +{ + return adc_juno_element_table; +} + +struct fwk_module_config config_juno_adc = { + .get_element_table = get_adc_juno_element_table, +}; diff --git a/product/juno/scp_ramfw/config_juno_xrp7724.c b/product/juno/scp_ramfw/config_juno_xrp7724.c index bb17ae5eb7901bea9feac0121872509d4bbe5aad..1e1ec69e6771e5415360a74ce1aed45fe821af21 100644 --- a/product/juno/scp_ramfw/config_juno_xrp7724.c +++ b/product/juno/scp_ramfw/config_juno_xrp7724.c @@ -11,12 +11,10 @@ #include #include #include +#include #include - -enum mod_juno_xrp7724_element_idx { - MOD_JUNO_XRP7724_ELEMENT_IDX_GPIO, - MOD_JUNO_XRP7724_ELEMENT_IDX_COUNT -}; +#include +#include enum mod_juno_xrp7724_gpio_idx { MOD_JUNO_XRP7724_GPIO_IDX_ASSERT, @@ -24,7 +22,28 @@ enum mod_juno_xrp7724_gpio_idx { MOD_JUNO_XRP7724_GPIO_IDX_COUNT, }; +/* + * Temperature sensor information + */ +static struct mod_sensor_info juno_xrp7724_info_temperature = { + .type = MOD_SENSOR_TYPE_DEGREES_C, + .update_interval = 0, + .update_interval_multiplier = 0, + .unit_multiplier = -3, +}; + static const struct fwk_element juno_xrp7724_element_table[] = { + [MOD_JUNO_XRP7724_ELEMENT_IDX_SENSOR] = { + .name = "TEMPERATURE SENSOR", + .data = &(const struct mod_juno_xrp7724_dev_config) { + .driver_response_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SENSOR, + MOD_JUNO_SENSOR_XRP7724_PMIC_TEMP_IDX), + .driver_response_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SENSOR, + MOD_SENSOR_API_IDX_DRIVER_RESPONSE), + .sensor_info = &juno_xrp7724_info_temperature, + .type = MOD_JUNO_XRP7724_ELEMENT_TYPE_SENSOR, + }, + }, [MOD_JUNO_XRP7724_ELEMENT_IDX_GPIO] = { .name = "GPIOs", .sub_element_count = MOD_JUNO_XRP7724_GPIO_IDX_COUNT, diff --git a/product/juno/scp_ramfw/config_juno_xrp7724.h b/product/juno/scp_ramfw/config_juno_xrp7724.h new file mode 100644 index 0000000000000000000000000000000000000000..78e6714eea70771e8baf760ed97eedb12f273d35 --- /dev/null +++ b/product/juno/scp_ramfw/config_juno_xrp7724.h @@ -0,0 +1,18 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_JUNO_XRP7724_H +#define CONFIG_JUNO_XRP7724_H + +/* Element indices for Juno XRP7724 */ +enum mod_juno_xrp7724_element_idx { + MOD_JUNO_XRP7724_ELEMENT_IDX_SENSOR, + MOD_JUNO_XRP7724_ELEMENT_IDX_GPIO, + MOD_JUNO_XRP7724_ELEMENT_IDX_COUNT +}; + +#endif /* CONFIG_JUNO_XRP7724_H */ diff --git a/product/juno/scp_ramfw/config_reg_sensor.c b/product/juno/scp_ramfw/config_reg_sensor.c new file mode 100644 index 0000000000000000000000000000000000000000..e4a4f531ff289e988b4d701f887fe869f7425207 --- /dev/null +++ b/product/juno/scp_ramfw/config_reg_sensor.c @@ -0,0 +1,46 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +static uint32_t fake_register = 0x00001234; + +/* + * Register Sensor driver config + */ +static struct mod_sensor_info info_fake_temperature = { + .type = MOD_SENSOR_TYPE_DEGREES_C, + .update_interval = 0, + .update_interval_multiplier = 0, + .unit_multiplier = 0, +}; + +static const struct fwk_element reg_sensor_element_table[] = { + [0] = { + .name = "Fake Temperature", + .data = &((struct mod_reg_sensor_dev_config) { + .reg = (uintptr_t)(&fake_register), + .info = &info_fake_temperature, + }), + }, + + [1] = { 0 }, +}; + +static const struct fwk_element *get_reg_sensor_element_table(fwk_id_t id) +{ + return reg_sensor_element_table; +} + +struct fwk_module_config config_reg_sensor = { + .get_element_table = get_reg_sensor_element_table, + .data = NULL, +}; diff --git a/product/juno/scp_ramfw/config_sensor.c b/product/juno/scp_ramfw/config_sensor.c new file mode 100644 index 0000000000000000000000000000000000000000..e666874c8bea4de17956bb298f6edc07043c1750 --- /dev/null +++ b/product/juno/scp_ramfw/config_sensor.c @@ -0,0 +1,228 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct fwk_element sensor_element_table[] = { + /* + * ADC Sensors + */ + [MOD_JUNO_SENSOR_AMPS_SYS_IDX] = { + .name = "Juno amps-sys", + .data = &((struct mod_sensor_dev_config) { + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC, + ADC_TYPE_CURRENT, + ADC_DEV_SYS), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC, + MOD_JUNO_ADC_API_IDX_DRIVER), + }), + }, + [MOD_JUNO_SENSOR_AMPS_BIG_IDX] = { + .name = "Juno amps-big", + .data = &((struct mod_sensor_dev_config) { + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC, + ADC_TYPE_CURRENT, + ADC_DEV_BIG), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC, + MOD_JUNO_ADC_API_IDX_DRIVER), + }), + }, + [MOD_JUNO_SENSOR_AMPS_LITTLE_IDX] = { + .name = "Juno amps-little", + .data = &((struct mod_sensor_dev_config) { + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC, + ADC_TYPE_CURRENT, + ADC_DEV_LITTLE), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC, + MOD_JUNO_ADC_API_IDX_DRIVER), + }), + }, + [MOD_JUNO_SENSOR_AMPS_GPU_IDX] = { + .name = "Juno amps-gpu", + .data = &((struct mod_sensor_dev_config) { + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC, + ADC_TYPE_CURRENT, + ADC_DEV_GPU), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC, + MOD_JUNO_ADC_API_IDX_DRIVER), + }), + }, + [MOD_JUNO_SENSOR_VOLT_SYS_IDX] = { + .name = "Juno volt-sys", + .data = &((struct mod_sensor_dev_config) { + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC, + ADC_TYPE_VOLT, + ADC_DEV_SYS), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC, + MOD_JUNO_ADC_API_IDX_DRIVER), + }), + }, + [MOD_JUNO_SENSOR_VOLT_BIG_IDX] = { + .name = "Juno volt-big", + .data = &((struct mod_sensor_dev_config) { + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC, + ADC_TYPE_VOLT, + ADC_DEV_BIG), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC, + MOD_JUNO_ADC_API_IDX_DRIVER), + }), + }, + [MOD_JUNO_SENSOR_VOLT_LITTLE_IDX] = { + .name = "Juno volt-little", + .data = &((struct mod_sensor_dev_config) { + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC, + ADC_TYPE_VOLT, + ADC_DEV_LITTLE), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC, + MOD_JUNO_ADC_API_IDX_DRIVER), + }), + }, + [MOD_JUNO_SENSOR_VOLT_GPU_IDX] = { + .name = "Juno volt-gpu", + .data = &((struct mod_sensor_dev_config) { + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC, + ADC_TYPE_VOLT, + ADC_DEV_GPU), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC, + MOD_JUNO_ADC_API_IDX_DRIVER), + }), + }, + [MOD_JUNO_SENSOR_WATT_SYS_IDX] = { + .name = "Juno watt-sys", + .data = &((struct mod_sensor_dev_config) { + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC, + ADC_TYPE_POWER, + ADC_DEV_SYS), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC, + MOD_JUNO_ADC_API_IDX_DRIVER), + }), + }, + [MOD_JUNO_SENSOR_WATT_BIG_IDX] = { + .name = "Juno watt-big", + .data = &((struct mod_sensor_dev_config) { + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC, + ADC_TYPE_POWER, + ADC_DEV_BIG), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC, + MOD_JUNO_ADC_API_IDX_DRIVER), + }), + }, + [MOD_JUNO_SENSOR_WATT_LITTLE_IDX] = { + .name = "Juno watt-little", + .data = &((struct mod_sensor_dev_config) { + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC, + ADC_TYPE_POWER, + ADC_DEV_LITTLE), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC, + MOD_JUNO_ADC_API_IDX_DRIVER), + }), + }, + [MOD_JUNO_SENSOR_WATT_GPU_IDX] = { + .name = "Juno watt-gpu", + .data = &((struct mod_sensor_dev_config) { + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC, + ADC_TYPE_POWER, + ADC_DEV_GPU), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC, + MOD_JUNO_ADC_API_IDX_DRIVER), + }), + }, + [MOD_JUNO_SENSOR_JOULE_SYS_IDX] = { + .name = "Juno joule-sys", + .data = &((struct mod_sensor_dev_config) { + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC, + ADC_TYPE_ENERGY, + ADC_DEV_SYS), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC, + MOD_JUNO_ADC_API_IDX_DRIVER), + }), + }, + [MOD_JUNO_SENSOR_JOULE_BIG_IDX] = { + .name = "Juno joule-big", + .data = &((struct mod_sensor_dev_config) { + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC, + ADC_TYPE_ENERGY, + ADC_DEV_BIG), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC, + MOD_JUNO_ADC_API_IDX_DRIVER), + }), + }, + [MOD_JUNO_SENSOR_JOULE_LITTLE_IDX] = { + .name = "Juno joule-little", + .data = &((struct mod_sensor_dev_config) { + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC, + ADC_TYPE_ENERGY, + ADC_DEV_LITTLE), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC, + MOD_JUNO_ADC_API_IDX_DRIVER), + }), + }, + [MOD_JUNO_SENSOR_JOULE_GPU_IDX] = { + .name = "Juno joule-gpu", + .data = &((struct mod_sensor_dev_config) { + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_ADC, + ADC_TYPE_ENERGY, + ADC_DEV_GPU), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_ADC, + MOD_JUNO_ADC_API_IDX_DRIVER), + }), + }, + [MOD_JUNO_SENSOR_XRP7724_PMIC_TEMP_IDX] = { + .name = "PMIC temperature", + .data = &(struct mod_sensor_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_XRP7724, 0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_XRP7724, + MOD_JUNO_XRP7724_API_IDX_SENSOR), + + }, + }, + + [MOD_JUNO_SENSOR_IDX_COUNT] = { 0 } /* Termination description */ +}; + +/* + * When running on a model at least one fake sensor is required to register in + * order to properly initialize scmi sensor management. + */ +static const struct fwk_element sensor_element_table_fvp[] = { + [0] = { + .name = "Juno fake reg sensor", + .data = &((struct mod_sensor_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_REG_SENSOR, 0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_REG_SENSOR, 0), + }), + }, + + [1] = { 0 } /* Termination description */ +}; + +static const struct fwk_element *get_sensor_element_table(fwk_id_t module_id) +{ + int status; + enum juno_idx_platform platform_id = JUNO_IDX_PLATFORM_COUNT; + + status = juno_id_get_platform(&platform_id); + if (!fwk_expect(status == FWK_SUCCESS)) + return NULL; + + if (platform_id == JUNO_IDX_PLATFORM_FVP) + return sensor_element_table_fvp; + else + return sensor_element_table; +} + +struct fwk_module_config config_sensor = { + .get_element_table = get_sensor_element_table, + .data = NULL, +}; diff --git a/product/juno/scp_ramfw/config_sensor.h b/product/juno/scp_ramfw/config_sensor.h new file mode 100644 index 0000000000000000000000000000000000000000..63f315438c2ba66d706a254f7311010f3ff22764 --- /dev/null +++ b/product/juno/scp_ramfw/config_sensor.h @@ -0,0 +1,38 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_SENSOR_H +#define CONFIG_SENSOR_H + +/* Sensor indices for Juno */ +enum mod_juno_sensor_element_idx { + /* ADC sensors */ + MOD_JUNO_SENSOR_AMPS_SYS_IDX = 0, + MOD_JUNO_SENSOR_AMPS_BIG_IDX, + MOD_JUNO_SENSOR_AMPS_LITTLE_IDX, + MOD_JUNO_SENSOR_AMPS_GPU_IDX, + MOD_JUNO_SENSOR_VOLT_SYS_IDX, + MOD_JUNO_SENSOR_VOLT_BIG_IDX, + MOD_JUNO_SENSOR_VOLT_LITTLE_IDX, + MOD_JUNO_SENSOR_VOLT_GPU_IDX, + MOD_JUNO_SENSOR_WATT_SYS_IDX, + MOD_JUNO_SENSOR_WATT_BIG_IDX, + MOD_JUNO_SENSOR_WATT_LITTLE_IDX, + MOD_JUNO_SENSOR_WATT_GPU_IDX, + MOD_JUNO_SENSOR_JOULE_SYS_IDX, + MOD_JUNO_SENSOR_JOULE_BIG_IDX, + MOD_JUNO_SENSOR_JOULE_LITTLE_IDX, + MOD_JUNO_SENSOR_JOULE_GPU_IDX, + + /* XRP7724 sensors */ + MOD_JUNO_SENSOR_XRP7724_PMIC_TEMP_IDX, + + /* Number of sensors */ + MOD_JUNO_SENSOR_IDX_COUNT +}; + +#endif /* CONFIG_SENSOR_H */ diff --git a/product/juno/scp_ramfw/firmware.mk b/product/juno/scp_ramfw/firmware.mk index 75f7051f8fb087a90dfe0067246a15b214e6265a..0b82ffec29ee16fb5216aa615abcfb6e13216339 100644 --- a/product/juno/scp_ramfw/firmware.mk +++ b/product/juno/scp_ramfw/firmware.mk @@ -35,7 +35,10 @@ BS_FIRMWARE_MODULES := \ sds \ i2c \ dw_apb_i2c \ - juno_xrp7724 + juno_adc \ + juno_xrp7724 \ + sensor \ + reg_sensor BS_FIRMWARE_SOURCES := \ rtx_config.c \ @@ -56,6 +59,9 @@ BS_FIRMWARE_SOURCES := \ config_scmi.c \ config_scmi_system_power.c \ config_i2c.c \ - config_juno_xrp7724.c + config_juno_adc.c \ + config_juno_xrp7724.c \ + config_sensor.c \ + config_reg_sensor.c include $(BS_DIR)/firmware.mk diff --git a/product/n1sdp/scp_ramfw/config_sensor.c b/product/n1sdp/scp_ramfw/config_sensor.c index 4d51dfb0a1bba7565919a87904136ad2ac123a34..be3fcf0385ebadab2e43160d22f374b6e5843d52 100644 --- a/product/n1sdp/scp_ramfw/config_sensor.c +++ b/product/n1sdp/scp_ramfw/config_sensor.c @@ -114,6 +114,7 @@ static const struct fwk_element sensor_element_table[] = { .data = &((struct mod_sensor_dev_config) { .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_N1SDP_SENSOR, MOD_N1SDP_TEMP_SENSOR_IDX_CLUSTER0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_N1SDP_SENSOR, 0), }), }, [MOD_N1SDP_TEMP_SENSOR_IDX_CLUSTER1] = { @@ -121,6 +122,7 @@ static const struct fwk_element sensor_element_table[] = { .data = &((struct mod_sensor_dev_config) { .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_N1SDP_SENSOR, MOD_N1SDP_TEMP_SENSOR_IDX_CLUSTER1), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_N1SDP_SENSOR, 0), }), }, [MOD_N1SDP_TEMP_SENSOR_IDX_SYSTEM] = { @@ -128,6 +130,7 @@ static const struct fwk_element sensor_element_table[] = { .data = &((struct mod_sensor_dev_config) { .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_N1SDP_SENSOR, MOD_N1SDP_TEMP_SENSOR_IDX_SYSTEM), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_N1SDP_SENSOR, 0), }), }, [MOD_N1SDP_VOLT_SENSOR_IDX_CLUS0CORE0] = { @@ -135,6 +138,7 @@ static const struct fwk_element sensor_element_table[] = { .data = &((struct mod_sensor_dev_config) { .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_N1SDP_SENSOR, MOD_N1SDP_VOLT_SENSOR_IDX_CLUS0CORE0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_N1SDP_SENSOR, 0), }), }, [MOD_N1SDP_VOLT_SENSOR_IDX_CLUS0CORE1] = { @@ -142,6 +146,7 @@ static const struct fwk_element sensor_element_table[] = { .data = &((struct mod_sensor_dev_config) { .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_N1SDP_SENSOR, MOD_N1SDP_VOLT_SENSOR_IDX_CLUS0CORE1), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_N1SDP_SENSOR, 0), }), }, [MOD_N1SDP_VOLT_SENSOR_IDX_CLUS1CORE0] = { @@ -149,6 +154,7 @@ static const struct fwk_element sensor_element_table[] = { .data = &((struct mod_sensor_dev_config) { .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_N1SDP_SENSOR, MOD_N1SDP_VOLT_SENSOR_IDX_CLUS1CORE0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_N1SDP_SENSOR, 0), }), }, [MOD_N1SDP_VOLT_SENSOR_IDX_CLUS1CORE1] = { @@ -156,6 +162,7 @@ static const struct fwk_element sensor_element_table[] = { .data = &((struct mod_sensor_dev_config) { .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_N1SDP_SENSOR, MOD_N1SDP_VOLT_SENSOR_IDX_CLUS1CORE1), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_N1SDP_SENSOR, 0), }), }, [MOD_N1SDP_VOLT_SENSOR_IDX_SYSTEM] = { @@ -163,6 +170,7 @@ static const struct fwk_element sensor_element_table[] = { .data = &((struct mod_sensor_dev_config) { .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_N1SDP_SENSOR, MOD_N1SDP_VOLT_SENSOR_IDX_SYSTEM), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_N1SDP_SENSOR, 0), }), }, [MOD_N1SDP_VOLT_SENSOR_COUNT] = { 0 }, diff --git a/product/rdn1e1/scp_ramfw/config_sensor.c b/product/rdn1e1/scp_ramfw/config_sensor.c index 3a1a07195bde9edb9002c7c0628d5a3bcbf263ee..f97d659584f381c6928fb94d402f1a854b2e467f 100644 --- a/product/rdn1e1/scp_ramfw/config_sensor.c +++ b/product/rdn1e1/scp_ramfw/config_sensor.c @@ -56,6 +56,7 @@ static const struct fwk_element sensor_element_table[] = { .data = &((const struct mod_sensor_dev_config) { .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_REG_SENSOR, REG_SENSOR_DEV_SOC_TEMP), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_REG_SENSOR, 0), }), }, [1] = { 0 }, diff --git a/product/sgi575/scp_ramfw/config_sensor.c b/product/sgi575/scp_ramfw/config_sensor.c index 388b759102758f193859650148c4b27977333e88..7a10a4b1a9443401392e32afed828cb22fa7f407 100644 --- a/product/sgi575/scp_ramfw/config_sensor.c +++ b/product/sgi575/scp_ramfw/config_sensor.c @@ -56,6 +56,7 @@ static const struct fwk_element sensor_element_table[] = { .data = &((const struct mod_sensor_dev_config) { .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_REG_SENSOR, REG_SENSOR_DEV_SOC_TEMP), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_REG_SENSOR, 0), }), }, [1] = { 0 }, diff --git a/product/sgm775/scp_ramfw/config_sensor.c b/product/sgm775/scp_ramfw/config_sensor.c index 7882be7c60d9337c260988770b48fa75ade99064..2d5917b57d2f8851807d3bae0d7bb15385cee932 100644 --- a/product/sgm775/scp_ramfw/config_sensor.c +++ b/product/sgm775/scp_ramfw/config_sensor.c @@ -57,6 +57,7 @@ static const struct fwk_element sensor_element_table[] = { .data = &((const struct mod_sensor_dev_config) { .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_REG_SENSOR, REG_SENSOR_DEV_SOC_TEMP), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_REG_SENSOR, 0), }), }, [1] = { 0 },