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