aboutsummaryrefslogtreecommitdiff
path: root/product/sgi575
diff options
context:
space:
mode:
authorAmit Daniel Kachhap <amit.kachhap@arm.com>2018-07-20 18:59:39 +0530
committerronald-cron-arm <39518861+ronald-cron-arm@users.noreply.github.com>2018-10-18 17:22:34 +0000
commit04294a13be5bffc5976df96dbb1fcaa8f376dd3c (patch)
tree71c974f6a3dcd848d5ec4fe2d5f65444a404ca49 /product/sgi575
parentba55cdcbefdd1f5f4e5b8789eca93a3c4876d975 (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.c212
-rw-r--r--product/sgi575/scp_ramfw/config_power_domain.h27
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 */