diff options
author | Amit Daniel Kachhap <amit.kachhap@arm.com> | 2018-07-20 18:59:39 +0530 |
---|---|---|
committer | ronald-cron-arm <39518861+ronald-cron-arm@users.noreply.github.com> | 2018-10-18 17:22:34 +0000 |
commit | 04294a13be5bffc5976df96dbb1fcaa8f376dd3c (patch) | |
tree | 71c974f6a3dcd848d5ec4fe2d5f65444a404ca49 /product/sgi575 | |
parent | ba55cdcbefdd1f5f4e5b8789eca93a3c4876d975 (diff) |
sgi575/scp_ramfw: Add power domain config
Change-Id: I41377b35b0fad19624bfa570380fbb82416776a6
Signed-off-by: Amit Daniel Kachhap <amit.kachhap@arm.com>
Diffstat (limited to 'product/sgi575')
-rw-r--r-- | product/sgi575/scp_ramfw/config_power_domain.c | 212 | ||||
-rw-r--r-- | product/sgi575/scp_ramfw/config_power_domain.h | 27 |
2 files changed, 239 insertions, 0 deletions
diff --git a/product/sgi575/scp_ramfw/config_power_domain.c b/product/sgi575/scp_ramfw/config_power_domain.c new file mode 100644 index 00000000..d2d44829 --- /dev/null +++ b/product/sgi575/scp_ramfw/config_power_domain.c @@ -0,0 +1,212 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <fwk_element.h> +#include <fwk_macros.h> +#include <fwk_mm.h> +#include <fwk_module.h> +#include <fwk_module_idx.h> +#include <mod_power_domain.h> +#include <mod_ppu_v1.h> +#include <mod_system_power.h> +#include <sgi575_power_domain.h> +#include <sgi575_core.h> +#include <config_ppu_v0.h> +#include <config_power_domain.h> + +/* Maximum power domain name size including the null terminator */ +#define PD_NAME_SIZE 12 + +/* Mask of the allowed states for the systop power domain */ +static const uint32_t systop_allowed_state_mask_table[] = { + [0] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK | + (1 << MOD_SYSTEM_POWER_POWER_STATE_SLEEP0) | + (1 << MOD_SYSTEM_POWER_POWER_STATE_SLEEP1) +}; + +/* + * Mask of the allowed states for the top level power domains + * (but the cluster power domains) depending on the system states. + */ +static const uint32_t toplevel_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK, + [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK, + [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = MOD_PD_STATE_OFF_MASK, + [MOD_SYSTEM_POWER_POWER_STATE_SLEEP1] = MOD_PD_STATE_OFF_MASK +}; + +/* + * Mask of the allowed states for the cluster power domain depending on the + * system states. + */ +static const uint32_t cluster_pd_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_SLEEP_MASK, + [MOD_PD_STATE_ON] = SGI575_CLUSTER_VALID_STATE_MASK, + [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = MOD_PD_STATE_OFF_MASK, + [MOD_SYSTEM_POWER_POWER_STATE_SLEEP1] = MOD_PD_STATE_OFF_MASK +}; + +/* Mask of the allowed states for a core depending on the cluster states. */ +static const uint32_t core_pd_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_SLEEP_MASK, + [MOD_PD_STATE_ON] = SGI575_CORE_VALID_STATE_MASK, + [MOD_PD_STATE_SLEEP] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_SLEEP_MASK, + [SGI575_POWER_DOMAIN_STATE_FUNC_RET] = SGI575_CORE_VALID_STATE_MASK, + [SGI575_POWER_DOMAIN_STATE_MEM_RET] = MOD_PD_STATE_OFF_MASK +}; + +/* Power module specific configuration data (none) */ +static const struct mod_power_domain_config sgi575_power_domain_config = { 0 }; + +static struct fwk_element sgi575_power_domain_static_element_table[] = { + [PD_STATIC_DEV_IDX_CLUSTER0] = { + .name = "CLUS0", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_CLUSTER, + .tree_pos = MOD_PD_TREE_POS( + MOD_PD_LEVEL_1, 0, 0, PD_STATIC_DEV_IDX_CLUSTER0, 0), + .api_id = FWK_ID_API_INIT( + FWK_MODULE_IDX_PPU_V1, + MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER), + .allowed_state_mask_table = cluster_pd_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(cluster_pd_allowed_state_mask_table) + }), + }, + [PD_STATIC_DEV_IDX_CLUSTER1] = { + .name = "CLUS1", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_CLUSTER, + .tree_pos = MOD_PD_TREE_POS( + MOD_PD_LEVEL_1, 0, 0, PD_STATIC_DEV_IDX_CLUSTER1, 0), + .api_id = FWK_ID_API_INIT( + FWK_MODULE_IDX_PPU_V1, + MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER), + .allowed_state_mask_table = cluster_pd_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(cluster_pd_allowed_state_mask_table) + }), + }, + [PD_STATIC_DEV_IDX_DBGTOP] = { + .name = "DBGTOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE_DEBUG, + .tree_pos = MOD_PD_TREE_POS( + MOD_PD_LEVEL_1, 0, 0, PD_STATIC_DEV_IDX_DBGTOP, 0), + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_PPU_V0, PPU_V0_ELEMENT_IDX_DBGTOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [PD_STATIC_DEV_IDX_SYSTOP] = { + .name = "SYSTOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_SYSTEM, + .tree_pos = MOD_PD_TREE_POS( + MOD_PD_LEVEL_2, 0, 0, 0, 0), + .driver_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SYSTEM_POWER), + .api_id = FWK_ID_API_INIT( + FWK_MODULE_IDX_SYSTEM_POWER, + MOD_SYSTEM_POWER_API_IDX_PD_DRIVER), + .allowed_state_mask_table = systop_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(systop_allowed_state_mask_table) + }), + }, +}; + +/* + * Function definitions with internal linkage + */ +static const struct fwk_element *sgi575_power_domain_get_element_table + (fwk_id_t module_id) +{ + struct fwk_element *element_table, *element; + struct mod_power_domain_element_config *pd_config_table, *pd_config; + unsigned int core_idx; + unsigned int cluster_idx; + unsigned int core_count; + unsigned int cluster_count; + unsigned int core_element_count = 0; + + core_count = sgi575_core_get_core_count(); + cluster_count = sgi575_core_get_cluster_count(); + + element_table = fwk_mm_calloc( + core_count + + FWK_ARRAY_SIZE(sgi575_power_domain_static_element_table) + + 1, /* Terminator */ + sizeof(struct fwk_element)); + if (element_table == NULL) + return NULL; + + pd_config_table = fwk_mm_calloc(core_count, + sizeof(struct mod_power_domain_element_config)); + if (pd_config_table == NULL) + return NULL; + + for (cluster_idx = 0; cluster_idx < cluster_count; cluster_idx++) { + for (core_idx = 0; + core_idx < sgi575_core_get_core_per_cluster_count(cluster_idx); + core_idx++) { + + element = &element_table[core_element_count]; + pd_config = &pd_config_table[core_element_count]; + + element->name = fwk_mm_alloc(PD_NAME_SIZE, 1); + if (element->name == NULL) + return NULL; + + snprintf((char *)element->name, PD_NAME_SIZE, "CLUS%uCORE%u", + cluster_idx, core_idx); + + element->data = pd_config; + + pd_config->attributes.pd_type = MOD_PD_TYPE_CORE; + pd_config->tree_pos = MOD_PD_TREE_POS( + MOD_PD_LEVEL_0, 0, 0, cluster_idx, core_idx); + pd_config->driver_id = + FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1, + core_element_count); + pd_config->api_id = FWK_ID_API( + FWK_MODULE_IDX_PPU_V1, + MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER); + pd_config->allowed_state_mask_table = + core_pd_allowed_state_mask_table; + pd_config->allowed_state_mask_table_size = + FWK_ARRAY_SIZE(core_pd_allowed_state_mask_table); + core_element_count++; + } + + /* Define the driver id for the cluster */ + pd_config = (struct mod_power_domain_element_config *) + sgi575_power_domain_static_element_table[cluster_idx].data; + pd_config->driver_id = + FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1, + (core_count + cluster_idx)); + } + + memcpy(element_table + core_count, + sgi575_power_domain_static_element_table, + sizeof(sgi575_power_domain_static_element_table)); + + return element_table; +} + +/* + * Power module configuration data + */ +const struct fwk_module_config config_power_domain = { + .get_element_table = sgi575_power_domain_get_element_table, + .data = &sgi575_power_domain_config, +}; diff --git a/product/sgi575/scp_ramfw/config_power_domain.h b/product/sgi575/scp_ramfw/config_power_domain.h new file mode 100644 index 00000000..b428c148 --- /dev/null +++ b/product/sgi575/scp_ramfw/config_power_domain.h @@ -0,0 +1,27 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_POWER_DOMAIN_H +#define CONFIG_POWER_DOMAIN_H + +/* + * Power domain indices for the statically defined domains used for: + * - Indexing the domains in the sgi575_power_domain_static_element_table + * - Indexing the SYSTOP children in the power domain tree + * + * When calculating a power domain element index, use the formula: + * core_count + pd_static_dev_idx + */ +enum pd_static_dev_idx { + PD_STATIC_DEV_IDX_CLUSTER0, + PD_STATIC_DEV_IDX_CLUSTER1, + PD_STATIC_DEV_IDX_DBGTOP, + PD_STATIC_DEV_IDX_SYSTOP, + PD_STATIC_DEV_IDX_COUNT +}; + +#endif /* CONFIG_POWER_DOMAIN_H */ |