From 968a3a9f04a94ca366dcf9bf467ac6a6f394d590 Mon Sep 17 00:00:00 2001 From: Nicolas Royer Date: Sun, 27 Sep 2020 17:48:36 +0200 Subject: rcar/module: add rcar system_power module and config data Change-Id: I4267a31991d36fd7b63b13a7cdb16ab28dda1c2d Signed-off-by: Tsutomu Muroya Signed-off-by: Nicolas Royer --- .../include/mod_rcar_system_power.h | 125 +++++++++++ .../rcar_system_power/include/mod_system_power.h | 15 ++ product/rcar/module/rcar_system_power/src/Makefile | 11 + .../rcar_system_power/src/mod_rcar_system_power.c | 238 +++++++++++++++++++++ product/rcar/scp_ramfw/config_rcar_system_power.c | 24 +++ 5 files changed, 413 insertions(+) create mode 100644 product/rcar/module/rcar_system_power/include/mod_rcar_system_power.h create mode 100644 product/rcar/module/rcar_system_power/include/mod_system_power.h create mode 100644 product/rcar/module/rcar_system_power/src/Makefile create mode 100644 product/rcar/module/rcar_system_power/src/mod_rcar_system_power.c create mode 100644 product/rcar/scp_ramfw/config_rcar_system_power.c diff --git a/product/rcar/module/rcar_system_power/include/mod_rcar_system_power.h b/product/rcar/module/rcar_system_power/include/mod_rcar_system_power.h new file mode 100644 index 00000000..37acff18 --- /dev/null +++ b/product/rcar/module/rcar_system_power/include/mod_rcar_system_power.h @@ -0,0 +1,125 @@ +/* + * Renesas SCP/MCP Software + * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MOD_RCAR_SYSTEM_POWER_H +#define MOD_RCAR_SYSTEM_POWER_H + +#include + +#include + +/*! + * \ingroup GroupRCARModule RCAR Product Modules + * \defgroup GroupRCARSystemPower System Power Support + * + * @{ + */ + +/*! Additional system_power power states */ +enum mod_system_power_power_states { + MOD_SYSTEM_POWER_POWER_STATE_SLEEP0 = MOD_PD_STATE_COUNT, + MOD_SYSTEM_POWER_POWER_STATE_SLEEP1, + MOD_SYSTEM_POWER_POWER_STATE_COUNT +}; + +/*! Extended PPU configuration */ +struct mod_system_power_ext_ppu_config { + /*! PPU identifier */ + fwk_id_t ppu_id; + + /*! API identifier */ + fwk_id_t api_id; +}; + +/*! 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; + + /*! + * \brief Pointer to array of extended PPU configurations. + * + * \details These PPUs will be powered on automatically with the rest of the + * system. + */ + const struct mod_system_power_ext_ppu_config *ext_ppus; + + /*! System shutdown driver identifier */ + fwk_id_t driver_id; + + /*! System shutdown driver API identifier */ + fwk_id_t driver_api_id; +}; + +/*! + * \brief Driver interface. + */ +struct mod_system_power_driver_api { + /*! + * \brief Pointer to the system shutdown function. + * + * \note This function is \b mandatory. In case of a successful call the + * function does not return. + * + * \param system_shutdown Type of system shutdown. + * + * \retval One of the driver-defined error code. + */ + int (*system_shutdown)(enum mod_pd_system_shutdown system_shutdown); +}; + +/*! + * \defgroup GroupSystemPowerIds Identifiers + * \{ + */ + +/*! + * \brief API indices. + */ +enum mod_system_power_api_idx { + /*! API index for the power domain driver API */ + MOD_SYSTEM_POWER_API_IDX_PD_DRIVER, + + /*! API index for the power domain driver input API */ + MOD_SYSTEM_POWER_API_IDX_PD_DRIVER_INPUT, + + /*! Number of exposed APIs */ + MOD_SYSTEM_POWER_API_COUNT +}; + +/*! Identifier of the power domain driver API */ +static const fwk_id_t mod_system_power_api_id_pd_driver = FWK_ID_API_INIT( + FWK_MODULE_IDX_SYSTEM_POWER, + MOD_SYSTEM_POWER_API_IDX_PD_DRIVER); + +/*! Identifier of the power domain driver input API */ +static const fwk_id_t mod_system_power_api_id_pd_driver_input = FWK_ID_API_INIT( + FWK_MODULE_IDX_SYSTEM_POWER, + MOD_SYSTEM_POWER_API_IDX_PD_DRIVER_INPUT); + +/*! + * \} + */ + +/*! + * @} + */ + +#endif /* MOD_RCAR_SYSTEM_POWER_H */ diff --git a/product/rcar/module/rcar_system_power/include/mod_system_power.h b/product/rcar/module/rcar_system_power/include/mod_system_power.h new file mode 100644 index 00000000..314af9d6 --- /dev/null +++ b/product/rcar/module/rcar_system_power/include/mod_system_power.h @@ -0,0 +1,15 @@ +/* + * Renesas SCP/MCP Software + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MOD_SYSTEM_POWER_H +#define MOD_SYSTEM_POWER_H + +#define FWK_MODULE_IDX_SYSTEM_POWER FWK_MODULE_IDX_RCAR_SYSTEM_POWER + +#include "mod_rcar_system_power.h" + +#endif /* MOD_SYSTEM_POWER_H */ diff --git a/product/rcar/module/rcar_system_power/src/Makefile b/product/rcar/module/rcar_system_power/src/Makefile new file mode 100644 index 00000000..38f07462 --- /dev/null +++ b/product/rcar/module/rcar_system_power/src/Makefile @@ -0,0 +1,11 @@ +# +# Renesas SCP/MCP Software +# Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := RCAR SYSTEM POWER +BS_LIB_SOURCES = mod_rcar_system_power.c + +include $(BS_DIR)/lib.mk diff --git a/product/rcar/module/rcar_system_power/src/mod_rcar_system_power.c b/product/rcar/module/rcar_system_power/src/mod_rcar_system_power.c new file mode 100644 index 00000000..ba9f0af1 --- /dev/null +++ b/product/rcar/module/rcar_system_power/src/mod_rcar_system_power.c @@ -0,0 +1,238 @@ +/* + * Renesas SCP/MCP Software + * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* 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; + + /* SYS1 power domain driver API pointer*/ + const struct mod_pd_driver_api *sys1_api; + + /* Pointer to array of extended PPU power domain driver APIs */ + const struct mod_pd_driver_api *ext_ppu_apis; + + /* Power domain module restricted API pointer */ + const struct mod_pd_restricted_api *mod_pd_restricted_api; + + /* Power domain module driver input API pointer */ + const struct mod_pd_driver_input_api *mod_pd_driver_input_api; + + /* Driver API pointer */ + const struct mod_system_power_driver_api *driver_api; + + /* Power domain module identifier of the system power domain */ + fwk_id_t mod_pd_system_id; + + /* Current system-level power state */ + unsigned int state; + + /* Pointer to module config */ + 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; + +/* + * Functions fulfilling the Power Domain module's driver API + */ + +static int system_power_set_state(fwk_id_t pd_id, unsigned int state) +{ + return FWK_SUCCESS; +} + +static int system_power_get_state(fwk_id_t pd_id, unsigned int *state) +{ + *state = system_power_ctx.state; + + return FWK_SUCCESS; +} + +static int system_power_reset(fwk_id_t pd_id) +{ + return FWK_E_SUPPORT; +} + +static int system_power_shutdown( + fwk_id_t pd_id, + enum mod_pd_system_shutdown system_shutdown) +{ + int status; + + status = system_power_set_state(pd_id, MOD_PD_STATE_OFF); + if (status != FWK_SUCCESS) + return status; + + return system_power_ctx.driver_api->system_shutdown(system_shutdown); +} + +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); + + status = system_power_ctx.mod_pd_restricted_api->set_state_async( + pd_id, false, state); + assert(status == FWK_SUCCESS); + (void)status; +} + +static const struct mod_pd_driver_api system_power_power_domain_driver_api = { + .set_state = system_power_set_state, + .get_state = system_power_get_state, + .reset = system_power_reset, + .shutdown = system_power_shutdown +}; + +/* + * Functions fulfilling the Power Domain module's driver input API + */ + +static int system_power_report_power_state_transition( + fwk_id_t module_id, + unsigned int state) +{ + int status; + unsigned int sys0_state, sys1_state; + + 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); + + 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; + + 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; + + return FWK_SUCCESS; +} + +static const struct mod_pd_driver_input_api + system_power_power_domain_driver_input_api = { + .report_power_state_transition = + system_power_report_power_state_transition + }; + +/* + * Functions fulfilling the framework's module interface + */ + +static int system_power_mod_init( + fwk_id_t module_id, + unsigned int unused, + const void *data) +{ + assert(data != NULL); + + system_power_ctx.config = data; + system_power_ctx.mod_pd_system_id = FWK_ID_NONE; + + if (system_power_ctx.config->ext_ppus_count > 0) { + system_power_ctx.ext_ppu_apis = fwk_mm_calloc( + system_power_ctx.config->ext_ppus_count, + sizeof(system_power_ctx.ext_ppu_apis[0])); + if (system_power_ctx.ext_ppu_apis == NULL) + return FWK_E_NOMEM; + } + + 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; +} + +static int system_power_bind(fwk_id_t id, unsigned int round) +{ + int 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; + + 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; + + return FWK_SUCCESS; +} + +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) +{ + 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), + fwk_module_id_power_domain)) + return FWK_E_ACCESS; + + *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)) + return FWK_E_ACCESS; + *api = &system_power_power_domain_driver_input_api; + } + + return FWK_SUCCESS; +} + +const struct fwk_module module_rcar_system_power = { + .name = "SYSTEM_POWER", + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = MOD_SYSTEM_POWER_API_COUNT, + .init = system_power_mod_init, + .bind = system_power_bind, + .process_bind_request = system_power_process_bind_request, +}; diff --git a/product/rcar/scp_ramfw/config_rcar_system_power.c b/product/rcar/scp_ramfw/config_rcar_system_power.c new file mode 100644 index 00000000..392791e1 --- /dev/null +++ b/product/rcar/scp_ramfw/config_rcar_system_power.c @@ -0,0 +1,24 @@ +/* + * Renesas SCP/MCP Software + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +const struct fwk_module_config config_rcar_system_power = { + .data = &((struct mod_system_power_config){ + .soc_wakeup_irq = FWK_INTERRUPT_NONE, + .driver_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_RCAR_SYSTEM), + .driver_api_id = FWK_ID_API_INIT( + FWK_MODULE_IDX_RCAR_SYSTEM, + MOD_RCAR_SYSTEM_API_IDX_SYSTEM_POWER_DRIVER) }) +}; -- cgit v1.2.3