xref: /btstack/port/samv71-xplained-atwilc3000/ASF/common/services/clock/samv71/genclk.h (revision 1b2596b5303dd8caeea8565532c93cca8dab8cc4)
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