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