Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-bcmring/csp/chipc/chipcHw_init.c
10820 views
1
/*****************************************************************************
2
* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved.
3
*
4
* Unless you and Broadcom execute a separate written software license
5
* agreement governing use of this software, this software is licensed to you
6
* under the terms of the GNU General Public License version 2, available at
7
* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
8
*
9
* Notwithstanding the above, under no circumstances may you combine this
10
* software in any way with any other Broadcom software provided under a
11
* license other than the GPL, without Broadcom's express prior written
12
* consent.
13
*****************************************************************************/
14
15
/****************************************************************************/
16
/**
17
* @file chipcHw_init.c
18
*
19
* @brief Low level CHIPC PLL configuration functions
20
*
21
* @note
22
*
23
* These routines provide basic PLL controlling functionality only.
24
*/
25
/****************************************************************************/
26
27
/* ---- Include Files ---------------------------------------------------- */
28
29
#include <csp/errno.h>
30
#include <csp/stdint.h>
31
#include <csp/module.h>
32
33
#include <mach/csp/chipcHw_def.h>
34
#include <mach/csp/chipcHw_inline.h>
35
36
#include <csp/reg.h>
37
#include <csp/delay.h>
38
/* ---- Private Constants and Types --------------------------------------- */
39
40
/*
41
Calculation for NDIV_i to obtain VCO frequency
42
-----------------------------------------------
43
44
Freq_vco = Freq_ref * (P2 / P1) * (PLL_NDIV_i + PLL_NDIV_f)
45
for Freq_vco = VCO_FREQ_MHz
46
Freq_ref = chipcHw_XTAL_FREQ_Hz
47
PLL_P1 = PLL_P2 = 1
48
and
49
PLL_NDIV_f = 0
50
51
We get:
52
PLL_NDIV_i = Freq_vco / Freq_ref = VCO_FREQ_MHz / chipcHw_XTAL_FREQ_Hz
53
54
Calculation for PLL MDIV to obtain frequency Freq_x for channel x
55
-----------------------------------------------------------------
56
Freq_x = chipcHw_XTAL_FREQ_Hz * PLL_NDIV_i / PLL_MDIV_x = VCO_FREQ_MHz / PLL_MDIV_x
57
58
PLL_MDIV_x = VCO_FREQ_MHz / Freq_x
59
*/
60
61
/* ---- Private Variables ------------------------------------------------- */
62
/****************************************************************************/
63
/**
64
* @brief Initializes the PLL2
65
*
66
* This function initializes the PLL2
67
*
68
*/
69
/****************************************************************************/
70
void chipcHw_pll2Enable(uint32_t vcoFreqHz)
71
{
72
uint32_t pllPreDivider2 = 0;
73
74
{
75
REG_LOCAL_IRQ_SAVE;
76
pChipcHw->PLLConfig2 =
77
chipcHw_REG_PLL_CONFIG_D_RESET |
78
chipcHw_REG_PLL_CONFIG_A_RESET;
79
80
pllPreDivider2 = chipcHw_REG_PLL_PREDIVIDER_POWER_DOWN |
81
chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER |
82
(chipcHw_REG_PLL_PREDIVIDER_NDIV_i(vcoFreqHz) <<
83
chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT) |
84
(chipcHw_REG_PLL_PREDIVIDER_P1 <<
85
chipcHw_REG_PLL_PREDIVIDER_P1_SHIFT) |
86
(chipcHw_REG_PLL_PREDIVIDER_P2 <<
87
chipcHw_REG_PLL_PREDIVIDER_P2_SHIFT);
88
89
/* Enable CHIPC registers to control the PLL */
90
pChipcHw->PLLStatus |= chipcHw_REG_PLL_STATUS_CONTROL_ENABLE;
91
92
/* Set pre divider to get desired VCO frequency */
93
pChipcHw->PLLPreDivider2 = pllPreDivider2;
94
/* Set NDIV Frac */
95
pChipcHw->PLLDivider2 = chipcHw_REG_PLL_DIVIDER_NDIV_f;
96
97
/* This has to be removed once the default values are fixed for PLL2. */
98
pChipcHw->PLLControl12 = 0x38000700;
99
pChipcHw->PLLControl22 = 0x00000015;
100
101
/* Reset PLL2 */
102
if (vcoFreqHz > chipcHw_REG_PLL_CONFIG_VCO_SPLIT_FREQ) {
103
pChipcHw->PLLConfig2 = chipcHw_REG_PLL_CONFIG_D_RESET |
104
chipcHw_REG_PLL_CONFIG_A_RESET |
105
chipcHw_REG_PLL_CONFIG_VCO_1601_3200 |
106
chipcHw_REG_PLL_CONFIG_POWER_DOWN;
107
} else {
108
pChipcHw->PLLConfig2 = chipcHw_REG_PLL_CONFIG_D_RESET |
109
chipcHw_REG_PLL_CONFIG_A_RESET |
110
chipcHw_REG_PLL_CONFIG_VCO_800_1600 |
111
chipcHw_REG_PLL_CONFIG_POWER_DOWN;
112
}
113
REG_LOCAL_IRQ_RESTORE;
114
}
115
116
/* Insert certain amount of delay before deasserting ARESET. */
117
udelay(1);
118
119
{
120
REG_LOCAL_IRQ_SAVE;
121
/* Remove analog reset and Power on the PLL */
122
pChipcHw->PLLConfig2 &=
123
~(chipcHw_REG_PLL_CONFIG_A_RESET |
124
chipcHw_REG_PLL_CONFIG_POWER_DOWN);
125
126
REG_LOCAL_IRQ_RESTORE;
127
128
}
129
130
/* Wait until PLL is locked */
131
while (!(pChipcHw->PLLStatus2 & chipcHw_REG_PLL_STATUS_LOCKED))
132
;
133
134
{
135
REG_LOCAL_IRQ_SAVE;
136
/* Remove digital reset */
137
pChipcHw->PLLConfig2 &= ~chipcHw_REG_PLL_CONFIG_D_RESET;
138
139
REG_LOCAL_IRQ_RESTORE;
140
}
141
}
142
143
EXPORT_SYMBOL(chipcHw_pll2Enable);
144
145
/****************************************************************************/
146
/**
147
* @brief Initializes the PLL1
148
*
149
* This function initializes the PLL1
150
*
151
*/
152
/****************************************************************************/
153
void chipcHw_pll1Enable(uint32_t vcoFreqHz, chipcHw_SPREAD_SPECTRUM_e ssSupport)
154
{
155
uint32_t pllPreDivider = 0;
156
157
{
158
REG_LOCAL_IRQ_SAVE;
159
160
pChipcHw->PLLConfig =
161
chipcHw_REG_PLL_CONFIG_D_RESET |
162
chipcHw_REG_PLL_CONFIG_A_RESET;
163
/* Setting VCO frequency */
164
if (ssSupport == chipcHw_SPREAD_SPECTRUM_ALLOW) {
165
pllPreDivider =
166
chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASH_1_8 |
167
((chipcHw_REG_PLL_PREDIVIDER_NDIV_i(vcoFreqHz) -
168
1) << chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT) |
169
(chipcHw_REG_PLL_PREDIVIDER_P1 <<
170
chipcHw_REG_PLL_PREDIVIDER_P1_SHIFT) |
171
(chipcHw_REG_PLL_PREDIVIDER_P2 <<
172
chipcHw_REG_PLL_PREDIVIDER_P2_SHIFT);
173
} else {
174
pllPreDivider = chipcHw_REG_PLL_PREDIVIDER_POWER_DOWN |
175
chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER |
176
(chipcHw_REG_PLL_PREDIVIDER_NDIV_i(vcoFreqHz) <<
177
chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT) |
178
(chipcHw_REG_PLL_PREDIVIDER_P1 <<
179
chipcHw_REG_PLL_PREDIVIDER_P1_SHIFT) |
180
(chipcHw_REG_PLL_PREDIVIDER_P2 <<
181
chipcHw_REG_PLL_PREDIVIDER_P2_SHIFT);
182
}
183
184
/* Enable CHIPC registers to control the PLL */
185
pChipcHw->PLLStatus |= chipcHw_REG_PLL_STATUS_CONTROL_ENABLE;
186
187
/* Set pre divider to get desired VCO frequency */
188
pChipcHw->PLLPreDivider = pllPreDivider;
189
/* Set NDIV Frac */
190
if (ssSupport == chipcHw_SPREAD_SPECTRUM_ALLOW) {
191
pChipcHw->PLLDivider = chipcHw_REG_PLL_DIVIDER_M1DIV |
192
chipcHw_REG_PLL_DIVIDER_NDIV_f_SS;
193
} else {
194
pChipcHw->PLLDivider = chipcHw_REG_PLL_DIVIDER_M1DIV |
195
chipcHw_REG_PLL_DIVIDER_NDIV_f;
196
}
197
198
/* Reset PLL1 */
199
if (vcoFreqHz > chipcHw_REG_PLL_CONFIG_VCO_SPLIT_FREQ) {
200
pChipcHw->PLLConfig = chipcHw_REG_PLL_CONFIG_D_RESET |
201
chipcHw_REG_PLL_CONFIG_A_RESET |
202
chipcHw_REG_PLL_CONFIG_VCO_1601_3200 |
203
chipcHw_REG_PLL_CONFIG_POWER_DOWN;
204
} else {
205
pChipcHw->PLLConfig = chipcHw_REG_PLL_CONFIG_D_RESET |
206
chipcHw_REG_PLL_CONFIG_A_RESET |
207
chipcHw_REG_PLL_CONFIG_VCO_800_1600 |
208
chipcHw_REG_PLL_CONFIG_POWER_DOWN;
209
}
210
211
REG_LOCAL_IRQ_RESTORE;
212
213
/* Insert certain amount of delay before deasserting ARESET. */
214
udelay(1);
215
216
{
217
REG_LOCAL_IRQ_SAVE;
218
/* Remove analog reset and Power on the PLL */
219
pChipcHw->PLLConfig &=
220
~(chipcHw_REG_PLL_CONFIG_A_RESET |
221
chipcHw_REG_PLL_CONFIG_POWER_DOWN);
222
REG_LOCAL_IRQ_RESTORE;
223
}
224
225
/* Wait until PLL is locked */
226
while (!(pChipcHw->PLLStatus & chipcHw_REG_PLL_STATUS_LOCKED)
227
|| !(pChipcHw->
228
PLLStatus2 & chipcHw_REG_PLL_STATUS_LOCKED))
229
;
230
231
/* Remove digital reset */
232
{
233
REG_LOCAL_IRQ_SAVE;
234
pChipcHw->PLLConfig &= ~chipcHw_REG_PLL_CONFIG_D_RESET;
235
REG_LOCAL_IRQ_RESTORE;
236
}
237
}
238
}
239
240
EXPORT_SYMBOL(chipcHw_pll1Enable);
241
242
/****************************************************************************/
243
/**
244
* @brief Initializes the chipc module
245
*
246
* This function initializes the PLLs and core system clocks
247
*
248
*/
249
/****************************************************************************/
250
251
void chipcHw_Init(chipcHw_INIT_PARAM_t *initParam /* [ IN ] Misc chip initialization parameter */
252
) {
253
#if !(defined(__KERNEL__) && !defined(STANDALONE))
254
delay_init();
255
#endif
256
257
/* Do not program PLL, when warm reset */
258
if (!(chipcHw_getStickyBits() & chipcHw_REG_STICKY_CHIP_WARM_RESET)) {
259
chipcHw_pll1Enable(initParam->pllVcoFreqHz,
260
initParam->ssSupport);
261
chipcHw_pll2Enable(initParam->pll2VcoFreqHz);
262
} else {
263
/* Clear sticky bits */
264
chipcHw_clearStickyBits(chipcHw_REG_STICKY_CHIP_WARM_RESET);
265
}
266
/* Clear sticky bits */
267
chipcHw_clearStickyBits(chipcHw_REG_STICKY_CHIP_SOFT_RESET);
268
269
/* Before configuring the ARM clock, atleast we need to make sure BUS clock maintains the proper ratio with ARM clock */
270
pChipcHw->ACLKClock =
271
(pChipcHw->
272
ACLKClock & ~chipcHw_REG_ACLKClock_CLK_DIV_MASK) | (initParam->
273
armBusRatio &
274
chipcHw_REG_ACLKClock_CLK_DIV_MASK);
275
276
/* Set various core component frequencies. The order in which this is done is important for some. */
277
/* The RTBUS (DDR PHY) is derived from the BUS, and the BUS from the ARM, and VPM needs to know BUS */
278
/* frequency to find its ratio with the BUS. Hence we must set the ARM first, followed by the BUS, */
279
/* then VPM and RTBUS. */
280
281
chipcHw_setClockFrequency(chipcHw_CLOCK_ARM,
282
initParam->busClockFreqHz *
283
initParam->armBusRatio);
284
chipcHw_setClockFrequency(chipcHw_CLOCK_BUS, initParam->busClockFreqHz);
285
chipcHw_setClockFrequency(chipcHw_CLOCK_VPM,
286
initParam->busClockFreqHz *
287
initParam->vpmBusRatio);
288
chipcHw_setClockFrequency(chipcHw_CLOCK_DDR,
289
initParam->busClockFreqHz *
290
initParam->ddrBusRatio);
291
chipcHw_setClockFrequency(chipcHw_CLOCK_RTBUS,
292
initParam->busClockFreqHz / 2);
293
}
294
295