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_v0.h"
10 #include "sgm775_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  * While the clusters may reach a SLEEP state, SLEEP does not appear in this
51  * table. This is because the PPU driver backing the clusters will not accept a
52  * manual SLEEP request, but will transition to it automatically when possible.
53  */
54 static const uint32_t cluster_pd_allowed_state_mask_table[] = {
55     [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK,
56     [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK,
57     [MOD_SYSTEM_POWER_POWER_STATE_SLEEP0] = MOD_PD_STATE_OFF_MASK,
58     [MOD_SYSTEM_POWER_POWER_STATE_SLEEP1] = MOD_PD_STATE_OFF_MASK
59 };
60 
61 /* Mask of the allowed states for a core depending on the cluster states. */
62 static const uint32_t core_pd_allowed_state_mask_table[] = {
63     [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK,
64     [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK |
65         MOD_PD_STATE_SLEEP_MASK,
66     [MOD_PD_STATE_SLEEP] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_SLEEP_MASK,
67 };
68 
69 /* Power module specific configuration data (none) */
70 static const struct mod_power_domain_config sgm775_power_domain_config = { 0 };
71 
72 static struct fwk_element sgm775_power_domain_static_element_table[] = {
73     [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DBGTOP] = {
74         .name = "DBGTOP",
75         .data = &((struct mod_power_domain_element_config) {
76             .attributes.pd_type = MOD_PD_TYPE_DEVICE_DEBUG,
77             .driver_id = FWK_ID_ELEMENT_INIT(
78                 FWK_MODULE_IDX_PPU_V0, PPU_V0_ELEMENT_IDX_DBGTOP),
79             .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0, 0),
80             .allowed_state_mask_table = toplevel_allowed_state_mask_table,
81             .allowed_state_mask_table_size =
82                 FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table)
83         }),
84     },
85     [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU0TOP] = {
86         .name = "DPU0TOP",
87         .data = &((struct mod_power_domain_element_config) {
88             .attributes.pd_type = MOD_PD_TYPE_DEVICE,
89             .driver_id = FWK_ID_ELEMENT_INIT(
90                 FWK_MODULE_IDX_PPU_V0, PPU_V0_ELEMENT_IDX_DPU0TOP),
91             .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0, 0),
92             .allowed_state_mask_table = toplevel_allowed_state_mask_table,
93             .allowed_state_mask_table_size =
94                 FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table)
95         }),
96     },
97     [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU1TOP] = {
98         .name = "DPU1TOP",
99         .data = &((struct mod_power_domain_element_config) {
100             .attributes.pd_type = MOD_PD_TYPE_DEVICE,
101             .driver_id = FWK_ID_ELEMENT_INIT(
102                 FWK_MODULE_IDX_PPU_V0, PPU_V0_ELEMENT_IDX_DPU1TOP),
103             .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0, 0),
104             .allowed_state_mask_table = toplevel_allowed_state_mask_table,
105             .allowed_state_mask_table_size =
106                 FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table)
107         }),
108     },
109     [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_GPUTOP] = {
110         .name = "GPUTOP",
111         .data = &((struct mod_power_domain_element_config) {
112             .attributes.pd_type = MOD_PD_TYPE_DEVICE,
113             .driver_id = FWK_ID_ELEMENT_INIT(
114                 FWK_MODULE_IDX_PPU_V0, PPU_V0_ELEMENT_IDX_GPUTOP),
115             .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0, 0),
116             .allowed_state_mask_table = toplevel_allowed_state_mask_table,
117             .allowed_state_mask_table_size =
118                 FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table)
119         }),
120     },
121     [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_VPUTOP] = {
122         .name = "VPUTOP",
123         .data = &((struct mod_power_domain_element_config) {
124             .attributes.pd_type = MOD_PD_TYPE_DEVICE,
125             .driver_id = FWK_ID_ELEMENT_INIT(
126                 FWK_MODULE_IDX_PPU_V0, PPU_V0_ELEMENT_IDX_VPUTOP),
127             .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_PPU_V0, 0),
128             .allowed_state_mask_table = toplevel_allowed_state_mask_table,
129             .allowed_state_mask_table_size =
130                 FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table)
131         }),
132     },
133     [CONFIG_POWER_DOMAIN_SYSTOP_SYSTEM] = {
134         .name = "SYSTOP",
135         .data = &((struct mod_power_domain_element_config) {
136             .attributes.pd_type = MOD_PD_TYPE_SYSTEM,
137             .parent_idx = CONFIG_POWER_DOMAIN_NONE,
138             .driver_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SYSTEM_POWER),
139             .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_POWER,
140                 MOD_SYSTEM_POWER_API_IDX_PD_DRIVER),
141             .allowed_state_mask_table = systop_allowed_state_mask_table,
142             .allowed_state_mask_table_size =
143                 FWK_ARRAY_SIZE(systop_allowed_state_mask_table)
144         }),
145     },
146 };
147 
148 /*
149  * Function definitions with internal linkage
150  */
sgm775_power_domain_get_element_table(fwk_id_t module_id)151 static const struct fwk_element *sgm775_power_domain_get_element_table
152     (fwk_id_t module_id)
153 {
154     return create_power_domain_element_table(
155         sgm775_core_get_count(),
156         sgm775_cluster_get_count(),
157         FWK_MODULE_IDX_PPU_V1,
158         MOD_PPU_V1_API_IDX_POWER_DOMAIN_DRIVER,
159         core_pd_allowed_state_mask_table,
160         FWK_ARRAY_SIZE(core_pd_allowed_state_mask_table),
161         cluster_pd_allowed_state_mask_table,
162         FWK_ARRAY_SIZE(cluster_pd_allowed_state_mask_table),
163         sgm775_power_domain_static_element_table,
164         FWK_ARRAY_SIZE(sgm775_power_domain_static_element_table));
165 }
166 
167 /*
168  * Power module configuration data
169  */
170 struct fwk_module_config config_power_domain = {
171     .data = &sgm775_power_domain_config,
172     .elements =
173         FWK_MODULE_DYNAMIC_ELEMENTS(sgm775_power_domain_get_element_table),
174 };
175