1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2022, 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 "tc2_core.h"
11
12 #include <mod_cmn_booker.h>
13 #include <mod_power_domain.h>
14 #include <mod_ppu_v1.h>
15 #include <mod_tc2_bl1.h>
16
17 #include <fwk_element.h>
18 #include <fwk_id.h>
19 #include <fwk_interrupt.h>
20 #include <fwk_macros.h>
21 #include <fwk_mm.h>
22 #include <fwk_module.h>
23 #include <fwk_module_idx.h>
24 #include <fwk_string.h>
25
26 #include <stdio.h>
27 #include <string.h>
28
29 /* Maximum PPU core name size including the null terminator */
30 #define PPU_CORE_NAME_SIZE 12
31
32 /* Maximum PPU cluster name size including the null terminator */
33 #define PPU_CLUS_NAME_SIZE 6
34
35 /* Lookup table for translating cluster indicies into CMN_BOOKER node IDs */
36 static const unsigned int cluster_idx_to_node_id[1] = { 68 };
37
38 static const struct fwk_element ppu_v1_system_element_table[1] = {
39 {
40 .name = "SYS0",
41 .data = &((struct mod_ppu_v1_pd_config){
42 .pd_type = MOD_PD_TYPE_SYSTEM,
43 .ppu.reg_base = SCP_PPU_SYS0_BASE,
44 .observer_id = FWK_ID_NONE_INIT,
45 .default_power_on = true,
46 }),
47 },
48 };
49
tc2_ppu_v1_get_element_table(fwk_id_t module_id)50 static const struct fwk_element *tc2_ppu_v1_get_element_table(
51 fwk_id_t module_id)
52 {
53 struct fwk_element *element_table, *element;
54 struct mod_ppu_v1_pd_config *pd_config_table, *pd_config;
55
56 /*
57 * Allocate element descriptors based on:
58 * Core0
59 * + Cluster0
60 * + Number of system power domain descriptors
61 * + 1 terminator descriptor
62 */
63 element_table = fwk_mm_calloc(
64 2 + FWK_ARRAY_SIZE(ppu_v1_system_element_table) + 1,
65 sizeof(struct fwk_element));
66 if (element_table == NULL) {
67 return NULL;
68 }
69
70 pd_config_table = fwk_mm_calloc(2, sizeof(struct mod_ppu_v1_pd_config));
71 if (pd_config_table == NULL) {
72 return NULL;
73 }
74
75 // pd_config for core0
76 element = &element_table[0];
77 pd_config = &pd_config_table[0];
78
79 element->name = fwk_mm_alloc(PPU_CORE_NAME_SIZE, 1);
80 if (element->name == NULL) {
81 return NULL;
82 }
83
84 (void)snprintf((char *)element->name, PPU_CORE_NAME_SIZE, "CLUS0CORE0");
85
86 element->data = pd_config;
87
88 pd_config->pd_type = MOD_PD_TYPE_CORE;
89 pd_config->ppu.reg_base = SCP_PPU_CORE_BASE(0);
90 pd_config->ppu.irq = FWK_INTERRUPT_NONE;
91 pd_config->cluster_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1, 1);
92 pd_config->observer_id = FWK_ID_NONE;
93
94 element = &element_table[1];
95 pd_config = &pd_config_table[1];
96
97 element->name = fwk_mm_alloc(PPU_CLUS_NAME_SIZE, 1);
98 if (element->name == NULL) {
99 return NULL;
100 }
101
102 (void)snprintf((char *)element->name, PPU_CLUS_NAME_SIZE, "CLUS0");
103
104 element->data = pd_config;
105
106 pd_config->pd_type = MOD_PD_TYPE_CLUSTER;
107 pd_config->ppu.reg_base = SCP_PPU_CLUSTER_BASE;
108 pd_config->ppu.irq = FWK_INTERRUPT_NONE;
109
110 pd_config->observer_id = fwk_module_id_cmn_booker;
111 pd_config->observer_api = FWK_ID_API(
112 FWK_MODULE_IDX_CMN_BOOKER, MOD_CMN_BOOKER_API_IDX_PPU_OBSERVER);
113 pd_config->post_ppu_on_param = (void *)&cluster_idx_to_node_id[0];
114
115 fwk_str_memcpy(
116 &element_table[2],
117 ppu_v1_system_element_table,
118 sizeof(ppu_v1_system_element_table));
119
120 return element_table;
121 }
122
123 /*
124 * Power module configuration data
125 */
126 struct fwk_module_config config_ppu_v1 = {
127 .elements = FWK_MODULE_DYNAMIC_ELEMENTS(tc2_ppu_v1_get_element_table),
128 .data =
129 &(struct mod_ppu_v1_config){
130 .pd_notification_id = FWK_ID_NOTIFICATION_INIT(
131 FWK_MODULE_IDX_TC2_BL1,
132 MOD_TC2_BL1_NOTIFICATION_IDX_POWER_SYSTOP),
133 .pd_source_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_TC2_BL1),
134 },
135 };
136