init_at91.c
Go to the documentation of this file.00001
00039 #include <io/arm.h>
00040 #include <cfg/macros.h>
00041
00042 #define USE_FIXED_PLL 1
00043
00044 #define XTAL_FREQ 18420000UL
00045
00046 #if USE_FIXED_PLL
00047 #if CPU_FREQ != 48023000L
00048
00049 #if !defined(ARCH_NIGHTTEST) || !(ARCH & ARCH_NIGHTTEST)
00050 #warning Clock registers set for 48.023MHz operation, revise following code if you want a different clock.
00051 #endif
00052 #endif
00053
00054
00055
00056
00057
00058 #define PLL_MUL_VAL 72
00059 #define PLL_DIV_VAL 14
00060 #define AT91MCK_PRES PMC_PRES_CLK_2
00061
00062 #else
00063
00064 #define PLL_IN_MIN 1000000UL
00065 #define PLL_IN_MAX 32000000UL
00066 #define PLL_OUT_MIN 80000000UL
00067 #define PLL_OUT_MAX 160000000UL
00068
00069 #define DIV_HARD_MIN 1
00070 #define DIV_HARD_MAX 255
00071
00072 #define DIV_MIN (DIV_ROUND(XTAL_FREQ, PLL_IN_MAX) \
00073 < DIV_HARD_MIN ? DIV_HARD_MIN : DIV_ROUND(XTAL_FREQ, PLL_IN_MAX))
00074
00075 #define DIV_MAX (DIV_ROUND(XTAL_FREQ, PLL_IN_MIN) \
00076 > DIV_HARD_MAX ? DIV_HARD_MAX : DIV_ROUND(XTAL_FREQ, PLL_IN_MIN))
00077
00078 #define MUL_MIN 0
00079 #define MUL_MAX 2047
00080
00081 typedef struct PllRegs
00082 {
00083 uint32_t mul;
00084 uint32_t div;
00085 uint32_t pres;
00086 } PllRegs;
00087
00093 static const PllRegs pllCostants(void)
00094 {
00095 uint32_t best_err = CPU_FREQ;
00096 PllRegs res;
00097
00098 for (uint32_t div = DIV_MIN; div <= DIV_MAX; div++)
00099 {
00100 for (uint32_t pres = 0; pres < 8; pres++)
00101 {
00102 uint32_t mul = DIV_ROUND((CPU_FREQ * div) << pres, XTAL_FREQ) - 1;
00103 if (mul <= MUL_MAX)
00104 {
00105 uint32_t pll = (XTAL_FREQ * (mul + 1)) / div;
00106 if (pll >= PLL_OUT_MIN && pll <= PLL_OUT_MAX)
00107 {
00108 uint32_t err = ABS((int32_t)((pll >> pres) - CPU_FREQ));
00109 if (err == 0)
00110 {
00111 res.div = div;
00112 res.mul = mul;
00113 res.pres = pres;
00114 return res;
00115 }
00116 if (err < best_err)
00117 {
00118 best_err = err;
00119 res.div = div;
00120 res.mul = mul;
00121 res.pres = pres;
00122 }
00123 }
00124 }
00125 }
00126 }
00127 return res;
00128 }
00129 #endif
00130
00131
00132
00133
00134
00135
00136 void __init1(void);
00137 void __init2(void);
00138
00151 void __init1(void)
00152 {
00153
00154
00155
00156
00157
00158
00159 #define MCN DIV_ROUNDUP(CPU_FREQ, 666667UL)
00160 #define FMCN (CPU_FREQ <= 33333UL ? 0 : (MCN < 0xFF ? MCN : 0xFF))
00161
00162 #if CPU_FREQ < 30000000UL
00163
00164 MC_FMR = FMCN << MC_FMCN_SHIFT | MC_FWS_1R2W;
00165 #else
00166
00167 MC_FMR = FMCN << MC_FMCN_SHIFT | MC_FWS_2R3W;
00168 #endif
00169
00170
00171 AIC_EOICR = 0xFFFFFFFF;
00172 AIC_IDCR = 0xFFFFFFFF;
00173
00174
00175 WDT_MR = BV(WDT_WDDIS);
00176
00177
00178
00179
00180
00181 CKGR_MOR = (6 << 8) | BV(CKGR_MOSCEN);
00182 while (!(PMC_SR & BV(PMC_MOSCS))) ;
00183
00184
00185 PMC_MCKR &= ~PMC_CSS_MASK;
00186 while (!(PMC_SR & BV(PMC_MCKRDY))) ;
00187
00188
00189 PMC_MCKR &= ~PMC_PRES_MASK;
00190 while (!(PMC_SR & BV(PMC_MCKRDY))) ;
00191
00192 uint32_t div, pres, mul;
00193 #if USE_FIXED_PLL
00194 div = PLL_DIV_VAL;
00195 mul = PLL_MUL_VAL;
00196 pres = AT91MCK_PRES;
00197 #else
00198 PllRegs pll = pllCostants();
00199 div = pll.div;
00200 mul = pll.mul;
00201 pres = pll.pres << PMC_PRES_SHIFT;
00202 #endif
00203
00204
00205
00206
00207
00208
00209 CKGR_PLLR = ((mul << CKGR_MUL_SHIFT)
00210 | (28 << CKGR_PLLCOUNT_SHIFT) | div);
00211 while (!(PMC_SR & BV(PMC_LOCK))) ;
00212
00213
00214 PMC_MCKR = pres;
00215 while (!(PMC_SR & BV(PMC_MCKRDY))) ;
00216
00217
00218
00219
00220
00221 PMC_MCKR |= PMC_CSS_PLL_CLK;
00222 while (!(PMC_SR & BV(PMC_MCKRDY))) ;
00223 }
00224
00230 void __init2(void)
00231 {
00232
00233 RSTC_MR = (RSTC_KEY | BV(RSTC_URSTEN));
00234
00235
00236 PMC_PCER = BV(PIOA_ID);
00237 #if CPU_ARM_SAM7X
00238 PMC_PCER |= BV(PIOB_ID);
00239 #endif
00240 }