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