- Main Page
- Related Pages
- Data Structures
- Files

- File List
- Globals

# pm_uc3l.c

Go to the documentation of this file.

    00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
    00016 /* Copyright (c) 2009 Atmel Corporation. All rights reserved.
    00017  *
    00018  * Redistribution and use in source and binary forms, with or without
    00019  * modification, are permitted provided that the following conditions are met:
    00020  *
    00021  * 1. Redistributions of source code must retain the above copyright notice, this
    00022  * list of conditions and the following disclaimer.
    00023  *
    00024  * 2. Redistributions in binary form must reproduce the above copyright notice,
    00025  * this list of conditions and the following disclaimer in the documentation
    00026  * and/or other materials provided with the distribution.
    00027  *
    00028  * 3. The name of Atmel may not be used to endorse or promote products derived
    00029  * from this software without specific prior written permission.
    00030  *
    00031  * 4. This software may only be redistributed and used in connection with an Atmel
    00032  * AVR product.
    00033  *
    00034  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
    00035  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    00036  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
    00037  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
    00038  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    00039  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    00040  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    00041  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00042  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    00043  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
    00044  *
    00045  */
    00046 #include "pm_uc3l.h"
    00047
    00048
    00049 #ifndef AVR32_PM_VERSION_RESETVALUE
    00050   #error Cannot use this software module with the current device.
    00051 #else
    00052   #if AVR32_PM_VERSION_RESETVALUE < 0x400
    00053     #error Cannot use this software module with the current device
    00054   #endif
    00055 #endif
    00056
    00059
    00060
    00061 typedef union
    00062 {
    00063   unsigned long                 cfdctrl;
    00064   avr32_pm_cfdctrl_t            CFDCTRL;
    00065 } u_avr32_pm_cfdctrl_t;
    00066
    00067 typedef union
    00068 {
    00069   unsigned long                 cpusel;
    00070   avr32_pm_cpusel_t             CPUSEL;
    00071 } u_avr32_pm_cpusel_t;
    00072
    00073 typedef union
    00074 {
    00075   unsigned long                 pbasel;
    00076   avr32_pm_pbasel_t             PBASEL;
    00077 } u_avr32_pm_pbasel_t;
    00078
    00079 typedef union
    00080 {
    00081   unsigned long                 pbbsel;
    00082   avr32_pm_pbbsel_t             PBBSEL;
    00083 } u_avr32_pm_pbbsel_t;
    00084
    00086
    00087
    00088 // Forward declarations
    00089 static pm_divratio_t pm_find_divratio(unsigned long ref_freq_hz, unsigned long target_freq_hz);
    00090
    00091
    00096 long pm_set_mclk_source(pm_clk_src_t src)
    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 }
    00106
    00107 long pm_config_mainclk_safety(bool cfd, bool ocp, bool final)
    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 }
    00128
    00129 long pm_set_clk_domain_div(pm_clk_domain_t clock_domain, pm_divratio_t divratio)
    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 }
    00160
    00161 long pm_disable_clk_domain_div(pm_clk_domain_t clock_domain)
    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 }
    00185
    00186 void pm_set_all_cksel(unsigned long main_clock_f_hz, unsigned long cpu_f_hz,
    00187                       unsigned long pba_f_hz, unsigned long pbb_f_hz)
    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 }
    00216
    00217 long pm_wait_for_clk_ready(void)
    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 }
    00227
    00238 static pm_divratio_t pm_find_divratio(unsigned long ref_freq_hz, unsigned long target_freq_hz)
    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 }
    00251
    00252
    00257 long pm_enable_module(unsigned long module)
    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 }
    00279
    00280 long pm_disable_module(unsigned long module)
    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 }
    00302
    00303
    00304
    00308 // Implemented as inline in pm_uc3l.h
    00309
    00310
    00311
    00315 // Implemented as inline in pm_uc3l.h
    00316
    00317
    00318
    00322 // Implemented as inline in pm_uc3l.h
    00323
    00324
    00325
    00329 // Implemented as inline in pm_uc3l.h
    00330