1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2019-2021, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "config_mock_clock.h"
9 #include "config_power_domain.h"
10 #include "juno_clock.h"
11 #include "juno_id.h"
12 
13 #include <mod_clock.h>
14 #include <mod_juno_cdcel937.h>
15 #include <mod_juno_hdlcd.h>
16 #include <mod_juno_soc_clock_ram.h>
17 #include <mod_mock_clock.h>
18 #include <mod_power_domain.h>
19 
20 #include <fwk_element.h>
21 #include <fwk_id.h>
22 #include <fwk_module.h>
23 #include <fwk_module_idx.h>
24 
25 static struct fwk_element clock_dev_desc_table[] = {
26     [JUNO_CLOCK_IDX_I2SCLK] = {
27         .name = "I2SCLK",
28         .data = &((struct mod_clock_dev_config) {
29             .pd_source_id = FWK_ID_NONE_INIT,
30         }),
31     },
32     [JUNO_CLOCK_IDX_HDLCDREFCLK] = {
33         .name = "HDLCDREFCLK",
34         .data = &((struct mod_clock_dev_config) {
35             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_CDCEL937,
36                 JUNO_CLOCK_CDCEL937_IDX_HDLCDREFCLK),
37             .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_CDCEL937,
38                                       MOD_JUNO_CDCEL937_API_IDX_CLOCK_DRIVER),
39             .pd_source_id = FWK_ID_NONE_INIT,
40         }),
41     },
42     [JUNO_CLOCK_IDX_HDLCDPXL] = {
43         .name = "HDLCDPXL",
44         .data = &((struct mod_clock_dev_config) {
45             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_CDCEL937,
46                 JUNO_CLOCK_CDCEL937_IDX_HDLCDPXL),
47             .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_CDCEL937,
48                                       MOD_JUNO_CDCEL937_API_IDX_CLOCK_DRIVER),
49             .pd_source_id = FWK_ID_NONE_INIT,
50         }),
51     },
52     [JUNO_CLOCK_IDX_HDLCD0] = {
53         .name = "HDLCD_0",
54         .data = &((struct mod_clock_dev_config) {
55             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_HDLCD,
56                 JUNO_CLOCK_HDLCD_IDX_HDLCD0),
57             .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_HDLCD,
58                                       MOD_JUNO_HDLCD_API_IDX_CLOCK_DRIVER),
59             .pd_source_id = FWK_ID_NONE_INIT,
60         }),
61     },
62     [JUNO_CLOCK_IDX_HDLCD1] = {
63         .name = "HDLCD_1",
64         .data = &((struct mod_clock_dev_config) {
65             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_HDLCD,
66                 JUNO_CLOCK_HDLCD_IDX_HDLCD1),
67             .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_HDLCD,
68                                       MOD_JUNO_HDLCD_API_IDX_CLOCK_DRIVER),
69             .pd_source_id = FWK_ID_NONE_INIT,
70         }),
71     },
72     [JUNO_CLOCK_IDX_BIGCLK] = {
73         .name = "BIG_CLK",
74         .data = &((struct mod_clock_dev_config) {
75             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_SOC_CLOCK_RAM,
76                 JUNO_CLOCK_SOC_RAM_IDX_BIGCLK),
77             .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_SOC_CLOCK_RAM,
78                                       MOD_JUNO_SOC_CLOCK_RAM_API_IDX_DRIVER),
79             .pd_source_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_POWER_DOMAIN,
80                 POWER_DOMAIN_IDX_BIG_SSTOP),
81         }),
82     },
83     [JUNO_CLOCK_IDX_LITTLECLK] = {
84         .name = "LITTLE_CLK",
85         .data = &((struct mod_clock_dev_config) {
86             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_SOC_CLOCK_RAM,
87                 JUNO_CLOCK_SOC_RAM_IDX_LITTLECLK),
88             .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_SOC_CLOCK_RAM,
89                                       MOD_JUNO_SOC_CLOCK_RAM_API_IDX_DRIVER),
90             .pd_source_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_POWER_DOMAIN,
91                 POWER_DOMAIN_IDX_LITTLE_SSTOP),
92         }),
93     },
94     [JUNO_CLOCK_IDX_GPUCLK] = {
95         .name = "GPU_CLK",
96         .data = &((struct mod_clock_dev_config) {
97             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_SOC_CLOCK_RAM,
98                 JUNO_CLOCK_SOC_RAM_IDX_GPUCLK),
99             .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_SOC_CLOCK_RAM,
100                                       MOD_JUNO_SOC_CLOCK_RAM_API_IDX_DRIVER),
101             .pd_source_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_POWER_DOMAIN,
102                 POWER_DOMAIN_IDX_GPUTOP),
103         }),
104     },
105     [JUNO_CLOCK_IDX_COUNT] = { 0 }, /* Termination description. */
106 };
107 
clock_get_dev_desc_table(fwk_id_t module_id)108 static const struct fwk_element *clock_get_dev_desc_table(fwk_id_t module_id)
109 {
110     int status;
111     enum juno_idx_platform platform_id = JUNO_IDX_PLATFORM_COUNT;
112     struct mod_clock_dev_config *dev_cfg;
113 
114     status = juno_id_get_platform(&platform_id);
115     if (!fwk_expect(status == FWK_SUCCESS)) {
116         return NULL;
117     }
118 
119     /*
120      * When running under an FVP the I2S clock does not fully function,
121      * as it requires the I2C hardware interrupt to properly work. This
122      * is replaced with the mock clock.
123      *
124      * Referencing and dereferencing is required to bypass the const qualifier.
125      */
126     dev_cfg = (struct mod_clock_dev_config
127                    *)(clock_dev_desc_table[JUNO_CLOCK_IDX_I2SCLK].data);
128     if (platform_id == JUNO_IDX_PLATFORM_FVP) {
129         *((fwk_id_t *)(&dev_cfg->api_id)) = (fwk_id_t)FWK_ID_API_INIT(
130             FWK_MODULE_IDX_MOCK_CLOCK, MOD_MOCK_CLOCK_API_TYPE_DRIVER);
131         *((fwk_id_t *)(&dev_cfg->driver_id)) = (fwk_id_t)FWK_ID_ELEMENT_INIT(
132             FWK_MODULE_IDX_MOCK_CLOCK, MOD_MOCK_CLOCK_ELEMENT_IDX_I2S);
133     } else {
134         *((fwk_id_t *)(&dev_cfg->api_id)) = (fwk_id_t)FWK_ID_API_INIT(
135             FWK_MODULE_IDX_JUNO_CDCEL937,
136             MOD_JUNO_CDCEL937_API_IDX_CLOCK_DRIVER);
137         *((fwk_id_t *)(&dev_cfg->driver_id)) = (fwk_id_t)FWK_ID_ELEMENT_INIT(
138             FWK_MODULE_IDX_JUNO_CDCEL937, JUNO_CLOCK_CDCEL937_IDX_I2SCLK);
139     }
140 
141     return clock_dev_desc_table;
142 }
143 
144 struct fwk_module_config config_clock = {
145     .data =
146         &(struct mod_clock_config){
147             .pd_transition_notification_id = FWK_ID_NOTIFICATION_INIT(
148                 FWK_MODULE_IDX_POWER_DOMAIN,
149                 MOD_PD_NOTIFICATION_IDX_POWER_STATE_TRANSITION),
150             .pd_pre_transition_notification_id = FWK_ID_NOTIFICATION_INIT(
151                 FWK_MODULE_IDX_POWER_DOMAIN,
152                 MOD_PD_NOTIFICATION_IDX_POWER_STATE_PRE_TRANSITION),
153         },
154 
155     .elements = FWK_MODULE_DYNAMIC_ELEMENTS(clock_get_dev_desc_table),
156 };
157