1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 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_v0.h>
10 #include <morello_core.h>
11 #include <morello_power_domain.h>
12 
13 #include <mod_power_domain.h>
14 #include <mod_ppu_v1.h>
15 #include <mod_system_power.h>
16 
17 #include <fwk_element.h>
18 #include <fwk_macros.h>
19 #include <fwk_mm.h>
20 #include <fwk_module.h>
21 #include <fwk_module_idx.h>
22 
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <string.h>
26 
27 /* Maximum power domain name size including the null terminator */
28 #define PD_NAME_SIZE 16
29 
30 /* Mask of the allowed states for the systop power domain */
31 static const uint32_t systop_allowed_state_mask_table[2] = {
32     [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK,
33     [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK |
34         (1 << MOD_SYSTEM_POWER_POWER_STATE_SLEEP0) |
35         (1 << MOD_SYSTEM_POWER_POWER_STATE_SLEEP1)
36 };
37 
38 /*
39  * Mask of the allowed states for the top level power domains
40  * (but the cluster power domains) depending on the system states.
41  */
42 static const uint32_t toplevel_allowed_state_mask_table[5] = {
43     [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK,
44     [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK,
45     [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = MOD_PD_STATE_OFF_MASK,
46     [MOD_SYSTEM_POWER_POWER_STATE_SLEEP1] = MOD_PD_STATE_OFF_MASK
47 };
48 
49 /*
50  * Mask of the allowed states for the cluster power domain depending on the
51  * system states.
52  */
53 static const uint32_t cluster_pd_allowed_state_mask_table[5] = {
54     [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_SLEEP_MASK,
55     [MOD_PD_STATE_ON] = MORELLO_CLUSTER_VALID_STATE_MASK,
56     [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = MOD_PD_STATE_OFF_MASK,
57     [MOD_SYSTEM_POWER_POWER_STATE_SLEEP1] = MOD_PD_STATE_OFF_MASK
58 };
59 
60 /* Mask of the allowed states for a core depending on the cluster states. */
61 static const uint32_t core_pd_allowed_state_mask_table[6] = {
62     [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_SLEEP_MASK,
63     [MOD_PD_STATE_ON] = MORELLO_CORE_VALID_STATE_MASK,
64     [MOD_PD_STATE_SLEEP] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_SLEEP_MASK,
65     [MORELLO_POWER_DOMAIN_STATE_FUNC_RET] = MORELLO_CORE_VALID_STATE_MASK,
66     [MORELLO_POWER_DOMAIN_STATE_MEM_RET] = MOD_PD_STATE_OFF_MASK
67 };
68 
69 /* Power module specific configuration data (none) */
70 static const struct mod_power_domain_config morello_power_domain_config = { 0 };
71 
72 /* Power domain element table pointer */
73 struct fwk_element *element_table = NULL;
74 
75 /* Power domain element configuration table pointer */
76 struct mod_power_domain_element_config *pd_config_table = NULL;
77 
78 /*
79  * The SCP's view of PD tree in a single chip mode looks like below:
80  *
81  *            -------------SYSTOP0----------------
82  *           /        /       |        \          \
83  *          /        /        |         \          \
84  *         /        /         |          \          \
85  *    CLUS0       CLUS1    DBGTOP0    GPUTOP0    DPUTOP0
86  *   /    \      /    \
87  * CPU0--CPU1--CPU2--CPU3
88  *
89  */
90 
91 static struct fwk_element
92         morello_pd_single_chip_element_table[PD_SINGLE_CHIP_IDX_COUNT + 1] = {
93     [PD_SINGLE_CHIP_IDX_CLUS0CORE0] = {
94         .name = "CLUS0CORE0",
95         .data = &((struct mod_power_domain_element_config) {
96             .attributes.pd_type = MOD_PD_TYPE_CORE,
97             .parent_idx = PD_SINGLE_CHIP_IDX_CLUSTER0,
98             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PPU_V1, 0),
99             .api_id = FWK_ID_API_INIT(
100                 FWK_MODULE_IDX_PPU_V1,
101                 MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER),
102             .allowed_state_mask_table = core_pd_allowed_state_mask_table,
103             .allowed_state_mask_table_size =
104                 FWK_ARRAY_SIZE(core_pd_allowed_state_mask_table)
105         }),
106     },
107     [PD_SINGLE_CHIP_IDX_CLUS0CORE1] = {
108         .name = "CLUS0CORE1",
109         .data = &((struct mod_power_domain_element_config) {
110             .attributes.pd_type = MOD_PD_TYPE_CORE,
111             .parent_idx = PD_SINGLE_CHIP_IDX_CLUSTER0,
112             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PPU_V1, 1),
113             .api_id = FWK_ID_API_INIT(
114                 FWK_MODULE_IDX_PPU_V1,
115                 MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER),
116             .allowed_state_mask_table = core_pd_allowed_state_mask_table,
117             .allowed_state_mask_table_size =
118                 FWK_ARRAY_SIZE(core_pd_allowed_state_mask_table)
119         }),
120     },
121     [PD_SINGLE_CHIP_IDX_CLUS1CORE0] = {
122         .name = "CLUS1CORE0",
123         .data = &((struct mod_power_domain_element_config) {
124             .attributes.pd_type = MOD_PD_TYPE_CORE,
125             .parent_idx = PD_SINGLE_CHIP_IDX_CLUSTER1,
126             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PPU_V1, 2),
127             .api_id = FWK_ID_API_INIT(
128                 FWK_MODULE_IDX_PPU_V1,
129                 MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER),
130             .allowed_state_mask_table = core_pd_allowed_state_mask_table,
131             .allowed_state_mask_table_size =
132                 FWK_ARRAY_SIZE(core_pd_allowed_state_mask_table)
133         }),
134     },
135     [PD_SINGLE_CHIP_IDX_CLUS1CORE1] = {
136         .name = "CLUS1CORE1",
137         .data = &((struct mod_power_domain_element_config) {
138             .attributes.pd_type = MOD_PD_TYPE_CORE,
139             .parent_idx = PD_SINGLE_CHIP_IDX_CLUSTER1,
140             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PPU_V1, 3),
141             .api_id = FWK_ID_API_INIT(
142                 FWK_MODULE_IDX_PPU_V1,
143                 MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER),
144             .allowed_state_mask_table = core_pd_allowed_state_mask_table,
145             .allowed_state_mask_table_size =
146                 FWK_ARRAY_SIZE(core_pd_allowed_state_mask_table)
147         }),
148     },
149     [PD_SINGLE_CHIP_IDX_CLUSTER0] = {
150         .name = "CLUS0",
151         .data = &((struct mod_power_domain_element_config) {
152             .attributes.pd_type = MOD_PD_TYPE_CLUSTER,
153             .parent_idx = PD_SINGLE_CHIP_IDX_SYSTOP0,
154             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PPU_V1, 4),
155             .api_id = FWK_ID_API_INIT(
156                 FWK_MODULE_IDX_PPU_V1,
157                 MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER),
158             .allowed_state_mask_table = cluster_pd_allowed_state_mask_table,
159             .allowed_state_mask_table_size =
160                 FWK_ARRAY_SIZE(cluster_pd_allowed_state_mask_table)
161         }),
162     },
163     [PD_SINGLE_CHIP_IDX_CLUSTER1] = {
164         .name = "CLUS1",
165         .data = &((struct mod_power_domain_element_config) {
166             .attributes.pd_type = MOD_PD_TYPE_CLUSTER,
167             .parent_idx = PD_SINGLE_CHIP_IDX_SYSTOP0,
168             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PPU_V1, 5),
169             .api_id = FWK_ID_API_INIT(
170                 FWK_MODULE_IDX_PPU_V1,
171                 MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER),
172             .allowed_state_mask_table = cluster_pd_allowed_state_mask_table,
173             .allowed_state_mask_table_size =
174                 FWK_ARRAY_SIZE(cluster_pd_allowed_state_mask_table)
175         }),
176     },
177     [PD_SINGLE_CHIP_IDX_DBGTOP0] = {
178         .name = "DBGTOP0",
179         .data = &((struct mod_power_domain_element_config) {
180             .attributes.pd_type = MOD_PD_TYPE_DEVICE_DEBUG,
181             .parent_idx = PD_SINGLE_CHIP_IDX_SYSTOP0,
182             .driver_id = FWK_ID_ELEMENT_INIT(
183                 FWK_MODULE_IDX_PPU_V0, PPU_V0_ELEMENT_IDX_DBGTOP),
184             .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0, 0),
185             .allowed_state_mask_table = toplevel_allowed_state_mask_table,
186             .allowed_state_mask_table_size =
187                 FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table)
188         }),
189     },
190     [PD_SINGLE_CHIP_IDX_GPUTOP0] = {
191         .name = "GPUTOP0",
192         .data = &((struct mod_power_domain_element_config) {
193             .attributes.pd_type = MOD_PD_TYPE_DEVICE,
194             .parent_idx = PD_SINGLE_CHIP_IDX_SYSTOP0,
195             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PPU_V1, 8),
196             .api_id = FWK_ID_API_INIT(
197                 FWK_MODULE_IDX_PPU_V1,
198                 MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER),
199             .allowed_state_mask_table = toplevel_allowed_state_mask_table,
200             .allowed_state_mask_table_size =
201                 FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table)
202         }),
203     },
204     [PD_SINGLE_CHIP_IDX_DPUTOP0] = {
205         .name = "DPUTOP0",
206         .data = &((struct mod_power_domain_element_config) {
207             .attributes.pd_type = MOD_PD_TYPE_DEVICE,
208             .parent_idx = PD_SINGLE_CHIP_IDX_SYSTOP0,
209             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PPU_V1, 9),
210             .api_id = FWK_ID_API_INIT(
211                 FWK_MODULE_IDX_PPU_V1,
212                 MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER),
213             .allowed_state_mask_table = toplevel_allowed_state_mask_table,
214             .allowed_state_mask_table_size =
215                 FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table)
216         }),
217     },
218     [PD_SINGLE_CHIP_IDX_SYSTOP0] = {
219         .name = "SYSTOP0",
220         .data = &((struct mod_power_domain_element_config) {
221             .attributes.pd_type = MOD_PD_TYPE_SYSTEM,
222             .parent_idx = PD_SINGLE_CHIP_IDX_NONE,
223             .driver_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SYSTEM_POWER),
224             .api_id = FWK_ID_API_INIT(
225                 FWK_MODULE_IDX_SYSTEM_POWER,
226                 MOD_SYSTEM_POWER_API_IDX_PD_DRIVER),
227             .allowed_state_mask_table = systop_allowed_state_mask_table,
228             .allowed_state_mask_table_size =
229                 FWK_ARRAY_SIZE(systop_allowed_state_mask_table)
230         }),
231     },
232     [PD_SINGLE_CHIP_IDX_COUNT] = { 0 },
233 };
234 
235 /*
236  * Function definitions with internal linkage
237  */
morello_power_domain_get_element_table(fwk_id_t module_id)238 static const struct fwk_element *morello_power_domain_get_element_table(
239     fwk_id_t module_id)
240 {
241     return morello_pd_single_chip_element_table;
242 }
243 
244 /*
245  * Power module configuration data
246  */
247 const struct fwk_module_config config_power_domain = {
248     .elements =
249         FWK_MODULE_DYNAMIC_ELEMENTS(morello_power_domain_get_element_table),
250     .data = &morello_power_domain_config,
251 };
252