pm_uc3l.c File Reference


Detailed Description

Power Manager(PM) driver interface.

Author:
Atmel Corporation: http://www.atmel.com
Support and FAQ: http://support.atmel.no/

Definition in file pm_uc3l.c.

#include "pm_uc3l.h"

Go to the source code of this file.

Data Structures

union  u_avr32_pm_cfdctrl_t
union  u_avr32_pm_cpusel_t
union  u_avr32_pm_pbasel_t
union  u_avr32_pm_pbbsel_t

Functions

long pm_config_mainclk_safety (bool cfd, bool ocp, bool final)
 Configure the main clock safety mechanisms.
long pm_disable_clk_domain_div (pm_clk_domain_t clock_domain)
 Disable the division ratio for a clock domain.
long pm_disable_module (unsigned long module)
 Disable the clock of a module.
long pm_enable_module (unsigned long module)
 Module Functions.
static pm_divratio_t pm_find_divratio (unsigned long ref_freq_hz, unsigned long target_freq_hz)
 Compute the division ratio field of the PM CPU/PBxSEL registers to apply to get a target frequency from a main clock source frequency.
void pm_set_all_cksel (unsigned long main_clock_f_hz, unsigned long cpu_f_hz, unsigned long pba_f_hz, unsigned long pbb_f_hz)
 Enable or Disable the division ratio for each clock domain depending on the main source clock frequency and each clock domain target frequency.
long pm_set_clk_domain_div (pm_clk_domain_t clock_domain, pm_divratio_t divratio)
 Set the division ratio for a clock domain.
long pm_set_mclk_source (pm_clk_src_t src)
 Clock Functions.
long pm_wait_for_clk_ready (void)
 Wait actively for the clock settings to be effective.


Function Documentation

long pm_config_mainclk_safety ( bool  cfd,
bool  ocp,
bool  final 
)

Configure the main clock safety mechanisms.

Note:
Refer to the section Clock Failure Detector of the PM chapter in the datasheet
Warning:
The Critical Path Oscillator (CRIPOSC) must be enabled before enabling the Over Clock Protection mechanism.
Parameters:
cfd Enable/disable the Clock Failure Detection mechanism
ocp Enable/disable the Over Clock Protection mechanism
final If true, make this configuration definitive
Returns:
Status.
Return values:
=0 Success.
<0 An error occured.

Definition at line 107 of file pm_uc3l.c.

References u_avr32_pm_cfdctrl_t::cfdctrl, u_avr32_pm_cfdctrl_t::CFDCTRL, and PM_UNLOCK.

00108 {
00109   u_avr32_pm_cfdctrl_t u_avr32_pm_cfdctrl = {AVR32_PM.cfdctrl};
00110 
00111   // Check if the CFDCTRL register is read-only.
00112   if(AVR32_PM.cfdctrl & AVR32_PM_CFDCTRL_SFV_MASK)
00113     return -1;
00114 
00115   // Modify
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   // Unlock the write-protected CFDCTRL register
00121   PM_UNLOCK(AVR32_PM_CFDCTRL);
00122   // Write back
00123   AVR32_PM.cfdctrl = u_avr32_pm_cfdctrl.cfdctrl;
00124   AVR32_LEAVE_CRITICAL_REGION( );
00125   
00126   return PASS;
00127 }

long pm_disable_clk_domain_div ( pm_clk_domain_t  clock_domain  ) 

Disable the division ratio for a clock domain.

Parameters:
clock_domain The clock domain to alter.
Warning:
Care should be taken that each new frequency of the synchronous clocks does not exceed the maximum frequency for each clock domain.
Returns:
Status.
Return values:
=0 Success.
<0 An error occured.

Definition at line 161 of file pm_uc3l.c.

References u_avr32_pm_cpusel_t::cpusel, u_avr32_pm_cpusel_t::CPUSEL, and PM_UNLOCK.

00162 {
00163   u_avr32_pm_cpusel_t u_avr32_pm_cpusel = {AVR32_PM.cpusel};
00164 
00165 //# Implementation note: the CPUSEL and PBASEL and PBBSEL registers all have the
00166 //# same structure.
00167 
00168 //# Implementation note: the ckSEL registers are contiguous and memory-mapped in
00169 //# that order: CPUSEL, HSBSEL, PBASEL, PBBSEL.
00170 
00171   // ckSEL must not be written while SR.CKRDY is 0.
00172   while(!(AVR32_PM.sr & AVR32_PM_SR_CKRDY_MASK));
00173 
00174   // Modify
00175   u_avr32_pm_cpusel.CPUSEL.cpudiv= DISABLE;
00176   AVR32_ENTER_CRITICAL_REGION( );
00177   // Unlock the write-protected ckSEL register
00178   PM_UNLOCK(AVR32_PM_CPUSEL + clock_domain*sizeof(avr32_pm_cpusel_t));
00179   // Update
00180   *(&(AVR32_PM.cpusel) + clock_domain)= u_avr32_pm_cpusel.cpusel;
00181   AVR32_LEAVE_CRITICAL_REGION( );
00182 
00183   return PASS;
00184 }

long pm_disable_module ( unsigned long  module  ) 

Disable the clock of a module.

Parameters:
module The module to shut down (use one of the defines in the part-specific header file under "toolchain folder"/avr32/inc(lude)/avr32/; depending on the clock domain, look for the sections "CPU clocks", "HSB clocks", "PBx clocks")
Returns:
Status.
Return values:
0 Success.
<0 An error occured.

Definition at line 280 of file pm_uc3l.c.

References PM_UNLOCK.

00281 {
00282   unsigned long domain = module>>5;
00283 //# Implementation note: the ckMASK registers are contiguous and memory-mapped
00284 //# in that order: CPUMASK, HSBMASK, PBAMASK, PBBMASK.
00285   volatile unsigned long *regptr = (volatile unsigned long*)(&(AVR32_PM.cpumask) + domain);
00286   unsigned long regvalue;
00287 
00288 
00289   // Read
00290   regvalue = *regptr;
00291   // Modify
00292   regvalue &= ~(1<<(module%32));
00293   AVR32_ENTER_CRITICAL_REGION( );
00294   // Unlock the write-protected ckMASK register
00295   PM_UNLOCK(AVR32_PM_CPUMASK + domain*sizeof(unsigned long));
00296   // Write
00297   *regptr = regvalue;
00298   AVR32_LEAVE_CRITICAL_REGION( );
00299 
00300   return PASS;
00301 }

long pm_enable_module ( unsigned long  module  ) 

Module Functions.

Enable the clock of a module.

Definition at line 257 of file pm_uc3l.c.

References PM_UNLOCK.

00258 {
00259   unsigned long domain = module>>5;
00260 //# Implementation note: the ckMASK registers are contiguous and memory-mapped
00261 //# in that order: CPUMASK, HSBMASK, PBAMASK, PBBMASK.
00262   unsigned long *regptr = (unsigned long*)(&(AVR32_PM.cpumask) + domain);  
00263   unsigned long regvalue;
00264 
00265 
00266   // Read
00267   regvalue = *regptr;
00268   // Modify
00269   regvalue |= (1<<(module%32));
00270   AVR32_ENTER_CRITICAL_REGION( );
00271   // Unlock the write-protected ckMASK register
00272   PM_UNLOCK(AVR32_PM_CPUMASK + domain*sizeof(unsigned long));
00273   // Write
00274   *regptr = regvalue;
00275   AVR32_LEAVE_CRITICAL_REGION( );
00276 
00277   return PASS;
00278 }

static pm_divratio_t pm_find_divratio ( unsigned long  ref_freq_hz,
unsigned long  target_freq_hz 
) [static]

Compute the division ratio field of the PM CPU/PBxSEL registers to apply to get a target frequency from a main clock source frequency.

Parameters:
ref_freq_hz The main clock source frequency (Hz)
target_freq_hz The target frequency (Hz)
Returns:
the division ratio CPUSEL
Return values:
PM_CKSEL_DIVRATIO_ERROR no div ratio to apply
the div ratio enum value

Definition at line 238 of file pm_uc3l.c.

References PM_CKSEL_DIVRATIO_ERROR.

Referenced by pm_set_all_cksel().

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     // div ratio field value so that rel_freq_hz = target_freq_hz*2pow(divratio+1)
00248     return((pm_divratio_t)(ctz(div_ratio)-1));
00249   }
00250 }

void pm_set_all_cksel ( unsigned long  main_clock_f_hz,
unsigned long  cpu_f_hz,
unsigned long  pba_f_hz,
unsigned long  pbb_f_hz 
)

Enable or Disable the division ratio for each clock domain depending on the main source clock frequency and each clock domain target frequency.

Parameters:
main_clock_f_hz The main source clock frequency
cpu_f_hz The target CPU clock domain frequency
pba_f_hz The target PBA clock domain frequency
pbb_f_hz The target PBB clock domain frequency
Warning:
Care should be taken that each new frequency of the synchronous clocks does not exceed the maximum frequency for each clock domain.

Definition at line 186 of file pm_uc3l.c.

References PM_CKSEL_DIVRATIO_ERROR, pm_disable_clk_domain_div(), pm_find_divratio(), and pm_set_clk_domain_div().

00188 {
00189   pm_divratio_t div_ratio;
00190 
00191 
00192   // Find the divratio to apply to reach the target cpu_f frequency.
00193   div_ratio = pm_find_divratio(main_clock_f_hz, cpu_f_hz);
00194   // Apply the division ratio for the CPU clock domain.
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   // Find the divratio to apply to reach the target pba_f frequency.
00201   div_ratio = pm_find_divratio(main_clock_f_hz, pba_f_hz);
00202   // Apply the division ratio for the PBA clock domain.
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   // Find the divratio to apply to reach the target pbb_f frequency.
00209   div_ratio = pm_find_divratio(main_clock_f_hz, pbb_f_hz);
00210   // Apply the division ratio for the PBB clock domain.
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 }

long pm_set_clk_domain_div ( pm_clk_domain_t  clock_domain,
pm_divratio_t  divratio 
)

Set the division ratio for a clock domain.

Parameters:
clock_domain The clock domain to alter.
divratio The division ratio to set.
Warning:
Care should be taken that each new frequency of the synchronous clocks does not exceed the maximum frequency for each clock domain.
Returns:
Status.
Return values:
=0 Success.
<0 An error occured.

Definition at line 129 of file pm_uc3l.c.

References u_avr32_pm_cpusel_t::cpusel, u_avr32_pm_cpusel_t::CPUSEL, PM_CPUSEL_DIVRATIO_MAX, and PM_UNLOCK.

00130 {
00131   u_avr32_pm_cpusel_t u_avr32_pm_cpusel = {AVR32_PM.cpusel};
00132 
00133 //# Implementation note: the CPUSEL and PBASEL and PBBSEL registers all have the
00134 //# same structure.
00135 
00136 //# Implementation note: the ckSEL registers are contiguous and memory-mapped in
00137 //# that order: CPUSEL, HSBSEL, PBASEL, PBBSEL.
00138   
00139 #ifdef AVR32SFW_INPUT_CHECK
00140   // Check the divratio
00141   if((divratio > PM_CPUSEL_DIVRATIO_MAX)||(divratio < 0))
00142     return -1;
00143 #endif
00144 
00145   // ckSEL must not be written while SR.CKRDY is 0.
00146   while(!(AVR32_PM.sr & AVR32_PM_SR_CKRDY_MASK));
00147 
00148   // Modify
00149   u_avr32_pm_cpusel.CPUSEL.cpudiv= 1;
00150   u_avr32_pm_cpusel.CPUSEL.cpusel = divratio;
00151   AVR32_ENTER_CRITICAL_REGION( );
00152   // Unlock the write-protected ckSEL register
00153   PM_UNLOCK(AVR32_PM_CPUSEL + clock_domain*sizeof(avr32_pm_cpusel_t));
00154   // Update
00155   *(&(AVR32_PM.cpusel) + clock_domain)= u_avr32_pm_cpusel.cpusel;
00156   AVR32_LEAVE_CRITICAL_REGION( );
00157 
00158   return PASS;
00159 }

long pm_set_mclk_source ( pm_clk_src_t  src  ) 

Clock Functions.

Set the main clock.

Definition at line 96 of file pm_uc3l.c.

References PM_UNLOCK.

00097 {
00098   AVR32_ENTER_CRITICAL_REGION( );
00099   // Unlock the write-protected MCCTRL register
00100   PM_UNLOCK(AVR32_PM_MCCTRL);
00101   AVR32_PM.mcctrl = src;
00102   AVR32_LEAVE_CRITICAL_REGION( );
00103   
00104   return PASS;
00105 }

long pm_wait_for_clk_ready ( void   ) 

Wait actively for the clock settings to be effective.

Note:
To avoid an infinite loop, this function checks the clock ready flag PM_POLL_TIMEOUT times.
Returns:
Status.
Return values:
0 Success.
<0 Unable to reach a clock ready status within the polling limit.

Definition at line 217 of file pm_uc3l.c.

References PM_POLL_TIMEOUT.

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 }


Generated on Fri Feb 19 02:26:06 2010 for AVR32 UC3 - Power Manager Driver Example 2 by  doxygen 1.5.5