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 #include "pm_at32ap7000.h"
00044 #include "board.h"
00045 #include "ap7_errno.h"
00046 #include "compiler.h"
00047
00048 int pm_reset(void)
00049 {
00050 volatile avr32_pm_t *pm = &AVR32_PM;
00051 unsigned int status = 0;
00052 int disable_module_mask = 0xFFFFffff;
00053
00054 pm_set_mclk_source(PM_OSC0);
00055
00056 pm->cksel = 0x00000000;
00057 status |= pm_wait_for_status(AVR32_PM_ISR_CKRDY);
00058
00059 pm->cpumask = disable_module_mask;
00060 status |= pm_wait_for_status(AVR32_PM_ISR_MSKRDY);
00061
00062 pm->hsbmask = disable_module_mask;
00063 status |= pm_wait_for_status(AVR32_PM_ISR_MSKRDY);
00064
00065 pm->pbamask = disable_module_mask;
00066 status |= pm_wait_for_status(AVR32_PM_ISR_MSKRDY);
00067
00068 pm->pbbmask = disable_module_mask;
00069 status |= pm_wait_for_status(AVR32_PM_ISR_MSKRDY);
00070
00071 pm->idr = 0x7f;
00072 pm->icr = 0x7f;
00073
00074 return status;
00075 }
00076
00077
00078 unsigned int pm_get_reset_cause(void)
00079 {
00080 volatile avr32_pm_t *pm = &AVR32_PM;
00081
00082 return pm->rcause;
00083 }
00084
00085
00086 int pm_start_osc(const pm_osc_opt_t *opt)
00087 {
00088 return PM_NOT_SUPPORTED;
00089 }
00090
00091
00092 int pm_stop_osc(int osc_id)
00093 {
00094 return PM_NOT_SUPPORTED;
00095 }
00096
00097
00098 int pm_start_pll(pm_pll_opt_t *opt)
00099 {
00100 volatile avr32_pm_t *pm = &AVR32_PM;
00101 unsigned int pllreg;
00102 int retval;
00103
00104
00105 if ((opt->pll_id == 0) && (pm_get_mclk_source() == PM_PLL0))
00106 pm_set_mclk_source(PM_OSC0);
00107
00108 if ((opt->mul == 0) | (opt->div == 0) | (opt->osc_id > 1))
00109 return INVALID_ARGUMENT;
00110
00111 pllreg = opt->count << AVR32_PM_PLLCOUNT_OFFSET
00112 | (opt->mul - 1) << AVR32_PM_PLLMUL_OFFSET
00113 | (opt->div - 1) << AVR32_PM_PLLDIV_OFFSET
00114 | 4 << AVR32_PM_PLLOPT_OFFSET
00115 | opt->osc_id << AVR32_PM_PLLOSC_OFFSET
00116 | 1 << AVR32_PM_PLLEN_OFFSET;
00117
00118 if (opt->pll_id == 0)
00119 pm->pll0 = pllreg;
00120 else if (opt->pll_id == 1)
00121 pm->pll1 = pllreg;
00122 else
00123 return INVALID_ARGUMENT;
00124
00125 if (opt->wait_for_lock) {
00126 retval = pm_wait_for_clock_source_lock(opt->pll_id == 0 ? PM_PLL0 : PM_PLL1);
00127 if (retval != 0)
00128 return retval;
00129 }
00130
00131 return pm_get_clock_source_freq_hz(opt->pll_id == 0 ? PM_PLL0 : PM_PLL1);
00132 }
00133
00134
00135 int pm_start_pll_freq(int pll, unsigned int freq, Bool wait_for_lock)
00136 {
00137 return PM_NOT_SUPPORTED;
00138 }
00139
00140
00141 int pm_stop_pll(int pll)
00142 {
00143 return PM_NOT_SUPPORTED;
00144 }
00145
00146
00147 int pm_wait_for_clock_source_lock(int source)
00148 {
00149 unsigned int status;
00150
00151 switch (source) {
00152 case PM_OSC0:
00153 case PM_OSC1:
00154 return 0;
00155 case PM_PLL0:
00156 status = 1 << AVR32_PM_ISR_LOCK0;
00157 break;
00158 case PM_PLL1:
00159 status = 1 << AVR32_PM_ISR_LOCK1;
00160 break;
00161 default:
00162 return INVALID_ARGUMENT;
00163 }
00164
00165 return pm_wait_for_status(status);
00166 }
00167
00168
00169 int pm_get_clock_source_freq_hz(int clock_source)
00170 {
00171 volatile avr32_pm_t *pm = &AVR32_PM;
00172 unsigned int mul, div, osc;
00173
00174 switch (clock_source) {
00175 case PM_OSC0:
00176 return FOSC0;
00177 case PM_OSC1:
00178 return FOSC1;
00179 case PM_PLL0:
00180 mul = ((pm->pll0 & AVR32_PM_PLL0_PLLMUL_MASK) >> AVR32_PM_PLL0_PLLMUL_OFFSET) + 1;
00181 div = ((pm->pll0 & AVR32_PM_PLL0_PLLDIV_MASK) >> AVR32_PM_PLL0_PLLDIV_OFFSET) + 1;
00182 if((pm->pll0 & AVR32_PM_PLL0_PLLOSC_MASK) >> AVR32_PM_PLL0_PLLOSC_OFFSET)
00183 osc = FOSC1;
00184 else
00185 osc = FOSC0;
00186 break;
00187 case PM_PLL1:
00188 mul = ((pm->pll1 & AVR32_PM_PLL1_PLLMUL_MASK) >> AVR32_PM_PLL1_PLLMUL_OFFSET) + 1;
00189 div = ((pm->pll1 & AVR32_PM_PLL1_PLLDIV_MASK) >> AVR32_PM_PLL1_PLLDIV_OFFSET) + 1;
00190 if((pm->pll1 & AVR32_PM_PLL1_PLLOSC_MASK) >> AVR32_PM_PLL1_PLLOSC_OFFSET)
00191 osc = FOSC1;
00192 else
00193 osc = FOSC0;
00194 break;
00195 default:
00196 return INVALID_ARGUMENT;
00197 }
00198
00199 return (mul * osc) / div;
00200 }
00201
00202
00203 int pm_wait_for_status(unsigned int status)
00204 {
00205 unsigned int timeout = PM_TIMEOUT;
00206
00207 while ((pm_get_interrupt_status() & status) != status) {
00208 timeout--;
00209 if (timeout==0)
00210 return -1;
00211 }
00212
00213 pm_clear_interrupt_status(status);
00214
00215 return 0;
00216 }
00217
00218
00219 int pm_enable_interrupt(unsigned int mask)
00220 {
00221 volatile avr32_pm_t *pm = &AVR32_PM;
00222
00223 pm->ier = mask;
00224
00225 return pm->ier;
00226 }
00227
00228
00229 int pm_disable_interrupt(unsigned int mask)
00230 {
00231 volatile avr32_pm_t *pm = &AVR32_PM;
00232
00233 pm->idr = mask;
00234
00235 return pm->idr;
00236 }
00237
00238
00239 unsigned int pm_get_enabled_interrupts(void)
00240 {
00241 volatile avr32_pm_t *pm = &AVR32_PM;
00242
00243 return pm->imr;
00244 }
00245
00246
00247 unsigned int pm_get_interrupt_status(void)
00248 {
00249 volatile avr32_pm_t *pm = &AVR32_PM;
00250 return pm->isr;
00251 }
00252
00253
00254 int pm_clear_interrupt_status(unsigned int mask)
00255 {
00256 volatile avr32_pm_t *pm = &AVR32_PM;
00257
00258 pm->icr=mask;
00259
00260 return ~(pm->isr & mask);
00261 }
00262
00263
00264 int pm_calibrate(int source, unsigned int calibration_value)
00265 {
00266 return PM_NOT_SUPPORTED;
00267 }
00268
00269
00270 int pm_set_bod_settings(unsigned int bod_control, Bool hysteresis, unsigned char level)
00271 {
00272 return PM_NOT_SUPPORTED;
00273 }
00274
00275
00276 int pm_get_bod_settings(unsigned int bod_control, Bool hysteresis, unsigned char level)
00277 {
00278 return PM_NOT_SUPPORTED;
00279 }
00280
00281
00282 int pm_set_mclk_source(int clock_source)
00283 {
00284 volatile avr32_pm_t *pm = &AVR32_PM;
00285
00286 if ((clock_source == PM_OSC0))
00287 pm->mcctrl = (0 << AVR32_PM_PLLSEL_OFFSET);
00288 else if (clock_source == PM_PLL0)
00289 pm->mcctrl = (1 << AVR32_PM_PLLSEL_OFFSET);
00290 else
00291 return INVALID_ARGUMENT;
00292
00293 return pm_wait_for_clock_source_lock(clock_source);
00294 }
00295
00296
00297 int pm_get_mclk_source(void)
00298 {
00299 unsigned int source;
00300 volatile avr32_pm_t *pm = &AVR32_PM;
00301
00302 source = pm->mcctrl & AVR32_PM_PLLSEL_MASK;
00303
00304 if(source==0)
00305 return PM_OSC0;
00306 else if(source==AVR32_PM_PLLSEL_MASK)
00307 return PM_PLL0;
00308 else
00309 return INVALID_ARGUMENT;
00310 }
00311
00312
00313 int pm_get_mclk_freq_hz(void)
00314 {
00315 unsigned int f_hz;
00316 int source;
00317
00318
00319 source = pm_get_mclk_source();
00320
00321
00322 if( source == PM_OSC0 )
00323 f_hz = FOSC0;
00324
00325 else if ( source == PM_PLL0 )
00326 f_hz = pm_get_clock_source_freq_hz(PM_PLL0);
00327 else
00328 return INVALID_ARGUMENT;
00329
00330 return f_hz;
00331 }
00332
00333
00334 int pm_read_module_domain_scaler(unsigned int module_domain)
00335 {
00336 volatile avr32_pm_t *pm = &AVR32_PM;
00337 unsigned int divider, offset, cksel;
00338
00339
00340 if(module_domain == PM_PBB_DOMAIN)
00341 offset = AVR32_PM_CKSEL_PBBSEL_OFFSET;
00342 else if(module_domain == PM_PBA_DOMAIN)
00343 offset = AVR32_PM_CKSEL_PBASEL_OFFSET;
00344 else if(module_domain == PM_HSB_DOMAIN)
00345 offset = AVR32_PM_CKSEL_HSBSEL_OFFSET;
00346 else if(module_domain == PM_CPU_DOMAIN)
00347 offset = AVR32_PM_CKSEL_CPUSEL_OFFSET;
00348 else
00349 return INVALID_ARGUMENT;
00350
00351 cksel = pm->cksel >> offset;
00352
00353 if (cksel & AVR32_PM_CKSEL_CPUDIV_MASK)
00354 divider = 1 << ((cksel & AVR32_PM_CKSEL_CPUSEL_MASK) + 1);
00355 else
00356 divider = 1;
00357
00358 return divider;
00359 }
00360
00361
00362 int pm_set_clock_domain_scaler(unsigned int clock_domain, int divider)
00363 {
00364 volatile avr32_pm_t *pm = &AVR32_PM;
00365 unsigned int offset;
00366 int divsel;
00367
00368
00369 divsel = ctz(divider);
00370
00371 if ((divsel > 8) || ((1 << divsel) != divider))
00372 return INVALID_ARGUMENT;
00373
00374 if (divsel > 0)
00375 divsel = (divsel - 1) | AVR32_PM_CKSEL_CPUDIV_MASK;
00376
00377
00378 switch (clock_domain){
00379 case PM_PBB_DOMAIN:
00380 offset = AVR32_PM_CKSEL_PBBSEL_OFFSET;
00381 break;
00382 case PM_PBA_DOMAIN:
00383 offset = AVR32_PM_CKSEL_PBASEL_OFFSET;
00384 break;
00385 case PM_HSB_DOMAIN:
00386 offset = AVR32_PM_CKSEL_HSBSEL_OFFSET;
00387 break;
00388 case PM_CPU_DOMAIN:
00389 offset = AVR32_PM_CKSEL_CPUSEL_OFFSET;
00390 break;
00391 default:
00392 return INVALID_ARGUMENT;
00393 }
00394
00395 pm->cksel = (pm->cksel & ~((AVR32_PM_CKSEL_CPUDIV_MASK | AVR32_PM_CKSEL_CPUSEL_MASK) << offset))
00396 | (divsel << offset);
00397
00398 pm_wait_for_status(AVR32_PM_ISR_CKRDY);
00399
00400 return 0;
00401 }
00402
00403
00404 int pm_read_module_freq_hz(unsigned int module)
00405 {
00406 unsigned int clk, domain;
00407 int divider;
00408
00409 clk = pm_get_mclk_freq_hz();
00410
00411 domain = module / 32;
00412 divider = pm_read_module_domain_scaler(domain);
00413 if (divider < 0)
00414 return divider;
00415
00416
00417
00418 return clk / divider;
00419 }
00420
00421
00422 int pm_enable_module(unsigned int module)
00423 {
00424 volatile avr32_pm_t *pm = &AVR32_PM;
00425
00426 switch (module % 32){
00427 case PM_CPU_DOMAIN:
00428
00429 if( (module/32) > PM_CPU_DOMAIN_SIZE )
00430 return INVALID_ARGUMENT;
00431 else{
00432 pm->cpumask |= ( 1<<(module/32) );
00433 break;
00434 }
00435 case PM_HSB_DOMAIN:
00436
00437 if( (module/32) > PM_HSB_DOMAIN_SIZE )
00438 return INVALID_ARGUMENT;
00439 else{
00440 pm->hsbmask |= ( 1<<(module/32) );
00441 break;
00442 }
00443 case PM_PBA_DOMAIN:
00444
00445 if( (module/32) > PM_PBA_DOMAIN_SIZE )
00446 return INVALID_ARGUMENT;
00447 else{
00448 pm->pbamask |= ( 1<<(module/32) );
00449 break;
00450 }
00451 case PM_PBB_DOMAIN:
00452
00453 if( (module/32) > PM_PBB_DOMAIN_SIZE )
00454 return INVALID_ARGUMENT;
00455 else{
00456 pm->pbbmask |= ( 1<<(module/32) );
00457 break;
00458 }
00459 default:
00460 return INVALID_ARGUMENT;
00461 }
00462 return 0;
00463 }
00464
00465
00466 int pm_disable_module(unsigned int module)
00467 {
00468 volatile avr32_pm_t *pm = &AVR32_PM;
00469
00470 switch (module % 32){
00471 case PM_CPU_DOMAIN:
00472
00473 if( (module/32) > PM_CPU_DOMAIN_SIZE )
00474 return INVALID_ARGUMENT;
00475 else{
00476 pm->cpumask &= ~( 1<<(module/32) );
00477 break;
00478 }
00479 case PM_HSB_DOMAIN:
00480
00481 if( (module/32) > PM_HSB_DOMAIN_SIZE )
00482 return INVALID_ARGUMENT;
00483 else{
00484 pm->hsbmask &= ~( 1<<(module/32) );
00485 break;
00486 }
00487 case PM_PBA_DOMAIN:
00488
00489 if( (module/32) > PM_PBA_DOMAIN_SIZE )
00490 return INVALID_ARGUMENT;
00491 else{
00492 pm->pbamask &= ~( 1<<(module/32) );
00493 break;
00494 }
00495 case PM_PBB_DOMAIN:
00496
00497 if( (module/32) > PM_PBB_DOMAIN_SIZE )
00498 return INVALID_ARGUMENT;
00499 else{
00500 pm->pbbmask &= ~( 1<<(module/32) );
00501 break;
00502 }
00503 default:
00504 return INVALID_ARGUMENT;
00505 }
00506 return 0;
00507 }
00508
00509
00510 int pm_start_generic_clock(unsigned int clock, const pm_gen_clk_opt_t *opt)
00511 {
00512 volatile avr32_pm_t *pm = &AVR32_PM;
00513 unsigned int reg = 1 << AVR32_PM_GCCTRL0_CEN_OFFSET;
00514
00515 if (opt->divider > 1)
00516 reg |= (((opt->divider >> 1) - 1) << AVR32_PM_GCCTRL0_DIV_OFFSET) | (1 << AVR32_PM_GCCTRL0_DIVEN_OFFSET);
00517
00518 if ( (opt->clock_source == PM_OSC0) || (opt->clock_source == PM_OSC1) )
00519 reg |= opt->clock_source << AVR32_PM_GCCTRL0_OSCSEL_OFFSET;
00520 else if ( (opt->clock_source == PM_PLL0) || (opt->clock_source == PM_PLL1) )
00521 reg |= ((opt->clock_source-3) << AVR32_PM_GCCTRL0_OSCSEL_OFFSET) | (1 << AVR32_PM_GCCTRL0_PLLSEL_OFFSET);
00522 else
00523 return INVALID_ARGUMENT;
00524
00525 pm->gcctrl[clock] = reg;
00526
00527 return 0;
00528 }
00529
00530
00531 int pm_stop_generic_clock(unsigned int clock)
00532 {
00533 volatile avr32_pm_t *pm = &AVR32_PM;
00534
00535 pm->gcctrl[clock] &= ~(1 << AVR32_PM_GCCTRL0_CEN_OFFSET);
00536
00537 return 0;
00538 }
00539