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