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