1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2017-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 "sgm775_core.h"
10 #include "sgm775_mmap.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_mm.h>
18 #include <fwk_module.h>
19 #include <fwk_module_idx.h>
20 
21 #include <fmw_cmsis.h>
22 
23 #include <stddef.h>
24 #include <stdint.h>
25 
26 static const char *core_pd_name_table[SGM775_CORE_PER_CLUSTER_MAX] = {
27     "CLUS0CORE0", "CLUS0CORE1", "CLUS0CORE2", "CLUS0CORE3",
28     "CLUS0CORE4", "CLUS0CORE5", "CLUS0CORE6", "CLUS0CORE7",
29 };
30 
31 static uintptr_t core_pd_ppu_base_table[] = {
32     PPU_CLUS0CORE0_BASE, PPU_CLUS0CORE1_BASE, PPU_CLUS0CORE2_BASE,
33     PPU_CLUS0CORE3_BASE, PPU_CLUS0CORE4_BASE, PPU_CLUS0CORE5_BASE,
34     PPU_CLUS0CORE6_BASE, PPU_CLUS0CORE7_BASE
35 };
36 
37 static unsigned int core_pd_ppu_irq_table[] = {
38     PPU_CLUS0CORE0_IRQ, PPU_CLUS0CORE1_IRQ, PPU_CLUS0CORE2_IRQ,
39     PPU_CLUS0CORE3_IRQ, PPU_CLUS0CORE4_IRQ, PPU_CLUS0CORE5_IRQ,
40     PPU_CLUS0CORE6_IRQ, PPU_CLUS0CORE7_IRQ
41 };
42 
43 struct mod_ppu_v1_config sgm775_ppu_v1_notification_config = {
44     .pd_notification_id = FWK_ID_NOTIFICATION_INIT(
45         FWK_MODULE_IDX_POWER_DOMAIN,
46         MOD_PD_NOTIFICATION_IDX_POWER_STATE_TRANSITION),
47 };
48 
sgm775_ppu_v1_get_element_table(fwk_id_t module_id)49 static const struct fwk_element *sgm775_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     unsigned int core_idx;
55 
56     /*
57      * Allocate element descriptors based on:
58      *   Number of cores
59      *   +1 cluster descriptor
60      *   +1 terminator descriptor
61      */
62     element_table = fwk_mm_calloc(sgm775_core_get_count() + 2,
63                                   sizeof(struct fwk_element));
64 
65     pd_config_table = fwk_mm_calloc(sgm775_core_get_count() + 1,
66                                     sizeof(struct mod_ppu_v1_pd_config));
67 
68     for (core_idx = 0; core_idx < sgm775_core_get_count(); core_idx++) {
69         element = &element_table[core_idx];
70         pd_config = &pd_config_table[core_idx];
71 
72         element->name = core_pd_name_table[core_idx];
73         element->data = pd_config;
74 
75         pd_config->pd_type = MOD_PD_TYPE_CORE;
76         pd_config->ppu.reg_base = core_pd_ppu_base_table[core_idx];
77         pd_config->ppu.irq = core_pd_ppu_irq_table[core_idx];
78         pd_config->cluster_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_PPU_V1,
79                                                sgm775_core_get_count());
80         pd_config->observer_id = FWK_ID_NONE;
81     }
82 
83     element = &element_table[sgm775_core_get_count()];
84     pd_config = &pd_config_table[sgm775_core_get_count()];
85 
86     element->name = "CLUS0";
87     element->data = pd_config;
88 
89     pd_config->pd_type = MOD_PD_TYPE_CLUSTER;
90     pd_config->ppu.reg_base = PPU_CLUS0_BASE;
91     pd_config->ppu.irq = PPU_CLUS0_IRQ;
92     pd_config->observer_id = FWK_ID_NONE;
93 
94     sgm775_ppu_v1_notification_config.pd_source_id = FWK_ID_ELEMENT(
95         FWK_MODULE_IDX_POWER_DOMAIN,
96         CONFIG_POWER_DOMAIN_SYSTOP_SYSTEM + sgm775_core_get_count() +
97             sgm775_cluster_get_count());
98 
99     return element_table;
100 }
101 
102 /*
103  * Power module configuration data
104  */
105 struct fwk_module_config config_ppu_v1 = {
106     .data = &sgm775_ppu_v1_notification_config,
107     .elements = FWK_MODULE_DYNAMIC_ELEMENTS(sgm775_ppu_v1_get_element_table),
108 };
109