# pm_uc3l.c File Reference

Power Manager(PM) driver interface. More...

`#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.

## Detailed Description

Power Manager(PM) driver interface.

- Compiler: IAR EWAVR32 and GNU GCC for AVR32
- Supported devices: All AVR32 UC3L devices.
- AppNote:

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

Definition in file pm_uc3l.c.

## 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 AVR32_ENTER_CRITICAL_REGION, AVR32_LEAVE_CRITICAL_REGION, u_avr32_pm_cfdctrl_t::cfdctrl, u_avr32_pm_cfdctrl_t::CFDCTRL, PASS, 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 AVR32_ENTER_CRITICAL_REGION, AVR32_LEAVE_CRITICAL_REGION, u_avr32_pm_cpusel_t::cpusel, u_avr32_pm_cpusel_t::CPUSEL, DISABLE, PASS, and PM_UNLOCK.

Referenced by pm_set_all_cksel().

    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 AVR32_ENTER_CRITICAL_REGION, AVR32_LEAVE_CRITICAL_REGION, PASS, and 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(avr32_pm_cpumask_t));
    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 AVR32_ENTER_CRITICAL_REGION, AVR32_LEAVE_CRITICAL_REGION, PASS, and 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(avr32_pm_cpumask_t));
    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 ctz, and 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().

Referenced by pcl_configure_synchronous_clocks().

    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 AVR32_ENTER_CRITICAL_REGION, AVR32_LEAVE_CRITICAL_REGION, u_avr32_pm_cpusel_t::cpusel, u_avr32_pm_cpusel_t::CPUSEL, PASS, PM_CPUSEL_DIVRATIO_MAX, and PM_UNLOCK.

Referenced by main(), pcl_configure_clocks(), and pm_set_all_cksel().

    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 AVR32_ENTER_CRITICAL_REGION, AVR32_LEAVE_CRITICAL_REGION, PASS, and PM_UNLOCK.

Referenced by main(), pcl_configure_clocks(), pcl_configure_synchronous_clocks(), and pcl_switch_to_osc().

    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 PASS, and 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 }