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_cmn_booker.h>
13 #include <mod_msys_rom.h>
14 #include <mod_power_domain.h>
15 #include <mod_ppu_v1.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 
25 #include <stdio.h>
26 #include <string.h>
27 
28 /* Maximum PPU core name size including the null terminator */
29 #define PPU_CORE_NAME_SIZE 12
30 
31 /* Maximum PPU cluster name size including the null terminator */
32 #define PPU_CLUS_NAME_SIZE 6
33 
34 /* Lookup table for translating cluster indicies into CMN_BOOKER node IDs */
35 static const unsigned int cluster_idx_to_node_id[1] = { 68 };
36 
37 static const struct fwk_element ppu_v1_system_element_table[1] = {
38     {
39         .name = "SYS0",
40         .data = &((struct mod_ppu_v1_pd_config){
41             .pd_type = MOD_PD_TYPE_SYSTEM,
42             .ppu.reg_base = SCP_PPU_SYS0_BASE,
43             .observer_id = FWK_ID_NONE_INIT,
44             .default_power_on = true,
45         }),
46     },
47 };
48 
tc1_ppu_v1_get_element_table(fwk_id_t module_id)49 static const struct fwk_element *tc1_ppu_v1_get_element_table(
50     fwk_id_t module_id)
51 {
52     struct fwk_element *element_table, *element;
53     struct mod_ppu_v1_pd_config *pd_config_table, *pd_config;
54 
55     /*
56      * Allocate element descriptors based on:
57      *   Core0
58      *   + Cluster0
59      *   + Number of system power domain descriptors
60      *   + 1 terminator descriptor
61      */
62     element_table = fwk_mm_calloc(
63         2 + FWK_ARRAY_SIZE(ppu_v1_system_element_table) + 1,
64         sizeof(struct fwk_element));
65     if (element_table == NULL) {
66         return NULL;
67     }
68 
69     pd_config_table = fwk_mm_calloc(2, sizeof(struct mod_ppu_v1_pd_config));
70     if (pd_config_table == NULL) {
71         return NULL;
72     }
73 
74     // pd_config for core0
75     element = &element_table[0];
76     pd_config = &pd_config_table[0];
77 
78     element->name = fwk_mm_alloc(PPU_CORE_NAME_SIZE, 1);
79     if (element->name == NULL) {
80         return NULL;
81     }
82 
83     (void)snprintf((char *)element->name, PPU_CORE_NAME_SIZE, "CLUS0CORE0");
84 
85     element->data = pd_config;
86 
87     pd_config->pd_type = MOD_PD_TYPE_CORE;
88     pd_config->ppu.reg_base = SCP_PPU_CORE_BASE(0);
89     pd_config->ppu.irq = FWK_INTERRUPT_NONE;
90     pd_config->cluster_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1, 1);
91     pd_config->observer_id = FWK_ID_NONE;
92 
93     // pd_config for cluster0
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     (void)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(tc1_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_MSYS_ROM,
132                 MOD_MSYS_ROM_NOTIFICATION_IDX_POWER_SYSTOP),
133             .pd_source_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_MSYS_ROM),
134         },
135 };
136