diff --git a/include/sdfw/sdfw_services/dvfs_service.h b/include/sdfw/sdfw_services/dvfs_service.h new file mode 100644 index 000000000000..99e474593112 --- /dev/null +++ b/include/sdfw/sdfw_services/dvfs_service.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + + #ifndef DVFS_SERVICE_H__ + #define DVFS_SERVICE_H__ + + #include + #include + + #include + + int ssf_dvfs_set_oppoint(uint8_t opp); + + #endif /* DVFS_SERVICE_H__ */ diff --git a/subsys/sdfw_services/services/CMakeLists.txt b/subsys/sdfw_services/services/CMakeLists.txt index d61863d22716..32ad9d49d7a1 100644 --- a/subsys/sdfw_services/services/CMakeLists.txt +++ b/subsys/sdfw_services/services/CMakeLists.txt @@ -10,3 +10,4 @@ add_subdirectory_ifdef(CONFIG_SSF_ENC_FW_SERVICE_ENABLED enc_fw) add_subdirectory_ifdef(CONFIG_SSF_EXTMEM_SERVICE_ENABLED extmem) add_subdirectory_ifdef(CONFIG_SSF_PSA_CRYPTO_SERVICE_ENABLED psa_crypto) add_subdirectory_ifdef(CONFIG_SSF_SUIT_SERVICE_ENABLED suit_service) +add_subdirectory_ifdef(CONFIG_SSF_DVFS_SERVICE_ENABLED dvfs) diff --git a/subsys/sdfw_services/services/Kconfig b/subsys/sdfw_services/services/Kconfig index 8536439091a6..aca0c100a3c8 100644 --- a/subsys/sdfw_services/services/Kconfig +++ b/subsys/sdfw_services/services/Kconfig @@ -10,3 +10,4 @@ rsource "enc_fw/Kconfig" rsource "extmem/Kconfig" rsource "psa_crypto/Kconfig" rsource "suit_service/Kconfig" +rsource "dvfs/Kconfig" diff --git a/subsys/sdfw_services/services/device_info/CMakeLists.txt b/subsys/sdfw_services/services/device_info/CMakeLists.txt index c34b4469d8f7..c49e79e22918 100644 --- a/subsys/sdfw_services/services/device_info/CMakeLists.txt +++ b/subsys/sdfw_services/services/device_info/CMakeLists.txt @@ -7,6 +7,6 @@ zephyr_sources(device_info_service.c) generate_and_add_cbor_files(device_info_service.cddl zcbor_generated - device_info_service_req - device_info_service_rsp + device_info_req + device_info_resp ) diff --git a/subsys/sdfw_services/services/dvfs/CMakeLists.txt b/subsys/sdfw_services/services/dvfs/CMakeLists.txt new file mode 100644 index 000000000000..a12ab2d28c30 --- /dev/null +++ b/subsys/sdfw_services/services/dvfs/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +zephyr_sources(dvfs_service.c) + +generate_and_add_cbor_files(dvfs_service.cddl zcbor_generated + dvfs_oppoint_req + dvfs_oppoint_rsp +) diff --git a/subsys/sdfw_services/services/dvfs/Kconfig b/subsys/sdfw_services/services/dvfs/Kconfig new file mode 100644 index 000000000000..34d8e81a4fa9 --- /dev/null +++ b/subsys/sdfw_services/services/dvfs/Kconfig @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +service_name = DVFS +service_default_enabled = y +service_id = 0xDD +service_version = 1 +service_buffer_size = 32 +service_name_str = DVFS +rsource "../Kconfig.template.service" diff --git a/subsys/sdfw_services/services/dvfs/dvfs_service.c b/subsys/sdfw_services/services/dvfs/dvfs_service.c new file mode 100644 index 000000000000..2942ef0b6491 --- /dev/null +++ b/subsys/sdfw_services/services/dvfs/dvfs_service.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include + +#include + +#include "dvfs_service_decode.h" +#include "dvfs_service_encode.h" +#include "dvfs_service_types.h" +#include +#include +#include "ssf_client_os.h" + +SSF_CLIENT_SERVICE_DEFINE(dvfs_srvc, DVFS, cbor_encode_dvfs_oppoint_req, + cbor_decode_dvfs_oppoint_rsp); + +int ssf_dvfs_set_oppoint(uint8_t opp) +{ + int ret = -SSF_ENODATA; + + if (opp >= dvfs_oppoint_DVFS_FREQ_HIGH_c && opp <= dvfs_oppoint_DVFS_FREQ_LOW_c) { + const uint8_t *rsp_pkt; + + int stat = stat_INTERNAL_ERROR_c; + + struct dvfs_oppoint_req dvfs_request = { + .dvfs_oppoint_req_data + .dvfs_oppoint_choice = opp, + }; + + struct dvfs_oppoint_rsp dvfs_response; + + ret = ssf_client_send_request(&dvfs_srvc, &dvfs_request, + &dvfs_response, &rsp_pkt); + if (ret == 0) { + if (dvfs_response.dvfs_oppoint_rsp_status.stat_choice == + stat_SUCCESS_c) { + stat = dvfs_response.dvfs_oppoint_rsp_status.stat_choice; + if (stat == stat_SUCCESS_c) { + printk("DVFS scaling done, new frequency setting %d\n", + dvfs_response.dvfs_oppoint_rsp_data + .dvfs_oppoint_choice); + ret = 0; + } else { + ret = -SSF_EPROTO; + } + } else { + ret = -SSF_EBADMSG; + } + + ssf_client_decode_done(rsp_pkt); + } + } + + return ret; +} diff --git a/subsys/sdfw_services/services/dvfs/dvfs_service.cddl b/subsys/sdfw_services/services/dvfs/dvfs_service.cddl new file mode 100644 index 000000000000..013b75c240d8 --- /dev/null +++ b/subsys/sdfw_services/services/dvfs/dvfs_service.cddl @@ -0,0 +1,28 @@ +; +; Copyright (c) 2024 Nordic Semiconductor ASA +; +; SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +; + +; .. include_startingpoint_dvfs_cddl_rst + +stat = (SUCCESS: 0) / + (INTERNAL_ERROR: 16781313) + +dvfs_oppoint = (DVFS_FREQ_HIGH: 0) / + (DVFS_FREQ_MEDLOW: 1) / + (DVFS_FREQ_LOW: 2) + +dvfs_oppoint_req = ( + 1, + data: dvfs_oppoint, +) + +; DVFS service response. +dvfs_oppoint_rsp = ( + 1, + data: dvfs_oppoint, + status: stat, +) + +; .. include_endingpoint_dvfs_cddl_rst diff --git a/subsys/sdfw_services/services/dvfs/zcbor_generated/CMakeLists.txt b/subsys/sdfw_services/services/dvfs/zcbor_generated/CMakeLists.txt new file mode 100644 index 000000000000..19635917408a --- /dev/null +++ b/subsys/sdfw_services/services/dvfs/zcbor_generated/CMakeLists.txt @@ -0,0 +1,16 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# +# Generated using cmake macro generate_and_add_cbor_files. +# + +zephyr_sources( + dvfs_service_decode.c + dvfs_service_encode.c +) + +zephyr_include_directories(.) diff --git a/subsys/sdfw_services/services/dvfs/zcbor_generated/dvfs_service_decode.c b/subsys/sdfw_services/services/dvfs/zcbor_generated/dvfs_service_decode.c new file mode 100644 index 000000000000..d97e4f62996f --- /dev/null +++ b/subsys/sdfw_services/services/dvfs/zcbor_generated/dvfs_service_decode.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* + * Generated using zcbor version 0.9.1 + * https://github.com/NordicSemiconductor/zcbor + * Generated with a --default-max-qty of 3 + */ + +#include +#include +#include +#include +#include "zcbor_decode.h" +#include "dvfs_service_decode.h" +#include "zcbor_print.h" + +#if DEFAULT_MAX_QTY != 3 +#error "The type file was generated with a different default_max_qty than this file" +#endif + +#define log_result(state, result, func) \ + do { \ + if (!result) { \ + zcbor_trace_file(state); \ + zcbor_log("%s error: %s\r\n", func, \ + zcbor_error_str(zcbor_peek_error(state))); \ + } else { \ + zcbor_log("%s success\r\n", func); \ + } \ + } while (0) + +static bool decode_dvfs_oppoint(zcbor_state_t *state, struct dvfs_oppoint_r *result); +static bool decode_stat(zcbor_state_t *state, struct stat_r *result); +static bool decode_dvfs_oppoint_rsp(zcbor_state_t *state, struct dvfs_oppoint_rsp *result); +static bool decode_dvfs_oppoint_req(zcbor_state_t *state, struct dvfs_oppoint_req *result); + +static bool decode_dvfs_oppoint(zcbor_state_t *state, struct dvfs_oppoint_r *result) +{ + zcbor_log("%s\r\n", __func__); + + bool res = (( + (((zcbor_uint_decode(state, &(*result).dvfs_oppoint_choice, + sizeof((*result).dvfs_oppoint_choice)))) && + ((((((*result).dvfs_oppoint_choice == dvfs_oppoint_DVFS_FREQ_HIGH_c) && ((1))) || + (((*result).dvfs_oppoint_choice == dvfs_oppoint_DVFS_FREQ_MEDLOW_c) && ((1))) || + (((*result).dvfs_oppoint_choice == dvfs_oppoint_DVFS_FREQ_LOW_c) && ((1)))) || + (zcbor_error(state, ZCBOR_ERR_WRONG_VALUE), false)))))); + + log_result(state, res, __func__); + return res; +} + +static bool decode_stat(zcbor_state_t *state, struct stat_r *result) +{ + zcbor_log("%s\r\n", __func__); + + bool res = (((((zcbor_uint_decode(state, &(*result).stat_choice, + sizeof((*result).stat_choice)))) && + ((((((*result).stat_choice == stat_SUCCESS_c) && ((1))) || + (((*result).stat_choice == stat_INTERNAL_ERROR_c) && ((1)))) || + (zcbor_error(state, ZCBOR_ERR_WRONG_VALUE), false)))))); + + log_result(state, res, __func__); + return res; +} + +static bool decode_dvfs_oppoint_rsp(zcbor_state_t *state, struct dvfs_oppoint_rsp *result) +{ + zcbor_log("%s\r\n", __func__); + + bool res = (((((zcbor_uint32_expect(state, (1)))) && + ((decode_dvfs_oppoint(state, (&(*result).dvfs_oppoint_rsp_data)))) && + ((decode_stat(state, (&(*result).dvfs_oppoint_rsp_status))))))); + + log_result(state, res, __func__); + return res; +} + +static bool decode_dvfs_oppoint_req(zcbor_state_t *state, struct dvfs_oppoint_req *result) +{ + zcbor_log("%s\r\n", __func__); + + bool res = (((((zcbor_uint32_expect(state, (1)))) && + ((decode_dvfs_oppoint(state, (&(*result).dvfs_oppoint_req_data))))))); + + log_result(state, res, __func__); + return res; +} + +int cbor_decode_dvfs_oppoint_req(const uint8_t *payload, size_t payload_len, + struct dvfs_oppoint_req *result, size_t *payload_len_out) +{ + zcbor_state_t states[3]; + + return zcbor_entry_function(payload, payload_len, (void *)result, payload_len_out, states, + (zcbor_decoder_t *)decode_dvfs_oppoint_req, + sizeof(states) / sizeof(zcbor_state_t), 2); +} + +int cbor_decode_dvfs_oppoint_rsp(const uint8_t *payload, size_t payload_len, + struct dvfs_oppoint_rsp *result, size_t *payload_len_out) +{ + zcbor_state_t states[3]; + + return zcbor_entry_function(payload, payload_len, (void *)result, payload_len_out, states, + (zcbor_decoder_t *)decode_dvfs_oppoint_rsp, + sizeof(states) / sizeof(zcbor_state_t), 3); +} diff --git a/subsys/sdfw_services/services/dvfs/zcbor_generated/dvfs_service_decode.h b/subsys/sdfw_services/services/dvfs/zcbor_generated/dvfs_service_decode.h new file mode 100644 index 000000000000..b6e72b69099a --- /dev/null +++ b/subsys/sdfw_services/services/dvfs/zcbor_generated/dvfs_service_decode.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* + * Generated using zcbor version 0.9.1 + * https://github.com/NordicSemiconductor/zcbor + * Generated with a --default-max-qty of 3 + */ + +#ifndef DVFS_SERVICE_DECODE_H__ +#define DVFS_SERVICE_DECODE_H__ + +#include +#include +#include +#include +#include "dvfs_service_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if DEFAULT_MAX_QTY != 3 +#error "The type file was generated with a different default_max_qty than this file" +#endif + +int cbor_decode_dvfs_oppoint_req(const uint8_t *payload, size_t payload_len, + struct dvfs_oppoint_req *result, size_t *payload_len_out); + +int cbor_decode_dvfs_oppoint_rsp(const uint8_t *payload, size_t payload_len, + struct dvfs_oppoint_rsp *result, size_t *payload_len_out); + +#ifdef __cplusplus +} +#endif + +#endif /* DVFS_SERVICE_DECODE_H__ */ diff --git a/subsys/sdfw_services/services/dvfs/zcbor_generated/dvfs_service_encode.c b/subsys/sdfw_services/services/dvfs/zcbor_generated/dvfs_service_encode.c new file mode 100644 index 000000000000..14bf7c376f44 --- /dev/null +++ b/subsys/sdfw_services/services/dvfs/zcbor_generated/dvfs_service_encode.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* + * Generated using zcbor version 0.9.1 + * https://github.com/NordicSemiconductor/zcbor + * Generated with a --default-max-qty of 3 + */ + +#include +#include +#include +#include +#include "zcbor_encode.h" +#include "dvfs_service_encode.h" +#include "zcbor_print.h" + +#if DEFAULT_MAX_QTY != 3 +#error "The type file was generated with a different default_max_qty than this file" +#endif + +#define log_result(state, result, func) \ + do { \ + if (!result) { \ + zcbor_trace_file(state); \ + zcbor_log("%s error: %s\r\n", func, \ + zcbor_error_str(zcbor_peek_error(state))); \ + } else { \ + zcbor_log("%s success\r\n", func); \ + } \ + } while (0) + +static bool encode_dvfs_oppoint(zcbor_state_t *state, const struct dvfs_oppoint_r *input); +static bool encode_stat(zcbor_state_t *state, const struct stat_r *input); +static bool encode_dvfs_oppoint_rsp(zcbor_state_t *state, const struct dvfs_oppoint_rsp *input); +static bool encode_dvfs_oppoint_req(zcbor_state_t *state, const struct dvfs_oppoint_req *input); + +static bool encode_dvfs_oppoint(zcbor_state_t *state, const struct dvfs_oppoint_r *input) +{ + zcbor_log("%s\r\n", __func__); + + bool res = (( + (((*input).dvfs_oppoint_choice == dvfs_oppoint_DVFS_FREQ_HIGH_c) ? + ((zcbor_uint32_put(state, (0)))) : + (((*input).dvfs_oppoint_choice == dvfs_oppoint_DVFS_FREQ_MEDLOW_c) ? + ((zcbor_uint32_put(state, (1)))) : + (((*input).dvfs_oppoint_choice == dvfs_oppoint_DVFS_FREQ_LOW_c) ? + ((zcbor_uint32_put(state, (2)))) : + false))))); + + log_result(state, res, __func__); + return res; +} + +static bool encode_stat(zcbor_state_t *state, const struct stat_r *input) +{ + zcbor_log("%s\r\n", __func__); + + bool res = (((((*input).stat_choice == stat_SUCCESS_c) ? + ((zcbor_uint32_put(state, (0)))) : + (((*input).stat_choice == stat_INTERNAL_ERROR_c) ? + ((zcbor_uint32_put(state, (16781313)))) : + false)))); + + log_result(state, res, __func__); + return res; +} + +static bool encode_dvfs_oppoint_rsp(zcbor_state_t *state, const struct dvfs_oppoint_rsp *input) +{ + zcbor_log("%s\r\n", __func__); + + bool res = (((((zcbor_uint32_put(state, (1)))) && + ((encode_dvfs_oppoint(state, (&(*input).dvfs_oppoint_rsp_data)))) && + ((encode_stat(state, (&(*input).dvfs_oppoint_rsp_status))))))); + + log_result(state, res, __func__); + return res; +} + +static bool encode_dvfs_oppoint_req(zcbor_state_t *state, const struct dvfs_oppoint_req *input) +{ + zcbor_log("%s\r\n", __func__); + + bool res = (((((zcbor_uint32_put(state, (1)))) && + ((encode_dvfs_oppoint(state, (&(*input).dvfs_oppoint_req_data))))))); + + log_result(state, res, __func__); + return res; +} + +int cbor_encode_dvfs_oppoint_req(uint8_t *payload, size_t payload_len, + const struct dvfs_oppoint_req *input, size_t *payload_len_out) +{ + zcbor_state_t states[3]; + + return zcbor_entry_function(payload, payload_len, (void *)input, payload_len_out, states, + (zcbor_decoder_t *)encode_dvfs_oppoint_req, + sizeof(states) / sizeof(zcbor_state_t), 2); +} + +int cbor_encode_dvfs_oppoint_rsp(uint8_t *payload, size_t payload_len, + const struct dvfs_oppoint_rsp *input, size_t *payload_len_out) +{ + zcbor_state_t states[3]; + + return zcbor_entry_function(payload, payload_len, (void *)input, payload_len_out, states, + (zcbor_decoder_t *)encode_dvfs_oppoint_rsp, + sizeof(states) / sizeof(zcbor_state_t), 3); +} diff --git a/subsys/sdfw_services/services/dvfs/zcbor_generated/dvfs_service_encode.h b/subsys/sdfw_services/services/dvfs/zcbor_generated/dvfs_service_encode.h new file mode 100644 index 000000000000..c453db77419a --- /dev/null +++ b/subsys/sdfw_services/services/dvfs/zcbor_generated/dvfs_service_encode.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* + * Generated using zcbor version 0.9.1 + * https://github.com/NordicSemiconductor/zcbor + * Generated with a --default-max-qty of 3 + */ + +#ifndef DVFS_SERVICE_ENCODE_H__ +#define DVFS_SERVICE_ENCODE_H__ + +#include +#include +#include +#include +#include "dvfs_service_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if DEFAULT_MAX_QTY != 3 +#error "The type file was generated with a different default_max_qty than this file" +#endif + +int cbor_encode_dvfs_oppoint_req(uint8_t *payload, size_t payload_len, + const struct dvfs_oppoint_req *input, size_t *payload_len_out); + +int cbor_encode_dvfs_oppoint_rsp(uint8_t *payload, size_t payload_len, + const struct dvfs_oppoint_rsp *input, size_t *payload_len_out); + +#ifdef __cplusplus +} +#endif + +#endif /* DVFS_SERVICE_ENCODE_H__ */ diff --git a/subsys/sdfw_services/services/dvfs/zcbor_generated/dvfs_service_types.h b/subsys/sdfw_services/services/dvfs/zcbor_generated/dvfs_service_types.h new file mode 100644 index 000000000000..c0d453621d70 --- /dev/null +++ b/subsys/sdfw_services/services/dvfs/zcbor_generated/dvfs_service_types.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* + * Generated using zcbor version 0.9.1 + * https://github.com/NordicSemiconductor/zcbor + * Generated with a --default-max-qty of 3 + */ + +#ifndef DVFS_SERVICE_TYPES_H__ +#define DVFS_SERVICE_TYPES_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Which value for --default-max-qty this file was created with. + * + * The define is used in the other generated file to do a build-time + * compatibility check. + * + * See `zcbor --help` for more information about --default-max-qty + */ +#define DEFAULT_MAX_QTY 3 + +struct dvfs_oppoint_r { + enum { + dvfs_oppoint_DVFS_FREQ_HIGH_c = 0, + dvfs_oppoint_DVFS_FREQ_MEDLOW_c = 1, + dvfs_oppoint_DVFS_FREQ_LOW_c = 2, + } dvfs_oppoint_choice; +}; + +struct dvfs_oppoint_req { + struct dvfs_oppoint_r dvfs_oppoint_req_data; +}; + +struct stat_r { + enum { + stat_SUCCESS_c = 0, + stat_INTERNAL_ERROR_c = 16781313, + } stat_choice; +}; + +struct dvfs_oppoint_rsp { + struct dvfs_oppoint_r dvfs_oppoint_rsp_data; + struct stat_r dvfs_oppoint_rsp_status; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* DVFS_SERVICE_TYPES_H__ */ diff --git a/west.yml b/west.yml index 749630c005ee..334833fce97e 100644 --- a/west.yml +++ b/west.yml @@ -65,7 +65,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: e48bca44dd596dc66d71378e97bf5ceff2c483d0 + revision: pull/2818/head import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above