Skip to content

Commit 5c6aea9

Browse files
committed
atmel-samd/samd51: Implement samd.clock
Fill out the dummy implementation.
1 parent 6479cb0 commit 5c6aea9

File tree

1 file changed

+323
-0
lines changed

1 file changed

+323
-0
lines changed

ports/atmel-samd/samd51_clocks.c

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#include "hpl_gclk_config.h"
3030

31+
#include "bindings/samd/Clock.h"
3132
#include "shared-bindings/microcontroller/__init__.h"
3233

3334
#include "py/runtime.h"
@@ -61,26 +62,348 @@ void disable_clock_generator(uint8_t gclk) {
6162
while ((GCLK->SYNCBUSY.vec.GENCTRL & (1 << gclk)) != 0) {}
6263
}
6364

65+
static bool clk_enabled(uint8_t clk) {
66+
return GCLK->PCHCTRL[clk].bit.CHEN;
67+
}
68+
69+
static uint8_t clk_get_generator(uint8_t clk) {
70+
return GCLK->PCHCTRL[clk].bit.GEN;
71+
}
72+
73+
static uint8_t generator_get_source(uint8_t gen) {
74+
return GCLK->GENCTRL[gen].bit.SRC;
75+
}
76+
77+
static bool osc_enabled(uint8_t index) {
78+
switch (index) {
79+
case GCLK_SOURCE_XOSC0:
80+
return OSCCTRL->XOSCCTRL[0].bit.ENABLE;
81+
case GCLK_SOURCE_XOSC1:
82+
return OSCCTRL->XOSCCTRL[1].bit.ENABLE;
83+
case GCLK_SOURCE_OSCULP32K:
84+
return true;
85+
case GCLK_SOURCE_XOSC32K:
86+
return OSC32KCTRL->XOSC32K.bit.ENABLE;
87+
case GCLK_SOURCE_DFLL:
88+
return OSCCTRL->DFLLCTRLA.bit.ENABLE;
89+
case GCLK_SOURCE_DPLL0:
90+
return OSCCTRL->Dpll[0].DPLLCTRLA.bit.ENABLE;
91+
case GCLK_SOURCE_DPLL1:
92+
return OSCCTRL->Dpll[1].DPLLCTRLA.bit.ENABLE;
93+
};
94+
return false;
95+
}
96+
97+
static uint32_t osc_get_source(uint8_t index) {
98+
uint8_t dpll_index = index - GCLK_SOURCE_DPLL0;
99+
uint32_t refclk = OSCCTRL->Dpll[dpll_index].DPLLCTRLB.bit.REFCLK;
100+
switch (refclk) {
101+
case 0x0:
102+
return generator_get_source(GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0 + dpll_index].bit.GEN);
103+
case 0x1:
104+
return GCLK_SOURCE_XOSC32K;
105+
case 0x2:
106+
return GCLK_SOURCE_XOSC0;
107+
case 0x3:
108+
return GCLK_SOURCE_XOSC1;
109+
}
110+
return 0;
111+
}
112+
113+
static uint32_t osc_get_frequency(uint8_t index);
114+
115+
static uint32_t generator_get_frequency(uint8_t gen) {
116+
uint8_t src = GCLK->GENCTRL[gen].bit.SRC;
117+
uint32_t div;
118+
if (GCLK->GENCTRL[gen].bit.DIVSEL) {
119+
div = 1 << (GCLK->GENCTRL[gen].bit.DIV + 1);
120+
} else {
121+
div = GCLK->GENCTRL[gen].bit.DIV;
122+
if (!div)
123+
div = 1;
124+
}
125+
126+
return osc_get_frequency(src) / div;
127+
}
128+
129+
static uint32_t dpll_get_frequency(uint8_t index) {
130+
uint8_t dpll_index = index - GCLK_SOURCE_DPLL0;
131+
uint32_t refclk = OSCCTRL->Dpll[dpll_index].DPLLCTRLB.bit.REFCLK;
132+
uint32_t freq;
133+
134+
switch (refclk) {
135+
case 0x0: // GCLK
136+
freq = generator_get_frequency(GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0 + dpll_index].bit.GEN);
137+
break;
138+
case 0x1: // XOSC32
139+
freq = 32768;
140+
break;
141+
case 0x2: // XOSC0
142+
case 0x3: // XOSC1
143+
return 0; // unknown
144+
}
145+
146+
return (freq * (OSCCTRL->Dpll[dpll_index].DPLLRATIO.bit.LDR + 1)) +
147+
(freq * OSCCTRL->Dpll[dpll_index].DPLLRATIO.bit.LDRFRAC / 32);
148+
}
149+
150+
static uint32_t osc_get_frequency(uint8_t index) {
151+
switch (index) {
152+
case GCLK_SOURCE_XOSC0:
153+
case GCLK_SOURCE_XOSC1:
154+
return 0; // unknown
155+
case GCLK_SOURCE_OSCULP32K:
156+
case GCLK_SOURCE_XOSC32K:
157+
return 32768;
158+
case GCLK_SOURCE_DFLL:
159+
return 48000000;
160+
case GCLK_SOURCE_DPLL0:
161+
case GCLK_SOURCE_DPLL1:
162+
return dpll_get_frequency(index);
163+
}
164+
return 0;
165+
}
166+
64167
bool clock_get_enabled(uint8_t type, uint8_t index) {
168+
if (type == 0)
169+
return osc_enabled(index);
170+
if (type == 1)
171+
return clk_enabled(index);
172+
if (type == 2)
173+
return SysTick->CTRL & SysTick_CTRL_ENABLE_Msk;
65174
return false;
66175
}
67176

68177
bool clock_get_parent(uint8_t type, uint8_t index, uint8_t *p_type, uint8_t *p_index) {
178+
if (type == 0 && osc_enabled(index)) {
179+
if (index == GCLK_SOURCE_DPLL0 || index == GCLK_SOURCE_DPLL1) {
180+
*p_type = 0;
181+
*p_index = osc_get_source(index);
182+
return true;
183+
}
184+
return false;
185+
}
186+
if (type == 1 && index <= 47 && clk_enabled(index)) {
187+
*p_type = 0;
188+
*p_index = generator_get_source(clk_get_generator(index));
189+
return true;
190+
}
191+
if (type == 2) {
192+
switch (index) {
193+
case 0:
194+
case 1:
195+
*p_type = 0;
196+
*p_index = generator_get_source(0);
197+
return true;
198+
case 2:
199+
*p_type = 0;
200+
switch (OSC32KCTRL->RTCCTRL.bit.RTCSEL) {
201+
case 0:
202+
case 1:
203+
*p_index = GCLK_SOURCE_OSCULP32K;
204+
return true;
205+
case 4:
206+
case 5:
207+
*p_index = GCLK_SOURCE_XOSC32K;
208+
return true;
209+
}
210+
return false;
211+
}
212+
}
69213
return false;
70214
}
71215

72216
uint32_t clock_get_frequency(uint8_t type, uint8_t index) {
217+
if (type == 0) {
218+
return osc_get_frequency(index);
219+
}
220+
if (type == 1 && index <= 47 && clk_enabled(index)) {
221+
return generator_get_frequency(clk_get_generator(index));
222+
}
223+
if (type == 2) {
224+
switch (index) {
225+
case 0:
226+
return clock_get_frequency(0, generator_get_source(0)) / SysTick->LOAD;
227+
case 1:
228+
return clock_get_frequency(0, generator_get_source(0)) / MCLK->CPUDIV.bit.DIV;
229+
case 2:
230+
switch (OSC32KCTRL->RTCCTRL.bit.RTCSEL) {
231+
case 0:
232+
case 4:
233+
return 1024;
234+
case 1:
235+
case 5:
236+
return 32768;
237+
}
238+
}
239+
}
73240
return 0;
74241
}
75242

76243
uint32_t clock_get_calibration(uint8_t type, uint8_t index) {
244+
if (type == 0) {
245+
switch (index) {
246+
case GCLK_SOURCE_OSCULP32K:
247+
return OSC32KCTRL->OSCULP32K.bit.CALIB;
248+
};
249+
}
250+
if (type == 2 && index == 0) {
251+
return SysTick->LOAD + 1;
252+
}
77253
return 0;
78254
}
79255

80256
int clock_set_calibration(uint8_t type, uint8_t index, uint32_t val) {
257+
if (type == 0) {
258+
switch (index) {
259+
case GCLK_SOURCE_OSCULP32K:
260+
if (val > 0x3f)
261+
return -1;
262+
OSC32KCTRL->OSCULP32K.bit.CALIB = val;
263+
return 0;
264+
};
265+
}
266+
if (type == 2 && index == 0) {
267+
if (val < 0x1000 || val > 0x1000000)
268+
return -1;
269+
SysTick->LOAD = val - 1;
270+
return 0;
271+
}
81272
return -2;
82273
}
83274

275+
#include <instance/can0.h>
276+
#include <instance/can1.h>
277+
#include <instance/i2s.h>
278+
#include <instance/sdhc1.h>
279+
#include <instance/sercom6.h>
280+
#include <instance/sercom7.h>
281+
#include <instance/tcc4.h>
282+
283+
CLOCK_SOURCE(XOSC0);
284+
CLOCK_SOURCE(XOSC1);
285+
CLOCK_SOURCE(GCLKIN);
286+
CLOCK_SOURCE(GCLKGEN1);
287+
CLOCK_SOURCE(OSCULP32K);
288+
CLOCK_SOURCE(XOSC32K);
289+
CLOCK_SOURCE(DFLL);
290+
CLOCK_SOURCE(DPLL0);
291+
CLOCK_SOURCE(DPLL1);
292+
293+
CLOCK_GCLK_(OSCCTRL, DFLL48);
294+
CLOCK_GCLK_(OSCCTRL, FDPLL0);
295+
CLOCK_GCLK_(OSCCTRL, FDPLL1);
296+
CLOCK_GCLK_(OSCCTRL, FDPLL032K); // GCLK_OSCCTRL_FDPLL1_32K, GCLK_SDHC0_SLOW, GCLK_SDHC1_SLOW, GCLK_SERCOM[0..7]_SLOW
297+
CLOCK_GCLK(EIC);
298+
CLOCK_GCLK_(FREQM, MSR);
299+
// 6: GCLK_FREQM_REF
300+
CLOCK_GCLK_(SERCOM0, CORE);
301+
CLOCK_GCLK_(SERCOM1, CORE);
302+
CLOCK(TC0_TC1, 1, 9);
303+
CLOCK_GCLK(USB);
304+
CLOCK_GCLK_(EVSYS, 0);
305+
CLOCK_GCLK_(EVSYS, 1);
306+
CLOCK_GCLK_(EVSYS, 2);
307+
CLOCK_GCLK_(EVSYS, 3);
308+
CLOCK_GCLK_(EVSYS, 4);
309+
CLOCK_GCLK_(EVSYS, 5);
310+
CLOCK_GCLK_(EVSYS, 6);
311+
CLOCK_GCLK_(EVSYS, 7);
312+
CLOCK_GCLK_(EVSYS, 8);
313+
CLOCK_GCLK_(EVSYS, 9);
314+
CLOCK_GCLK_(EVSYS, 10);
315+
CLOCK_GCLK_(EVSYS, 11);
316+
CLOCK_GCLK_(SERCOM2, CORE);
317+
CLOCK_GCLK_(SERCOM3, CORE);
318+
CLOCK(TCC0_TCC1, 1, 25);
319+
CLOCK(TC2_TC3, 1, 26);
320+
CLOCK_GCLK(CAN0);
321+
CLOCK_GCLK(CAN1);
322+
CLOCK(TCC2_TCC3, 1, 29);
323+
CLOCK(TC4_TC5, 1, 30);
324+
CLOCK_GCLK(PDEC);
325+
CLOCK_GCLK(AC);
326+
CLOCK_GCLK(CCL);
327+
CLOCK_GCLK_(SERCOM4, CORE);
328+
CLOCK_GCLK_(SERCOM5, CORE);
329+
CLOCK_GCLK_(SERCOM6, CORE);
330+
CLOCK_GCLK_(SERCOM7, CORE);
331+
CLOCK_GCLK(TCC4);
332+
CLOCK(TC6_TC7, 1, 39);
333+
CLOCK_GCLK(ADC0);
334+
CLOCK_GCLK(ADC1);
335+
CLOCK_GCLK(DAC);
336+
CLOCK_GCLK_(I2S, 0);
337+
CLOCK_GCLK_(I2S, 1);
338+
CLOCK_GCLK(SDHC0);
339+
CLOCK_GCLK(SDHC1);
340+
// 47: GCLK_CM4_TRACE
341+
342+
CLOCK(SYSTICK, 2, 0);
343+
CLOCK(CPU, 2, 1);
344+
CLOCK(RTC, 2, 2);
345+
346+
84347
STATIC const mp_rom_map_elem_t samd_clock_global_dict_table[] = {
348+
CLOCK_ENTRY(XOSC0),
349+
CLOCK_ENTRY(XOSC1),
350+
CLOCK_ENTRY(GCLKIN),
351+
CLOCK_ENTRY(GCLKGEN1),
352+
CLOCK_ENTRY(OSCULP32K),
353+
CLOCK_ENTRY(XOSC32K),
354+
CLOCK_ENTRY(DFLL),
355+
CLOCK_ENTRY(DPLL0),
356+
CLOCK_ENTRY(DPLL1),
357+
358+
CLOCK_ENTRY_(OSCCTRL, DFLL48),
359+
CLOCK_ENTRY_(OSCCTRL, FDPLL0),
360+
CLOCK_ENTRY_(OSCCTRL, FDPLL1),
361+
CLOCK_ENTRY_(OSCCTRL, FDPLL032K),
362+
CLOCK_ENTRY(EIC),
363+
CLOCK_ENTRY_(FREQM, MSR),
364+
CLOCK_ENTRY_(SERCOM0, CORE),
365+
CLOCK_ENTRY_(SERCOM1, CORE),
366+
CLOCK_ENTRY(TC0_TC1),
367+
CLOCK_ENTRY(USB),
368+
CLOCK_ENTRY_(EVSYS, 0),
369+
CLOCK_ENTRY_(EVSYS, 1),
370+
CLOCK_ENTRY_(EVSYS, 2),
371+
CLOCK_ENTRY_(EVSYS, 3),
372+
CLOCK_ENTRY_(EVSYS, 4),
373+
CLOCK_ENTRY_(EVSYS, 5),
374+
CLOCK_ENTRY_(EVSYS, 6),
375+
CLOCK_ENTRY_(EVSYS, 7),
376+
CLOCK_ENTRY_(EVSYS, 8),
377+
CLOCK_ENTRY_(EVSYS, 9),
378+
CLOCK_ENTRY_(EVSYS, 10),
379+
CLOCK_ENTRY_(EVSYS, 11),
380+
CLOCK_ENTRY_(SERCOM2, CORE),
381+
CLOCK_ENTRY_(SERCOM3, CORE),
382+
CLOCK_ENTRY(TCC0_TCC1),
383+
CLOCK_ENTRY(TC2_TC3),
384+
CLOCK_ENTRY(CAN0),
385+
CLOCK_ENTRY(CAN1),
386+
CLOCK_ENTRY(TCC2_TCC3),
387+
CLOCK_ENTRY(TC4_TC5),
388+
CLOCK_ENTRY(PDEC),
389+
CLOCK_ENTRY(AC),
390+
CLOCK_ENTRY(CCL),
391+
CLOCK_ENTRY_(SERCOM4, CORE),
392+
CLOCK_ENTRY_(SERCOM5, CORE),
393+
CLOCK_ENTRY_(SERCOM6, CORE),
394+
CLOCK_ENTRY_(SERCOM7, CORE),
395+
CLOCK_ENTRY(TCC4),
396+
CLOCK_ENTRY(TC6_TC7),
397+
CLOCK_ENTRY(ADC0),
398+
CLOCK_ENTRY(ADC1),
399+
CLOCK_ENTRY(DAC),
400+
CLOCK_ENTRY_(I2S, 0),
401+
CLOCK_ENTRY_(I2S, 1),
402+
CLOCK_ENTRY(SDHC0),
403+
CLOCK_ENTRY(SDHC1),
404+
405+
CLOCK_ENTRY(SYSTICK),
406+
CLOCK_ENTRY(CPU),
407+
CLOCK_ENTRY(RTC),
85408
};
86409
MP_DEFINE_CONST_DICT(samd_clock_globals, samd_clock_global_dict_table);

0 commit comments

Comments
 (0)