blob: 118492872373350d24e3c928620eb8c701041ebe [file] [log] [blame]
Sheetal Tigadoli2a96dc22019-12-18 12:01:01 +05301/*
2 * Copyright (c) 2016-2020, Broadcom
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <stdint.h>
8
9#include <common/debug.h>
10#include <lib/mmio.h>
11
12#include <dmu.h>
13
14#define IHOST0_CONFIG_ROOT 0x66000000
15#define IHOST1_CONFIG_ROOT 0x66002000
16#define IHOST2_CONFIG_ROOT 0x66004000
17#define IHOST3_CONFIG_ROOT 0x66006000
18#define A72_CRM_PLL_PWR_ON 0x00000070
19#define A72_CRM_PLL_PWR_ON__PLL0_RESETB_R 4
20#define A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R 5
21#define A72_CRM_PLL_CHNL_BYPS_EN 0x000000ac
22#define A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R 0
23#define A72_CRM_PLL_CHNL_BYPS_EN_DATAMASK 0x0000ec1f
24#define A72_CRM_PLL_CMD 0x00000080
25#define A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_VCO_R 0
26#define A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_POST_R 1
27#define A72_CRM_PLL_STATUS 0x00000084
28#define A72_CRM_PLL_STATUS__PLL0_LOCK_R 9
29#define A72_CRM_PLL0_CTRL1 0x00000100
30#define A72_CRM_PLL0_CTRL2 0x00000104
31#define A72_CRM_PLL0_CTRL3 0x00000108
32#define A72_CRM_PLL0_CTRL3__PLL0_PDIV_R 12
33#define A72_CRM_PLL0_CTRL4 0x0000010c
34#define A72_CRM_PLL0_CTRL4__PLL0_KP_R 0
35#define A72_CRM_PLL0_CTRL4__PLL0_KI_R 4
36#define A72_CRM_PLL0_CTRL4__PLL0_KA_R 7
37#define A72_CRM_PLL0_CTRL4__PLL0_FREFEFF_INFO_R 10
38
39#define PLL_MODE_VCO 0x0
40#define PLL_MODE_BYPASS 0x1
41#define PLL_RESET_TYPE_PLL 0x1
42#define PLL_RESET_TYPE_POST 0x2
43#define PLL_VCO 0x1
44#define PLL_POSTDIV 0x2
45#define ARM_FREQ_3G PLL_FREQ_FULL
46#define ARM_FREQ_1P5G PLL_FREQ_HALF
47#define ARM_FREQ_750M PLL_FREQ_QRTR
48
49static unsigned int ARMCOE_crm_getBaseAddress(unsigned int cluster_num)
50{
51 unsigned int ihostx_config_root;
52
53 switch (cluster_num) {
54 case 0:
55 default:
56 ihostx_config_root = IHOST0_CONFIG_ROOT;
57 break;
58 case 1:
59 ihostx_config_root = IHOST1_CONFIG_ROOT;
60 break;
61 case 2:
62 ihostx_config_root = IHOST2_CONFIG_ROOT;
63 break;
64 case 3:
65 ihostx_config_root = IHOST3_CONFIG_ROOT;
66 break;
67 }
68
69 return ihostx_config_root;
70}
71
72static void ARMCOE_crm_pllAssertReset(unsigned int cluster_num,
73 unsigned int reset_type)
74{
75 unsigned long ihostx_config_root;
76 unsigned int pll_rst_ctrl;
77
78 ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
79 pll_rst_ctrl = mmio_read_32(ihostx_config_root + A72_CRM_PLL_PWR_ON);
80
81 // PLL reset
82 if (reset_type & PLL_RESET_TYPE_PLL) {
83 pll_rst_ctrl &= ~(0x1<<A72_CRM_PLL_PWR_ON__PLL0_RESETB_R);
84 }
85 // post-div channel reset
86 if (reset_type & PLL_RESET_TYPE_POST) {
87 pll_rst_ctrl &= ~(0x1<<A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R);
88 }
89
90 mmio_write_32(ihostx_config_root + A72_CRM_PLL_PWR_ON, pll_rst_ctrl);
91}
92
93static void ARMCOE_crm_pllSetMode(unsigned int cluster_num, unsigned int mode)
94{
95 unsigned long ihostx_config_root;
96 unsigned int pll_byp_ctrl;
97
98 ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
99 pll_byp_ctrl = mmio_read_32(ihostx_config_root +
100 A72_CRM_PLL_CHNL_BYPS_EN);
101
102 if (mode == PLL_MODE_VCO) {
103 // use PLL DCO output
104 pll_byp_ctrl &=
105 ~BIT(A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R);
106 } else {
107 // use PLL bypass sources
108 pll_byp_ctrl |=
109 BIT(A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R);
110 }
111
112 mmio_write_32(ihostx_config_root + A72_CRM_PLL_CHNL_BYPS_EN,
113 pll_byp_ctrl);
114}
115
116static void ARMCOE_crm_pllFreqSet(unsigned int cluster_num,
117 unsigned int ihost_pll_freq_sel,
118 unsigned int pdiv)
119{
120 unsigned int ndiv_int;
121 unsigned int ndiv_frac_low, ndiv_frac_high;
122 unsigned long ihostx_config_root;
123
124 ndiv_frac_low = 0x0;
125 ndiv_frac_high = 0x0;
126
127 if (ihost_pll_freq_sel == ARM_FREQ_3G) {
128 ndiv_int = 0x78;
129 } else if (ihost_pll_freq_sel == ARM_FREQ_1P5G) {
130 ndiv_int = 0x3c;
131 } else if (ihost_pll_freq_sel == ARM_FREQ_750M) {
132 ndiv_int = 0x1e;
133 } else {
134 return;
135 }
136
137 ndiv_int &= 0x3FF; // low 10 bits
138 ndiv_frac_low &= 0x3FF;
139 ndiv_frac_high &= 0x3FF;
140
141 ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
142
143 mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL1, ndiv_frac_low);
144 mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL2, ndiv_frac_high);
145 mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL3,
146 ndiv_int |
147 ((pdiv << A72_CRM_PLL0_CTRL3__PLL0_PDIV_R & 0xF000)));
148
149 mmio_write_32(ihostx_config_root + A72_CRM_PLL0_CTRL4,
150 /* From Section 10 of PLL spec */
151 (3 << A72_CRM_PLL0_CTRL4__PLL0_KP_R) |
152 /* From Section 10 of PLL spec */
153 (2 << A72_CRM_PLL0_CTRL4__PLL0_KI_R) |
154 /* Normal mode (i.e. not fast-locking) */
155 (0 << A72_CRM_PLL0_CTRL4__PLL0_KA_R) |
156 /* 50 MHz */
157 (50 << A72_CRM_PLL0_CTRL4__PLL0_FREFEFF_INFO_R));
158}
159
160static void ARMCOE_crm_pllDeassertReset(unsigned int cluster_num,
161 unsigned int reset_type)
162{
163 unsigned long ihostx_config_root;
164 unsigned int pll_rst_ctrl;
165
166 ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
167 pll_rst_ctrl = mmio_read_32(ihostx_config_root + A72_CRM_PLL_PWR_ON);
168
169 // PLL reset
170 if (reset_type & PLL_RESET_TYPE_PLL) {
171 pll_rst_ctrl |= (0x1 << A72_CRM_PLL_PWR_ON__PLL0_RESETB_R);
172 }
173
174 // post-div channel reset
175 if (reset_type & PLL_RESET_TYPE_POST) {
176 pll_rst_ctrl |= (0x1 << A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R);
177 }
178
179 mmio_write_32(ihostx_config_root + A72_CRM_PLL_PWR_ON, pll_rst_ctrl);
180}
181
182static void ARMCOE_crm_pllUpdate(unsigned int cluster_num, unsigned int type)
183{
184 unsigned long ihostx_config_root;
185 unsigned int pll_cmd;
186
187 ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
188 pll_cmd = mmio_read_32(ihostx_config_root + A72_CRM_PLL_CMD);
189
190 // VCO update
191 if (type & PLL_VCO) {
192 pll_cmd |= BIT(A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_VCO_R);
193 }
194 // post-div channel update
195 if (type & PLL_POSTDIV) {
196 pll_cmd |= BIT(A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_POST_R);
197 }
198
199 mmio_write_32(ihostx_config_root+A72_CRM_PLL_CMD, pll_cmd);
200}
201
202static void insert_delay(unsigned int delay)
203{
204 volatile unsigned int index;
205
206 for (index = 0; index < delay; index++)
207 ;
208}
209
210
211/*
212 * Returns 1 if PLL locked within certain interval
213 */
214static unsigned int ARMCOE_crm_pllIsLocked(unsigned int cluster_num)
215{
216 unsigned long ihostx_config_root;
217 unsigned int lock_status;
218 unsigned int i;
219
220 ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
221
222 /* wait a while for pll to lock before returning from this function */
223 for (i = 0; i < 1500; i++) {
224 insert_delay(256);
225 lock_status = mmio_read_32(ihostx_config_root +
226 A72_CRM_PLL_STATUS);
227 if (lock_status & BIT(A72_CRM_PLL_STATUS__PLL0_LOCK_R))
228 return 1;
229 }
230
231 ERROR("PLL of Cluster #%u failed to lock\n", cluster_num);
232 return 0;
233}
234
235/*
236 * ihost PLL Variable Frequency Configuration
237 *
238 * Frequency Limit {VCO,ARM} (GHz):
239 * 0 - no limit,
240 * 1 - {3.0,1.5},
241 * 2 - {4.0,2.0},
242 * 3 - {5.0,2.5}
243 */
244uint32_t bcm_set_ihost_pll_freq(uint32_t cluster_num, int ihost_pll_freq_sel)
245{
246 NOTICE("cluster: %u, freq_sel:0x%x\n", cluster_num, ihost_pll_freq_sel);
247
248 //bypass PLL
249 ARMCOE_crm_pllSetMode(cluster_num, PLL_MODE_BYPASS);
250 //assert reset
251 ARMCOE_crm_pllAssertReset(cluster_num,
252 PLL_RESET_TYPE_PLL | PLL_RESET_TYPE_POST);
253 //set ndiv_int for different freq
254 ARMCOE_crm_pllFreqSet(cluster_num, ihost_pll_freq_sel, 0x1);
255 //de-assert reset
256 ARMCOE_crm_pllDeassertReset(cluster_num, PLL_RESET_TYPE_PLL);
257 ARMCOE_crm_pllUpdate(cluster_num, PLL_VCO);
258 //waiting for PLL lock
259 ARMCOE_crm_pllIsLocked(cluster_num);
260 ARMCOE_crm_pllDeassertReset(cluster_num, PLL_RESET_TYPE_POST);
261 //disable bypass PLL
262 ARMCOE_crm_pllSetMode(cluster_num, PLL_MODE_VCO);
263
264 return 0;
265}
266
267uint32_t bcm_get_ihost_pll_freq(uint32_t cluster_num)
268{
269 unsigned long ihostx_config_root;
270 uint32_t ndiv_int;
271 uint32_t ihost_pll_freq_sel;
272
273 ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
274 ndiv_int = mmio_read_32(ihostx_config_root+A72_CRM_PLL0_CTRL3) & 0x3FF;
275
276 if (ndiv_int == 0x78) {
277 ihost_pll_freq_sel = ARM_FREQ_3G;
278 } else if (ndiv_int == 0x3c) {
279 ihost_pll_freq_sel = ARM_FREQ_1P5G;
280 } else if (ndiv_int == 0x1e) {
281 ihost_pll_freq_sel = ARM_FREQ_750M;
282 } else {
283 /* return unlimit otherwise*/
284 ihost_pll_freq_sel = 0;
285 }
286 return ihost_pll_freq_sel;
287}