diff options
Diffstat (limited to 'firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/PM')
5 files changed, 2252 insertions, 0 deletions
| diff --git a/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/PM/pm.c b/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/PM/pm.c new file mode 100644 index 0000000..76d9268 --- /dev/null +++ b/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/PM/pm.c @@ -0,0 +1,546 @@ +/* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */ + +/*This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief Power Manager driver. + * + * + * - Compiler:           IAR EWAVR32 and GNU GCC for AVR32 + * - Supported devices:  All AVR32 devices. + * - AppNote: + * + * \author               Atmel Corporation: http://www.atmel.com \n + *                       Support and FAQ: http://support.atmel.no/ + * + *****************************************************************************/ + +/* Copyright (c) 2009 Atmel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an Atmel + * AVR product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE + * + */ + +#include "compiler.h" +#include "pm.h" + + +/*! \name PM Writable Bit-Field Registers + */ +//! @{ + +typedef union +{ +  unsigned long                 mcctrl; +  avr32_pm_mcctrl_t             MCCTRL; +} u_avr32_pm_mcctrl_t; + +typedef union +{ +  unsigned long                 cksel; +  avr32_pm_cksel_t              CKSEL; +} u_avr32_pm_cksel_t; + +typedef union +{ +  unsigned long                 pll; +  avr32_pm_pll_t                PLL; +} u_avr32_pm_pll_t; + +typedef union +{ +  unsigned long                 oscctrl0; +  avr32_pm_oscctrl0_t           OSCCTRL0; +} u_avr32_pm_oscctrl0_t; + +typedef union +{ +  unsigned long                 oscctrl1; +  avr32_pm_oscctrl1_t           OSCCTRL1; +} u_avr32_pm_oscctrl1_t; + +typedef union +{ +  unsigned long                 oscctrl32; +  avr32_pm_oscctrl32_t          OSCCTRL32; +} u_avr32_pm_oscctrl32_t; + +typedef union +{ +  unsigned long                 ier; +  avr32_pm_ier_t                IER; +} u_avr32_pm_ier_t; + +typedef union +{ +  unsigned long                 idr; +  avr32_pm_idr_t                IDR; +} u_avr32_pm_idr_t; + +typedef union +{ +  unsigned long                 icr; +  avr32_pm_icr_t                ICR; +} u_avr32_pm_icr_t; + +typedef union +{ +  unsigned long                 gcctrl; +  avr32_pm_gcctrl_t             GCCTRL; +} u_avr32_pm_gcctrl_t; + +typedef union +{ +  unsigned long                 rccr; +  avr32_pm_rccr_t               RCCR; +} u_avr32_pm_rccr_t; + +typedef union +{ +  unsigned long                 bgcr; +  avr32_pm_bgcr_t               BGCR; +} u_avr32_pm_bgcr_t; + +typedef union +{ +  unsigned long                 vregcr; +  avr32_pm_vregcr_t             VREGCR; +} u_avr32_pm_vregcr_t; + +typedef union +{ +  unsigned long                 bod; +  avr32_pm_bod_t                BOD; +} u_avr32_pm_bod_t; + +//! @} + + +/*! \brief Sets the mode of the oscillator 0. + * + * \param pm Base address of the Power Manager (i.e. &AVR32_PM). + * \param mode Oscillator 0 mode (i.e. AVR32_PM_OSCCTRL0_MODE_x). + */ +static void pm_set_osc0_mode(volatile avr32_pm_t *pm, unsigned int mode) +{ +  // Read +  u_avr32_pm_oscctrl0_t u_avr32_pm_oscctrl0 = {pm->oscctrl0}; +  // Modify +  u_avr32_pm_oscctrl0.OSCCTRL0.mode = mode; +  // Write +  pm->oscctrl0 = u_avr32_pm_oscctrl0.oscctrl0; +} + + +void pm_enable_osc0_ext_clock(volatile avr32_pm_t *pm) +{ +  pm_set_osc0_mode(pm, AVR32_PM_OSCCTRL0_MODE_EXT_CLOCK); +} + + +void pm_enable_osc0_crystal(volatile avr32_pm_t *pm, unsigned int fosc0) +{ +  pm_set_osc0_mode(pm, (fosc0 <  900000) ? AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G0 : +                       (fosc0 < 3000000) ? AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G1 : +                       (fosc0 < 8000000) ? AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G2 : +                                           AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G3); +} + + +void pm_enable_clk0(volatile avr32_pm_t *pm, unsigned int startup) +{ +  pm_enable_clk0_no_wait(pm, startup); +  pm_wait_for_clk0_ready(pm); +} + + +void pm_disable_clk0(volatile avr32_pm_t *pm) +{ +  pm->mcctrl &= ~AVR32_PM_MCCTRL_OSC0EN_MASK; +} + + +void pm_enable_clk0_no_wait(volatile avr32_pm_t *pm, unsigned int startup) +{ +  // Read register +  u_avr32_pm_oscctrl0_t u_avr32_pm_oscctrl0 = {pm->oscctrl0}; +  // Modify +  u_avr32_pm_oscctrl0.OSCCTRL0.startup = startup; +  // Write back +  pm->oscctrl0 = u_avr32_pm_oscctrl0.oscctrl0; + +  pm->mcctrl |= AVR32_PM_MCCTRL_OSC0EN_MASK; +} + + +void pm_wait_for_clk0_ready(volatile avr32_pm_t *pm) +{ +  while (!(pm->poscsr & AVR32_PM_POSCSR_OSC0RDY_MASK)); +} + + +/*! \brief Sets the mode of the oscillator 1. + * + * \param pm Base address of the Power Manager (i.e. &AVR32_PM). + * \param mode Oscillator 1 mode (i.e. AVR32_PM_OSCCTRL1_MODE_x). + */ +static void pm_set_osc1_mode(volatile avr32_pm_t *pm, unsigned int mode) +{ +  // Read +  u_avr32_pm_oscctrl1_t u_avr32_pm_oscctrl1 = {pm->oscctrl1}; +  // Modify +  u_avr32_pm_oscctrl1.OSCCTRL1.mode = mode; +  // Write +  pm->oscctrl1 = u_avr32_pm_oscctrl1.oscctrl1; +} + + +void pm_enable_osc1_ext_clock(volatile avr32_pm_t *pm) +{ +  pm_set_osc1_mode(pm, AVR32_PM_OSCCTRL1_MODE_EXT_CLOCK); +} + + +void pm_enable_osc1_crystal(volatile avr32_pm_t *pm, unsigned int fosc1) +{ +  pm_set_osc1_mode(pm, (fosc1 <  900000) ? AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G0 : +                       (fosc1 < 3000000) ? AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G1 : +                       (fosc1 < 8000000) ? AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G2 : +                                           AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G3); +} + + +void pm_enable_clk1(volatile avr32_pm_t *pm, unsigned int startup) +{ +  pm_enable_clk1_no_wait(pm, startup); +  pm_wait_for_clk1_ready(pm); +} + + +void pm_disable_clk1(volatile avr32_pm_t *pm) +{ +  pm->mcctrl &= ~AVR32_PM_MCCTRL_OSC1EN_MASK; +} + + +void pm_enable_clk1_no_wait(volatile avr32_pm_t *pm, unsigned int startup) +{ +  // Read register +  u_avr32_pm_oscctrl1_t u_avr32_pm_oscctrl1 = {pm->oscctrl1}; +  // Modify +  u_avr32_pm_oscctrl1.OSCCTRL1.startup = startup; +  // Write back +  pm->oscctrl1 = u_avr32_pm_oscctrl1.oscctrl1; + +  pm->mcctrl |= AVR32_PM_MCCTRL_OSC1EN_MASK; +} + + +void pm_wait_for_clk1_ready(volatile avr32_pm_t *pm) +{ +  while (!(pm->poscsr & AVR32_PM_POSCSR_OSC1RDY_MASK)); +} + + +/*! \brief Sets the mode of the 32-kHz oscillator. + * + * \param pm Base address of the Power Manager (i.e. &AVR32_PM). + * \param mode 32-kHz oscillator mode (i.e. AVR32_PM_OSCCTRL32_MODE_x). + */ +static void pm_set_osc32_mode(volatile avr32_pm_t *pm, unsigned int mode) +{ +  // Read +  u_avr32_pm_oscctrl32_t u_avr32_pm_oscctrl32 = {pm->oscctrl32}; +  // Modify +  u_avr32_pm_oscctrl32.OSCCTRL32.mode = mode; +  // Write +  pm->oscctrl32 = u_avr32_pm_oscctrl32.oscctrl32; +} + + +void pm_enable_osc32_ext_clock(volatile avr32_pm_t *pm) +{ +  pm_set_osc32_mode(pm, AVR32_PM_OSCCTRL32_MODE_EXT_CLOCK); +} + + +void pm_enable_osc32_crystal(volatile avr32_pm_t *pm) +{ +  pm_set_osc32_mode(pm, AVR32_PM_OSCCTRL32_MODE_CRYSTAL); +} + + +void pm_enable_clk32(volatile avr32_pm_t *pm, unsigned int startup) +{ +  pm_enable_clk32_no_wait(pm, startup); +  pm_wait_for_clk32_ready(pm); +} + + +void pm_disable_clk32(volatile avr32_pm_t *pm) +{ +  pm->oscctrl32 &= ~AVR32_PM_OSCCTRL32_OSC32EN_MASK; +} + + +void pm_enable_clk32_no_wait(volatile avr32_pm_t *pm, unsigned int startup) +{ +  // Read register +  u_avr32_pm_oscctrl32_t u_avr32_pm_oscctrl32 = {pm->oscctrl32}; +  // Modify +  u_avr32_pm_oscctrl32.OSCCTRL32.osc32en = 1; +  u_avr32_pm_oscctrl32.OSCCTRL32.startup = startup; +  // Write back +  pm->oscctrl32 = u_avr32_pm_oscctrl32.oscctrl32; +} + + +void pm_wait_for_clk32_ready(volatile avr32_pm_t *pm) +{ +  while (!(pm->poscsr & AVR32_PM_POSCSR_OSC32RDY_MASK)); +} + + +void pm_cksel(volatile avr32_pm_t *pm, +              unsigned int pbadiv, +              unsigned int pbasel, +              unsigned int pbbdiv, +              unsigned int pbbsel, +              unsigned int hsbdiv, +              unsigned int hsbsel) +{ +  u_avr32_pm_cksel_t u_avr32_pm_cksel = {0}; + +  u_avr32_pm_cksel.CKSEL.cpusel = hsbsel; +  u_avr32_pm_cksel.CKSEL.cpudiv = hsbdiv; +  u_avr32_pm_cksel.CKSEL.hsbsel = hsbsel; +  u_avr32_pm_cksel.CKSEL.hsbdiv = hsbdiv; +  u_avr32_pm_cksel.CKSEL.pbasel = pbasel; +  u_avr32_pm_cksel.CKSEL.pbadiv = pbadiv; +  u_avr32_pm_cksel.CKSEL.pbbsel = pbbsel; +  u_avr32_pm_cksel.CKSEL.pbbdiv = pbbdiv; + +  pm->cksel = u_avr32_pm_cksel.cksel; + +  // Wait for ckrdy bit and then clear it +  while (!(pm->poscsr & AVR32_PM_POSCSR_CKRDY_MASK)); +} + + +void pm_gc_setup(volatile avr32_pm_t *pm, +                  unsigned int gc, +                  unsigned int osc_or_pll, // Use Osc (=0) or PLL (=1) +                  unsigned int pll_osc, // Sel Osc0/PLL0 or Osc1/PLL1 +                  unsigned int diven, +                  unsigned int div) +{ +  u_avr32_pm_gcctrl_t u_avr32_pm_gcctrl = {0}; + +  u_avr32_pm_gcctrl.GCCTRL.oscsel = pll_osc; +  u_avr32_pm_gcctrl.GCCTRL.pllsel = osc_or_pll; +  u_avr32_pm_gcctrl.GCCTRL.diven  = diven; +  u_avr32_pm_gcctrl.GCCTRL.div    = div; + +  pm->gcctrl[gc] = u_avr32_pm_gcctrl.gcctrl; +} + + +void pm_gc_enable(volatile avr32_pm_t *pm, +                  unsigned int gc) +{ +  pm->gcctrl[gc] |= AVR32_PM_GCCTRL_CEN_MASK; +} + + +void pm_gc_disable(volatile avr32_pm_t *pm, +                   unsigned int gc) +{ +  pm->gcctrl[gc] &= ~AVR32_PM_GCCTRL_CEN_MASK; +} + + +void pm_pll_setup(volatile avr32_pm_t *pm, +                  unsigned int pll, +                  unsigned int mul, +                  unsigned int div, +                  unsigned int osc, +                  unsigned int lockcount) +{ +  u_avr32_pm_pll_t u_avr32_pm_pll = {0}; + +  u_avr32_pm_pll.PLL.pllosc   = osc; +  u_avr32_pm_pll.PLL.plldiv   = div; +  u_avr32_pm_pll.PLL.pllmul   = mul; +  u_avr32_pm_pll.PLL.pllcount = lockcount; + +  pm->pll[pll] = u_avr32_pm_pll.pll; +} + + +void pm_pll_set_option(volatile avr32_pm_t *pm, +                       unsigned int pll, +                       unsigned int pll_freq, +                       unsigned int pll_div2, +                       unsigned int pll_wbwdisable) +{ +  u_avr32_pm_pll_t u_avr32_pm_pll = {pm->pll[pll]}; +  u_avr32_pm_pll.PLL.pllopt = pll_freq | (pll_div2 << 1) | (pll_wbwdisable << 2); +  pm->pll[pll] = u_avr32_pm_pll.pll; +} + + +unsigned int pm_pll_get_option(volatile avr32_pm_t *pm, +                               unsigned int pll) +{ +  return (pm->pll[pll] & AVR32_PM_PLLOPT_MASK) >> AVR32_PM_PLLOPT_OFFSET; +} + + +void pm_pll_enable(volatile avr32_pm_t *pm, +                  unsigned int pll) +{ +  pm->pll[pll] |= AVR32_PM_PLLEN_MASK; +} + + +void pm_pll_disable(volatile avr32_pm_t *pm, +                  unsigned int pll) +{ +  pm->pll[pll] &= ~AVR32_PM_PLLEN_MASK; +} + + +void pm_wait_for_pll0_locked(volatile avr32_pm_t *pm) +{ +  while (!(pm->poscsr & AVR32_PM_POSCSR_LOCK0_MASK)); +} + + +void pm_wait_for_pll1_locked(volatile avr32_pm_t *pm) +{ +  while (!(pm->poscsr & AVR32_PM_POSCSR_LOCK1_MASK)); +} + + +void pm_switch_to_clock(volatile avr32_pm_t *pm, unsigned long clock) +{ +  // Read +  u_avr32_pm_mcctrl_t u_avr32_pm_mcctrl = {pm->mcctrl}; +  // Modify +  u_avr32_pm_mcctrl.MCCTRL.mcsel = clock; +  // Write back +  pm->mcctrl = u_avr32_pm_mcctrl.mcctrl; +} + + +void pm_switch_to_osc0(volatile avr32_pm_t *pm, unsigned int fosc0, unsigned int startup) +{ +  pm_enable_osc0_crystal(pm, fosc0);            // Enable the Osc0 in crystal mode +  pm_enable_clk0(pm, startup);                  // Crystal startup time - This parameter is critical and depends on the characteristics of the crystal +  pm_switch_to_clock(pm, AVR32_PM_MCSEL_OSC0);  // Then switch main clock to Osc0 +} + + +void pm_bod_enable_irq(volatile avr32_pm_t *pm) +{ +  pm->ier = AVR32_PM_IER_BODDET_MASK; +} + + +void pm_bod_disable_irq(volatile avr32_pm_t *pm) +{ +  Bool global_interrupt_enabled = Is_global_interrupt_enabled(); + +  if (global_interrupt_enabled) Disable_global_interrupt(); +  pm->idr = AVR32_PM_IDR_BODDET_MASK; +  pm->isr; +  if (global_interrupt_enabled) Enable_global_interrupt(); +} + + +void pm_bod_clear_irq(volatile avr32_pm_t *pm) +{ +  pm->icr = AVR32_PM_ICR_BODDET_MASK; +} + + +unsigned long pm_bod_get_irq_status(volatile avr32_pm_t *pm) +{ +  return ((pm->isr & AVR32_PM_ISR_BODDET_MASK) != 0); +} + + +unsigned long pm_bod_get_irq_enable_bit(volatile avr32_pm_t *pm) +{ +  return ((pm->imr & AVR32_PM_IMR_BODDET_MASK) != 0); +} + + +unsigned long pm_bod_get_level(volatile avr32_pm_t *pm) +{ +  return (pm->bod & AVR32_PM_BOD_LEVEL_MASK) >> AVR32_PM_BOD_LEVEL_OFFSET; +} + + +unsigned long pm_read_gplp(volatile avr32_pm_t *pm, unsigned long gplp) +{ +  return pm->gplp[gplp]; +} + + +void pm_write_gplp(volatile avr32_pm_t *pm, unsigned long gplp, unsigned long value) +{ +  pm->gplp[gplp] = value; +} + + +long pm_enable_module(volatile avr32_pm_t *pm, unsigned long module) +{ +  unsigned long domain = module>>5; +  unsigned long *regptr = (unsigned long*)(&(pm->cpumask) + domain); + +  // Implementation-specific shortcut: the ckMASK registers are contiguous and +  // memory-mapped in that order: CPUMASK, HSBMASK, PBAMASK, PBBMASK. + +  *regptr |= (1<<(module%32)); + +  return PASS; +} + +long pm_disable_module(volatile avr32_pm_t *pm, unsigned long module) +{ +  unsigned long domain = module>>5; +  unsigned long *regptr = (unsigned long*)(&(pm->cpumask) + domain); + +  // Implementation-specific shortcut: the ckMASK registers are contiguous and +  // memory-mapped in that order: CPUMASK, HSBMASK, PBAMASK, PBBMASK. + +  *regptr &= ~(1<<(module%32)); + +  return PASS; +} diff --git a/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/PM/pm.h b/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/PM/pm.h new file mode 100644 index 0000000..ca679f7 --- /dev/null +++ b/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/PM/pm.h @@ -0,0 +1,493 @@ +/* This header file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */ + +/*This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief Power Manager driver. + * + * + * - Compiler:           IAR EWAVR32 and GNU GCC for AVR32 + * - Supported devices:  All AVR32 devices. + * - AppNote: + * + * \author               Atmel Corporation: http://www.atmel.com \n + *                       Support and FAQ: http://support.atmel.no/ + * + *****************************************************************************/ + +/* Copyright (c) 2009 Atmel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an Atmel + * AVR product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE + * + */ + +#ifndef _PM_H_ +#define _PM_H_ + +#include <avr32/io.h> +#include "compiler.h" +#include "preprocessor.h" + + +/*! \brief Sets the MCU in the specified sleep mode. + * + * \param mode Sleep mode: + *   \arg \c AVR32_PM_SMODE_IDLE: Idle; + *   \arg \c AVR32_PM_SMODE_FROZEN: Frozen; + *   \arg \c AVR32_PM_SMODE_STANDBY: Standby; + *   \arg \c AVR32_PM_SMODE_STOP: Stop; + *   \arg \c AVR32_PM_SMODE_DEEP_STOP: DeepStop; + *   \arg \c AVR32_PM_SMODE_STATIC: Static. + */ +#define SLEEP(mode)   {__asm__ __volatile__ ("sleep "STRINGZ(mode));} + + +//! Input and output parameters when initializing PM clocks using pm_configure_clocks(). +typedef struct +{ +  //! CPU frequency (input/output argument). +  unsigned long cpu_f; + +  //! PBA frequency (input/output argument). +  unsigned long pba_f; + +  //! Oscillator 0's external crystal(or external clock) frequency (board dependant) (input argument). +  unsigned long osc0_f; + +  //! Oscillator 0's external crystal(or external clock) startup time: AVR32_PM_OSCCTRL0_STARTUP_x_RCOSC (input argument). +  unsigned long osc0_startup; +} pm_freq_param_t; + +#define PM_FREQ_STATUS_FAIL   (-1) +#define PM_FREQ_STATUS_OK     (0) + + +/*! \brief Gets the MCU reset cause. + * + * \param pm Base address of the Power Manager instance (i.e. &AVR32_PM). + * + * \return The MCU reset cause which can be masked with the + *         \c AVR32_PM_RCAUSE_x_MASK bit-masks to isolate specific causes. + */ +#if (defined __GNUC__) +__attribute__((__always_inline__)) +#endif +extern __inline__ unsigned int pm_get_reset_cause(volatile avr32_pm_t *pm) +{ +  return pm->rcause; +} + + +/*! + * \brief This function will enable the external clock mode of the oscillator 0. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + */ +extern void pm_enable_osc0_ext_clock(volatile avr32_pm_t *pm); + + +/*! + * \brief This function will enable the crystal mode of the oscillator 0. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param fosc0 Oscillator 0 crystal frequency (Hz) + */ +extern void pm_enable_osc0_crystal(volatile avr32_pm_t *pm, unsigned int fosc0); + + +/*! + * \brief This function will enable the oscillator 0 to be used with a startup time. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param startup Clock 0 startup time. AVR32_PM_OSCCTRL0_STARTUP_x_RCOSC. + */ +extern void pm_enable_clk0(volatile avr32_pm_t *pm, unsigned int startup); + + +/*! + * \brief This function will disable the oscillator 0. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + */ +extern void pm_disable_clk0(volatile avr32_pm_t *pm); + + +/*! + * \brief This function will enable the oscillator 0 to be used with no startup time. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param startup Clock 0 startup time, for which the function does not wait. AVR32_PM_OSCCTRL0_STARTUP_x_RCOSC. + */ +extern void pm_enable_clk0_no_wait(volatile avr32_pm_t *pm, unsigned int startup); + + +/*! + * \brief This function will wait until the Osc0 clock is ready. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + */ +extern void pm_wait_for_clk0_ready(volatile avr32_pm_t *pm); + + +/*! + * \brief This function will enable the external clock mode of the oscillator 1. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + */ +extern void pm_enable_osc1_ext_clock(volatile avr32_pm_t *pm); + + +/*! + * \brief This function will enable the crystal mode of the oscillator 1. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param fosc1 Oscillator 1 crystal frequency (Hz) + */ +extern void pm_enable_osc1_crystal(volatile avr32_pm_t *pm, unsigned int fosc1); + + +/*! + * \brief This function will enable the oscillator 1 to be used with a startup time. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param startup Clock 1 startup time. AVR32_PM_OSCCTRL1_STARTUP_x_RCOSC. + */ +extern void pm_enable_clk1(volatile avr32_pm_t *pm, unsigned int startup); + + +/*! + * \brief This function will disable the oscillator 1. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + */ +extern void pm_disable_clk1(volatile avr32_pm_t *pm); + + +/*! + * \brief This function will enable the oscillator 1 to be used with no startup time. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param startup Clock 1 startup time, for which the function does not wait. AVR32_PM_OSCCTRL1_STARTUP_x_RCOSC. + */ +extern void pm_enable_clk1_no_wait(volatile avr32_pm_t *pm, unsigned int startup); + + +/*! + * \brief This function will wait until the Osc1 clock is ready. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + */ +extern void pm_wait_for_clk1_ready(volatile avr32_pm_t *pm); + + +/*! + * \brief This function will enable the external clock mode of the 32-kHz oscillator. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + */ +extern void pm_enable_osc32_ext_clock(volatile avr32_pm_t *pm); + + +/*! + * \brief This function will enable the crystal mode of the 32-kHz oscillator. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + */ +extern void pm_enable_osc32_crystal(volatile avr32_pm_t *pm); + + +/*! + * \brief This function will enable the oscillator 32 to be used with a startup time. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param startup Clock 32 kHz startup time. AVR32_PM_OSCCTRL32_STARTUP_x_RCOSC. + */ +extern void pm_enable_clk32(volatile avr32_pm_t *pm, unsigned int startup); + + +/*! + * \brief This function will disable the oscillator 32. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + */ +extern void pm_disable_clk32(volatile avr32_pm_t *pm); + + +/*! + * \brief This function will enable the oscillator 32 to be used with no startup time. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param startup Clock 32 kHz startup time, for which the function does not wait. AVR32_PM_OSCCTRL32_STARTUP_x_RCOSC. + */ +extern void pm_enable_clk32_no_wait(volatile avr32_pm_t *pm, unsigned int startup); + + +/*! + * \brief This function will wait until the osc32 clock is ready. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + */ +extern void pm_wait_for_clk32_ready(volatile avr32_pm_t *pm); + + +/*! + * \brief This function will select all the power manager clocks. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param pbadiv Peripheral Bus A clock divisor enable + * \param pbasel Peripheral Bus A select + * \param pbbdiv Peripheral Bus B clock divisor enable + * \param pbbsel Peripheral Bus B select + * \param hsbdiv High Speed Bus clock divisor enable (CPU clock = HSB clock) + * \param hsbsel High Speed Bus select (CPU clock = HSB clock ) + */ +extern void pm_cksel(volatile avr32_pm_t *pm, unsigned int pbadiv, unsigned int pbasel, unsigned int pbbdiv, unsigned int pbbsel, unsigned int hsbdiv, unsigned int hsbsel); + + +/*! + * \brief This function will setup a generic clock. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param gc generic clock number (0 for gc0...) + * \param osc_or_pll Use OSC (=0) or PLL (=1) + * \param pll_osc Select Osc0/PLL0 or Osc1/PLL1 + * \param diven Generic clock divisor enable + * \param div Generic clock divisor + */ +extern void pm_gc_setup(volatile avr32_pm_t *pm, unsigned int gc, unsigned int osc_or_pll, unsigned int pll_osc, unsigned int diven, unsigned int div); + + +/*! + * \brief This function will enable a generic clock. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param gc generic clock number (0 for gc0...) + */ +extern void pm_gc_enable(volatile avr32_pm_t *pm, unsigned int gc); + + +/*! + * \brief This function will disable a generic clock. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param gc generic clock number (0 for gc0...) + */ +extern void pm_gc_disable(volatile avr32_pm_t *pm, unsigned int gc); + + +/*! + * \brief This function will setup a PLL. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param pll PLL number(0 for PLL0, 1 for PLL1) + * \param mul PLL MUL in the PLL formula + * \param div PLL DIV in the PLL formula + * \param osc OSC number (0 for osc0, 1 for osc1) + * \param lockcount PLL lockount + */ +extern void pm_pll_setup(volatile avr32_pm_t *pm, unsigned int pll, unsigned int mul, unsigned int div, unsigned int osc, unsigned int lockcount); + + +/*! + * \brief This function will set a PLL option. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param pll PLL number(0 for PLL0, 1 for PLL1) + * \param pll_freq Set to 1 for VCO frequency range 80-180MHz, set to 0 for VCO frequency range 160-240Mhz. + * \param pll_div2 Divide the PLL output frequency by 2 (this settings does not change the FVCO value) + * \param pll_wbwdisable 1 Disable the Wide-Bandith Mode (Wide-Bandwith mode allow a faster startup time and out-of-lock time). 0 to enable the Wide-Bandith Mode. + */ +extern void pm_pll_set_option(volatile avr32_pm_t *pm, unsigned int pll, unsigned int  pll_freq, unsigned int  pll_div2, unsigned int  pll_wbwdisable); + + +/*! + * \brief This function will get a PLL option. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param pll PLL number(0 for PLL0, 1 for PLL1) + * \return       Option + */ +extern unsigned int pm_pll_get_option(volatile avr32_pm_t *pm, unsigned int pll); + + +/*! + * \brief This function will enable a PLL. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param pll PLL number(0 for PLL0, 1 for PLL1) + */ +extern void pm_pll_enable(volatile avr32_pm_t *pm, unsigned int pll); + + +/*! + * \brief This function will disable a PLL. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param pll PLL number(0 for PLL0, 1 for PLL1) + */ +extern void pm_pll_disable(volatile avr32_pm_t *pm, unsigned int pll); + + +/*! + * \brief This function will wait for PLL0 locked + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + */ +extern void pm_wait_for_pll0_locked(volatile avr32_pm_t *pm); + + +/*! + * \brief This function will wait for PLL1 locked + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + */ +extern void pm_wait_for_pll1_locked(volatile avr32_pm_t *pm); + + +/*! + * \brief This function will switch the power manager main clock. + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param clock Clock to be switched on. AVR32_PM_MCSEL_SLOW for RCOsc, AVR32_PM_MCSEL_OSC0 for Osc0, AVR32_PM_MCSEL_PLL0 for PLL0. + */ +extern void pm_switch_to_clock(volatile avr32_pm_t *pm, unsigned long clock); + + +/*! + * \brief Switch main clock to clock Osc0 (crystal mode) + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param fosc0 Oscillator 0 crystal frequency (Hz) + * \param startup Crystal 0 startup time. AVR32_PM_OSCCTRL0_STARTUP_x_RCOSC. + */ +extern void pm_switch_to_osc0(volatile avr32_pm_t *pm, unsigned int fosc0, unsigned int startup); + + +/*! \brief Enables the Brown-Out Detector interrupt. + * + * \param pm Base address of the Power Manager (i.e. &AVR32_PM). + */ +extern void pm_bod_enable_irq(volatile avr32_pm_t *pm); + + +/*! \brief Disables the Brown-Out Detector interrupt. + * + * \param pm Base address of the Power Manager (i.e. &AVR32_PM). + */ +extern void pm_bod_disable_irq(volatile avr32_pm_t *pm); + + +/*! \brief Clears the Brown-Out Detector interrupt flag. + * + * \param pm Base address of the Power Manager (i.e. &AVR32_PM). + */ +extern void pm_bod_clear_irq(volatile avr32_pm_t *pm); + + +/*! \brief Gets the Brown-Out Detector interrupt flag. + * + * \param pm Base address of the Power Manager (i.e. &AVR32_PM). + * + * \retval 0 No BOD interrupt. + * \retval 1 BOD interrupt pending. + */ +extern unsigned long pm_bod_get_irq_status(volatile avr32_pm_t *pm); + + +/*! \brief Gets the Brown-Out Detector interrupt enable status. + * + * \param pm Base address of the Power Manager (i.e. &AVR32_PM). + * + * \retval 0 BOD interrupt disabled. + * \retval 1 BOD interrupt enabled. + */ +extern unsigned long pm_bod_get_irq_enable_bit(volatile avr32_pm_t *pm); + + +/*! \brief Gets the triggering threshold of the Brown-Out Detector. + * + * \param pm Base address of the Power Manager (i.e. &AVR32_PM). + * + * \return Triggering threshold of the BOD. See the electrical characteristics + *         in the part datasheet for actual voltage levels. + */ +extern unsigned long pm_bod_get_level(volatile avr32_pm_t *pm); + + +/*! + * \brief Read the content of the PM GPLP registers + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param gplp GPLP register index (0,1,... depending on the number of GPLP registers for a given part) + * + * \return The content of the chosen GPLP register. + */ +extern unsigned long pm_read_gplp(volatile avr32_pm_t *pm, unsigned long gplp); + + +/*! + * \brief Write into the PM GPLP registers + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param gplp GPLP register index (0,1,... depending on the number of GPLP registers for a given part) + * \param value Value to write + */ +extern void pm_write_gplp(volatile avr32_pm_t *pm, unsigned long gplp, unsigned long value); + + +/*! \brief Enable the clock of a module. + * + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param module The module to clock (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") + * + * \return Status. + *   \retval 0  Success. + *   \retval <0 An error occured. + */ +extern long pm_enable_module(volatile avr32_pm_t *pm, unsigned long module); + +/*! \brief Disable the clock of a module. + * + * \param pm Base address of the Power Manager (i.e. &AVR32_PM) + * \param 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") + * + * \return Status. + *   \retval 0  Success. + *   \retval <0 An error occured. + */ +extern long pm_disable_module(volatile avr32_pm_t *pm, unsigned long module); + + + +/*! \brief Automatically configure the CPU, PBA, PBB, and HSB clocks + *         according to the user wishes. + * + * This function needs some parameters stored in a pm_freq_param_t structure: + *  - cpu_f and pba_f are the wanted frequencies, + *  - osc0_f is the oscillator 0 on-board frequency (e.g. FOSC0), + *  - osc0_startup is the oscillator 0 startup time (e.g. OSC0_STARTUP). + * + * The function will then configure the clocks using the following rules: + *  - It first try to find a valid PLL frequency (the highest possible value to avoid jitter) in order + *    to satisfy the CPU frequency, + *  - It optimizes the configuration depending the various divide stages, + *  - Then, the PBA frequency is configured from the CPU freq. + *  - Note that HSB and PBB are configured with the same frequency as CPU. + *  - Note also that the number of wait states of the flash read accesses is automatically set-up depending + *    the CPU frequency. As a consequence, the application needs the FLASHC driver to compile. + * + * The CPU, HSB and PBA frequencies programmed after configuration are stored back into cpu_f and pba_f. + * + * \param param    pointer on the configuration structure. + * + * \retval PM_FREQ_STATUS_OK    Mode successfully initialized. + * \retval PM_FREQ_STATUS_FAIL  The configuration can not be done. + */ +extern int pm_configure_clocks(pm_freq_param_t *param); + + +/*! \brief Automatically configure the USB clock. + * + * USB clock is configured to 48MHz, using the PLL1 from the Oscillator0, assuming + * a 12 MHz crystal is connected to it. + */ +extern void pm_configure_usb_clock(void); + + +#endif  // _PM_H_ diff --git a/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/PM/pm_conf_clocks.c b/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/PM/pm_conf_clocks.c new file mode 100644 index 0000000..8beb83b --- /dev/null +++ b/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/PM/pm_conf_clocks.c @@ -0,0 +1,268 @@ +/* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */ + +/*This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief Power Manager clocks configuration helper. + * + * + * - Compiler:           IAR EWAVR32 and GNU GCC for AVR32 + * - Supported devices:  All AVR32 devices. + * - AppNote: + * + * \author               Atmel Corporation: http://www.atmel.com \n + *                       Support and FAQ: http://support.atmel.no/ + * + *****************************************************************************/ + +/* Copyright (c) 2009 Atmel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an Atmel + * AVR product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE + * + */ + +#include <string.h> +#include "compiler.h" +#include "pm.h" + +extern void flashc_set_wait_state(unsigned int wait_state); +#if (defined AVR32_FLASHC_210_H_INCLUDED) +extern void flashc_issue_command(unsigned int command, int page_number); +#endif + + +#define PM_MAX_MUL                ((1 << AVR32_PM_PLL0_PLLMUL_SIZE) - 1) + + +int pm_configure_clocks(pm_freq_param_t *param) +{ +  // Supported frequencies: +  // Fosc0 mul div PLL div2_en cpu_f pba_f   Comment +  //  12   15   1  192     1     12    12 +  //  12    9   3   40     1     20    20    PLL out of spec +  //  12   15   1  192     1     24    12 +  //  12    9   1  120     1     30    15 +  //  12    9   3   40     0     40    20    PLL out of spec +  //  12   15   1  192     1     48    12 +  //  12   15   1  192     1     48    24 +  //  12    8   1  108     1     54    27 +  //  12    9   1  120     1     60    15 +  //  12    9   1  120     1     60    30 +  //  12   10   1  132     1     66    16.5 +  // +  unsigned long in_cpu_f  = param->cpu_f; +  unsigned long in_osc0_f = param->osc0_f; +  unsigned long mul, div, div2_en = 0, div2_cpu = 0, div2_pba = 0; +  unsigned long pll_freq, rest; +  Bool b_div2_pba, b_div2_cpu; + +  // Switch to external Oscillator 0 +  pm_switch_to_osc0(&AVR32_PM, in_osc0_f, param->osc0_startup); + +  // Start with CPU freq config +  if (in_cpu_f == in_osc0_f) +  { +    param->cpu_f = in_osc0_f; +    param->pba_f = in_osc0_f; +    return PM_FREQ_STATUS_OK; +  } +  else if (in_cpu_f < in_osc0_f) +  { +    // TBD +  } + +  rest = in_cpu_f % in_osc0_f; + +  for (div = 1; div < 32; div++) +  { +    if ((div * rest) % in_osc0_f == 0) +      break; +  } +  if (div == 32) +    return PM_FREQ_STATUS_FAIL; + +  mul = (in_cpu_f * div) / in_osc0_f; + +  if (mul > PM_MAX_MUL) +    return PM_FREQ_STATUS_FAIL; + +  // export 2power from PLL div to div2_cpu +  while (!(div % 2)) +  { +    div /= 2; +    div2_cpu++; +  } + +  // Here we know the mul and div parameter of the PLL config. +  // . Check out if the PLL has a valid in_cpu_f. +  // . Try to have for the PLL frequency (VCO output) the highest possible value +  //   to reduce jitter. +  while (in_osc0_f * 2 * mul / div < AVR32_PM_PLL_VCO_RANGE0_MAX_FREQ) +  { +    if (2 * mul > PM_MAX_MUL) +      break; +    mul *= 2; +    div2_cpu++; +  } + +  if (div2_cpu != 0) +  { +    div2_cpu--; +    div2_en = 1; +  } + +  pll_freq = in_osc0_f * mul / (div * (1 << div2_en)); + +  // Update real CPU Frequency +  param->cpu_f = pll_freq / (1 << div2_cpu); +  mul--; + +  pm_pll_setup(&AVR32_PM +  , 0   // pll +  , mul // mul +  , div // div +  , 0   // osc +  , 16  // lockcount +  ); + +  pm_pll_set_option(&AVR32_PM +  , 0 // pll +  // PLL clock is lower than 160MHz: need to set pllopt. +  , (pll_freq < AVR32_PM_PLL_VCO_RANGE0_MIN_FREQ) ? 1 : 0 // pll_freq +  , div2_en // pll_div2 +  , 0 // pll_wbwdisable +  ); + +  rest = pll_freq; +  while (rest > AVR32_PM_PBA_MAX_FREQ || +         rest != param->pba_f) +  { +    div2_pba++; +    rest = pll_freq / (1 << div2_pba); +    if (rest < param->pba_f) +      break; +  } + +  // Update real PBA Frequency +  param->pba_f = pll_freq / (1 << div2_pba); + +  // Enable PLL0 +  pm_pll_enable(&AVR32_PM, 0); + +  // Wait for PLL0 locked +  pm_wait_for_pll0_locked(&AVR32_PM); + +  if (div2_cpu) +  { +    b_div2_cpu = TRUE; +    div2_cpu--; +  } +  else +    b_div2_cpu = FALSE; + +  if (div2_pba) +  { +    b_div2_pba = TRUE; +    div2_pba--; +  } +  else +    b_div2_pba = FALSE; + +  pm_cksel(&AVR32_PM +  , b_div2_pba, div2_pba // PBA +  , b_div2_cpu, div2_cpu // PBB +  , b_div2_cpu, div2_cpu // HSB +  ); + +  if (param->cpu_f > AVR32_FLASHC_FWS_0_MAX_FREQ) +  { +    flashc_set_wait_state(1); +#if (defined AVR32_FLASHC_210_H_INCLUDED) +    if (param->cpu_f > AVR32_FLASHC_HSEN_FWS_1_MAX_FREQ) +      flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSEN, -1); +    else +      flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSDIS, -1); +#endif +  } +  else +  { +    flashc_set_wait_state(0); +#if (defined AVR32_FLASHC_210_H_INCLUDED) +    if (param->cpu_f > AVR32_FLASHC_HSEN_FWS_0_MAX_FREQ) +      flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSEN, -1); +    else +      flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSDIS, -1); +#endif +  } + +  pm_switch_to_clock(&AVR32_PM, AVR32_PM_MCCTRL_MCSEL_PLL0); + +  return PM_FREQ_STATUS_OK; +} + + +void pm_configure_usb_clock(void) +{ +#if UC3A3 + +  // Setup USB GCLK. +  pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_USBB, // gc +                  0,                  // osc_or_pll: use Osc (if 0) or PLL (if 1) +                  0,                  // pll_osc: select Osc0/PLL0 or Osc1/PLL1 +                  0,                  // diven +                  0);                 // div + +  // Enable USB GCLK. +  pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_USBB); +#else +  // Use 12MHz from OSC0 and generate 96 MHz +  pm_pll_setup(&AVR32_PM, 1,  // pll. +	  7,   // mul. +	  1,   // div. +	  0,   // osc. +	  16); // lockcount. + +  pm_pll_set_option(&AVR32_PM, 1, // pll. +	  1,  // pll_freq: choose the range 80-180MHz. +	  1,  // pll_div2. +	  0); // pll_wbwdisable. + +  // start PLL1 and wait forl lock +  pm_pll_enable(&AVR32_PM, 1); + +  // Wait for PLL1 locked. +  pm_wait_for_pll1_locked(&AVR32_PM); + +  pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_USBB,  // gc. +            1,  // osc_or_pll: use Osc (if 0) or PLL (if 1). +            1,  // pll_osc: select Osc0/PLL0 or Osc1/PLL1. +            0,  // diven. +            0); // div. +  pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_USBB); +#endif +} diff --git a/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/PM/power_clocks_lib.c b/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/PM/power_clocks_lib.c new file mode 100644 index 0000000..f5fc155 --- /dev/null +++ b/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/PM/power_clocks_lib.c @@ -0,0 +1,566 @@ +/* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */ + +/*This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief High-level library abstracting features such as oscillators/pll/dfll + *        configuration, clock configuration, System-sensible parameters + *        configuration, buses clocks configuration, sleep mode, reset. + * + * + * - Compiler:           IAR EWAVR32 and GNU GCC for AVR32 + * - Supported devices:  All AVR32 devices. + * - AppNote: + * + * \author               Atmel Corporation: http://www.atmel.com \n + *                       Support and FAQ: http://support.atmel.no/ + * + *****************************************************************************/ + +/* Copyright (c) 2009 Atmel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an Atmel + * AVR product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE + * + */ +#include "power_clocks_lib.h" + + +//! Device-specific data +#if UC3L +static long int pcl_configure_clocks_uc3l(pcl_freq_param_t *param); // FORWARD declaration +#endif + +#if UC3C +static long int pcl_configure_clocks_uc3c(pcl_freq_param_t *param); // FORWARD declaration +#endif + +long int pcl_configure_clocks(pcl_freq_param_t *param) +{ +#ifndef AVR32_PM_VERSION_RESETVALUE +  // Implementation for UC3A, UC3A3, UC3B parts. +  return(pm_configure_clocks(param)); +#else +  #ifdef AVR32_PM_410_H_INCLUDED +    // Implementation for UC3C parts. +    return(pcl_configure_clocks_uc3c(param)); +  #else +    // Implementation for UC3L parts. +    return(pcl_configure_clocks_uc3l(param)); +  #endif +#endif +} + + +//! Device-specific implementation +#if UC3L +// FORWARD declaration +static long int pcl_configure_synchronous_clocks( pm_clk_src_t main_clk_src, +                                                  unsigned long main_clock_freq_hz, +                                                  pcl_freq_param_t *param); + +long int pcl_configure_clocks_rcsys(pcl_freq_param_t *param) +{ +  // Supported main clock sources: PCL_MC_RCSYS + +  // Supported synchronous clocks frequencies if RCSYS is the main clock source: +  // 115200Hz, 57600Hz, 28800Hz, 14400Hz, 7200Hz, 3600Hz, 1800Hz, 900Hz, 450Hz. + +  // NOTE: by default, this implementation doesn't perform thorough checks on the +  // input parameters. To enable the checks, define AVR32SFW_INPUT_CHECK. + +#ifdef AVR32SFW_INPUT_CHECK +  // Verify that fCPU >= fPBx +  if((param->cpu_f < param->pba_f) || (param->cpu_f < param->pbb_f)) +    return(-1); +#endif + +#ifdef AVR32SFW_INPUT_CHECK +    // Verify that the target frequencies are reachable. +    if((param->cpu_f > SCIF_SLOWCLOCK_FREQ_HZ) || (param->pba_f > SCIF_SLOWCLOCK_FREQ_HZ) +      || (param->pbb_f > SCIF_SLOWCLOCK_FREQ_HZ)) +      return(-1); +#endif + +  return(pcl_configure_synchronous_clocks(PM_CLK_SRC_SLOW, SCIF_SLOWCLOCK_FREQ_HZ, param)); +} + + +long int pcl_configure_clocks_rc120m(pcl_freq_param_t *param) +{ +  // Supported main clock sources: PCL_MC_RC120M + +  // Supported synchronous clocks frequencies if RC120M is the main clock source: +  // 30MHz, 15MHz, 7.5MHz, 3.75MHz, 1.875MHz, 937.5kHz, 468.75kHz. + +  // NOTE: by default, this implementation doesn't perform thorough checks on the +  // input parameters. To enable the checks, define AVR32SFW_INPUT_CHECK. + +#ifdef AVR32SFW_INPUT_CHECK +  // Verify that fCPU >= fPBx +  if((param->cpu_f < param->pba_f) || (param->cpu_f < param->pbb_f)) +    return(-1); +#endif + +#ifdef AVR32SFW_INPUT_CHECK +  // Verify that the target frequencies are reachable. +  if((param->cpu_f > SCIF_RC120M_FREQ_HZ) || (param->pba_f > SCIF_RC120M_FREQ_HZ) +    || (param->pbb_f > SCIF_RC120M_FREQ_HZ)) +    return(-1); +#endif + +  // Start the 120MHz internal RCosc (RC120M) clock +  scif_start_rc120M(); + +  return(pcl_configure_synchronous_clocks(PM_CLK_SRC_RC120M, SCIF_RC120M_FREQ_HZ, param)); +} + + +long int pcl_configure_clocks_osc0(pcl_freq_param_t *param) +{ +  // Supported main clock sources: PCL_MC_OSC0 + +  // Supported synchronous clocks frequencies if OSC0 is the main clock source: +  // (these obviously depend on the OSC0 frequency; we'll take 16MHz as an example) +  // 16MHz, 8MHz, 4MHz, 2MHz, 1MHz, 500kHz, 250kHz, 125kHz, 62.5kHz. + +  // NOTE: by default, this implementation doesn't perform thorough checks on the +  // input parameters. To enable the checks, define AVR32SFW_INPUT_CHECK. + +  unsigned long               main_clock_freq; + + +#ifdef AVR32SFW_INPUT_CHECK +  // Verify that fCPU >= fPBx +  if((param->cpu_f < param->pba_f) || (param->cpu_f < param->pbb_f)) +    return(-1); +#endif + +  main_clock_freq = param->osc0_f; +#ifdef AVR32SFW_INPUT_CHECK +  // Verify that the target frequencies are reachable. +  if((param->cpu_f > main_clock_freq) || (param->pba_f > main_clock_freq) +    || (param->pbb_f > main_clock_freq)) +    return(-1); +#endif +  // Configure OSC0 in crystal mode, external crystal with a fcrystal Hz frequency. +  scif_configure_osc_crystalmode(SCIF_OSC0, main_clock_freq); +  // Enable the OSC0 +  scif_enable_osc(SCIF_OSC0, param->osc0_startup, true); + +  return(pcl_configure_synchronous_clocks(PM_CLK_SRC_OSC0, main_clock_freq, param)); +} + + +long int pcl_configure_clocks_dfll0(pcl_freq_param_t *param) +{ +  // Supported main clock sources: PCL_MC_DFLL + +  // Supported synchronous clocks frequencies if DFLL is the main clock source: +  // (these obviously depend on the DFLL target frequency; we'll take 100MHz as an example) +  // 50MHz, 25MHz, 12.5MHz, 6.25MHz, 3.125MHz, 1562.5kHz, 781.25kHz, 390.625kHz. + +  // NOTE: by default, this implementation doesn't perform thorough checks on the +  // input parameters. To enable the checks, define AVR32SFW_INPUT_CHECK. + +  unsigned long   main_clock_freq; +  scif_gclk_opt_t *pgc_dfllif_ref_opt; + + +#ifdef AVR32SFW_INPUT_CHECK +  // Verify that fCPU >= fPBx +  if((param->cpu_f < param->pba_f) || (param->cpu_f < param->pbb_f)) +    return(-1); +#endif + +  main_clock_freq = param->dfll_f; +#ifdef AVR32SFW_INPUT_CHECK +  // Verify that the target DFLL output frequency is in the correct range. +  if((main_clock_freq > SCIF_DFLL_MAXFREQ_HZ) || (main_clock_freq < SCIF_DFLL_MINFREQ_HZ)) +    return(-1); +  // Verify that the target frequencies are reachable. +  if((param->cpu_f > main_clock_freq) || (param->pba_f > main_clock_freq) +    || (param->pbb_f > main_clock_freq)) +    return(-1); +#endif +  pgc_dfllif_ref_opt = (scif_gclk_opt_t *)param->pextra_params; +  // Implementation note: this implementation configures the DFLL in closed-loop +  // mode (because it gives the best accuracy) which enables the generic clock CLK_DFLLIF_REF +  // as a reference (RCSYS being used as the generic clock source, undivided). +  scif_dfll0_closedloop_configure_and_start(pgc_dfllif_ref_opt, main_clock_freq, TRUE); + +  return(pcl_configure_synchronous_clocks(PM_CLK_SRC_DFLL0, main_clock_freq, param)); +} + + +static long int pcl_configure_clocks_uc3l(pcl_freq_param_t *param) +{ +  // Supported main clock sources: PCL_MC_RCSYS, PCL_MC_OSC0, PCL_MC_DFLL0, PCL_MC_RC120M + +  // Supported synchronous clocks frequencies if RCSYS is the main clock source: +  // 115200Hz, 57600Hz, 28800Hz, 14400Hz, 7200Hz, 3600Hz, 1800Hz, 900Hz, 450Hz. + +  // Supported synchronous clocks frequencies if RC120M is the main clock source: +  // 30MHz, 15MHz, 7.5MHz, 3.75MHz, 1.875MHz, 937.5kHz, 468.75kHz. + +  // Supported synchronous clocks frequencies if OSC0 is the main clock source: +  // (these obviously depend on the OSC0 frequency; we'll take 16MHz as an example) +  // 16MHz, 8MHz, 4MHz, 2MHz, 1MHz, 500kHz, 250kHz, 125kHz, 62.5kHz. + +  // Supported synchronous clocks frequencies if DFLL is the main clock source: +  // (these obviously depend on the DFLL target frequency; we'll take 100MHz as an example) +  // 50MHz, 25MHz, 12.5MHz, 6.25MHz, 3.125MHz, 1562.5kHz, 781.25kHz, 390.625kHz. + +  // NOTE: by default, this implementation doesn't perform thorough checks on the +  // input parameters. To enable the checks, define AVR32SFW_INPUT_CHECK. + + +#ifdef AVR32SFW_INPUT_CHECK +  // Verify that fCPU >= fPBx +  if((param->cpu_f < param->pba_f) || (param->cpu_f < param->pbb_f)) +    return(-1); +#endif + +  if(PCL_MC_RCSYS == param->main_clk_src) +  { +    return(pcl_configure_clocks_rcsys(param)); +  } +  else if(PCL_MC_RC120M == param->main_clk_src) +  { +    return(pcl_configure_clocks_rc120m(param)); +  } +  else if(PCL_MC_OSC0 == param->main_clk_src) +  { +    return(pcl_configure_clocks_osc0(param)); +  } +  else // PCL_MC_DFLL0 == param->main_clk_src +  { +    return(pcl_configure_clocks_dfll0(param)); +  } +} + +static long int pcl_configure_synchronous_clocks(pm_clk_src_t main_clk_src, unsigned long main_clock_freq_hz, pcl_freq_param_t *param) +{ +  //# +  //# Set the Synchronous clock division ratio for each clock domain +  //# +  pm_set_all_cksel(main_clock_freq_hz, param->cpu_f, param->pba_f, param->pbb_f); + +  //# +  //# Set the Flash wait state and the speed read mode (depending on the target CPU frequency). +  //# +#if UC3L +    flashcdw_set_flash_waitstate_and_readmode(param->cpu_f); +#elif UC3C +    flashc_set_flash_waitstate_and_readmode(param->cpu_f); +#endif + + +  //# +  //# Switch the main clock source to the selected clock. +  //# +  pm_set_mclk_source(main_clk_src); + +  return PASS; +} + +#endif // UC3L device-specific implementation + +//! UC3C Device-specific implementation +#if UC3C +static long int pcl_configure_clocks_uc3c(pcl_freq_param_t *param) +{ +  #define PM_MAX_MUL                         ((1 << AVR32_SCIF_PLLMUL_SIZE) - 1) +  #define AVR32_PM_PBA_MAX_FREQ              66000000 +  #define AVR32_PM_PLL_VCO_RANGE0_MAX_FREQ   240000000 +  #define AVR32_PM_PLL_VCO_RANGE0_MIN_FREQ   160000000 + +    // Implementation for  UC3C parts. +        // Supported frequencies: +        // Fosc0 mul div PLL div2_en cpu_f pba_f   Comment +        //  12   15   1  192     1     12    12 +        //  12    9   3   40     1     20    20    PLL out of spec +        //  12   15   1  192     1     24    12 +        //  12    9   1  120     1     30    15 +        //  12    9   3   40     0     40    20    PLL out of spec +        //  12   15   1  192     1     48    12 +        //  12   15   1  192     1     48    24 +        //  12    8   1  108     1     54    27 +        //  12    9   1  120     1     60    15 +        //  12    9   1  120     1     60    30 +        //  12   10   1  132     1     66    16.5 +        // +        unsigned long in_cpu_f  = param->cpu_f; +        unsigned long in_osc0_f = param->osc0_f; +        unsigned long mul, div, div2_en = 0, div2_cpu = 0, div2_pba = 0; +        unsigned long pll_freq, rest; +        Bool b_div2_pba, b_div2_cpu; + +        // Configure OSC0 in crystal mode, external crystal with a FOSC0 Hz frequency. +        scif_configure_osc_crystalmode(SCIF_OSC0, in_osc0_f); +        // Enable the OSC0 +        scif_enable_osc(SCIF_OSC0, param->osc0_startup, true); +        // Set the main clock source as being OSC0. +        pm_set_mclk_source(PM_CLK_SRC_OSC0); + +        // Start with CPU freq config +        if (in_cpu_f == in_osc0_f) +        { +          param->cpu_f = in_osc0_f; +          param->pba_f = in_osc0_f; +          return PASS; +        } +        else if (in_cpu_f < in_osc0_f) +        { +          // TBD +        } + +        rest = in_cpu_f % in_osc0_f; + +        for (div = 1; div < 32; div++) +        { +          if ((div * rest) % in_osc0_f == 0) +            break; +        } +        if (div == 32) +          return FAIL; + +        mul = (in_cpu_f * div) / in_osc0_f; + +        if (mul > PM_MAX_MUL) +          return FAIL; + +        // export 2power from PLL div to div2_cpu +        while (!(div % 2)) +        { +          div /= 2; +          div2_cpu++; +        } + +        // Here we know the mul and div parameter of the PLL config. +        // . Check out if the PLL has a valid in_cpu_f. +        // . Try to have for the PLL frequency (VCO output) the highest possible value +        //   to reduce jitter. +        while (in_osc0_f * 2 * mul / div < AVR32_PM_PLL_VCO_RANGE0_MAX_FREQ) +        { +          if (2 * mul > PM_MAX_MUL) +            break; +          mul *= 2; +          div2_cpu++; +        } + +        if (div2_cpu != 0) +        { +          div2_cpu--; +          div2_en = 1; +        } + +        pll_freq = in_osc0_f * mul / (div * (1 << div2_en)); + +        // Update real CPU Frequency +        param->cpu_f = pll_freq / (1 << div2_cpu); +        mul--; + +        scif_pll_opt_t opt; + +        opt.osc = SCIF_OSC0,     // Sel Osc0 or Osc1 +        opt.lockcount = 16,      // lockcount in main clock for the PLL wait lock +        opt.div = div,             // DIV=1 in the formula +        opt.mul = mul,             // MUL=7 in the formula +        opt.pll_div2 = div2_en,        // pll_div2 Divide the PLL output frequency by 2 (this settings does not change the FVCO value) +        opt.pll_wbwdisable = 0,  //pll_wbwdisable 1 Disable the Wide-Bandith Mode (Wide-Bandwith mode allow a faster startup time and out-of-lock time). 0 to enable the Wide-Bandith Mode. +        opt.pll_freq = (pll_freq < AVR32_PM_PLL_VCO_RANGE0_MIN_FREQ) ? 1 : 0,        // Set to 1 for VCO frequency range 80-180MHz, set to 0 for VCO frequency range 160-240Mhz. + + +        scif_pll_setup(SCIF_PLL0, opt); // lockcount in main clock for the PLL wait lock + +        /* Enable PLL0 */ +        scif_pll_enable(SCIF_PLL0); + +        /* Wait for PLL0 locked */ +        scif_wait_for_pll_locked(SCIF_PLL0) ; + +        rest = pll_freq; +        while (rest > AVR32_PM_PBA_MAX_FREQ || +               rest != param->pba_f) +        { +          div2_pba++; +          rest = pll_freq / (1 << div2_pba); +          if (rest < param->pba_f) +            break; +        } + +        // Update real PBA Frequency +        param->pba_f = pll_freq / (1 << div2_pba); + + +        if (div2_cpu) +        { +          b_div2_cpu = TRUE; +          div2_cpu--; +        } +        else +          b_div2_cpu = FALSE; + +        if (div2_pba) +        { +          b_div2_pba = TRUE; +          div2_pba--; +        } +        else +          b_div2_pba = FALSE; + +        if (b_div2_cpu == TRUE ) +        { +          pm_set_clk_domain_div(PM_CLK_DOMAIN_0, (pm_divratio_t) div2_cpu); // CPU +          pm_set_clk_domain_div(PM_CLK_DOMAIN_1, (pm_divratio_t) div2_cpu); // HSB +          pm_set_clk_domain_div(PM_CLK_DOMAIN_3, (pm_divratio_t) div2_cpu); // PBB +        } +        if (b_div2_pba == TRUE ) +        { +          pm_set_clk_domain_div(PM_CLK_DOMAIN_2, (pm_divratio_t) div2_pba); // PBA +          pm_set_clk_domain_div(PM_CLK_DOMAIN_4, (pm_divratio_t) div2_pba); // PBC +        } + +        // Set Flashc Wait State +        flashc_set_flash_waitstate_and_readmode(param->cpu_f); + +        // Set the main clock source as being PLL0. +        pm_set_mclk_source(PM_CLK_SRC_PLL0); + +        return PASS; +} +#endif // UC3C device-specific implementation + +long int pcl_switch_to_osc(pcl_osc_t osc, unsigned int fcrystal, unsigned int startup) +{ +#ifndef AVR32_PM_VERSION_RESETVALUE +// Implementation for UC3A, UC3A3, UC3B parts. +  if(PCL_OSC0 == osc) +  { +    // Configure OSC0 in crystal mode, external crystal with a FOSC0 Hz frequency, +    // enable the OSC0, set the main clock source as being OSC0. +    pm_switch_to_osc0(&AVR32_PM, fcrystal, startup); +  } +  else +  { +    return PCL_NOT_SUPPORTED; +  } +#else +// Implementation for UC3C, UC3L parts. +  #if AVR32_PM_VERSION_RESETVALUE < 0x400 +    return PCL_NOT_SUPPORTED; +  #else +  if(PCL_OSC0 == osc) +  { +    // Configure OSC0 in crystal mode, external crystal with a fcrystal Hz frequency. +    scif_configure_osc_crystalmode(SCIF_OSC0, fcrystal); +    // Enable the OSC0 +    scif_enable_osc(SCIF_OSC0, startup, true); +    // Set the Flash wait state and the speed read mode (depending on the target CPU frequency). +#if UC3L +    flashcdw_set_flash_waitstate_and_readmode(fcrystal); +#elif UC3C +    flashc_set_flash_waitstate_and_readmode(fcrystal); +#endif +    // Set the main clock source as being OSC0. +    pm_set_mclk_source(PM_CLK_SRC_OSC0); +  } +  else +  { +    return PCL_NOT_SUPPORTED; +  } +  #endif +#endif +  return PASS; +} + +long int pcl_configure_usb_clock(void) +{ +#ifndef AVR32_PM_VERSION_RESETVALUE +// Implementation for UC3A, UC3A3, UC3B parts. +  pm_configure_usb_clock(); +  return PASS; +#else +  #ifdef AVR32_PM_410_H_INCLUDED +    const scif_pll_opt_t opt = { +              .osc = SCIF_OSC0,     // Sel Osc0 or Osc1 +              .lockcount = 16,      // lockcount in main clock for the PLL wait lock +              .div = 1,             // DIV=1 in the formula +              .mul = 5,             // MUL=7 in the formula +              .pll_div2 = 1,        // pll_div2 Divide the PLL output frequency by 2 (this settings does not change the FVCO value) +              .pll_wbwdisable = 0,  //pll_wbwdisable 1 Disable the Wide-Bandith Mode (Wide-Bandwith mode allow a faster startup time and out-of-lock time). 0 to enable the Wide-Bandith Mode. +              .pll_freq = 1,        // Set to 1 for VCO frequency range 80-180MHz, set to 0 for VCO frequency range 160-240Mhz. +    }; + +    /* Setup PLL1 on Osc0, mul=7 ,no divisor, lockcount=16, ie. 16Mhzx6 = 96MHz output */ +    scif_pll_setup(SCIF_PLL1, opt); // lockcount in main clock for the PLL wait lock + +    /* Enable PLL1 */ +    scif_pll_enable(SCIF_PLL1); + +    /* Wait for PLL1 locked */ +    scif_wait_for_pll_locked(SCIF_PLL1) ; + +  // Implementation for UC3C parts. +    // Setup the generic clock for USB +    scif_gc_setup(AVR32_SCIF_GCLK_USB, +                  SCIF_GCCTRL_PLL1, +                  AVR32_SCIF_GC_NO_DIV_CLOCK, +                  0); +    // Now enable the generic clock +    scif_gc_enable(AVR32_SCIF_GCLK_USB); +    return PASS; +  #else +      return PCL_NOT_SUPPORTED; +  #endif +#endif +} + + +#if UC3L +#else +void pcl_write_gplp(unsigned long gplp, unsigned long value) +{ +#ifndef AVR32_PM_VERSION_RESETVALUE +// Implementation for UC3A, UC3A3, UC3B parts. +  pm_write_gplp(&AVR32_PM,gplp,value); +#else +  scif_write_gplp(gplp,value); +#endif +} + +unsigned long pcl_read_gplp(unsigned long gplp) +{ +#ifndef AVR32_PM_VERSION_RESETVALUE +// Implementation for UC3A, UC3A3, UC3B parts. +  return pm_read_gplp(&AVR32_PM,gplp); +#else +  return scif_read_gplp(gplp); +#endif +} +#endif diff --git a/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/PM/power_clocks_lib.h b/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/PM/power_clocks_lib.h new file mode 100644 index 0000000..28c5888 --- /dev/null +++ b/firmwares/wifishield/wifiHD/src/SOFTWARE_FRAMEWORK/DRIVERS/PM/power_clocks_lib.h @@ -0,0 +1,379 @@ +/* This header file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */ + +/*This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief High-level library abstracting features such as oscillators/pll/dfll + *        configuration, clock configuration, System-sensible parameters + *        configuration, buses clocks configuration, sleep mode, reset. + * + * + * - Compiler:           IAR EWAVR32 and GNU GCC for AVR32 + * - Supported devices:  All AVR32 devices. + * - AppNote: + * + * \author               Atmel Corporation: http://www.atmel.com \n + *                       Support and FAQ: http://support.atmel.no/ + * + *****************************************************************************/ + +/* Copyright (c) 2009 Atmel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an Atmel + * AVR product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE + * + */ + +#ifndef _POWER_CLOCKS_LIB_H_ +#define _POWER_CLOCKS_LIB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <avr32/io.h> +#include "compiler.h" + +#ifndef AVR32_PM_VERSION_RESETVALUE +// Support for UC3A, UC3A3, UC3B parts. +  #include "pm.h" +#else +//! Device-specific data +#if UC3L  +  #include "pm_uc3l.h" +  #include "scif_uc3l.h" +  #include "flashcdw.h" +#elif UC3C +  #include "pm_uc3c.h" +  #include "scif_uc3c.h" +  #include "flashc.h" +#endif +#endif + +/*! \name Clocks Management + */ +//! @{ + +//! The different oscillators +typedef enum +{ +  PCL_OSC0  = 0, +  PCL_OSC1  = 1 +} pcl_osc_t; + +//! The different DFLLs +typedef enum +{ +  PCL_DFLL0  = 0, +  PCL_DFLL1  = 1 +} pcl_dfll_t; + +//! Possible Main Clock Sources +typedef enum +{ +  PCL_MC_RCSYS,      // Default main clock source, supported by all (aka Slow Clock) +  PCL_MC_OSC0,       // Supported by all +  PCL_MC_OSC1,       // Supported by UC3C only +  PCL_MC_OSC0_PLL0,  // Supported by UC3A, UC3B, UC3A3, UC3C (the main clock source is PLL0 with OSC0 as reference) +  PCL_MC_OSC1_PLL0,  // Supported by UC3A, UC3B, UC3A3, UC3C (the main clock source is PLL0 with OSC1 as reference) +  PCL_MC_OSC0_PLL1,  // Supported by UC3C  (the main clock source is PLL1 with OSC0 as reference) +  PCL_MC_OSC1_PLL1,  // Supported by UC3C  (the main clock source is PLL1 with OSC1 as reference) +  PCL_MC_DFLL0,      // Supported by UC3L +  PCL_MC_DFLL1,      // Not supported yet +  PCL_MC_RC120M,     // Supported by UC3L, UC3C +  PCL_MC_RC8M,       // Supported by UC3C +  PCL_MC_CRIPOSC     // Supported by UC3C +} pcl_mainclk_t; + +//! Input and output parameters to configure clocks with pcl_configure_clocks(). +// NOTE: regarding the frequency settings, always abide by the datasheet rules and min & max supported frequencies. +#ifndef AVR32_PM_VERSION_RESETVALUE +// Support for UC3A, UC3A3, UC3B parts. +#define pcl_freq_param_t  pm_freq_param_t // See pm.h +#else +// Support for UC3C, UC3L parts. +typedef struct +{ +  //! Main clock source selection (input argument). +  pcl_mainclk_t main_clk_src; + +  //! Target CPU frequency (input/output argument). +  unsigned long cpu_f; + +  //! Target PBA frequency (input/output argument). +  unsigned long pba_f; + +  //! Target PBB frequency (input/output argument). +  unsigned long pbb_f; + +  //! Target PBC frequency (input/output argument). +  unsigned long pbc_f; + +  //! Oscillator 0's external crystal(or external clock) frequency (board dependant) (input argument). +  unsigned long osc0_f; + +  //! Oscillator 0's external crystal(or external clock) startup time: AVR32_PM_OSCCTRL0_STARTUP_x_RCOSC (input argument). +  unsigned long osc0_startup; + +  //! DFLL target frequency (input/output argument) (NOTE: the bigger, the most stable the frequency) +  unsigned long dfll_f; +   +  //! Other parameters that might be necessary depending on the device (implementation-dependent). +  // For the UC3L DFLL setup, this parameter should be pointing to a structure of +  // type (scif_gclk_opt_t *). +  void *pextra_params; +} pcl_freq_param_t; +#endif + +//! Define "not supported" for the lib. +#define PCL_NOT_SUPPORTED (-10000) + +/*! \brief Automatically configure the CPU, PBA, PBB, and HSB clocks + * + * This function needs some parameters stored in a pcl_freq_param_t structure: + *  - main_clk_src is the id of the main clock source to use, + *  - cpu_f and pba_f and pbb_f are the wanted frequencies, + *  - osc0_f is the oscillator 0's external crystal (or external clock) on-board frequency (e.g. FOSC0), + *  - osc0_startup is the oscillator 0's external crystal (or external clock) startup time (e.g. OSC0_STARTUP). + *  - dfll_f is the target DFLL frequency to set-up if main_clk_src is the dfll. + * + * The CPU, HSB and PBA frequencies programmed after configuration are stored back into cpu_f and pba_f. + * + * \note: since it is dynamically computing the appropriate field values of the + * configuration registers from the parameters structure, this function is not + * optimal in terms of code size. For a code size optimal solution, it is better + * to create a new function from pcl_configure_clocks() and modify it to use + * preprocessor computation from pre-defined target frequencies. + * + * \param param    pointer on the configuration structure. + * + * \retval 0   Success. + * \retval <0  The configuration cannot be performed. + */ +extern long int pcl_configure_clocks(pcl_freq_param_t *param); + +/*! \brief Automatically configure the CPU, PBA, PBB, and HSB clocks using the RCSYS osc as main source clock. + * + * This function needs some parameters stored in a pcl_freq_param_t structure: + *  - cpu_f and pba_f and pbb_f are the wanted frequencies + * + * Supported main clock sources: PCL_MC_RCSYS + * + * Supported synchronous clocks frequencies: + * 115200Hz, 57600Hz, 28800Hz, 14400Hz, 7200Hz, 3600Hz, 1800Hz, 900Hz, 450Hz. + * + * \note: by default, this implementation doesn't perform thorough checks on the + *        input parameters. To enable the checks, define AVR32SFW_INPUT_CHECK. + * + * \note: since it is dynamically computing the appropriate field values of the + * configuration registers from the parameters structure, this function is not + * optimal in terms of code size. For a code size optimal solution, it is better + * to create a new function from pcl_configure_clocks_rcsys() and modify it to use + * preprocessor computation from pre-defined target frequencies. + * + * \param param    pointer on the configuration structure. + * + * \retval 0   Success. + * \retval <0  The configuration cannot be performed. + */ +extern long int pcl_configure_clocks_rcsys(pcl_freq_param_t *param); + +/*! \brief Automatically configure the CPU, PBA, PBB, and HSB clocks using the RC120M osc as main source clock. + * + * This function needs some parameters stored in a pcl_freq_param_t structure: + *  - cpu_f and pba_f and pbb_f are the wanted frequencies + * + * Supported main clock sources: PCL_MC_RC120M + * + * Supported synchronous clocks frequencies: + * 30MHz, 15MHz, 7.5MHz, 3.75MHz, 1.875MHz, 937.5kHz, 468.75kHz. + * + * \note: by default, this implementation doesn't perform thorough checks on the + *        input parameters. To enable the checks, define AVR32SFW_INPUT_CHECK. + * + * \note: since it is dynamically computing the appropriate field values of the + * configuration registers from the parameters structure, this function is not + * optimal in terms of code size. For a code size optimal solution, it is better + * to create a new function from pcl_configure_clocks_rc120m() and modify it to + * use preprocessor computation from pre-defined target frequencies. + * + * \param param    pointer on the configuration structure. + * + * \retval 0   Success. + * \retval <0  The configuration cannot be performed. + */ +extern long int pcl_configure_clocks_rc120m(pcl_freq_param_t *param); + +/*! \brief Automatically configure the CPU, PBA, PBB, and HSB clocks using the OSC0 osc as main source clock + * + * This function needs some parameters stored in a pcl_freq_param_t structure: + *  - cpu_f and pba_f and pbb_f are the wanted frequencies, + *  - osc0_f is the oscillator 0's external crystal (or external clock) on-board frequency (e.g. FOSC0), + *  - osc0_startup is the oscillator 0's external crystal (or external clock) startup time (e.g. OSC0_STARTUP). + * + * Supported main clock sources: PCL_MC_OSC0 + * + * Supported synchronous clocks frequencies: + * (these obviously depend on the OSC0 frequency; we'll take 16MHz as an example) + * 16MHz, 8MHz, 4MHz, 2MHz, 1MHz, 500kHz, 250kHz, 125kHz, 62.5kHz. + * + * \note: by default, this implementation doesn't perform thorough checks on the + *        input parameters. To enable the checks, define AVR32SFW_INPUT_CHECK. + * + * \note: since it is dynamically computing the appropriate field values of the + * configuration registers from the parameters structure, this function is not + * optimal in terms of code size. For a code size optimal solution, it is better + * to create a new function from pcl_configure_clocks_osc0() and modify it to use + * preprocessor computation from pre-defined target frequencies. + * + * \param param    pointer on the configuration structure. + * + * \retval 0   Success. + * \retval <0  The configuration cannot be performed. + */ +extern long int pcl_configure_clocks_osc0(pcl_freq_param_t *param); + +/*! \brief Automatically configure the CPU, PBA, PBB, and HSB clocks using the DFLL0 as main source clock + * + * This function needs some parameters stored in a pcl_freq_param_t structure: + *  - cpu_f and pba_f and pbb_f are the wanted frequencies, + *  - dfll_f is the target DFLL frequency to set-up + * + * \note: when the DFLL0 is to be used as main source clock for the synchronous clocks, + *  the target frequency of the DFLL should be chosen to be as high as possible + *  within the specification range (for stability reasons); the target cpu and pbx + *  frequencies will then be reached by appropriate division ratio. + * + * Supported main clock sources: PCL_MC_DFLL0 + * + * Supported synchronous clocks frequencies: + * (these obviously depend on the DFLL target frequency; we'll take 100MHz as an example) + * 50MHz, 25MHz, 12.5MHz, 6.25MHz, 3.125MHz, 1562.5kHz, 781.25kHz, 390.625kHz. + * + * \note: by default, this implementation doesn't perform thorough checks on the + *        input parameters. To enable the checks, define AVR32SFW_INPUT_CHECK. + * + * \note: since it is dynamically computing the appropriate field values of the + * configuration registers from the parameters structure, this function is not + * optimal in terms of code size. For a code size optimal solution, it is better + * to create a new function from pcl_configure_clocks_dfll0() and modify it to + * use preprocessor computation from pre-defined target frequencies. + * + * \param param    pointer on the configuration structure. + * + * \retval 0   Success. + * \retval <0  The configuration cannot be performed. + */ +extern long int pcl_configure_clocks_dfll0(pcl_freq_param_t *param); + +/*! \brief Switch the main clock source to Osc0 configured in crystal mode + * + * \param osc The oscillator to enable and switch to. + * \param fcrystal Oscillator external crystal frequency (Hz) + * \param startup Oscillator startup time. + * + * \return Status. + *   \retval 0  Success. + *   \retval <0 An error occured. + */ +extern long int pcl_switch_to_osc(pcl_osc_t osc, unsigned int fcrystal, unsigned int startup); + +/*! \brief Enable the clock of a module. + * + * \param module The module to clock (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" + * or look in the module section). + * + * \return Status. + *   \retval 0  Success. + *   \retval <0 An error occured. + */ +#ifndef AVR32_PM_VERSION_RESETVALUE +// Implementation for UC3A, UC3A3, UC3B parts. +#define pcl_enable_module(module) pm_enable_module(&AVR32_PM, module) +#else +// Implementation for UC3C, UC3L parts. +#define pcl_enable_module(module) pm_enable_module(module) +#endif + +/*! \brief Disable the clock of a module. + * + * \param 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" + * or look in the module section). + * + * \return Status. + *   \retval 0  Success. + *   \retval <0 An error occured. + */ +#ifndef AVR32_PM_VERSION_RESETVALUE +// Implementation for UC3A, UC3A3, UC3B parts. +#define pcl_disable_module(module)  pm_disable_module(&AVR32_PM, module) +#else +// Implementation for UC3C, UC3L parts. +#define pcl_disable_module(module)  pm_disable_module(module) +#endif + +/*! \brief Configure the USB Clock + * + * + * \return Status. + *   \retval 0  Success. + *   \retval <0 An error occured. + */ +extern long int pcl_configure_usb_clock(void); + +//! @} + +/*! \name Power Management + */ +//! @{ +/*! + * \brief Read the content of the GPLP registers + * \param gplp GPLP register index (0,1,... depending on the number of GPLP registers for a given part) + * + * \return The content of the chosen GPLP register. + */ +extern unsigned long pcl_read_gplp(unsigned long gplp); + + +/*! + * \brief Write into the GPLP registers + * \param gplp GPLP register index (0,1,... depending on the number of GPLP registers for a given part) + * \param value Value to write + */ +extern void pcl_write_gplp(unsigned long gplp, unsigned long value); + +//! @} + +#ifdef __cplusplus +} +#endif + +#endif  // _POWER_CLOCKS_LIB_H_ | 
