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