diff options
author | Nicola Mazzucato <nicola.mazzucato@arm.com> | 2019-05-02 16:27:27 +0100 |
---|---|---|
committer | ronald-cron-arm <39518861+ronald-cron-arm@users.noreply.github.com> | 2019-06-04 12:00:40 +0200 |
commit | c22a0b8fd5b6b2b986ab211c057f29f9466320de (patch) | |
tree | 7fda571953abbca615028dadb99caa440d8c4330 /module/system_power | |
parent | 6970a1eb436bec5750ba3c335f837be956632470 (diff) |
system_power: Update module to a configurable number of system PPUs
This patch removes the constraint of a fixed number of
system PPUs by expanding the module to support an
adjustable number of elements.
Change-Id: Ic52c2751fa32e5e267e0940255af0b1a1fc570d1
Signed-off-by: Nicola Mazzucato <nicola.mazzucato@arm.com>
Diffstat (limited to 'module/system_power')
-rw-r--r-- | module/system_power/include/mod_system_power.h | 27 | ||||
-rw-r--r-- | module/system_power/src/mod_system_power.c | 242 |
2 files changed, 169 insertions, 100 deletions
diff --git a/module/system_power/include/mod_system_power.h b/module/system_power/include/mod_system_power.h index 45d5aa12..eb12d490 100644 --- a/module/system_power/include/mod_system_power.h +++ b/module/system_power/include/mod_system_power.h @@ -37,20 +37,26 @@ struct mod_system_power_ext_ppu_config { fwk_id_t api_id; }; +/*! Element configuration */ +struct mod_system_power_dev_config { + /*! Identifier of the system PPU */ + fwk_id_t sys_ppu_id; + + /*! System PPU API identifier */ + fwk_id_t api_id; + + /*! + * \brief Pointer to a table defining the power states this system PPU will + * be set for each system state. + */ + const uint8_t *sys_state_table; +}; + /*! Module configuration */ struct mod_system_power_config { /*! SoC wakeup IRQ number */ unsigned int soc_wakeup_irq; - /*! System 0 PPU element ID */ - fwk_id_t ppu_sys0_id; - - /*! System 1 PPU element ID */ - fwk_id_t ppu_sys1_id; - - /*! System PPUs API ID */ - fwk_id_t ppu_sys_api_id; - /*! Number of extended PPUs */ size_t ext_ppus_count; @@ -67,6 +73,9 @@ struct mod_system_power_config { /*! System shutdown driver API identifier */ fwk_id_t driver_api_id; + + /*! Initial System Power state after power-on */ + enum mod_pd_state initial_system_power_state; }; /*! Platform-specific interrupt commands indices */ diff --git a/module/system_power/src/mod_system_power.c b/module/system_power/src/mod_system_power.c index 26ba6a38..fbe980d6 100644 --- a/module/system_power/src/mod_system_power.c +++ b/module/system_power/src/mod_system_power.c @@ -32,16 +32,25 @@ static const fwk_id_t mod_system_power_soc_wakeup_pd_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_POWER_DOMAIN, 0); +/* Element context */ +struct system_power_dev_ctx { + /* Element configuration data pointer */ + const struct mod_system_power_dev_config *config; + + /* Power domain driver API pointer */ + const struct mod_pd_driver_api *sys_ppu_api; +}; + /* Module context */ struct system_power_ctx { /* Log API pointer */ const struct mod_log_api *log_api; - /* SYS0 power domain driver API pointer */ - const struct mod_pd_driver_api *sys0_api; + /* System power element context table */ + struct system_power_dev_ctx *dev_ctx_table; - /* SYS1 power domain driver API pointer*/ - const struct mod_pd_driver_api *sys1_api; + /* Number of elements */ + unsigned int dev_count; /* Pointer to array of extended PPU power domain driver APIs */ const struct mod_pd_driver_api **ext_ppu_apis; @@ -61,6 +70,9 @@ struct system_power_ctx { /* Current system-level power state */ unsigned int state; + /* Requested power state */ + unsigned int requested_state; + /* Pointer to module config */ const struct mod_system_power_config *config; }; @@ -82,6 +94,27 @@ static void ext_ppus_set_state(enum mod_pd_state state) } } +static int set_system_power_state(unsigned int state) +{ + int status; + unsigned int i; + struct system_power_dev_ctx *dev_ctx; + const uint8_t *sys_state_table; + + for (i = 0; i < system_power_ctx.dev_count; i++) { + dev_ctx = &system_power_ctx.dev_ctx_table[i]; + + sys_state_table = dev_ctx->config->sys_state_table; + + status = dev_ctx->sys_ppu_api->set_state(dev_ctx->config->sys_ppu_id, + sys_state_table[state]); + if (status != FWK_SUCCESS) + return status; + } + + return FWK_SUCCESS; +} + /* * Functions fulfilling the Power Domain module's driver API */ @@ -95,8 +128,13 @@ static int system_power_set_state(fwk_id_t pd_id, unsigned int state) if (status != FWK_SUCCESS) return status; + if (!fwk_expect(state < MOD_SYSTEM_POWER_POWER_STATE_COUNT)) + return FWK_E_PARAM; + soc_wakeup_irq = system_power_ctx.config->soc_wakeup_irq; + system_power_ctx.requested_state = state; + switch (state) { case MOD_PD_STATE_ON: fwk_interrupt_disable(soc_wakeup_irq); @@ -108,10 +146,9 @@ static int system_power_set_state(fwk_id_t pd_id, unsigned int state) return FWK_E_DEVICE; } - system_power_ctx.sys0_api->set_state( - system_power_ctx.config->ppu_sys0_id, MOD_PD_STATE_ON); - system_power_ctx.sys0_api->set_state( - system_power_ctx.config->ppu_sys1_id, MOD_PD_STATE_ON); + status = set_system_power_state(state); + if (status != FWK_SUCCESS) + return status; ext_ppus_set_state(MOD_PD_STATE_ON); @@ -130,10 +167,9 @@ static int system_power_set_state(fwk_id_t pd_id, unsigned int state) return FWK_E_DEVICE; } - system_power_ctx.sys0_api->set_state( - system_power_ctx.config->ppu_sys0_id, MOD_PD_STATE_OFF); - system_power_ctx.sys0_api->set_state( - system_power_ctx.config->ppu_sys1_id, MOD_PD_STATE_ON); + status = set_system_power_state(state); + if (status != FWK_SUCCESS) + return status; fwk_interrupt_enable(soc_wakeup_irq); @@ -158,10 +194,9 @@ static int system_power_set_state(fwk_id_t pd_id, unsigned int state) ext_ppus_set_state(MOD_PD_STATE_OFF); - system_power_ctx.sys0_api->set_state( - system_power_ctx.config->ppu_sys0_id, MOD_PD_STATE_OFF); - system_power_ctx.sys0_api->set_state( - system_power_ctx.config->ppu_sys1_id, MOD_PD_STATE_OFF); + status = set_system_power_state(state); + if (status != FWK_SUCCESS) + return status; break; @@ -224,31 +259,28 @@ static const struct mod_pd_driver_api system_power_power_domain_driver_api = { * Functions fulfilling the Power Domain module's driver input API */ -static int system_power_report_power_state_transition(fwk_id_t module_id, +static int system_power_report_power_state_transition(fwk_id_t dev_id, unsigned int state) { int status; - unsigned int sys0_state, sys1_state; + static unsigned int sys_ppu_transition_count = 0; - system_power_ctx.sys0_api->get_state(system_power_ctx.config->ppu_sys0_id, - &sys0_state); - system_power_ctx.sys1_api->get_state(system_power_ctx.config->ppu_sys1_id, - &sys1_state); + status = fwk_module_check_call(dev_id); + if (status != FWK_SUCCESS) + return status; - if ((sys0_state == MOD_PD_STATE_ON) && (sys1_state == MOD_PD_STATE_ON)) - system_power_ctx.state = MOD_PD_STATE_ON; - else if ((sys0_state == MOD_PD_STATE_OFF) && - (sys1_state == MOD_PD_STATE_ON)) - system_power_ctx.state = MOD_SYSTEM_POWER_POWER_STATE_SLEEP0; - else - system_power_ctx.state = MOD_PD_STATE_OFF; + sys_ppu_transition_count++; - status = - system_power_ctx.mod_pd_driver_input_api->report_power_state_transition( - system_power_ctx.mod_pd_system_id, system_power_ctx.state); - fwk_expect(status == FWK_SUCCESS); + if (sys_ppu_transition_count < system_power_ctx.dev_count) + return FWK_SUCCESS; - return FWK_SUCCESS; + system_power_ctx.state = system_power_ctx.requested_state; + + sys_ppu_transition_count = 0; + + return system_power_ctx.mod_pd_driver_input_api-> + report_power_state_transition(system_power_ctx.mod_pd_system_id, + system_power_ctx.state); } static const struct mod_pd_driver_input_api @@ -261,13 +293,22 @@ static const struct mod_pd_driver_input_api */ static int system_power_mod_init(fwk_id_t module_id, - unsigned int unused, + unsigned int element_count, const void *data) { + const struct mod_system_power_config *config; + fwk_assert(data != NULL); + fwk_expect(element_count > 0); - system_power_ctx.config = data; + system_power_ctx.config = config = data; system_power_ctx.mod_pd_system_id = FWK_ID_NONE; + system_power_ctx.dev_count = element_count; + + system_power_ctx.dev_ctx_table = + fwk_mm_calloc(element_count, sizeof(struct system_power_dev_ctx)); + if (system_power_ctx.dev_ctx_table == NULL) + return FWK_E_NOMEM; if (system_power_ctx.config->ext_ppus_count > 0) { system_power_ctx.ext_ppu_apis = fwk_mm_calloc( @@ -285,12 +326,37 @@ static int system_power_mod_init(fwk_id_t module_id, return FWK_SUCCESS; } +static int system_power_mod_element_init(fwk_id_t element_id, + unsigned int unused, + const void *data) +{ + struct system_power_dev_ctx *dev_ctx; + + fwk_assert(data != NULL); + + dev_ctx = + system_power_ctx.dev_ctx_table + fwk_id_get_element_idx(element_id); + + dev_ctx->config = data; + + /* Ensure a system state table is provided */ + if (dev_ctx->config->sys_state_table == NULL) + return FWK_E_DATA; + + return FWK_SUCCESS; +} + static int system_power_bind(fwk_id_t id, unsigned int round) { int status; unsigned int i; + const struct mod_system_power_config *config; + struct system_power_dev_ctx *dev_ctx; if (round == 1) { + if (!fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) + return FWK_SUCCESS; + /* * During the first round of binding, the power domain module should * have bound to the power domain driver API provided by the present @@ -303,50 +369,49 @@ static int system_power_bind(fwk_id_t id, unsigned int round) &system_power_ctx.mod_pd_driver_input_api); } - status = fwk_module_bind(FWK_ID_MODULE(FWK_MODULE_IDX_LOG), - FWK_ID_API(FWK_MODULE_IDX_LOG, 0), &system_power_ctx.log_api); - if (status != FWK_SUCCESS) - return status; + if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) { + status = fwk_module_bind(FWK_ID_MODULE(FWK_MODULE_IDX_LOG), + FWK_ID_API(FWK_MODULE_IDX_LOG, 0), &system_power_ctx.log_api); + if (status != FWK_SUCCESS) + return status; - status = fwk_module_bind(system_power_ctx.config->ppu_sys0_id, - system_power_ctx.config->ppu_sys_api_id, - &system_power_ctx.sys0_api); - if (status != FWK_SUCCESS) - return status; + config = system_power_ctx.config; - status = fwk_module_bind(system_power_ctx.config->ppu_sys1_id, - system_power_ctx.config->ppu_sys_api_id, - &system_power_ctx.sys1_api); - if (status != FWK_SUCCESS) - return status; + for (i = 0; i < config->ext_ppus_count; i++) { + status = fwk_module_bind( + config->ext_ppus[i].ppu_id, + config->ext_ppus[i].api_id, + &system_power_ctx.ext_ppu_apis[i]); + if (status != FWK_SUCCESS) + return status; + } - for (i = 0; i < system_power_ctx.config->ext_ppus_count; i++) { - status = fwk_module_bind( - system_power_ctx.config->ext_ppus[i].ppu_id, - system_power_ctx.config->ext_ppus[i].api_id, - &system_power_ctx.ext_ppu_apis[i]); + status = fwk_module_bind(config->driver_id, + config->driver_api_id, + &system_power_ctx.driver_api); if (status != FWK_SUCCESS) return status; - } - status = fwk_module_bind(system_power_ctx.config->driver_id, - system_power_ctx.config->driver_api_id, &system_power_ctx.driver_api); - if (status != FWK_SUCCESS) - return status; + return fwk_module_bind(fwk_module_id_power_domain, + mod_pd_api_id_restricted, + &system_power_ctx.mod_pd_restricted_api); + } - status = fwk_module_bind(fwk_module_id_power_domain, - mod_pd_api_id_restricted, - &system_power_ctx.mod_pd_restricted_api); - if (status != FWK_SUCCESS) - return status; + dev_ctx = system_power_ctx.dev_ctx_table + fwk_id_get_element_idx(id); - return FWK_SUCCESS; + return fwk_module_bind(dev_ctx->config->sys_ppu_id, + dev_ctx->config->api_id, + &dev_ctx->sys_ppu_api); } static int system_power_process_bind_request(fwk_id_t requester_id, - fwk_id_t pd_id, fwk_id_t api_id, - const void **api) + fwk_id_t pd_id, + fwk_id_t api_id, + const void **api) { + unsigned int dev_idx; + struct system_power_dev_ctx *dev_ctx; + if (fwk_id_is_equal(api_id, mod_system_power_api_id_pd_driver)) { if (!fwk_id_is_equal(fwk_id_build_module_id(requester_id), @@ -356,11 +421,21 @@ static int system_power_process_bind_request(fwk_id_t requester_id, *api = &system_power_power_domain_driver_api; system_power_ctx.mod_pd_system_id = requester_id; } else { - if (!fwk_id_is_equal(requester_id, - system_power_ctx.config->ppu_sys0_id) && - !fwk_id_is_equal(requester_id, - system_power_ctx.config->ppu_sys1_id)) + for (dev_idx = 0; dev_idx < system_power_ctx.dev_count; dev_idx++) { + dev_ctx = &system_power_ctx.dev_ctx_table[dev_idx]; + + /* + * If requester_id refers to a system PPU configured by any one of + * our elements, break when dev_idx reaches that element. + */ + if (fwk_id_is_equal(requester_id, dev_ctx->config->sys_ppu_id)) + break; + } + if (dev_idx >= system_power_ctx.dev_count) { + /* Requester_id does not refer to any configured system PPU */ return FWK_E_ACCESS; + } + *api = &system_power_power_domain_driver_input_api; } @@ -370,7 +445,6 @@ static int system_power_process_bind_request(fwk_id_t requester_id, static int system_power_start(fwk_id_t id) { int status; - unsigned int state; if (system_power_ctx.driver_api->platform_interrupts != NULL) { status = system_power_ctx.driver_api->platform_interrupts( @@ -379,24 +453,9 @@ static int system_power_start(fwk_id_t id) return status; } - status = system_power_ctx.sys1_api->get_state - (system_power_ctx.config->ppu_sys1_id, &state); - if (status != FWK_SUCCESS) - return status; - - if (state == MOD_PD_STATE_OFF) { - system_power_ctx.state = MOD_PD_STATE_OFF; - return FWK_SUCCESS; - } - - status = system_power_ctx.sys0_api->get_state - (system_power_ctx.config->ppu_sys0_id, &state); - if (status != FWK_SUCCESS) - return status; - - system_power_ctx.state = (state == MOD_PD_STATE_ON) ? - MOD_PD_STATE_ON : - MOD_SYSTEM_POWER_POWER_STATE_SLEEP0; + /* Configure initial power state */ + system_power_ctx.state = + (unsigned int)system_power_ctx.config->initial_system_power_state; return FWK_SUCCESS; } @@ -406,6 +465,7 @@ const struct fwk_module module_system_power = { .type = FWK_MODULE_TYPE_DRIVER, .api_count = MOD_SYSTEM_POWER_API_COUNT, .init = system_power_mod_init, + .element_init = system_power_mod_element_init, .bind = system_power_bind, .start = system_power_start, .process_bind_request = system_power_process_bind_request, |