From 32f4b8d5ed55216ed01f7b772f7039146620d956 Mon Sep 17 00:00:00 2001 From: Nicola Mazzucato Date: Thu, 2 May 2019 15:15:56 +0100 Subject: [PATCH 1/4] system_power: Update module This patch updates the assertions and removes the unused 'system_power_isr' structure Change-Id: I8a25563f08f0c15c43cdec97bd551c31ad14a454 Signed-off-by: Nicola Mazzucato --- module/system_power/src/mod_system_power.c | 43 ++++++++++++---------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/module/system_power/src/mod_system_power.c b/module/system_power/src/mod_system_power.c index 2b7eaca1c..fe1da672c 100644 --- a/module/system_power/src/mod_system_power.c +++ b/module/system_power/src/mod_system_power.c @@ -20,6 +20,18 @@ #include #include +/* SoC wakeup composite state */ +#define MOD_SYSTEM_POWER_SOC_WAKEUP_STATE \ + MOD_PD_COMPOSITE_STATE(MOD_PD_LEVEL_2, \ + 0, \ + MOD_PD_STATE_ON, \ + MOD_PD_STATE_ON, \ + MOD_PD_STATE_ON) + +/* SoC wakeup Power Domain Identifier */ +static const fwk_id_t mod_system_power_soc_wakeup_pd_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_POWER_DOMAIN, 0); + /* Module context */ struct system_power_ctx { /* Log API pointer */ @@ -53,13 +65,12 @@ struct system_power_ctx { const struct mod_system_power_config *config; }; -struct system_power_isr { - unsigned int interrupt; - void (*handler)(void); -}; - static struct system_power_ctx system_power_ctx; +/* + * Static helpers + */ + static void ext_ppus_set_state(enum mod_pd_state state) { unsigned int i; @@ -159,18 +170,12 @@ static int system_power_shutdown(fwk_id_t pd_id, static void soc_wakeup_handler(void) { int status; - fwk_id_t pd_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_POWER_DOMAIN, 0); - uint32_t state = MOD_PD_COMPOSITE_STATE(MOD_PD_LEVEL_2, - 0, - MOD_PD_STATE_ON, - MOD_PD_STATE_ON, - MOD_PD_STATE_ON); + uint32_t state = MOD_SYSTEM_POWER_SOC_WAKEUP_STATE; status = system_power_ctx.mod_pd_restricted_api->set_composite_state_async( - pd_id, false, state); - assert(status == FWK_SUCCESS); - (void)status; + mod_system_power_soc_wakeup_pd_id, false, state); + fwk_expect(status == FWK_SUCCESS); } static const struct mod_pd_driver_api system_power_power_domain_driver_api = { @@ -206,8 +211,7 @@ static int system_power_report_power_state_transition(fwk_id_t module_id, status = system_power_ctx.mod_pd_driver_input_api->report_power_state_transition( system_power_ctx.mod_pd_system_id, system_power_ctx.state); - assert(status == FWK_SUCCESS); - (void)status; + fwk_expect(status == FWK_SUCCESS); return FWK_SUCCESS; } @@ -225,7 +229,7 @@ static int system_power_mod_init(fwk_id_t module_id, unsigned int unused, const void *data) { - assert(data != NULL); + fwk_assert(data != NULL); system_power_ctx.config = data; system_power_ctx.mod_pd_system_id = FWK_ID_NONE; @@ -241,8 +245,9 @@ static int system_power_mod_init(fwk_id_t module_id, if (system_power_ctx.config->soc_wakeup_irq != FWK_INTERRUPT_NONE) { return fwk_interrupt_set_isr(system_power_ctx.config->soc_wakeup_irq, soc_wakeup_handler); - } else - return FWK_SUCCESS; + } + + return FWK_SUCCESS; } static int system_power_bind(fwk_id_t id, unsigned int round) -- GitLab From 5588b943eefe06f1da306548e492d5c72f80ab99 Mon Sep 17 00:00:00 2001 From: Nicola Mazzucato Date: Tue, 7 May 2019 17:08:11 +0100 Subject: [PATCH 2/4] system_power: Clear pending ISR before enabling Change-Id: I00bc809a0db98ade3e1344ceb000037debdc6653 Signed-off-by: Nicola Mazzucato --- module/system_power/src/mod_system_power.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/module/system_power/src/mod_system_power.c b/module/system_power/src/mod_system_power.c index fe1da672c..8c9885713 100644 --- a/module/system_power/src/mod_system_power.c +++ b/module/system_power/src/mod_system_power.c @@ -89,14 +89,17 @@ static void ext_ppus_set_state(enum mod_pd_state state) static int system_power_set_state(fwk_id_t pd_id, unsigned int state) { int status; + unsigned int soc_wakeup_irq; status = fwk_module_check_call(pd_id); if (status != FWK_SUCCESS) return status; + soc_wakeup_irq = system_power_ctx.config->soc_wakeup_irq; + switch (state) { case MOD_PD_STATE_ON: - fwk_interrupt_disable(system_power_ctx.config->soc_wakeup_irq); + fwk_interrupt_disable(soc_wakeup_irq); system_power_ctx.sys0_api->set_state( system_power_ctx.config->ppu_sys0_id, MOD_PD_STATE_ON); @@ -110,17 +113,19 @@ static int system_power_set_state(fwk_id_t pd_id, unsigned int state) case MOD_SYSTEM_POWER_POWER_STATE_SLEEP0: ext_ppus_set_state(MOD_PD_STATE_OFF); + fwk_interrupt_clear_pending(soc_wakeup_irq); + 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); - fwk_interrupt_enable(system_power_ctx.config->soc_wakeup_irq); + fwk_interrupt_enable(soc_wakeup_irq); break; case MOD_PD_STATE_OFF: - fwk_interrupt_disable(system_power_ctx.config->soc_wakeup_irq); + fwk_interrupt_disable(soc_wakeup_irq); ext_ppus_set_state(MOD_PD_STATE_OFF); system_power_ctx.sys0_api->set_state( -- GitLab From 98ab41ff50ab7683ea6ccdaf8f7b5c03e425d4db Mon Sep 17 00:00:00 2001 From: Nicola Mazzucato Date: Tue, 7 May 2019 17:59:20 +0100 Subject: [PATCH 3/4] system_power: Add platform interrupts API This patch adds support for platform-specific interrupts that may be required at system level. Change-Id: Ibff0ecf48a8076b77197346db656050854625955 Signed-off-by: Nicola Mazzucato --- .../system_power/include/mod_system_power.h | 26 +++++++++++++ module/system_power/src/mod_system_power.c | 37 +++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/module/system_power/include/mod_system_power.h b/module/system_power/include/mod_system_power.h index 95c738275..45d5aa123 100644 --- a/module/system_power/include/mod_system_power.h +++ b/module/system_power/include/mod_system_power.h @@ -69,6 +69,15 @@ struct mod_system_power_config { fwk_id_t driver_api_id; }; +/*! Platform-specific interrupt commands indices */ +enum mod_system_power_platform_interrupt_cmd { + MOD_SYSTEM_POWER_PLATFORM_INTERRUPT_CMD_INIT, + MOD_SYSTEM_POWER_PLATFORM_INTERRUPT_CMD_ENABLE, + MOD_SYSTEM_POWER_PLATFORM_INTERRUPT_CMD_DISABLE, + MOD_SYSTEM_POWER_PLATFORM_INTERRUPT_CMD_CLEAR_PENDING, + MOD_SYSTEM_POWER_PLATFORM_INTERRUPT_CMD_COUNT, +}; + /*! * \brief Driver interface. */ @@ -84,6 +93,23 @@ struct mod_system_power_driver_api { * \retval One of the driver-defined error code. */ int (*system_shutdown)(enum mod_pd_system_shutdown system_shutdown); + + /*! + * \brief Pointer to the platform interrupt management function. + * + * \details This function allows the driver to manage additional + * platform-specific interrupts. + * + * \note This function is \b optional. + * + * \param isr_cmd Type of command requested. + * + * \retval ::FWK_E_PARAM The interrupt command is not valid. + * \retval ::FWK_SUCCESS The operation succeeded. + * \return One of the standard framework error codes. + */ + int (*platform_interrupts)(enum mod_system_power_platform_interrupt_cmd + isr_cmd); }; /*! diff --git a/module/system_power/src/mod_system_power.c b/module/system_power/src/mod_system_power.c index 8c9885713..26ba6a381 100644 --- a/module/system_power/src/mod_system_power.c +++ b/module/system_power/src/mod_system_power.c @@ -101,6 +101,13 @@ static int system_power_set_state(fwk_id_t pd_id, unsigned int state) case MOD_PD_STATE_ON: fwk_interrupt_disable(soc_wakeup_irq); + if (system_power_ctx.driver_api->platform_interrupts != NULL) { + status = system_power_ctx.driver_api->platform_interrupts( + MOD_SYSTEM_POWER_PLATFORM_INTERRUPT_CMD_DISABLE); + if (status != FWK_SUCCESS) + 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( @@ -115,6 +122,14 @@ static int system_power_set_state(fwk_id_t pd_id, unsigned int state) fwk_interrupt_clear_pending(soc_wakeup_irq); + if (system_power_ctx.driver_api->platform_interrupts != NULL) { + status = + system_power_ctx.driver_api->platform_interrupts( + MOD_SYSTEM_POWER_PLATFORM_INTERRUPT_CMD_CLEAR_PENDING); + if (status != FWK_SUCCESS) + 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( @@ -122,10 +137,25 @@ static int system_power_set_state(fwk_id_t pd_id, unsigned int state) fwk_interrupt_enable(soc_wakeup_irq); + if (system_power_ctx.driver_api->platform_interrupts != NULL) { + status = system_power_ctx.driver_api->platform_interrupts( + MOD_SYSTEM_POWER_PLATFORM_INTERRUPT_CMD_ENABLE); + if (status != FWK_SUCCESS) + return FWK_E_DEVICE; + } + break; case MOD_PD_STATE_OFF: fwk_interrupt_disable(soc_wakeup_irq); + + if (system_power_ctx.driver_api->platform_interrupts != NULL) { + status = system_power_ctx.driver_api->platform_interrupts( + MOD_SYSTEM_POWER_PLATFORM_INTERRUPT_CMD_DISABLE); + if (status != FWK_SUCCESS) + return FWK_E_DEVICE; + } + ext_ppus_set_state(MOD_PD_STATE_OFF); system_power_ctx.sys0_api->set_state( @@ -342,6 +372,13 @@ 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( + MOD_SYSTEM_POWER_PLATFORM_INTERRUPT_CMD_INIT); + if (status != FWK_SUCCESS) + return status; + } + status = system_power_ctx.sys1_api->get_state (system_power_ctx.config->ppu_sys1_id, &state); if (status != FWK_SUCCESS) -- GitLab From 0b9b3a7a95ce3041c1322c407878ce6136212d42 Mon Sep 17 00:00:00 2001 From: Nicola Mazzucato Date: Thu, 2 May 2019 16:27:27 +0100 Subject: [PATCH 4/4] 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 --- .../system_power/include/mod_system_power.h | 27 +- module/system_power/src/mod_system_power.c | 242 +++++++++++------- product/n1sdp/scp_ramfw/config_system_power.c | 66 +++-- .../rdn1e1/scp_ramfw/config_system_power.c | 66 +++-- .../sgi575/scp_ramfw/config_system_power.c | 68 +++-- .../sgm775/scp_ramfw/config_system_power.c | 53 +++- 6 files changed, 360 insertions(+), 162 deletions(-) diff --git a/module/system_power/include/mod_system_power.h b/module/system_power/include/mod_system_power.h index 45d5aa123..eb12d4905 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 26ba6a381..fbe980d69 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, diff --git a/product/n1sdp/scp_ramfw/config_system_power.c b/product/n1sdp/scp_ramfw/config_system_power.c index 7b9360f52..c87ca1e5a 100644 --- a/product/n1sdp/scp_ramfw/config_system_power.c +++ b/product/n1sdp/scp_ramfw/config_system_power.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -15,41 +16,70 @@ #include #include -/* Table with only a terminator */ -static const struct fwk_element n1sdp_system_element_table = { 0 }; +static const uint8_t system_power_to_sys_ppu0_state[] = { + [MOD_PD_STATE_ON] = (uint8_t)MOD_PD_STATE_ON, + [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = (uint8_t)MOD_PD_STATE_OFF, + [MOD_PD_STATE_OFF] = (uint8_t)MOD_PD_STATE_OFF, +}; + +static const uint8_t system_power_to_sys_ppu1_state[] = { + [MOD_PD_STATE_ON] = (uint8_t)MOD_PD_STATE_ON, + [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = (uint8_t)MOD_PD_STATE_ON, + [MOD_PD_STATE_OFF] = (uint8_t)MOD_PD_STATE_OFF, +}; + +static struct fwk_element system_power_element_table[] = { + [0] = { + .name = "SYS-PPU-0", + .data = &((struct mod_system_power_dev_config) { + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V1, + MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER), + .sys_state_table = system_power_to_sys_ppu0_state, + }), + }, + + [1] = { + .name = "SYS-PPU-1", + .data = &((struct mod_system_power_dev_config) { + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V1, + MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER), + .sys_state_table = system_power_to_sys_ppu1_state, + }), + }, + + [2] = { 0 }, /* Termination description */ +}; static struct mod_system_power_config system_power_config = { .soc_wakeup_irq = SCP_EXT_IRQ, - /* PPU settings */ - .ppu_sys_api_id = FWK_ID_API_INIT( - FWK_MODULE_IDX_PPU_V1, - MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER), - /* System driver */ .driver_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_N1SDP_SYSTEM), .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_N1SDP_SYSTEM, MOD_N1SDP_SYSTEM_API_IDX_SYSTEM_POWER_DRIVER), + + /* Initial system state */ + .initial_system_power_state = MOD_PD_STATE_OFF, }; static const struct fwk_element *n1sdp_system_get_element_table( fwk_id_t unused) { + struct mod_system_power_dev_config *dev_config_table; + unsigned int i; + /* The system PPUs are placed after the core and cluster PPUs */ unsigned int ppu_idx_base = n1sdp_core_get_core_count() + n1sdp_core_get_cluster_count(); - /* Set the system PPU elements */ - system_power_config.ppu_sys0_id = fwk_id_build_element_id( - fwk_module_id_ppu_v1, ppu_idx_base); - system_power_config.ppu_sys1_id = fwk_id_build_element_id( - fwk_module_id_ppu_v1, ppu_idx_base + 1); - - /* - * Return table with only a terminator as this function is only used to - * setup the dynamic module data. - */ - return &n1sdp_system_element_table; + for (i = 0; i < (FWK_ARRAY_SIZE(system_power_element_table) - 1); i++) { + dev_config_table = (struct mod_system_power_dev_config *) + system_power_element_table[i].data; + dev_config_table->sys_ppu_id = + fwk_id_build_element_id(fwk_module_id_ppu_v1, ppu_idx_base + i); + } + + return system_power_element_table; } const struct fwk_module_config config_system_power = { diff --git a/product/rdn1e1/scp_ramfw/config_system_power.c b/product/rdn1e1/scp_ramfw/config_system_power.c index c92d6549b..af1a896f7 100644 --- a/product/rdn1e1/scp_ramfw/config_system_power.c +++ b/product/rdn1e1/scp_ramfw/config_system_power.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -15,41 +16,70 @@ #include #include -/* Table with only a terminator */ -static const struct fwk_element rdn1e1_system_element_table = { 0 }; +static const uint8_t system_power_to_sys_ppu0_state[] = { + [MOD_PD_STATE_ON] = (uint8_t)MOD_PD_STATE_ON, + [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = (uint8_t)MOD_PD_STATE_OFF, + [MOD_PD_STATE_OFF] = (uint8_t)MOD_PD_STATE_OFF, +}; + +static const uint8_t system_power_to_sys_ppu1_state[] = { + [MOD_PD_STATE_ON] = (uint8_t)MOD_PD_STATE_ON, + [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = (uint8_t)MOD_PD_STATE_ON, + [MOD_PD_STATE_OFF] = (uint8_t)MOD_PD_STATE_OFF, +}; + +static struct fwk_element system_power_element_table[] = { + [0] = { + .name = "SYS-PPU-0", + .data = &((struct mod_system_power_dev_config) { + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V1, + MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER), + .sys_state_table = system_power_to_sys_ppu0_state, + }), + }, + + [1] = { + .name = "SYS-PPU-1", + .data = &((struct mod_system_power_dev_config) { + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V1, + MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER), + .sys_state_table = system_power_to_sys_ppu1_state, + }), + }, + + [2] = { 0 }, /* Termination description */ +}; static struct mod_system_power_config system_power_config = { .soc_wakeup_irq = SOC_WAKEUP0_IRQ, - /* PPU settings */ - .ppu_sys_api_id = FWK_ID_API_INIT( - FWK_MODULE_IDX_PPU_V1, - MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER), - /* System driver */ .driver_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_RDN1E1_SYSTEM), .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_RDN1E1_SYSTEM, MOD_RDN1E1_SYSTEM_API_IDX_SYSTEM_POWER_DRIVER), + + /* Initial system state */ + .initial_system_power_state = MOD_PD_STATE_OFF, }; static const struct fwk_element *rdn1e1_system_get_element_table( fwk_id_t unused) { + struct mod_system_power_dev_config *dev_config_table; + unsigned int i; + /* The system PPUs are placed after the core and cluster PPUs */ unsigned int ppu_idx_base = rdn1e1_core_get_core_count() + rdn1e1_core_get_cluster_count(); - /* Set the system PPU elements */ - system_power_config.ppu_sys0_id = fwk_id_build_element_id( - fwk_module_id_ppu_v1, ppu_idx_base); - system_power_config.ppu_sys1_id = fwk_id_build_element_id( - fwk_module_id_ppu_v1, ppu_idx_base + 1); - - /* - * Return table with only a terminator as this function is only used to - * setup the dynamic module data. - */ - return &rdn1e1_system_element_table; + for (i = 0; i < (FWK_ARRAY_SIZE(system_power_element_table) - 1); i++) { + dev_config_table = (struct mod_system_power_dev_config *) + system_power_element_table[i].data; + dev_config_table->sys_ppu_id = + fwk_id_build_element_id(fwk_module_id_ppu_v1, ppu_idx_base + i); + } + + return system_power_element_table; } const struct fwk_module_config config_system_power = { diff --git a/product/sgi575/scp_ramfw/config_system_power.c b/product/sgi575/scp_ramfw/config_system_power.c index 95a2bb277..cf24b08bb 100644 --- a/product/sgi575/scp_ramfw/config_system_power.c +++ b/product/sgi575/scp_ramfw/config_system_power.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -15,44 +16,73 @@ #include #include -/* Table with only a terminator */ -static const struct fwk_element sgi575_system_element_table = { 0 }; +static const uint8_t system_power_to_sys_ppu0_state[] = { + [MOD_PD_STATE_ON] = (uint8_t)MOD_PD_STATE_ON, + [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = (uint8_t)MOD_PD_STATE_OFF, + [MOD_PD_STATE_OFF] = (uint8_t)MOD_PD_STATE_OFF, +}; + +static const uint8_t system_power_to_sys_ppu1_state[] = { + [MOD_PD_STATE_ON] = (uint8_t)MOD_PD_STATE_ON, + [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = (uint8_t)MOD_PD_STATE_ON, + [MOD_PD_STATE_OFF] = (uint8_t)MOD_PD_STATE_OFF, +}; + +static struct fwk_element system_power_element_table[] = { + [0] = { + .name = "SYS-PPU-0", + .data = &((struct mod_system_power_dev_config) { + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V1, + MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER), + .sys_state_table = system_power_to_sys_ppu0_state, + }), + }, + + [1] = { + .name = "SYS-PPU-1", + .data = &((struct mod_system_power_dev_config) { + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V1, + MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER), + .sys_state_table = system_power_to_sys_ppu1_state, + }), + }, + + [2] = { 0 }, /* Termination description */ +}; static struct mod_system_power_config system_power_config = { .soc_wakeup_irq = SOC_WAKEUP0_IRQ, - /* PPU settings */ - .ppu_sys_api_id = FWK_ID_API_INIT( - FWK_MODULE_IDX_PPU_V1, - MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER), - /* System driver */ .driver_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SGI575_SYSTEM), .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SGI575_SYSTEM, MOD_SGI575_SYSTEM_API_IDX_SYSTEM_POWER_DRIVER), + + /* Initial system state */ + .initial_system_power_state = MOD_PD_STATE_OFF, }; static const struct fwk_element *sgi575_system_get_element_table( fwk_id_t unused) { + struct mod_system_power_dev_config *dev_config_table; + unsigned int i; + /* The system PPUs are placed after the core and cluster PPUs */ unsigned int ppu_idx_base = sgi575_core_get_core_count() + sgi575_core_get_cluster_count(); - /* Set the system PPU elements */ - system_power_config.ppu_sys0_id = fwk_id_build_element_id( - fwk_module_id_ppu_v1, ppu_idx_base); - system_power_config.ppu_sys1_id = fwk_id_build_element_id( - fwk_module_id_ppu_v1, ppu_idx_base + 1); - - /* - * Return table with only a terminator as this function is only used to - * setup the dynamic module data. - */ - return &sgi575_system_element_table; + for (i = 0; i < (FWK_ARRAY_SIZE(system_power_element_table) - 1); i++) { + dev_config_table = (struct mod_system_power_dev_config *) + system_power_element_table[i].data; + dev_config_table->sys_ppu_id = + fwk_id_build_element_id(fwk_module_id_ppu_v1, ppu_idx_base + i); + } + + return system_power_element_table; } const struct fwk_module_config config_system_power = { - .get_element_table = sgi575_system_get_element_table, .data = &system_power_config, + .get_element_table = sgi575_system_get_element_table, }; diff --git a/product/sgm775/scp_ramfw/config_system_power.c b/product/sgm775/scp_ramfw/config_system_power.c index 0823ffd18..d80595a61 100644 --- a/product/sgm775/scp_ramfw/config_system_power.c +++ b/product/sgm775/scp_ramfw/config_system_power.c @@ -45,18 +45,57 @@ static const struct mod_system_power_ext_ppu_config ext_ppus[] = { }, }; +static const uint8_t system_power_to_sys_ppu0_state[] = { + [MOD_PD_STATE_ON] = (uint8_t)MOD_PD_STATE_ON, + [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = (uint8_t)MOD_PD_STATE_OFF, + [MOD_PD_STATE_OFF] = (uint8_t)MOD_PD_STATE_OFF, +}; + +static const uint8_t system_power_to_sys_ppu1_state[] = { + [MOD_PD_STATE_ON] = (uint8_t)MOD_PD_STATE_ON, + [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = (uint8_t)MOD_PD_STATE_ON, + [MOD_PD_STATE_OFF] = (uint8_t)MOD_PD_STATE_OFF, +}; + +static const struct fwk_element system_power_element_table[] = { + [0] = { + .name = "SYS-PPU-0", + .data = &((struct mod_system_power_dev_config) { + .sys_ppu_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PPU_V0, + PPU_V0_ELEMENT_IDX_SYS0), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0, 0), + .sys_state_table = system_power_to_sys_ppu0_state, + }), + }, + + [1] = { + .name = "SYS-PPU-1", + .data = &((struct mod_system_power_dev_config) { + .sys_ppu_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PPU_V0, + PPU_V0_ELEMENT_IDX_SYS1), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0, 0), + .sys_state_table = system_power_to_sys_ppu1_state, + }), + }, + + [2] = { 0 }, /* Termination description */ +}; + +static const struct fwk_element *system_power_get_element_table( + fwk_id_t module_id) +{ + return system_power_element_table; +} + const struct fwk_module_config config_system_power = { .data = &((struct mod_system_power_config) { .soc_wakeup_irq = SOC_WAKEUP0_IRQ, - .ppu_sys0_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PPU_V0, - PPU_V0_ELEMENT_IDX_SYS0), - .ppu_sys1_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PPU_V0, - PPU_V0_ELEMENT_IDX_SYS1), - .ppu_sys_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0, 0), .ext_ppus = ext_ppus, .ext_ppus_count = FWK_ARRAY_SIZE(ext_ppus), .driver_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SGM775_SYSTEM), .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SGM775_SYSTEM, - MOD_SGM775_SYSTEM_API_IDX_SYSTEM_POWER_DRIVER) - }) + MOD_SGM775_SYSTEM_API_IDX_SYSTEM_POWER_DRIVER), + .initial_system_power_state = MOD_PD_STATE_ON, + }), + .get_element_table = system_power_get_element_table, }; -- GitLab