]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_ATSAM3S-EK2_Atmel_Studio/src/asf/common/services/clock/sam3s/pll.h
Add demo for SAM3S-EK2.
[freertos] / FreeRTOS / Demo / CORTEX_ATSAM3S-EK2_Atmel_Studio / src / asf / common / services / clock / sam3s / pll.h
1 /**\r
2  * \file\r
3  *\r
4  * \brief Chip-specific PLL definitions.\r
5  *\r
6  * Copyright (c) 2011-2012 Atmel Corporation. All rights reserved.\r
7  *\r
8  * \asf_license_start\r
9  *\r
10  * \page License\r
11  *\r
12  * Redistribution and use in source and binary forms, with or without\r
13  * modification, are permitted provided that the following conditions are met:\r
14  *\r
15  * 1. Redistributions of source code must retain the above copyright notice,\r
16  *    this list of conditions and the following disclaimer.\r
17  *\r
18  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
19  *    this list of conditions and the following disclaimer in the documentation\r
20  *    and/or other materials provided with the distribution.\r
21  *\r
22  * 3. The name of Atmel may not be used to endorse or promote products derived\r
23  *    from this software without specific prior written permission.\r
24  *\r
25  * 4. This software may only be redistributed and used in connection with an\r
26  *    Atmel microcontroller product.\r
27  *\r
28  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
29  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
31  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
32  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
36  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
37  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
38  * POSSIBILITY OF SUCH DAMAGE.\r
39  *\r
40  * \asf_license_stop\r
41  *\r
42  */\r
43 \r
44 #ifndef CHIP_PLL_H_INCLUDED\r
45 #define CHIP_PLL_H_INCLUDED\r
46 \r
47 #include <osc.h>\r
48 \r
49 /// @cond 0\r
50 /**INDENT-OFF**/\r
51 #ifdef __cplusplus\r
52 extern "C" {\r
53 #endif\r
54 /**INDENT-ON**/\r
55 /// @endcond\r
56 \r
57 /**\r
58  * \weakgroup pll_group\r
59  * @{\r
60  */\r
61 \r
62 #define PLL_OUTPUT_MIN_HZ       60000000\r
63 #define PLL_OUTPUT_MAX_HZ       130000000\r
64 \r
65 #define PLL_INPUT_MIN_HZ        3500000\r
66 #define PLL_INPUT_MAX_HZ        20000000\r
67 \r
68 #define NR_PLLS                         2\r
69 #define PLLA_ID                         0\r
70 #define PLLB_ID                         1\r
71 \r
72 #define PLL_COUNT                       0x3fU\r
73 \r
74 enum pll_source {\r
75         PLL_SRC_MAINCK_4M_RC            = OSC_MAINCK_4M_RC,             //!< Internal 4MHz RC oscillator.\r
76         PLL_SRC_MAINCK_8M_RC            = OSC_MAINCK_8M_RC,             //!< Internal 8MHz RC oscillator.\r
77         PLL_SRC_MAINCK_12M_RC           = OSC_MAINCK_12M_RC,    //!< Internal 12MHz RC oscillator.\r
78         PLL_SRC_MAINCK_XTAL                     = OSC_MAINCK_XTAL,              //!< External crystal oscillator.\r
79         PLL_SRC_MAINCK_BYPASS           = OSC_MAINCK_BYPASS,    //!< External bypass oscillator.\r
80         PLL_NR_SOURCES,                                                                         //!< Number of PLL sources.\r
81 };\r
82 \r
83 struct pll_config {\r
84         uint32_t ctrl;\r
85 };\r
86 \r
87 #define pll_get_default_rate(pll_id)                                       \\r
88         ((osc_get_rate(CONFIG_PLL##pll_id##_SOURCE)                            \\r
89                         * CONFIG_PLL##pll_id##_MUL)                                    \\r
90                         / CONFIG_PLL##pll_id##_DIV)\r
91 \r
92 /**\r
93  * \note The SAM3S PLL hardware interprets mul as mul+1. For readability the hardware mul+1\r
94  * is hidden in this implementation. Use mul as mul effective value.\r
95  */\r
96 static inline void pll_config_init(struct pll_config *p_cfg,\r
97                 enum pll_source e_src, uint32_t ul_div, uint32_t ul_mul)\r
98 {\r
99         uint32_t vco_hz;\r
100 \r
101         Assert(e_src < PLL_NR_SOURCES);\r
102 \r
103         /* Calculate internal VCO frequency */\r
104         vco_hz = osc_get_rate(e_src) / ul_div;\r
105         Assert(vco_hz >= PLL_INPUT_MIN_HZ);\r
106         Assert(vco_hz <= PLL_INPUT_MAX_HZ);\r
107         \r
108         vco_hz *= ul_mul;\r
109         Assert(vco_hz >= PLL_OUTPUT_MIN_HZ);\r
110         Assert(vco_hz <= PLL_OUTPUT_MAX_HZ);\r
111 \r
112         /* PMC hardware will automatically make it mul+1 */\r
113         p_cfg->ctrl = CKGR_PLLAR_MULA(ul_mul - 1) | CKGR_PLLAR_DIVA(ul_div) | CKGR_PLLAR_PLLACOUNT(PLL_COUNT);\r
114 }\r
115 \r
116 #define pll_config_defaults(cfg, pll_id)                                   \\r
117         pll_config_init(cfg,                                                   \\r
118                         CONFIG_PLL##pll_id##_SOURCE,                                   \\r
119                         CONFIG_PLL##pll_id##_DIV,                                      \\r
120                         CONFIG_PLL##pll_id##_MUL)\r
121 \r
122 static inline void pll_config_read(struct pll_config *p_cfg, uint32_t ul_pll_id)\r
123 {\r
124         Assert(ul_pll_id < NR_PLLS);\r
125 \r
126         if (ul_pll_id == PLLA_ID)\r
127                 p_cfg->ctrl = PMC->CKGR_PLLAR;\r
128         else\r
129                 p_cfg->ctrl = PMC->CKGR_PLLBR;\r
130 }\r
131 \r
132 static inline void pll_config_write(const struct pll_config *p_cfg, uint32_t ul_pll_id)\r
133 {\r
134         Assert(ul_pll_id < NR_PLLS);\r
135         \r
136         if (ul_pll_id == PLLA_ID) {\r
137                 pmc_disable_pllack(); // Always stop PLL first!\r
138                 PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | p_cfg->ctrl;\r
139         } else {\r
140                 pmc_disable_pllbck();\r
141                 PMC->CKGR_PLLBR = p_cfg->ctrl;\r
142         }\r
143 }\r
144 \r
145 static inline void pll_enable(const struct pll_config *p_cfg, uint32_t ul_pll_id)\r
146 {\r
147         Assert(ul_pll_id < NR_PLLS);\r
148         \r
149         if (ul_pll_id == PLLA_ID) {\r
150                 pmc_disable_pllack(); // Always stop PLL first!\r
151                 PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | p_cfg->ctrl;\r
152         } else {\r
153                 pmc_disable_pllbck();\r
154                 PMC->CKGR_PLLBR = p_cfg->ctrl;\r
155         }\r
156 }\r
157 \r
158 /** \r
159  * \note This will only disable the selected PLL, not the underlying oscillator (mainck).\r
160  */\r
161 static inline void pll_disable(uint32_t ul_pll_id)\r
162 {\r
163         Assert(ul_pll_id < NR_PLLS);\r
164         \r
165         if (ul_pll_id == PLLA_ID)\r
166                 pmc_disable_pllack();\r
167         else\r
168                 pmc_disable_pllbck();\r
169 }\r
170 \r
171 static inline uint32_t pll_is_locked(uint32_t ul_pll_id)\r
172 {\r
173         Assert(ul_pll_id < NR_PLLS);\r
174         \r
175         if (ul_pll_id == PLLA_ID)\r
176                 return pmc_is_locked_pllack();\r
177         else\r
178                 return pmc_is_locked_pllbck();\r
179 }\r
180 \r
181 static inline void pll_enable_source(enum pll_source e_src)\r
182 {\r
183         switch (e_src) {\r
184         case PLL_SRC_MAINCK_4M_RC:\r
185         case PLL_SRC_MAINCK_8M_RC:\r
186         case PLL_SRC_MAINCK_12M_RC:\r
187         case PLL_SRC_MAINCK_XTAL:\r
188         case PLL_SRC_MAINCK_BYPASS:\r
189                 osc_enable(e_src);\r
190                 osc_wait_ready(e_src);\r
191                 break;\r
192 \r
193         default:\r
194                 Assert(false);\r
195                 break;\r
196         }\r
197 }\r
198 \r
199 static inline void pll_enable_config_defaults(unsigned int ul_pll_id)\r
200 {\r
201         struct pll_config pllcfg;\r
202 \r
203         if (pll_is_locked(ul_pll_id)) {\r
204                 return; // Pll already running\r
205         }\r
206         switch (ul_pll_id) {\r
207 #ifdef CONFIG_PLL0_SOURCE\r
208         case 0:\r
209                 pll_enable_source(CONFIG_PLL0_SOURCE);\r
210                 pll_config_init(&pllcfg,\r
211                                 CONFIG_PLL0_SOURCE,\r
212                                 CONFIG_PLL0_DIV,\r
213                                 CONFIG_PLL0_MUL);\r
214                 break;\r
215 #endif\r
216 #ifdef CONFIG_PLL1_SOURCE\r
217         case 1:\r
218                 pll_enable_source(CONFIG_PLL1_SOURCE);\r
219                 pll_config_init(&pllcfg,\r
220                                 CONFIG_PLL1_SOURCE,\r
221                                 CONFIG_PLL1_DIV,\r
222                                 CONFIG_PLL1_MUL);\r
223                 break;\r
224 #endif\r
225         default:\r
226                 Assert(false);\r
227                 break;\r
228         }\r
229         pll_enable(&pllcfg, ul_pll_id);\r
230         while (!pll_is_locked(ul_pll_id));\r
231 }\r
232 \r
233 //! @}\r
234 \r
235 /// @cond 0\r
236 /**INDENT-OFF**/\r
237 #ifdef __cplusplus\r
238 }\r
239 #endif\r
240 /**INDENT-ON**/\r
241 /// @endcond\r
242 \r
243 #endif /* CHIP_PLL_H_INCLUDED */\r