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 "scp_mmap.h"
10 #include "tc1_core.h"
11
12 #include <mod_power_domain.h>
13 #include <mod_ppu_v1.h>
14
15 #include <fwk_element.h>
16 #include <fwk_id.h>
17 #include <fwk_interrupt.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 <stdio.h>
24 #include <string.h>
25
26 /* Maximum PPU core name size including the null terminator */
27 #define PPU_CORE_NAME_SIZE 12
28
29 /* Maximum PPU cluster name size including the null terminator */
30 #define PPU_CLUS_NAME_SIZE 6
31
32 /* Cluster ID for Theodul DSU */
33 #define CLUSTER_ID 0
34
35 /* Module configuration data */
36 static struct mod_ppu_v1_config ppu_v1_config_data = {
37 .pd_notification_id = FWK_ID_NOTIFICATION_INIT(
38 FWK_MODULE_IDX_POWER_DOMAIN,
39 MOD_PD_NOTIFICATION_IDX_POWER_STATE_TRANSITION),
40 };
41
42 static const struct fwk_element ppu_v1_system_element_table[1] = {
43 [0] =
44 {
45 .name = "SYS0",
46 .data = &((struct mod_ppu_v1_pd_config){
47 .pd_type = MOD_PD_TYPE_SYSTEM,
48 .ppu.reg_base = SCP_PPU_SYS0_BASE,
49 .observer_id = FWK_ID_NONE_INIT,
50 }),
51 },
52 };
53
ppu_v1_get_element_table(fwk_id_t module_id)54 static const struct fwk_element *ppu_v1_get_element_table(fwk_id_t module_id)
55 {
56 struct fwk_element *element_table, *element;
57 struct mod_ppu_v1_pd_config *pd_config_table, *pd_config;
58 unsigned int core_idx;
59 unsigned int core_count;
60 unsigned int cluster_count;
61 unsigned int core_element_count = 0;
62
63 core_count = tc1_core_get_core_count();
64 cluster_count = tc1_core_get_cluster_count();
65
66 /*
67 * Allocate element descriptors based on:
68 * Number of cores
69 * + Number of cluster descriptors
70 * + Number of system power domain descriptors
71 * + 1 terminator descriptor
72 */
73 element_table = fwk_mm_calloc(
74 core_count + cluster_count +
75 FWK_ARRAY_SIZE(ppu_v1_system_element_table) + 1,
76 sizeof(struct fwk_element));
77 if (element_table == NULL) {
78 return NULL;
79 }
80
81 pd_config_table = fwk_mm_calloc(
82 core_count + cluster_count, sizeof(struct mod_ppu_v1_pd_config));
83 if (pd_config_table == NULL) {
84 return NULL;
85 }
86
87 for (core_idx = 0;
88 core_idx < tc1_core_get_core_per_cluster_count(CLUSTER_ID);
89 core_idx++) {
90 element = &element_table[core_element_count];
91 pd_config = &pd_config_table[core_element_count];
92
93 element->name = fwk_mm_alloc(PPU_CORE_NAME_SIZE, 1);
94 if (element->name == NULL) {
95 return NULL;
96 }
97
98 (void)snprintf(
99 (char *)element->name, PPU_CORE_NAME_SIZE, "CORE%u", core_idx);
100
101 element->data = pd_config;
102
103 pd_config->pd_type = MOD_PD_TYPE_CORE;
104 pd_config->ppu.reg_base = SCP_PPU_CORE_BASE(core_idx);
105 pd_config->ppu.irq = FWK_INTERRUPT_NONE;
106 pd_config->cluster_id =
107 FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1, core_count);
108 pd_config->observer_id = FWK_ID_NONE;
109 core_element_count++;
110 }
111
112 element = &element_table[core_count];
113 pd_config = &pd_config_table[core_count];
114
115 element->name = fwk_mm_alloc(PPU_CLUS_NAME_SIZE, 1);
116 if (element->name == NULL) {
117 return NULL;
118 }
119
120 element->data = pd_config;
121
122 pd_config->pd_type = MOD_PD_TYPE_CLUSTER;
123 pd_config->ppu.reg_base = SCP_PPU_CLUSTER_BASE;
124 pd_config->ppu.irq = FWK_INTERRUPT_NONE;
125 pd_config->observer_id = FWK_ID_NONE;
126
127 (void)memcpy(
128 &element_table[core_count + cluster_count],
129 ppu_v1_system_element_table,
130 sizeof(ppu_v1_system_element_table));
131
132 /*
133 * Configure pd_source_id with the SYSTOP identifier from the power domain
134 * module which is dynamically defined based on the number of cores.
135 */
136 ppu_v1_config_data.pd_source_id = fwk_id_build_element_id(
137 fwk_module_id_power_domain,
138 core_count + cluster_count + PD_STATIC_DEV_IDX_SYSTOP);
139
140 return element_table;
141 }
142
143 /*
144 * Power module configuration data
145 */
146 const struct fwk_module_config config_ppu_v1 = {
147 .elements = FWK_MODULE_DYNAMIC_ELEMENTS(ppu_v1_get_element_table),
148 .data = &ppu_v1_config_data,
149 };
150