1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2017-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 "config_ppu_v1.h"
10 #include "sgm776_core.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 <string.h>
27 
28 /* Mask of the allowed states for the systop power domain */
29 static const uint32_t systop_allowed_state_mask_table[] = {
30     [0] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK |
31           (1 << MOD_SYSTEM_POWER_POWER_STATE_SLEEP0) |
32           (1 << MOD_SYSTEM_POWER_POWER_STATE_SLEEP1)
33 };
34 
35 /*
36  * Mask of the allowed states for the top level power domains
37  * (but the cluster power domains) depending on the system states.
38  */
39 static const uint32_t toplevel_allowed_state_mask_table[] = {
40     [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK,
41     [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK,
42     [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = MOD_PD_STATE_OFF_MASK,
43     [MOD_SYSTEM_POWER_POWER_STATE_SLEEP1] = MOD_PD_STATE_OFF_MASK
44 };
45 
46 /*
47  * Mask of the allowed states for the cluster power domain depending on the
48  * system states.
49  */
50 static const uint32_t cluster_pd_allowed_state_mask_table[] = {
51     [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK,
52     [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK |
53         MOD_PD_STATE_SLEEP_MASK,
54     [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = MOD_PD_STATE_OFF_MASK,
55     [MOD_SYSTEM_POWER_POWER_STATE_SLEEP1] = MOD_PD_STATE_OFF_MASK
56 };
57 
58 /* Mask of the allowed states for a core depending on the cluster states. */
59 static const uint32_t core_pd_allowed_state_mask_table[] = {
60     [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK,
61     [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK |
62         MOD_PD_STATE_SLEEP_MASK,
63     [MOD_PD_STATE_SLEEP] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_SLEEP_MASK,
64 };
65 
66 /* Power module specific configuration data (none) */
67 static const struct mod_power_domain_config sgm776_power_domain_config = { 0 };
68 
69 static struct fwk_element sgm776_power_domain_static_element_table[] = {
70     [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DBGTOP] = {
71         .name = "DBGTOP",
72         .data = &((struct mod_power_domain_element_config) {
73             .attributes.pd_type = MOD_PD_TYPE_DEVICE_DEBUG,
74             .driver_id = FWK_ID_ELEMENT_INIT(
75                 FWK_MODULE_IDX_PPU_V1, PPU_V1_ELEMENT_IDX_DBGTOP),
76             .api_id = FWK_ID_API_INIT(
77                 FWK_MODULE_IDX_PPU_V1,
78                 MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER),
79             .allowed_state_mask_table = toplevel_allowed_state_mask_table,
80             .allowed_state_mask_table_size =
81                 FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table)
82         }),
83     },
84     [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPUTOP] = {
85         .name = "DPUTOP",
86         .data = &((struct mod_power_domain_element_config) {
87             .attributes.pd_type = MOD_PD_TYPE_DEVICE,
88             .driver_id = FWK_ID_ELEMENT_INIT(
89                 FWK_MODULE_IDX_PPU_V1, PPU_V1_ELEMENT_IDX_DPUTOP),
90             .api_id = FWK_ID_API_INIT(
91                 FWK_MODULE_IDX_PPU_V1,
92                 MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER),
93             .allowed_state_mask_table = toplevel_allowed_state_mask_table,
94             .allowed_state_mask_table_size =
95                 FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table)
96         }),
97     },
98     [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_GPUTOP] = {
99         .name = "GPUTOP",
100         .data = &((struct mod_power_domain_element_config) {
101             .attributes.pd_type = MOD_PD_TYPE_DEVICE,
102             .driver_id = FWK_ID_ELEMENT_INIT(
103                 FWK_MODULE_IDX_PPU_V1, PPU_V1_ELEMENT_IDX_GPUTOP),
104             .api_id = FWK_ID_API_INIT(
105                 FWK_MODULE_IDX_PPU_V1,
106                 MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER),
107             .allowed_state_mask_table = toplevel_allowed_state_mask_table,
108             .allowed_state_mask_table_size =
109                 FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table)
110         }),
111     },
112     [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_VPUTOP] = {
113         .name = "VPUTOP",
114         .data = &((struct mod_power_domain_element_config) {
115             .attributes.pd_type = MOD_PD_TYPE_DEVICE,
116             .driver_id = FWK_ID_ELEMENT_INIT(
117                 FWK_MODULE_IDX_PPU_V1, PPU_V1_ELEMENT_IDX_VPUTOP),
118             .api_id = FWK_ID_API_INIT(
119                 FWK_MODULE_IDX_PPU_V1,
120                 MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER),
121             .allowed_state_mask_table = toplevel_allowed_state_mask_table,
122             .allowed_state_mask_table_size =
123                 FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table)
124         }),
125     },
126     [CONFIG_POWER_DOMAIN_SYSTOP_SYSTEM] = {
127         .name = "SYSTOP",
128         .data = &((struct mod_power_domain_element_config) {
129             .attributes.pd_type = MOD_PD_TYPE_SYSTEM,
130             .parent_idx = CONFIG_POWER_DOMAIN_NONE,
131             .driver_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SYSTEM_POWER),
132             .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_POWER,
133                 MOD_SYSTEM_POWER_API_IDX_PD_DRIVER),
134             .allowed_state_mask_table = systop_allowed_state_mask_table,
135             .allowed_state_mask_table_size =
136                 FWK_ARRAY_SIZE(systop_allowed_state_mask_table)
137         }),
138     },
139 };
140 
141 /*
142  * Function definitions with internal linkage
143  */
sgm776_power_domain_get_element_table(fwk_id_t module_id)144 static const struct fwk_element *sgm776_power_domain_get_element_table
145     (fwk_id_t module_id)
146 {
147     unsigned int elem_idx;
148     struct mod_power_domain_element_config *pd_config;
149     size_t static_table_size =
150         FWK_ARRAY_SIZE(sgm776_power_domain_static_element_table);
151 
152     for (elem_idx = 0; elem_idx < (static_table_size - 1); elem_idx++) {
153         pd_config = (struct mod_power_domain_element_config *)
154                         sgm776_power_domain_static_element_table[elem_idx]
155                             .data;
156 
157         pd_config->driver_id = FWK_ID_ELEMENT(
158             FWK_MODULE_IDX_PPU_V1,
159             elem_idx + sgm776_core_get_count() + sgm776_cluster_get_count());
160     }
161 
162     return create_power_domain_element_table(
163         sgm776_core_get_count(),
164         sgm776_cluster_get_count(),
165         FWK_MODULE_IDX_PPU_V1,
166         MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER,
167         core_pd_allowed_state_mask_table,
168         FWK_ARRAY_SIZE(core_pd_allowed_state_mask_table),
169         cluster_pd_allowed_state_mask_table,
170         FWK_ARRAY_SIZE(cluster_pd_allowed_state_mask_table),
171         sgm776_power_domain_static_element_table,
172         FWK_ARRAY_SIZE(sgm776_power_domain_static_element_table));
173 }
174 
175 /*
176  * Power module configuration data
177  */
178 struct fwk_module_config config_power_domain = {
179     .data = &sgm776_power_domain_config,
180     .elements =
181         FWK_MODULE_DYNAMIC_ELEMENTS(sgm776_power_domain_get_element_table),
182 };
183