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 "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     int status;
76     struct mod_juno_hdlcd_dev_config *config;
77     unsigned int i;
78     enum juno_idx_platform platform_id;
79     uintptr_t hdlcd_lookup = HDLCD_PRESET_TABLE_BASE;
80 
81     status = juno_id_get_platform(&platform_id);
82     if (status != FWK_SUCCESS) {
83         return NULL;
84     }
85 
86     for (i = 0; i < JUNO_HDLCD_ELEMENT_COUNT; i++) {
87         config = (struct mod_juno_hdlcd_dev_config *)
88             (juno_hdlcd_element_table[i].data);
89         if (SCC->GPR0 & SCC_GPR0_HIGH_PXLCLK_ENABLE) {
90             config->lookup_table_count =
91                 JUNO_CLOCK_HDLCD_LOOKUP_HIGH_PXCLK_ENABLE_COUNT;
92             config->max_rate = 210 * FWK_MHZ;
93             if (platform_id == JUNO_IDX_PLATFORM_RTL) {
94                 /* Check that the signatures are present */
95                 fwk_assert(
96                     ((struct juno_clock_hdlcd_lookup_high_pxlclk_enable *)
97                         hdlcd_lookup)->SIGNATURE_A == 0x9DCA7B7A);
98                 fwk_assert(
99                     ((struct juno_clock_hdlcd_lookup_high_pxlclk_enable *)
100                         hdlcd_lookup)->SIGNATURE_B == 0x5C7852A9);
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             if (platform_id == JUNO_IDX_PLATFORM_RTL) {
109                 /* Check that the signatures are present */
110                 fwk_assert(((struct juno_clock_hdlcd_lookup *)
111                     hdlcd_lookup)->SIGNATURE_A == 0x9DCA7B7A);
112                 fwk_assert(((struct juno_clock_hdlcd_lookup *)
113                     hdlcd_lookup)->SIGNATURE_B == 0x5C7852A9);
114             }
115             config->lookup_table = ((struct juno_clock_hdlcd_lookup *)
116                 HDLCD_PRESET_TABLE_BASE)->CLK;
117         }
118     }
119 
120     return juno_hdlcd_element_table;
121 }
122 
123 struct fwk_module_config config_juno_hdlcd = {
124     .elements = FWK_MODULE_DYNAMIC_ELEMENTS(juno_hdlcd_get_element_table),
125 };
126