00001 #include "pm.h"
00002
00003
00004 int pm_reset( void )
00005 {
00006 avr32_sm_t *sm = (void *) AVR32_SM_ADDRESS;
00007 unsigned int status = PM_SUCCESS;
00008 int disable_clock_mask = 0xFFFFffff;
00009
00010 pm_set_mclk_source(PM_OSC0);
00011
00012 sm->pm_cksel = 0x00000000;
00013 status |= pm_wait_for_lock(AVR32_SM_PM_ISR_CKRDY);
00014
00015 sm->pm_cpu_mask = disable_clock_mask;
00016 status |= pm_wait_for_lock(AVR32_SM_PM_ISR_MSKRDY);
00017
00018 sm->pm_ahb_mask = disable_clock_mask;
00019 status |= pm_wait_for_lock(AVR32_SM_PM_ISR_MSKRDY);
00020
00021 sm->pm_apba_mask = disable_clock_mask;
00022 status |= pm_wait_for_lock(AVR32_SM_PM_ISR_MSKRDY);
00023
00024 sm->pm_apbb_mask = disable_clock_mask;
00025 status |= pm_wait_for_lock(AVR32_SM_PM_ISR_MSKRDY);
00026
00027 sm->pm_ier = 0x7F;
00028 sm->pm_icr |= 0x7F;
00029
00030 return status;
00031 }
00032
00033 int pm_wait_for_lock(unsigned int lockbit)
00034 {
00035 unsigned int timeout = PM_TIMEOUT;
00036 unsigned int lockStatus=0;
00037
00038 while (!lockStatus){
00039 lockStatus = pm_interrupt_status(lockbit);
00040 --timeout;
00041 if (timeout==0)
00042 return PM_LOCK_ERROR;
00043 }
00044
00045 pm_interrupt_clear(lockbit);
00046
00047 return PM_SUCCESS;
00048 }
00049
00050
00051 int pm_set_pll(volatile struct pll_opt_t *opt)
00052 {
00053 volatile avr32_sm_t *sm = (void *) AVR32_SM_ADDRESS;
00054 unsigned int pllreg, lockbit;
00055
00056
00057 if(pm_read_mclk_source()==PM_PLL0)
00058 pm_set_mclk_source(PM_OSC0);
00059
00060 if ( (opt->multiplier == 0) | (opt->divider == 0) )
00061 return PM_INVALID_ARGUMENT;
00062
00063 pllreg = (1<<AVR32_SM_PM_PLL0_PLLCOUNT_OFFSET)|(1<<AVR32_SM_PM_PLL0_PLLEN_OFFSET);
00064
00065
00066 if (opt->multiplier != 0)
00067 pllreg = pllreg | (((opt->multiplier) -1 ) << AVR32_SM_PLLMUL_OFFSET);
00068
00069 if(opt->divider != 0)
00070 pllreg = pllreg | (((opt->divider) - 1) << AVR32_SM_PLLDIV_OFFSET);
00071
00072 if(opt->oscillator <= 1)
00073 pllreg = pllreg | ((opt->oscillator) << AVR32_SM_PLLOSC_OFFSET);
00074
00075
00076
00077 if( opt->pll == PM_PLL0 )
00078 sm->pm_pll0 = pllreg;
00079 else if ( opt->pll == PM_PLL1 )
00080 sm->pm_pll1 = pllreg;
00081 else
00082 return PM_INVALID_ARGUMENT;
00083
00084
00085 if(opt->pll == PM_PLL0){
00086 lockbit = AVR32_SM_PM_ISR_LOCK0;
00087 }
00088 else{
00089 lockbit = AVR32_SM_PM_ISR_LOCK1;
00090 }
00091
00092 return pm_wait_for_lock(lockbit);
00093 }
00094
00095 int pm_read_pll_frequency( unsigned int pll )
00096 {
00097 volatile avr32_sm_t *sm = (void *) AVR32_SM_ADDRESS;
00098 unsigned int mul,div,osc;
00099
00100 if ( pll==PM_PLL0 ){
00101 mul = ( (sm->pm_pll0&AVR32_SM_PM_PLL0_PLLMUL_MASK)>>AVR32_SM_PM_PLL0_PLLMUL_OFFSET)+1;
00102 div = ( (sm->pm_pll0&AVR32_SM_PM_PLL0_PLLDIV_MASK)>>AVR32_SM_PM_PLL0_PLLDIV_OFFSET)+1;
00103 if((sm->pm_pll0&AVR32_SM_PM_PLL0_PLLOSC_MASK)>>AVR32_SM_PM_PLL0_PLLOSC_OFFSET)
00104 osc = PM_OSC1_HZ;
00105 else
00106 osc = PM_OSC0_HZ;
00107 }
00108 else if ( pll==PM_PLL1 ){
00109 mul = ( (sm->pm_pll1&AVR32_SM_PM_PLL1_PLLMUL_MASK)>>AVR32_SM_PM_PLL1_PLLMUL_OFFSET)+1;
00110 div = ( (sm->pm_pll1&AVR32_SM_PM_PLL1_PLLDIV_MASK)>>AVR32_SM_PM_PLL1_PLLDIV_OFFSET)+1;
00111 if((sm->pm_pll1&AVR32_SM_PM_PLL1_PLLOSC_MASK)>>AVR32_SM_PM_PLL1_PLLOSC_OFFSET)
00112 osc = PM_OSC1_HZ;
00113 else
00114 osc = PM_OSC0_HZ;
00115 }
00116 else
00117 return PM_INVALID_ARGUMENT;
00118
00119 return (mul*osc)/div;
00120 }
00121
00122
00123
00124 int pm_read_osc( unsigned int osc )
00125 {
00126 if(osc == 0)
00127 return PM_OSC0_HZ;
00128 else if(osc == 1)
00129 return PM_OSC1_HZ;
00130 else
00131 return PM_INVALID_ARGUMENT;
00132 }
00133
00134
00135 int pm_set_mclk_source(unsigned int source)
00136 {
00137 volatile avr32_sm_t *sm = (void *) AVR32_SM_ADDRESS;
00138
00139 if( (source == PM_OSC0) ){
00140 sm->pm_mcctrl = (0 << AVR32_SM_PLLSEL_OFFSET);
00141 }
00142 else if( source ==PM_PLL0 ){
00143 sm->pm_mcctrl = (1 << AVR32_SM_PLLSEL_OFFSET);
00144 }
00145 else
00146 return PM_INVALID_ARGUMENT;
00147
00148 return pm_wait_for_lock(AVR32_SM_PM_ISR_CKRDY);
00149
00150 }
00151
00152
00153
00154
00155 int pm_read_mclk_source( void )
00156 {
00157 int source;
00158 avr32_sm_t *sm = (void *) AVR32_SM_ADDRESS;
00159
00160 source = (sm->pm_mcctrl)&AVR32_SM_PLLSEL_MASK;
00161
00162 if(source==0)
00163 return PM_OSC0;
00164 else if(source==AVR32_SM_PLLSEL_MASK)
00165 return PM_PLL0;
00166 else
00167 return PM_INVALID_ARGUMENT;
00168 }
00169
00170
00171
00172
00173 int pm_read_mclk( void )
00174 {
00175 unsigned int f_hz, source;
00176
00177
00178 source = pm_read_mclk_source();
00179
00180
00181 if( source == PM_OSC0 )
00182 f_hz = PM_OSC0_HZ;
00183
00184 else if ( source == PM_PLL0 )
00185 f_hz = pm_read_pll_frequency(PM_PLL0);
00186 else
00187 return PM_INVALID_ARGUMENT;
00188
00189 return f_hz;
00190 }
00191
00192
00193
00194
00195 int pm_read_clock_domain_scaler(unsigned int clock_domain)
00196 {
00197 static avr32_sm_t *sm = (void *) AVR32_SM_ADDRESS;
00198 int divider, offset;
00199
00200
00201 if(clock_domain == PM_APBB_DOMAIN)
00202 offset = AVR32_SM_PM_CKSEL_APBBSEL_OFFSET;
00203 else if(clock_domain == PM_APBA_DOMAIN)
00204 offset = AVR32_SM_PM_CKSEL_APBASEL_OFFSET;
00205 else if(clock_domain == PM_AHB_DOMAIN)
00206 offset = AVR32_SM_PM_CKSEL_AHBSEL_OFFSET;
00207 else if(clock_domain == PM_CPU_DOMAIN)
00208 offset = AVR32_SM_PM_CKSEL_CPUSEL_OFFSET;
00209 else
00210 return PM_INVALID_ARGUMENT;
00211
00212
00213 divider = sm->pm_cksel & (AVR32_SM_PM_CKSEL_CPUSEL_MASK<<offset);
00214 divider = divider >> offset;
00215
00216 return (divider+1);
00217
00218 }
00219
00220
00221
00222
00223 int pm_set_clock_domain_scaler(volatile struct clk_sel_opt_t *opt)
00224 {
00225 volatile avr32_sm_t *sm = (void *) AVR32_SM_ADDRESS;
00226 int offset,new_settings;
00227
00228
00229 if( (opt->div_enable == 1) & ((opt->divider == 0)|(opt->divider >= (1<<AVR32_SM_PM_CKSEL_CPUSEL_SIZE))) )
00230 return PM_INVALID_ARGUMENT;
00231
00232
00233 switch (opt->clock){
00234 case PM_APBB_DOMAIN:
00235 offset = AVR32_SM_PM_CKSEL_APBBSEL_OFFSET;
00236 break;
00237 case PM_APBA_DOMAIN:
00238 offset = AVR32_SM_PM_CKSEL_APBASEL_OFFSET;
00239 break;
00240 case PM_AHB_DOMAIN:
00241 offset = AVR32_SM_PM_CKSEL_AHBSEL_OFFSET;
00242 break;
00243 case PM_CPU_DOMAIN:
00244 offset = AVR32_SM_PM_CKSEL_CPUSEL_OFFSET;
00245 break;
00246 default:
00247 return PM_INVALID_ARGUMENT;
00248 break;
00249 }
00250
00251
00252 if(opt->div_enable == 0){
00253 new_settings = 0x00;
00254 }
00255
00256
00257 else if (opt->div_enable == 1) {
00258 new_settings = 1<<AVR32_SM_PM_CKSEL_CPUDIV;
00259 new_settings |= ((opt->divider)-1);
00260 }
00261
00262
00263 else
00264 return PM_INVALID_ARGUMENT;
00265
00266 sm->pm_cksel &= ~((AVR32_SM_PM_CKSEL_CPUDIV_MASK|AVR32_SM_PM_CKSEL_CPUSEL_MASK)<<offset);
00267 sm->pm_cksel |= (new_settings<<offset);
00268
00269 pm_wait_for_lock(AVR32_SM_PM_ISR_CKRDY);
00270
00271 return PM_SUCCESS;
00272
00273 }
00274
00275
00276 int pm_read_scaling_register(void)
00277 {
00278 volatile avr32_sm_t *sm = (void *) AVR32_SM_ADDRESS;
00279
00280 return sm->pm_cksel;
00281 }
00282
00283
00284 int pm_unmask_module_clock( unsigned int clock )
00285 {
00286 avr32_sm_t *sm = (void *)AVR32_SM_ADDRESS;
00287
00288 switch (clock % 32){
00289 case PM_CPU_DOMAIN:
00290
00291 if( (clock/32) > PM_CPU_DOMAIN_SIZE )
00292 return PM_INVALID_ARGUMENT;
00293 else{
00294 sm->pm_cpu_mask |= ( 1<<(clock/32) );
00295 break;
00296 }
00297 case PM_AHB_DOMAIN:
00298
00299 if( (clock/32) > PM_AHB_DOMAIN_SIZE )
00300 return PM_INVALID_ARGUMENT;
00301 else{
00302 sm->pm_ahb_mask |= ( 1<<(clock/32) );
00303 break;
00304 }
00305 case PM_APBA_DOMAIN:
00306
00307 if( (clock/32) > PM_APBA_DOMAIN_SIZE )
00308 return PM_INVALID_ARGUMENT;
00309 else{
00310 sm->pm_apba_mask |= ( 1<<(clock/32) );
00311 break;
00312 }
00313 case PM_APBB_DOMAIN:
00314
00315 if( (clock/32) > PM_APBB_DOMAIN_SIZE )
00316 return PM_INVALID_ARGUMENT;
00317 else{
00318 sm->pm_apbb_mask |= ( 1<<(clock/32) );
00319 break;
00320 }
00321 default:
00322 return PM_INVALID_ARGUMENT;
00323 }
00324 return 0;
00325 }
00326
00327
00328
00329
00330 int pm_mask_module_clock( unsigned int clock )
00331 {
00332 avr32_sm_t *sm = (void *)AVR32_SM_ADDRESS;
00333
00334 switch (clock % 32){
00335 case PM_CPU_DOMAIN:
00336
00337 if( (clock/32) > PM_CPU_DOMAIN_SIZE )
00338 return PM_INVALID_ARGUMENT;
00339 else{
00340 sm->pm_cpu_mask &= ~( 1<<(clock/32) );
00341 break;
00342 }
00343 case PM_AHB_DOMAIN:
00344
00345 if( (clock/32) > PM_AHB_DOMAIN_SIZE )
00346 return PM_INVALID_ARGUMENT;
00347 else{
00348 sm->pm_ahb_mask &= ~( 1<<(clock/32) );
00349 break;
00350 }
00351 case PM_APBA_DOMAIN:
00352
00353 if( (clock/32) > PM_APBA_DOMAIN_SIZE )
00354 return PM_INVALID_ARGUMENT;
00355 else{
00356 sm->pm_apba_mask &= ~( 1<<(clock/32) );
00357 break;
00358 }
00359 case PM_APBB_DOMAIN:
00360
00361 if( (clock/32) > PM_APBB_DOMAIN_SIZE )
00362 return PM_INVALID_ARGUMENT;
00363 else{
00364 sm->pm_apbb_mask &= ~( 1<<(clock/32) );
00365 break;
00366 }
00367 default:
00368 return PM_INVALID_ARGUMENT;
00369 }
00370 return 0;
00371 }
00372
00373
00374 void pm_unmask_all_module_clocks ( void )
00375 {
00376 avr32_sm_t *sm = (void *)AVR32_SM_ADDRESS;
00377
00378 sm->pm_cpu_mask = 0x00000000;
00379 sm->pm_ahb_mask = 0x00000000;
00380 sm->pm_apba_mask = 0x00000000;
00381 sm->pm_apbb_mask = 0x00000000;
00382 pm_wait_for_lock(AVR32_SM_PM_ISR_MSKRDY);
00383 }
00384
00385
00386 void pm_mask_all_module_clocks ( void )
00387 {
00388 avr32_sm_t *sm = (void *)AVR32_SM_ADDRESS;
00389
00390 sm->pm_cpu_mask = 0xFFFFffff;
00391 sm->pm_ahb_mask = 0xFFFFffff;
00392 sm->pm_apba_mask = 0xFFFFffff;
00393 sm->pm_apbb_mask = 0xFFFFffff;
00394
00395 pm_wait_for_lock(AVR32_SM_PM_ISR_MSKRDY);
00396 }
00397
00398 int pm_read_module_frequency(int module)
00399 {
00400 int clk, domain, divider;
00401
00402 clk = pm_read_mclk();
00403
00404 divider = pm_read_clock_domain_scaler(PM_AHB_DOMAIN);
00405
00406 domain = module/32;
00407 if( domain==PM_APBA_DOMAIN)
00408 divider = divider * pm_read_clock_domain_scaler(PM_APBA_DOMAIN);
00409 else if( domain==PM_APBB_DOMAIN)
00410 divider = divider * pm_read_clock_domain_scaler(PM_APBB_DOMAIN);
00411 else
00412 return PM_INVALID_ARGUMENT;
00413
00414
00415
00416 return clk/divider;
00417 }
00418
00419
00420 int pm_interrupt_enable( unsigned int source )
00421 {
00422 avr32_sm_t *sm = (void *)AVR32_SM_ADDRESS;
00423
00424 if( source > (PM_INT_SOURCES-1) )
00425 return PM_INVALID_ARGUMENT;
00426 else{
00427 sm->pm_ier |= (1 << source);
00428 return 0;
00429 }
00430 }
00431
00432
00433
00434
00435 int pm_interrupt_disable( unsigned int source )
00436 {
00437 avr32_sm_t *sm = (void *)AVR32_SM_ADDRESS;
00438
00439 if( source > (PM_INT_SOURCES-1) )
00440 return PM_INVALID_ARGUMENT;
00441 else{
00442 sm->pm_idr |= (1 << source);
00443 return 0;
00444 }
00445 }
00446
00447
00448
00449
00450 int pm_interrupt_status( unsigned int source )
00451 {
00452 avr32_sm_t *sm = (void *)AVR32_SM_ADDRESS;
00453
00454 if ( source > (PM_INT_SOURCES-1) )
00455 return PM_INVALID_ARGUMENT;
00456 else
00457 return (sm->pm_isr & source)>>source;
00458 }
00459
00460
00461
00462
00463 int pm_interrupt_clear( unsigned int source )
00464 {
00465 avr32_sm_t *sm = (void *)AVR32_SM_ADDRESS;
00466
00467 if( source > (PM_INT_SOURCES-1) )
00468 return PM_INVALID_ARGUMENT;
00469 else{
00470 sm->pm_icr |= (1 << source);
00471 return 0;
00472 }
00473 }
00474
00475
00476
00477
00478 int pm_interrupt_mask( unsigned int source )
00479 {
00480 avr32_sm_t *sm = (void *)AVR32_SM_ADDRESS;
00481
00482 if( source > (PM_INT_SOURCES-1) )
00483 return PM_INVALID_ARGUMENT;
00484 else{
00485 return (sm->pm_ier & source ) >> source ;
00486 }
00487 }
00488
00489
00490
00491
00492 int pm_generic_clock_control( struct gen_clk_opt_t *opt)
00493 {
00494 avr32_sm_t *sm = (void *)AVR32_SM_ADDRESS;
00495
00496
00497 if( opt->div > 0xFF)
00498 return PM_INVALID_ARGUMENT;
00499
00500 if ( ((opt->diven)|(opt->cen)|(opt->pllsel)|(opt->oscsel)) > 1)
00501 return PM_INVALID_ARGUMENT;
00502 else
00503 sm->pm_gcctrl = (opt->div << AVR32_SM_PM_GCCTRL_DIV_OFFSET)| \
00504 (opt->diven << AVR32_SM_PM_GCCTRL_DIVEN_OFFSET)|\
00505 (opt->cen << AVR32_SM_PM_GCCTRL_CEN_OFFSET)|\
00506 (opt->pllsel << AVR32_SM_PM_GCCTRL_PLLSEL_OFFSET)|\
00507 (opt->oscsel << AVR32_SM_PM_GCCTRL_OSCSEL_OFFSET);
00508
00509 return 0;
00510 }
00511
00512
00513 int pm_rc_errors(void)
00514 {
00515 avr32_sm_t *sm = (void *)AVR32_SM_ADDRESS;
00516
00517 return sm->rtc_icr;
00518 }
00519