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