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