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