pm_uc3l.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. /*!
  2. * Copyright (C) 2001-2010 by egnite Software GmbH
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. *
  34. * Portions Copyright Atmel Corporation, see the following note.
  35. */
  36. /* Copyright (c) 2009 Atmel Corporation. All rights reserved.
  37. *
  38. * Redistribution and use in source and binary forms, with or without
  39. * modification, are permitted provided that the following conditions are met:
  40. *
  41. * 1. Redistributions of source code must retain the above copyright notice, this
  42. * list of conditions and the following disclaimer.
  43. *
  44. * 2. Redistributions in binary form must reproduce the above copyright notice,
  45. * this list of conditions and the following disclaimer in the documentation
  46. * and/or other materials provided with the distribution.
  47. *
  48. * 3. The name of Atmel may not be used to endorse or promote products derived
  49. * from this software without specific prior written permission.
  50. *
  51. * 4. This software may only be redistributed and used in connection with an Atmel
  52. * AVR product.
  53. *
  54. * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
  55. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  56. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  57. * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
  58. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  59. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  60. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  61. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  62. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  63. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
  64. *
  65. */
  66. #include <avr32/io.h>
  67. #include <arch/avr32.h>
  68. #include <arch/avr32/pm.h>
  69. #include <cfg/os.h>
  70. #include <cfg/clock.h>
  71. #include <arch/avr32.h>
  72. #include <dev/irqreg.h>
  73. #include <sys/timer.h>
  74. #include <arch/avr32/ihndlr.h>
  75. #include <avr32/io.h>
  76. #include "compiler.h"
  77. /*! \name SCIF Writable Bit-Field Registers
  78. */
  79. //! @{
  80. typedef union
  81. {
  82. unsigned long oscctrl0;
  83. avr32_scif_oscctrl0_t OSCCTRL0;
  84. } u_avr32_scif_oscctrl0_t;
  85. typedef union
  86. {
  87. unsigned long oscctrl32;
  88. avr32_scif_oscctrl32_t OSCCTRL32;
  89. } u_avr32_scif_oscctrl32_t;
  90. typedef union
  91. {
  92. unsigned long dfll0conf;
  93. avr32_scif_dfll0conf_t DFLL0CONF;
  94. } u_avr32_scif_dfll0conf_t;
  95. typedef union
  96. {
  97. unsigned long dfll0ssg;
  98. avr32_scif_dfll0ssg_t DFLL0SSG;
  99. } u_avr32_scif_dfll0ssg_t;
  100. #if (UC3L0128 || UC3L0256)
  101. typedef union
  102. {
  103. unsigned long pll0;
  104. avr32_scif_pll_t PLL0;
  105. } u_avr32_scif_pll_t;
  106. #endif
  107. //! @}
  108. //! Unlock SCIF register macro
  109. #define SCIF_UNLOCK(reg) (AVR32_SCIF.unlock = (AVR32_SCIF_UNLOCK_KEY_VALUE << AVR32_SCIF_UNLOCK_KEY_OFFSET)|(reg))
  110. #define SCIF_DFLL0_MODE_OPENLOOP 0
  111. #define SCIF_DFLL0_MODE_CLOSEDLOOP 1
  112. //! The min DFLL output frequency
  113. #if defined(MCU_UC3L0128) || defined(MCU_UC3L0256)
  114. #define SCIF_DFLL_MINFREQ_KHZ 20000
  115. #define SCIF_DFLL_MINFREQ_HZ 20000000UL
  116. #else
  117. #define SCIF_DFLL_MINFREQ_KHZ 40000
  118. #define SCIF_DFLL_MINFREQ_HZ 40000000UL
  119. #endif
  120. //! The max DFLL output frequency
  121. #define SCIF_DFLL_MAXFREQ_KHZ 150000
  122. #define SCIF_DFLL_MAXFREQ_HZ 150000000UL
  123. #define DFLL_COARSE_MAX (AVR32_SCIF_COARSE_MASK >> AVR32_SCIF_COARSE_OFFSET)
  124. #define DFLL_FINE_MAX (AVR32_SCIF_FINE_MASK >> AVR32_SCIF_FINE_OFFSET)
  125. #define DFLL_FINE_HALF (1UL << (AVR32_SCIF_FINE_SIZE - 1))
  126. //! \name System clock source
  127. //@{
  128. #define SYSCLK_SRC_RCSYS 0 //!< System RC oscillator
  129. #define SYSCLK_SRC_OSC0 1 //!< Oscillator 0
  130. #define SYSCLK_SRC_DFLL 2 //!< Digital Frequency Locked Loop
  131. #define SYSCLK_SRC_RC120M 3 //!< 120 MHz RC oscillator
  132. #if (UC3L0128 || UC3L0256)
  133. #define SYSCLK_SRC_PLL0 4 //!< Phase Locked Loop 0
  134. #endif
  135. struct genclk_config {
  136. uint32_t ctrl;
  137. };
  138. struct dfll_config {
  139. struct genclk_config ref_cfg; //!< Reference clock
  140. uint32_t conf; //!< DFLLnCONF
  141. uint32_t mul; //!< DFLLnMUL
  142. uint32_t step; //!< DFLLnSTEP
  143. uint32_t ssg; //!< DFLLnSSG
  144. };
  145. typedef uint32_t irqflags_t;
  146. #define barrier() asm volatile("" ::: "memory")
  147. #define sysreg_write(reg, val) __builtin_mtsr(reg, val)
  148. #define sysreg_read(reg) __builtin_mfsr(reg)
  149. #define cpu_irq_disable() \
  150. do { \
  151. __builtin_ssrf(AVR32_SR_GM_OFFSET); \
  152. barrier(); \
  153. } while (0)
  154. static inline irqflags_t cpu_irq_save(void)
  155. {
  156. irqflags_t flags;
  157. flags = sysreg_read(AVR32_SR);
  158. cpu_irq_disable();
  159. return flags;
  160. }
  161. static inline void cpu_irq_restore(irqflags_t flags)
  162. {
  163. barrier();
  164. #if defined(__ICCAVR32__)
  165. // Barrier " __asm__ __volatile__ ("")"
  166. // Don't work with sysreg_write(AVR32_SR, flags)
  167. if( cpu_irq_is_enabled_flags(flags) ) {
  168. cpu_irq_enable();
  169. }
  170. #else
  171. sysreg_write(AVR32_SR, flags);
  172. #endif
  173. barrier();
  174. }
  175. #define dfll_write_reg(reg, value) \
  176. do { \
  177. irqflags_t dfll_flags; \
  178. while (!(AVR32_SCIF.pclksr & AVR32_SCIF_DFLL0RDY_MASK)); \
  179. dfll_flags = cpu_irq_save(); \
  180. SCIF_UNLOCK(AVR32_SCIF_##reg); \
  181. *(volatile uint32_t *)(AVR32_SCIF_ADDRESS + AVR32_SCIF_##reg) \
  182. = (value); \
  183. cpu_irq_restore(dfll_flags); \
  184. } while (0)
  185. void dfll_enable_open_loop(const struct dfll_config *cfg,
  186. unsigned int dfll_id)
  187. {
  188. irqflags_t flags;
  189. /* First, enable the DFLL, then configure it */
  190. flags = cpu_irq_save();
  191. SCIF_UNLOCK(AVR32_SCIF_DFLL0CONF);
  192. AVR32_SCIF.dfll0conf = 1U << AVR32_SCIF_DFLL0CONF_EN;
  193. cpu_irq_restore(flags);
  194. dfll_write_reg(DFLL0CONF, cfg->conf | (1U << AVR32_SCIF_DFLL0CONF_EN));
  195. dfll_write_reg(DFLL0SSG, cfg->ssg);
  196. }
  197. static inline void genclk_enable(const struct genclk_config *cfg, unsigned int id)
  198. {
  199. AVR32_SCIF.gcctrl[id] = cfg->ctrl | (1U << AVR32_SCIF_GCCTRL_CEN);
  200. }
  201. void dfll_enable_closed_loop(const struct dfll_config *cfg,
  202. unsigned int dfll_id)
  203. {
  204. irqflags_t flags;
  205. /* Enable the reference clock */
  206. genclk_enable(&cfg->ref_cfg, 0);
  207. /*
  208. * Enable the DFLL first, but don't wait for the DFLL0RDY bit
  209. * because if the DFLL has been disabled before, the DFLL0RDY
  210. * bit stays cleared until it is re-enabled.
  211. */
  212. flags = cpu_irq_save();
  213. AVR32_SCIF.unlock = 0xaa000000 | AVR32_SCIF_DFLL0CONF;
  214. AVR32_SCIF.dfll0conf = 1U << AVR32_SCIF_DFLL0CONF_EN;
  215. cpu_irq_restore(flags);
  216. /*
  217. * Then, configure the DFLL, taking care to wait for the
  218. * DFLL0RDY bit before every step.
  219. */
  220. dfll_write_reg(DFLL0STEP, cfg->step);
  221. #ifdef AVR32_SCIF_DFLL0FMUL
  222. dfll_write_reg(DFLL0FMUL, cfg->mul);
  223. #else
  224. dfll_write_reg(DFLL0MUL, cfg->mul);
  225. #endif
  226. dfll_write_reg(DFLL0SSG, cfg->ssg);
  227. dfll_write_reg(DFLL0CONF, cfg->conf | (1U << AVR32_SCIF_DFLL0CONF_EN));
  228. }
  229. static inline void genclk_config_defaults(struct genclk_config *cfg, unsigned int id)
  230. {
  231. cfg->ctrl = 0;
  232. }
  233. static inline void genclk_config_set_source(struct genclk_config *cfg, int src)
  234. {
  235. cfg->ctrl = (cfg->ctrl & ~AVR32_SCIF_GCCTRL_OSCSEL_MASK)
  236. | (src << AVR32_SCIF_GCCTRL_OSCSEL);
  237. }
  238. static inline void genclk_config_set_divider(struct genclk_config *cfg,
  239. unsigned int divider)
  240. {
  241. // Assert(divider > 0 && divider <= GENCLK_DIV_MAX);
  242. /* Clear all the bits we're about to modify */
  243. cfg->ctrl &= ~(AVR32_SCIF_GCCTRL_DIVEN_MASK
  244. | AVR32_SCIF_GCCTRL_DIV_MASK);
  245. if (divider > 1) {
  246. cfg->ctrl |= 1U << AVR32_SCIF_GCCTRL_DIVEN;
  247. cfg->ctrl |= (((divider + 1) / 2) - 1) << AVR32_SCIF_GCCTRL_DIV;
  248. }
  249. }
  250. static inline void dfll_config_init_open_loop_mode(struct dfll_config *cfg)
  251. {
  252. genclk_config_defaults(&cfg->ref_cfg, 0);
  253. cfg->conf = 1;
  254. cfg->mul = 0;
  255. cfg->step = 0;
  256. cfg->ssg = 0;
  257. }
  258. static inline void dfll_config_init_closed_loop_mode(struct dfll_config *cfg,
  259. int refclk, uint16_t div, uint16_t mul)
  260. {
  261. /*
  262. * Set up generic clock source with specified reference clock
  263. * and divider.
  264. */
  265. genclk_config_defaults(&cfg->ref_cfg, 0);
  266. genclk_config_set_source(&cfg->ref_cfg, refclk);
  267. genclk_config_set_divider(&cfg->ref_cfg, div);
  268. cfg->conf = 1U << AVR32_SCIF_DFLL0CONF_MODE;
  269. cfg->mul = mul << 16;
  270. /*
  271. * Initial step length of 4. If this is set too high, the DFLL
  272. * may fail to lock.
  273. */
  274. cfg->step = ((4U << AVR32_SCIF_DFLL0STEP_FSTEP)
  275. | (4U << AVR32_SCIF_DFLL0STEP_CSTEP));
  276. cfg->ssg = 0;
  277. }
  278. static inline void dfll_config_set_initial_tuning(struct dfll_config *cfg,
  279. uint16_t coarse, uint16_t fine)
  280. {
  281. cfg->conf &= ~(AVR32_SCIF_DFLL0CONF_COARSE_MASK
  282. | AVR32_SCIF_DFLL0CONF_FINE_MASK);
  283. cfg->conf |= ((coarse << AVR32_SCIF_DFLL0CONF_COARSE)
  284. | (fine << AVR32_SCIF_DFLL0CONF_FINE));
  285. }
  286. /**
  287. * \brief Tune the DFLL configuration for a specific target frequency
  288. *
  289. * This will set the initial coarse and fine DFLL tuning to match the
  290. * given target frequency. In open loop mode, this will cause the DFLL
  291. * to run close to the specified frequency, though it may not match
  292. * exactly. In closed loop mode, the DFLL will automatically tune itself
  293. * to the target frequency regardless of the initial tuning, but this
  294. * function may be used to set a starting point close to the desired
  295. * frequency in order to reduce the startup time.
  296. *
  297. * \par Calculating the DFLL frequency
  298. *
  299. * \f{eqnarray*}{
  300. f_{DFLL} &=& \left[f_{min} + \left(f_{max} - f_{min}\right)
  301. \frac{\mathrm{COARSE}}{\mathrm{COARSE}_{max}}\right]
  302. \left(1 + x \frac{\mathrm{FINE}
  303. - \mathrm{FINE}_{half}}{\mathrm{FINE}_{max}}\right)
  304. = f_{coarse} \left(1 + x
  305. \frac{\mathrm{FINE}
  306. - \mathrm{FINE}_{half}}{\mathrm{FINE}_{max}}\right) \\
  307. \mathrm{COARSE} &=& \frac{\left(f_{DFLL} - f_{min}\right)}
  308. {f_{max} - f_{min}} \mathrm{COARSE}_{max} \\
  309. f_{coarse} &=& f_{min} + \left(f_{max} - f_{min}\right)
  310. \frac{\mathrm{COARSE}}{\mathrm{COARSE}_{max}} \\
  311. \mathrm{FINE} &=& \left(10 \frac{f_{DFLL} - f_{coarse}}
  312. {f_{coarse}} + \mathrm{FINE}_{half}\right) / 4
  313. \f}
  314. *
  315. * \param cfg The DFLL configuration to be tuned.
  316. * \param target_hz Target frequency in Hz.
  317. */
  318. static inline void dfll_config_tune_for_target_hz(struct dfll_config *cfg,
  319. uint32_t target_hz)
  320. {
  321. uint32_t target_khz;
  322. uint32_t coarse_khz;
  323. uint32_t delta_khz;
  324. uint32_t coarse;
  325. uint32_t fine;
  326. target_khz = target_hz / 1000;
  327. coarse = ((target_khz - SCIF_DFLL_MINFREQ_KHZ) * DFLL_COARSE_MAX)
  328. / (SCIF_DFLL_MAXFREQ_KHZ - SCIF_DFLL_MINFREQ_KHZ);
  329. coarse_khz = SCIF_DFLL_MINFREQ_KHZ + (((SCIF_DFLL_MAXFREQ_KHZ - SCIF_DFLL_MINFREQ_KHZ)
  330. / DFLL_COARSE_MAX) * coarse);
  331. delta_khz = target_khz - coarse_khz;
  332. fine = (((delta_khz * DFLL_FINE_MAX) * 2) / coarse_khz) * 5;
  333. fine += DFLL_FINE_HALF;
  334. fine /= 4;
  335. dfll_config_set_initial_tuning(cfg, coarse, fine);
  336. }
  337. /**
  338. * \brief Set system clock prescaler configuration
  339. *
  340. * This function will change the system clock prescaler configuration to
  341. * match the parameters.
  342. *
  343. * \note The parameters to this function are device-specific.
  344. *
  345. * \param cpu_shift The CPU clock will be divided by \f$2^{cpu\_shift}\f$
  346. * \param pba_shift The PBA clock will be divided by \f$2^{pba\_shift}\f$
  347. * \param pbb_shift The PBB clock will be divided by \f$2^{pbb\_shift}\f$
  348. */
  349. void sysclk_set_prescalers(unsigned int cpu_shift,
  350. unsigned int pba_shift, unsigned int pbb_shift)
  351. {
  352. irqflags_t flags;
  353. uint32_t cpu_cksel = 0;
  354. uint32_t pba_cksel = 0;
  355. uint32_t pbb_cksel = 0;
  356. // Assert(cpu_shift <= pba_shift);
  357. // Assert(cpu_shift <= pbb_shift);
  358. if (cpu_shift > 0)
  359. cpu_cksel = ((cpu_shift - 1) << AVR32_PM_CPUSEL_CPUSEL)
  360. | (1U << AVR32_PM_CPUSEL_CPUDIV);
  361. if (pba_shift > 0)
  362. pba_cksel = ((pba_shift - 1) << AVR32_PM_PBASEL_PBSEL)
  363. | (1U << AVR32_PM_PBASEL_PBDIV);
  364. if (pbb_shift > 0)
  365. pbb_cksel = ((pbb_shift - 1) << AVR32_PM_PBBSEL_PBSEL)
  366. | (1U << AVR32_PM_PBBSEL_PBDIV);
  367. flags = cpu_irq_save();
  368. AVR32_PM.unlock = 0xaa000000 | AVR32_PM_CPUSEL;
  369. AVR32_PM.cpusel = cpu_cksel;
  370. AVR32_PM.unlock = 0xaa000000 | AVR32_PM_PBASEL;
  371. AVR32_PM.pbasel = pba_cksel;
  372. AVR32_PM.unlock = 0xaa000000 | AVR32_PM_PBBSEL;
  373. AVR32_PM.pbbsel = pbb_cksel;
  374. cpu_irq_restore(flags);
  375. }
  376. void pm_enable_osc0_crystal(unsigned int fosc0)
  377. {
  378. AVR32_SCIF.gcctrl[AVR32_SCIF_GCLK_DFLL0_REF] = ((0 << AVR32_SCIF_GCCTRL_DIV_OFFSET)&AVR32_SCIF_GCCTRL_DIV_MASK)
  379. |((0 << AVR32_SCIF_GCCTRL_DIVEN_OFFSET)&AVR32_SCIF_GCCTRL_DIVEN_MASK)
  380. |((AVR32_SCIF_GC_USES_OSC0 << AVR32_SCIF_GCCTRL_OSCSEL_OFFSET)&AVR32_SCIF_GCCTRL_OSCSEL_MASK)
  381. |(AVR32_SCIF_GCCTRL_CEN_MASK);
  382. }
  383. #if 0
  384. static void pm_enable_dfll(void)
  385. {
  386. u_avr32_scif_dfll0conf_t u_avr32_scif_dfll0conf = {AVR32_SCIF.dfll0conf};
  387. u_avr32_scif_dfll0conf.DFLL0CONF.en = 1;
  388. SCIF_UNLOCK(AVR32_SCIF_DFLL0CONF);
  389. AVR32_SCIF.dfll0conf = u_avr32_scif_dfll0conf.dfll0conf;
  390. while(!(AVR32_SCIF.pclksr & AVR32_SCIF_PCLKSR_DFLL0RDY_MASK));
  391. #define COARSEMAXSTEP (((DFLL_CPU_FREQ - SCIF_DFLL_MINFREQ_HZ)*255)/(SCIF_DFLL_MAXFREQ_HZ - SCIF_DFLL_MINFREQ_HZ))
  392. SCIF_UNLOCK(AVR32_SCIF_DFLL0STEP);
  393. AVR32_SCIF.dfll0step = ((COARSEMAXSTEP << AVR32_SCIF_DFLL0STEP_CSTEP_OFFSET) & AVR32_SCIF_DFLL0STEP_CSTEP_MASK) | ((0x0000004 << AVR32_SCIF_DFLL0STEP_FSTEP_OFFSET) & AVR32_SCIF_DFLL0STEP_FSTEP_MASK);
  394. while(!(AVR32_SCIF.pclksr & AVR32_SCIF_PCLKSR_DFLL0RDY_MASK));
  395. #if defined( AVR32_SCIF_DFLL0MUL )
  396. SCIF_UNLOCK(AVR32_SCIF_DFLL0MUL);
  397. AVR32_SCIF.dfll0mul = ((DFLL_CPU_FMUL << AVR32_SCIF_DFLL0MUL_FMUL_OFFSET)&AVR32_SCIF_DFLL0MUL_FMUL_MASK)
  398. | ((DFLL_CPU_IMUL << AVR32_SCIF_DFLL0MUL_IMUL_OFFSET)&AVR32_SCIF_DFLL0MUL_IMUL_MASK);
  399. #else
  400. SCIF_UNLOCK(AVR32_SCIF_DFLL0FMUL);
  401. AVR32_SCIF.dfll0fmul = (DFLL_CPU_FMUL << AVR32_SCIF_DFLL0FMUL_FMUL_OFFSET)&AVR32_SCIF_DFLL0FMUL_FMUL_MASK;
  402. #endif
  403. while(!(AVR32_SCIF.pclksr & AVR32_SCIF_PCLKSR_DFLL0RDY_MASK));
  404. // Set the DFLL0 to operate in closed-loop mode: DFLL0CONF.MODE=1
  405. u_avr32_scif_dfll0conf.DFLL0CONF.mode = SCIF_DFLL0_MODE_CLOSEDLOOP;
  406. u_avr32_scif_dfll0conf.DFLL0CONF.coarse = COARSEMAXSTEP;
  407. SCIF_UNLOCK(AVR32_SCIF_DFLL0CONF);
  408. AVR32_SCIF.dfll0conf = u_avr32_scif_dfll0conf.dfll0conf;
  409. // Wait for PCLKSR.DFLL0RDY is high
  410. while(!(AVR32_SCIF.pclksr & AVR32_SCIF_PCLKSR_DFLL0RDY_MASK));
  411. // Wait until the DFLL is locked on Fine value, and is ready to be selected as
  412. // clock source with a highly accurate output clock.
  413. while(!(AVR32_SCIF.pclksr & AVR32_SCIF_PCLKSR_DFLL0LOCKF_MASK));
  414. }
  415. #endif
  416. /**
  417. * \brief Change the source of the main system clock.
  418. *
  419. * \param src The new system clock source. Must be one of the constants
  420. * from the <em>System Clock Sources</em> section.
  421. */
  422. void sysclk_set_source(uint_fast8_t src)
  423. {
  424. irqflags_t flags;
  425. // Assert(src <= SYSCLK_SRC_RC120M);
  426. flags = cpu_irq_save();
  427. AVR32_PM.unlock = 0xaa000000 | AVR32_PM_MCCTRL;
  428. AVR32_PM.mcctrl = src;
  429. cpu_irq_restore(flags);
  430. }
  431. static inline int dfll_is_fine_locked(unsigned int dfll_id)
  432. {
  433. return !!(AVR32_SCIF.pclksr & (1U << AVR32_SCIF_PCLKSR_DFLL0LOCKF));
  434. }
  435. static inline int dfll_wait_for_fine_lock(unsigned int dfll_id)
  436. {
  437. /* TODO: Add timeout mechanism */
  438. while (!dfll_is_fine_locked(dfll_id)) {
  439. /* Do nothing */
  440. }
  441. return 0;
  442. }
  443. void pm_switch_to_osc0(unsigned int fosc0, unsigned int startup)
  444. {
  445. struct dfll_config dcfg;
  446. dfll_config_init_closed_loop_mode(&dcfg,
  447. 0, 1,
  448. 50000000 / AVR32_SCIF_RCOSC_FREQUENCY);
  449. dfll_enable_closed_loop(&dcfg, 0);
  450. sysclk_set_prescalers(1, 1, 1);
  451. dfll_wait_for_fine_lock(0);
  452. sysclk_set_source(SYSCLK_SRC_DFLL);
  453. // // Switch clock source to OSC0
  454. // pm_enable_osc0_crystal( fosc0 );
  455. //
  456. // // Configure and start DFLL
  457. // pm_enable_dfll();
  458. }
  459. void Avr32InitClockTree( void )
  460. {
  461. /* Enable one wait state for flash access */
  462. AVR32_FLASHCDW.fcr = AVR32_FLASHCDW_FWS_MASK;
  463. pm_switch_to_osc0( OSC0_VAL, 0 );
  464. }