pm.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. /* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
  2. /*This file has been prepared for Doxygen automatic documentation generation.*/
  3. /*! \file *********************************************************************
  4. *
  5. * \brief Power Manager driver.
  6. *
  7. *
  8. * - Compiler: IAR EWAVR32 and GNU GCC for AVR32
  9. * - Supported devices: All AVR32 devices.
  10. * - AppNote:
  11. *
  12. * \author Atmel Corporation: http://www.atmel.com \n
  13. * Support and FAQ: http://support.atmel.no/
  14. *
  15. *****************************************************************************/
  16. /* Copyright (c) 2009 Atmel Corporation. All rights reserved.
  17. *
  18. * Redistribution and use in source and binary forms, with or without
  19. * modification, are permitted provided that the following conditions are met:
  20. *
  21. * 1. Redistributions of source code must retain the above copyright notice, this
  22. * list of conditions and the following disclaimer.
  23. *
  24. * 2. Redistributions in binary form must reproduce the above copyright notice,
  25. * this list of conditions and the following disclaimer in the documentation
  26. * and/or other materials provided with the distribution.
  27. *
  28. * 3. The name of Atmel may not be used to endorse or promote products derived
  29. * from this software without specific prior written permission.
  30. *
  31. * 4. This software may only be redistributed and used in connection with an Atmel
  32. * AVR product.
  33. *
  34. * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
  35. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  36. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  37. * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
  38. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  39. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  40. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  41. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  42. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  43. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
  44. *
  45. */
  46. #include "compiler.h"
  47. #include "pm.h"
  48. /*! \name PM Writable Bit-Field Registers
  49. */
  50. //! @{
  51. typedef union
  52. {
  53. unsigned long mcctrl;
  54. avr32_pm_mcctrl_t MCCTRL;
  55. } u_avr32_pm_mcctrl_t;
  56. typedef union
  57. {
  58. unsigned long cksel;
  59. avr32_pm_cksel_t CKSEL;
  60. } u_avr32_pm_cksel_t;
  61. typedef union
  62. {
  63. unsigned long pll;
  64. avr32_pm_pll_t PLL;
  65. } u_avr32_pm_pll_t;
  66. typedef union
  67. {
  68. unsigned long oscctrl0;
  69. avr32_pm_oscctrl0_t OSCCTRL0;
  70. } u_avr32_pm_oscctrl0_t;
  71. typedef union
  72. {
  73. unsigned long oscctrl1;
  74. avr32_pm_oscctrl1_t OSCCTRL1;
  75. } u_avr32_pm_oscctrl1_t;
  76. typedef union
  77. {
  78. unsigned long oscctrl32;
  79. avr32_pm_oscctrl32_t OSCCTRL32;
  80. } u_avr32_pm_oscctrl32_t;
  81. typedef union
  82. {
  83. unsigned long ier;
  84. avr32_pm_ier_t IER;
  85. } u_avr32_pm_ier_t;
  86. typedef union
  87. {
  88. unsigned long idr;
  89. avr32_pm_idr_t IDR;
  90. } u_avr32_pm_idr_t;
  91. typedef union
  92. {
  93. unsigned long icr;
  94. avr32_pm_icr_t ICR;
  95. } u_avr32_pm_icr_t;
  96. typedef union
  97. {
  98. unsigned long gcctrl;
  99. avr32_pm_gcctrl_t GCCTRL;
  100. } u_avr32_pm_gcctrl_t;
  101. typedef union
  102. {
  103. unsigned long rccr;
  104. avr32_pm_rccr_t RCCR;
  105. } u_avr32_pm_rccr_t;
  106. typedef union
  107. {
  108. unsigned long bgcr;
  109. avr32_pm_bgcr_t BGCR;
  110. } u_avr32_pm_bgcr_t;
  111. typedef union
  112. {
  113. unsigned long vregcr;
  114. avr32_pm_vregcr_t VREGCR;
  115. } u_avr32_pm_vregcr_t;
  116. typedef union
  117. {
  118. unsigned long bod;
  119. avr32_pm_bod_t BOD;
  120. } u_avr32_pm_bod_t;
  121. //! @}
  122. /*! \brief Sets the mode of the oscillator 0.
  123. *
  124. * \param pm Base address of the Power Manager (i.e. &AVR32_PM).
  125. * \param mode Oscillator 0 mode (i.e. AVR32_PM_OSCCTRL0_MODE_x).
  126. */
  127. static void pm_set_osc0_mode(volatile avr32_pm_t *pm, unsigned int mode)
  128. {
  129. // Read
  130. u_avr32_pm_oscctrl0_t u_avr32_pm_oscctrl0 = {pm->oscctrl0};
  131. // Modify
  132. u_avr32_pm_oscctrl0.OSCCTRL0.mode = mode;
  133. // Write
  134. pm->oscctrl0 = u_avr32_pm_oscctrl0.oscctrl0;
  135. }
  136. void pm_enable_osc0_ext_clock(volatile avr32_pm_t *pm)
  137. {
  138. pm_set_osc0_mode(pm, AVR32_PM_OSCCTRL0_MODE_EXT_CLOCK);
  139. }
  140. void pm_enable_osc0_crystal(volatile avr32_pm_t *pm, unsigned int fosc0)
  141. {
  142. pm_set_osc0_mode(pm, (fosc0 < 900000) ? AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G0 :
  143. (fosc0 < 3000000) ? AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G1 :
  144. (fosc0 < 8000000) ? AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G2 :
  145. AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G3);
  146. }
  147. void pm_enable_clk0(volatile avr32_pm_t *pm, unsigned int startup)
  148. {
  149. pm_enable_clk0_no_wait(pm, startup);
  150. pm_wait_for_clk0_ready(pm);
  151. }
  152. void pm_disable_clk0(volatile avr32_pm_t *pm)
  153. {
  154. pm->mcctrl &= ~AVR32_PM_MCCTRL_OSC0EN_MASK;
  155. }
  156. void pm_enable_clk0_no_wait(volatile avr32_pm_t *pm, unsigned int startup)
  157. {
  158. // Read register
  159. u_avr32_pm_oscctrl0_t u_avr32_pm_oscctrl0 = {pm->oscctrl0};
  160. // Modify
  161. u_avr32_pm_oscctrl0.OSCCTRL0.startup = startup;
  162. // Write back
  163. pm->oscctrl0 = u_avr32_pm_oscctrl0.oscctrl0;
  164. pm->mcctrl |= AVR32_PM_MCCTRL_OSC0EN_MASK;
  165. }
  166. void pm_wait_for_clk0_ready(volatile avr32_pm_t *pm)
  167. {
  168. while (!(pm->poscsr & AVR32_PM_POSCSR_OSC0RDY_MASK));
  169. }
  170. /*! \brief Sets the mode of the oscillator 1.
  171. *
  172. * \param pm Base address of the Power Manager (i.e. &AVR32_PM).
  173. * \param mode Oscillator 1 mode (i.e. AVR32_PM_OSCCTRL1_MODE_x).
  174. */
  175. static void pm_set_osc1_mode(volatile avr32_pm_t *pm, unsigned int mode)
  176. {
  177. // Read
  178. u_avr32_pm_oscctrl1_t u_avr32_pm_oscctrl1 = {pm->oscctrl1};
  179. // Modify
  180. u_avr32_pm_oscctrl1.OSCCTRL1.mode = mode;
  181. // Write
  182. pm->oscctrl1 = u_avr32_pm_oscctrl1.oscctrl1;
  183. }
  184. void pm_enable_osc1_ext_clock(volatile avr32_pm_t *pm)
  185. {
  186. pm_set_osc1_mode(pm, AVR32_PM_OSCCTRL1_MODE_EXT_CLOCK);
  187. }
  188. void pm_enable_osc1_crystal(volatile avr32_pm_t *pm, unsigned int fosc1)
  189. {
  190. pm_set_osc1_mode(pm, (fosc1 < 900000) ? AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G0 :
  191. (fosc1 < 3000000) ? AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G1 :
  192. (fosc1 < 8000000) ? AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G2 :
  193. AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G3);
  194. }
  195. void pm_enable_clk1(volatile avr32_pm_t *pm, unsigned int startup)
  196. {
  197. pm_enable_clk1_no_wait(pm, startup);
  198. pm_wait_for_clk1_ready(pm);
  199. }
  200. void pm_disable_clk1(volatile avr32_pm_t *pm)
  201. {
  202. pm->mcctrl &= ~AVR32_PM_MCCTRL_OSC1EN_MASK;
  203. }
  204. void pm_enable_clk1_no_wait(volatile avr32_pm_t *pm, unsigned int startup)
  205. {
  206. // Read register
  207. u_avr32_pm_oscctrl1_t u_avr32_pm_oscctrl1 = {pm->oscctrl1};
  208. // Modify
  209. u_avr32_pm_oscctrl1.OSCCTRL1.startup = startup;
  210. // Write back
  211. pm->oscctrl1 = u_avr32_pm_oscctrl1.oscctrl1;
  212. pm->mcctrl |= AVR32_PM_MCCTRL_OSC1EN_MASK;
  213. }
  214. void pm_wait_for_clk1_ready(volatile avr32_pm_t *pm)
  215. {
  216. while (!(pm->poscsr & AVR32_PM_POSCSR_OSC1RDY_MASK));
  217. }
  218. /*! \brief Sets the mode of the 32-kHz oscillator.
  219. *
  220. * \param pm Base address of the Power Manager (i.e. &AVR32_PM).
  221. * \param mode 32-kHz oscillator mode (i.e. AVR32_PM_OSCCTRL32_MODE_x).
  222. */
  223. static void pm_set_osc32_mode(volatile avr32_pm_t *pm, unsigned int mode)
  224. {
  225. // Read
  226. u_avr32_pm_oscctrl32_t u_avr32_pm_oscctrl32 = {pm->oscctrl32};
  227. // Modify
  228. u_avr32_pm_oscctrl32.OSCCTRL32.mode = mode;
  229. // Write
  230. pm->oscctrl32 = u_avr32_pm_oscctrl32.oscctrl32;
  231. }
  232. void pm_enable_osc32_ext_clock(volatile avr32_pm_t *pm)
  233. {
  234. pm_set_osc32_mode(pm, AVR32_PM_OSCCTRL32_MODE_EXT_CLOCK);
  235. }
  236. void pm_enable_osc32_crystal(volatile avr32_pm_t *pm)
  237. {
  238. pm_set_osc32_mode(pm, AVR32_PM_OSCCTRL32_MODE_CRYSTAL);
  239. }
  240. void pm_enable_clk32(volatile avr32_pm_t *pm, unsigned int startup)
  241. {
  242. pm_enable_clk32_no_wait(pm, startup);
  243. pm_wait_for_clk32_ready(pm);
  244. }
  245. void pm_disable_clk32(volatile avr32_pm_t *pm)
  246. {
  247. pm->oscctrl32 &= ~AVR32_PM_OSCCTRL32_OSC32EN_MASK;
  248. }
  249. void pm_enable_clk32_no_wait(volatile avr32_pm_t *pm, unsigned int startup)
  250. {
  251. // Read register
  252. u_avr32_pm_oscctrl32_t u_avr32_pm_oscctrl32 = {pm->oscctrl32};
  253. // Modify
  254. u_avr32_pm_oscctrl32.OSCCTRL32.osc32en = 1;
  255. u_avr32_pm_oscctrl32.OSCCTRL32.startup = startup;
  256. // Write back
  257. pm->oscctrl32 = u_avr32_pm_oscctrl32.oscctrl32;
  258. }
  259. void pm_wait_for_clk32_ready(volatile avr32_pm_t *pm)
  260. {
  261. while (!(pm->poscsr & AVR32_PM_POSCSR_OSC32RDY_MASK));
  262. }
  263. void pm_cksel(volatile avr32_pm_t *pm,
  264. unsigned int pbadiv,
  265. unsigned int pbasel,
  266. unsigned int pbbdiv,
  267. unsigned int pbbsel,
  268. unsigned int hsbdiv,
  269. unsigned int hsbsel)
  270. {
  271. u_avr32_pm_cksel_t u_avr32_pm_cksel = {0};
  272. u_avr32_pm_cksel.CKSEL.cpusel = hsbsel;
  273. u_avr32_pm_cksel.CKSEL.cpudiv = hsbdiv;
  274. u_avr32_pm_cksel.CKSEL.hsbsel = hsbsel;
  275. u_avr32_pm_cksel.CKSEL.hsbdiv = hsbdiv;
  276. u_avr32_pm_cksel.CKSEL.pbasel = pbasel;
  277. u_avr32_pm_cksel.CKSEL.pbadiv = pbadiv;
  278. u_avr32_pm_cksel.CKSEL.pbbsel = pbbsel;
  279. u_avr32_pm_cksel.CKSEL.pbbdiv = pbbdiv;
  280. pm->cksel = u_avr32_pm_cksel.cksel;
  281. // Wait for ckrdy bit and then clear it
  282. while (!(pm->poscsr & AVR32_PM_POSCSR_CKRDY_MASK));
  283. }
  284. void pm_gc_setup(volatile avr32_pm_t *pm,
  285. unsigned int gc,
  286. unsigned int osc_or_pll, // Use Osc (=0) or PLL (=1)
  287. unsigned int pll_osc, // Sel Osc0/PLL0 or Osc1/PLL1
  288. unsigned int diven,
  289. unsigned int div)
  290. {
  291. u_avr32_pm_gcctrl_t u_avr32_pm_gcctrl = {0};
  292. u_avr32_pm_gcctrl.GCCTRL.oscsel = pll_osc;
  293. u_avr32_pm_gcctrl.GCCTRL.pllsel = osc_or_pll;
  294. u_avr32_pm_gcctrl.GCCTRL.diven = diven;
  295. u_avr32_pm_gcctrl.GCCTRL.div = div;
  296. pm->gcctrl[gc] = u_avr32_pm_gcctrl.gcctrl;
  297. }
  298. void pm_gc_enable(volatile avr32_pm_t *pm,
  299. unsigned int gc)
  300. {
  301. pm->gcctrl[gc] |= AVR32_PM_GCCTRL_CEN_MASK;
  302. }
  303. void pm_gc_disable(volatile avr32_pm_t *pm,
  304. unsigned int gc)
  305. {
  306. pm->gcctrl[gc] &= ~AVR32_PM_GCCTRL_CEN_MASK;
  307. }
  308. void pm_pll_setup(volatile avr32_pm_t *pm,
  309. unsigned int pll,
  310. unsigned int mul,
  311. unsigned int div,
  312. unsigned int osc,
  313. unsigned int lockcount)
  314. {
  315. u_avr32_pm_pll_t u_avr32_pm_pll = {0};
  316. u_avr32_pm_pll.PLL.pllosc = osc;
  317. u_avr32_pm_pll.PLL.plldiv = div;
  318. u_avr32_pm_pll.PLL.pllmul = mul;
  319. u_avr32_pm_pll.PLL.pllcount = lockcount;
  320. pm->pll[pll] = u_avr32_pm_pll.pll;
  321. }
  322. void pm_pll_set_option(volatile avr32_pm_t *pm,
  323. unsigned int pll,
  324. unsigned int pll_freq,
  325. unsigned int pll_div2,
  326. unsigned int pll_wbwdisable)
  327. {
  328. u_avr32_pm_pll_t u_avr32_pm_pll = {pm->pll[pll]};
  329. u_avr32_pm_pll.PLL.pllopt = pll_freq | (pll_div2 << 1) | (pll_wbwdisable << 2);
  330. pm->pll[pll] = u_avr32_pm_pll.pll;
  331. }
  332. unsigned int pm_pll_get_option(volatile avr32_pm_t *pm,
  333. unsigned int pll)
  334. {
  335. return (pm->pll[pll] & AVR32_PM_PLLOPT_MASK) >> AVR32_PM_PLLOPT_OFFSET;
  336. }
  337. void pm_pll_enable(volatile avr32_pm_t *pm,
  338. unsigned int pll)
  339. {
  340. pm->pll[pll] |= AVR32_PM_PLLEN_MASK;
  341. }
  342. void pm_pll_disable(volatile avr32_pm_t *pm,
  343. unsigned int pll)
  344. {
  345. pm->pll[pll] &= ~AVR32_PM_PLLEN_MASK;
  346. }
  347. void pm_wait_for_pll0_locked(volatile avr32_pm_t *pm)
  348. {
  349. while (!(pm->poscsr & AVR32_PM_POSCSR_LOCK0_MASK));
  350. }
  351. void pm_wait_for_pll1_locked(volatile avr32_pm_t *pm)
  352. {
  353. while (!(pm->poscsr & AVR32_PM_POSCSR_LOCK1_MASK));
  354. }
  355. void pm_switch_to_clock(volatile avr32_pm_t *pm, unsigned long clock)
  356. {
  357. // Read
  358. u_avr32_pm_mcctrl_t u_avr32_pm_mcctrl = {pm->mcctrl};
  359. // Modify
  360. u_avr32_pm_mcctrl.MCCTRL.mcsel = clock;
  361. // Write back
  362. pm->mcctrl = u_avr32_pm_mcctrl.mcctrl;
  363. }
  364. void pm_switch_to_osc0(volatile avr32_pm_t *pm, unsigned int fosc0, unsigned int startup)
  365. {
  366. pm_enable_osc0_crystal(pm, fosc0); // Enable the Osc0 in crystal mode
  367. pm_enable_clk0(pm, startup); // Crystal startup time - This parameter is critical and depends on the characteristics of the crystal
  368. pm_switch_to_clock(pm, AVR32_PM_MCSEL_OSC0); // Then switch main clock to Osc0
  369. }
  370. void pm_bod_enable_irq(volatile avr32_pm_t *pm)
  371. {
  372. pm->ier = AVR32_PM_IER_BODDET_MASK;
  373. }
  374. void pm_bod_disable_irq(volatile avr32_pm_t *pm)
  375. {
  376. Bool global_interrupt_enabled = Is_global_interrupt_enabled();
  377. if (global_interrupt_enabled) Disable_global_interrupt();
  378. pm->idr = AVR32_PM_IDR_BODDET_MASK;
  379. pm->isr;
  380. if (global_interrupt_enabled) Enable_global_interrupt();
  381. }
  382. void pm_bod_clear_irq(volatile avr32_pm_t *pm)
  383. {
  384. pm->icr = AVR32_PM_ICR_BODDET_MASK;
  385. }
  386. unsigned long pm_bod_get_irq_status(volatile avr32_pm_t *pm)
  387. {
  388. return ((pm->isr & AVR32_PM_ISR_BODDET_MASK) != 0);
  389. }
  390. unsigned long pm_bod_get_irq_enable_bit(volatile avr32_pm_t *pm)
  391. {
  392. return ((pm->imr & AVR32_PM_IMR_BODDET_MASK) != 0);
  393. }
  394. unsigned long pm_bod_get_level(volatile avr32_pm_t *pm)
  395. {
  396. return (pm->bod & AVR32_PM_BOD_LEVEL_MASK) >> AVR32_PM_BOD_LEVEL_OFFSET;
  397. }
  398. unsigned long pm_read_gplp(volatile avr32_pm_t *pm, unsigned long gplp)
  399. {
  400. return pm->gplp[gplp];
  401. }
  402. void pm_write_gplp(volatile avr32_pm_t *pm, unsigned long gplp, unsigned long value)
  403. {
  404. pm->gplp[gplp] = value;
  405. }
  406. long pm_enable_module(volatile avr32_pm_t *pm, unsigned long module)
  407. {
  408. unsigned long domain = module>>5;
  409. unsigned long *regptr = (unsigned long*)(&(pm->cpumask) + domain);
  410. // Implementation-specific shortcut: the ckMASK registers are contiguous and
  411. // memory-mapped in that order: CPUMASK, HSBMASK, PBAMASK, PBBMASK.
  412. *regptr |= (1<<(module%32));
  413. return PASS;
  414. }
  415. long pm_disable_module(volatile avr32_pm_t *pm, unsigned long module)
  416. {
  417. unsigned long domain = module>>5;
  418. unsigned long *regptr = (unsigned long*)(&(pm->cpumask) + domain);
  419. // Implementation-specific shortcut: the ckMASK registers are contiguous and
  420. // memory-mapped in that order: CPUMASK, HSBMASK, PBAMASK, PBBMASK.
  421. *regptr &= ~(1<<(module%32));
  422. return PASS;
  423. }