1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "config_power_domain.h"
9 #include "tc0_core.h"
10 #include "tc0_power_domain.h"
11 
12 #include <power_domain_utils.h>
13 
14 #include <mod_power_domain.h>
15 #include <mod_ppu_v1.h>
16 #include <mod_system_power.h>
17 
18 #include <fwk_element.h>
19 #include <fwk_id.h>
20 #include <fwk_macros.h>
21 #include <fwk_mm.h>
22 #include <fwk_module.h>
23 #include <fwk_module_idx.h>
24 
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <string.h>
28 
29 /* Maximum power domain name size including the null terminator */
30 #define PD_NAME_SIZE 12
31 
32 /* Mask of the allowed states for the systop power domain */
33 static const uint32_t systop_allowed_state_mask_table[] = {
34     [0] = MOD_PD_STATE_ON_MASK
35 };
36 
37 /*
38  * Mask of the allowed states for the cluster power domain depending on the
39  * system states.
40  */
41 static const uint32_t cluster_pd_allowed_state_mask_table[] = {
42     [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK,
43     [MOD_PD_STATE_ON] = TC0_CLUSTER_VALID_STATE_MASK,
44 };
45 
46 /* Mask of the allowed states for a core depending on the cluster states. */
47 static const uint32_t core_pd_allowed_state_mask_table[] = {
48     [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_SLEEP_MASK,
49     [MOD_PD_STATE_ON] = TC0_CORE_VALID_STATE_MASK,
50 };
51 
52 /* Power module specific configuration data (none) */
53 static const struct mod_power_domain_config tc0_power_domain_config = { 0 };
54 
55 static struct fwk_element tc0_power_domain_static_element_table[] = {
56     [PD_STATIC_DEV_IDX_SYSTOP] =
57         {
58             .name = "SYSTOP",
59             .data = &((struct mod_power_domain_element_config){
60                 .attributes.pd_type = MOD_PD_TYPE_SYSTEM,
61                 .parent_idx = PD_STATIC_DEV_IDX_NONE,
62                 .driver_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SYSTEM_POWER),
63                 .api_id = FWK_ID_API_INIT(
64                     FWK_MODULE_IDX_SYSTEM_POWER,
65                     MOD_SYSTEM_POWER_API_IDX_PD_DRIVER),
66                 .allowed_state_mask_table = systop_allowed_state_mask_table,
67                 .allowed_state_mask_table_size =
68                     FWK_ARRAY_SIZE(systop_allowed_state_mask_table) }),
69         },
70 };
71 
72 /*
73  * Function definitions with internal linkage
74  */
tc0_power_domain_get_element_table(fwk_id_t module_id)75 static const struct fwk_element *tc0_power_domain_get_element_table(
76     fwk_id_t module_id)
77 {
78     return create_power_domain_element_table(
79         tc0_core_get_core_count(),
80         tc0_core_get_cluster_count(),
81         FWK_MODULE_IDX_PPU_V1,
82         MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER,
83         core_pd_allowed_state_mask_table,
84         FWK_ARRAY_SIZE(core_pd_allowed_state_mask_table),
85         cluster_pd_allowed_state_mask_table,
86         FWK_ARRAY_SIZE(cluster_pd_allowed_state_mask_table),
87         tc0_power_domain_static_element_table,
88         FWK_ARRAY_SIZE(tc0_power_domain_static_element_table));
89 }
90 
91 /*
92  * Power module configuration data
93  */
94 const struct fwk_module_config config_power_domain = {
95     .elements = FWK_MODULE_DYNAMIC_ELEMENTS(tc0_power_domain_get_element_table),
96     .data = &tc0_power_domain_config,
97 };
98