aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-bcmring/csp/chipc/Makefile1
-rw-r--r--arch/arm/mach-bcmring/csp/chipc/chipcHw.c776
-rw-r--r--arch/arm/mach-bcmring/csp/chipc/chipcHw_init.c293
-rw-r--r--arch/arm/mach-bcmring/csp/chipc/chipcHw_reset.c124
-rw-r--r--arch/arm/mach-bcmring/csp/chipc/chipcHw_str.c64
5 files changed, 1258 insertions, 0 deletions
diff --git a/arch/arm/mach-bcmring/csp/chipc/Makefile b/arch/arm/mach-bcmring/csp/chipc/Makefile
new file mode 100644
index 000000000000..673952768ee5
--- /dev/null
+++ b/arch/arm/mach-bcmring/csp/chipc/Makefile
@@ -0,0 +1 @@
obj-y += chipcHw.o chipcHw_str.o chipcHw_reset.o chipcHw_init.o
diff --git a/arch/arm/mach-bcmring/csp/chipc/chipcHw.c b/arch/arm/mach-bcmring/csp/chipc/chipcHw.c
new file mode 100644
index 000000000000..b3a61d860c65
--- /dev/null
+++ b/arch/arm/mach-bcmring/csp/chipc/chipcHw.c
@@ -0,0 +1,776 @@
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.c
18*
19* @brief Low level Various CHIP clock controlling routines
20*
21* @note
22*
23* These routines provide basic clock 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
39/* ---- Private Constants and Types --------------------------------------- */
40
41/* VPM alignment algorithm uses this */
42#define MAX_PHASE_ADJUST_COUNT 0xFFFF /* Max number of times allowed to adjust the phase */
43#define MAX_PHASE_ALIGN_ATTEMPTS 10 /* Max number of attempt to align the phase */
44
45/* Local definition of clock type */
46#define PLL_CLOCK 1 /* PLL Clock */
47#define NON_PLL_CLOCK 2 /* Divider clock */
48
49static int chipcHw_divide(int num, int denom)
50 __attribute__ ((section(".aramtext")));
51
52/****************************************************************************/
53/**
54* @brief Set clock fequency for miscellaneous configurable clocks
55*
56* This function sets clock frequency
57*
58* @return Configured clock frequency in hertz
59*
60*/
61/****************************************************************************/
62chipcHw_freq chipcHw_getClockFrequency(chipcHw_CLOCK_e clock /* [ IN ] Configurable clock */
63 ) {
64 volatile uint32_t *pPLLReg = (uint32_t *) 0x0;
65 volatile uint32_t *pClockCtrl = (uint32_t *) 0x0;
66 volatile uint32_t *pDependentClock = (uint32_t *) 0x0;
67 uint32_t vcoFreqPll1Hz = 0; /* Effective VCO frequency for PLL1 in Hz */
68 uint32_t vcoFreqPll2Hz = 0; /* Effective VCO frequency for PLL2 in Hz */
69 uint32_t dependentClockType = 0;
70 uint32_t vcoHz = 0;
71
72 /* Get VCO frequencies */
73 if ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASK) != chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER) {
74 uint64_t adjustFreq = 0;
75
76 vcoFreqPll1Hz = chipcHw_XTAL_FREQ_Hz *
77 chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) *
78 ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
79 chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT);
80
81 /* Adjusted frequency due to chipcHw_REG_PLL_DIVIDER_NDIV_f_SS */
82 adjustFreq = (uint64_t) chipcHw_XTAL_FREQ_Hz *
83 (uint64_t) chipcHw_REG_PLL_DIVIDER_NDIV_f_SS *
84 chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, (chipcHw_REG_PLL_PREDIVIDER_P2 * (uint64_t) chipcHw_REG_PLL_DIVIDER_FRAC));
85 vcoFreqPll1Hz += (uint32_t) adjustFreq;
86 } else {
87 vcoFreqPll1Hz = chipcHw_XTAL_FREQ_Hz *
88 chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) *
89 ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
90 chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT);
91 }
92 vcoFreqPll2Hz =
93 chipcHw_XTAL_FREQ_Hz *
94 chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) *
95 ((pChipcHw->PLLPreDivider2 & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
96 chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT);
97
98 switch (clock) {
99 case chipcHw_CLOCK_DDR:
100 pPLLReg = &pChipcHw->DDRClock;
101 vcoHz = vcoFreqPll1Hz;
102 break;
103 case chipcHw_CLOCK_ARM:
104 pPLLReg = &pChipcHw->ARMClock;
105 vcoHz = vcoFreqPll1Hz;
106 break;
107 case chipcHw_CLOCK_ESW:
108 pPLLReg = &pChipcHw->ESWClock;
109 vcoHz = vcoFreqPll1Hz;
110 break;
111 case chipcHw_CLOCK_VPM:
112 pPLLReg = &pChipcHw->VPMClock;
113 vcoHz = vcoFreqPll1Hz;
114 break;
115 case chipcHw_CLOCK_ESW125:
116 pPLLReg = &pChipcHw->ESW125Clock;
117 vcoHz = vcoFreqPll1Hz;
118 break;
119 case chipcHw_CLOCK_UART:
120 pPLLReg = &pChipcHw->UARTClock;
121 vcoHz = vcoFreqPll1Hz;
122 break;
123 case chipcHw_CLOCK_SDIO0:
124 pPLLReg = &pChipcHw->SDIO0Clock;
125 vcoHz = vcoFreqPll1Hz;
126 break;
127 case chipcHw_CLOCK_SDIO1:
128 pPLLReg = &pChipcHw->SDIO1Clock;
129 vcoHz = vcoFreqPll1Hz;
130 break;
131 case chipcHw_CLOCK_SPI:
132 pPLLReg = &pChipcHw->SPIClock;
133 vcoHz = vcoFreqPll1Hz;
134 break;
135 case chipcHw_CLOCK_ETM:
136 pPLLReg = &pChipcHw->ETMClock;
137 vcoHz = vcoFreqPll1Hz;
138 break;
139 case chipcHw_CLOCK_USB:
140 pPLLReg = &pChipcHw->USBClock;
141 vcoHz = vcoFreqPll2Hz;
142 break;
143 case chipcHw_CLOCK_LCD:
144 pPLLReg = &pChipcHw->LCDClock;
145 vcoHz = vcoFreqPll2Hz;
146 break;
147 case chipcHw_CLOCK_APM:
148 pPLLReg = &pChipcHw->APMClock;
149 vcoHz = vcoFreqPll2Hz;
150 break;
151 case chipcHw_CLOCK_BUS:
152 pClockCtrl = &pChipcHw->ACLKClock;
153 pDependentClock = &pChipcHw->ARMClock;
154 vcoHz = vcoFreqPll1Hz;
155 dependentClockType = PLL_CLOCK;
156 break;
157 case chipcHw_CLOCK_OTP:
158 pClockCtrl = &pChipcHw->OTPClock;
159 break;
160 case chipcHw_CLOCK_I2C:
161 pClockCtrl = &pChipcHw->I2CClock;
162 break;
163 case chipcHw_CLOCK_I2S0:
164 pClockCtrl = &pChipcHw->I2S0Clock;
165 break;
166 case chipcHw_CLOCK_RTBUS:
167 pClockCtrl = &pChipcHw->RTBUSClock;
168 pDependentClock = &pChipcHw->ACLKClock;
169 dependentClockType = NON_PLL_CLOCK;
170 break;
171 case chipcHw_CLOCK_APM100:
172 pClockCtrl = &pChipcHw->APM100Clock;
173 pDependentClock = &pChipcHw->APMClock;
174 vcoHz = vcoFreqPll2Hz;
175 dependentClockType = PLL_CLOCK;
176 break;
177 case chipcHw_CLOCK_TSC:
178 pClockCtrl = &pChipcHw->TSCClock;
179 break;
180 case chipcHw_CLOCK_LED:
181 pClockCtrl = &pChipcHw->LEDClock;
182 break;
183 case chipcHw_CLOCK_I2S1:
184 pClockCtrl = &pChipcHw->I2S1Clock;
185 break;
186 }
187
188 if (pPLLReg) {
189 /* Obtain PLL clock frequency */
190 if (*pPLLReg & chipcHw_REG_PLL_CLOCK_BYPASS_SELECT) {
191 /* Return crystal clock frequency when bypassed */
192 return chipcHw_XTAL_FREQ_Hz;
193 } else if (clock == chipcHw_CLOCK_DDR) {
194 /* DDR frequency is configured in PLLDivider register */
195 return chipcHw_divide (vcoHz, (((pChipcHw->PLLDivider & 0xFF000000) >> 24) ? ((pChipcHw->PLLDivider & 0xFF000000) >> 24) : 256));
196 } else {
197 /* From chip revision number B0, LCD clock is internally divided by 2 */
198 if ((pPLLReg == &pChipcHw->LCDClock) && (chipcHw_getChipRevisionNumber() != chipcHw_REV_NUMBER_A0)) {
199 vcoHz >>= 1;
200 }
201 /* Obtain PLL clock frequency using VCO dividers */
202 return chipcHw_divide(vcoHz, ((*pPLLReg & chipcHw_REG_PLL_CLOCK_MDIV_MASK) ? (*pPLLReg & chipcHw_REG_PLL_CLOCK_MDIV_MASK) : 256));
203 }
204 } else if (pClockCtrl) {
205 /* Obtain divider clock frequency */
206 uint32_t div;
207 uint32_t freq = 0;
208
209 if (*pClockCtrl & chipcHw_REG_DIV_CLOCK_BYPASS_SELECT) {
210 /* Return crystal clock frequency when bypassed */
211 return chipcHw_XTAL_FREQ_Hz;
212 } else if (pDependentClock) {
213 /* Identify the dependent clock frequency */
214 switch (dependentClockType) {
215 case PLL_CLOCK:
216 if (*pDependentClock & chipcHw_REG_PLL_CLOCK_BYPASS_SELECT) {
217 /* Use crystal clock frequency when dependent PLL clock is bypassed */
218 freq = chipcHw_XTAL_FREQ_Hz;
219 } else {
220 /* Obtain PLL clock frequency using VCO dividers */
221 div = *pDependentClock & chipcHw_REG_PLL_CLOCK_MDIV_MASK;
222 freq = div ? chipcHw_divide(vcoHz, div) : 0;
223 }
224 break;
225 case NON_PLL_CLOCK:
226 if (pDependentClock == (uint32_t *) &pChipcHw->ACLKClock) {
227 freq = chipcHw_getClockFrequency (chipcHw_CLOCK_BUS);
228 } else {
229 if (*pDependentClock & chipcHw_REG_DIV_CLOCK_BYPASS_SELECT) {
230 /* Use crystal clock frequency when dependent divider clock is bypassed */
231 freq = chipcHw_XTAL_FREQ_Hz;
232 } else {
233 /* Obtain divider clock frequency using XTAL dividers */
234 div = *pDependentClock & chipcHw_REG_DIV_CLOCK_DIV_MASK;
235 freq = chipcHw_divide (chipcHw_XTAL_FREQ_Hz, (div ? div : 256));
236 }
237 }
238 break;
239 }
240 } else {
241 /* Dependent on crystal clock */
242 freq = chipcHw_XTAL_FREQ_Hz;
243 }
244
245 div = *pClockCtrl & chipcHw_REG_DIV_CLOCK_DIV_MASK;
246 return chipcHw_divide(freq, (div ? div : 256));
247 }
248 return 0;
249}
250
251/****************************************************************************/
252/**
253* @brief Set clock fequency for miscellaneous configurable clocks
254*
255* This function sets clock frequency
256*
257* @return Configured clock frequency in Hz
258*
259*/
260/****************************************************************************/
261chipcHw_freq chipcHw_setClockFrequency(chipcHw_CLOCK_e clock, /* [ IN ] Configurable clock */
262 uint32_t freq /* [ IN ] Clock frequency in Hz */
263 ) {
264 volatile uint32_t *pPLLReg = (uint32_t *) 0x0;
265 volatile uint32_t *pClockCtrl = (uint32_t *) 0x0;
266 volatile uint32_t *pDependentClock = (uint32_t *) 0x0;
267 uint32_t vcoFreqPll1Hz = 0; /* Effective VCO frequency for PLL1 in Hz */
268 uint32_t desVcoFreqPll1Hz = 0; /* Desired VCO frequency for PLL1 in Hz */
269 uint32_t vcoFreqPll2Hz = 0; /* Effective VCO frequency for PLL2 in Hz */
270 uint32_t dependentClockType = 0;
271 uint32_t vcoHz = 0;
272 uint32_t desVcoHz = 0;
273
274 /* Get VCO frequencies */
275 if ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASK) != chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER) {
276 uint64_t adjustFreq = 0;
277
278 vcoFreqPll1Hz = chipcHw_XTAL_FREQ_Hz *
279 chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) *
280 ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
281 chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT);
282
283 /* Adjusted frequency due to chipcHw_REG_PLL_DIVIDER_NDIV_f_SS */
284 adjustFreq = (uint64_t) chipcHw_XTAL_FREQ_Hz *
285 (uint64_t) chipcHw_REG_PLL_DIVIDER_NDIV_f_SS *
286 chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, (chipcHw_REG_PLL_PREDIVIDER_P2 * (uint64_t) chipcHw_REG_PLL_DIVIDER_FRAC));
287 vcoFreqPll1Hz += (uint32_t) adjustFreq;
288
289 /* Desired VCO frequency */
290 desVcoFreqPll1Hz = chipcHw_XTAL_FREQ_Hz *
291 chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) *
292 (((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
293 chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT) + 1);
294 } else {
295 vcoFreqPll1Hz = desVcoFreqPll1Hz = chipcHw_XTAL_FREQ_Hz *
296 chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) *
297 ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
298 chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT);
299 }
300 vcoFreqPll2Hz = chipcHw_XTAL_FREQ_Hz * chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) *
301 ((pChipcHw->PLLPreDivider2 & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
302 chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT);
303
304 switch (clock) {
305 case chipcHw_CLOCK_DDR:
306 /* Configure the DDR_ctrl:BUS ratio settings */
307 {
308 REG_LOCAL_IRQ_SAVE;
309 /* Dvide DDR_phy by two to obtain DDR_ctrl clock */
310 pChipcHw->DDRClock = (pChipcHw->DDRClock & ~chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_MASK) | ((((freq / 2) / chipcHw_getClockFrequency(chipcHw_CLOCK_BUS)) - 1)
311 << chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_SHIFT);
312 REG_LOCAL_IRQ_RESTORE;
313 }
314 pPLLReg = &pChipcHw->DDRClock;
315 vcoHz = vcoFreqPll1Hz;
316 desVcoHz = desVcoFreqPll1Hz;
317 break;
318 case chipcHw_CLOCK_ARM:
319 pPLLReg = &pChipcHw->ARMClock;
320 vcoHz = vcoFreqPll1Hz;
321 desVcoHz = desVcoFreqPll1Hz;
322 break;
323 case chipcHw_CLOCK_ESW:
324 pPLLReg = &pChipcHw->ESWClock;
325 vcoHz = vcoFreqPll1Hz;
326 desVcoHz = desVcoFreqPll1Hz;
327 break;
328 case chipcHw_CLOCK_VPM:
329 /* Configure the VPM:BUS ratio settings */
330 {
331 REG_LOCAL_IRQ_SAVE;
332 pChipcHw->VPMClock = (pChipcHw->VPMClock & ~chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_MASK) | ((chipcHw_divide (freq, chipcHw_getClockFrequency(chipcHw_CLOCK_BUS)) - 1)
333 << chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_SHIFT);
334 REG_LOCAL_IRQ_RESTORE;
335 }
336 pPLLReg = &pChipcHw->VPMClock;
337 vcoHz = vcoFreqPll1Hz;
338 desVcoHz = desVcoFreqPll1Hz;
339 break;
340 case chipcHw_CLOCK_ESW125:
341 pPLLReg = &pChipcHw->ESW125Clock;
342 vcoHz = vcoFreqPll1Hz;
343 desVcoHz = desVcoFreqPll1Hz;
344 break;
345 case chipcHw_CLOCK_UART:
346 pPLLReg = &pChipcHw->UARTClock;
347 vcoHz = vcoFreqPll1Hz;
348 desVcoHz = desVcoFreqPll1Hz;
349 break;
350 case chipcHw_CLOCK_SDIO0:
351 pPLLReg = &pChipcHw->SDIO0Clock;
352 vcoHz = vcoFreqPll1Hz;
353 desVcoHz = desVcoFreqPll1Hz;
354 break;
355 case chipcHw_CLOCK_SDIO1:
356 pPLLReg = &pChipcHw->SDIO1Clock;
357 vcoHz = vcoFreqPll1Hz;
358 desVcoHz = desVcoFreqPll1Hz;
359 break;
360 case chipcHw_CLOCK_SPI:
361 pPLLReg = &pChipcHw->SPIClock;
362 vcoHz = vcoFreqPll1Hz;
363 desVcoHz = desVcoFreqPll1Hz;
364 break;
365 case chipcHw_CLOCK_ETM:
366 pPLLReg = &pChipcHw->ETMClock;
367 vcoHz = vcoFreqPll1Hz;
368 desVcoHz = desVcoFreqPll1Hz;
369 break;
370 case chipcHw_CLOCK_USB:
371 pPLLReg = &pChipcHw->USBClock;
372 vcoHz = vcoFreqPll2Hz;
373 desVcoHz = vcoFreqPll2Hz;
374 break;
375 case chipcHw_CLOCK_LCD:
376 pPLLReg = &pChipcHw->LCDClock;
377 vcoHz = vcoFreqPll2Hz;
378 desVcoHz = vcoFreqPll2Hz;
379 break;
380 case chipcHw_CLOCK_APM:
381 pPLLReg = &pChipcHw->APMClock;
382 vcoHz = vcoFreqPll2Hz;
383 desVcoHz = vcoFreqPll2Hz;
384 break;
385 case chipcHw_CLOCK_BUS:
386 pClockCtrl = &pChipcHw->ACLKClock;
387 pDependentClock = &pChipcHw->ARMClock;
388 vcoHz = vcoFreqPll1Hz;
389 desVcoHz = desVcoFreqPll1Hz;
390 dependentClockType = PLL_CLOCK;
391 break;
392 case chipcHw_CLOCK_OTP:
393 pClockCtrl = &pChipcHw->OTPClock;
394 break;
395 case chipcHw_CLOCK_I2C:
396 pClockCtrl = &pChipcHw->I2CClock;
397 break;
398 case chipcHw_CLOCK_I2S0:
399 pClockCtrl = &pChipcHw->I2S0Clock;
400 break;
401 case chipcHw_CLOCK_RTBUS:
402 pClockCtrl = &pChipcHw->RTBUSClock;
403 pDependentClock = &pChipcHw->ACLKClock;
404 dependentClockType = NON_PLL_CLOCK;
405 break;
406 case chipcHw_CLOCK_APM100:
407 pClockCtrl = &pChipcHw->APM100Clock;
408 pDependentClock = &pChipcHw->APMClock;
409 vcoHz = vcoFreqPll2Hz;
410 desVcoHz = vcoFreqPll2Hz;
411 dependentClockType = PLL_CLOCK;
412 break;
413 case chipcHw_CLOCK_TSC:
414 pClockCtrl = &pChipcHw->TSCClock;
415 break;
416 case chipcHw_CLOCK_LED:
417 pClockCtrl = &pChipcHw->LEDClock;
418 break;
419 case chipcHw_CLOCK_I2S1:
420 pClockCtrl = &pChipcHw->I2S1Clock;
421 break;
422 }
423
424 if (pPLLReg) {
425 /* Select XTAL as bypass source */
426 reg32_modify_and(pPLLReg, ~chipcHw_REG_PLL_CLOCK_SOURCE_GPIO);
427 reg32_modify_or(pPLLReg, chipcHw_REG_PLL_CLOCK_BYPASS_SELECT);
428 /* For DDR settings use only the PLL divider clock */
429 if (pPLLReg == &pChipcHw->DDRClock) {
430 /* Set M1DIV for PLL1, which controls the DDR clock */
431 reg32_write(&pChipcHw->PLLDivider, (pChipcHw->PLLDivider & 0x00FFFFFF) | ((chipcHw_REG_PLL_DIVIDER_MDIV (desVcoHz, freq)) << 24));
432 /* Calculate expected frequency */
433 freq = chipcHw_divide(vcoHz, (((pChipcHw->PLLDivider & 0xFF000000) >> 24) ? ((pChipcHw->PLLDivider & 0xFF000000) >> 24) : 256));
434 } else {
435 /* From chip revision number B0, LCD clock is internally divided by 2 */
436 if ((pPLLReg == &pChipcHw->LCDClock) && (chipcHw_getChipRevisionNumber() != chipcHw_REV_NUMBER_A0)) {
437 desVcoHz >>= 1;
438 vcoHz >>= 1;
439 }
440 /* Set MDIV to change the frequency */
441 reg32_modify_and(pPLLReg, ~(chipcHw_REG_PLL_CLOCK_MDIV_MASK));
442 reg32_modify_or(pPLLReg, chipcHw_REG_PLL_DIVIDER_MDIV(desVcoHz, freq));
443 /* Calculate expected frequency */
444 freq = chipcHw_divide(vcoHz, ((*(pPLLReg) & chipcHw_REG_PLL_CLOCK_MDIV_MASK) ? (*(pPLLReg) & chipcHw_REG_PLL_CLOCK_MDIV_MASK) : 256));
445 }
446 /* Wait for for atleast 200ns as per the protocol to change frequency */
447 udelay(1);
448 /* Do not bypass */
449 reg32_modify_and(pPLLReg, ~chipcHw_REG_PLL_CLOCK_BYPASS_SELECT);
450 /* Return the configured frequency */
451 return freq;
452 } else if (pClockCtrl) {
453 uint32_t divider = 0;
454
455 /* Divider clock should not be bypassed */
456 reg32_modify_and(pClockCtrl,
457 ~chipcHw_REG_DIV_CLOCK_BYPASS_SELECT);
458
459 /* Identify the clock source */
460 if (pDependentClock) {
461 switch (dependentClockType) {
462 case PLL_CLOCK:
463 divider = chipcHw_divide(chipcHw_divide (desVcoHz, (*pDependentClock & chipcHw_REG_PLL_CLOCK_MDIV_MASK)), freq);
464 break;
465 case NON_PLL_CLOCK:
466 {
467 uint32_t sourceClock = 0;
468
469 if (pDependentClock == (uint32_t *) &pChipcHw->ACLKClock) {
470 sourceClock = chipcHw_getClockFrequency (chipcHw_CLOCK_BUS);
471 } else {
472 uint32_t div = *pDependentClock & chipcHw_REG_DIV_CLOCK_DIV_MASK;
473 sourceClock = chipcHw_divide (chipcHw_XTAL_FREQ_Hz, ((div) ? div : 256));
474 }
475 divider = chipcHw_divide(sourceClock, freq);
476 }
477 break;
478 }
479 } else {
480 divider = chipcHw_divide(chipcHw_XTAL_FREQ_Hz, freq);
481 }
482
483 if (divider) {
484 REG_LOCAL_IRQ_SAVE;
485 /* Set the divider to obtain the required frequency */
486 *pClockCtrl = (*pClockCtrl & (~chipcHw_REG_DIV_CLOCK_DIV_MASK)) | (((divider > 256) ? chipcHw_REG_DIV_CLOCK_DIV_256 : divider) & chipcHw_REG_DIV_CLOCK_DIV_MASK);
487 REG_LOCAL_IRQ_RESTORE;
488 return freq;
489 }
490 }
491
492 return 0;
493}
494
495EXPORT_SYMBOL(chipcHw_setClockFrequency);
496
497/****************************************************************************/
498/**
499* @brief Set VPM clock in sync with BUS clock for Chip Rev #A0
500*
501* This function does the phase adjustment between VPM and BUS clock
502*
503* @return >= 0 : On success (# of adjustment required)
504* -1 : On failure
505*
506*/
507/****************************************************************************/
508static int vpmPhaseAlignA0(void)
509{
510 uint32_t phaseControl;
511 uint32_t phaseValue;
512 uint32_t prevPhaseComp;
513 int iter = 0;
514 int adjustCount = 0;
515 int count = 0;
516
517 for (iter = 0; (iter < MAX_PHASE_ALIGN_ATTEMPTS) && (adjustCount < MAX_PHASE_ADJUST_COUNT); iter++) {
518 phaseControl = (pChipcHw->VPMClock & chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK) >> chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT;
519 phaseValue = 0;
520 prevPhaseComp = 0;
521
522 /* Step 1: Look for falling PH_COMP transition */
523
524 /* Read the contents of VPM Clock resgister */
525 phaseValue = pChipcHw->VPMClock;
526 do {
527 /* Store previous value of phase comparator */
528 prevPhaseComp = phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP;
529 /* Change the value of PH_CTRL. */
530 reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
531 /* Wait atleast 20 ns */
532 udelay(1);
533 /* Toggle the LOAD_CH after phase control is written. */
534 pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE;
535 /* Read the contents of VPM Clock resgister. */
536 phaseValue = pChipcHw->VPMClock;
537
538 if ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) == 0x0) {
539 phaseControl = (0x3F & (phaseControl - 1));
540 } else {
541 /* Increment to the Phase count value for next write, if Phase is not stable. */
542 phaseControl = (0x3F & (phaseControl + 1));
543 }
544 /* Count number of adjustment made */
545 adjustCount++;
546 } while (((prevPhaseComp == (phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP)) || /* Look for a transition */
547 ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) != 0x0)) && /* Look for a falling edge */
548 (adjustCount < MAX_PHASE_ADJUST_COUNT) /* Do not exceed the limit while trying */
549 );
550
551 if (adjustCount >= MAX_PHASE_ADJUST_COUNT) {
552 /* Failed to align VPM phase after MAX_PHASE_ADJUST_COUNT tries */
553 return -1;
554 }
555
556 /* Step 2: Keep moving forward to make sure falling PH_COMP transition was valid */
557
558 for (count = 0; (count < 5) && ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) == 0); count++) {
559 phaseControl = (0x3F & (phaseControl + 1));
560 reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
561 /* Wait atleast 20 ns */
562 udelay(1);
563 /* Toggle the LOAD_CH after phase control is written. */
564 pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE;
565 phaseValue = pChipcHw->VPMClock;
566 /* Count number of adjustment made */
567 adjustCount++;
568 }
569
570 if (adjustCount >= MAX_PHASE_ADJUST_COUNT) {
571 /* Failed to align VPM phase after MAX_PHASE_ADJUST_COUNT tries */
572 return -1;
573 }
574
575 if (count != 5) {
576 /* Detected false transition */
577 continue;
578 }
579
580 /* Step 3: Keep moving backward to make sure falling PH_COMP transition was stable */
581
582 for (count = 0; (count < 3) && ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) == 0); count++) {
583 phaseControl = (0x3F & (phaseControl - 1));
584 reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
585 /* Wait atleast 20 ns */
586 udelay(1);
587 /* Toggle the LOAD_CH after phase control is written. */
588 pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE;
589 phaseValue = pChipcHw->VPMClock;
590 /* Count number of adjustment made */
591 adjustCount++;
592 }
593
594 if (adjustCount >= MAX_PHASE_ADJUST_COUNT) {
595 /* Failed to align VPM phase after MAX_PHASE_ADJUST_COUNT tries */
596 return -1;
597 }
598
599 if (count != 3) {
600 /* Detected noisy transition */
601 continue;
602 }
603
604 /* Step 4: Keep moving backward before the original transition took place. */
605
606 for (count = 0; (count < 5); count++) {
607 phaseControl = (0x3F & (phaseControl - 1));
608 reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
609 /* Wait atleast 20 ns */
610 udelay(1);
611 /* Toggle the LOAD_CH after phase control is written. */
612 pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE;
613 phaseValue = pChipcHw->VPMClock;
614 /* Count number of adjustment made */
615 adjustCount++;
616 }
617
618 if (adjustCount >= MAX_PHASE_ADJUST_COUNT) {
619 /* Failed to align VPM phase after MAX_PHASE_ADJUST_COUNT tries */
620 return -1;
621 }
622
623 if ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) == 0) {
624 /* Detected false transition */
625 continue;
626 }
627
628 /* Step 5: Re discover the valid transition */
629
630 do {
631 /* Store previous value of phase comparator */
632 prevPhaseComp = phaseValue;
633 /* Change the value of PH_CTRL. */
634 reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
635 /* Wait atleast 20 ns */
636 udelay(1);
637 /* Toggle the LOAD_CH after phase control is written. */
638 pChipcHw->VPMClock ^=
639 chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE;
640 /* Read the contents of VPM Clock resgister. */
641 phaseValue = pChipcHw->VPMClock;
642
643 if ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) == 0x0) {
644 phaseControl = (0x3F & (phaseControl - 1));
645 } else {
646 /* Increment to the Phase count value for next write, if Phase is not stable. */
647 phaseControl = (0x3F & (phaseControl + 1));
648 }
649
650 /* Count number of adjustment made */
651 adjustCount++;
652 } while (((prevPhaseComp == (phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP)) || ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) != 0x0)) && (adjustCount < MAX_PHASE_ADJUST_COUNT));
653
654 if (adjustCount >= MAX_PHASE_ADJUST_COUNT) {
655 /* Failed to align VPM phase after MAX_PHASE_ADJUST_COUNT tries */
656 return -1;
657 } else {
658 /* Valid phase must have detected */
659 break;
660 }
661 }
662
663 /* For VPM Phase should be perfectly aligned. */
664 phaseControl = (((pChipcHw->VPMClock >> chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT) - 1) & 0x3F);
665 {
666 REG_LOCAL_IRQ_SAVE;
667
668 pChipcHw->VPMClock = (pChipcHw->VPMClock & ~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT);
669 /* Load new phase value */
670 pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE;
671
672 REG_LOCAL_IRQ_RESTORE;
673 }
674 /* Return the status */
675 return (int)adjustCount;
676}
677
678/****************************************************************************/
679/**
680* @brief Set VPM clock in sync with BUS clock
681*
682* This function does the phase adjustment between VPM and BUS clock
683*
684* @return >= 0 : On success (# of adjustment required)
685* -1 : On failure
686*
687*/
688/****************************************************************************/
689int chipcHw_vpmPhaseAlign(void)
690{
691
692 if (chipcHw_getChipRevisionNumber() == chipcHw_REV_NUMBER_A0) {
693 return vpmPhaseAlignA0();
694 } else {
695 uint32_t phaseControl = chipcHw_getVpmPhaseControl();
696 uint32_t phaseValue = 0;
697 int adjustCount = 0;
698
699 /* Disable VPM access */
700 pChipcHw->Spare1 &= ~chipcHw_REG_SPARE1_VPM_BUS_ACCESS_ENABLE;
701 /* Disable HW VPM phase alignment */
702 chipcHw_vpmHwPhaseAlignDisable();
703 /* Enable SW VPM phase alignment */
704 chipcHw_vpmSwPhaseAlignEnable();
705 /* Adjust VPM phase */
706 while (adjustCount < MAX_PHASE_ADJUST_COUNT) {
707 phaseValue = chipcHw_getVpmHwPhaseAlignStatus();
708
709 /* Adjust phase control value */
710 if (phaseValue > 0xF) {
711 /* Increment phase control value */
712 phaseControl++;
713 } else if (phaseValue < 0xF) {
714 /* Decrement phase control value */
715 phaseControl--;
716 } else {
717 /* Enable VPM access */
718 pChipcHw->Spare1 |= chipcHw_REG_SPARE1_VPM_BUS_ACCESS_ENABLE;
719 /* Return adjust count */
720 return adjustCount;
721 }
722 /* Change the value of PH_CTRL. */
723 reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
724 /* Wait atleast 20 ns */
725 udelay(1);
726 /* Toggle the LOAD_CH after phase control is written. */
727 pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE;
728 /* Count adjustment */
729 adjustCount++;
730 }
731 }
732
733 /* Disable VPM access */
734 pChipcHw->Spare1 &= ~chipcHw_REG_SPARE1_VPM_BUS_ACCESS_ENABLE;
735 return -1;
736}
737
738/****************************************************************************/
739/**
740* @brief Local Divide function
741*
742* This function does the divide
743*
744* @return divide value
745*
746*/
747/****************************************************************************/
748static int chipcHw_divide(int num, int denom)
749{
750 int r;
751 int t = 1;
752
753 /* Shift denom and t up to the largest value to optimize algorithm */
754 /* t contains the units of each divide */
755 while ((denom & 0x40000000) == 0) { /* fails if denom=0 */
756 denom = denom << 1;
757 t = t << 1;
758 }
759
760 /* Intialize the result */
761 r = 0;
762
763 do {
764 /* Determine if there exists a positive remainder */
765 if ((num - denom) >= 0) {
766 /* Accumlate t to the result and calculate a new remainder */
767 num = num - denom;
768 r = r + t;
769 }
770 /* Continue to shift denom and shift t down to 0 */
771 denom = denom >> 1;
772 t = t >> 1;
773 } while (t != 0);
774
775 return r;
776}
diff --git a/arch/arm/mach-bcmring/csp/chipc/chipcHw_init.c b/arch/arm/mach-bcmring/csp/chipc/chipcHw_init.c
new file mode 100644
index 000000000000..367df75d4bb3
--- /dev/null
+++ b/arch/arm/mach-bcmring/csp/chipc/chipcHw_init.c
@@ -0,0 +1,293 @@
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/****************************************************************************/
70void 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
143EXPORT_SYMBOL(chipcHw_pll2Enable);
144
145/****************************************************************************/
146/**
147* @brief Initializes the PLL1
148*
149* This function initializes the PLL1
150*
151*/
152/****************************************************************************/
153void 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
240EXPORT_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
251void 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}
diff --git a/arch/arm/mach-bcmring/csp/chipc/chipcHw_reset.c b/arch/arm/mach-bcmring/csp/chipc/chipcHw_reset.c
new file mode 100644
index 000000000000..2671d8896bbb
--- /dev/null
+++ b/arch/arm/mach-bcmring/csp/chipc/chipcHw_reset.c
@@ -0,0 +1,124 @@
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/* ---- Include Files ---------------------------------------------------- */
16#include <csp/stdint.h>
17#include <mach/csp/chipcHw_def.h>
18#include <mach/csp/chipcHw_inline.h>
19#include <csp/intcHw.h>
20#include <csp/cache.h>
21
22/* ---- Private Constants and Types --------------------------------------- */
23/* ---- Private Variables ------------------------------------------------- */
24void chipcHw_reset_run_from_aram(void);
25
26typedef void (*RUNFUNC) (void);
27
28/****************************************************************************/
29/**
30* @brief warmReset
31*
32* @note warmReset configures the clocks which are not reset back to the state
33* required to execute on reset. To do so we need to copy the code into internal
34* memory to change the ARM clock while we are not executing from DDR.
35*/
36/****************************************************************************/
37void chipcHw_reset(uint32_t mask)
38{
39 int i = 0;
40 RUNFUNC runFunc = (RUNFUNC) (unsigned long)MM_ADDR_IO_ARAM;
41
42 /* Disable all interrupts */
43 intcHw_irq_disable(INTCHW_INTC0, 0xffffffff);
44 intcHw_irq_disable(INTCHW_INTC1, 0xffffffff);
45 intcHw_irq_disable(INTCHW_SINTC, 0xffffffff);
46
47 {
48 REG_LOCAL_IRQ_SAVE;
49 if (mask & chipcHw_REG_SOFT_RESET_CHIP_SOFT) {
50 chipcHw_softReset(chipcHw_REG_SOFT_RESET_CHIP_SOFT);
51 }
52 /* Bypass the PLL clocks before reboot */
53 pChipcHw->UARTClock |= chipcHw_REG_PLL_CLOCK_BYPASS_SELECT;
54 pChipcHw->SPIClock |= chipcHw_REG_PLL_CLOCK_BYPASS_SELECT;
55
56 /* Copy the chipcHw_warmReset_run_from_aram function into ARAM */
57 do {
58 ((uint32_t *) MM_IO_BASE_ARAM)[i] =
59 ((uint32_t *) &chipcHw_reset_run_from_aram)[i];
60 i++;
61 } while (((uint32_t *) MM_IO_BASE_ARAM)[i - 1] != 0xe1a0f00f); /* 0xe1a0f00f == asm ("mov r15, r15"); */
62
63 CSP_CACHE_FLUSH_ALL;
64
65 /* run the function from ARAM */
66 runFunc();
67
68 /* Code will never get here, but include it to balance REG_LOCAL_IRQ_SAVE above */
69 REG_LOCAL_IRQ_RESTORE;
70 }
71}
72
73/* This function must run from internal memory */
74void chipcHw_reset_run_from_aram(void)
75{
76/* Make sure, pipeline is filled with instructions coming from ARAM */
77__asm (" nop \n\t"
78 " nop \n\t"
79#if defined(__KERNEL__) && !defined(STANDALONE)
80 " MRC p15,#0x0,r0,c1,c0,#0 \n\t"
81 " BIC r0,r0,#0xd \n\t"
82 " MCR p15,#0x0,r0,c1,c0,#0 \n\t"
83 " nop \n\t"
84 " nop \n\t"
85 " nop \n\t"
86 " nop \n\t"
87 " nop \n\t"
88 " nop \n\t"
89#endif
90 " nop \n\t"
91 " nop \n\t"
92/* Bypass the ARM clock and switch to XTAL clock */
93 " MOV r2,#0x80000000 \n\t"
94 " LDR r3,[r2,#8] \n\t"
95 " ORR r3,r3,#0x20000 \n\t"
96 " STR r3,[r2,#8] \n\t"
97
98 " nop \n\t"
99 " nop \n\t"
100 " nop \n\t"
101 " nop \n\t"
102 " nop \n\t"
103 " nop \n\t"
104 " nop \n\t"
105 " nop \n\t"
106 " nop \n\t"
107 " nop \n\t"
108 " nop \n\t"
109 " nop \n\t"
110 " nop \n\t"
111 " nop \n\t"
112 " nop \n\t"
113 " nop \n\t"
114 " nop \n\t"
115 " nop \n\t"
116 " nop \n\t"
117 " nop \n\t"
118/* Issue reset */
119 " MOV r3,#0x2 \n\t"
120 " STR r3,[r2,#0x80] \n\t"
121/* End here */
122 " MOV pc,pc \n\t");
123/* 0xe1a0f00f == asm ("mov r15, r15"); */
124}
diff --git a/arch/arm/mach-bcmring/csp/chipc/chipcHw_str.c b/arch/arm/mach-bcmring/csp/chipc/chipcHw_str.c
new file mode 100644
index 000000000000..54ad964fe94c
--- /dev/null
+++ b/arch/arm/mach-bcmring/csp/chipc/chipcHw_str.c
@@ -0,0 +1,64 @@
1/*****************************************************************************
2* Copyright 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* @file chipcHw_str.c
17*
18* @brief Contains strings which are useful to linux and csp
19*
20* @note
21*/
22/****************************************************************************/
23
24/* ---- Include Files ---------------------------------------------------- */
25
26#include <mach/csp/chipcHw_inline.h>
27
28/* ---- Private Constants and Types --------------------------------------- */
29
30static const char *gMuxStr[] = {
31 "GPIO", /* 0 */
32 "KeyPad", /* 1 */
33 "I2C-Host", /* 2 */
34 "SPI", /* 3 */
35 "Uart", /* 4 */
36 "LED-Mtx-P", /* 5 */
37 "LED-Mtx-S", /* 6 */
38 "SDIO-0", /* 7 */
39 "SDIO-1", /* 8 */
40 "PCM", /* 9 */
41 "I2S", /* 10 */
42 "ETM", /* 11 */
43 "Debug", /* 12 */
44 "Misc", /* 13 */
45 "0xE", /* 14 */
46 "0xF", /* 15 */
47};
48
49/****************************************************************************/
50/**
51* @brief Retrieves a string representation of the mux setting for a pin.
52*
53* @return Pointer to a character string.
54*/
55/****************************************************************************/
56
57const char *chipcHw_getGpioPinFunctionStr(int pin)
58{
59 if ((pin < 0) || (pin >= chipcHw_GPIO_COUNT)) {
60 return "";
61 }
62
63 return gMuxStr[chipcHw_getGpioPinFunction(pin)];
64}