Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
CTCaer
GitHub Repository: CTCaer/hekate
Path: blob/master/bdk/soc/clock.c
3694 views
1
/*
2
* Copyright (c) 2018 naehrwert
3
* Copyright (c) 2018-2026 CTCaer
4
*
5
* This program is free software; you can redistribute it and/or modify it
6
* under the terms and conditions of the GNU General Public License,
7
* version 2, as published by the Free Software Foundation.
8
*
9
* This program is distributed in the hope it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
* more details.
13
*
14
* You should have received a copy of the GNU General Public License
15
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
*/
17
18
#include <soc/bpmp.h>
19
#include <soc/clock.h>
20
#include <soc/hw_init.h>
21
#include <soc/pmc.h>
22
#include <soc/timer.h>
23
#include <soc/t210.h>
24
#include <storage/sdmmc.h>
25
26
#define RST_DEV_L_SET CLK_RST_CONTROLLER_RST_DEV_L_SET
27
#define RST_DEV_H_SET CLK_RST_CONTROLLER_RST_DEV_H_SET
28
#define RST_DEV_U_SET CLK_RST_CONTROLLER_RST_DEV_U_SET
29
#define RST_DEV_V_SET CLK_RST_CONTROLLER_RST_DEV_V_SET
30
#define RST_DEV_W_SET CLK_RST_CONTROLLER_RST_DEV_W_SET
31
#define RST_DEV_X_SET CLK_RST_CONTROLLER_RST_DEV_X_SET
32
#define RST_DEV_Y_SET CLK_RST_CONTROLLER_RST_DEV_Y_SET
33
34
#define CLK_ENB_L_SET CLK_RST_CONTROLLER_CLK_ENB_L_SET
35
#define CLK_ENB_H_SET CLK_RST_CONTROLLER_CLK_ENB_H_SET
36
#define CLK_ENB_U_SET CLK_RST_CONTROLLER_CLK_ENB_U_SET
37
#define CLK_ENB_V_SET CLK_RST_CONTROLLER_CLK_ENB_V_SET
38
#define CLK_ENB_W_SET CLK_RST_CONTROLLER_CLK_ENB_W_SET
39
#define CLK_ENB_X_SET CLK_RST_CONTROLLER_CLK_ENB_X_SET
40
#define CLK_ENB_Y_SET CLK_RST_CONTROLLER_CLK_ENB_Y_SET
41
42
#define RST_DEV_H_CLR CLK_RST_CONTROLLER_RST_DEV_H_CLR
43
#define CLK_ENB_H_CLR CLK_RST_CONTROLLER_CLK_ENB_H_CLR
44
45
typedef struct _clk_rst_mgd_t
46
{
47
u16 reset; // Reset SET.
48
u16 enable; // Enable SET.
49
u16 source;
50
u8 index;
51
} clk_rst_mgd_t;
52
53
typedef struct _clock_osc_t
54
{
55
u32 freq;
56
u16 min;
57
u16 max;
58
} clock_osc_t;
59
60
static const clock_osc_t _clock_osc_cnt[] = {
61
{ 12000, 706, 757 },
62
{ 13000, 766, 820 },
63
{ 16800, 991, 1059 },
64
{ 19200, 1133, 1210 },
65
{ 26000, 1535, 1638 },
66
{ 38400, 2268, 2418 },
67
{ 48000, 2836, 3023 }
68
};
69
70
/*
71
* T210 rare HW Errata
72
* A fraction of T210 silicon has an undocumented HW Errata on SDMMC clock state machine.
73
* Specifically on enable when using the combo registers. Using SET/CLR variants is mandatory.
74
*/
75
static const clk_rst_mgd_t _clock_sdmmc[] = {
76
{ RST_DEV_L_SET, CLK_ENB_L_SET, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1, CLK_L_SDMMC1 },
77
{ RST_DEV_L_SET, CLK_ENB_L_SET, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2, CLK_L_SDMMC2 },
78
{ RST_DEV_U_SET, CLK_ENB_U_SET, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3, CLK_U_SDMMC3 },
79
{ RST_DEV_L_SET, CLK_ENB_L_SET, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4, CLK_L_SDMMC4 },
80
};
81
82
/* clk_rst_t: reset, enable, source, index, clk_src, clk_div */
83
84
static const clk_rst_t _clock_uart[] = {
85
{ RST_DEV_L_SET, CLK_ENB_L_SET, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, CLK_L_UARTA, 0, CLK_SRC_DIV(2) },
86
{ RST_DEV_L_SET, CLK_ENB_L_SET, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, CLK_L_UARTB, 0, CLK_SRC_DIV(2) },
87
{ RST_DEV_H_SET, CLK_ENB_H_SET, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, CLK_H_UARTC, 0, CLK_SRC_DIV(2) },
88
{ RST_DEV_U_SET, CLK_ENB_U_SET, CLK_RST_CONTROLLER_CLK_SOURCE_UARTD, CLK_U_UARTD, 0, CLK_SRC_DIV(2) },
89
{ RST_DEV_Y_SET, CLK_ENB_Y_SET, CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE, CLK_Y_UARTAPE, 0, CLK_SRC_DIV(2) }
90
};
91
92
// I2C Fout = Fin / (TLOW + THIGH + 2) / FM_DIV). Default parameters - TLOW: 4, THIGH: 2, DEBOUNCE: 0, FM_DIV: 6.
93
static const clk_rst_t _clock_i2c[] = {
94
{ RST_DEV_L_SET, CLK_ENB_L_SET, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, CLK_L_I2C1, 6, CLK_I2C_SRC_DIV(4) }, // 4.8 MHz -> 100 KHz
95
{ RST_DEV_H_SET, CLK_ENB_H_SET, CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, CLK_H_I2C2, 6, CLK_I2C_SRC_DIV(1) }, // 19.2 MHz -> 400 KHz
96
{ RST_DEV_U_SET, CLK_ENB_U_SET, CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, CLK_U_I2C3, 6, CLK_I2C_SRC_DIV(1) }, // 19.2 MHz -> 400 KHz
97
{ RST_DEV_V_SET, CLK_ENB_V_SET, CLK_RST_CONTROLLER_CLK_SOURCE_I2C4, CLK_V_I2C4, 6, CLK_I2C_SRC_DIV(4) }, // 4.8 MHz -> 100 KHz
98
{ RST_DEV_H_SET, CLK_ENB_H_SET, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, CLK_H_I2C5, 6, CLK_I2C_SRC_DIV(1) }, // 19.2 MHz -> 400 KHz
99
{ RST_DEV_X_SET, CLK_ENB_X_SET, CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, CLK_X_I2C6, 6, CLK_I2C_SRC_DIV(4) } // 4.8 MHz -> 100 KHz
100
};
101
102
static clk_rst_t _clock_se = {
103
RST_DEV_V_SET, CLK_ENB_V_SET, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, CLK_SRC_DIV(1) // 408 MHz. Max: 627.2 MHz.
104
};
105
static clk_rst_t _clock_tzram = {
106
RST_DEV_V_SET, CLK_ENB_V_SET, CLK_NO_SOURCE, CLK_V_TZRAM, 0, 0
107
};
108
static clk_rst_t _clock_host1x = { // Has idle divisor.
109
RST_DEV_L_SET, CLK_ENB_L_SET, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, CLK_SRC_DIV(2.5) // 163.2MHz. Max: 408 MHz.
110
};
111
static clk_rst_t _clock_tsec = {
112
RST_DEV_U_SET, CLK_ENB_U_SET, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, CLK_SRC_DIV(2) // 204 MHz. Max: 408 MHz.
113
};
114
static clk_rst_t _clock_nvdec = {
115
RST_DEV_Y_SET, CLK_ENB_Y_SET, CLK_RST_CONTROLLER_CLK_SOURCE_NVDEC, CLK_Y_NVDEC, 4, CLK_SRC_DIV(1) // 408 MHz. Max: 716.8/979.2 MHz.
116
};
117
static clk_rst_t _clock_nvjpg = {
118
RST_DEV_Y_SET, CLK_ENB_Y_SET, CLK_RST_CONTROLLER_CLK_SOURCE_NVJPG, CLK_Y_NVJPG, 4, CLK_SRC_DIV(1) // 408 MHz. Max: 627.2/652.8 MHz.
119
};
120
static clk_rst_t _clock_vic = { // Has idle divisor.
121
RST_DEV_X_SET, CLK_ENB_X_SET, CLK_RST_CONTROLLER_CLK_SOURCE_VIC, CLK_X_VIC, 2, CLK_SRC_DIV(1) // 408 MHz. Max: 627.2/652.8 MHz.
122
};
123
static clk_rst_t _clock_sor_safe = {
124
RST_DEV_Y_SET, CLK_ENB_Y_SET, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, 0 // 24 MHz.
125
};
126
static clk_rst_t _clock_sor0 = {
127
RST_DEV_X_SET, CLK_ENB_X_SET, CLK_NOT_USED, CLK_X_SOR0, 0, 0 // 24 MHz (safe).
128
};
129
static clk_rst_t _clock_sor1 = {
130
RST_DEV_X_SET, CLK_ENB_X_SET, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, CLK_SRC_DIV(2) // 204 MHz.
131
};
132
static clk_rst_t _clock_kfuse = {
133
RST_DEV_H_SET, CLK_ENB_H_SET, CLK_NO_SOURCE, CLK_H_KFUSE, 0, 0
134
};
135
static clk_rst_t _clock_cl_dvfs = {
136
RST_DEV_W_SET, CLK_ENB_W_SET, CLK_NO_SOURCE, CLK_W_DVFS, 0, 0
137
};
138
static clk_rst_t _clock_coresight = {
139
RST_DEV_U_SET, CLK_ENB_U_SET, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, CLK_SRC_DIV(3) // 136 MHz.
140
};
141
static clk_rst_t _clock_pwm = {
142
RST_DEV_L_SET, CLK_ENB_L_SET, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, CLK_SRC_DIV(3) // Fref: 6.4MHz. HOS: PLLP / 54 = 7.55MHz.
143
};
144
static clk_rst_t _clock_sdmmc_legacy_tm = {
145
RST_DEV_Y_SET, CLK_ENB_Y_SET, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM, CLK_Y_SDMMC_LEGACY_TM, 4, CLK_SRC_DIV(34) // 12MHz.
146
};
147
static clk_rst_t _clock_apbdma = {
148
RST_DEV_H_SET, CLK_ENB_H_SET, CLK_NO_SOURCE, CLK_H_APBDMA, 0, 0 // Max: 204 MHz.
149
};
150
static clk_rst_t _clock_ahbdma = {
151
RST_DEV_H_SET, CLK_ENB_H_SET, CLK_NO_SOURCE, CLK_H_AHBDMA, 0, 0 // Max: 408 MHz.
152
};
153
static clk_rst_t _clock_actmon = {
154
RST_DEV_V_SET, CLK_ENB_V_SET, CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON, CLK_V_ACTMON, 6, CLK_SRC_DIV(1) // 19.2 MHz.
155
};
156
static clk_rst_t _clock_extperiph1 = {
157
RST_DEV_V_SET, CLK_ENB_V_SET, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1, CLK_V_EXTPERIPH1, 0, CLK_SRC_DIV(1)
158
};
159
static clk_rst_t _clock_extperiph2 = {
160
RST_DEV_V_SET, CLK_ENB_V_SET, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH2, CLK_V_EXTPERIPH2, 2, CLK_SRC_DIV(102) // 4.0 MHz
161
};
162
163
void clock_enable(const clk_rst_t *clk)
164
{
165
const u32 module = BIT(clk->index);
166
167
// Put clock into reset.
168
CLOCK(clk->reset) = module;
169
170
// Disable.
171
CLOCK(clk->enable + CLK_CLR_OFFSET) = module;
172
173
// Configure clock source if required.
174
if (clk->source)
175
CLOCK(clk->source) = (clk->clk_src << 29u) | clk->clk_div;
176
177
// Enable.
178
CLOCK(clk->enable) = module;
179
usleep(2);
180
181
// Take clock off reset.
182
CLOCK(clk->reset + CLK_CLR_OFFSET) = module;
183
184
// Commit changes.
185
(void)CLOCK(clk->reset);
186
}
187
188
void clock_disable(const clk_rst_t *clk)
189
{
190
const u32 module = BIT(clk->index);
191
192
// Put clock into reset.
193
CLOCK(clk->reset) = module;
194
195
// Disable.
196
CLOCK(clk->enable + CLK_CLR_OFFSET) = module;
197
}
198
199
void clock_enable_fuse(bool enable)
200
{
201
// Enable Fuse registers visibility.
202
CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) = (CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) & 0xEFFFFFFF) | ((enable & 1) << 28);
203
}
204
205
void clock_enable_uart(u32 idx)
206
{
207
// Ease the stress to APB.
208
bpmp_clk_rate_relaxed(true);
209
210
clock_enable(&_clock_uart[idx]);
211
212
// Restore sys clock.
213
bpmp_clk_rate_relaxed(false);
214
}
215
216
void clock_disable_uart(u32 idx)
217
{
218
clock_disable(&_clock_uart[idx]);
219
}
220
221
#define UART_SRC_CLK_DIV_EN BIT(24)
222
223
int clock_uart_use_src_div(u32 idx, u32 baud)
224
{
225
u32 clk_src = CLOCK(_clock_uart[idx].source) & 0xE0000000;
226
227
if (baud == 3000000)
228
CLOCK(_clock_uart[idx].source) = clk_src | UART_SRC_CLK_DIV_EN | CLK_SRC_DIV(8.5);
229
else if (baud == 1000000)
230
CLOCK(_clock_uart[idx].source) = clk_src | UART_SRC_CLK_DIV_EN | CLK_SRC_DIV(25.5);
231
else
232
{
233
CLOCK(_clock_uart[idx].source) = clk_src | CLK_SRC_DIV(2);
234
235
return 1;
236
}
237
238
return 0;
239
}
240
241
void clock_enable_i2c(u32 idx)
242
{
243
// Ease the stress to APB.
244
bpmp_clk_rate_relaxed(true);
245
246
clock_enable(&_clock_i2c[idx]);
247
248
// Restore sys clock.
249
bpmp_clk_rate_relaxed(false);
250
}
251
252
void clock_disable_i2c(u32 idx)
253
{
254
clock_disable(&_clock_i2c[idx]);
255
}
256
257
void clock_enable_se()
258
{
259
clock_enable(&_clock_se);
260
261
// Lock clock to always enabled if T210B01.
262
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
263
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SE) |= BIT(8);
264
}
265
266
void clock_enable_tzram()
267
{
268
clock_enable(&_clock_tzram);
269
}
270
271
void clock_enable_host1x()
272
{
273
clock_enable(&_clock_host1x);
274
275
// Set idle frequency to 81.6 MHz.
276
// CLOCK(_clock_host1x.clk_src) |= CLK_SRC_DIV(5) << 8;
277
}
278
279
void clock_disable_host1x()
280
{
281
clock_disable(&_clock_host1x);
282
}
283
284
void clock_enable_tsec()
285
{
286
clock_enable(&_clock_tsec);
287
}
288
289
void clock_disable_tsec()
290
{
291
clock_disable(&_clock_tsec);
292
}
293
294
void clock_enable_nvdec()
295
{
296
clock_enable(&_clock_nvdec);
297
}
298
299
void clock_disable_nvdec()
300
{
301
clock_disable(&_clock_nvdec);
302
}
303
304
void clock_enable_nvjpg()
305
{
306
clock_enable(&_clock_nvjpg);
307
}
308
309
void clock_disable_nvjpg()
310
{
311
clock_disable(&_clock_nvjpg);
312
}
313
314
void clock_enable_vic()
315
{
316
// Ease the stress to APB.
317
bpmp_clk_rate_relaxed(true);
318
319
clock_enable(&_clock_vic);
320
321
// Set idle frequency to 136 MHz.
322
// CLOCK(_clock_vic.clk_src) |= CLK_SRC_DIV(3) << 8;
323
324
// Restore sys clock.
325
bpmp_clk_rate_relaxed(false);
326
}
327
328
void clock_disable_vic()
329
{
330
clock_disable(&_clock_vic);
331
}
332
333
void clock_enable_sor_safe()
334
{
335
clock_enable(&_clock_sor_safe);
336
}
337
338
void clock_disable_sor_safe()
339
{
340
clock_disable(&_clock_sor_safe);
341
}
342
343
void clock_enable_sor0()
344
{
345
clock_enable(&_clock_sor0);
346
}
347
348
void clock_disable_sor0()
349
{
350
clock_disable(&_clock_sor0);
351
}
352
353
void clock_enable_sor1()
354
{
355
clock_enable(&_clock_sor1);
356
}
357
358
void clock_disable_sor1()
359
{
360
clock_disable(&_clock_sor1);
361
}
362
363
void clock_enable_kfuse()
364
{
365
CLOCK(RST_DEV_H_SET) = BIT(CLK_H_KFUSE);
366
CLOCK(CLK_ENB_H_CLR) = BIT(CLK_H_KFUSE);
367
CLOCK(CLK_ENB_H_SET) = BIT(CLK_H_KFUSE);
368
usleep(10); // Wait 10us to prevent glitching.
369
370
CLOCK(RST_DEV_H_CLR) = BIT(CLK_H_KFUSE);
371
usleep(20); // Wait 20us for KFUSE HW to init.
372
}
373
374
void clock_disable_kfuse()
375
{
376
clock_disable(&_clock_kfuse);
377
}
378
379
void clock_enable_cl_dvfs()
380
{
381
clock_enable(&_clock_cl_dvfs);
382
}
383
384
void clock_disable_cl_dvfs()
385
{
386
clock_disable(&_clock_cl_dvfs);
387
}
388
389
void clock_enable_coresight()
390
{
391
clock_enable(&_clock_coresight);
392
}
393
394
void clock_disable_coresight()
395
{
396
clock_disable(&_clock_coresight);
397
}
398
399
void clock_enable_pwm()
400
{
401
// Ease the stress to APB.
402
bpmp_clk_rate_relaxed(true);
403
404
clock_enable(&_clock_pwm);
405
406
// Restore sys clock.
407
bpmp_clk_rate_relaxed(false);
408
}
409
410
void clock_disable_pwm()
411
{
412
clock_disable(&_clock_pwm);
413
}
414
415
void clock_enable_apbdma()
416
{
417
clock_enable(&_clock_apbdma);
418
}
419
420
void clock_disable_apbdma()
421
{
422
clock_disable(&_clock_apbdma);
423
}
424
425
void clock_enable_ahbdma()
426
{
427
clock_enable(&_clock_ahbdma);
428
}
429
430
void clock_disable_ahbdma()
431
{
432
clock_disable(&_clock_ahbdma);
433
}
434
435
void clock_enable_actmon()
436
{
437
clock_enable(&_clock_actmon);
438
}
439
440
void clock_disable_actmon()
441
{
442
clock_disable(&_clock_actmon);
443
}
444
445
void clock_enable_extperiph1()
446
{
447
clock_enable(&_clock_extperiph1);
448
449
PMC(APBDEV_PMC_CLK_OUT_CNTRL) |= PMC_CLK_OUT_CNTRL_CLK1_SRC_SEL(OSC_CAR) | PMC_CLK_OUT_CNTRL_CLK1_FORCE_EN;
450
usleep(5);
451
}
452
453
void clock_disable_extperiph1()
454
{
455
PMC(APBDEV_PMC_CLK_OUT_CNTRL) &= ~((PMC_CLK_OUT_CNTRL_CLK1_SRC_SEL(OSC_CAR)) | PMC_CLK_OUT_CNTRL_CLK1_FORCE_EN);
456
clock_disable(&_clock_extperiph1);
457
}
458
459
void clock_enable_extperiph2()
460
{
461
clock_enable(&_clock_extperiph2);
462
463
PMC(APBDEV_PMC_CLK_OUT_CNTRL) |= PMC_CLK_OUT_CNTRL_CLK2_SRC_SEL(OSC_CAR) | PMC_CLK_OUT_CNTRL_CLK2_FORCE_EN;
464
usleep(5);
465
}
466
467
void clock_disable_extperiph2()
468
{
469
PMC(APBDEV_PMC_CLK_OUT_CNTRL) &= ~((PMC_CLK_OUT_CNTRL_CLK2_SRC_SEL(OSC_CAR)) | PMC_CLK_OUT_CNTRL_CLK2_FORCE_EN);
470
clock_disable(&_clock_extperiph2);
471
}
472
473
static void _clock_pll_wait_lock(u32 base, u32 max_delay)
474
{
475
for (u32 i = 0; i < max_delay; i++)
476
{
477
if (CLOCK(base) & PLL_BASE_LOCK)
478
break;
479
usleep(1);
480
}
481
482
usleep(2);
483
}
484
485
void clock_enable_plld(u32 divp, u32 divn, bool lowpower, bool tegra_t210)
486
{
487
u32 plld_div = (divp << 20) | (divn << 11) | 1;
488
489
// N divider is fractional, so N = DIVN + 1/2 + PLLD_SDM_DIN/8192.
490
u32 misc = BIT(21) | BIT(19) | BIT(18) | BIT(16) | 0xFC00; // Clock enable and PLLD_SDM_DIN: -1024 -> DIVN + 0.375.
491
if (lowpower && tegra_t210)
492
misc = BIT(21) | BIT(19) | BIT(18) | BIT(16) | 0x0AAA; // Clock enable and PLLD_SDM_DIN: 2730 -> DIVN + 0.833.
493
494
// Set DISP1 clock source.
495
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DISP1) = 2 << 29u; // PLLD_OUT0.
496
497
// Set dividers and enable PLLD.
498
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLL_BASE_ENABLE | PLL_BASE_LOCK | plld_div;
499
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = tegra_t210 ? 0x20 : 0; // Keep default PLLD_SETUP.
500
501
// Set PLLD_SDM_DIN and enable (T210) PLLD to DSI pads.
502
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = misc;
503
504
// Wait for PLL to stabilize.
505
_clock_pll_wait_lock(CLK_RST_CONTROLLER_PLLD_BASE, 1000);
506
}
507
508
void clock_enable_pllx()
509
{
510
// Configure and enable PLLX if disabled.
511
if (!(CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) & PLL_BASE_ENABLE)) // PLLX_ENABLE.
512
{
513
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC_3) &= ~PLLX_MISC3_IDDQ; // Disable IDDQ.
514
usleep(2);
515
516
// Set div configuration.
517
const u32 pllx_div_cfg = (2 << 20) | (156 << 8) | 2; // P div: 2 (3), N div: 156, M div: 2. 998.4 MHz.
518
519
// Bypass dividers.
520
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLL_BASE_BYPASS | pllx_div_cfg;
521
// Disable bypass
522
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = pllx_div_cfg;
523
// Set PLLX_LOCK_ENABLE.
524
CLOCK(CLK_RST_CONTROLLER_PLLX_MISC) |= PLLX_MISC_LOCK_EN;
525
// Enable PLLX.
526
CLOCK(CLK_RST_CONTROLLER_PLLX_BASE) = PLL_BASE_ENABLE | pllx_div_cfg;
527
}
528
529
// Wait for PLL to stabilize.
530
_clock_pll_wait_lock(CLK_RST_CONTROLLER_PLLX_BASE, 300);
531
}
532
533
void clock_enable_pllc(u32 divn)
534
{
535
u32 enabled = CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) & PLL_BASE_ENABLE;
536
u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF;
537
538
// Check if already enabled and configured.
539
if (enabled && (pll_divn_curr == divn))
540
return;
541
542
// WAR: Disable first to avoid HPLL overshoot.
543
if (enabled)
544
clock_disable_pllc();
545
546
// Take PLLC out of reset (misc) and set misc2 parameters.
547
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) = (0x8000 << 4); // PLLC_EXT_FRU.
548
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) |= 0xF << 8; // PLLC_FLL_LD_MEM.
549
550
// Disable PLL and IDDQ in case they are on.
551
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLL_BASE_ENABLE;
552
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) &= ~PLLC_MISC1_IDDQ;
553
usleep(10);
554
555
// Set PLLC dividers.
556
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) = (divn << 10) | 6; // DIVM: 6, DIVP: 1.
557
558
// Enable PLLC and wait for Phase and Frequency lock.
559
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLL_BASE_ENABLE;
560
_clock_pll_wait_lock(CLK_RST_CONTROLLER_PLLC_BASE, 300);
561
562
// Disable PLLC_OUT1, enable reset and set div to 1.
563
CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) = 0;
564
565
// Enable PLLC_OUT1 and bring it out of reset.
566
CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) |= PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR;
567
msleep(1); // Wait a bit for PLL to stabilize.
568
}
569
570
void clock_disable_pllc()
571
{
572
// Disable PLLC and PLLC_OUT1.
573
CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) &= ~PLLC_OUT1_RSTN_CLR;
574
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) = PLLC_MISC_RESET;
575
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLL_BASE_ENABLE;
576
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) |= PLLC_MISC1_IDDQ;
577
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) &= ~(0xFF << 8); // PLLC_FLL_LD_MEM.
578
usleep(10);
579
}
580
581
#define PLLC4_ENABLED BIT(31)
582
#define PLLC4_IN_USE (~PLLC4_ENABLED)
583
584
u32 pllc4_enabled = 0;
585
586
static void _clock_enable_pllc4(u32 mask)
587
{
588
pllc4_enabled |= mask;
589
590
if (pllc4_enabled & PLLC4_ENABLED)
591
return;
592
593
// Enable Phase and Frequency lock detection.
594
CLOCK(CLK_RST_CONTROLLER_PLLC4_MISC) = PLLC4_MISC_EN_LCKDET;
595
596
// Disable PLL and IDDQ in case they are on.
597
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLL_BASE_ENABLE;
598
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLLC4_BASE_IDDQ;
599
usleep(10);
600
601
// Set PLLC4 dividers.
602
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) = (0 << 19) | (104 << 8) | 4; // DIVP: 1, DIVN: 104, DIVM: 4. 998MHz OUT0, 199MHz OUT2.
603
604
// Enable PLLC4 and wait for Phase and Frequency lock.
605
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) |= PLL_BASE_ENABLE;
606
_clock_pll_wait_lock(CLK_RST_CONTROLLER_PLLC4_BASE, 300 + 700);
607
608
pllc4_enabled |= PLLC4_ENABLED;
609
}
610
611
static void _clock_disable_pllc4(u32 mask)
612
{
613
pllc4_enabled &= ~mask;
614
615
// Check if currently in use or disabled.
616
if ((pllc4_enabled & PLLC4_IN_USE) || !(pllc4_enabled & PLLC4_ENABLED))
617
return;
618
619
// Disable PLLC4.
620
usleep(100); // Wait at least 100us to prevent glitching.
621
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) &= ~PLL_BASE_ENABLE;
622
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) |= PLLC4_BASE_IDDQ;
623
usleep(10);
624
625
pllc4_enabled = 0;
626
}
627
628
void clock_enable_pllu()
629
{
630
// Configure PLLU.
631
CLOCK(CLK_RST_CONTROLLER_PLLU_MISC) |= BIT(29); // Disable reference clock.
632
u32 pllu_cfg = (CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) & 0xFFE00000) | BIT(24) | (1 << 16) | (0x19 << 8) | 2;
633
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg;
634
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg | PLL_BASE_ENABLE; // Enable.
635
636
// Wait for PLL to stabilize.
637
_clock_pll_wait_lock(CLK_RST_CONTROLLER_PLLU_BASE, 1000);
638
usleep(8);
639
640
// Enable PLLU USB/HSIC/ICUSB/48M.
641
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) |= 0x2E00000;
642
}
643
644
void clock_disable_pllu()
645
{
646
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) &= ~0x2E00000; // Disable PLLU USB/HSIC/ICUSB/48M.
647
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) &= ~BIT(30); // Disable PLLU.
648
CLOCK(CLK_RST_CONTROLLER_PLLU_MISC) &= ~BIT(29); // Enable reference clock.
649
}
650
651
void clock_enable_utmipll()
652
{
653
// Set UTMIPLL dividers and config based on OSC and enable it to 960 MHz.
654
CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG0) = (CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG0) & 0xFF0000FF) | (25 << 16) | (1 << 8); // 38.4Mhz * (25 / 1) = 960 MHz.
655
CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) = (CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) & 0xFF00003F) | (24 << 18); // Set delay count for 38.4Mhz osc crystal.
656
CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG1) = (CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG1) & 0x7FFA000) | (1 << 15) | 375;
657
658
// Wait for UTMIPLL to stabilize.
659
u32 retries = 10; // Wait 20us
660
while (!(CLOCK(CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0) & UTMIPLL_LOCK) && retries)
661
{
662
usleep(1);
663
retries--;
664
}
665
}
666
667
static int _clock_sdmmc_in_reset(u32 id)
668
{
669
const clk_rst_mgd_t *clk = &_clock_sdmmc[id];
670
671
return CLOCK(clk->reset) & BIT(clk->index);
672
}
673
674
static void _clock_sdmmc_set_reset(u32 id)
675
{
676
const clk_rst_mgd_t *clk = &_clock_sdmmc[id];
677
678
CLOCK(clk->reset) = BIT(clk->index);
679
}
680
681
static void _clock_sdmmc_clr_reset(u32 id)
682
{
683
const clk_rst_mgd_t *clk = &_clock_sdmmc[id];
684
685
CLOCK(clk->reset + CLK_CLR_OFFSET) = BIT(clk->index);
686
}
687
688
static int _clock_sdmmc_is_enabled(u32 id)
689
{
690
const clk_rst_mgd_t *clk = &_clock_sdmmc[id];
691
692
return CLOCK(clk->enable) & BIT(clk->index);
693
}
694
695
static void _clock_sdmmc_set_enable(u32 id)
696
{
697
const clk_rst_mgd_t *clk = &_clock_sdmmc[id];
698
699
CLOCK(clk->enable) = BIT(clk->index);
700
}
701
702
static void _clock_sdmmc_clr_enable(u32 id)
703
{
704
const clk_rst_mgd_t *clk = &_clock_sdmmc[id];
705
706
CLOCK(clk->enable + CLK_CLR_OFFSET) = BIT(clk->index);
707
}
708
709
static void _clock_sdmmc_config_legacy_tm()
710
{
711
const clk_rst_t *clk = &_clock_sdmmc_legacy_tm;
712
713
if (!(CLOCK(clk->enable) & BIT(clk->index)))
714
clock_enable(clk);
715
}
716
717
typedef struct _clock_sdmmc_t
718
{
719
u32 clock;
720
u32 pclock;
721
} clock_sdmmc_t;
722
723
static clock_sdmmc_t _clock_sdmmc_table[4] = { 0 };
724
725
#define SDMMC_CLOCK_SRC_PLLP_OUT0 0x0
726
#define SDMMC_CLOCK_SRC_PLLC4_OUT2 0x3
727
#define SDMMC_CLOCK_SRC_PLLC4_OUT0 0x7
728
#define SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ 0x1
729
730
static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 clock)
731
{
732
u32 divisor = 0;
733
u32 source = SDMMC_CLOCK_SRC_PLLP_OUT0;
734
735
if (id > SDMMC_4)
736
return 1;
737
738
// Get IO clock divisor.
739
switch (clock)
740
{
741
case 25000:
742
*pclock = 24728;
743
divisor = CLK_SRC_DIV(16.5);
744
break;
745
746
case 26000:
747
*pclock = 25500;
748
divisor = CLK_SRC_DIV(16);
749
break;
750
751
case 50000:
752
*pclock = 48000;
753
divisor = CLK_SRC_DIV(8.5);
754
break;
755
756
case 52000:
757
*pclock = 51000;
758
divisor = CLK_SRC_DIV(8);
759
break;
760
761
case 82000:
762
*pclock = 81600;
763
divisor = CLK_SRC_DIV(5);
764
break;
765
766
case 100000:
767
source = SDMMC_CLOCK_SRC_PLLC4_OUT2;
768
*pclock = 99840;
769
divisor = CLK_SRC_DIV(2);
770
break;
771
772
case 164000:
773
*pclock = 163200;
774
divisor = CLK_SRC_DIV(2.5);
775
break;
776
777
case 200000:
778
switch (id)
779
{
780
case SDMMC_1:
781
case SDMMC_3:
782
source = SDMMC_CLOCK_SRC_PLLC4_OUT2;
783
break;
784
case SDMMC_2:
785
case SDMMC_4:
786
source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ; // CLK RST divisor is ignored.
787
break;
788
}
789
*pclock = 199680;
790
divisor = CLK_SRC_DIV(1);
791
break;
792
793
#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT
794
case 400000:
795
source = SDMMC_CLOCK_SRC_PLLC4_OUT0;
796
*pclock = 399360;
797
divisor = CLK_SRC_DIV(2.5);
798
break;
799
#endif
800
}
801
802
_clock_sdmmc_table[id].clock = clock;
803
_clock_sdmmc_table[id].pclock = *pclock;
804
805
// Enable PLLC4 if in use by any SDMMC.
806
if (source != SDMMC_CLOCK_SRC_PLLP_OUT0)
807
_clock_enable_pllc4(BIT(id));
808
809
// Set SDMMC legacy timeout clock.
810
_clock_sdmmc_config_legacy_tm();
811
812
// Set SDMMC clock.
813
const clk_rst_mgd_t *clk = &_clock_sdmmc[id];
814
CLOCK(clk->source) = (source << 29u) | divisor;
815
816
return 0;
817
}
818
819
void clock_sdmmc_config_clock_source(u32 *pclock, u32 id, u32 clock)
820
{
821
if (_clock_sdmmc_table[id].clock == clock)
822
{
823
*pclock = _clock_sdmmc_table[id].pclock;
824
}
825
else
826
{
827
// Ease the stress to APB.
828
if (id == SDMMC_1)
829
bpmp_clk_rate_relaxed(true);
830
831
int is_enabled = _clock_sdmmc_is_enabled(id);
832
if (is_enabled)
833
_clock_sdmmc_clr_enable(id);
834
835
_clock_sdmmc_config_clock_host(pclock, id, clock);
836
837
if (is_enabled)
838
_clock_sdmmc_set_enable(id);
839
840
// Commit changes.
841
_clock_sdmmc_in_reset(id);
842
843
// Restore sys clock.
844
if (id == SDMMC_1)
845
bpmp_clk_rate_relaxed(false);
846
}
847
}
848
849
void clock_sdmmc_get_card_clock_div(u32 *pclock, u16 *pdivisor, u32 type)
850
{
851
// Get Card clock divisor.
852
switch (type)
853
{
854
case SDHCI_TIMING_MMC_ID: // Actual card clock: 386.36 KHz.
855
*pclock = 26000;
856
*pdivisor = 66;
857
break;
858
859
case SDHCI_TIMING_MMC_LS26:
860
*pclock = 26000;
861
*pdivisor = 1;
862
break;
863
864
case SDHCI_TIMING_MMC_HS52:
865
*pclock = 52000;
866
*pdivisor = 1;
867
break;
868
869
case SDHCI_TIMING_MMC_HS200:
870
case SDHCI_TIMING_MMC_HS400:
871
case SDHCI_TIMING_UHS_SDR104:
872
*pclock = 200000;
873
*pdivisor = 1;
874
break;
875
876
case SDHCI_TIMING_SD_ID: // Actual card clock: 386.38 KHz.
877
*pclock = 25000;
878
*pdivisor = 64;
879
break;
880
881
case SDHCI_TIMING_SD_DS12:
882
case SDHCI_TIMING_UHS_SDR12:
883
*pclock = 25000;
884
*pdivisor = 1;
885
break;
886
887
case SDHCI_TIMING_SD_HS25:
888
case SDHCI_TIMING_UHS_SDR25:
889
*pclock = 50000;
890
*pdivisor = 1;
891
break;
892
893
case SDHCI_TIMING_UHS_SDR50:
894
*pclock = 100000;
895
*pdivisor = 1;
896
break;
897
898
case SDHCI_TIMING_UHS_SDR82:
899
*pclock = 164000;
900
*pdivisor = 1;
901
break;
902
903
case SDHCI_TIMING_UHS_DDR50: // Actual card clock: 40.80 MHz.
904
*pclock = 82000;
905
*pdivisor = 2;
906
break;
907
908
case SDHCI_TIMING_MMC_HS100: // Actual card clock: 99.84 MHz.
909
*pclock = 200000;
910
*pdivisor = 2;
911
break;
912
913
#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT
914
case SDHCI_TIMING_UHS_DDR200: // Actual card clock: 199.68 KHz.
915
*pclock = 400000;
916
*pdivisor = 2;
917
break;
918
#endif
919
}
920
}
921
922
int clock_sdmmc_is_active(u32 id)
923
{
924
return !_clock_sdmmc_in_reset(id) && _clock_sdmmc_is_enabled(id);
925
}
926
927
void clock_sdmmc_enable(u32 id, u32 clock)
928
{
929
u32 pclock = 0;
930
931
// Ease the stress to APB.
932
if (id == SDMMC_1)
933
bpmp_clk_rate_relaxed(true);
934
935
_clock_sdmmc_clr_enable(id);
936
_clock_sdmmc_set_reset(id);
937
_clock_sdmmc_config_clock_host(&pclock, id, clock);
938
_clock_sdmmc_set_enable(id);
939
940
// Commit changes and wait 100 cycles for reset and for clocks to stabilize.
941
_clock_sdmmc_in_reset(id);
942
usleep((100 * 1000 + pclock - 1) / pclock);
943
944
_clock_sdmmc_clr_reset(id);
945
_clock_sdmmc_in_reset(id);
946
947
// Restore sys clock.
948
if (id == SDMMC_1)
949
bpmp_clk_rate_relaxed(false);
950
}
951
952
void clock_sdmmc_disable(u32 id)
953
{
954
_clock_sdmmc_set_reset(id);
955
_clock_sdmmc_clr_enable(id);
956
_clock_sdmmc_in_reset(id);
957
_clock_disable_pllc4(BIT(id));
958
}
959
960
u32 clock_get_osc_freq()
961
{
962
CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET) = OSC_FREQ_DET_TRIG | (2 - 1); // 2 periods of 32.76KHz window.
963
while (CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY)
964
;
965
u32 cnt = (CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_CNT);
966
CLOCK(CLK_RST_CONTROLLER_OSC_FREQ_DET) = 0;
967
968
// Return frequency in KHz.
969
for (u32 i = 0; i < ARRAY_SIZE(_clock_osc_cnt); i++)
970
if (cnt >= _clock_osc_cnt[i].min && cnt <= _clock_osc_cnt[i].max)
971
return _clock_osc_cnt[i].freq;
972
973
return 0;
974
}
975
976
u32 clock_get_dev_freq(clock_pto_id_t id)
977
{
978
const u32 pto_win = 16;
979
const u32 pto_osc = 32768;
980
981
u32 val = ((id & PTO_SRC_SEL_MASK) << PTO_SRC_SEL_SHIFT) | PTO_DIV_SEL_DIV1 | PTO_CLK_ENABLE | (pto_win - 1);
982
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val;
983
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
984
usleep(2);
985
986
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_RST;
987
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
988
usleep(2);
989
990
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val;
991
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
992
usleep(2);
993
994
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = val | PTO_CNT_EN;
995
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
996
usleep((1000000 * pto_win / pto_osc) + 12 + 2);
997
998
while (CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT_BUSY)
999
;
1000
1001
u32 cnt = CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_STATUS) & PTO_CLK_CNT;
1002
1003
CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL) = 0;
1004
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
1005
usleep(2);
1006
1007
u32 freq_khz = (u64)cnt * pto_osc / pto_win / 1000;
1008
1009
return freq_khz;
1010
}
1011
1012
1013