libopencm3
A free/libre/open-source firmware library for various ARM Cortex-M3 microcontrollers.
ccs.c
Go to the documentation of this file.
1/**
2 * @brief <b>PAC55xxxx CCS Driver</b>
3 * @author @htmlonly &copy; @endhtmlonly 2020 Kevin Stefanik <kevin@allocor.tech>
4 * @date March 7, 2020
5 *
6 * This library supports the CCS module in the PAC55xx SoC from Qorvo.
7 *
8 * LGPL License Terms @ref lgpl_license
9 */
10/*
11 * This file is part of the libopencm3 project.
12 *
13 * This library is free software: you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License as published by
15 * the Free Software Foundation, either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with this library. If not, see <http://www.gnu.org/licenses/>.
25 */
30
31static volatile uint32_t ccs_extclk_frequency = 0;
32static volatile uint32_t ccs_frclk_frequency = CCS_ROSC_FREQ;
33static volatile uint32_t ccs_sclk_frequency = CCS_ROSC_FREQ;
34static volatile uint32_t ccs_pll_clk_frequency = 0;
35static volatile uint32_t ccs_hclk_frequency = CCS_ROSC_FREQ;
36static volatile uint32_t ccs_aclk_frequency = CCS_ROSC_FREQ;
37static volatile uint32_t ccs_pclk_frequency = CCS_ROSC_FREQ;
38
39void ccs_frclkmux_select(uint32_t sel) {
40 CCSCTL = (CCSCTL & ~CCS_CTL_FRCLKMUXSEL(CCS_CTL_FRCLKMUXSEL_MASK)) | CCS_CTL_FRCLKMUXSEL(sel);
41}
42void ccs_rosc_enable(void) {
44}
45void ccs_rosc_disable(void) {
46 CCSCTL &= ~CCS_CTL_ROSCEN;
47}
49 CCSCTL &= ~CCS_CTL_SCLKMUXSEL;
50}
53}
56}
58 CCSCTL &= ~CCS_CTL_CLKFAILEN;
59}
61 CCSCTL &= ~CCS_CTL_CLKFAILMUXSEL;
62}
65}
66void ccs_ldo_enable(void) {
68}
69void ccs_ldo_disable(void) {
70 CCSCTL &= ~CCS_CTL_LDOEN;
71}
72void ccs_pclk_enable(void) {
74}
75void ccs_pclk_disable(void) {
76 CCSCTL &= ~CCS_CTL_PCLKEN;
77}
78void ccs_aclk_enable(void) {
80}
81void ccs_aclk_disable(void) {
82 CCSCTL &= ~CCS_CTL_ACLKEN;
83}
86}
88 CCSCTL &= ~CCS_CTL_ADCCLKEN;
89}
92}
94 CCSCTL &= ~CCS_CTL_STCLKSLPEN;
95}
96void ccs_set_pclkdiv(uint32_t div) {
97 CCSCTL = (CCSCTL & ~CCS_CTL_PCLKDIV(8)) | CCS_CTL_PCLKDIV(div);
98}
99void ccs_set_aclkdiv(uint32_t div) {
100 CCSCTL = (CCSCTL & ~CCS_CTL_ACLKDIV(8)) | CCS_CTL_ACLKDIV(div);
101}
102void ccs_set_hclkdiv(uint32_t div) {
103 CCSCTL = (CCSCTL & ~CCS_CTL_HCLKDIV(8)) | CCS_CTL_HCLKDIV(div);
104}
105void ccs_pll_enable(void) {
107}
108void ccs_pll_disable(void) {
109 CCSPLLCTL &= ~CCS_PLLCTL_PLLEN;
110}
111bool ccs_pll_locked(void) {
113}
116}
118 CCSPLLCTL &= ~CCS_PLLCTL_PLLBP;
119}
120void ccs_pll_set_outdiv(uint32_t div) {
121 CCSPLLCTL = (CCSPLLCTL & ~CCS_PLLCTL_PLLOUTDIV(CCS_PLLCTL_PLLOUTDIV_MASK)) | CCS_PLLCTL_PLLOUTDIV(div);
122}
123void ccs_pll_set_indiv(uint32_t div) {
124 if (div <= 15 && div >= 1) {
125 CCSPLLCTL = (CCSPLLCTL & ~CCS_PLLCTL_PLLINDIV(CCS_PLLCTL_PLLINDIV_MASK)) | CCS_PLLCTL_PLLINDIV(div);
126 } else {
128 }
129}
130void ccs_pll_set_fbdiv(uint32_t div) {
131 if (div <= 16383 && div >= 4) {
132 CCSPLLCTL = (CCSPLLCTL & ~CCS_PLLCTL_PLLFBDIV(CCS_PLLCTL_PLLFBDIV_MASK)) | CCS_PLLCTL_PLLFBDIV(div);
133 } else {
135 }
136}
137void css_pll_config_enable(uint32_t indiv, uint32_t fbdiv, uint32_t outdiv) {
139 ccs_pll_set_fbdiv(fbdiv);
140 ccs_pll_set_outdiv(outdiv);
141 ccs_pll_set_indiv(indiv);
143 while (!ccs_pll_locked()) ; /* Wait for PLL lock ~500us */
144}
145uint32_t ccs_get_peripheral_clk_freq(uint32_t periph, uint32_t select) {
146 switch (periph) {
147 case ADC_BASE:
148 return ccs_sclk_frequency;
149 case I2C_BASE: /* fall through */
150 case USARTA_BASE: /* fall through */
151 case USARTB_BASE: /* fall through */
152 case USARTC_BASE: /* fall through */
153 case USARTD_BASE: /* fall through */
154 case CAN_BASE: /* fall through */
155 case GPTIMERA_BASE: /* fall through */
156 case GPTIMERB_BASE:
157 return ccs_pclk_frequency;
158 case TIMERA_BASE: /* fall through */
159 case TIMERB_BASE: /* fall through */
160 case TIMERC_BASE: /* fall through */
161 case TIMERD_BASE:
162 return (select == 0) ? ccs_pclk_frequency : ccs_aclk_frequency;
163 case MEMCTL_BASE:
164 return (select == 0) ? CCS_ROSC_FREQ : ccs_hclk_frequency;
165 case WWDT_BASE:
166 return (select == 0) ? ccs_frclk_frequency : CCS_ROSC_FREQ;
167 case RTC_BASE:
168 return ccs_frclk_frequency;
169 case CRC_BASE: /* fall through */
170 case SYS_TICK_BASE:
171 return ccs_hclk_frequency;
172 default:
174 }
175}
176
181 CCSPLLCTL = 0;
182}
183
184void ccs_configure_clocks(const struct ccs_clk_config *config) {
186
187 ccs_reset_clocks(); /* set safe defaults */
191
192 if (config->mem_enable_cache) {
194 } else {
196 }
197
198 ccs_frclkmux_select(CCS_CTL_FRCLKMUXSEL_CLKREF); /* switch frclk to 4MHz CLKREF */
199
200 switch (config->frclk_source) {
204 break;
208 break;
211 || config->extclk_frequency == 0) {
213 }
216 break;
217 default:
219 }
220
221 if (config->sclk_source == CCS_CTL_SCLKMUXSEL_FRCLK) {
222 ccs_set_hclkdiv(config->hclkdiv);
223 ccs_set_aclkdiv(config->aclkdiv);
227 if (config->mem_mclksel == false) {
229 } else {
231 }
233 } else if (config->sclk_source == CCS_CTL_SCLKMUXSEL_PLLCLK) {
234 css_pll_config_enable(config->pll_indiv, config->pll_fbdiv, config->pll_outdiv);
235 ccs_set_hclkdiv(config->hclkdiv);
236 ccs_set_aclkdiv(config->aclkdiv);
240 if (config->mem_mclksel == false) {
242 } else {
244 }
245 ccs_pll_clk_frequency = ((ccs_frclk_frequency * config->pll_fbdiv) / config->pll_indiv) >> config->pll_outdiv;
247 } else {
249 }
250 ccs_set_pclkdiv(config->pclkdiv);
255
259
261}
static volatile uint32_t ccs_extclk_frequency
PAC55xxxx CCS Driver
Definition: ccs.c:31
static volatile uint32_t ccs_pclk_frequency
Definition: ccs.c:37
static volatile uint32_t ccs_frclk_frequency
Definition: ccs.c:32
static volatile uint32_t ccs_pll_clk_frequency
Definition: ccs.c:34
static volatile uint32_t ccs_sclk_frequency
Definition: ccs.c:33
static volatile uint32_t ccs_hclk_frequency
Definition: ccs.c:35
static volatile uint32_t ccs_aclk_frequency
Definition: ccs.c:36
#define SYS_TICK_BASE
Definition: cm3/memorymap.h:60
void ccs_clkfail_disable(void)
Disable Clock Fail Detection.
Definition: ccs.c:57
void ccs_stclk_sleep_disable(void)
Disable SysTick clock gating in deep sleep mode.
Definition: ccs.c:93
void ccs_pll_bypass_enable(void)
Enable the PLL bypass.
Definition: ccs.c:114
void ccs_set_pclkdiv(uint32_t div)
Set the divisor for the Peripheral Clock.
Definition: ccs.c:96
bool ccs_pll_locked(void)
Check if the PLL is locked.
Definition: ccs.c:111
void ccs_aclk_disable(void)
Disable the Auxiliary Clock.
Definition: ccs.c:81
void ccs_configure_clocks(const struct ccs_clk_config *config)
Setup the PAC55xx clocks with the given struct.
Definition: ccs.c:184
void ccs_pll_set_indiv(uint32_t div)
Set the PLL input divisor.
Definition: ccs.c:123
void ccs_clkfail_enable(void)
Enable Clock Fail Detection.
Definition: ccs.c:54
void ccs_clkfailmux_select_pllclk(void)
Select PLLCLK for Clock Fail Detection.
Definition: ccs.c:63
void ccs_reset_clocks(void)
Restores CCSCTL and CCSPLLCTL registers to default/safe values.
Definition: ccs.c:177
void ccs_pll_set_fbdiv(uint32_t div)
Set the PLL feedback divisor.
Definition: ccs.c:130
void ccs_stclk_sleep_enable(void)
Enable SysTick clock gating in deep sleep mode.
Definition: ccs.c:90
void ccs_aclk_enable(void)
Enable the Auxiliary Clock.
Definition: ccs.c:78
void ccs_ldo_enable(void)
Enable the LDO.
Definition: ccs.c:66
void ccs_ldo_disable(void)
Disable the LDO.
Definition: ccs.c:69
void ccs_rosc_enable(void)
Enable the 16MHz Ring oscillator.
Definition: ccs.c:42
void ccs_frclkmux_select(uint32_t sel)
Select the source for FRCLK.
Definition: ccs.c:39
void ccs_pll_enable(void)
Enable the PLL.
Definition: ccs.c:105
void ccs_clkfailmux_select_frclk(void)
Select FRCLK for Clock Fail Detection.
Definition: ccs.c:60
void ccs_set_hclkdiv(uint32_t div)
Set the divisor for the AHB Clock.
Definition: ccs.c:102
void ccs_pll_set_outdiv(uint32_t div)
Set the output divisor.
Definition: ccs.c:120
void ccs_set_aclkdiv(uint32_t div)
Set the divisor for the Auxiliary Clock.
Definition: ccs.c:99
uint32_t ccs_get_peripheral_clk_freq(uint32_t periph, uint32_t select)
Get the clock rate (in Hz) of the specified peripheral.
Definition: ccs.c:145
void css_pll_config_enable(uint32_t indiv, uint32_t fbdiv, uint32_t outdiv)
Configure the CCS PLL, enable it, and wait for lock.
Definition: ccs.c:137
void ccs_pclk_disable(void)
Disable the Peripheral Clock.
Definition: ccs.c:75
void ccs_pclk_enable(void)
Enable the Peripheral Clock.
Definition: ccs.c:72
void ccs_pll_disable(void)
Disable the PLL.
Definition: ccs.c:108
void ccs_sclkmux_select_pllclk(void)
Select PLLCLK for SCLK.
Definition: ccs.c:51
void ccs_pll_bypass_disable(void)
Disable the PLL bypass.
Definition: ccs.c:117
void ccs_adcclk_enable(void)
Enable the ADC Clock.
Definition: ccs.c:84
void ccs_adcclk_disable(void)
Disable the ADC Clock.
Definition: ccs.c:87
void ccs_rosc_disable(void)
Disable the 16MHz Ring oscillator.
Definition: ccs.c:45
void ccs_sclkmux_select_frclk(void)
Select FRCLK for SCLK.
Definition: ccs.c:48
#define CCS_CTL_FRCLKMUXSEL(sel)
Definition: ccs.h:54
#define CCS_CTL_STCLKSLPEN
Definition: ccs.h:70
#define CCS_CTL_ROSCEN
Definition: ccs.h:58
#define CCS_CTL_ACLKEN
Definition: ccs.h:68
#define CCS_CTL_PCLKDIV(div)
Definition: ccs.h:74
#define CCS_CTL_FRCLKMUXSEL_MASK
Definition: ccs.h:53
#define CCS_CTL_PCLKEN
Definition: ccs.h:67
#define CCS_CTL_CLKFAILMUXSEL
Definition: ccs.h:63
#define CCS_CTL_SCLKMUXSEL_PLLCLK
Definition: ccs.h:61
#define CCSCTL
Definition: ccs.h:52
#define CCS_CTL_FRCLKMUXSEL_EXTCLK
Definition: ccs.h:57
#define CCS_CTL_LDOEN
Definition: ccs.h:65
#define CCS_CTL_SCLKMUXSEL
Definition: ccs.h:59
#define CCS_CTL_SCLKMUXSEL_FRCLK
Definition: ccs.h:60
#define CCS_CTL_FRCLKMUXSEL_ROSC
Definition: ccs.h:55
#define CCS_CTL_HCLKDIV(div)
Definition: ccs.h:82
#define CCS_CTL_ADCCLKEN
Definition: ccs.h:69
#define CCS_CTL_ACLKDIV(div)
Definition: ccs.h:78
#define CCS_CTL_CLKFAILEN
Definition: ccs.h:62
#define CCS_CTL_FRCLKMUXSEL_CLKREF
Definition: ccs.h:56
#define CCS_EXTCLK_MAX_FREQ
Maximum external clock frequency.
Definition: ccs.h:47
#define CCS_ROSC_FREQ
Ring Oscillator Frequency.
Definition: ccs.h:43
#define CCS_CLKREF_FREQ
Internally generated and trimmed 4MHz clock.
Definition: ccs.h:45
#define CCS_PLLCTL_PLLINDIV_MASK
Definition: ccs.h:104
#define CCS_PLLCTL_PLLINDIV(div)
PLL Input Divisor.
Definition: ccs.h:107
#define CCS_PLLCTL_PLLFBDIV(div)
PLL Feedback Divisor.
Definition: ccs.h:111
#define CCS_PLLCTL_PLLOUTDIV_MASK
Definition: ccs.h:96
#define CCS_PLLCTL_PLLEN
PLL Enable.
Definition: ccs.h:93
#define CCSPLLCTL
Definition: ccs.h:91
#define CCS_PLLCTL_PLLFBDIV_MASK
Definition: ccs.h:108
#define CCS_PLLCTL_PLLOUTDIV(div)
PLL Output Divisor.
Definition: ccs.h:99
#define CCS_PLLCTL_PLLLOCK
PLL Lock.
Definition: ccs.h:113
#define CCS_PLLCTL_PLLBP
PLL Bypass.
Definition: ccs.h:95
#define cm3_assert_not_reached()
Check if unreachable code is reached.
Definition: assert.h:102
#define MEMCTL_FLASHLOCK
Flash Lock Access Register.
Definition: memctl.h:81
#define MEMCTL_FLASHLOCK_CLEAR
Definition: memctl.h:82
#define MEMCTL_FLASHLOCK_ALLOW_MEMCTL_WRITE
Definition: memctl.h:84
#define TIMERD_BASE
#define USARTC_BASE
#define USARTA_BASE
#define TIMERC_BASE
#define I2C_BASE
#define TIMERB_BASE
#define TIMERA_BASE
#define CAN_BASE
#define ADC_BASE
#define USARTB_BASE
#define USARTD_BASE
#define GPTIMERB_BASE
#define GPTIMERA_BASE
#define WWDT_BASE
#define RTC_BASE
#define CRC_BASE
#define MEMCTL_BASE
void memctl_flash_select_mclk(void)
Select MCLK as input to Flash Memory Controller.
Definition: memctl.c:52
void memctl_flash_select_roscclk(void)
Select ROSCCLK as input to Flash Memory Controller.
Definition: memctl.c:49
void memctl_flash_cache_enable(void)
Enable Flash cache.
Definition: memctl.c:43
void memctl_flash_set_wstate(uint32_t wstate)
Set the number of wait states for Flash reads.
Definition: memctl.c:28
void memctl_flash_set_mclkdiv(uint32_t div)
Set the MCLK divisor.
Definition: memctl.c:31
void memctl_flash_cache_disable(void)
Disable Flash cache.
Definition: memctl.c:46
CCS Clock Configuration structure.
Definition: ccs.h:350
uint32_t pll_outdiv
PLL Output Divider.
Definition: ccs.h:356
uint32_t aclkdiv
Divisor from SCLK to ACLK.
Definition: ccs.h:358
uint32_t frclk_source
FRCLK source input selection.
Definition: ccs.h:351
bool mem_mclksel
false: ROSCLK, true: HCLK/MCLK
Definition: ccs.h:362
uint32_t hclkdiv
Divisor from SCLK to HCLK.
Definition: ccs.h:357
uint32_t mem_wstate
Number of Flash Read wait states.
Definition: ccs.h:360
uint32_t pll_indiv
PLL Input Divider 1-15.
Definition: ccs.h:354
uint32_t sclk_source
SCLK source selection.
Definition: ccs.h:353
uint32_t mem_mclkdiv
Divisor from HCLK to MCLK.
Definition: ccs.h:361
uint32_t extclk_frequency
EXTCLK frequency, 0 if none.
Definition: ccs.h:352
bool mem_enable_cache
false: disable cache, true: enable cache
Definition: ccs.h:363
uint32_t pll_fbdiv
PLL Feedback Divider 4-16383.
Definition: ccs.h:355
uint32_t pclkdiv
Divisor from HCLK to PCLK.
Definition: ccs.h:359