3
* (C) Copyright 2000-2003
4
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
6
* Copyright (C) 2004-2008, 2012 Freescale Semiconductor, Inc.
7
* TsiChung Liew (Tsi-Chung.Liew@freescale.com)
9
* SPDX-License-Identifier: GPL-2.0+
13
#include <asm/processor.h>
15
#include <asm/immap.h>
18
DECLARE_GLOBAL_DATA_PTR;
20
/* PLL min/max specifications */
21
#define MAX_FVCO 500000 /* KHz */
22
#define MAX_FSYS 80000 /* KHz */
23
#define MIN_FSYS 58333 /* KHz */
25
#ifdef CONFIG_MCF5301x
26
#define FREF 20000 /* KHz */
27
#define MAX_MFD 63 /* Multiplier */
28
#define MIN_MFD 0 /* Multiplier */
31
/* Low Power Divider specifications */
32
#define MIN_LPD (0) /* Divider (not encoded) */
33
#define MAX_LPD (15) /* Divider (not encoded) */
34
#define DEFAULT_LPD (0) /* Divider (not encoded) */
38
#define FREF 16000 /* KHz */
39
#define MAX_MFD 135 /* Multiplier */
40
#define MIN_MFD 88 /* Multiplier */
42
/* Low Power Divider specifications */
43
#define MIN_LPD (1 << 0) /* Divider (not encoded) */
44
#define MAX_LPD (1 << 15) /* Divider (not encoded) */
45
#define DEFAULT_LPD (1 << 1) /* Divider (not encoded) */
48
#define BUSDIV 6 /* Divider */
50
/* Get the value of the current system clock */
51
int get_sys_clock(void)
53
ccm_t *ccm = (ccm_t *)(MMAP_CCM);
54
pll_t *pll = (pll_t *)(MMAP_PLL);
57
/* Test to see if device is in LIMP mode */
58
if (in_be16(&ccm->misccr) & CCM_MISCCR_LIMP) {
59
divider = in_be16(&ccm->cdr) & CCM_CDR_LPDIV(0xF);
60
#ifdef CONFIG_MCF5301x
61
return (FREF / (3 * (1 << divider)));
64
return (FREF / (2 << divider));
67
#ifdef CONFIG_MCF5301x
68
u32 pfdr = (in_be32(&pll->pcr) & 0x3F) + 1;
69
u32 refdiv = (1 << ((in_be32(&pll->pcr) & PLL_PCR_REFDIV(7)) >> 8));
70
u32 busdiv = ((in_be32(&pll->pdr) & 0x00F0) >> 4) + 1;
72
return (((FREF * pfdr) / refdiv) / busdiv);
75
return (FREF * in_8(&pll->pfdr)) / (BUSDIV * 4);
81
* Initialize the Low Power Divider circuit
84
* div Desired system frequency divider
87
* The resulting output system frequency
89
int clock_limp(int div)
91
ccm_t *ccm = (ccm_t *)(MMAP_CCM);
94
/* Check bounds of divider */
100
/* Save of the current value of the SSIDIV so we don't overwrite the value */
101
temp = (in_be16(&ccm->cdr) & CCM_CDR_SSIDIV(0xFF));
103
/* Apply the divider to the system clock */
104
out_be16(&ccm->cdr, CCM_CDR_LPDIV(div) | CCM_CDR_SSIDIV(temp));
106
setbits_be16(&ccm->misccr, CCM_MISCCR_LIMP);
108
return (FREF / (3 * (1 << div)));
111
/* Exit low power LIMP mode */
112
int clock_exit_limp(void)
114
ccm_t *ccm = (ccm_t *)(MMAP_CCM);
118
clrbits_be16(&ccm->misccr, CCM_MISCCR_LIMP);
120
/* Wait for PLL to lock */
121
while (!(in_be16(&ccm->misccr) & CCM_MISCCR_PLL_LOCK))
124
fout = get_sys_clock();
129
/* Initialize the PLL
132
* fref PLL reference clock frequency in KHz
133
* fsys Desired PLL output frequency in KHz
134
* flags Operating parameters
137
* The resulting output system frequency
139
int clock_pll(int fsys, int flags)
141
#ifdef CONFIG_MCF532x
142
u32 *sdram_workaround = (u32 *)(MMAP_SDRAM + 0x80);
144
sdram_t *sdram = (sdram_t *)(MMAP_SDRAM);
145
pll_t *pll = (pll_t *)(MMAP_PLL);
146
int fref, temp, fout, mfd;
152
/* Return current PLL output */
153
#ifdef CONFIG_MCF5301x
154
u32 busdiv = ((in_be32(&pll->pdr) >> 4) & 0x0F) + 1;
155
mfd = (in_be32(&pll->pcr) & 0x3F) + 1;
157
return (fref * mfd) / busdiv;
159
#ifdef CONFIG_MCF532x
160
mfd = in_8(&pll->pfdr);
162
return (fref * mfd / (BUSDIV * 4));
166
/* Check bounds of requested system clock */
174
* Multiplying by 100 when calculating the temp value,
175
* and then dividing by 100 to calculate the mfd allows
176
* for exact values without needing to include floating
179
temp = (100 * fsys) / fref;
180
#ifdef CONFIG_MCF5301x
181
mfd = (BUSDIV * temp) / 100;
183
/* Determine the output frequency for selected values */
184
fout = ((fref * mfd) / BUSDIV);
186
#ifdef CONFIG_MCF532x
187
mfd = (4 * BUSDIV * temp) / 100;
189
/* Determine the output frequency for selected values */
190
fout = ((fref * mfd) / (BUSDIV * 4));
193
/* must not tamper with SDRAMC if running from SDRAM */
194
#if !defined(CONFIG_MONITOR_IS_IN_RAM)
196
* Check to see if the SDRAM has already been initialized.
197
* If it has then the SDRAM needs to be put into self refresh
198
* mode before reprogramming the PLL.
200
if (in_be32(&sdram->ctrl) & SDRAMC_SDCR_REF)
201
clrbits_be32(&sdram->ctrl, SDRAMC_SDCR_CKE);
204
* Initialize the PLL to generate the new system clock frequency.
205
* The device must be put into LIMP mode to reprogram the PLL.
208
/* Enter LIMP mode */
209
clock_limp(DEFAULT_LPD);
211
#ifdef CONFIG_MCF5301x
213
PLL_PDR_OUTDIV1((BUSDIV / 3) - 1) |
214
PLL_PDR_OUTDIV2(BUSDIV - 1) |
215
PLL_PDR_OUTDIV3((BUSDIV / 2) - 1) |
216
PLL_PDR_OUTDIV4(USBDIV - 1));
218
clrbits_be32(&pll->pcr, ~PLL_PCR_FBDIV_UNMASK);
219
setbits_be32(&pll->pcr, PLL_PCR_FBDIV(mfd - 1));
221
#ifdef CONFIG_MCF532x
222
/* Reprogram PLL for desired fsys */
224
PLL_PODR_CPUDIV(BUSDIV / 3) | PLL_PODR_BUSDIV(BUSDIV));
226
out_8(&pll->pfdr, mfd);
232
/* Return the SDRAM to normal operation if it is in use. */
233
if (in_be32(&sdram->ctrl) & SDRAMC_SDCR_REF)
234
setbits_be32(&sdram->ctrl, SDRAMC_SDCR_CKE);
236
#ifdef CONFIG_MCF532x
238
* software workaround for SDRAM opeartion after exiting LIMP
241
out_be32(sdram_workaround, CONFIG_SYS_SDRAM_BASE);
244
/* wait for DQS logic to relock */
245
for (i = 0; i < 0x200; i++) ;
246
#endif /* !defined(CONFIG_MONITOR_IS_IN_RAM) */
251
/* get_clocks() fills in gd->cpu_clock and gd->bus_clk */
254
gd->bus_clk = clock_pll(CONFIG_SYS_CLK / 1000, 0) * 1000;
255
gd->cpu_clk = (gd->bus_clk * 3);
257
#ifdef CONFIG_SYS_I2C_FSL
258
gd->arch.i2c1_clk = gd->bus_clk;