source: SVN/rincon/u-boot/cpu/mcf532x/speed.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 22 months ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 5.2 KB
Line 
1/*
2 *
3 * (C) Copyright 2000-2003
4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 *
6 * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
7 * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
8 *
9 * See file CREDITS for list of people who contributed to this
10 * project.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 * MA 02111-1307 USA
26 */
27
28#include <common.h>
29#include <asm/processor.h>
30
31#include <asm/immap.h>
32
33DECLARE_GLOBAL_DATA_PTR;
34
35/* PLL min/max specifications */
36#define MAX_FVCO        500000  /* KHz */
37#define MAX_FSYS        80000   /* KHz */
38#define MIN_FSYS        58333   /* KHz */
39#define FREF            16000   /* KHz */
40#define MAX_MFD         135     /* Multiplier */
41#define MIN_MFD         88      /* Multiplier */
42#define BUSDIV          6       /* Divider */
43/*
44 * Low Power Divider specifications
45 */
46#define MIN_LPD         (1 << 0)        /* Divider (not encoded) */
47#define MAX_LPD         (1 << 15)       /* Divider (not encoded) */
48#define DEFAULT_LPD     (1 << 1)        /* Divider (not encoded) */
49
50/*
51 * Get the value of the current system clock
52 *
53 * Parameters:
54 *  none
55 *
56 * Return Value:
57 *  The current output system frequency
58 */
59int get_sys_clock(void)
60{
61        volatile ccm_t *ccm = (volatile ccm_t *)(MMAP_CCM);
62        volatile pll_t *pll = (volatile pll_t *)(MMAP_PLL);
63        int divider;
64
65        /* Test to see if device is in LIMP mode */
66        if (ccm->misccr & CCM_MISCCR_LIMP) {
67                divider = ccm->cdr & CCM_CDR_LPDIV(0xF);
68                return (FREF / (2 << divider));
69        } else {
70                return ((FREF * pll->pfdr) / (BUSDIV * 4));
71        }
72}
73
74/*
75 * Initialize the Low Power Divider circuit
76 *
77 * Parameters:
78 *  div     Desired system frequency divider
79 *
80 * Return Value:
81 *  The resulting output system frequency
82 */
83int clock_limp(int div)
84{
85        volatile ccm_t *ccm = (volatile ccm_t *)(MMAP_CCM);
86        u32 temp;
87
88        /* Check bounds of divider */
89        if (div < MIN_LPD)
90                div = MIN_LPD;
91        if (div > MAX_LPD)
92                div = MAX_LPD;
93
94        /* Save of the current value of the SSIDIV so we don't overwrite the value */
95        temp = (ccm->cdr & CCM_CDR_SSIDIV(0xF));
96
97        /* Apply the divider to the system clock */
98        ccm->cdr = (CCM_CDR_LPDIV(div) | CCM_CDR_SSIDIV(temp));
99
100        ccm->misccr |= CCM_MISCCR_LIMP;
101
102        return (FREF / (3 * (1 << div)));
103}
104
105/*
106 * Exit low power LIMP mode
107 *
108 * Parameters:
109 *  div     Desired system frequency divider
110 *
111 * Return Value:
112 *  The resulting output system frequency
113 */
114int clock_exit_limp(void)
115{
116        volatile ccm_t *ccm = (volatile ccm_t *)(MMAP_CCM);
117        int fout;
118
119        /* Exit LIMP mode */
120        ccm->misccr &= (~CCM_MISCCR_LIMP);
121
122        /* Wait for PLL to lock */
123        while (!(ccm->misccr & CCM_MISCCR_PLL_LOCK)) ;
124
125        fout = get_sys_clock();
126
127        return fout;
128}
129
130/* Initialize the PLL
131 *
132 * Parameters:
133 *  fref    PLL reference clock frequency in KHz
134 *  fsys    Desired PLL output frequency in KHz
135 *  flags   Operating parameters
136 *
137 * Return Value:
138 *  The resulting output system frequency
139 */
140int clock_pll(int fsys, int flags)
141{
142        volatile u32 *sdram_workaround = (volatile u32 *)(MMAP_SDRAM + 0x80);
143        volatile pll_t *pll = (volatile pll_t *)(MMAP_PLL);
144        int fref, temp, fout, mfd;
145        u32 i;
146
147        fref = FREF;
148
149        if (fsys == 0) {
150                /* Return current PLL output */
151                mfd = pll->pfdr;
152
153                return (fref * mfd / (BUSDIV * 4));
154        }
155
156        /* Check bounds of requested system clock */
157        if (fsys > MAX_FSYS)
158                fsys = MAX_FSYS;
159
160        if (fsys < MIN_FSYS)
161                fsys = MIN_FSYS;
162
163        /* Multiplying by 100 when calculating the temp value,
164           and then dividing by 100 to calculate the mfd allows
165           for exact values without needing to include floating
166           point libraries. */
167        temp = (100 * fsys) / fref;
168        mfd = (4 * BUSDIV * temp) / 100;
169
170        /* Determine the output frequency for selected values */
171        fout = ((fref * mfd) / (BUSDIV * 4));
172
173        /*
174         * Check to see if the SDRAM has already been initialized.
175         * If it has then the SDRAM needs to be put into self refresh
176         * mode before reprogramming the PLL.
177         */
178
179        /*
180         * Initialize the PLL to generate the new system clock frequency.
181         * The device must be put into LIMP mode to reprogram the PLL.
182         */
183
184        /* Enter LIMP mode */
185        clock_limp(DEFAULT_LPD);
186
187        /* Reprogram PLL for desired fsys */
188        pll->podr = (PLL_PODR_CPUDIV(BUSDIV / 3) | PLL_PODR_BUSDIV(BUSDIV));
189
190        pll->pfdr = mfd;
191
192        /* Exit LIMP mode */
193        clock_exit_limp();
194
195        /*
196         * Return the SDRAM to normal operation if it is in use.
197         */
198
199        /* software workaround for SDRAM opeartion after exiting LIMP mode errata */
200        *sdram_workaround = CFG_SDRAM_BASE;
201
202        /* wait for DQS logic to relock */
203        for (i = 0; i < 0x200; i++) ;
204
205        return fout;
206}
207
208/*
209 * get_clocks() fills in gd->cpu_clock and gd->bus_clk
210 */
211int get_clocks(void)
212{
213        gd->bus_clk = clock_pll(CFG_CLK / 1000, 0) * 1000;
214        gd->cpu_clk = (gd->bus_clk * 3);
215
216#ifdef CONFIG_FSL_I2C
217        gd->i2c1_clk = gd->bus_clk;
218#endif
219
220        return (0);
221}
Note: See TracBrowser for help on using the repository browser.