pm.c 14 KB

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