forked from zephyrproject-rtos/zephyr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclock_agilex_ll.c
144 lines (116 loc) · 3.54 KB
/
clock_agilex_ll.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
* Copyright (c) 2019-2021, Intel Corporation. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <arch/cpu.h>
#include <arch/common/sys_bitops.h>
#include <drivers/clock_control/clock_agilex_ll.h>
#include <socfpga_system_manager.h>
/*
* Intel SoC re-use Arm Trusted Firmware (ATF) driver code in Zephyr.
* The migrated ATF driver code uses mmio_X macro to access the register.
* The following macros map mmio_X to Zephyr compatible function for
* register access. This allow Zephyr to re-use the ATF driver codes
* without massive changes.
*/
#define mmio_write_32(addr, data) sys_write32((data), (addr))
#define mmio_read_32(addr) sys_read32((addr))
#define mmio_setbits_32(addr, mask) sys_set_bits((addr), (mask))
#define mmio_clrbits_32(addr, mask) sys_clear_bits((addr), (mask))
/* Extract reference clock from platform clock source */
uint32_t get_ref_clk(uint32_t pllglob)
{
uint32_t arefclkdiv, ref_clk;
uint32_t scr_reg;
switch (CLKMGR_PSRC(pllglob)) {
case CLKMGR_PLLGLOB_PSRC_EOSC1:
scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1);
ref_clk = mmio_read_32(scr_reg);
break;
case CLKMGR_PLLGLOB_PSRC_INTOSC:
ref_clk = CLKMGR_INTOSC_HZ;
break;
case CLKMGR_PLLGLOB_PSRC_F2S:
scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2);
ref_clk = mmio_read_32(scr_reg);
break;
default:
ref_clk = 0;
break;
}
arefclkdiv = CLKMGR_PLLGLOB_AREFCLKDIV(pllglob);
ref_clk /= arefclkdiv;
return ref_clk;
}
/* Calculate clock frequency based on parameter */
uint32_t get_clk_freq(uint32_t psrc_reg, uint32_t main_pllc, uint32_t per_pllc)
{
uint32_t clk_psrc, mdiv, ref_clk;
uint32_t pllm_reg, pllc_reg, pllc_div, pllglob_reg;
clk_psrc = mmio_read_32(CLKMGR_MAINPLL + psrc_reg);
switch (CLKMGR_PSRC(clk_psrc)) {
case CLKMGR_PSRC_MAIN:
pllm_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLM;
pllc_reg = CLKMGR_MAINPLL + main_pllc;
pllglob_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB;
break;
case CLKMGR_PSRC_PER:
pllm_reg = CLKMGR_PERPLL + CLKMGR_PERPLL_PLLM;
pllc_reg = CLKMGR_PERPLL + per_pllc;
pllglob_reg = CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB;
break;
default:
return 0;
}
ref_clk = get_ref_clk(mmio_read_32(pllglob_reg));
mdiv = CLKMGR_PLLM_MDIV(mmio_read_32(pllm_reg));
ref_clk *= mdiv;
pllc_div = mmio_read_32(pllc_reg) & 0x7ff;
return ref_clk / pllc_div;
}
/* Return L3 interconnect clock */
uint32_t get_l3_clk(void)
{
uint32_t l3_clk;
l3_clk = get_clk_freq(CLKMGR_MAINPLL_NOCCLK, CLKMGR_MAINPLL_PLLC1,
CLKMGR_PERPLL_PLLC1);
return l3_clk;
}
/* Calculate clock frequency to be used for mpu */
uint32_t get_mpu_clk(void)
{
uint32_t mpu_clk = 0;
mpu_clk = get_clk_freq(CLKMGR_MAINPLL_MPUCLK, CLKMGR_MAINPLL_PLLC0,
CLKMGR_PERPLL_PLLC0);
return mpu_clk;
}
/* Calculate clock frequency to be used for watchdog timer */
uint32_t get_wdt_clk(void)
{
uint32_t l3_clk, l4_sys_clk;
l3_clk = get_l3_clk();
l4_sys_clk = l3_clk / 4;
return l4_sys_clk;
}
/* Calculate clock frequency to be used for UART driver */
uint32_t get_uart_clk(void)
{
uint32_t data32, l3_clk, l4_sp_clk;
l3_clk = get_l3_clk();
data32 = mmio_read_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV);
data32 = (data32 >> 16) & 0x3;
l4_sp_clk = l3_clk >> data32;
return l4_sp_clk;
}
/* Calculate clock frequency to be used for SDMMC driver */
uint32_t get_mmc_clk(void)
{
uint32_t data32, mmc_clk;
mmc_clk = get_clk_freq(CLKMGR_ALTERA_SDMMCCTR,
CLKMGR_MAINPLL_PLLC3, CLKMGR_PERPLL_PLLC3);
data32 = mmio_read_32(CLKMGR_ALTERA + CLKMGR_ALTERA_SDMMCCTR);
data32 = (data32 & 0x7ff) + 1;
mmc_clk = (mmc_clk / data32) / 4;
return mmc_clk;
}