1 
2 /**
3  * \file
4  *
5  * \brief SAM Oscillators Controller.
6  *
7  * Copyright (C) 2015 - 2016 Atmel Corporation. All rights reserved.
8  *
9  * \asf_license_start
10  *
11  * \page License
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions are met:
15  *
16  * 1. Redistributions of source code must retain the above copyright notice,
17  *    this list of conditions and the following disclaimer.
18  *
19  * 2. Redistributions in binary form must reproduce the above copyright notice,
20  *    this list of conditions and the following disclaimer in the documentation
21  *    and/or other materials provided with the distribution.
22  *
23  * 3. The name of Atmel may not be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * 4. This software may only be redistributed and used in connection with an
27  *    Atmel microcontroller product.
28  *
29  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
30  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
31  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
32  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
33  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39  * POSSIBILITY OF SUCH DAMAGE.
40  *
41  * \asf_license_stop
42  *
43  */
44 #include <compiler.h>
45 #include <hpl_init.h>
46 #include <hpl_oscctrl_config.h>
47 
48 /**
49  * \brief Initialize clock sources
50  */
_oscctrl_init_sources(void)51 void _oscctrl_init_sources(void)
52 {
53 	void *hw = (void *)OSCCTRL;
54 
55 #if CONF_XOSC_CONFIG == 1
56 	hri_oscctrl_write_XOSCCTRL_reg(hw,
57 	                               OSCCTRL_XOSCCTRL_STARTUP(CONF_XOSC_STARTUP)
58 	                                   | (CONF_XOSC_AMPGC << OSCCTRL_XOSCCTRL_AMPGC_Pos)
59 	                                   | OSCCTRL_XOSCCTRL_GAIN(CONF_XOSC_GAIN)
60 	                                   | (CONF_XOSC_ONDEMAND << OSCCTRL_XOSCCTRL_ONDEMAND_Pos)
61 	                                   | (CONF_XOSC_RUNSTDBY << OSCCTRL_XOSCCTRL_RUNSTDBY_Pos)
62 	                                   | (CONF_XOSC_XTALEN << OSCCTRL_XOSCCTRL_XTALEN_Pos)
63 	                                   | (CONF_XOSC_ENABLE << OSCCTRL_XOSCCTRL_ENABLE_Pos));
64 
65 #endif
66 
67 #if CONF_OSC16M_CONFIG == 1
68 	hri_oscctrl_write_OSC16MCTRL_reg(hw,
69 	                                 (CONF_OSC16M_ONDEMAND << OSCCTRL_OSC16MCTRL_ONDEMAND_Pos)
70 	                                     | (CONF_OSC16M_RUNSTDBY << OSCCTRL_OSC16MCTRL_RUNSTDBY_Pos)
71 	                                     | (CONF_OSC16M_ENABLE << OSCCTRL_OSC16MCTRL_ENABLE_Pos)
72 	                                     | OSCCTRL_OSC16MCTRL_FSEL(CONF_OSC16M_FSEL));
73 #endif
74 
75 #if CONF_XOSC_CONFIG == 1
76 #if CONF_XOSC_ENABLE == 1
77 	while (!hri_oscctrl_get_STATUS_XOSCRDY_bit(hw))
78 		;
79 #endif
80 #if CONF_XOSC_ONDEMAND == 1
81 	hri_oscctrl_set_XOSCCTRL_ONDEMAND_bit(hw);
82 #endif
83 #endif
84 
85 #if CONF_OSC16M_CONFIG == 1
86 #if CONF_OSC16M_ENABLE == 1
87 	while (!hri_oscctrl_get_STATUS_OSC16MRDY_bit(hw))
88 		;
89 #endif
90 #if CONF_OSC16M_ONDEMAND == 1
91 	hri_oscctrl_set_OSC16MCTRL_ONDEMAND_bit(hw);
92 #endif
93 #endif
94 	(void)hw;
95 }
96 
_oscctrl_init_referenced_generators(void)97 void _oscctrl_init_referenced_generators(void)
98 {
99 	void *                     hw = (void *)OSCCTRL;
100 	hri_oscctrl_dfllctrl_reg_t tmp;
101 
102 #if CONF_DFLL_CONFIG == 1
103 #if CONF_DFLL_OVERWRITE_CALIBRATION == 0
104 #define NVM_DFLL_COARSE_POS 26
105 #define NVM_DFLL_COARSE_SIZE 6
106 	uint32_t coarse;
107 	coarse = *((uint32_t *)(NVMCTRL_OTP5)) >> NVM_DFLL_COARSE_POS;
108 #endif
109 #if CONF_DFLL_USBCRM != 1 && CONF_DFLL_MODE != 0
110 	hri_gclk_write_PCHCTRL_reg(GCLK, 0, (1 << GCLK_PCHCTRL_CHEN_Pos) | GCLK_PCHCTRL_GEN(CONF_DFLL_GCLK));
111 #endif
112 	hri_oscctrl_write_DFLLCTRL_reg(hw, OSCCTRL_DFLLCTRL_ENABLE);
113 	while (!hri_oscctrl_get_STATUS_DFLLRDY_bit(hw))
114 		;
115 	hri_oscctrl_write_DFLLMUL_reg(hw,
116 	                              OSCCTRL_DFLLMUL_CSTEP(CONF_DFLL_CSTEP) | OSCCTRL_DFLLMUL_FSTEP(CONF_DFLL_FSTEP)
117 	                                  | OSCCTRL_DFLLMUL_MUL(CONF_DFLL_MUL));
118 	while (!hri_oscctrl_get_STATUS_DFLLRDY_bit(hw))
119 		;
120 
121 #if CONF_DFLL_OVERWRITE_CALIBRATION == 0
122 	/* FINE is set to fixed value, which defined by DFLL48M Characteristics */
123 	hri_oscctrl_write_DFLLVAL_reg(hw, OSCCTRL_DFLLVAL_COARSE(coarse) | OSCCTRL_DFLLVAL_FINE(512));
124 #else
125 	hri_oscctrl_write_DFLLVAL_reg(hw, OSCCTRL_DFLLVAL_COARSE(CONF_DFLL_COARSE) | OSCCTRL_DFLLVAL_FINE(CONF_DFLL_FINE));
126 #endif
127 
128 	tmp = (CONF_DFLL_WAITLOCK << OSCCTRL_DFLLCTRL_WAITLOCK_Pos) | (CONF_DFLL_BPLCKC << OSCCTRL_DFLLCTRL_BPLCKC_Pos)
129 	      | (CONF_DFLL_QLDIS << OSCCTRL_DFLLCTRL_QLDIS_Pos) | (CONF_DFLL_CCDIS << OSCCTRL_DFLLCTRL_CCDIS_Pos)
130 	      | (CONF_DFLL_RUNSTDBY << OSCCTRL_DFLLCTRL_RUNSTDBY_Pos) | (CONF_DFLL_USBCRM << OSCCTRL_DFLLCTRL_USBCRM_Pos)
131 	      | (CONF_DFLL_LLAW << OSCCTRL_DFLLCTRL_LLAW_Pos) | (CONF_DFLL_STABLE << OSCCTRL_DFLLCTRL_STABLE_Pos)
132 	      | (CONF_DFLL_MODE << OSCCTRL_DFLLCTRL_MODE_Pos) | (CONF_DFLL_ENABLE << OSCCTRL_DFLLCTRL_ENABLE_Pos);
133 	hri_oscctrl_write_DFLLCTRL_reg(hw, tmp);
134 
135 #endif
136 
137 #if CONF_DPLL_CONFIG == 1
138 #if CONF_DPLL_REFCLK == 2
139 	hri_gclk_write_PCHCTRL_reg(GCLK, 1, (1 << GCLK_PCHCTRL_CHEN_Pos) | GCLK_PCHCTRL_GEN(CONF_DPLL_GCLK));
140 #endif
141 	hri_oscctrl_write_DPLLRATIO_reg(
142 	    hw, OSCCTRL_DPLLRATIO_LDRFRAC(CONF_DPLL_LDRFRAC) | OSCCTRL_DPLLRATIO_LDR(CONF_DPLL_LDR));
143 	hri_oscctrl_write_DPLLCTRLB_reg(hw,
144 	                                OSCCTRL_DPLLCTRLB_DIV(CONF_DPLL_DIV)
145 	                                    | (CONF_DPLL_LBYPASS << OSCCTRL_DPLLCTRLB_LBYPASS_Pos)
146 	                                    | OSCCTRL_DPLLCTRLB_LTIME(CONF_DPLL_LTIME)
147 	                                    | OSCCTRL_DPLLCTRLB_REFCLK(CONF_DPLL_REFCLK)
148 	                                    | (CONF_DPLL_WUF << OSCCTRL_DPLLCTRLB_WUF_Pos)
149 	                                    | (CONF_DPLL_LPEN << OSCCTRL_DPLLCTRLB_LPEN_Pos)
150 	                                    | OSCCTRL_DPLLCTRLB_FILTER(CONF_DPLL_FILTER));
151 	hri_oscctrl_write_DPLLPRESC_reg(hw, OSCCTRL_DPLLPRESC_PRESC(CONF_DPLL_PRESC));
152 	hri_oscctrl_write_DPLLCTRLA_reg(hw,
153 	                                (0 << OSCCTRL_DPLLCTRLA_ONDEMAND_Pos)
154 	                                    | (CONF_DPLL_RUNSTDBY << OSCCTRL_DPLLCTRLA_RUNSTDBY_Pos)
155 	                                    | (CONF_DPLL_ENABLE << OSCCTRL_DPLLCTRLA_ENABLE_Pos));
156 #endif
157 
158 #if CONF_DFLL_CONFIG == 1
159 	if (hri_oscctrl_get_DFLLCTRL_MODE_bit(hw)) {
160 		hri_oscctrl_status_reg_t status_mask = OSCCTRL_STATUS_DFLLRDY | OSCCTRL_STATUS_DFLLLCKC;
161 
162 		while (hri_oscctrl_get_STATUS_reg(hw, status_mask) != status_mask)
163 			;
164 	} else {
165 		while (!hri_oscctrl_get_STATUS_DFLLRDY_bit(hw))
166 			;
167 	}
168 #if CONF_DFLL_ONDEMAND == 1
169 	hri_oscctrl_set_DFLLCTRL_ONDEMAND_bit(hw);
170 #endif
171 #endif
172 
173 #if CONF_DPLL_CONFIG == 1
174 #if CONF_DPLL_ENABLE == 1
175 	while (!(hri_oscctrl_get_DPLLSTATUS_LOCK_bit(hw) || hri_oscctrl_get_DPLLSTATUS_CLKRDY_bit(hw)))
176 		;
177 #endif
178 #if CONF_DPLL_ONDEMAND == 1
179 	hri_oscctrl_set_DPLLCTRLA_ONDEMAND_bit(hw);
180 #endif
181 #endif
182 
183 #if CONF_DFLL_CONFIG == 1
184 	while (hri_gclk_read_SYNCBUSY_reg(GCLK))
185 		;
186 #endif
187 	(void)hw, (void)tmp;
188 }
189