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