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