blob: 130f63ad2c37e20eda168a9461a994181bdac5f2 [file] [log] [blame]
Kévin Redon4cd3f7d2019-01-24 17:57:13 +01001
2/**
3 * \file
4 *
5 * \brief SAM Serial Communication Interface
6 *
7 * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
8 *
9 * \asf_license_start
10 *
11 * \page License
12 *
13 * Subject to your compliance with these terms, you may use Microchip
14 * software and any derivatives exclusively with Microchip products.
15 * It is your responsibility to comply with third party license terms applicable
16 * to your use of third party software (including open source software) that
17 * may accompany Microchip software.
18 *
19 * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
20 * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
21 * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
22 * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
23 * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
24 * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
25 * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
26 * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
27 * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
28 * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
29 * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
30 *
31 * \asf_license_stop
32 *
33 */
34#include <hpl_dma.h>
35#include <hpl_i2c_m_async.h>
36#include <hpl_i2c_m_sync.h>
37#include <hpl_i2c_s_async.h>
38#include <hpl_sercom_config.h>
39#include <hpl_spi_m_async.h>
40#include <hpl_spi_m_sync.h>
41#include <hpl_spi_s_async.h>
42#include <hpl_spi_s_sync.h>
43#include <hpl_usart_async.h>
44#include <hpl_usart_sync.h>
45#include <utils.h>
46#include <utils_assert.h>
47
48#ifndef CONF_SERCOM_0_USART_ENABLE
49#define CONF_SERCOM_0_USART_ENABLE 0
50#endif
51#ifndef CONF_SERCOM_1_USART_ENABLE
52#define CONF_SERCOM_1_USART_ENABLE 0
53#endif
54#ifndef CONF_SERCOM_2_USART_ENABLE
55#define CONF_SERCOM_2_USART_ENABLE 0
56#endif
57#ifndef CONF_SERCOM_3_USART_ENABLE
58#define CONF_SERCOM_3_USART_ENABLE 0
59#endif
60#ifndef CONF_SERCOM_4_USART_ENABLE
61#define CONF_SERCOM_4_USART_ENABLE 0
62#endif
63#ifndef CONF_SERCOM_5_USART_ENABLE
64#define CONF_SERCOM_5_USART_ENABLE 0
65#endif
66#ifndef CONF_SERCOM_6_USART_ENABLE
67#define CONF_SERCOM_6_USART_ENABLE 0
68#endif
69#ifndef CONF_SERCOM_7_USART_ENABLE
70#define CONF_SERCOM_7_USART_ENABLE 0
71#endif
72
73/** Amount of SERCOM that is used as USART. */
74#define SERCOM_USART_AMOUNT \
75 (CONF_SERCOM_0_USART_ENABLE + CONF_SERCOM_1_USART_ENABLE + CONF_SERCOM_2_USART_ENABLE + CONF_SERCOM_3_USART_ENABLE \
76 + CONF_SERCOM_4_USART_ENABLE + CONF_SERCOM_5_USART_ENABLE + CONF_SERCOM_6_USART_ENABLE \
77 + CONF_SERCOM_7_USART_ENABLE)
78
79/**
80 * \brief Macro is used to fill usart configuration structure based on
81 * its number
82 *
83 * \param[in] n The number of structures
84 */
85#define SERCOM_CONFIGURATION(n) \
86 { \
87 n, \
88 SERCOM_USART_CTRLA_MODE(CONF_SERCOM_##n##_USART_MODE) \
89 | (CONF_SERCOM_##n##_USART_RUNSTDBY << SERCOM_USART_CTRLA_RUNSTDBY_Pos) \
90 | (CONF_SERCOM_##n##_USART_IBON << SERCOM_USART_CTRLA_IBON_Pos) \
91 | (CONF_SERCOM_##n##_USART_TXINV << SERCOM_USART_CTRLA_TXINV_Pos) \
92 | (CONF_SERCOM_##n##_USART_RXINV << SERCOM_USART_CTRLA_RXINV_Pos) \
93 | SERCOM_USART_CTRLA_SAMPR(CONF_SERCOM_##n##_USART_SAMPR) \
94 | SERCOM_USART_CTRLA_TXPO(CONF_SERCOM_##n##_USART_TXPO) \
95 | SERCOM_USART_CTRLA_RXPO(CONF_SERCOM_##n##_USART_RXPO) \
96 | SERCOM_USART_CTRLA_SAMPA(CONF_SERCOM_##n##_USART_SAMPA) \
97 | SERCOM_USART_CTRLA_FORM(CONF_SERCOM_##n##_USART_FORM) \
98 | (CONF_SERCOM_##n##_USART_CMODE << SERCOM_USART_CTRLA_CMODE_Pos) \
99 | (CONF_SERCOM_##n##_USART_CPOL << SERCOM_USART_CTRLA_CPOL_Pos) \
100 | (CONF_SERCOM_##n##_USART_DORD << SERCOM_USART_CTRLA_DORD_Pos), \
101 SERCOM_USART_CTRLB_CHSIZE(CONF_SERCOM_##n##_USART_CHSIZE) \
102 | (CONF_SERCOM_##n##_USART_SBMODE << SERCOM_USART_CTRLB_SBMODE_Pos) \
103 | (CONF_SERCOM_##n##_USART_CLODEN << SERCOM_USART_CTRLB_COLDEN_Pos) \
104 | (CONF_SERCOM_##n##_USART_SFDE << SERCOM_USART_CTRLB_SFDE_Pos) \
105 | (CONF_SERCOM_##n##_USART_ENC << SERCOM_USART_CTRLB_ENC_Pos) \
106 | (CONF_SERCOM_##n##_USART_PMODE << SERCOM_USART_CTRLB_PMODE_Pos) \
107 | (CONF_SERCOM_##n##_USART_TXEN << SERCOM_USART_CTRLB_TXEN_Pos) \
108 | (CONF_SERCOM_##n##_USART_RXEN << SERCOM_USART_CTRLB_RXEN_Pos), \
109 SERCOM_USART_CTRLC_GTIME(CONF_SERCOM_##n##_USART_GTIME) \
110 | (CONF_SERCOM_##n##_USART_DSNACK << SERCOM_USART_CTRLC_DSNACK_Pos) \
111 | (CONF_SERCOM_##n##_USART_INACK << SERCOM_USART_CTRLC_INACK_Pos) \
112 | SERCOM_USART_CTRLC_MAXITER(CONF_SERCOM_##n##_USART_MAXITER), \
113 (uint16_t)(CONF_SERCOM_##n##_USART_BAUD_RATE), CONF_SERCOM_##n##_USART_FRACTIONAL, \
114 CONF_SERCOM_##n##_USART_RECEIVE_PULSE_LENGTH, CONF_SERCOM_##n##_USART_DEBUG_STOP_MODE, \
115 }
116
117/**
118 * \brief SERCOM USART configuration type
119 */
120struct usart_configuration {
121 uint8_t number;
122 hri_sercomusart_ctrla_reg_t ctrl_a;
123 hri_sercomusart_ctrlb_reg_t ctrl_b;
124 hri_sercomusart_ctrlc_reg_t ctrl_c;
125 hri_sercomusart_baud_reg_t baud;
126 uint8_t fractional;
127 hri_sercomusart_rxpl_reg_t rxpl;
128 hri_sercomusart_dbgctrl_reg_t debug_ctrl;
129};
130
131#if SERCOM_USART_AMOUNT < 1
132/** Dummy array to pass compiling. */
133static struct usart_configuration _usarts[1] = {{0}};
134#else
135/**
136 * \brief Array of SERCOM USART configurations
137 */
138static struct usart_configuration _usarts[] = {
139#if CONF_SERCOM_0_USART_ENABLE == 1
140 SERCOM_CONFIGURATION(0),
141#endif
142#if CONF_SERCOM_1_USART_ENABLE == 1
143 SERCOM_CONFIGURATION(1),
144#endif
145#if CONF_SERCOM_2_USART_ENABLE == 1
146 SERCOM_CONFIGURATION(2),
147#endif
148#if CONF_SERCOM_3_USART_ENABLE == 1
149 SERCOM_CONFIGURATION(3),
150#endif
151#if CONF_SERCOM_4_USART_ENABLE == 1
152 SERCOM_CONFIGURATION(4),
153#endif
154#if CONF_SERCOM_5_USART_ENABLE == 1
155 SERCOM_CONFIGURATION(5),
156#endif
157#if CONF_SERCOM_6_USART_ENABLE == 1
158 SERCOM_CONFIGURATION(6),
159#endif
160#if CONF_SERCOM_7_USART_ENABLE == 1
161 SERCOM_CONFIGURATION(7),
162#endif
163};
164#endif
165
166static uint8_t _get_sercom_index(const void *const hw);
167static uint8_t _sercom_get_irq_num(const void *const hw);
168static void _sercom_init_irq_param(const void *const hw, void *dev);
169static uint8_t _sercom_get_hardware_index(const void *const hw);
170
171static int32_t _usart_init(void *const hw);
172static inline void _usart_deinit(void *const hw);
173static uint16_t _usart_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples,
174 const enum usart_baud_rate_mode mode, const uint8_t fraction);
175static void _usart_set_baud_rate(void *const hw, const uint32_t baud_rate);
176static void _usart_set_data_order(void *const hw, const enum usart_data_order order);
177static void _usart_set_mode(void *const hw, const enum usart_mode mode);
178static void _usart_set_parity(void *const hw, const enum usart_parity parity);
179static void _usart_set_stop_bits(void *const hw, const enum usart_stop_bits stop_bits);
180static void _usart_set_character_size(void *const hw, const enum usart_character_size size);
181
182/**
183 * \brief Initialize synchronous SERCOM USART
184 */
185int32_t _usart_sync_init(struct _usart_sync_device *const device, void *const hw)
186{
187 ASSERT(device);
188
189 device->hw = hw;
190
191 return _usart_init(hw);
192}
193
194/**
195 * \brief Initialize asynchronous SERCOM USART
196 */
197int32_t _usart_async_init(struct _usart_async_device *const device, void *const hw)
198{
199 int32_t init_status;
200
201 ASSERT(device);
202
203 init_status = _usart_init(hw);
204 if (init_status) {
205 return init_status;
206 }
207 device->hw = hw;
208 _sercom_init_irq_param(hw, (void *)device);
209 uint8_t irq = _sercom_get_irq_num(hw);
210 for (uint32_t i = 0; i < 4; i++) {
211 NVIC_DisableIRQ((IRQn_Type)irq);
212 NVIC_ClearPendingIRQ((IRQn_Type)irq);
213 NVIC_EnableIRQ((IRQn_Type)irq);
214 irq++;
215 }
216 return ERR_NONE;
217}
218
219/**
220 * \brief De-initialize SERCOM USART
221 */
222void _usart_sync_deinit(struct _usart_sync_device *const device)
223{
224 _usart_deinit(device->hw);
225}
226
227/**
228 * \brief De-initialize SERCOM USART
229 */
230void _usart_async_deinit(struct _usart_async_device *const device)
231{
232 NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(device->hw));
233 _usart_deinit(device->hw);
234}
235
236/**
237 * \brief Calculate baud rate register value
238 */
239uint16_t _usart_sync_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples,
240 const enum usart_baud_rate_mode mode, const uint8_t fraction)
241{
242 return _usart_calculate_baud_rate(baud, clock_rate, samples, mode, fraction);
243}
244
245/**
246 * \brief Calculate baud rate register value
247 */
248uint16_t _usart_async_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples,
249 const enum usart_baud_rate_mode mode, const uint8_t fraction)
250{
251 return _usart_calculate_baud_rate(baud, clock_rate, samples, mode, fraction);
252}
253
254/**
255 * \brief Enable SERCOM module
256 */
257void _usart_sync_enable(struct _usart_sync_device *const device)
258{
259 hri_sercomusart_set_CTRLA_ENABLE_bit(device->hw);
260}
261
262/**
263 * \brief Enable SERCOM module
264 */
265void _usart_async_enable(struct _usart_async_device *const device)
266{
267 hri_sercomusart_set_CTRLA_ENABLE_bit(device->hw);
268}
269
270/**
271 * \brief Disable SERCOM module
272 */
273void _usart_sync_disable(struct _usart_sync_device *const device)
274{
275 hri_sercomusart_clear_CTRLA_ENABLE_bit(device->hw);
276}
277
278/**
279 * \brief Disable SERCOM module
280 */
281void _usart_async_disable(struct _usart_async_device *const device)
282{
283 hri_sercomusart_clear_CTRLA_ENABLE_bit(device->hw);
284}
285
286/**
287 * \brief Set baud rate
288 */
289void _usart_sync_set_baud_rate(struct _usart_sync_device *const device, const uint32_t baud_rate)
290{
291 _usart_set_baud_rate(device->hw, baud_rate);
292}
293
294/**
295 * \brief Set baud rate
296 */
297void _usart_async_set_baud_rate(struct _usart_async_device *const device, const uint32_t baud_rate)
298{
299 _usart_set_baud_rate(device->hw, baud_rate);
300}
301
302/**
303 * \brief Set data order
304 */
305void _usart_sync_set_data_order(struct _usart_sync_device *const device, const enum usart_data_order order)
306{
307 _usart_set_data_order(device->hw, order);
308}
309
310/**
311 * \brief Set data order
312 */
313void _usart_async_set_data_order(struct _usart_async_device *const device, const enum usart_data_order order)
314{
315 _usart_set_data_order(device->hw, order);
316}
317
318/**
319 * \brief Set mode
320 */
321void _usart_sync_set_mode(struct _usart_sync_device *const device, const enum usart_mode mode)
322{
323 _usart_set_mode(device->hw, mode);
324}
325
326/**
327 * \brief Set mode
328 */
329void _usart_async_set_mode(struct _usart_async_device *const device, const enum usart_mode mode)
330{
331 _usart_set_mode(device->hw, mode);
332}
333
334/**
335 * \brief Set parity
336 */
337void _usart_sync_set_parity(struct _usart_sync_device *const device, const enum usart_parity parity)
338{
339 _usart_set_parity(device->hw, parity);
340}
341
342/**
343 * \brief Set parity
344 */
345void _usart_async_set_parity(struct _usart_async_device *const device, const enum usart_parity parity)
346{
347 _usart_set_parity(device->hw, parity);
348}
349
350/**
351 * \brief Set stop bits mode
352 */
353void _usart_sync_set_stop_bits(struct _usart_sync_device *const device, const enum usart_stop_bits stop_bits)
354{
355 _usart_set_stop_bits(device->hw, stop_bits);
356}
357
358/**
359 * \brief Set stop bits mode
360 */
361void _usart_async_set_stop_bits(struct _usart_async_device *const device, const enum usart_stop_bits stop_bits)
362{
363 _usart_set_stop_bits(device->hw, stop_bits);
364}
365
366/**
367 * \brief Set character size
368 */
369void _usart_sync_set_character_size(struct _usart_sync_device *const device, const enum usart_character_size size)
370{
371 _usart_set_character_size(device->hw, size);
372}
373
374/**
375 * \brief Set character size
376 */
377void _usart_async_set_character_size(struct _usart_async_device *const device, const enum usart_character_size size)
378{
379 _usart_set_character_size(device->hw, size);
380}
381
382/**
383 * \brief Retrieve SERCOM usart status
384 */
385uint32_t _usart_sync_get_status(const struct _usart_sync_device *const device)
386{
387 return hri_sercomusart_read_STATUS_reg(device->hw);
388}
389
390/**
391 * \brief Retrieve SERCOM usart status
392 */
393uint32_t _usart_async_get_status(const struct _usart_async_device *const device)
394{
395 return hri_sercomusart_read_STATUS_reg(device->hw);
396}
397
398/**
399 * \brief Write a byte to the given SERCOM USART instance
400 */
401void _usart_sync_write_byte(struct _usart_sync_device *const device, uint8_t data)
402{
403 hri_sercomusart_write_DATA_reg(device->hw, data);
404}
405
406/**
407 * \brief Write a byte to the given SERCOM USART instance
408 */
409void _usart_async_write_byte(struct _usart_async_device *const device, uint8_t data)
410{
411 hri_sercomusart_write_DATA_reg(device->hw, data);
412}
413
414/**
415 * \brief Read a byte from the given SERCOM USART instance
416 */
417uint8_t _usart_sync_read_byte(const struct _usart_sync_device *const device)
418{
419 return hri_sercomusart_read_DATA_reg(device->hw);
420}
421
422/**
423 * \brief Check if USART is ready to send next byte
424 */
425bool _usart_sync_is_ready_to_send(const struct _usart_sync_device *const device)
426{
427 return hri_sercomusart_get_interrupt_DRE_bit(device->hw);
428}
429
430/**
431 * \brief Check if USART transmission complete
432 */
433bool _usart_sync_is_transmit_done(const struct _usart_sync_device *const device)
434{
435 return hri_sercomusart_get_interrupt_TXC_bit(device->hw);
436}
437
438/**
439 * \brief Check if USART is ready to send next byte
440 */
441bool _usart_async_is_byte_sent(const struct _usart_async_device *const device)
442{
443 return hri_sercomusart_get_interrupt_DRE_bit(device->hw);
444}
445
446/**
447 * \brief Check if there is data received by USART
448 */
449bool _usart_sync_is_byte_received(const struct _usart_sync_device *const device)
450{
451 return hri_sercomusart_get_interrupt_RXC_bit(device->hw);
452}
453
454/**
455 * \brief Set the state of flow control pins
456 */
457void _usart_sync_set_flow_control_state(struct _usart_sync_device *const device,
458 const union usart_flow_control_state state)
459{
460 (void)device;
461 (void)state;
462}
463
464/**
465 * \brief Set the state of flow control pins
466 */
467void _usart_async_set_flow_control_state(struct _usart_async_device *const device,
468 const union usart_flow_control_state state)
469{
470 (void)device;
471 (void)state;
472}
473
474/**
475 * \brief Retrieve the state of flow control pins
476 */
477union usart_flow_control_state _usart_sync_get_flow_control_state(const struct _usart_sync_device *const device)
478{
479 (void)device;
480 union usart_flow_control_state state;
481
482 state.value = 0;
483 state.bit.unavailable = 1;
484 return state;
485}
486
487/**
488 * \brief Retrieve the state of flow control pins
489 */
490union usart_flow_control_state _usart_async_get_flow_control_state(const struct _usart_async_device *const device)
491{
492 (void)device;
493 union usart_flow_control_state state;
494
495 state.value = 0;
496 state.bit.unavailable = 1;
497 return state;
498}
499
500/**
501 * \brief Enable data register empty interrupt
502 */
503void _usart_async_enable_byte_sent_irq(struct _usart_async_device *const device)
504{
505 hri_sercomusart_set_INTEN_DRE_bit(device->hw);
506}
507
508/**
509 * \brief Enable transmission complete interrupt
510 */
511void _usart_async_enable_tx_done_irq(struct _usart_async_device *const device)
512{
513 hri_sercomusart_set_INTEN_TXC_bit(device->hw);
514}
515
516/**
517 * \brief Retrieve ordinal number of the given sercom hardware instance
518 */
519static uint8_t _sercom_get_hardware_index(const void *const hw)
520{
521 Sercom *const sercom_modules[] = SERCOM_INSTS;
522 /* Find index for SERCOM instance. */
523 for (uint32_t i = 0; i < SERCOM_INST_NUM; i++) {
524 if ((uint32_t)hw == (uint32_t)sercom_modules[i]) {
525 return i;
526 }
527 }
528 return 0;
529}
530
531/**
532 * \brief Retrieve ordinal number of the given SERCOM USART hardware instance
533 */
534uint8_t _usart_sync_get_hardware_index(const struct _usart_sync_device *const device)
535{
536 return _sercom_get_hardware_index(device->hw);
537}
538
539/**
540 * \brief Retrieve ordinal number of the given SERCOM USART hardware instance
541 */
542uint8_t _usart_async_get_hardware_index(const struct _usart_async_device *const device)
543{
544 return _sercom_get_hardware_index(device->hw);
545}
546
547/**
548 * \brief Enable/disable USART interrupt
549 */
550void _usart_async_set_irq_state(struct _usart_async_device *const device, const enum _usart_async_callback_type type,
551 const bool state)
552{
553 ASSERT(device);
554
555 if (USART_ASYNC_BYTE_SENT == type || USART_ASYNC_TX_DONE == type) {
556 hri_sercomusart_write_INTEN_DRE_bit(device->hw, state);
557 hri_sercomusart_write_INTEN_TXC_bit(device->hw, state);
558 } else if (USART_ASYNC_RX_DONE == type) {
559 hri_sercomusart_write_INTEN_RXC_bit(device->hw, state);
560 } else if (USART_ASYNC_ERROR == type) {
561 hri_sercomusart_write_INTEN_ERROR_bit(device->hw, state);
562 }
563}
564
565/**
566 * \internal Retrieve ordinal number of the given sercom hardware instance
567 *
568 * \param[in] hw The pointer to hardware instance
569
570 * \return The ordinal number of the given sercom hardware instance
571 */
572static uint8_t _get_sercom_index(const void *const hw)
573{
574 uint8_t sercom_offset = _sercom_get_hardware_index(hw);
575 uint8_t i;
576
577 for (i = 0; i < ARRAY_SIZE(_usarts); i++) {
578 if (_usarts[i].number == sercom_offset) {
579 return i;
580 }
581 }
582
583 ASSERT(false);
584 return 0;
585}
586
587/**
588 * \brief Init irq param with the given sercom hardware instance
589 */
590static void _sercom_init_irq_param(const void *const hw, void *dev)
591{
592}
593
594/**
595 * \internal Initialize SERCOM USART
596 *
597 * \param[in] hw The pointer to hardware instance
598 *
599 * \return The status of initialization
600 */
601static int32_t _usart_init(void *const hw)
602{
603 uint8_t i = _get_sercom_index(hw);
604
605 if (!hri_sercomusart_is_syncing(hw, SERCOM_USART_SYNCBUSY_SWRST)) {
606 uint32_t mode = _usarts[i].ctrl_a & SERCOM_USART_CTRLA_MODE_Msk;
607 if (hri_sercomusart_get_CTRLA_reg(hw, SERCOM_USART_CTRLA_ENABLE)) {
608 hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
609 hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
610 }
611 hri_sercomusart_write_CTRLA_reg(hw, SERCOM_USART_CTRLA_SWRST | mode);
612 }
613 hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_SWRST);
614
615 hri_sercomusart_write_CTRLA_reg(hw, _usarts[i].ctrl_a);
616 hri_sercomusart_write_CTRLB_reg(hw, _usarts[i].ctrl_b);
617 hri_sercomusart_write_CTRLC_reg(hw, _usarts[i].ctrl_c);
618 if ((_usarts[i].ctrl_a & SERCOM_USART_CTRLA_SAMPR(0x1)) || (_usarts[i].ctrl_a & SERCOM_USART_CTRLA_SAMPR(0x3))) {
619 ((Sercom *)hw)->USART.BAUD.FRAC.BAUD = _usarts[i].baud;
620 ((Sercom *)hw)->USART.BAUD.FRAC.FP = _usarts[i].fractional;
621 } else {
622 hri_sercomusart_write_BAUD_reg(hw, _usarts[i].baud);
623 }
624
625 hri_sercomusart_write_RXPL_reg(hw, _usarts[i].rxpl);
626 hri_sercomusart_write_DBGCTRL_reg(hw, _usarts[i].debug_ctrl);
627
628 return ERR_NONE;
629}
630
631/**
632 * \internal De-initialize SERCOM USART
633 *
634 * \param[in] hw The pointer to hardware instance
635 */
636static inline void _usart_deinit(void *const hw)
637{
638 hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
639 hri_sercomusart_set_CTRLA_SWRST_bit(hw);
640}
641
642/**
643 * \internal Calculate baud rate register value
644 *
645 * \param[in] baud Required baud rate
646 * \param[in] clock_rate SERCOM clock frequency
647 * \param[in] samples The number of samples
648 * \param[in] mode USART mode
649 * \param[in] fraction A fraction value
650 *
651 * \return Calculated baud rate register value
652 */
653static uint16_t _usart_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples,
654 const enum usart_baud_rate_mode mode, const uint8_t fraction)
655{
656 if (USART_BAUDRATE_ASYNCH_ARITHMETIC == mode) {
657 return 65536 - ((uint64_t)65536 * samples * baud) / clock_rate;
658 }
659
660 if (USART_BAUDRATE_ASYNCH_FRACTIONAL == mode) {
661 return clock_rate / baud / samples + SERCOM_USART_BAUD_FRACFP_FP(fraction);
662 }
663
664 if (USART_BAUDRATE_SYNCH == mode) {
665 return clock_rate / baud / 2 - 1;
666 }
667
668 return 0;
669}
670
671/**
672 * \internal Set baud rate
673 *
674 * \param[in] device The pointer to USART device instance
675 * \param[in] baud_rate A baud rate to set
676 */
677static void _usart_set_baud_rate(void *const hw, const uint32_t baud_rate)
678{
679 bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
680
681 hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
682
683 CRITICAL_SECTION_ENTER()
684 hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
685 hri_sercomusart_write_BAUD_reg(hw, baud_rate);
686 CRITICAL_SECTION_LEAVE()
687
688 hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled);
689}
690
691/**
692 * \internal Set data order
693 *
694 * \param[in] device The pointer to USART device instance
695 * \param[in] order A data order to set
696 */
697static void _usart_set_data_order(void *const hw, const enum usart_data_order order)
698{
699 bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
700
701 hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
702
703 CRITICAL_SECTION_ENTER()
704 hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
705 hri_sercomusart_write_CTRLA_DORD_bit(hw, order);
706 CRITICAL_SECTION_LEAVE()
707
708 hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled);
709}
710
711/**
712 * \internal Set mode
713 *
714 * \param[in] device The pointer to USART device instance
715 * \param[in] mode A mode to set
716 */
717static void _usart_set_mode(void *const hw, const enum usart_mode mode)
718{
719 bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
720
721 hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
722
723 CRITICAL_SECTION_ENTER()
724 hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
725 hri_sercomusart_write_CTRLA_CMODE_bit(hw, mode);
726 CRITICAL_SECTION_LEAVE()
727
728 hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled);
729}
730
731/**
732 * \internal Set parity
733 *
734 * \param[in] device The pointer to USART device instance
735 * \param[in] parity A parity to set
736 */
737static void _usart_set_parity(void *const hw, const enum usart_parity parity)
738{
739 bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
740
741 hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
742
743 CRITICAL_SECTION_ENTER()
744 hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
745
746 if (USART_PARITY_NONE != parity) {
747 hri_sercomusart_set_CTRLA_FORM_bf(hw, 1);
748 } else {
749 hri_sercomusart_clear_CTRLA_FORM_bf(hw, 1);
750 }
751
752 hri_sercomusart_write_CTRLB_PMODE_bit(hw, parity);
753 CRITICAL_SECTION_LEAVE()
754
755 hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled);
756}
757
758/**
759 * \internal Set stop bits mode
760 *
761 * \param[in] device The pointer to USART device instance
762 * \param[in] stop_bits A stop bits mode to set
763 */
764static void _usart_set_stop_bits(void *const hw, const enum usart_stop_bits stop_bits)
765{
766 bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
767
768 hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
769
770 CRITICAL_SECTION_ENTER()
771 hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
772 hri_sercomusart_write_CTRLB_SBMODE_bit(hw, stop_bits);
773 CRITICAL_SECTION_LEAVE()
774
775 hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled);
776}
777
778/**
779 * \internal Set character size
780 *
781 * \param[in] device The pointer to USART device instance
782 * \param[in] size A character size to set
783 */
784static void _usart_set_character_size(void *const hw, const enum usart_character_size size)
785{
786 bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
787
788 hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
789
790 CRITICAL_SECTION_ENTER()
791 hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
792 hri_sercomusart_write_CTRLB_CHSIZE_bf(hw, size);
793 CRITICAL_SECTION_LEAVE()
794
795 if (enabled) {
796 hri_sercomusart_set_CTRLA_ENABLE_bit(hw);
797 }
798}
799
800 /* Sercom I2C implementation */
801
802#ifndef CONF_SERCOM_0_I2CM_ENABLE
803#define CONF_SERCOM_0_I2CM_ENABLE 0
804#endif
805#ifndef CONF_SERCOM_1_I2CM_ENABLE
806#define CONF_SERCOM_1_I2CM_ENABLE 0
807#endif
808#ifndef CONF_SERCOM_2_I2CM_ENABLE
809#define CONF_SERCOM_2_I2CM_ENABLE 0
810#endif
811#ifndef CONF_SERCOM_3_I2CM_ENABLE
812#define CONF_SERCOM_3_I2CM_ENABLE 0
813#endif
814#ifndef CONF_SERCOM_4_I2CM_ENABLE
815#define CONF_SERCOM_4_I2CM_ENABLE 0
816#endif
817#ifndef CONF_SERCOM_5_I2CM_ENABLE
818#define CONF_SERCOM_5_I2CM_ENABLE 0
819#endif
820#ifndef CONF_SERCOM_6_I2CM_ENABLE
821#define CONF_SERCOM_6_I2CM_ENABLE 0
822#endif
823#ifndef CONF_SERCOM_7_I2CM_ENABLE
824#define CONF_SERCOM_7_I2CM_ENABLE 0
825#endif
826
827/** Amount of SERCOM that is used as I2C Master. */
828#define SERCOM_I2CM_AMOUNT \
829 (CONF_SERCOM_0_I2CM_ENABLE + CONF_SERCOM_1_I2CM_ENABLE + CONF_SERCOM_2_I2CM_ENABLE + CONF_SERCOM_3_I2CM_ENABLE \
830 + CONF_SERCOM_4_I2CM_ENABLE + CONF_SERCOM_5_I2CM_ENABLE + CONF_SERCOM_6_I2CM_ENABLE + CONF_SERCOM_7_I2CM_ENABLE)
831
832/**
833 * \brief Macro is used to fill i2cm configuration structure based on
834 * its number
835 *
836 * \param[in] n The number of structures
837 */
838#define I2CM_CONFIGURATION(n) \
839 { \
840 (n), \
841 (SERCOM_I2CM_CTRLA_MODE_I2C_MASTER) | (CONF_SERCOM_##n##_I2CM_RUNSTDBY << SERCOM_I2CM_CTRLA_RUNSTDBY_Pos) \
842 | (CONF_SERCOM_##n##_I2CM_SPEED << SERCOM_I2CM_CTRLA_SPEED_Pos) \
843 | (CONF_SERCOM_##n##_I2CM_MEXTTOEN << SERCOM_I2CM_CTRLA_MEXTTOEN_Pos) \
844 | (CONF_SERCOM_##n##_I2CM_SEXTTOEN << SERCOM_I2CM_CTRLA_SEXTTOEN_Pos) \
845 | (CONF_SERCOM_##n##_I2CM_INACTOUT << SERCOM_I2CM_CTRLA_INACTOUT_Pos) \
846 | (CONF_SERCOM_##n##_I2CM_LOWTOUT << SERCOM_I2CM_CTRLA_LOWTOUTEN_Pos) \
847 | (CONF_SERCOM_##n##_I2CM_SDAHOLD << SERCOM_I2CM_CTRLA_SDAHOLD_Pos), \
848 SERCOM_I2CM_CTRLB_SMEN, (uint32_t)(CONF_SERCOM_##n##_I2CM_BAUD_RATE), \
849 CONF_SERCOM_##n##_I2CM_DEBUG_STOP_MODE, CONF_SERCOM_##n##_I2CM_TRISE, CONF_GCLK_SERCOM##n##_CORE_FREQUENCY \
850 }
851
852#define ERROR_FLAG (1 << 7)
853#define SB_FLAG (1 << 1)
854#define MB_FLAG (1 << 0)
855
856#define CMD_STOP 0x3
857#define I2C_IDLE 0x1
858#define I2C_SM 0x0
859#define I2C_FM 0x1
860#define I2C_HS 0x2
861#define TEN_ADDR_FRAME 0x78
862#define TEN_ADDR_MASK 0x3ff
863#define SEVEN_ADDR_MASK 0x7f
864
865/**
866 * \brief SERCOM I2CM configuration type
867 */
868struct i2cm_configuration {
869 uint8_t number;
870 hri_sercomi2cm_ctrla_reg_t ctrl_a;
871 hri_sercomi2cm_ctrlb_reg_t ctrl_b;
872 hri_sercomi2cm_baud_reg_t baud;
873 hri_sercomi2cm_dbgctrl_reg_t dbgctrl;
874 uint16_t trise;
875 uint32_t clk; /* SERCOM peripheral clock frequency */
876};
877
878static inline void _i2c_m_enable_implementation(void *hw);
879static int32_t _i2c_m_sync_init_impl(struct _i2c_m_service *const service, void *const hw);
880
881#if SERCOM_I2CM_AMOUNT < 1
882/** Dummy array to pass compiling. */
883static struct i2cm_configuration _i2cms[1] = {{0}};
884#else
885/**
886 * \brief Array of SERCOM I2CM configurations
887 */
888static struct i2cm_configuration _i2cms[] = {
889#if CONF_SERCOM_0_I2CM_ENABLE == 1
890 I2CM_CONFIGURATION(0),
891#endif
892#if CONF_SERCOM_1_I2CM_ENABLE == 1
893 I2CM_CONFIGURATION(1),
894#endif
895#if CONF_SERCOM_2_I2CM_ENABLE == 1
896 I2CM_CONFIGURATION(2),
897#endif
898#if CONF_SERCOM_3_I2CM_ENABLE == 1
899 I2CM_CONFIGURATION(3),
900#endif
901#if CONF_SERCOM_4_I2CM_ENABLE == 1
902 I2CM_CONFIGURATION(4),
903#endif
904#if CONF_SERCOM_5_I2CM_ENABLE == 1
905 I2CM_CONFIGURATION(5),
906#endif
907#if CONF_SERCOM_6_I2CM_ENABLE == 1
908 I2CM_CONFIGURATION(6),
909#endif
910#if CONF_SERCOM_7_I2CM_ENABLE == 1
911 I2CM_CONFIGURATION(7),
912#endif
913};
914#endif
915
916/**
917 * \internal Retrieve ordinal number of the given sercom hardware instance
918 *
919 * \param[in] hw The pointer to hardware instance
920
921 * \return The ordinal number of the given sercom hardware instance
922 */
923static int8_t _get_i2cm_index(const void *const hw)
924{
925 uint8_t sercom_offset = _sercom_get_hardware_index(hw);
926 uint8_t i;
927
928 for (i = 0; i < ARRAY_SIZE(_i2cms); i++) {
929 if (_i2cms[i].number == sercom_offset) {
930 return i;
931 }
932 }
933
934 ASSERT(false);
935 return -1;
936}
937
938static inline void _sercom_i2c_send_stop(void *const hw)
939{
940 hri_sercomi2cm_set_CTRLB_CMD_bf(hw, CMD_STOP);
941}
942
943/**
944 * \brief SERCOM I2CM analyze hardware status and transfer next byte
945 */
946static inline int32_t _sercom_i2c_sync_analyse_flags(void *const hw, uint32_t flags, struct _i2c_m_msg *const msg)
947{
948 int sclsm = hri_sercomi2cm_get_CTRLA_SCLSM_bit(hw);
949 uint16_t status = hri_sercomi2cm_read_STATUS_reg(hw);
950
951 if (flags & MB_FLAG) {
952 /* tx error */
953 if (status & SERCOM_I2CM_STATUS_ARBLOST) {
954 hri_sercomi2cm_clear_interrupt_MB_bit(hw);
955 msg->flags |= I2C_M_FAIL;
956 msg->flags &= ~I2C_M_BUSY;
957
958 if (status & SERCOM_I2CM_STATUS_BUSERR) {
959 return I2C_ERR_BUS;
960 }
961
962 return I2C_ERR_BAD_ADDRESS;
963 } else {
964 if (status & SERCOM_I2CM_STATUS_RXNACK) {
965
966 /* Slave rejects to receive more data */
967 if (msg->len > 0) {
968 msg->flags |= I2C_M_FAIL;
969 }
970
971 if (msg->flags & I2C_M_STOP) {
972 _sercom_i2c_send_stop(hw);
973 }
974
975 msg->flags &= ~I2C_M_BUSY;
976
977 return I2C_NACK;
978 }
979
980 if (msg->flags & I2C_M_TEN) {
981 hri_sercomi2cm_write_ADDR_reg(hw,
982 ((((msg->addr & TEN_ADDR_MASK) >> 8) | TEN_ADDR_FRAME) << 1) | I2C_M_RD
983 | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS));
984 msg->flags &= ~I2C_M_TEN;
985
986 return I2C_OK;
987 }
988
989 if (msg->len == 0) {
990 if (msg->flags & I2C_M_STOP) {
991 _sercom_i2c_send_stop(hw);
992 }
993
994 msg->flags &= ~I2C_M_BUSY;
995 } else {
996 hri_sercomi2cm_write_DATA_reg(hw, *msg->buffer);
997 msg->buffer++;
998 msg->len--;
999 }
1000
1001 return I2C_OK;
1002 }
1003 } else if (flags & SB_FLAG) {
1004 if ((msg->len) && !(status & SERCOM_I2CM_STATUS_RXNACK)) {
1005 msg->len--;
1006
1007 /* last byte, send nack */
1008 if ((msg->len == 0 && !sclsm) || (msg->len == 1 && sclsm)) {
1009 hri_sercomi2cm_set_CTRLB_ACKACT_bit(hw);
1010 }
1011
1012 if (msg->len == 0) {
1013 if (msg->flags & I2C_M_STOP) {
1014 hri_sercomi2cm_clear_CTRLB_SMEN_bit(hw);
1015 _sercom_i2c_send_stop(hw);
1016 }
1017
1018 msg->flags &= ~I2C_M_BUSY;
1019 }
1020
1021 /* Accessing DATA.DATA auto-triggers I2C bus operations.
1022 * The operation performed depends on the state of
1023 * CTRLB.ACKACT, CTRLB.SMEN
1024 **/
1025 *msg->buffer++ = hri_sercomi2cm_read_DATA_reg(hw);
1026 } else {
1027 hri_sercomi2cm_clear_interrupt_SB_bit(hw);
1028 return I2C_NACK;
1029 }
1030
1031 hri_sercomi2cm_clear_interrupt_SB_bit(hw);
1032 }
1033
1034 return I2C_OK;
1035}
1036
1037/**
1038 * \brief Enable the i2c master module
1039 *
1040 * \param[in] i2c_dev The pointer to i2c device
1041 */
1042int32_t _i2c_m_async_enable(struct _i2c_m_async_device *const i2c_dev)
1043{
1044 ASSERT(i2c_dev);
1045
1046 _i2c_m_enable_implementation(i2c_dev->hw);
1047
1048 return ERR_NONE;
1049}
1050
1051/**
1052 * \brief Disable the i2c master module
1053 *
1054 * \param[in] i2c_dev The pointer to i2c device
1055 */
1056int32_t _i2c_m_async_disable(struct _i2c_m_async_device *const i2c_dev)
1057{
1058 void *hw = i2c_dev->hw;
1059
1060 ASSERT(i2c_dev);
1061 ASSERT(i2c_dev->hw);
1062
1063 NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(hw));
1064 hri_sercomi2cm_clear_CTRLA_ENABLE_bit(hw);
1065
1066 return ERR_NONE;
1067}
1068
1069/**
1070 * \brief Set baudrate of master
1071 *
1072 * \param[in] i2c_dev The pointer to i2c device
1073 * \param[in] clkrate The clock rate of i2c master, in KHz
1074 * \param[in] baudrate The baud rate desired for i2c master, in KHz
1075 */
1076int32_t _i2c_m_async_set_baudrate(struct _i2c_m_async_device *const i2c_dev, uint32_t clkrate, uint32_t baudrate)
1077{
1078 uint32_t tmp;
1079 void * hw = i2c_dev->hw;
1080
1081 if (hri_sercomi2cm_get_CTRLA_ENABLE_bit(hw)) {
1082 return ERR_DENIED;
1083 }
1084
1085 tmp = _get_i2cm_index(hw);
1086 clkrate = _i2cms[tmp].clk / 1000;
1087
1088 if (i2c_dev->service.mode == I2C_STANDARD_MODE) {
1089 tmp = (uint32_t)((clkrate - 10 * baudrate - baudrate * clkrate * (i2c_dev->service.trise * 0.000000001))
1090 / (2 * baudrate));
1091 hri_sercomi2cm_write_BAUD_BAUD_bf(hw, tmp);
1092 } else if (i2c_dev->service.mode == I2C_FASTMODE) {
1093 tmp = (uint32_t)((clkrate - 10 * baudrate - baudrate * clkrate * (i2c_dev->service.trise * 0.000000001))
1094 / (2 * baudrate));
1095 hri_sercomi2cm_write_BAUD_BAUD_bf(hw, tmp);
1096 } else if (i2c_dev->service.mode == I2C_HIGHSPEED_MODE) {
1097 tmp = (clkrate - 2 * baudrate) / (2 * baudrate);
1098 hri_sercomi2cm_write_BAUD_HSBAUD_bf(hw, tmp);
1099 } else {
1100 /* error baudrate */
1101 return ERR_INVALID_ARG;
1102 }
1103
1104 return ERR_NONE;
1105}
1106
1107/**
1108 * \brief Retrieve IRQ number for the given hardware instance
1109 */
1110static uint8_t _sercom_get_irq_num(const void *const hw)
1111{
1112 return SERCOM0_0_IRQn + (_sercom_get_hardware_index(hw) << 2);
1113}
1114
1115/**
1116 * \brief Initialize sercom i2c module to use in async mode
1117 *
1118 * \param[in] i2c_dev The pointer to i2c device
1119 */
1120int32_t _i2c_m_async_init(struct _i2c_m_async_device *const i2c_dev, void *const hw)
1121{
1122 int32_t init_status;
1123
1124 ASSERT(i2c_dev);
1125
1126 i2c_dev->hw = hw;
1127
1128 init_status = _i2c_m_sync_init_impl(&i2c_dev->service, hw);
1129 if (init_status) {
1130 return init_status;
1131 }
1132
1133 _sercom_init_irq_param(hw, (void *)i2c_dev);
1134 uint8_t irq = _sercom_get_irq_num(hw);
1135 for (uint32_t i = 0; i < 4; i++) {
1136 NVIC_DisableIRQ((IRQn_Type)irq);
1137 NVIC_ClearPendingIRQ((IRQn_Type)irq);
1138 NVIC_EnableIRQ((IRQn_Type)irq);
1139 irq++;
1140 }
1141 return ERR_NONE;
1142}
1143
1144/**
1145 * \brief Deinitialize sercom i2c module
1146 *
1147 * \param[in] i2c_dev The pointer to i2c device
1148 */
1149int32_t _i2c_m_async_deinit(struct _i2c_m_async_device *const i2c_dev)
1150{
1151 ASSERT(i2c_dev);
1152
1153 hri_sercomi2cm_clear_CTRLA_ENABLE_bit(i2c_dev->hw);
1154 hri_sercomi2cm_set_CTRLA_SWRST_bit(i2c_dev->hw);
1155
1156 return ERR_NONE;
1157}
1158
1159/**
1160 * \brief Transfer the slave address to bus, which will start the transfer
1161 *
1162 * \param[in] i2c_dev The pointer to i2c device
1163 */
1164static int32_t _sercom_i2c_send_address(struct _i2c_m_async_device *const i2c_dev)
1165{
1166 void * hw = i2c_dev->hw;
1167 struct _i2c_m_msg *msg = &i2c_dev->service.msg;
1168 int sclsm = hri_sercomi2cm_get_CTRLA_SCLSM_bit(hw);
1169
1170 ASSERT(i2c_dev);
1171
1172 if (msg->len == 1 && sclsm) {
1173 hri_sercomi2cm_set_CTRLB_ACKACT_bit(hw);
1174 } else {
1175 hri_sercomi2cm_clear_CTRLB_ACKACT_bit(hw);
1176 }
1177
1178 /* ten bit address */
1179 if (msg->addr & I2C_M_TEN) {
1180 if (msg->flags & I2C_M_RD) {
1181 msg->flags |= I2C_M_TEN;
1182 }
1183
1184 hri_sercomi2cm_write_ADDR_reg(hw,
1185 ((msg->addr & TEN_ADDR_MASK) << 1) | SERCOM_I2CM_ADDR_TENBITEN
1186 | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS));
1187 } else {
1188 hri_sercomi2cm_write_ADDR_reg(hw,
1189 ((msg->addr & SEVEN_ADDR_MASK) << 1) | (msg->flags & I2C_M_RD ? I2C_M_RD : 0x0)
1190 | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS));
1191 }
1192
1193 return ERR_NONE;
1194}
1195
1196/**
1197 * \brief Transfer data specified by msg
1198 *
1199 * \param[in] i2c_dev The pointer to i2c device
1200 * \param[in] msg The pointer to i2c message
1201 *
1202 * \return Transfer status.
1203 * \retval 0 Transfer success
1204 * \retval <0 Transfer fail, return the error code
1205 */
1206int32_t _i2c_m_async_transfer(struct _i2c_m_async_device *i2c_dev, struct _i2c_m_msg *msg)
1207{
1208 int ret;
1209
1210 ASSERT(i2c_dev);
1211 ASSERT(i2c_dev->hw);
1212 ASSERT(msg);
1213
1214 if (msg->len == 0) {
1215 return ERR_NONE;
1216 }
1217
1218 if (i2c_dev->service.msg.flags & I2C_M_BUSY) {
1219 return ERR_BUSY;
1220 }
1221
1222 msg->flags |= I2C_M_BUSY;
1223 i2c_dev->service.msg = *msg;
1224 hri_sercomi2cm_set_CTRLB_SMEN_bit(i2c_dev->hw);
1225
1226 ret = _sercom_i2c_send_address(i2c_dev);
1227
1228 if (ret) {
1229 i2c_dev->service.msg.flags &= ~I2C_M_BUSY;
1230
1231 return ret;
1232 }
1233
1234 return ERR_NONE;
1235}
1236
1237/**
1238 * \brief Set callback to be called in interrupt handler
1239 *
1240 * \param[in] i2c_dev The pointer to master i2c device
1241 * \param[in] type The callback type
1242 * \param[in] func The callback function pointer
1243 */
1244int32_t _i2c_m_async_register_callback(struct _i2c_m_async_device *const i2c_dev, enum _i2c_m_async_callback_type type,
1245 FUNC_PTR func)
1246{
1247 switch (type) {
1248 case I2C_M_ASYNC_DEVICE_ERROR:
1249 i2c_dev->cb.error = (_i2c_error_cb_t)func;
1250 break;
1251 case I2C_M_ASYNC_DEVICE_TX_COMPLETE:
1252 i2c_dev->cb.tx_complete = (_i2c_complete_cb_t)func;
1253 break;
1254 case I2C_M_ASYNC_DEVICE_RX_COMPLETE:
1255 i2c_dev->cb.rx_complete = (_i2c_complete_cb_t)func;
1256 break;
1257 default:
1258 /* error */
1259 break;
1260 }
1261
1262 return ERR_NONE;
1263}
1264
1265/**
1266 * \brief Set stop condition on I2C
1267 *
1268 * \param i2c_dev Pointer to master i2c device
1269 *
1270 * \return Operation status
1271 * \retval I2C_OK Operation was successfull
1272 */
1273int32_t _i2c_m_async_send_stop(struct _i2c_m_async_device *const i2c_dev)
1274{
1275 void *hw = i2c_dev->hw;
1276
1277 _sercom_i2c_send_stop(hw);
1278
1279 return I2C_OK;
1280}
1281
1282/**
1283 * \brief Get number of bytes left in transfer buffer
1284 *
1285 * \param i2c_dev Pointer to i2c master device
1286 *
1287 * \return Bytes left in buffer
1288 * \retval =>0 Bytes left in buffer
1289 */
1290int32_t _i2c_m_async_get_bytes_left(struct _i2c_m_async_device *const i2c_dev)
1291{
1292 if (i2c_dev->service.msg.flags & I2C_M_BUSY) {
1293 return i2c_dev->service.msg.len;
1294 }
1295
1296 return 0;
1297}
1298
1299/**
1300 * \brief Initialize sercom i2c module to use in sync mode
1301 *
1302 * \param[in] i2c_dev The pointer to i2c device
1303 */
1304int32_t _i2c_m_sync_init(struct _i2c_m_sync_device *const i2c_dev, void *const hw)
1305{
1306 ASSERT(i2c_dev);
1307
1308 i2c_dev->hw = hw;
1309
1310 return _i2c_m_sync_init_impl(&i2c_dev->service, hw);
1311}
1312
1313/**
1314 * \brief Deinitialize sercom i2c module
1315 *
1316 * \param[in] i2c_dev The pointer to i2c device
1317 */
1318int32_t _i2c_m_sync_deinit(struct _i2c_m_sync_device *const i2c_dev)
1319{
1320 ASSERT(i2c_dev);
1321
1322 hri_sercomi2cm_clear_CTRLA_ENABLE_bit(i2c_dev->hw);
1323 hri_sercomi2cm_set_CTRLA_SWRST_bit(i2c_dev->hw);
1324
1325 return ERR_NONE;
1326}
1327
1328/**
1329 * \brief Enable the i2c master module
1330 *
1331 * \param[in] i2c_dev The pointer to i2c device
1332 */
1333int32_t _i2c_m_sync_enable(struct _i2c_m_sync_device *const i2c_dev)
1334{
1335 ASSERT(i2c_dev);
1336
1337 _i2c_m_enable_implementation(i2c_dev->hw);
1338
1339 return ERR_NONE;
1340}
1341
1342/**
1343 * \brief Disable the i2c master module
1344 *
1345 * \param[in] i2c_dev The pointer to i2c device
1346 */
1347int32_t _i2c_m_sync_disable(struct _i2c_m_sync_device *const i2c_dev)
1348{
1349 void *hw = i2c_dev->hw;
1350
1351 ASSERT(i2c_dev);
1352 ASSERT(i2c_dev->hw);
1353
1354 hri_sercomi2cm_clear_CTRLA_ENABLE_bit(hw);
1355
1356 return ERR_NONE;
1357}
1358
1359/**
1360 * \brief Set baudrate of master
1361 *
1362 * \param[in] i2c_dev The pointer to i2c device
1363 * \param[in] clkrate The clock rate of i2c master, in KHz
1364 * \param[in] baudrate The baud rate desired for i2c master, in KHz
1365 */
1366int32_t _i2c_m_sync_set_baudrate(struct _i2c_m_sync_device *const i2c_dev, uint32_t clkrate, uint32_t baudrate)
1367{
1368 uint32_t tmp;
1369 void * hw = i2c_dev->hw;
1370
1371 if (hri_sercomi2cm_get_CTRLA_ENABLE_bit(hw)) {
1372 return ERR_DENIED;
1373 }
1374
1375 tmp = _get_i2cm_index(hw);
1376 clkrate = _i2cms[tmp].clk / 1000;
1377
1378 if (i2c_dev->service.mode == I2C_STANDARD_MODE) {
1379 tmp = (uint32_t)((clkrate - 10 * baudrate - baudrate * clkrate * (i2c_dev->service.trise * 0.000000001))
1380 / (2 * baudrate));
1381 hri_sercomi2cm_write_BAUD_BAUD_bf(hw, tmp);
1382 } else if (i2c_dev->service.mode == I2C_FASTMODE) {
1383 tmp = (uint32_t)((clkrate - 10 * baudrate - baudrate * clkrate * (i2c_dev->service.trise * 0.000000001))
1384 / (2 * baudrate));
1385 hri_sercomi2cm_write_BAUD_BAUD_bf(hw, tmp);
1386 } else if (i2c_dev->service.mode == I2C_HIGHSPEED_MODE) {
1387 tmp = (clkrate - 2 * baudrate) / (2 * baudrate);
1388 hri_sercomi2cm_write_BAUD_HSBAUD_bf(hw, tmp);
1389 } else {
1390 /* error baudrate */
1391 return ERR_INVALID_ARG;
1392 }
1393
1394 return ERR_NONE;
1395}
1396
1397/**
1398 * \brief Enable/disable I2C master interrupt
1399 */
1400void _i2c_m_async_set_irq_state(struct _i2c_m_async_device *const device, const enum _i2c_m_async_callback_type type,
1401 const bool state)
1402{
1403 if (I2C_M_ASYNC_DEVICE_TX_COMPLETE == type || I2C_M_ASYNC_DEVICE_RX_COMPLETE == type) {
1404 hri_sercomi2cm_write_INTEN_SB_bit(device->hw, state);
1405 hri_sercomi2cm_write_INTEN_MB_bit(device->hw, state);
1406 } else if (I2C_M_ASYNC_DEVICE_ERROR == type) {
1407 hri_sercomi2cm_write_INTEN_ERROR_bit(device->hw, state);
1408 }
1409}
1410
1411/**
1412 * \brief Wait for bus response
1413 *
1414 * \param[in] i2c_dev The pointer to i2c device
1415 * \param[in] flags Store the hardware response
1416 *
1417 * \return Bus response status.
1418 * \retval 0 Bus response status OK
1419 * \retval <0 Bus response fail
1420 */
1421inline static int32_t _sercom_i2c_sync_wait_bus(struct _i2c_m_sync_device *const i2c_dev, uint32_t *flags)
1422{
1423 uint32_t timeout = 65535;
1424 void * hw = i2c_dev->hw;
1425
1426 do {
1427 *flags = hri_sercomi2cm_read_INTFLAG_reg(hw);
1428
1429 if (timeout-- == 0) {
1430 return I2C_ERR_BUS;
1431 }
1432 } while (!(*flags & MB_FLAG) && !(*flags & SB_FLAG));
1433
1434 return I2C_OK;
1435}
1436
1437/**
1438 * \brief Send the slave address to bus, which will start the transfer
1439 *
1440 * \param[in] i2c_dev The pointer to i2c device
1441 */
1442static int32_t _sercom_i2c_sync_send_address(struct _i2c_m_sync_device *const i2c_dev)
1443{
1444 void * hw = i2c_dev->hw;
1445 struct _i2c_m_msg *msg = &i2c_dev->service.msg;
1446 int sclsm = hri_sercomi2cm_get_CTRLA_SCLSM_bit(hw);
1447 uint32_t flags;
1448
1449 ASSERT(i2c_dev);
1450
1451 if (msg->len == 1 && sclsm) {
1452 hri_sercomi2cm_set_CTRLB_ACKACT_bit(hw);
1453 } else {
1454 hri_sercomi2cm_clear_CTRLB_ACKACT_bit(hw);
1455 }
1456
1457 /* ten bit address */
1458 if (msg->addr & I2C_M_TEN) {
1459 if (msg->flags & I2C_M_RD) {
1460 msg->flags |= I2C_M_TEN;
1461 }
1462
1463 hri_sercomi2cm_write_ADDR_reg(hw,
1464 ((msg->addr & TEN_ADDR_MASK) << 1) | SERCOM_I2CM_ADDR_TENBITEN
1465 | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS));
1466 } else {
1467 hri_sercomi2cm_write_ADDR_reg(hw,
1468 ((msg->addr & SEVEN_ADDR_MASK) << 1) | (msg->flags & I2C_M_RD ? I2C_M_RD : 0x0)
1469 | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS));
1470 }
1471
1472 _sercom_i2c_sync_wait_bus(i2c_dev, &flags);
1473 return _sercom_i2c_sync_analyse_flags(hw, flags, msg);
1474}
1475
1476/**
1477 * \brief Transfer data specified by msg
1478 *
1479 * \param[in] i2c_dev The pointer to i2c device
1480 * \param[in] msg The pointer to i2c message
1481 *
1482 * \return Transfer status.
1483 * \retval 0 Transfer success
1484 * \retval <0 Transfer fail or partial fail, return the error code
1485 */
1486int32_t _i2c_m_sync_transfer(struct _i2c_m_sync_device *const i2c_dev, struct _i2c_m_msg *msg)
1487{
1488 uint32_t flags;
1489 int ret;
1490 void * hw = i2c_dev->hw;
1491
1492 ASSERT(i2c_dev);
1493 ASSERT(i2c_dev->hw);
1494 ASSERT(msg);
1495
1496 if (i2c_dev->service.msg.flags & I2C_M_BUSY) {
1497 return I2C_ERR_BUSY;
1498 }
1499
1500 msg->flags |= I2C_M_BUSY;
1501 i2c_dev->service.msg = *msg;
1502 hri_sercomi2cm_set_CTRLB_SMEN_bit(hw);
1503
1504 ret = _sercom_i2c_sync_send_address(i2c_dev);
1505
1506 if (ret) {
1507 i2c_dev->service.msg.flags &= ~I2C_M_BUSY;
1508
1509 return ret;
1510 }
1511
1512 while (i2c_dev->service.msg.flags & I2C_M_BUSY) {
1513 ret = _sercom_i2c_sync_wait_bus(i2c_dev, &flags);
1514
1515 if (ret) {
1516 if (msg->flags & I2C_M_STOP) {
1517 _sercom_i2c_send_stop(hw);
1518 }
1519
1520 i2c_dev->service.msg.flags &= ~I2C_M_BUSY;
1521
1522 return ret;
1523 }
1524
1525 ret = _sercom_i2c_sync_analyse_flags(hw, flags, &i2c_dev->service.msg);
1526 }
1527
1528 return ret;
1529}
1530
1531int32_t _i2c_m_sync_send_stop(struct _i2c_m_sync_device *const i2c_dev)
1532{
1533 void *hw = i2c_dev->hw;
1534
1535 _sercom_i2c_send_stop(hw);
1536
1537 return I2C_OK;
1538}
1539
1540static inline void _i2c_m_enable_implementation(void *const hw)
1541{
1542 int timeout = 65535;
1543
1544 ASSERT(hw);
1545
1546 /* Enable interrupts */
1547 hri_sercomi2cm_set_CTRLA_ENABLE_bit(hw);
1548
1549 while (hri_sercomi2cm_read_STATUS_BUSSTATE_bf(hw) != I2C_IDLE) {
1550 timeout--;
1551
1552 if (timeout <= 0) {
1553 hri_sercomi2cm_clear_STATUS_reg(hw, SERCOM_I2CM_STATUS_BUSSTATE(I2C_IDLE));
1554 }
1555 }
1556}
1557
1558static int32_t _i2c_m_sync_init_impl(struct _i2c_m_service *const service, void *const hw)
1559{
1560 uint8_t i = _get_i2cm_index(hw);
1561
1562 if (!hri_sercomi2cm_is_syncing(hw, SERCOM_I2CM_SYNCBUSY_SWRST)) {
1563 uint32_t mode = _i2cms[i].ctrl_a & SERCOM_I2CM_CTRLA_MODE_Msk;
1564 if (hri_sercomi2cm_get_CTRLA_reg(hw, SERCOM_I2CM_CTRLA_ENABLE)) {
1565 hri_sercomi2cm_clear_CTRLA_ENABLE_bit(hw);
1566 hri_sercomi2cm_wait_for_sync(hw, SERCOM_I2CM_SYNCBUSY_ENABLE);
1567 }
1568 hri_sercomi2cm_write_CTRLA_reg(hw, SERCOM_I2CM_CTRLA_SWRST | mode);
1569 }
1570 hri_sercomi2cm_wait_for_sync(hw, SERCOM_I2CM_SYNCBUSY_SWRST);
1571
1572 hri_sercomi2cm_write_CTRLA_reg(hw, _i2cms[i].ctrl_a);
1573 hri_sercomi2cm_write_CTRLB_reg(hw, _i2cms[i].ctrl_b);
1574 hri_sercomi2cm_write_BAUD_reg(hw, _i2cms[i].baud);
1575
1576 service->mode = (_i2cms[i].ctrl_a & SERCOM_I2CM_CTRLA_SPEED_Msk) >> SERCOM_I2CM_CTRLA_SPEED_Pos;
1577 hri_sercomi2cm_write_ADDR_HS_bit(hw, service->mode < I2C_HS ? 0 : 1);
1578
1579 service->trise = _i2cms[i].trise;
1580
1581 return ERR_NONE;
1582}
1583
1584 /* SERCOM I2C slave */
1585
1586#ifndef CONF_SERCOM_0_I2CS_ENABLE
1587#define CONF_SERCOM_0_I2CS_ENABLE 0
1588#endif
1589#ifndef CONF_SERCOM_1_I2CS_ENABLE
1590#define CONF_SERCOM_1_I2CS_ENABLE 0
1591#endif
1592#ifndef CONF_SERCOM_2_I2CS_ENABLE
1593#define CONF_SERCOM_2_I2CS_ENABLE 0
1594#endif
1595#ifndef CONF_SERCOM_3_I2CS_ENABLE
1596#define CONF_SERCOM_3_I2CS_ENABLE 0
1597#endif
1598#ifndef CONF_SERCOM_4_I2CS_ENABLE
1599#define CONF_SERCOM_4_I2CS_ENABLE 0
1600#endif
1601#ifndef CONF_SERCOM_5_I2CS_ENABLE
1602#define CONF_SERCOM_5_I2CS_ENABLE 0
1603#endif
1604#ifndef CONF_SERCOM_6_I2CS_ENABLE
1605#define CONF_SERCOM_6_I2CS_ENABLE 0
1606#endif
1607#ifndef CONF_SERCOM_7_I2CS_ENABLE
1608#define CONF_SERCOM_7_I2CS_ENABLE 0
1609#endif
1610
1611/** Amount of SERCOM that is used as I2C Slave. */
1612#define SERCOM_I2CS_AMOUNT \
1613 (CONF_SERCOM_0_I2CS_ENABLE + CONF_SERCOM_1_I2CS_ENABLE + CONF_SERCOM_2_I2CS_ENABLE + CONF_SERCOM_3_I2CS_ENABLE \
1614 + CONF_SERCOM_4_I2CS_ENABLE + CONF_SERCOM_5_I2CS_ENABLE + CONF_SERCOM_6_I2CS_ENABLE + CONF_SERCOM_7_I2CS_ENABLE)
1615
1616/**
1617 * \brief Macro is used to fill I2C slave configuration structure based on
1618 * its number
1619 *
1620 * \param[in] n The number of structures
1621 */
1622#define I2CS_CONFIGURATION(n) \
1623 { \
1624 n, \
1625 SERCOM_I2CM_CTRLA_MODE_I2C_SLAVE | (CONF_SERCOM_##n##_I2CS_RUNSTDBY << SERCOM_I2CS_CTRLA_RUNSTDBY_Pos) \
1626 | SERCOM_I2CS_CTRLA_SDAHOLD(CONF_SERCOM_##n##_I2CS_SDAHOLD) \
1627 | (CONF_SERCOM_##n##_I2CS_SEXTTOEN << SERCOM_I2CS_CTRLA_SEXTTOEN_Pos) \
1628 | (CONF_SERCOM_##n##_I2CS_SPEED << SERCOM_I2CS_CTRLA_SPEED_Pos) \
1629 | (CONF_SERCOM_##n##_I2CS_SCLSM << SERCOM_I2CS_CTRLA_SCLSM_Pos) \
1630 | (CONF_SERCOM_##n##_I2CS_LOWTOUT << SERCOM_I2CS_CTRLA_LOWTOUTEN_Pos), \
1631 SERCOM_I2CS_CTRLB_SMEN | SERCOM_I2CS_CTRLB_AACKEN | SERCOM_I2CS_CTRLB_AMODE(CONF_SERCOM_##n##_I2CS_AMODE), \
1632 (CONF_SERCOM_##n##_I2CS_GENCEN << SERCOM_I2CS_ADDR_GENCEN_Pos) \
1633 | SERCOM_I2CS_ADDR_ADDR(CONF_SERCOM_##n##_I2CS_ADDRESS) \
1634 | (CONF_SERCOM_##n##_I2CS_TENBITEN << SERCOM_I2CS_ADDR_TENBITEN_Pos) \
1635 | SERCOM_I2CS_ADDR_ADDRMASK(CONF_SERCOM_##n##_I2CS_ADDRESS_MASK) \
1636 }
1637
1638/**
1639 * \brief Macro to check 10-bit addressing
1640 */
1641#define I2CS_7BIT_ADDRESSING_MASK 0x7F
1642
1643static int32_t _i2c_s_init(void *const hw);
1644static int8_t _get_i2c_s_index(const void *const hw);
1645static inline void _i2c_s_deinit(void *const hw);
1646static int32_t _i2c_s_set_address(void *const hw, const uint16_t address);
1647
1648/**
1649 * \brief SERCOM I2C slave configuration type
1650 */
1651struct i2cs_configuration {
1652 uint8_t number;
1653 hri_sercomi2cs_ctrla_reg_t ctrl_a;
1654 hri_sercomi2cs_ctrlb_reg_t ctrl_b;
1655 hri_sercomi2cs_addr_reg_t address;
1656};
1657
1658#if SERCOM_I2CS_AMOUNT < 1
1659/** Dummy array for compiling. */
1660static struct i2cs_configuration _i2css[1] = {{0}};
1661#else
1662/**
1663 * \brief Array of SERCOM I2C slave configurations
1664 */
1665static struct i2cs_configuration _i2css[] = {
1666#if CONF_SERCOM_0_I2CS_ENABLE == 1
1667 I2CS_CONFIGURATION(0),
1668#endif
1669#if CONF_SERCOM_1_I2CS_ENABLE == 1
1670 I2CS_CONFIGURATION(1),
1671#endif
1672#if CONF_SERCOM_2_I2CS_ENABLE == 1
1673 I2CS_CONFIGURATION(2),
1674#endif
1675#if CONF_SERCOM_3_I2CS_ENABLE == 1
1676 I2CS_CONFIGURATION(3),
1677#endif
1678#if CONF_SERCOM_4_I2CS_ENABLE == 1
1679 I2CS_CONFIGURATION(4),
1680#endif
1681#if CONF_SERCOM_5_I2CS_ENABLE == 1
1682 I2CS_CONFIGURATION(5),
1683#endif
1684};
1685#endif
1686
1687/**
1688 * \brief Initialize synchronous I2C slave
1689 */
1690int32_t _i2c_s_sync_init(struct _i2c_s_sync_device *const device, void *const hw)
1691{
1692 int32_t status;
1693
1694 ASSERT(device);
1695
1696 status = _i2c_s_init(hw);
1697 if (status) {
1698 return status;
1699 }
1700 device->hw = hw;
1701
1702 return ERR_NONE;
1703}
1704
1705/**
1706 * \brief Initialize asynchronous I2C slave
1707 */
1708int32_t _i2c_s_async_init(struct _i2c_s_async_device *const device, void *const hw)
1709{
1710 int32_t init_status;
1711
1712 ASSERT(device);
1713
1714 init_status = _i2c_s_init(hw);
1715 if (init_status) {
1716 return init_status;
1717 }
1718
1719 device->hw = hw;
1720 _sercom_init_irq_param(hw, (void *)device);
1721 uint8_t irq = _sercom_get_irq_num(hw);
1722 for (uint32_t i = 0; i < 4; i++) {
1723 NVIC_DisableIRQ((IRQn_Type)irq);
1724 NVIC_ClearPendingIRQ((IRQn_Type)irq);
1725 NVIC_EnableIRQ((IRQn_Type)irq);
1726 irq++;
1727 }
1728
1729 return ERR_NONE;
1730}
1731
1732/**
1733 * \brief Deinitialize synchronous I2C
1734 */
1735int32_t _i2c_s_sync_deinit(struct _i2c_s_sync_device *const device)
1736{
1737 _i2c_s_deinit(device->hw);
1738
1739 return ERR_NONE;
1740}
1741
1742/**
1743 * \brief Deinitialize asynchronous I2C
1744 */
1745int32_t _i2c_s_async_deinit(struct _i2c_s_async_device *const device)
1746{
1747 NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(device->hw));
1748 _i2c_s_deinit(device->hw);
1749
1750 return ERR_NONE;
1751}
1752
1753/**
1754 * \brief Enable I2C module
1755 */
1756int32_t _i2c_s_sync_enable(struct _i2c_s_sync_device *const device)
1757{
1758 hri_sercomi2cs_set_CTRLA_ENABLE_bit(device->hw);
1759
1760 return ERR_NONE;
1761}
1762
1763/**
1764 * \brief Enable I2C module
1765 */
1766int32_t _i2c_s_async_enable(struct _i2c_s_async_device *const device)
1767{
1768 hri_sercomi2cs_set_CTRLA_ENABLE_bit(device->hw);
1769
1770 return ERR_NONE;
1771}
1772
1773/**
1774 * \brief Disable I2C module
1775 */
1776int32_t _i2c_s_sync_disable(struct _i2c_s_sync_device *const device)
1777{
1778 hri_sercomi2cs_clear_CTRLA_ENABLE_bit(device->hw);
1779
1780 return ERR_NONE;
1781}
1782
1783/**
1784 * \brief Disable I2C module
1785 */
1786int32_t _i2c_s_async_disable(struct _i2c_s_async_device *const device)
1787{
1788 hri_sercomi2cs_clear_CTRLA_ENABLE_bit(device->hw);
1789
1790 return ERR_NONE;
1791}
1792
1793/**
1794 * \brief Check if 10-bit addressing mode is on
1795 */
1796int32_t _i2c_s_sync_is_10bit_addressing_on(const struct _i2c_s_sync_device *const device)
1797{
1798 return hri_sercomi2cs_get_ADDR_TENBITEN_bit(device->hw);
1799}
1800
1801/**
1802 * \brief Check if 10-bit addressing mode is on
1803 */
1804int32_t _i2c_s_async_is_10bit_addressing_on(const struct _i2c_s_async_device *const device)
1805{
1806 return hri_sercomi2cs_get_ADDR_TENBITEN_bit(device->hw);
1807}
1808
1809/**
1810 * \brief Set I2C slave address
1811 */
1812int32_t _i2c_s_sync_set_address(struct _i2c_s_sync_device *const device, const uint16_t address)
1813{
1814 return _i2c_s_set_address(device->hw, address);
1815}
1816
1817/**
1818 * \brief Set I2C slave address
1819 */
1820int32_t _i2c_s_async_set_address(struct _i2c_s_async_device *const device, const uint16_t address)
1821{
1822 return _i2c_s_set_address(device->hw, address);
1823}
1824
1825/**
1826 * \brief Write a byte to the given I2C instance
1827 */
1828void _i2c_s_sync_write_byte(struct _i2c_s_sync_device *const device, const uint8_t data)
1829{
1830 hri_sercomi2cs_write_DATA_reg(device->hw, data);
1831}
1832
1833/**
1834 * \brief Write a byte to the given I2C instance
1835 */
1836void _i2c_s_async_write_byte(struct _i2c_s_async_device *const device, const uint8_t data)
1837{
1838 hri_sercomi2cs_write_DATA_reg(device->hw, data);
1839}
1840
1841/**
1842 * \brief Read a byte from the given I2C instance
1843 */
1844uint8_t _i2c_s_sync_read_byte(const struct _i2c_s_sync_device *const device)
1845{
1846 return hri_sercomi2cs_read_DATA_reg(device->hw);
1847}
1848
1849/**
1850 * \brief Check if I2C is ready to send next byt
1851 */
1852bool _i2c_s_sync_is_byte_sent(const struct _i2c_s_sync_device *const device)
1853{
1854 return hri_sercomi2cs_get_interrupt_DRDY_bit(device->hw);
1855}
1856
1857/**
1858 * \brief Check if there is data received by I2C
1859 */
1860bool _i2c_s_sync_is_byte_received(const struct _i2c_s_sync_device *const device)
1861{
1862 return hri_sercomi2cs_get_interrupt_DRDY_bit(device->hw);
1863}
1864
1865/**
1866 * \brief Retrieve I2C slave status
1867 */
1868i2c_s_status_t _i2c_s_sync_get_status(const struct _i2c_s_sync_device *const device)
1869{
1870 return hri_sercomi2cs_read_STATUS_reg(device->hw);
1871}
1872
1873/**
1874 * \brief Clear the Data Ready interrupt flag
1875 */
1876int32_t _i2c_s_sync_clear_data_ready_flag(const struct _i2c_s_sync_device *const device)
1877{
1878 hri_sercomi2cs_clear_INTFLAG_DRDY_bit(device->hw);
1879
1880 return ERR_NONE;
1881}
1882
1883/**
1884 * \brief Retrieve I2C slave status
1885 */
1886i2c_s_status_t _i2c_s_async_get_status(const struct _i2c_s_async_device *const device)
1887{
1888 return hri_sercomi2cs_read_STATUS_reg(device->hw);
1889}
1890
1891/**
1892 * \brief Abort data transmission
1893 */
1894int32_t _i2c_s_async_abort_transmission(const struct _i2c_s_async_device *const device)
1895{
1896 hri_sercomi2cs_clear_INTEN_DRDY_bit(device->hw);
1897
1898 return ERR_NONE;
1899}
1900
1901/**
1902 * \brief Enable/disable I2C slave interrupt
1903 */
1904int32_t _i2c_s_async_set_irq_state(struct _i2c_s_async_device *const device, const enum _i2c_s_async_callback_type type,
1905 const bool state)
1906{
1907 ASSERT(device);
1908
1909 if (I2C_S_DEVICE_TX == type || I2C_S_DEVICE_RX_COMPLETE == type) {
1910 hri_sercomi2cs_write_INTEN_DRDY_bit(device->hw, state);
1911 } else if (I2C_S_DEVICE_ERROR == type) {
1912 hri_sercomi2cs_write_INTEN_ERROR_bit(device->hw, state);
1913 }
1914
1915 return ERR_NONE;
1916}
1917
1918/**
1919 * \internal Initalize i2c slave hardware
1920 *
1921 * \param[in] p The pointer to hardware instance
1922 *
1923 *\ return status of initialization
1924 */
1925static int32_t _i2c_s_init(void *const hw)
1926{
1927 int8_t i = _get_i2c_s_index(hw);
1928 if (i == -1) {
1929 return ERR_INVALID_ARG;
1930 }
1931
1932 if (!hri_sercomi2cs_is_syncing(hw, SERCOM_I2CS_CTRLA_SWRST)) {
1933 uint32_t mode = _i2css[i].ctrl_a & SERCOM_I2CS_CTRLA_MODE_Msk;
1934 if (hri_sercomi2cs_get_CTRLA_reg(hw, SERCOM_I2CS_CTRLA_ENABLE)) {
1935 hri_sercomi2cs_clear_CTRLA_ENABLE_bit(hw);
1936 hri_sercomi2cs_wait_for_sync(hw, SERCOM_I2CS_SYNCBUSY_ENABLE);
1937 }
1938 hri_sercomi2cs_write_CTRLA_reg(hw, SERCOM_I2CS_CTRLA_SWRST | mode);
1939 }
1940 hri_sercomi2cs_wait_for_sync(hw, SERCOM_I2CS_SYNCBUSY_SWRST);
1941
1942 hri_sercomi2cs_write_CTRLA_reg(hw, _i2css[i].ctrl_a);
1943 hri_sercomi2cs_write_CTRLB_reg(hw, _i2css[i].ctrl_b);
1944 hri_sercomi2cs_write_ADDR_reg(hw, _i2css[i].address);
1945
1946 return ERR_NONE;
1947}
1948
1949/**
1950 * \internal Retrieve ordinal number of the given sercom hardware instance
1951 *
1952 * \param[in] hw The pointer to hardware instance
1953 *
1954 * \return The ordinal number of the given sercom hardware instance
1955 */
1956static int8_t _get_i2c_s_index(const void *const hw)
1957{
1958 uint8_t sercom_offset = _sercom_get_hardware_index(hw);
1959 uint8_t i;
1960
1961 for (i = 0; i < ARRAY_SIZE(_i2css); i++) {
1962 if (_i2css[i].number == sercom_offset) {
1963 return i;
1964 }
1965 }
1966
1967 ASSERT(false);
1968 return -1;
1969}
1970
1971/**
1972 * \internal De-initialize i2c slave
1973 *
1974 * \param[in] hw The pointer to hardware instance
1975 */
1976static inline void _i2c_s_deinit(void *const hw)
1977{
1978 hri_sercomi2cs_clear_CTRLA_ENABLE_bit(hw);
1979 hri_sercomi2cs_set_CTRLA_SWRST_bit(hw);
1980}
1981
1982/**
1983 * \internal De-initialize i2c slave
1984 *
1985 * \param[in] hw The pointer to hardware instance
1986 * \param[in] address Address to set
1987 */
1988static int32_t _i2c_s_set_address(void *const hw, const uint16_t address)
1989{
1990 bool enabled;
1991
1992 enabled = hri_sercomi2cs_get_CTRLA_ENABLE_bit(hw);
1993
1994 CRITICAL_SECTION_ENTER()
1995 hri_sercomi2cs_clear_CTRLA_ENABLE_bit(hw);
1996 hri_sercomi2cs_write_ADDR_ADDR_bf(hw, address);
1997 CRITICAL_SECTION_LEAVE()
1998
1999 if (enabled) {
2000 hri_sercomi2cs_set_CTRLA_ENABLE_bit(hw);
2001 }
2002
2003 return ERR_NONE;
2004}
2005
2006 /* Sercom SPI implementation */
2007
2008#ifndef SERCOM_USART_CTRLA_MODE_SPI_SLAVE
2009#define SERCOM_USART_CTRLA_MODE_SPI_SLAVE (2 << 2)
2010#endif
2011
2012#define SPI_DEV_IRQ_MODE 0x8000
2013
2014#define _SPI_CS_PORT_EXTRACT(cs) (((cs) >> 0) & 0xFF)
2015#define _SPI_CS_PIN_EXTRACT(cs) (((cs) >> 8) & 0xFF)
2016
2017COMPILER_PACK_SET(1)
2018/** Initialization configuration of registers. */
2019struct sercomspi_regs_cfg {
2020 uint32_t ctrla;
2021 uint32_t ctrlb;
2022 uint32_t addr;
2023 uint8_t baud;
2024 uint8_t dbgctrl;
2025 uint16_t dummy_byte;
2026 uint8_t n;
2027};
2028COMPILER_PACK_RESET()
2029
2030/** Build configuration from header macros. */
2031#define SERCOMSPI_REGS(n) \
2032 { \
2033 (((CONF_SERCOM_##n##_SPI_DORD) << SERCOM_SPI_CTRLA_DORD_Pos) \
2034 | (CONF_SERCOM_##n##_SPI_CPOL << SERCOM_SPI_CTRLA_CPOL_Pos) \
2035 | (CONF_SERCOM_##n##_SPI_CPHA << SERCOM_SPI_CTRLA_CPHA_Pos) \
2036 | (CONF_SERCOM_##n##_SPI_AMODE_EN ? SERCOM_SPI_CTRLA_FORM(2) : SERCOM_SPI_CTRLA_FORM(0)) \
2037 | SERCOM_SPI_CTRLA_DOPO(CONF_SERCOM_##n##_SPI_TXPO) | SERCOM_SPI_CTRLA_DIPO(CONF_SERCOM_##n##_SPI_RXPO) \
2038 | (CONF_SERCOM_##n##_SPI_IBON << SERCOM_SPI_CTRLA_IBON_Pos) \
2039 | (CONF_SERCOM_##n##_SPI_RUNSTDBY << SERCOM_SPI_CTRLA_RUNSTDBY_Pos) \
2040 | SERCOM_SPI_CTRLA_MODE(CONF_SERCOM_##n##_SPI_MODE)), /* ctrla */ \
2041 ((CONF_SERCOM_##n##_SPI_RXEN << SERCOM_SPI_CTRLB_RXEN_Pos) \
2042 | (CONF_SERCOM_##n##_SPI_MSSEN << SERCOM_SPI_CTRLB_MSSEN_Pos) \
2043 | (CONF_SERCOM_##n##_SPI_SSDE << SERCOM_SPI_CTRLB_SSDE_Pos) \
2044 | (CONF_SERCOM_##n##_SPI_PLOADEN << SERCOM_SPI_CTRLB_PLOADEN_Pos) \
2045 | SERCOM_SPI_CTRLB_AMODE(CONF_SERCOM_##n##_SPI_AMODE) \
2046 | SERCOM_SPI_CTRLB_CHSIZE(CONF_SERCOM_##n##_SPI_CHSIZE)), /* ctrlb */ \
2047 (SERCOM_SPI_ADDR_ADDR(CONF_SERCOM_##n##_SPI_ADDR) \
2048 | SERCOM_SPI_ADDR_ADDRMASK(CONF_SERCOM_##n##_SPI_ADDRMASK)), /* addr */ \
2049 ((uint8_t)CONF_SERCOM_##n##_SPI_BAUD_RATE), /* baud */ \
2050 (CONF_SERCOM_##n##_SPI_DBGSTOP << SERCOM_SPI_DBGCTRL_DBGSTOP_Pos), /* dbgctrl */ \
2051 CONF_SERCOM_##n##_SPI_DUMMYBYTE, /* Dummy byte for SPI master mode */ \
2052 n /* sercom number */ \
2053 }
2054
2055#ifndef CONF_SERCOM_0_SPI_ENABLE
2056#define CONF_SERCOM_0_SPI_ENABLE 0
2057#endif
2058#ifndef CONF_SERCOM_1_SPI_ENABLE
2059#define CONF_SERCOM_1_SPI_ENABLE 0
2060#endif
2061#ifndef CONF_SERCOM_2_SPI_ENABLE
2062#define CONF_SERCOM_2_SPI_ENABLE 0
2063#endif
2064#ifndef CONF_SERCOM_3_SPI_ENABLE
2065#define CONF_SERCOM_3_SPI_ENABLE 0
2066#endif
2067#ifndef CONF_SERCOM_4_SPI_ENABLE
2068#define CONF_SERCOM_4_SPI_ENABLE 0
2069#endif
2070#ifndef CONF_SERCOM_5_SPI_ENABLE
2071#define CONF_SERCOM_5_SPI_ENABLE 0
2072#endif
2073#ifndef CONF_SERCOM_6_SPI_ENABLE
2074#define CONF_SERCOM_6_SPI_ENABLE 0
2075#endif
2076#ifndef CONF_SERCOM_7_SPI_ENABLE
2077#define CONF_SERCOM_7_SPI_ENABLE 0
2078#endif
2079
2080/** Amount of SERCOM that is used as SPI */
2081#define SERCOM_SPI_AMOUNT \
2082 (CONF_SERCOM_0_SPI_ENABLE + CONF_SERCOM_1_SPI_ENABLE + CONF_SERCOM_2_SPI_ENABLE + CONF_SERCOM_3_SPI_ENABLE \
2083 + CONF_SERCOM_4_SPI_ENABLE + CONF_SERCOM_5_SPI_ENABLE + CONF_SERCOM_6_SPI_ENABLE + CONF_SERCOM_7_SPI_ENABLE)
2084
2085#if SERCOM_SPI_AMOUNT < 1
2086/** Dummy array for compiling. */
2087static const struct sercomspi_regs_cfg sercomspi_regs[1] = {{0}};
2088#else
2089/** The SERCOM SPI configurations of SERCOM that is used as SPI. */
2090static const struct sercomspi_regs_cfg sercomspi_regs[] = {
2091#if CONF_SERCOM_0_SPI_ENABLE
2092 SERCOMSPI_REGS(0),
2093#endif
2094#if CONF_SERCOM_1_SPI_ENABLE
2095 SERCOMSPI_REGS(1),
2096#endif
2097#if CONF_SERCOM_2_SPI_ENABLE
2098 SERCOMSPI_REGS(2),
2099#endif
2100#if CONF_SERCOM_3_SPI_ENABLE
2101 SERCOMSPI_REGS(3),
2102#endif
2103#if CONF_SERCOM_4_SPI_ENABLE
2104 SERCOMSPI_REGS(4),
2105#endif
2106#if CONF_SERCOM_5_SPI_ENABLE
2107 SERCOMSPI_REGS(5),
2108#endif
2109#if CONF_SERCOM_6_SPI_ENABLE
2110 SERCOMSPI_REGS(6),
2111#endif
2112#if CONF_SERCOM_7_SPI_ENABLE
2113 SERCOMSPI_REGS(7),
2114#endif
2115};
2116#endif
2117
2118/** \internal De-initialize SERCOM SPI
2119 *
2120 * \param[in] hw Pointer to the hardware register base.
2121 *
2122 * \return De-initialization status
2123 */
2124static int32_t _spi_deinit(void *const hw)
2125{
2126 hri_sercomspi_clear_CTRLA_ENABLE_bit(hw);
2127 hri_sercomspi_set_CTRLA_SWRST_bit(hw);
2128
2129 return ERR_NONE;
2130}
2131
2132/** \internal Enable SERCOM SPI
2133 *
2134 * \param[in] hw Pointer to the hardware register base.
2135 *
2136 * \return Enabling status
2137 */
2138static int32_t _spi_sync_enable(void *const hw)
2139{
2140 if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) {
2141 return ERR_BUSY;
2142 }
2143
2144 hri_sercomspi_set_CTRLA_ENABLE_bit(hw);
2145
2146 return ERR_NONE;
2147}
2148
2149/** \internal Enable SERCOM SPI
2150 *
2151 * \param[in] hw Pointer to the hardware register base.
2152 *
2153 * \return Enabling status
2154 */
2155static int32_t _spi_async_enable(void *const hw)
2156{
2157 _spi_sync_enable(hw);
2158 uint8_t irq = _sercom_get_irq_num(hw);
2159 for (uint32_t i = 0; i < 4; i++) {
2160 NVIC_EnableIRQ((IRQn_Type)irq++);
2161 }
2162
2163 return ERR_NONE;
2164}
2165
2166/** \internal Disable SERCOM SPI
2167 *
2168 * \param[in] hw Pointer to the hardware register base.
2169 *
2170 * \return Disabling status
2171 */
2172static int32_t _spi_sync_disable(void *const hw)
2173{
2174 if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) {
2175 return ERR_BUSY;
2176 }
2177 hri_sercomspi_clear_CTRLA_ENABLE_bit(hw);
2178
2179 return ERR_NONE;
2180}
2181
2182/** \internal Disable SERCOM SPI
2183 *
2184 * \param[in] hw Pointer to the hardware register base.
2185 *
2186 * \return Disabling status
2187 */
2188static int32_t _spi_async_disable(void *const hw)
2189{
2190 _spi_sync_disable(hw);
2191 hri_sercomspi_clear_INTEN_reg(
2192 hw, SERCOM_SPI_INTFLAG_ERROR | SERCOM_SPI_INTFLAG_RXC | SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE);
2193 uint8_t irq = _sercom_get_irq_num(hw);
2194 for (uint32_t i = 0; i < 4; i++) {
2195 NVIC_DisableIRQ((IRQn_Type)irq++);
2196 }
2197
2198 return ERR_NONE;
2199}
2200
2201/** \internal Set SERCOM SPI mode
2202 *
2203 * \param[in] hw Pointer to the hardware register base.
2204 * \param[in] mode The mode to set
2205 *
2206 * \return Setting mode status
2207 */
2208static int32_t _spi_set_mode(void *const hw, const enum spi_transfer_mode mode)
2209{
2210 uint32_t ctrla;
2211
2212 if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST | SERCOM_SPI_SYNCBUSY_ENABLE)) {
2213 return ERR_BUSY;
2214 }
2215
2216 ctrla = hri_sercomspi_read_CTRLA_reg(hw);
2217 ctrla &= ~(SERCOM_SPI_CTRLA_CPOL | SERCOM_SPI_CTRLA_CPHA);
2218 ctrla |= (mode & 0x3u) << SERCOM_SPI_CTRLA_CPHA_Pos;
2219 hri_sercomspi_write_CTRLA_reg(hw, ctrla);
2220
2221 return ERR_NONE;
2222}
2223
2224/** \internal Set SERCOM SPI baudrate
2225 *
2226 * \param[in] hw Pointer to the hardware register base.
2227 * \param[in] baud_val The baudrate to set
2228 *
2229 * \return Setting baudrate status
2230 */
2231static int32_t _spi_set_baudrate(void *const hw, const uint32_t baud_val)
2232{
2233 if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) {
2234 return ERR_BUSY;
2235 }
2236
2237 hri_sercomspi_write_BAUD_reg(hw, baud_val);
2238
2239 return ERR_NONE;
2240}
2241
2242/** \internal Set SERCOM SPI char size
2243 *
2244 * \param[in] hw Pointer to the hardware register base.
2245 * \param[in] baud_val The baudrate to set
2246 * \param[out] size Stored char size
2247 *
2248 * \return Setting char size status
2249 */
2250static int32_t _spi_set_char_size(void *const hw, const enum spi_char_size char_size, uint8_t *const size)
2251{
2252 /* Only 8-bit or 9-bit accepted */
2253 if (!(char_size == SPI_CHAR_SIZE_8 || char_size == SPI_CHAR_SIZE_9)) {
2254 return ERR_INVALID_ARG;
2255 }
2256
2257 if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST | SERCOM_SPI_SYNCBUSY_CTRLB)) {
2258 return ERR_BUSY;
2259 }
2260
2261 hri_sercomspi_write_CTRLB_CHSIZE_bf(hw, char_size);
2262 *size = (char_size == SPI_CHAR_SIZE_8) ? 1 : 2;
2263
2264 return ERR_NONE;
2265}
2266
2267/** \internal Set SERCOM SPI data order
2268 *
2269 * \param[in] hw Pointer to the hardware register base.
2270 * \param[in] baud_val The baudrate to set
2271 *
2272 * \return Setting data order status
2273 */
2274static int32_t _spi_set_data_order(void *const hw, const enum spi_data_order dord)
2275{
2276 uint32_t ctrla;
2277
2278 if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) {
2279 return ERR_BUSY;
2280 }
2281
2282 ctrla = hri_sercomspi_read_CTRLA_reg(hw);
2283
2284 if (dord == SPI_DATA_ORDER_LSB_1ST) {
2285 ctrla |= SERCOM_SPI_CTRLA_DORD;
2286 } else {
2287 ctrla &= ~SERCOM_SPI_CTRLA_DORD;
2288 }
2289 hri_sercomspi_write_CTRLA_reg(hw, ctrla);
2290
2291 return ERR_NONE;
2292}
2293
2294/** \brief Load SERCOM registers to init for SPI master mode
2295 * The settings will be applied with default master mode, unsupported things
2296 * are ignored.
2297 * \param[in, out] hw Pointer to the hardware register base.
2298 * \param[in] regs Pointer to register configuration values.
2299 */
2300static inline void _spi_load_regs_master(void *const hw, const struct sercomspi_regs_cfg *regs)
2301{
2302 ASSERT(hw && regs);
2303 hri_sercomspi_write_CTRLA_reg(
2304 hw, regs->ctrla & ~(SERCOM_SPI_CTRLA_IBON | SERCOM_SPI_CTRLA_ENABLE | SERCOM_SPI_CTRLA_SWRST));
2305 hri_sercomspi_write_CTRLB_reg(
2306 hw,
2307 (regs->ctrlb
2308 & ~(SERCOM_SPI_CTRLB_MSSEN | SERCOM_SPI_CTRLB_AMODE_Msk | SERCOM_SPI_CTRLB_SSDE | SERCOM_SPI_CTRLB_PLOADEN))
2309 | (SERCOM_SPI_CTRLB_RXEN));
2310 hri_sercomspi_write_BAUD_reg(hw, regs->baud);
2311 hri_sercomspi_write_DBGCTRL_reg(hw, regs->dbgctrl);
2312}
2313
2314/** \brief Load SERCOM registers to init for SPI slave mode
2315 * The settings will be applied with default slave mode, unsupported things
2316 * are ignored.
2317 * \param[in, out] hw Pointer to the hardware register base.
2318 * \param[in] regs Pointer to register configuration values.
2319 */
2320static inline void _spi_load_regs_slave(void *const hw, const struct sercomspi_regs_cfg *regs)
2321{
2322 ASSERT(hw && regs);
2323 hri_sercomspi_write_CTRLA_reg(
2324 hw, regs->ctrla & ~(SERCOM_SPI_CTRLA_IBON | SERCOM_SPI_CTRLA_ENABLE | SERCOM_SPI_CTRLA_SWRST));
2325 hri_sercomspi_write_CTRLB_reg(hw,
2326 (regs->ctrlb & ~(SERCOM_SPI_CTRLB_MSSEN))
2327 | (SERCOM_SPI_CTRLB_RXEN | SERCOM_SPI_CTRLB_SSDE | SERCOM_SPI_CTRLB_PLOADEN));
2328 hri_sercomspi_write_ADDR_reg(hw, regs->addr);
2329 hri_sercomspi_write_DBGCTRL_reg(hw, regs->dbgctrl);
2330 while (hri_sercomspi_is_syncing(hw, 0xFFFFFFFF))
2331 ;
2332}
2333
2334/** \brief Return the pointer to register settings of specific SERCOM
2335 * \param[in] hw_addr The hardware register base address.
2336 * \return Pointer to register settings of specific SERCOM.
2337 */
2338static inline const struct sercomspi_regs_cfg *_spi_get_regs(const uint32_t hw_addr)
2339{
2340 uint8_t n = _sercom_get_hardware_index((const void *)hw_addr);
2341 uint8_t i;
2342
2343 for (i = 0; i < sizeof(sercomspi_regs) / sizeof(struct sercomspi_regs_cfg); i++) {
2344 if (sercomspi_regs[i].n == n) {
2345 return &sercomspi_regs[i];
2346 }
2347 }
2348
2349 return NULL;
2350}
2351
2352int32_t _spi_m_sync_init(struct _spi_m_sync_dev *dev, void *const hw)
2353{
2354 const struct sercomspi_regs_cfg *regs = _spi_get_regs((uint32_t)hw);
2355
2356 ASSERT(dev && hw);
2357
2358 if (regs == NULL) {
2359 return ERR_INVALID_ARG;
2360 }
2361
2362 if (!hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) {
2363 uint32_t mode = regs->ctrla & SERCOM_SPI_CTRLA_MODE_Msk;
2364 if (hri_sercomspi_get_CTRLA_reg(hw, SERCOM_SPI_CTRLA_ENABLE)) {
2365 hri_sercomspi_clear_CTRLA_ENABLE_bit(hw);
2366 hri_sercomspi_wait_for_sync(hw, SERCOM_SPI_SYNCBUSY_ENABLE);
2367 }
2368 hri_sercomspi_write_CTRLA_reg(hw, SERCOM_SPI_CTRLA_SWRST | mode);
2369 }
2370 hri_sercomspi_wait_for_sync(hw, SERCOM_SPI_SYNCBUSY_SWRST);
2371
2372 dev->prvt = hw;
2373
2374 if ((regs->ctrla & SERCOM_SPI_CTRLA_MODE_Msk) == SERCOM_USART_CTRLA_MODE_SPI_SLAVE) {
2375 _spi_load_regs_slave(hw, regs);
2376 } else {
2377 _spi_load_regs_master(hw, regs);
2378 }
2379
2380 /* Load character size from default hardware configuration */
2381 dev->char_size = ((regs->ctrlb & SERCOM_SPI_CTRLB_CHSIZE_Msk) == 0) ? 1 : 2;
2382
2383 dev->dummy_byte = regs->dummy_byte;
2384
2385 return ERR_NONE;
2386}
2387
2388int32_t _spi_s_sync_init(struct _spi_s_sync_dev *dev, void *const hw)
2389{
2390 return _spi_m_sync_init(dev, hw);
2391}
2392
2393int32_t _spi_m_async_init(struct _spi_async_dev *dev, void *const hw)
2394{
2395 struct _spi_async_dev *spid = dev;
2396 /* Do hardware initialize. */
2397 int32_t rc = _spi_m_sync_init((struct _spi_m_sync_dev *)dev, hw);
2398
2399 if (rc < 0) {
2400 return rc;
2401 }
2402
2403 _sercom_init_irq_param(hw, (void *)dev);
2404 /* Initialize callbacks: must use them */
2405 spid->callbacks.complete = NULL;
2406 spid->callbacks.rx = NULL;
2407 spid->callbacks.tx = NULL;
2408 uint8_t irq = _sercom_get_irq_num(hw);
2409 for (uint32_t i = 0; i < 4; i++) {
2410 NVIC_DisableIRQ((IRQn_Type)irq);
2411 NVIC_ClearPendingIRQ((IRQn_Type)irq);
2412 irq++;
2413 }
2414
2415 return ERR_NONE;
2416}
2417
2418int32_t _spi_s_async_init(struct _spi_s_async_dev *dev, void *const hw)
2419{
2420 return _spi_m_async_init(dev, hw);
2421}
2422
2423int32_t _spi_m_async_deinit(struct _spi_async_dev *dev)
2424{
2425 NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(dev->prvt));
2426 NVIC_ClearPendingIRQ((IRQn_Type)_sercom_get_irq_num(dev->prvt));
2427
2428 return _spi_deinit(dev->prvt);
2429}
2430
2431int32_t _spi_s_async_deinit(struct _spi_s_async_dev *dev)
2432{
2433 NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(dev->prvt));
2434 NVIC_ClearPendingIRQ((IRQn_Type)_sercom_get_irq_num(dev->prvt));
2435
2436 return _spi_deinit(dev->prvt);
2437}
2438
2439int32_t _spi_m_sync_deinit(struct _spi_m_sync_dev *dev)
2440{
2441 return _spi_deinit(dev->prvt);
2442}
2443
2444int32_t _spi_s_sync_deinit(struct _spi_s_sync_dev *dev)
2445{
2446 return _spi_deinit(dev->prvt);
2447}
2448
2449int32_t _spi_m_sync_enable(struct _spi_m_sync_dev *dev)
2450{
2451 ASSERT(dev && dev->prvt);
2452
2453 return _spi_sync_enable(dev->prvt);
2454}
2455
2456int32_t _spi_s_sync_enable(struct _spi_s_sync_dev *dev)
2457{
2458 ASSERT(dev && dev->prvt);
2459
2460 return _spi_sync_enable(dev->prvt);
2461}
2462
2463int32_t _spi_m_async_enable(struct _spi_async_dev *dev)
2464{
2465 ASSERT(dev && dev->prvt);
2466
2467 return _spi_async_enable(dev->prvt);
2468}
2469
2470int32_t _spi_s_async_enable(struct _spi_s_async_dev *dev)
2471{
2472 ASSERT(dev && dev->prvt);
2473
2474 return _spi_async_enable(dev->prvt);
2475}
2476
2477int32_t _spi_m_sync_disable(struct _spi_m_sync_dev *dev)
2478{
2479 ASSERT(dev && dev->prvt);
2480
2481 return _spi_sync_disable(dev->prvt);
2482}
2483
2484int32_t _spi_s_sync_disable(struct _spi_s_sync_dev *dev)
2485{
2486 ASSERT(dev && dev->prvt);
2487
2488 return _spi_sync_disable(dev->prvt);
2489}
2490
2491int32_t _spi_m_async_disable(struct _spi_async_dev *dev)
2492{
2493 ASSERT(dev && dev->prvt);
2494
2495 return _spi_async_disable(dev->prvt);
2496}
2497
2498int32_t _spi_s_async_disable(struct _spi_s_async_dev *dev)
2499{
2500 ASSERT(dev && dev->prvt);
2501
2502 return _spi_async_disable(dev->prvt);
2503}
2504
2505int32_t _spi_m_sync_set_mode(struct _spi_m_sync_dev *dev, const enum spi_transfer_mode mode)
2506{
2507 ASSERT(dev && dev->prvt);
2508
2509 return _spi_set_mode(dev->prvt, mode);
2510}
2511
2512int32_t _spi_m_async_set_mode(struct _spi_async_dev *dev, const enum spi_transfer_mode mode)
2513{
2514 ASSERT(dev && dev->prvt);
2515
2516 return _spi_set_mode(dev->prvt, mode);
2517}
2518
2519int32_t _spi_s_async_set_mode(struct _spi_s_async_dev *dev, const enum spi_transfer_mode mode)
2520{
2521 ASSERT(dev && dev->prvt);
2522
2523 return _spi_set_mode(dev->prvt, mode);
2524}
2525
2526int32_t _spi_s_sync_set_mode(struct _spi_s_sync_dev *dev, const enum spi_transfer_mode mode)
2527{
2528 ASSERT(dev && dev->prvt);
2529
2530 return _spi_set_mode(dev->prvt, mode);
2531}
2532
2533int32_t _spi_calc_baud_val(struct spi_dev *dev, const uint32_t clk, const uint32_t baud)
2534{
2535 int32_t rc;
2536 ASSERT(dev);
2537
2538 /* Not accept 0es */
2539 if (clk == 0 || baud == 0) {
2540 return ERR_INVALID_ARG;
2541 }
2542
2543 /* Check baudrate range of current assigned clock */
2544 if (!(baud <= (clk >> 1) && baud >= (clk >> 8))) {
2545 return ERR_INVALID_ARG;
2546 }
2547
2548 rc = ((clk >> 1) / baud) - 1;
2549 return rc;
2550}
2551
2552int32_t _spi_m_sync_set_baudrate(struct _spi_m_sync_dev *dev, const uint32_t baud_val)
2553{
2554 ASSERT(dev && dev->prvt);
2555
2556 return _spi_set_baudrate(dev->prvt, baud_val);
2557}
2558
2559int32_t _spi_m_async_set_baudrate(struct _spi_async_dev *dev, const uint32_t baud_val)
2560{
2561 ASSERT(dev && dev->prvt);
2562
2563 return _spi_set_baudrate(dev->prvt, baud_val);
2564}
2565
2566int32_t _spi_m_sync_set_char_size(struct _spi_m_sync_dev *dev, const enum spi_char_size char_size)
2567{
2568 ASSERT(dev && dev->prvt);
2569
2570 return _spi_set_char_size(dev->prvt, char_size, &dev->char_size);
2571}
2572
2573int32_t _spi_m_async_set_char_size(struct _spi_async_dev *dev, const enum spi_char_size char_size)
2574{
2575 ASSERT(dev && dev->prvt);
2576
2577 return _spi_set_char_size(dev->prvt, char_size, &dev->char_size);
2578}
2579
2580int32_t _spi_s_async_set_char_size(struct _spi_s_async_dev *dev, const enum spi_char_size char_size)
2581{
2582 ASSERT(dev && dev->prvt);
2583
2584 return _spi_set_char_size(dev->prvt, char_size, &dev->char_size);
2585}
2586
2587int32_t _spi_s_sync_set_char_size(struct _spi_s_sync_dev *dev, const enum spi_char_size char_size)
2588{
2589 ASSERT(dev && dev->prvt);
2590
2591 return _spi_set_char_size(dev->prvt, char_size, &dev->char_size);
2592}
2593
2594int32_t _spi_m_sync_set_data_order(struct _spi_m_sync_dev *dev, const enum spi_data_order dord)
2595{
2596 ASSERT(dev && dev->prvt);
2597
2598 return _spi_set_data_order(dev->prvt, dord);
2599}
2600
2601int32_t _spi_m_async_set_data_order(struct _spi_async_dev *dev, const enum spi_data_order dord)
2602{
2603 ASSERT(dev && dev->prvt);
2604
2605 return _spi_set_data_order(dev->prvt, dord);
2606}
2607
2608int32_t _spi_s_async_set_data_order(struct _spi_s_async_dev *dev, const enum spi_data_order dord)
2609{
2610 ASSERT(dev && dev->prvt);
2611
2612 return _spi_set_data_order(dev->prvt, dord);
2613}
2614
2615int32_t _spi_s_sync_set_data_order(struct _spi_s_sync_dev *dev, const enum spi_data_order dord)
2616{
2617 ASSERT(dev && dev->prvt);
2618
2619 return _spi_set_data_order(dev->prvt, dord);
2620}
2621
2622/** Wait until SPI bus idle. */
2623static inline void _spi_wait_bus_idle(void *const hw)
2624{
2625 while (!(hri_sercomspi_get_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE))) {
2626 ;
2627 }
2628 hri_sercomspi_clear_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE);
2629}
2630
2631/** Holds run time information for message sync transaction. */
2632struct _spi_trans_ctrl {
2633 /** Pointer to transmitting data buffer. */
2634 uint8_t *txbuf;
2635 /** Pointer to receiving data buffer. */
2636 uint8_t *rxbuf;
2637 /** Count number of data transmitted. */
2638 uint32_t txcnt;
2639 /** Count number of data received. */
2640 uint32_t rxcnt;
2641 /** Data character size. */
2642 uint8_t char_size;
2643};
2644
2645/** Check interrupt flag of RXC and update transaction runtime information. */
2646static inline bool _spi_rx_check_and_receive(void *const hw, const uint32_t iflag, struct _spi_trans_ctrl *ctrl)
2647{
2648 uint32_t data;
2649
2650 if (!(iflag & SERCOM_SPI_INTFLAG_RXC)) {
2651 return false;
2652 }
2653
2654 data = hri_sercomspi_read_DATA_reg(hw);
2655
2656 if (ctrl->rxbuf) {
2657 *ctrl->rxbuf++ = (uint8_t)data;
2658
2659 if (ctrl->char_size > 1) {
2660 *ctrl->rxbuf++ = (uint8_t)(data >> 8);
2661 }
2662 }
2663
2664 ctrl->rxcnt++;
2665
2666 return true;
2667}
2668
2669/** Check interrupt flag of DRE and update transaction runtime information. */
2670static inline void _spi_tx_check_and_send(void *const hw, const uint32_t iflag, struct _spi_trans_ctrl *ctrl,
2671 uint16_t dummy)
2672{
2673 uint32_t data;
2674
2675 if (!(SERCOM_SPI_INTFLAG_DRE & iflag)) {
2676 return;
2677 }
2678
2679 if (ctrl->txbuf) {
2680 data = *ctrl->txbuf++;
2681
2682 if (ctrl->char_size > 1) {
2683 data |= (*ctrl->txbuf) << 8;
2684 ctrl->txbuf++;
2685 }
2686 } else {
2687 data = dummy;
2688 }
2689
2690 ctrl->txcnt++;
2691 hri_sercomspi_write_DATA_reg(hw, data);
2692}
2693
2694/** Check interrupt flag of ERROR and update transaction runtime information. */
2695static inline int32_t _spi_err_check(const uint32_t iflag, void *const hw)
2696{
2697 if (SERCOM_SPI_INTFLAG_ERROR & iflag) {
2698 hri_sercomspi_clear_STATUS_reg(hw, ~0);
2699 hri_sercomspi_clear_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_ERROR);
2700 return ERR_OVERFLOW;
2701 }
2702
2703 return ERR_NONE;
2704}
2705
2706int32_t _spi_m_sync_trans(struct _spi_m_sync_dev *dev, const struct spi_msg *msg)
2707{
2708 void * hw = dev->prvt;
2709 int32_t rc = 0;
2710 struct _spi_trans_ctrl ctrl = {msg->txbuf, msg->rxbuf, 0, 0, dev->char_size};
2711
2712 ASSERT(dev && hw);
2713
2714 /* If settings are not applied (pending), we can not go on */
2715 if (hri_sercomspi_is_syncing(
2716 hw, (SERCOM_SPI_SYNCBUSY_SWRST | SERCOM_SPI_SYNCBUSY_ENABLE | SERCOM_SPI_SYNCBUSY_CTRLB))) {
2717 return ERR_BUSY;
2718 }
2719
2720 /* SPI must be enabled to start synchronous transfer */
2721 if (!hri_sercomspi_get_CTRLA_ENABLE_bit(hw)) {
2722 return ERR_NOT_INITIALIZED;
2723 }
2724
2725 for (;;) {
2726 uint32_t iflag = hri_sercomspi_read_INTFLAG_reg(hw);
2727
2728 if (!_spi_rx_check_and_receive(hw, iflag, &ctrl)) {
2729 /* In master mode, do not start next byte before previous byte received
2730 * to make better output waveform */
2731 if (ctrl.rxcnt >= ctrl.txcnt) {
2732 _spi_tx_check_and_send(hw, iflag, &ctrl, dev->dummy_byte);
2733 }
2734 }
2735
2736 rc = _spi_err_check(iflag, hw);
2737
2738 if (rc < 0) {
2739 break;
2740 }
2741 if (ctrl.txcnt >= msg->size && ctrl.rxcnt >= msg->size) {
2742 rc = ctrl.txcnt;
2743 break;
2744 }
2745 }
2746 /* Wait until SPI bus idle */
2747 _spi_wait_bus_idle(hw);
2748
2749 return rc;
2750}
2751
2752int32_t _spi_m_async_enable_tx(struct _spi_async_dev *dev, bool state)
2753{
2754 void *hw = dev->prvt;
2755
2756 ASSERT(dev && hw);
2757
2758 if (state) {
2759 hri_sercomspi_set_INTEN_DRE_bit(hw);
2760 } else {
2761 hri_sercomspi_clear_INTEN_DRE_bit(hw);
2762 }
2763
2764 return ERR_NONE;
2765}
2766
2767int32_t _spi_s_async_enable_tx(struct _spi_s_async_dev *dev, bool state)
2768{
2769 return _spi_m_async_enable_tx(dev, state);
2770}
2771
2772int32_t _spi_m_async_enable_rx(struct _spi_async_dev *dev, bool state)
2773{
2774 void *hw = dev->prvt;
2775
2776 ASSERT(dev);
2777 ASSERT(hw);
2778
2779 if (state) {
2780 hri_sercomspi_set_INTEN_RXC_bit(hw);
2781 } else {
2782 hri_sercomspi_clear_INTEN_RXC_bit(hw);
2783 }
2784
2785 return ERR_NONE;
2786}
2787
2788int32_t _spi_s_async_enable_rx(struct _spi_s_async_dev *dev, bool state)
2789{
2790 return _spi_m_async_enable_rx(dev, state);
2791}
2792
2793int32_t _spi_m_async_enable_tx_complete(struct _spi_async_dev *dev, bool state)
2794{
2795 ASSERT(dev && dev->prvt);
2796
2797 if (state) {
2798 hri_sercomspi_set_INTEN_TXC_bit(dev->prvt);
2799 } else {
2800 hri_sercomspi_clear_INTEN_TXC_bit(dev->prvt);
2801 }
2802
2803 return ERR_NONE;
2804}
2805
2806int32_t _spi_s_async_enable_ss_detect(struct _spi_s_async_dev *dev, bool state)
2807{
2808 return _spi_m_async_enable_tx_complete(dev, state);
2809}
2810
2811int32_t _spi_m_async_write_one(struct _spi_async_dev *dev, uint16_t data)
2812{
2813 ASSERT(dev && dev->prvt);
2814
2815 hri_sercomspi_write_DATA_reg(dev->prvt, data);
2816
2817 return ERR_NONE;
2818}
2819
2820int32_t _spi_s_async_write_one(struct _spi_s_async_dev *dev, uint16_t data)
2821{
2822 ASSERT(dev && dev->prvt);
2823
2824 hri_sercomspi_write_DATA_reg(dev->prvt, data);
2825
2826 return ERR_NONE;
2827}
2828
2829int32_t _spi_s_sync_write_one(struct _spi_s_sync_dev *dev, uint16_t data)
2830{
2831 ASSERT(dev && dev->prvt);
2832
2833 hri_sercomspi_write_DATA_reg(dev->prvt, data);
2834
2835 return ERR_NONE;
2836}
2837
2838uint16_t _spi_m_async_read_one(struct _spi_async_dev *dev)
2839{
2840 ASSERT(dev && dev->prvt);
2841
2842 return hri_sercomspi_read_DATA_reg(dev->prvt);
2843}
2844
2845uint16_t _spi_s_async_read_one(struct _spi_s_async_dev *dev)
2846{
2847 ASSERT(dev && dev->prvt);
2848
2849 return hri_sercomspi_read_DATA_reg(dev->prvt);
2850}
2851
2852uint16_t _spi_s_sync_read_one(struct _spi_s_sync_dev *dev)
2853{
2854 ASSERT(dev && dev->prvt);
2855
2856 return hri_sercomspi_read_DATA_reg(dev->prvt);
2857}
2858
2859int32_t _spi_m_async_register_callback(struct _spi_async_dev *dev, const enum _spi_async_dev_cb_type cb_type,
2860 const FUNC_PTR func)
2861{
2862 typedef void (*func_t)(void);
2863 struct _spi_async_dev *spid = dev;
2864
2865 ASSERT(dev && (cb_type < SPI_DEV_CB_N));
2866
2867 func_t *p_ls = (func_t *)&spid->callbacks;
2868 p_ls[cb_type] = (func_t)func;
2869
2870 return ERR_NONE;
2871}
2872
2873int32_t _spi_s_async_register_callback(struct _spi_s_async_dev *dev, const enum _spi_s_async_dev_cb_type cb_type,
2874 const FUNC_PTR func)
2875{
2876 return _spi_m_async_register_callback(dev, cb_type, func);
2877}
2878
2879bool _spi_s_sync_is_tx_ready(struct _spi_s_sync_dev *dev)
2880{
2881 ASSERT(dev && dev->prvt);
2882
2883 return hri_sercomi2cm_get_INTFLAG_reg(dev->prvt, SERCOM_SPI_INTFLAG_DRE);
2884}
2885
2886bool _spi_s_sync_is_rx_ready(struct _spi_s_sync_dev *dev)
2887{
2888 ASSERT(dev && dev->prvt);
2889
2890 return hri_sercomi2cm_get_INTFLAG_reg(dev->prvt, SERCOM_SPI_INTFLAG_RXC);
2891}
2892
2893bool _spi_s_sync_is_ss_deactivated(struct _spi_s_sync_dev *dev)
2894{
2895 void *hw = dev->prvt;
2896
2897 ASSERT(dev && hw);
2898
2899 if (hri_sercomi2cm_get_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_TXC)) {
2900 hri_sercomspi_clear_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_TXC);
2901 return true;
2902 }
2903 return false;
2904}
2905
2906bool _spi_s_sync_is_error(struct _spi_s_sync_dev *dev)
2907{
2908 void *hw = dev->prvt;
2909
2910 ASSERT(dev && hw);
2911
2912 if (hri_sercomi2cm_get_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_ERROR)) {
2913 hri_sercomspi_clear_STATUS_reg(hw, SERCOM_SPI_STATUS_BUFOVF);
2914 hri_sercomspi_clear_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_ERROR);
2915 return true;
2916 }
2917 return false;
2918}
2919
2920/**
2921 * \brief Enable/disable SPI master interrupt
2922 *
2923 * param[in] device The pointer to SPI master device instance
2924 * param[in] type The type of interrupt to disable/enable if applicable
2925 * param[in] state Enable or disable
2926 */
2927void _spi_m_async_set_irq_state(struct _spi_async_dev *const device, const enum _spi_async_dev_cb_type type,
2928 const bool state)
2929{
2930 ASSERT(device);
2931
2932 if (SPI_DEV_CB_ERROR == type) {
2933 hri_sercomspi_write_INTEN_ERROR_bit(device->prvt, state);
2934 }
2935}
2936
2937/**
2938 * \brief Enable/disable SPI slave interrupt
2939 *
2940 * param[in] device The pointer to SPI slave device instance
2941 * param[in] type The type of interrupt to disable/enable if applicable
2942 * param[in] state Enable or disable
2943 */
2944void _spi_s_async_set_irq_state(struct _spi_async_dev *const device, const enum _spi_async_dev_cb_type type,
2945 const bool state)
2946{
2947 _spi_m_async_set_irq_state(device, type, state);
2948}