diff --git a/module/dvfs/src/mod_dvfs.c b/module/dvfs/src/mod_dvfs.c index fc974df591611ac11f68d39ec23b0a83dc063e46..af29fc57db1e5a602a6221eec8cb3d5996b6784d 100644 --- a/module/dvfs/src/mod_dvfs.c +++ b/module/dvfs/src/mod_dvfs.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -505,6 +506,7 @@ static int dvfs_set_frequency(fwk_id_t domain_id, uintptr_t cookie, { struct mod_dvfs_domain_ctx *ctx; const struct mod_dvfs_opp *new_opp; + unsigned int interrupt; ctx = get_domain_ctx(domain_id); if (ctx == NULL) @@ -526,6 +528,10 @@ static int dvfs_set_frequency(fwk_id_t domain_id, uintptr_t cookie, (new_opp->voltage == ctx->current_opp.voltage)) return FWK_SUCCESS; + if (fwk_interrupt_get_current(&interrupt) == FWK_SUCCESS) + ctx->request.set_source_id = true; + else + ctx->request.set_source_id = false; return dvfs_set_frequency_start(ctx, cookie, new_opp, false, 0); } @@ -534,6 +540,7 @@ static int dvfs_set_frequency_limits(fwk_id_t domain_id, { struct mod_dvfs_domain_ctx *ctx; const struct mod_dvfs_opp *new_opp; + unsigned int interrupt; ctx = get_domain_ctx(domain_id); if (ctx == NULL) @@ -564,6 +571,10 @@ static int dvfs_set_frequency_limits(fwk_id_t domain_id, new_opp, true); } + if (fwk_interrupt_get_current(&interrupt) == FWK_SUCCESS) + ctx->request.set_source_id = true; + else + ctx->request.set_source_id = false; return dvfs_set_frequency_start(ctx, cookie, new_opp, true, 0); } diff --git a/module/scmi_perf/include/internal/scmi_perf.h b/module/scmi_perf/include/internal/scmi_perf.h index 6f5f63c721ef7a254e4011b8744a627e521e78f6..6321ec31e957a67acb66ef93d6cd5739f310c66b 100644 --- a/module/scmi_perf/include/internal/scmi_perf.h +++ b/module/scmi_perf/include/internal/scmi_perf.h @@ -14,7 +14,11 @@ #include #define SCMI_PROTOCOL_ID_PERF UINT32_C(0x13) +#ifdef BUILD_HAS_FAST_CHANNELS +#define SCMI_PROTOCOL_VERSION_PERF UINT32_C(0x20000) +#else #define SCMI_PROTOCOL_VERSION_PERF UINT32_C(0x10000) +#endif #define SCMI_PERF_SUPPORTS_STATS_SHARED_MEM_REGION 0 #define SCMI_PERF_STATS_SHARED_MEM_REGION_ADDR_LOW 0 @@ -33,7 +37,8 @@ enum scmi_perf_command_id { SCMI_PERF_LEVEL_SET = 0x007, SCMI_PERF_LEVEL_GET = 0x008, SCMI_PERF_NOTIFY_LIMITS = 0x009, - SCMI_PERF_NOTIFY_LEVEL = 0x00A + SCMI_PERF_NOTIFY_LEVEL = 0x00A, + SCMI_PERF_DESCRIBE_FAST_CHANNEL = 0x00B, }; enum scmi_perf_notification_id { @@ -77,6 +82,7 @@ struct __attribute((packed)) scmi_perf_protocol_attributes_p2a { #define SCMI_PERF_DOMAIN_ATTRIBUTES_CAN_SET_LEVEL_POS 30 #define SCMI_PERF_DOMAIN_ATTRIBUTES_LIMITS_NOTIFY_POS 29 #define SCMI_PERF_DOMAIN_ATTRIBUTES_LEVEL_NOTIFY_POS 28 +#define SCMI_PERF_DOMAIN_ATTRIBUTES_FAST_CHANNEL_POS 27 #define SCMI_PERF_DOMAIN_ATTRIBUTES_CAN_SET_LIMITS_MASK \ (UINT32_C(0x1) << SCMI_PERF_DOMAIN_ATTRIBUTES_CAN_SET_LIMITS_POS) @@ -88,8 +94,17 @@ struct __attribute((packed)) scmi_perf_protocol_attributes_p2a { #define SCMI_PERF_DOMAIN_ATTRIBUTES_LEVEL_NOTIFY_MASK \ (UINT32_C(0x1) << SCMI_PERF_DOMAIN_ATTRIBUTES_LEVEL_NOTIFY_POS) +#define SCMI_PERF_FC_MIN_RATE_LIMIT 4000 + +#define SCMI_PERF_DOMAIN_ATTRIBUTES_FAST_CHANNEL_MASK \ + (UINT32_C(0x1) << SCMI_PERF_DOMAIN_ATTRIBUTES_FAST_CHANNEL_POS) + +#define SCMI_PERF_DOMAIN_ATTRIBUTES_FAST_CHANNEL_MASK \ + (UINT32_C(0x1) << SCMI_PERF_DOMAIN_ATTRIBUTES_FAST_CHANNEL_POS) + #define SCMI_PERF_DOMAIN_ATTRIBUTES(LEVEL_NOTIFY, LIMITS_NOTIFY, \ - CAN_SET_LEVEL, CAN_SET_LIMITS) \ + CAN_SET_LEVEL, CAN_SET_LIMITS, \ + FAST_CHANNEL) \ ( \ (((LEVEL_NOTIFY) << \ SCMI_PERF_DOMAIN_ATTRIBUTES_LEVEL_NOTIFY_POS) & \ @@ -102,7 +117,10 @@ struct __attribute((packed)) scmi_perf_protocol_attributes_p2a { SCMI_PERF_DOMAIN_ATTRIBUTES_CAN_SET_LEVEL_MASK) | \ (((CAN_SET_LIMITS) << \ SCMI_PERF_DOMAIN_ATTRIBUTES_CAN_SET_LIMITS_POS) & \ - SCMI_PERF_DOMAIN_ATTRIBUTES_CAN_SET_LIMITS_MASK) \ + SCMI_PERF_DOMAIN_ATTRIBUTES_CAN_SET_LIMITS_MASK) | \ + (((FAST_CHANNEL) << \ + SCMI_PERF_DOMAIN_ATTRIBUTES_FAST_CHANNEL_POS) & \ + SCMI_PERF_DOMAIN_ATTRIBUTES_FAST_CHANNEL_MASK) \ ) struct __attribute((packed)) scmi_perf_domain_attributes_a2p { @@ -269,4 +287,29 @@ struct __attribute((packed)) scmi_perf_limits_changed { uint32_t range_min; uint32_t range_max; }; + +/* + * PERFORMANCE_DESCRIBE_FASTCHANNEL + */ + +struct __attribute((packed)) scmi_perf_describe_fc_a2p { + uint32_t domain_id; + uint32_t message_id; +}; + +struct __attribute((packed)) scmi_perf_describe_fc_p2a { + int32_t status; + uint32_t attributes; + uint32_t rate_limit; + uint32_t chan_addr_low; + uint32_t chan_addr_high; + uint32_t chan_size; + uint32_t doorbell_addr_low; + uint32_t doorbell_addr_high; + uint32_t doorbell_set_mask_low; + uint32_t doorbell_set_mask_high; + uint32_t doorbell_preserve_mask_low; + uint32_t doorbell_preserve_mask_high; +}; + #endif /* INTERNAL_SCMI_PERF_H */ diff --git a/module/scmi_perf/include/mod_scmi_perf.h b/module/scmi_perf/include/mod_scmi_perf.h index 070bf67b9b0965e4f874c58a42b26be87cb0dcdb..bbb23c638d1f578fb6002051149aec26cdb7badf 100644 --- a/module/scmi_perf/include/mod_scmi_perf.h +++ b/module/scmi_perf/include/mod_scmi_perf.h @@ -12,6 +12,7 @@ #define MOD_SCMI_PERF_H #include +#include #include #include @@ -45,6 +46,42 @@ enum mod_scmi_perf_permissions { */ struct mod_scmi_perf_domain_config { const uint32_t (*permissions)[]; /*!< Per-agent permission flags */ + + /*! + * \brief Domain fast channels. + * + * \details Platform Domain fast channel address + * + * \note May be set to 0x0, in which case support for fast + * channels is disabled for the platform. + */ + uint64_t fast_channels_addr_scp; + + /*! + * \brief Agent Domain fast channel address + * + * \details Address of shared memory for the agent + */ + uint64_t fast_channels_addr_ap; + + /*! + * \brief Rate limit in microsecs + */ + uint32_t fast_channels_rate_limit; +}; + +/*! + *\brief Domain Fast Channel + * + *\note Layout of the Per-Domain Fast Channel in shared memory. + */ +struct mod_scmi_perf_fast_channel { + FWK_R uint32_t set_level; /*!< Performance level to be set */ + FWK_R uint32_t set_limit_range_max; /*!< max limit to be set */ + FWK_R uint32_t set_limit_range_min; /*!< min limit to be set */ + FWK_W uint32_t get_level; /*!< Current performance level */ + FWK_W uint32_t get_limit_range_max; /*!< Current limits, max */ + FWK_W uint32_t get_limit_range_min; /*!< Current limits, min */ }; /*! @@ -53,6 +90,18 @@ struct mod_scmi_perf_domain_config { struct mod_scmi_perf_config { /*! Per-domain configuration data */ const struct mod_scmi_perf_domain_config (*domains)[]; + + /*! + * \brief Fast Channels Alarm ID + * + * \details The Fast Channel alarm triggers the callback which + * polls the fast channels and initiates the set_level and + * set_limits operations. + */ + fwk_id_t fast_channels_alarm_id; + + /*! Fast Channel polling rate */ + uint32_t fast_channels_rate_limit; }; /*! diff --git a/module/scmi_perf/src/mod_scmi_perf.c b/module/scmi_perf/src/mod_scmi_perf.c index ea106506c2abf155544aec819fc5ab9edd260993..d38b0e8bbc28a380b0b62c29e10575227261ef3a 100644 --- a/module/scmi_perf/src/mod_scmi_perf.c +++ b/module/scmi_perf/src/mod_scmi_perf.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,8 @@ static int scmi_perf_limits_set_handler( fwk_id_t service_id, const uint32_t *payload); static int scmi_perf_limits_get_handler( fwk_id_t service_id, const uint32_t *payload); +static int scmi_perf_describe_fast_channels( + fwk_id_t service_id, const uint32_t *payload); static int scmi_perf_limits_notify( fwk_id_t service_id, const uint32_t *payload); static int scmi_perf_level_notify( @@ -71,6 +74,8 @@ static int (*handler_table[])(fwk_id_t, const uint32_t *) = { scmi_perf_level_set_handler, [SCMI_PERF_LEVEL_GET] = scmi_perf_level_get_handler, + [SCMI_PERF_DESCRIBE_FAST_CHANNEL] = + scmi_perf_describe_fast_channels, [SCMI_PERF_NOTIFY_LIMITS] = scmi_perf_limits_notify, [SCMI_PERF_NOTIFY_LEVEL] = @@ -94,6 +99,8 @@ static unsigned int payload_size_table[] = { sizeof(struct scmi_perf_limits_set_a2p), [SCMI_PERF_LIMITS_GET] = sizeof(struct scmi_perf_limits_get_a2p), + [SCMI_PERF_DESCRIBE_FAST_CHANNEL] = + sizeof(struct scmi_perf_describe_fc_a2p), [SCMI_PERF_NOTIFY_LIMITS] = sizeof(struct scmi_perf_notify_limits_a2p), [SCMI_PERF_NOTIFY_LEVEL] = @@ -143,6 +150,15 @@ struct scmi_perf_ctx { /* Agent notifications table */ struct agent_notifications **agent_notifications; + + /* Alarm API for fast channels */ + const struct mod_timer_alarm_api *fc_alarm_api; + + /* Alarm for fast channels */ + fwk_id_t fast_channels_alarm_id; + + /* Fast Channels Polling Rate Limit */ + uint32_t fast_channels_rate_limit; }; static struct scmi_perf_ctx scmi_perf_ctx; @@ -215,11 +231,17 @@ static int scmi_perf_protocol_message_attributes_handler(fwk_id_t service_id, (handler_table[parameters->message_id] != NULL)) { return_values = (struct scmi_protocol_message_attributes_p2a) { .status = SCMI_SUCCESS, - .attributes = 0, /* All commands have an attributes value of 0 */ }; } else return_values.status = SCMI_NOT_FOUND; + return_values.attributes = 0; +#ifdef BUILD_HAS_FAST_CHANNELS + if ((parameters->message_id <= SCMI_PERF_LEVEL_GET) && + (parameters->message_id >= SCMI_PERF_LIMITS_SET)) + return_values.attributes = 1; /* Fast Channel available */ +#endif + scmi_perf_ctx.scmi_api->respond(service_id, &return_values, (return_values.status == SCMI_SUCCESS) ? sizeof(return_values) : sizeof(return_values.status)); @@ -241,6 +263,7 @@ static int scmi_perf_domain_attributes_handler(fwk_id_t service_id, .status = SCMI_GENERIC_ERROR, }; bool notifications = false; + bool fast_channels = false; parameters = (const struct scmi_perf_domain_attributes_a2p *)payload; @@ -266,13 +289,17 @@ static int scmi_perf_domain_attributes_handler(fwk_id_t service_id, #ifdef BUILD_HAS_SCMI_NOTIFICATIONS notifications = true; +#endif +#ifdef BUILD_HAS_FAST_CHANNELS + fast_channels = true; #endif return_values = (struct scmi_perf_domain_attributes_p2a) { .status = SCMI_SUCCESS, .attributes = SCMI_PERF_DOMAIN_ATTRIBUTES( notifications, notifications, !!(permissions & MOD_SCMI_PERF_PERMS_SET_LEVEL), - !!(permissions & MOD_SCMI_PERF_PERMS_SET_LIMITS) + !!(permissions & MOD_SCMI_PERF_PERMS_SET_LIMITS), + fast_channels ), .rate_limit = 0, /* Unsupported */ .sustained_freq = opp.frequency / FWK_KHZ, @@ -695,6 +722,8 @@ static int scmi_perf_level_notify(fwk_id_t service_id, goto exit; } + id = parameters->domain_id; + status = scmi_perf_ctx.scmi_api->get_agent_id(service_id, &agent_id); if (status != FWK_SUCCESS) goto exit; @@ -716,6 +745,122 @@ exit: return status; } +/* + * Note that the Fast Channel doorbell is not supported in this + * implementation. + */ +static int scmi_perf_describe_fast_channels(fwk_id_t service_id, + const uint32_t *payload) +{ + const struct mod_scmi_perf_domain_config *domain; + const struct scmi_perf_describe_fc_a2p *parameters; + struct scmi_perf_describe_fc_p2a return_values = { + .status = SCMI_GENERIC_ERROR, + }; + uint32_t chan_size, chan_offset; + + parameters = (const struct scmi_perf_describe_fc_a2p *)payload; + + /* Validate the domain identifier */ + if (parameters->domain_id >= scmi_perf_ctx.domain_count) { + return_values.status = SCMI_NOT_FOUND; + + goto exit; + } + + domain = &(*scmi_perf_ctx.config->domains)[parameters->domain_id]; + + fwk_assert(domain->fast_channels_addr_scp != 0x0); + + switch (parameters->message_id) { + case SCMI_PERF_LEVEL_GET: + chan_offset = offsetof(struct mod_scmi_perf_fast_channel, get_level); + chan_size = sizeof(uint32_t); + break; + + case SCMI_PERF_LEVEL_SET: + chan_offset = offsetof(struct mod_scmi_perf_fast_channel, set_level); + chan_size = sizeof(uint32_t); + break; + + case SCMI_PERF_LIMITS_SET: + chan_offset = offsetof(struct mod_scmi_perf_fast_channel, + set_limit_range_max); + chan_size = sizeof(uint32_t) * 2; + break; + + case SCMI_PERF_LIMITS_GET: + chan_offset = offsetof(struct mod_scmi_perf_fast_channel, + get_limit_range_max); + chan_size = sizeof(uint32_t) * 2; + break; + + default: + return_values.status = SCMI_NOT_SUPPORTED; + goto exit; + + } + + return_values.status = SCMI_SUCCESS; + return_values.attributes = 0; /* Doorbell not supported */ + return_values.rate_limit = scmi_perf_ctx.fast_channels_rate_limit; + return_values.chan_addr_low = (uint32_t) + (domain->fast_channels_addr_ap & ~0UL) + chan_offset; + return_values.chan_addr_high = + (domain->fast_channels_addr_ap >> 32); + return_values.chan_size = chan_size; + +exit: + scmi_perf_ctx.scmi_api->respond(service_id, &return_values, + (return_values.status == SCMI_SUCCESS) ? + sizeof(return_values) : sizeof(return_values.status)); + + return FWK_SUCCESS; +} + +/* + * Fast Channel Polling + */ +static void fast_channel_callback(uintptr_t param) +{ + const struct mod_scmi_perf_domain_config *domain; + struct mod_scmi_perf_fast_channel *fc; + unsigned int i; + + for (i = 0; i < scmi_perf_ctx.domain_count; i++) { + domain = &(*scmi_perf_ctx.config->domains)[i]; + if (domain->fast_channels_addr_scp != 0x0) { + fc = (struct mod_scmi_perf_fast_channel *) + ((uintptr_t)domain->fast_channels_addr_scp); + /* + * Check for set_level/set_limits request + */ + if ((fc->set_level == 0) && (fc->set_limit_range_max == 0) && + (fc->set_limit_range_min == 0)) + continue; + + if (fc->set_level == fc->get_level) { + if ((fc->set_limit_range_max == fc->get_limit_range_max) && + (fc->set_limit_range_min == fc->get_limit_range_min)) + continue; + if ((fc->set_limit_range_max == 0) && + (fc->set_limit_range_min == 0)) + continue; + scmi_perf_ctx.dvfs_api->set_frequency_limits( + FWK_ID_ELEMENT(FWK_MODULE_IDX_DVFS, i), + 0, &((struct mod_dvfs_frequency_limits) { + .minimum = fc->set_limit_range_min, + .maximum = fc->set_limit_range_max, + })); + } else if (fc->set_level != 0) { + scmi_perf_ctx.dvfs_api->set_frequency( + FWK_ID_ELEMENT(FWK_MODULE_IDX_DVFS, i), + 0, (uint64_t)fc->set_level); + } + } + } +} + /* * SCMI module -> SCMI performance module interface */ @@ -795,10 +940,21 @@ static void scmi_perf_notify_limits(fwk_id_t domain_id, struct scmi_perf_limits_changed limits_changed; fwk_id_t id; int i, idx; + const struct mod_scmi_perf_domain_config *domain; + struct mod_scmi_perf_fast_channel *fc; idx = fwk_id_get_element_idx(domain_id); - limits_changed.agent_id = (uint32_t)cookie; + domain = &(*scmi_perf_ctx.config->domains)[idx]; + if (domain->fast_channels_addr_scp != 0x0) { + fc = (struct mod_scmi_perf_fast_channel *) + ((uintptr_t)domain->fast_channels_addr_scp); + fc->get_limit_range_max = range_max; + fc->get_limit_range_min = range_min; + } + + + limits_changed.agent_id = (uint32_t)cookie; /* note: skip agent 0, platform agent */ for (i = 1; i < scmi_perf_ctx.agent_count; i++) { id = @@ -822,8 +978,18 @@ static void scmi_perf_notify_level(fwk_id_t domain_id, struct scmi_perf_level_changed level_changed; fwk_id_t id; int i, idx; + const struct mod_scmi_perf_domain_config *domain; + struct mod_scmi_perf_fast_channel *fc; idx = fwk_id_get_element_idx(domain_id); + + domain = &(*scmi_perf_ctx.config->domains)[idx]; + if (domain->fast_channels_addr_scp != 0x0) { + fc = (struct mod_scmi_perf_fast_channel *) + ((uintptr_t)domain->fast_channels_addr_scp); + fc->get_level = level; + } + level_changed.agent_id = (uint32_t)cookie; /* note: skip agent 0, platform agent */ @@ -870,6 +1036,12 @@ static int scmi_perf_init(fwk_id_t module_id, unsigned int element_count, scmi_perf_ctx.config = config; scmi_perf_ctx.domain_count = return_val; + scmi_perf_ctx.fast_channels_alarm_id = config->fast_channels_alarm_id; + if (config->fast_channels_rate_limit < SCMI_PERF_FC_MIN_RATE_LIMIT) + scmi_perf_ctx.fast_channels_rate_limit = SCMI_PERF_FC_MIN_RATE_LIMIT; + else + scmi_perf_ctx.fast_channels_rate_limit = + config->fast_channels_rate_limit; /* Initialize table */ for (i = 0; i < return_val; i++) @@ -930,6 +1102,14 @@ static int scmi_perf_bind(fwk_id_t id, unsigned int round) if (status != FWK_SUCCESS) return status; + if (!fwk_id_is_equal(scmi_perf_ctx.config->fast_channels_alarm_id, + FWK_ID_NONE)) { + status = fwk_module_bind(scmi_perf_ctx.config->fast_channels_alarm_id, + MOD_TIMER_API_ID_ALARM, &scmi_perf_ctx.fc_alarm_api); + if (status != FWK_SUCCESS) + return FWK_E_PANIC; + } + return fwk_module_bind(FWK_ID_MODULE(FWK_MODULE_IDX_DVFS), FWK_ID_API(FWK_MODULE_IDX_DVFS, 0), &scmi_perf_ctx.dvfs_api); } @@ -953,6 +1133,45 @@ static int scmi_perf_process_bind_request(fwk_id_t source_id, return FWK_SUCCESS; } +static int scmi_perf_start(fwk_id_t id) +{ + int status = FWK_SUCCESS; + const struct mod_scmi_perf_domain_config *domain; + struct mod_scmi_perf_fast_channel *fc; + uint32_t fc_interval_msecs; + unsigned int i; + + /* + * Set up the Fast Channel polling if required + */ + if (!fwk_id_is_equal(scmi_perf_ctx.config->fast_channels_alarm_id, + FWK_ID_NONE)) { + if (scmi_perf_ctx.config->fast_channels_rate_limit < + SCMI_PERF_FC_MIN_RATE_LIMIT) + fc_interval_msecs = (uint32_t)SCMI_PERF_FC_MIN_RATE_LIMIT / 1000; + else + fc_interval_msecs = (uint32_t) + scmi_perf_ctx.config->fast_channels_rate_limit / 1000; + status = scmi_perf_ctx.fc_alarm_api->start( + scmi_perf_ctx.config->fast_channels_alarm_id, + fc_interval_msecs, MOD_TIMER_ALARM_TYPE_PERIODIC, + fast_channel_callback, (uintptr_t)0); + if (status != FWK_SUCCESS) + return status; + } + + for (i = 0; i < scmi_perf_ctx.domain_count; i++) { + domain = &(*scmi_perf_ctx.config->domains)[i]; + if (domain->fast_channels_addr_scp != 0x0) { + fc = (struct mod_scmi_perf_fast_channel *) + ((uintptr_t)domain->fast_channels_addr_scp); + memset((void *)fc, 0, sizeof(struct mod_scmi_perf_domain_config)); + } + } + + return status; +} + /* * Handle a request for get_level/limits. */ @@ -1081,6 +1300,7 @@ const struct fwk_module module_scmi_perf = { .type = FWK_MODULE_TYPE_PROTOCOL, .init = scmi_perf_init, .bind = scmi_perf_bind, + .start = scmi_perf_start, .process_bind_request = scmi_perf_process_bind_request, .process_event = scmi_perf_process_event, }; diff --git a/product/juno/include/juno_alarm_idx.h b/product/juno/include/juno_alarm_idx.h index b3f25259b8ab452ed0a73230593960da6a5fb339..42da185b0a882495e540cd2d8da90fd182d5ed18 100644 --- a/product/juno/include/juno_alarm_idx.h +++ b/product/juno/include/juno_alarm_idx.h @@ -25,6 +25,9 @@ enum juno_dvfs_alarm_idx { JUNO_DVFS_ALARM_VLITTLE_IDX = JUNO_XRP7724_ALARM_IDX_COUNT, JUNO_DVFS_ALARM_BIG_IDX, JUNO_DVFS_ALARM_GPU_IDX, +#ifdef BUILD_HAS_FAST_CHANNELS + JUNO_SCMI_FAST_CHANNEL_IDX, +#endif JUNO_DVFS_ALARM_IDX_CNT, }; diff --git a/product/juno/include/software_mmap.h b/product/juno/include/software_mmap.h index 55f60f4f30b376dc9010003e4b34bf1d750bcbc7..abaf37fd5e86b3394abef664551a7c8ea5073337 100644 --- a/product/juno/include/software_mmap.h +++ b/product/juno/include/software_mmap.h @@ -88,4 +88,9 @@ #define SCMI_PAYLOAD_HIGH_P2A_BASE (SCMI_PAYLOAD_HIGH_A2P_BASE + \ SCMI_PAYLOAD_SIZE) +/* SCMIv2 Fast Channels */ +#define SCMI_FAST_CHANNEL_BASE (SCMI_PAYLOAD_HIGH_P2A_BASE + \ + SCMI_PAYLOAD_SIZE) +#define SCMI_FAST_CHANNEL_SIZE (SCMI_PAYLOAD_SIZE) + #endif /* SOFTWARE_MMAP_H */ diff --git a/product/juno/scp_ramfw/config_scmi_perf.c b/product/juno/scp_ramfw/config_scmi_perf.c index 0674125851d0e16001eae9740dd9e345f9a21546..7b139414daddc5a9cec9c964402a7d619936b242 100644 --- a/product/juno/scp_ramfw/config_scmi_perf.c +++ b/product/juno/scp_ramfw/config_scmi_perf.c @@ -6,11 +6,18 @@ */ #include "config_dvfs.h" +#include "juno_alarm_idx.h" #include "juno_scmi.h" +#include "software_mmap.h" +#include #include +#include +#include +#include #include +#include #include #include @@ -21,21 +28,39 @@ static const struct mod_scmi_perf_domain_config domains[] = { [JUNO_SCMI_AGENT_IDX_OSPM] = MOD_SCMI_PERF_PERMS_SET_LEVEL | MOD_SCMI_PERF_PERMS_SET_LIMITS, [JUNO_SCMI_AGENT_IDX_PSCI] = 0 /* No Access */, - } + }, +#ifdef BUILD_HAS_FAST_CHANNELS + .fast_channels_addr_scp = SCMI_FAST_CHANNEL_BASE, + .fast_channels_addr_ap = SCMI_FAST_CHANNEL_BASE - EXTERNAL_DEV_BASE, +#endif }, [DVFS_ELEMENT_IDX_BIG] = { .permissions = &(const uint32_t[]) { [JUNO_SCMI_AGENT_IDX_OSPM] = MOD_SCMI_PERF_PERMS_SET_LEVEL | MOD_SCMI_PERF_PERMS_SET_LIMITS, [JUNO_SCMI_AGENT_IDX_PSCI] = 0 /* No Access */, - } + }, +#ifdef BUILD_HAS_FAST_CHANNELS + .fast_channels_addr_scp = SCMI_FAST_CHANNEL_BASE + + sizeof(struct mod_scmi_perf_fast_channel), + .fast_channels_addr_ap = SCMI_FAST_CHANNEL_BASE + + sizeof(struct mod_scmi_perf_fast_channel) - + EXTERNAL_DEV_BASE, +#endif }, [DVFS_ELEMENT_IDX_GPU] = { .permissions = &(const uint32_t[]) { [JUNO_SCMI_AGENT_IDX_OSPM] = MOD_SCMI_PERF_PERMS_SET_LEVEL | MOD_SCMI_PERF_PERMS_SET_LIMITS, [JUNO_SCMI_AGENT_IDX_PSCI] = 0 /* No Access */, - } + }, +#ifdef BUILD_HAS_FAST_CHANNELS + .fast_channels_addr_scp = SCMI_FAST_CHANNEL_BASE + + (sizeof(struct mod_scmi_perf_fast_channel) * 2), + .fast_channels_addr_ap = SCMI_FAST_CHANNEL_BASE + + (sizeof(struct mod_scmi_perf_fast_channel) * 2) - + EXTERNAL_DEV_BASE, +#endif }, }; @@ -44,5 +69,13 @@ struct fwk_module_config config_scmi_perf = { .get_element_table = NULL, .data = &((struct mod_scmi_perf_config) { .domains = &domains, +#ifdef BUILD_HAS_FAST_CHANNELS + .fast_channels_alarm_id = + FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_TIMER, 0, + JUNO_SCMI_FAST_CHANNEL_IDX), + .fast_channels_rate_limit = SCMI_PERF_FC_MIN_RATE_LIMIT, +#else + .fast_channels_alarm_id = FWK_ID_NONE_INIT, +#endif }), }; diff --git a/product/juno/scp_ramfw/firmware.mk b/product/juno/scp_ramfw/firmware.mk index d2e2d5ecf7b24c498b6d5800874b67dd1bb4a2d2..8ee542da8f52ecc4d894a9f72754e3452fe3e013 100644 --- a/product/juno/scp_ramfw/firmware.mk +++ b/product/juno/scp_ramfw/firmware.mk @@ -12,6 +12,7 @@ BS_FIRMWARE_CPU := cortex-m3 BS_FIRMWARE_HAS_MULTITHREADING := yes BS_FIRMWARE_HAS_NOTIFICATION := yes BS_FIRMWARE_HAS_SCMI_NOTIFICATIONS := no +BS_FIRMWARE_HAS_FAST_CHANNELS := no BS_FIRMWARE_MODULE_HEADERS_ONLY := diff --git a/product/rdn1e1/scp_ramfw/config_scmi_perf.c b/product/rdn1e1/scp_ramfw/config_scmi_perf.c index a5304b351a48c76e28362d08e9eea32e1ce8e2c0..9039f77bf5517e3b0fd18dded7ba17133f5b7cb6 100644 --- a/product/rdn1e1/scp_ramfw/config_scmi_perf.c +++ b/product/rdn1e1/scp_ramfw/config_scmi_perf.c @@ -35,5 +35,6 @@ const struct fwk_module_config config_scmi_perf = { .get_element_table = NULL, .data = &((struct mod_scmi_perf_config) { .domains = &domains, + .fast_channels_alarm_id = FWK_ID_NONE_INIT, }), }; diff --git a/product/sgi575/scp_ramfw/config_scmi_perf.c b/product/sgi575/scp_ramfw/config_scmi_perf.c index 842e5469ce40cb55770d58ae1fb0595f9a8253ca..de948e2cf7780469693b69b930f10698696b74aa 100644 --- a/product/sgi575/scp_ramfw/config_scmi_perf.c +++ b/product/sgi575/scp_ramfw/config_scmi_perf.c @@ -35,5 +35,6 @@ const struct fwk_module_config config_scmi_perf = { .get_element_table = NULL, .data = &((struct mod_scmi_perf_config) { .domains = &domains, + .fast_channels_alarm_id = FWK_ID_NONE_INIT, }), }; diff --git a/product/sgm775/scp_ramfw/config_scmi_perf.c b/product/sgm775/scp_ramfw/config_scmi_perf.c index f130573a831100af42102a0329b90334780a841c..12398d013fdbdb0751f752d6ed3d8dfb286e8db9 100644 --- a/product/sgm775/scp_ramfw/config_scmi_perf.c +++ b/product/sgm775/scp_ramfw/config_scmi_perf.c @@ -43,5 +43,6 @@ struct fwk_module_config config_scmi_perf = { .get_element_table = NULL, .data = &((struct mod_scmi_perf_config) { .domains = &domains, + .fast_channels_alarm_id = FWK_ID_NONE_INIT, }), }; diff --git a/product/sgm776/scp_ramfw/config_scmi_perf.c b/product/sgm776/scp_ramfw/config_scmi_perf.c index 3120b6e9fb52e8c88453ec77067c7b1154ced85d..1e58347b6218db241ed3bf50b278626b2fc68f42 100644 --- a/product/sgm776/scp_ramfw/config_scmi_perf.c +++ b/product/sgm776/scp_ramfw/config_scmi_perf.c @@ -41,5 +41,6 @@ static const struct mod_scmi_perf_domain_config domains[] = { const struct fwk_module_config config_scmi_perf = { .data = &((struct mod_scmi_perf_config) { .domains = &domains, + .fast_channels_alarm_id = FWK_ID_NONE_INIT, }), }; diff --git a/tools/build_system/doc.md b/tools/build_system/doc.md index e8d3253a7fe0e3247e948d10527f7305dc0fec76..94debba3cf21f18ba3c55d565c12fb1d959ad0f5 100644 --- a/tools/build_system/doc.md +++ b/tools/build_system/doc.md @@ -193,6 +193,12 @@ When notification support is enabled, the following applies: number of notification subscriptions supported and set to the value defined by BS_FIRMWARE_NOTIFICATION_COUNT parameter. +Fast Channels Support {#section_fast_channels} +===================== + +When building a firmware and its dependencies, the BS_FIRMWARE_HAS_FAST_CHANNELS +parameter controls whether DVFS Fast channel support is enabled or not. + SCMI Notifications Support {#section_scmi_notifications} ========================== diff --git a/tools/build_system/firmware.mk b/tools/build_system/firmware.mk index 205b40d1aee0d0efb8ba70b1140bbbc7c4733194..f1c8d9ef21aea6dd89b412c43df060bfd7787eb6 100644 --- a/tools/build_system/firmware.mk +++ b/tools/build_system/firmware.mk @@ -211,6 +211,12 @@ ifeq ($(BUILD_HAS_NOTIFICATION),yes) export BUILD_NOTIFICATION_COUNT endif +ifeq ($(BS_FIRMWARE_HAS_FAST_CHANNELS),yes) + BUILD_HAS_FAST_CHANNELS := yes +else + BUILD_HAS_FAST_CHANNELS := no +endif + ifeq ($(BS_FIRMWARE_HAS_SCMI_NOTIFICATIONS),yes) BUILD_HAS_SCMI_NOTIFICATIONS := yes else diff --git a/tools/build_system/rules.mk b/tools/build_system/rules.mk index 02b729c0d635e35951c23beb2ba8d8ae7e0e2698..fb883d11500f15f36083149ab8ca5d3e07642f5f 100644 --- a/tools/build_system/rules.mk +++ b/tools/build_system/rules.mk @@ -29,6 +29,10 @@ ifeq ($(BUILD_HAS_SCMI_NOTIFICATIONS),yes) DEFINES += BUILD_HAS_SCMI_NOTIFICATIONS endif +ifeq ($(BUILD_HAS_FAST_CHANNELS),yes) + DEFINES += BUILD_HAS_FAST_CHANNELS +endif + export AS := $(CC) export LD := $(CC)