00001
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include "pm_uc3l.h"
00047
00048
00049 #ifndef AVR32_PM_VERSION_RESETVALUE
00050 #error Cannot use this software module with the current device.
00051 #else
00052 #if AVR32_PM_VERSION_RESETVALUE < 0x400
00053 #error Cannot use this software module with the current device
00054 #endif
00055 #endif
00056
00059
00060
00061 typedef union
00062 {
00063 unsigned long cfdctrl;
00064 avr32_pm_cfdctrl_t CFDCTRL;
00065 } u_avr32_pm_cfdctrl_t;
00066
00067 typedef union
00068 {
00069 unsigned long cpusel;
00070 avr32_pm_cpusel_t CPUSEL;
00071 } u_avr32_pm_cpusel_t;
00072
00073 typedef union
00074 {
00075 unsigned long pbasel;
00076 avr32_pm_pbasel_t PBASEL;
00077 } u_avr32_pm_pbasel_t;
00078
00079 typedef union
00080 {
00081 unsigned long pbbsel;
00082 avr32_pm_pbbsel_t PBBSEL;
00083 } u_avr32_pm_pbbsel_t;
00084
00086
00087
00088
00089 static pm_divratio_t pm_find_divratio(unsigned long ref_freq_hz, unsigned long target_freq_hz);
00090
00091
00096 long pm_set_mclk_source(pm_clk_src_t src)
00097 {
00098 AVR32_ENTER_CRITICAL_REGION( );
00099
00100 PM_UNLOCK(AVR32_PM_MCCTRL);
00101 AVR32_PM.mcctrl = src;
00102 AVR32_LEAVE_CRITICAL_REGION( );
00103
00104 return PASS;
00105 }
00106
00107 long pm_config_mainclk_safety(bool cfd, bool ocp, bool final)
00108 {
00109 u_avr32_pm_cfdctrl_t u_avr32_pm_cfdctrl = {AVR32_PM.cfdctrl};
00110
00111
00112 if(AVR32_PM.cfdctrl & AVR32_PM_CFDCTRL_SFV_MASK)
00113 return -1;
00114
00115
00116 u_avr32_pm_cfdctrl.CFDCTRL.cfden = cfd;
00117 u_avr32_pm_cfdctrl.CFDCTRL.ocpen = ocp;
00118 u_avr32_pm_cfdctrl.CFDCTRL.sfv = final;
00119 AVR32_ENTER_CRITICAL_REGION( );
00120
00121 PM_UNLOCK(AVR32_PM_CFDCTRL);
00122
00123 AVR32_PM.cfdctrl = u_avr32_pm_cfdctrl.cfdctrl;
00124 AVR32_LEAVE_CRITICAL_REGION( );
00125
00126 return PASS;
00127 }
00128
00129 long pm_set_clk_domain_div(pm_clk_domain_t clock_domain, pm_divratio_t divratio)
00130 {
00131 u_avr32_pm_cpusel_t u_avr32_pm_cpusel = {AVR32_PM.cpusel};
00132
00133
00134
00135
00136
00137
00138
00139 #ifdef AVR32SFW_INPUT_CHECK
00140
00141 if((divratio > PM_CPUSEL_DIVRATIO_MAX)||(divratio < 0))
00142 return -1;
00143 #endif
00144
00145
00146 while(!(AVR32_PM.sr & AVR32_PM_SR_CKRDY_MASK));
00147
00148
00149 u_avr32_pm_cpusel.CPUSEL.cpudiv= 1;
00150 u_avr32_pm_cpusel.CPUSEL.cpusel = divratio;
00151 AVR32_ENTER_CRITICAL_REGION( );
00152
00153 PM_UNLOCK(AVR32_PM_CPUSEL + clock_domain*sizeof(avr32_pm_cpusel_t));
00154
00155 *(&(AVR32_PM.cpusel) + clock_domain)= u_avr32_pm_cpusel.cpusel;
00156 AVR32_LEAVE_CRITICAL_REGION( );
00157
00158 return PASS;
00159 }
00160
00161 long pm_disable_clk_domain_div(pm_clk_domain_t clock_domain)
00162 {
00163 u_avr32_pm_cpusel_t u_avr32_pm_cpusel = {AVR32_PM.cpusel};
00164
00165
00166
00167
00168
00169
00170
00171
00172 while(!(AVR32_PM.sr & AVR32_PM_SR_CKRDY_MASK));
00173
00174
00175 u_avr32_pm_cpusel.CPUSEL.cpudiv= DISABLE;
00176 AVR32_ENTER_CRITICAL_REGION( );
00177
00178 PM_UNLOCK(AVR32_PM_CPUSEL + clock_domain*sizeof(avr32_pm_cpusel_t));
00179
00180 *(&(AVR32_PM.cpusel) + clock_domain)= u_avr32_pm_cpusel.cpusel;
00181 AVR32_LEAVE_CRITICAL_REGION( );
00182
00183 return PASS;
00184 }
00185
00186 void pm_set_all_cksel(unsigned long main_clock_f_hz, unsigned long cpu_f_hz,
00187 unsigned long pba_f_hz, unsigned long pbb_f_hz)
00188 {
00189 pm_divratio_t div_ratio;
00190
00191
00192
00193 div_ratio = pm_find_divratio(main_clock_f_hz, cpu_f_hz);
00194
00195 if(PM_CKSEL_DIVRATIO_ERROR == div_ratio)
00196 pm_disable_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_CPU);
00197 else
00198 pm_set_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_CPU, div_ratio);
00199
00200
00201 div_ratio = pm_find_divratio(main_clock_f_hz, pba_f_hz);
00202
00203 if(PM_CKSEL_DIVRATIO_ERROR == div_ratio)
00204 pm_disable_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_PBA);
00205 else
00206 pm_set_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_PBA, div_ratio);
00207
00208
00209 div_ratio = pm_find_divratio(main_clock_f_hz, pbb_f_hz);
00210
00211 if(PM_CKSEL_DIVRATIO_ERROR == div_ratio)
00212 pm_disable_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_PBB);
00213 else
00214 pm_set_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_PBB, div_ratio);
00215 }
00216
00217 long pm_wait_for_clk_ready(void)
00218 {
00219 unsigned int timeout = PM_POLL_TIMEOUT;
00220 while (!(AVR32_PM.sr & AVR32_PM_SR_CKRDY_MASK))
00221 {
00222 if(--timeout == 0)
00223 return -1;
00224 }
00225 return PASS;
00226 }
00227
00238 static pm_divratio_t pm_find_divratio(unsigned long ref_freq_hz, unsigned long target_freq_hz)
00239 {
00240 int div_ratio;
00241
00242 div_ratio = ref_freq_hz/target_freq_hz;
00243 if(div_ratio == 1)
00244 return(PM_CKSEL_DIVRATIO_ERROR);
00245 else
00246 {
00247
00248 return((pm_divratio_t)(ctz(div_ratio)-1));
00249 }
00250 }
00251
00252
00257 long pm_enable_module(unsigned long module)
00258 {
00259 unsigned long domain = module>>5;
00260
00261
00262 unsigned long *regptr = (unsigned long*)(&(AVR32_PM.cpumask) + domain);
00263 unsigned long regvalue;
00264
00265
00266
00267 regvalue = *regptr;
00268
00269 regvalue |= (1<<(module%32));
00270 AVR32_ENTER_CRITICAL_REGION( );
00271
00272 PM_UNLOCK(AVR32_PM_CPUMASK + domain*sizeof(unsigned long));
00273
00274 *regptr = regvalue;
00275 AVR32_LEAVE_CRITICAL_REGION( );
00276
00277 return PASS;
00278 }
00279
00280 long pm_disable_module(unsigned long module)
00281 {
00282 unsigned long domain = module>>5;
00283
00284
00285 volatile unsigned long *regptr = (volatile unsigned long*)(&(AVR32_PM.cpumask) + domain);
00286 unsigned long regvalue;
00287
00288
00289
00290 regvalue = *regptr;
00291
00292 regvalue &= ~(1<<(module%32));
00293 AVR32_ENTER_CRITICAL_REGION( );
00294
00295 PM_UNLOCK(AVR32_PM_CPUMASK + domain*sizeof(unsigned long));
00296
00297 *regptr = regvalue;
00298 AVR32_LEAVE_CRITICAL_REGION( );
00299
00300 return PASS;
00301 }
00302
00303
00304
00308
00309
00310
00311
00315
00316
00317
00318
00322
00323
00324
00325
00329
00330