1 /**
2 * \file
3 *
4 * \brief Chip-specific generic clock management.
5 *
6 * Copyright (c) 2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43 /*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47 #ifndef CHIP_GENCLK_H_INCLUDED
48 #define CHIP_GENCLK_H_INCLUDED
49
50 #include <osc.h>
51 #include <pll.h>
52
53 /// @cond 0
54 /**INDENT-OFF**/
55 #ifdef __cplusplus
56 extern "C" {
57 #endif
58 /**INDENT-ON**/
59 /// @endcond
60
61 /**
62 * \weakgroup genclk_group
63 * @{
64 */
65
66 //! \name Programmable Clock Identifiers (PCK)
67 //@{
68 #define GENCLK_PCK_0 0 //!< PCK0 ID
69 #define GENCLK_PCK_1 1 //!< PCK1 ID
70 #define GENCLK_PCK_2 2 //!< PCK2 ID
71 //@}
72
73 //! \name Programmable Clock Sources (PCK)
74 //@{
75
76 enum genclk_source {
77 GENCLK_PCK_SRC_SLCK_RC = 0,//!< Internal 32kHz RC oscillator as PCK source clock
78 GENCLK_PCK_SRC_SLCK_XTAL = 1,//!< External 32kHz crystal oscillator as PCK source clock
79 GENCLK_PCK_SRC_SLCK_BYPASS = 2,//!< External 32kHz bypass oscillator as PCK source clock
80 GENCLK_PCK_SRC_MAINCK_4M_RC = 3,//!< Internal 4MHz RC oscillator as PCK source clock
81 GENCLK_PCK_SRC_MAINCK_8M_RC = 4,//!< Internal 8MHz RC oscillator as PCK source clock
82 GENCLK_PCK_SRC_MAINCK_12M_RC = 5,//!< Internal 12MHz RC oscillator as PCK source clock
83 GENCLK_PCK_SRC_MAINCK_XTAL = 6,//!< External crystal oscillator as PCK source clock
84 GENCLK_PCK_SRC_MAINCK_BYPASS = 7,//!< External bypass oscillator as PCK source clock
85 GENCLK_PCK_SRC_PLLACK = 8,//!< Use PLLACK as PCK source clock
86 GENCLK_PCK_SRC_MCK = 9,//!< Use Master Clk as PCK source clock
87 };
88
89 //@}
90
91 //! \name Programmable Clock Prescalers (PCK)
92 //@{
93
94 enum genclk_divider {
95 GENCLK_PCK_PRES_1 = PMC_PCK_PRES(0), //!< Set PCK clock prescaler to 1
96 GENCLK_PCK_PRES_2 = PMC_PCK_PRES(1), //!< Set PCK clock prescaler to 2
97 GENCLK_PCK_PRES_4 = PMC_PCK_PRES(2), //!< Set PCK clock prescaler to 4
98 GENCLK_PCK_PRES_8 = PMC_PCK_PRES(3), //!< Set PCK clock prescaler to 8
99 GENCLK_PCK_PRES_16 = PMC_PCK_PRES(4), //!< Set PCK clock prescaler to 16
100 GENCLK_PCK_PRES_32 = PMC_PCK_PRES(5), //!< Set PCK clock prescaler to 32
101 GENCLK_PCK_PRES_64 = PMC_PCK_PRES(6), //!< Set PCK clock prescaler to 64
102 };
103
104 //@}
105
106 struct genclk_config {
107 uint32_t ctrl;
108 };
109
genclk_config_defaults(struct genclk_config * p_cfg,uint32_t ul_id)110 static inline void genclk_config_defaults(struct genclk_config *p_cfg,
111 uint32_t ul_id)
112 {
113 ul_id = ul_id;
114 p_cfg->ctrl = 0;
115 }
116
genclk_config_read(struct genclk_config * p_cfg,uint32_t ul_id)117 static inline void genclk_config_read(struct genclk_config *p_cfg,
118 uint32_t ul_id)
119 {
120 p_cfg->ctrl = PMC->PMC_PCK[ul_id];
121 }
122
genclk_config_write(const struct genclk_config * p_cfg,uint32_t ul_id)123 static inline void genclk_config_write(const struct genclk_config *p_cfg,
124 uint32_t ul_id)
125 {
126 PMC->PMC_PCK[ul_id] = p_cfg->ctrl;
127 }
128
129 //! \name Programmable Clock Source and Prescaler configuration
130 //@{
131
genclk_config_set_source(struct genclk_config * p_cfg,enum genclk_source e_src)132 static inline void genclk_config_set_source(struct genclk_config *p_cfg,
133 enum genclk_source e_src)
134 {
135 p_cfg->ctrl &= (~PMC_PCK_CSS_Msk);
136
137 switch (e_src) {
138 case GENCLK_PCK_SRC_SLCK_RC:
139 case GENCLK_PCK_SRC_SLCK_XTAL:
140 case GENCLK_PCK_SRC_SLCK_BYPASS:
141 p_cfg->ctrl |= (PMC_PCK_CSS_SLOW_CLK);
142 break;
143
144 case GENCLK_PCK_SRC_MAINCK_4M_RC:
145 case GENCLK_PCK_SRC_MAINCK_8M_RC:
146 case GENCLK_PCK_SRC_MAINCK_12M_RC:
147 case GENCLK_PCK_SRC_MAINCK_XTAL:
148 case GENCLK_PCK_SRC_MAINCK_BYPASS:
149 p_cfg->ctrl |= (PMC_PCK_CSS_MAIN_CLK);
150 break;
151
152 case GENCLK_PCK_SRC_PLLACK:
153 p_cfg->ctrl |= (PMC_PCK_CSS_PLLA_CLK);
154 break;
155
156 case GENCLK_PCK_SRC_MCK:
157 p_cfg->ctrl |= (PMC_PCK_CSS_MCK);
158 break;
159
160 default:
161 break;
162 }
163 }
164
genclk_config_set_divider(struct genclk_config * p_cfg,uint32_t e_divider)165 static inline void genclk_config_set_divider(struct genclk_config *p_cfg,
166 uint32_t e_divider)
167 {
168 p_cfg->ctrl &= ~PMC_PCK_PRES_Msk;
169 p_cfg->ctrl |= e_divider;
170 }
171
172 //@}
173
genclk_enable(const struct genclk_config * p_cfg,uint32_t ul_id)174 static inline void genclk_enable(const struct genclk_config *p_cfg, uint32_t ul_id)
175 {
176 PMC->PMC_PCK[ul_id] = p_cfg->ctrl;
177 pmc_enable_pck(ul_id);
178 }
179
genclk_disable(uint32_t ul_id)180 static inline void genclk_disable(uint32_t ul_id)
181 {
182 pmc_disable_pck(ul_id);
183 }
184
genclk_enable_source(enum genclk_source e_src)185 static inline void genclk_enable_source(enum genclk_source e_src)
186 {
187 switch (e_src) {
188 case GENCLK_PCK_SRC_SLCK_RC:
189 if (!osc_is_ready(OSC_SLCK_32K_RC)) {
190 osc_enable(OSC_SLCK_32K_RC);
191 osc_wait_ready(OSC_SLCK_32K_RC);
192 }
193 break;
194
195 case GENCLK_PCK_SRC_SLCK_XTAL:
196 if (!osc_is_ready(OSC_SLCK_32K_XTAL)) {
197 osc_enable(OSC_SLCK_32K_XTAL);
198 osc_wait_ready(OSC_SLCK_32K_XTAL);
199 }
200 break;
201
202 case GENCLK_PCK_SRC_SLCK_BYPASS:
203 if (!osc_is_ready(OSC_SLCK_32K_BYPASS)) {
204 osc_enable(OSC_SLCK_32K_BYPASS);
205 osc_wait_ready(OSC_SLCK_32K_BYPASS);
206 }
207 break;
208
209 case GENCLK_PCK_SRC_MAINCK_4M_RC:
210 if (!osc_is_ready(OSC_MAINCK_4M_RC)) {
211 osc_enable(OSC_MAINCK_4M_RC);
212 osc_wait_ready(OSC_MAINCK_4M_RC);
213 }
214 break;
215
216 case GENCLK_PCK_SRC_MAINCK_8M_RC:
217 if (!osc_is_ready(OSC_MAINCK_8M_RC)) {
218 osc_enable(OSC_MAINCK_8M_RC);
219 osc_wait_ready(OSC_MAINCK_8M_RC);
220 }
221 break;
222
223 case GENCLK_PCK_SRC_MAINCK_12M_RC:
224 if (!osc_is_ready(OSC_MAINCK_12M_RC)) {
225 osc_enable(OSC_MAINCK_12M_RC);
226 osc_wait_ready(OSC_MAINCK_12M_RC);
227 }
228 break;
229
230 case GENCLK_PCK_SRC_MAINCK_XTAL:
231 if (!osc_is_ready(OSC_MAINCK_XTAL)) {
232 osc_enable(OSC_MAINCK_XTAL);
233 osc_wait_ready(OSC_MAINCK_XTAL);
234 }
235 break;
236
237 case GENCLK_PCK_SRC_MAINCK_BYPASS:
238 if (!osc_is_ready(OSC_MAINCK_BYPASS)) {
239 osc_enable(OSC_MAINCK_BYPASS);
240 osc_wait_ready(OSC_MAINCK_BYPASS);
241 }
242 break;
243
244 #ifdef CONFIG_PLL0_SOURCE
245 case GENCLK_PCK_SRC_PLLACK:
246 pll_enable_config_defaults(0);
247 break;
248 #endif
249
250 case GENCLK_PCK_SRC_MCK:
251 break;
252
253 default:
254 Assert(false);
255 break;
256 }
257 }
258
259 //! @}
260
261 /// @cond 0
262 /**INDENT-OFF**/
263 #ifdef __cplusplus
264 }
265 #endif
266 /**INDENT-ON**/
267 /// @endcond
268
269 #endif /* CHIP_GENCLK_H_INCLUDED */
270