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 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 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 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 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 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 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 180 static inline void genclk_disable(uint32_t ul_id) 181 { 182 pmc_disable_pck(ul_id); 183 } 184 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