1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2019-2023, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "juno_clock.h"
9 #include "juno_id.h"
10 #include "juno_mmap.h"
11 #include "juno_scc.h"
12 
13 #include <mod_clock.h>
14 #include <mod_juno_cdcel937.h>
15 #include <mod_juno_hdlcd.h>
16 
17 #include <fwk_assert.h>
18 #include <fwk_element.h>
19 #include <fwk_id.h>
20 #include <fwk_macros.h>
21 #include <fwk_module.h>
22 #include <fwk_module_idx.h>
23 #include <fwk_status.h>
24 
25 #include <stddef.h>
26 #include <stdint.h>
27 
28 enum juno_hdlcd_element_idx {
29     JUNO_HDLCD_ELEMENT_IDX_HDLCD0,
30     JUNO_HDLCD_ELEMENT_IDX_HDLCD1,
31     JUNO_HDLCD_ELEMENT_COUNT,
32 };
33 
34 static const struct fwk_element juno_hdlcd_element_table[] = {
35     [JUNO_CLOCK_HDLCD_IDX_HDLCD0] = {
36         .name = "",
37         .data = &(struct mod_juno_hdlcd_dev_config) {
38             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_CDCEL937,
39                 JUNO_CLOCK_CDCEL937_IDX_HDLCD0),
40             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_CDCEL937,
41                 MOD_JUNO_CDCEL937_API_IDX_HDLCD_DRIVER),
42             .clock_hal_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK,
43                 JUNO_CLOCK_IDX_HDLCD0),
44             .clock_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_CLOCK,
45                 MOD_CLOCK_API_TYPE_DRIVER_RESPONSE),
46             .scc_control = &SCC->HDLCD0_CONTROL,
47             .min_rate = 23750 * FWK_KHZ,
48             .min_step = 250 * FWK_KHZ,
49             .rate_type = MOD_CLOCK_RATE_TYPE_CONTINUOUS,
50         }
51     },
52     [JUNO_CLOCK_HDLCD_IDX_HDLCD1] = {
53         .name = "",
54         .data = &(struct mod_juno_hdlcd_dev_config) {
55             .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_CDCEL937,
56                 JUNO_CLOCK_CDCEL937_IDX_HDLCD1),
57             .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_JUNO_CDCEL937,
58                 MOD_JUNO_CDCEL937_API_IDX_HDLCD_DRIVER),
59             .clock_hal_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK,
60                 JUNO_CLOCK_IDX_HDLCD1),
61             .clock_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_CLOCK,
62                 MOD_CLOCK_API_TYPE_DRIVER_RESPONSE),
63             .scc_control = &SCC->HDLCD1_CONTROL,
64             .min_rate = 23750 * FWK_KHZ,
65             .min_step = 250 * FWK_KHZ,
66             .rate_type = MOD_CLOCK_RATE_TYPE_CONTINUOUS,
67         }
68     },
69     [JUNO_CLOCK_HDLCD_IDX_COUNT] = { 0 },
70 };
71 
juno_hdlcd_get_element_table(fwk_id_t module_id)72 static const struct fwk_element *juno_hdlcd_get_element_table(
73         fwk_id_t module_id)
74 {
75     struct mod_juno_hdlcd_dev_config *config;
76     unsigned int i;
77 
78 #if (PLATFORM_VARIANT == JUNO_VARIANT_BOARD)
79     uintptr_t hdlcd_lookup = HDLCD_PRESET_TABLE_BASE;
80 #endif
81 
82     for (i = 0; i < JUNO_HDLCD_ELEMENT_COUNT; i++) {
83         config = (struct mod_juno_hdlcd_dev_config *)
84             (juno_hdlcd_element_table[i].data);
85         if (SCC->GPR0 & SCC_GPR0_HIGH_PXLCLK_ENABLE) {
86             config->lookup_table_count =
87                 JUNO_CLOCK_HDLCD_LOOKUP_HIGH_PXCLK_ENABLE_COUNT;
88             config->max_rate = 210 * FWK_MHZ;
89 
90 #if (PLATFORM_VARIANT == JUNO_VARIANT_BOARD)
91             /* Check that the signatures are present */
92             fwk_assert(
93                 ((struct juno_clock_hdlcd_lookup_high_pxlclk_enable *)
94                      hdlcd_lookup)
95                     ->SIGNATURE_A == 0x9DCA7B7A);
96             fwk_assert(
97                 ((struct juno_clock_hdlcd_lookup_high_pxlclk_enable *)
98                      hdlcd_lookup)
99                     ->SIGNATURE_B == 0x5C7852A9);
100 #endif
101 
102             config->lookup_table =
103                 ((struct juno_clock_hdlcd_lookup_high_pxlclk_enable *)
104                     HDLCD_PRESET_TABLE_BASE)->CLK;
105         } else {
106             config->lookup_table_count = JUNO_CLOCK_HDLCD_LOOKUP_COUNT;
107             config->max_rate = 165 * FWK_MHZ;
108 
109 #if (PLATFORM_VARIANT == JUNO_VARIANT_BOARD)
110             /* Check that the signatures are present */
111             fwk_assert(
112                 ((struct juno_clock_hdlcd_lookup *)hdlcd_lookup)->SIGNATURE_A ==
113                 0x9DCA7B7A);
114             fwk_assert(
115                 ((struct juno_clock_hdlcd_lookup *)hdlcd_lookup)->SIGNATURE_B ==
116                 0x5C7852A9);
117 #endif
118 
119             config->lookup_table = ((struct juno_clock_hdlcd_lookup *)
120                 HDLCD_PRESET_TABLE_BASE)->CLK;
121         }
122     }
123 
124     return juno_hdlcd_element_table;
125 }
126 
127 struct fwk_module_config config_juno_hdlcd = {
128     .elements = FWK_MODULE_DYNAMIC_ELEMENTS(juno_hdlcd_get_element_table),
129 };
130