1 /* ----------------------------------------------------------------------------
\r
2 * ATMEL Microcontroller Software Support
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2008, Atmel Corporation
\r
6 * All rights reserved.
\r
8 * Redistribution and use in source and binary forms, with or without
\r
9 * modification, are permitted provided that the following conditions are met:
\r
11 * - Redistributions of source code must retain the above copyright notice,
\r
12 * this list of conditions and the disclaimer below.
\r
14 * Atmel's name may not be used to endorse or promote products derived from
\r
15 * this software without specific prior written permission.
\r
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
\r
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
\r
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
\r
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
\r
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
\r
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
\r
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
\r
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
\r
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
27 * ----------------------------------------------------------------------------
\r
30 #if defined(at91cap9)
\r
31 //------------------------------------------------------------------------------
\r
33 //------------------------------------------------------------------------------
\r
36 #include <utility/assert.h>
\r
37 #include <utility/trace.h>
\r
38 #include <utility/util.h>
\r
40 //------------------------------------------------------------------------------
\r
41 // Local definitions
\r
42 //------------------------------------------------------------------------------
\r
44 /// Start Up Time Slow Clock 32K Oscillator // see DC characteritics in Datasheet
\r
45 #define T_ST_SLCK_32K_IN_MS 1200
\r
47 /// Start Up Time Slow Clock RC Oscillator // see DC characteritics in Datasheet
\r
48 #define T_ST_SLCK_RC_IN_US 75
\r
50 #define FREQ_SLCK_32K 32768 // see DC characteritics in Datasheet
\r
51 #define MIN_FREQ_SLCK_RC 20000 // see DC characteritics in Datasheet
\r
53 #define TIME_5_CYCLES_32K_IN_US ((2 * 5 * 1000000) / FREQ_SLCK_32K)
\r
54 #define TIME_5_CYCLES_RC_IN_US ((2 * 5 * 1000000) / MIN_FREQ_SLCK_RC)
\r
56 //------------------------------------------------------------------------------
\r
58 //------------------------------------------------------------------------------
\r
60 //------------------------------------------------------------------------------
\r
62 //------------------------------------------------------------------------------
\r
63 // not precise, depends on the compiler and on the options
\r
64 static void WaitTimeInMs(unsigned int pck, unsigned int time_ms)
\r
66 register unsigned int i = 0;
\r
67 i = (pck / 1000) * time_ms;
\r
72 //------------------------------------------------------------------------------
\r
74 //------------------------------------------------------------------------------
\r
75 // not precise, depends on the compiler and on the options
\r
76 static void WaitTimeInUs(unsigned int pck, unsigned int time_us)
\r
78 volatile unsigned int i = 0;
\r
79 i = (pck / 1000000) * time_us;
\r
84 //------------------------------------------------------------------------------
\r
86 //------------------------------------------------------------------------------
\r
88 //------------------------------------------------------------------------------
\r
89 /// Return 1 if the slow clock is 32k
\r
90 //------------------------------------------------------------------------------
\r
91 unsigned char SLCK_Is32k(void)
\r
93 return ((*AT91C_SYS_SLCKSEL & AT91C_SLCKSEL_OSCSEL) != 0);
\r
96 //------------------------------------------------------------------------------
\r
97 /// Configure the 32kHz oscillator for the slow clock
\r
98 //------------------------------------------------------------------------------
\r
99 void SLCK_RCto32k(void)
\r
101 // Check that the master clock has a different source than slow clock. If no,
\r
102 if( (AT91C_BASE_PMC->PMC_MCKR & AT91C_PMC_CSS) == 0)
\r
104 TRACE_WARNING("The master clock use the slow clock. " \
\r
105 "Not possible to change Slow clock\n\r");
\r
109 // Check that the slow clock source is RC
\r
112 TRACE_WARNING("The slow clock is already the external 32.768kHz crystal\n\r");
\r
116 // Enable the 32,768 Hz oscillator by setting the bit OSC32EN to 1.
\r
117 *AT91C_SYS_SLCKSEL |= AT91C_SLCKSEL_OSC32EN;
\r
119 // Wait 32,768 Hz Startup Time for clock stabilization (software loop).
\r
120 WaitTimeInMs(BOARD_MCK*2, T_ST_SLCK_32K_IN_MS);
\r
122 // Switch from internal RC to 32,768 Hz oscillator by setting the bit OSCSEL to 1.
\r
123 *AT91C_SYS_SLCKSEL |= AT91C_SLCKSEL_OSCSEL;
\r
125 // Wait 5 slow clock cycles for internal resynchronization.
\r
126 WaitTimeInUs(BOARD_MCK*2, TIME_5_CYCLES_32K_IN_US);
\r
128 // Disable the RC oscillator by setting the bit RCEN to 0.
\r
129 *AT91C_SYS_SLCKSEL &= (0xFFFFFFFF ^ AT91C_SLCKSEL_RCEN);
\r
131 TRACE_INFO("The slow clock is now the external 32.768kHz crystal\n\r");
\r
135 //------------------------------------------------------------------------------
\r
136 /// Configure the RC oscillator for the slow clock
\r
137 //------------------------------------------------------------------------------
\r
138 void SLCK_32ktoRC(void)
\r
140 // Check that the master clock has a different source than slow clock.
\r
141 if( (AT91C_BASE_PMC->PMC_MCKR & AT91C_PMC_CSS) == 0)
\r
143 TRACE_WARNING("The master clock use the slow clock. " \
\r
144 "Not possible to change Slow clock\n\r");
\r
148 // Check that the slow clock source is RC
\r
149 if( !SLCK_Is32k() )
\r
151 TRACE_WARNING("The slow clock is already the internal RC oscillator\n\r");
\r
155 // Enable the internal RC oscillator by setting the bit RCEN to 1
\r
156 *AT91C_SYS_SLCKSEL |= AT91C_SLCKSEL_RCEN;
\r
158 // Wait internal RC Startup Time for clock stabilization (software loop).
\r
159 WaitTimeInUs(BOARD_MCK*2, T_ST_SLCK_RC_IN_US);
\r
161 // Switch from 32768 Hz oscillator to internal RC by setting the bit OSCSEL to 0.
\r
162 *AT91C_SYS_SLCKSEL &= (0xFFFFFFFF ^ AT91C_SLCKSEL_OSCSEL);
\r
164 // Wait 5 slow clock cycles for internal resynchronization.
\r
165 WaitTimeInUs(BOARD_MCK*2, TIME_5_CYCLES_RC_IN_US);
\r
167 // Disable the 32768 Hz oscillator by setting the bit OSC32EN to 0.
\r
168 *AT91C_SYS_SLCKSEL &= (0xFFFFFFFF ^ AT91C_SLCKSEL_OSC32EN);
\r
170 TRACE_INFO("The slow clock is now the internal RC oscillator\n\r");
\r
173 //------------------------------------------------------------------------------
\r
174 /// by pass the 32kHz oscillator
\r
175 //------------------------------------------------------------------------------
\r
176 void SLCK_bypass32Kosc(void)
\r
178 // Enable the bypass path OSC32BYP bit set to 1
\r
179 *AT91C_SYS_SLCKSEL |= AT91C_SLCKSEL_OSC32BYP;
\r
181 // Disable the 32,768 Hz oscillator by setting the bit OSC32EN to 0
\r
182 *AT91C_SYS_SLCKSEL &= (0xFFFFFFFF ^ AT91C_SLCKSEL_OSC32EN);
\r
185 //------------------------------------------------------------------------------
\r
186 /// set Slow Clock Mode
\r
187 //------------------------------------------------------------------------------
\r
188 #define TIMEOUT 10000000
\r
189 void SLCK_UtilSetSlowClockMode(unsigned int timeInSlowClockMode)
\r
191 unsigned int oldPll;
\r
192 unsigned int oldMck;
\r
193 unsigned int timeout = 0;
\r
195 // Save previous values for PLL A and Master Clock configuration
\r
196 oldPll = AT91C_BASE_CKGR->CKGR_PLLAR;
\r
197 oldMck = AT91C_BASE_PMC->PMC_MCKR;
\r
199 // Slow clock is selected for Master Clock
\r
200 // 32kKz / 64 = 500Hz
\r
201 // PCK = 500Hz, MCK = 250 MHz
\r
202 AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_SLOW_CLK | AT91C_PMC_PRES_CLK_64 | AT91C_PMC_MDIV_2;
\r
204 while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) && timeout++ < TIMEOUT);
\r
207 // MULA: PLL A Multiplier 0 = The PLL A is deactivated.
\r
208 AT91C_BASE_CKGR->CKGR_PLLAR = 0x00003f00;
\r
210 // Stop Main Oscillator
\r
211 AT91C_BASE_CKGR->CKGR_MOR = AT91C_BASE_CKGR->CKGR_MOR & (~AT91C_CKGR_MOSCEN);
\r
213 // Wait a while. The clock is at 500Hz...
\r
214 while( timeInSlowClockMode-- );
\r
217 // Restart Main Oscillator
\r
218 AT91C_BASE_CKGR->CKGR_MOR = AT91C_BASE_CKGR->CKGR_MOR | (AT91C_CKGR_OSCOUNT & (0x32<<8) );
\r
219 AT91C_BASE_CKGR->CKGR_MOR = AT91C_BASE_CKGR->CKGR_MOR | (AT91C_CKGR_MOSCEN);
\r
222 AT91C_BASE_CKGR->CKGR_PLLAR = oldPll;
\r
224 while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKA) && timeout++ < TIMEOUT);
\r
226 // Selection of Master Clock MCK (so Processor Clock PCK)
\r
227 AT91C_BASE_PMC->PMC_MCKR = oldMck;
\r
229 while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) && timeout++ < TIMEOUT);
\r
231 // Reconfigure DBGU
\r
232 TRACE_CONFIGURE(DBGU_STANDARD, 115200, BOARD_MCK);
\r
235 //------------------------------------------------------------------------------
\r
236 /// get the slow clock frequency
\r
237 //------------------------------------------------------------------------------
\r
238 unsigned int SLCK_UtilGetFreq(void)
\r
240 unsigned int freq = 0;
\r
242 SLCK_UtilSetSlowClockMode(0);
\r
244 if(AT91C_BASE_PMC->PMC_MCFR & (1<<16)) {
\r
245 freq = BOARD_MAINOSC / (AT91C_BASE_PMC->PMC_MCFR & 0x0000FFFF);
\r
251 #endif //#if defined(at91cap9)