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