Skip to content
This repository was archived by the owner on Mar 17, 2025. It is now read-only.

Commit f2d791d

Browse files
andrzej-kaczmarekcarlescufi
authored andcommitted
Add da1469x_hal
This adds HAL files for some subsysems of DA1469x so drivers can reuse that code instead of accessing registers directly. These files are based on Apache Mynewt implementation. Signed-off-by: Andrzej Kaczmarek <[email protected]>
1 parent 468d3f2 commit f2d791d

File tree

13 files changed

+1530
-0
lines changed

13 files changed

+1530
-0
lines changed

smartbond/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# SPDX-License-Identifier: Apache-2.0
22

33
zephyr_include_directories(sdk/bsp/include)
4+
zephyr_include_directories(da1469x_hal)
5+
add_subdirectory(da1469x_hal)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
zephyr_library_sources(
4+
da1469x_clock.c
5+
da1469x_otp.c
6+
da1469x_pd.c
7+
da1469x_pdc.c
8+
da1469x_trimv.c
9+
)
Lines changed: 333 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,333 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#include <assert.h>
21+
#include <stdbool.h>
22+
#include <stdint.h>
23+
#include <DA1469xAB.h>
24+
#include <da1469x_config.h>
25+
#include <da1469x_clock.h>
26+
#include <da1469x_pd.h>
27+
#include <da1469x_pdc.h>
28+
29+
#define XTAL32M_FREQ 32000000
30+
#define RC32M_FREQ 32000000
31+
#define PLL_FREQ 96000000
32+
#define XTAL32K_FREQ 32768
33+
34+
static uint32_t g_mcu_clock_rcx_freq;
35+
static uint32_t g_mcu_clock_rc32k_freq;
36+
static uint32_t g_mcu_clock_rc32m_freq;
37+
38+
uint32_t SystemCoreClock = RC32M_FREQ;
39+
40+
static inline bool
41+
da1469x_clock_is_xtal32m_settled(void)
42+
{
43+
return ((*(volatile uint32_t *)0x5001001c & 0xff00) == 0) &&
44+
((*(volatile uint32_t *)0x50010054 & 0x000f) != 0xb);
45+
}
46+
47+
void
48+
da1469x_clock_sys_xtal32m_init(void)
49+
{
50+
uint32_t reg;
51+
int xtalrdy_cnt;
52+
53+
/*
54+
* Number of 256kHz clock cycles (~4.085us) assuming worst case when actual frequency is 244800.
55+
* RC32M is in range <30.6, 32.6> so 256Khz can ba as low as 30.6MHz / 125 = 244.8kHz.
56+
*/
57+
xtalrdy_cnt = 1000 * 1000 / 4085;
58+
59+
reg = CRG_XTAL->XTALRDY_CTRL_REG;
60+
reg &= ~(CRG_XTAL_XTALRDY_CTRL_REG_XTALRDY_CNT_Msk);
61+
reg |= CRG_XTAL_XTALRDY_CTRL_REG_XTALRDY_CLK_SEL_Msk;
62+
reg |= xtalrdy_cnt;
63+
CRG_XTAL->XTALRDY_CTRL_REG = reg;
64+
}
65+
66+
void
67+
da1469x_clock_sys_xtal32m_enable(void)
68+
{
69+
int idx;
70+
71+
idx = da1469x_pdc_find(MCU_PDC_TRIGGER_SW_TRIGGER, MCU_PDC_MASTER_M33,
72+
MCU_PDC_EN_XTAL);
73+
if (idx < 0) {
74+
idx = da1469x_pdc_add(MCU_PDC_TRIGGER_SW_TRIGGER, MCU_PDC_MASTER_M33,
75+
MCU_PDC_EN_XTAL);
76+
}
77+
assert(idx >= 0);
78+
79+
da1469x_pdc_set(idx);
80+
da1469x_pdc_ack(idx);
81+
}
82+
83+
void
84+
da1469x_clock_sys_xtal32m_switch(void)
85+
{
86+
if (CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_RC32M_Msk) {
87+
CRG_TOP->CLK_SWITCH2XTAL_REG = CRG_TOP_CLK_SWITCH2XTAL_REG_SWITCH2XTAL_Msk;
88+
} else {
89+
CRG_TOP->CLK_CTRL_REG &= ~CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Msk;
90+
}
91+
92+
while (!(CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_XTAL32M_Msk));
93+
94+
SystemCoreClock = XTAL32M_FREQ;
95+
}
96+
97+
void
98+
da1469x_clock_sys_xtal32m_wait_to_settle(void)
99+
{
100+
uint32_t primask;
101+
102+
primask = DA1469X_IRQ_DISABLE();
103+
while (!da1469x_clock_is_xtal32m_settled()) {
104+
__WFE();
105+
__SEV();
106+
__WFE();
107+
}
108+
DA1469X_IRQ_ENABLE(primask);
109+
}
110+
111+
void
112+
da1469x_clock_sys_xtal32m_switch_safe(void)
113+
{
114+
da1469x_clock_sys_xtal32m_wait_to_settle();
115+
116+
da1469x_clock_sys_xtal32m_switch();
117+
}
118+
119+
void
120+
da1469x_clock_sys_rc32m_disable(void)
121+
{
122+
CRG_TOP->CLK_RC32M_REG &= ~CRG_TOP_CLK_RC32M_REG_RC32M_ENABLE_Msk;
123+
}
124+
125+
void
126+
da1469x_clock_lp_xtal32k_enable(void)
127+
{
128+
CRG_TOP->CLK_XTAL32K_REG |= CRG_TOP_CLK_XTAL32K_REG_XTAL32K_ENABLE_Msk;
129+
}
130+
131+
void
132+
da1469x_clock_lp_xtal32k_switch(void)
133+
{
134+
CRG_TOP->CLK_CTRL_REG = (CRG_TOP->CLK_CTRL_REG &
135+
~CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) |
136+
(2 << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos);
137+
/* If system is running on LP clock update SystemCoreClock */
138+
if (CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_LP_CLK_Msk) {
139+
SystemCoreClock = XTAL32K_FREQ;
140+
}
141+
}
142+
143+
void
144+
da1469x_clock_lp_rcx_enable(void)
145+
{
146+
CRG_TOP->CLK_RCX_REG |= CRG_TOP_CLK_RCX_REG_RCX_ENABLE_Msk;
147+
}
148+
149+
void
150+
da1469x_clock_lp_rcx_switch(void)
151+
{
152+
CRG_TOP->CLK_CTRL_REG = (CRG_TOP->CLK_CTRL_REG &
153+
~CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) |
154+
(1 << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos);
155+
156+
/* If system is running on LP clock update SystemCoreClock */
157+
if (CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_LP_CLK_Msk) {
158+
SystemCoreClock = g_mcu_clock_rcx_freq;
159+
}
160+
}
161+
162+
/**
163+
* Measure clock frequency
164+
*
165+
* @param clock_sel - clock to measure
166+
* 0 - RC32K
167+
* 1 - RC32M
168+
* 2 - XTAL32K
169+
* 3 - RCX
170+
* 4 - RCOSC
171+
* @param ref_cnt - number of cycles used for measurement.
172+
* @return clock frequency
173+
*/
174+
static uint32_t
175+
da1469x_clock_calibrate(uint8_t clock_sel, uint16_t ref_cnt)
176+
{
177+
uint32_t ref_val;
178+
179+
da1469x_pd_acquire(MCU_PD_DOMAIN_PER);
180+
181+
assert(CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_XTAL32M_Msk);
182+
assert(!(ANAMISC_BIF->CLK_REF_SEL_REG & ANAMISC_BIF_CLK_REF_SEL_REG_REF_CAL_START_Msk));
183+
184+
ANAMISC_BIF->CLK_REF_CNT_REG = ref_cnt;
185+
ANAMISC_BIF->CLK_REF_SEL_REG = (clock_sel << ANAMISC_BIF_CLK_REF_SEL_REG_REF_CLK_SEL_Pos) |
186+
ANAMISC_BIF_CLK_REF_SEL_REG_REF_CAL_START_Msk;
187+
188+
while (ANAMISC_BIF->CLK_REF_SEL_REG & ANAMISC_BIF_CLK_REF_SEL_REG_REF_CAL_START_Msk);
189+
190+
ref_val = ANAMISC_BIF->CLK_REF_VAL_REG;
191+
192+
da1469x_pd_release(MCU_PD_DOMAIN_PER);
193+
194+
return 32000000 * ref_cnt / ref_val;
195+
}
196+
197+
void
198+
da1469x_clock_lp_rcx_calibrate(void)
199+
{
200+
g_mcu_clock_rcx_freq = da1469x_clock_calibrate(3, MCU_RCX_CAL_REF_CNT);
201+
}
202+
203+
void
204+
da1469x_clock_lp_rc32k_calibrate(void)
205+
{
206+
g_mcu_clock_rc32k_freq = da1469x_clock_calibrate(0, 100);
207+
}
208+
209+
void
210+
da1469x_clock_lp_rc32m_calibrate(void)
211+
{
212+
g_mcu_clock_rc32m_freq = da1469x_clock_calibrate(1, 100);
213+
}
214+
215+
uint32_t
216+
da1469x_clock_lp_rcx_freq_get(void)
217+
{
218+
assert(g_mcu_clock_rcx_freq);
219+
220+
return g_mcu_clock_rcx_freq;
221+
}
222+
223+
uint32_t
224+
da1469x_clock_lp_rc32k_freq_get(void)
225+
{
226+
assert(g_mcu_clock_rc32k_freq);
227+
228+
return g_mcu_clock_rc32k_freq;
229+
}
230+
231+
uint32_t
232+
da1469x_clock_lp_rc32m_freq_get(void)
233+
{
234+
assert(g_mcu_clock_rc32m_freq);
235+
236+
return g_mcu_clock_rc32m_freq;
237+
}
238+
239+
void
240+
da1469x_clock_lp_rcx_disable(void)
241+
{
242+
CRG_TOP->CLK_RCX_REG &= ~CRG_TOP_CLK_RCX_REG_RCX_ENABLE_Msk;
243+
}
244+
245+
static void
246+
da1469x_delay_us(uint32_t delay_us)
247+
{
248+
/*
249+
* SysTick runs on ~32 MHz clock while PLL is not started.
250+
* so multiplying by 32 to convert from us to SysTicks.
251+
*/
252+
SysTick->LOAD = delay_us * 32;
253+
SysTick->VAL = 0UL;
254+
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
255+
while (0 == (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
256+
SysTick->CTRL = 0;
257+
}
258+
259+
/**
260+
* Enable PLL96
261+
*/
262+
void
263+
da1469x_clock_sys_pll_enable(void)
264+
{
265+
/* Start PLL LDO if not done yet */
266+
if ((CRG_XTAL->PLL_SYS_STATUS_REG & CRG_XTAL_PLL_SYS_STATUS_REG_LDO_PLL_OK_Msk) == 0) {
267+
CRG_XTAL->PLL_SYS_CTRL1_REG |= CRG_XTAL_PLL_SYS_CTRL1_REG_LDO_PLL_ENABLE_Msk;
268+
/* Wait for XTAL LDO to settle */
269+
da1469x_delay_us(20);
270+
}
271+
if ((CRG_XTAL->PLL_SYS_STATUS_REG & CRG_XTAL_PLL_SYS_STATUS_REG_PLL_LOCK_FINE_Msk) == 0) {
272+
/* Enables DXTAL for the system PLL */
273+
CRG_XTAL->XTAL32M_CTRL0_REG |= CRG_XTAL_XTAL32M_CTRL0_REG_XTAL32M_DXTAL_SYSPLL_ENABLE_Msk;
274+
/* Use internal VCO current setting to enable precharge */
275+
CRG_XTAL->PLL_SYS_CTRL1_REG |= CRG_XTAL_PLL_SYS_CTRL1_REG_PLL_SEL_MIN_CUR_INT_Msk;
276+
/* Enable precharge */
277+
CRG_XTAL->PLL_SYS_CTRL2_REG |= CRG_XTAL_PLL_SYS_CTRL2_REG_PLL_RECALIB_Msk;
278+
/* Start the SYSPLL */
279+
CRG_XTAL->PLL_SYS_CTRL1_REG |= CRG_XTAL_PLL_SYS_CTRL1_REG_PLL_EN_Msk;
280+
/* Precharge loopfilter (Vtune) */
281+
da1469x_delay_us(10);
282+
/* Disable precharge */
283+
CRG_XTAL->PLL_SYS_CTRL2_REG &= ~CRG_XTAL_PLL_SYS_CTRL2_REG_PLL_RECALIB_Msk;
284+
/* Extra wait time */
285+
da1469x_delay_us(5);
286+
/* Take external VCO current setting */
287+
CRG_XTAL->PLL_SYS_CTRL1_REG &= ~CRG_XTAL_PLL_SYS_CTRL1_REG_PLL_SEL_MIN_CUR_INT_Msk;
288+
}
289+
}
290+
291+
void
292+
da1469x_clock_sys_pll_disable(void)
293+
{
294+
while (CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_PLL96M_Msk) {
295+
CRG_TOP->CLK_SWITCH2XTAL_REG = CRG_TOP_CLK_SWITCH2XTAL_REG_SWITCH2XTAL_Msk;
296+
297+
SystemCoreClock = XTAL32M_FREQ;
298+
}
299+
300+
CRG_XTAL->PLL_SYS_CTRL1_REG &= ~(CRG_XTAL_PLL_SYS_CTRL1_REG_PLL_EN_Msk |
301+
CRG_XTAL_PLL_SYS_CTRL1_REG_LDO_PLL_ENABLE_Msk);
302+
}
303+
304+
void
305+
da1469x_clock_pll_wait_to_lock(void)
306+
{
307+
uint32_t primask;
308+
309+
primask = DA1469X_IRQ_DISABLE();
310+
311+
NVIC_ClearPendingIRQ(PLL_LOCK_IRQn);
312+
313+
if (!da1469x_clock_is_pll_locked()) {
314+
NVIC_EnableIRQ(PLL_LOCK_IRQn);
315+
while (!NVIC_GetPendingIRQ(PLL_LOCK_IRQn)) {
316+
__WFI();
317+
}
318+
NVIC_DisableIRQ(PLL_LOCK_IRQn);
319+
}
320+
321+
DA1469X_IRQ_ENABLE(primask);
322+
}
323+
324+
void
325+
da1469x_clock_sys_pll_switch(void)
326+
{
327+
/* CLK_SEL_Msk == 3 means PLL */
328+
CRG_TOP->CLK_CTRL_REG |= CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Msk;
329+
330+
while (!(CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_RUNNING_AT_PLL96M_Msk));
331+
332+
SystemCoreClock = PLL_FREQ;
333+
}

0 commit comments

Comments
 (0)