1 /**
2  * \file
3  *
4  * \brief SAM SERCOM I2C Slave Driver
5  *
6  * Copyright (c) 2013-2016 Atmel Corporation. All rights reserved.
7  *
8  * \asf_license_start
9  *
10  * \page License
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright notice,
16  *    this list of conditions and the following disclaimer.
17  *
18  * 2. Redistributions in binary form must reproduce the above copyright notice,
19  *    this list of conditions and the following disclaimer in the documentation
20  *    and/or other materials provided with the distribution.
21  *
22  * 3. The name of Atmel may not be used to endorse or promote products derived
23  *    from this software without specific prior written permission.
24  *
25  * 4. This software may only be redistributed and used in connection with an
26  *    Atmel microcontroller product.
27  *
28  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  *
40  * \asf_license_stop
41  *
42  */
43 /*
44  * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45  */
46 
47 #ifndef I2C_SLAVE_H_INCLUDED
48 #define I2C_SLAVE_H_INCLUDED
49 
50 #include "i2c_common.h"
51 #include <sercom.h>
52 #include <pinmux.h>
53 
54 #if I2C_SLAVE_CALLBACK_MODE == true
55 #  include <sercom_interrupt.h>
56 #endif
57 
58 #ifndef PINMUX_DEFAULT
59 #  define PINMUX_DEFAULT 0
60 #endif
61 
62 #ifdef __cplusplus
63 extern "C" {
64 #endif
65 
66 /**
67  * \addtogroup asfdoc_sam0_sercom_i2c_group
68  *
69  * @{
70  *
71  */
72 
73 /**
74  * \name I2C Slave Status Flags
75  *
76  * I<SUP>2</SUP>C slave status flags, returned by \ref i2c_slave_get_status() and cleared
77  * by \ref i2c_slave_clear_status().
78  * @{
79  */
80 
81 /** Address Match.
82  * \note Should only be cleared internally by driver.
83  */
84 #define I2C_SLAVE_STATUS_ADDRESS_MATCH     (1UL << 0)
85 /** Data Ready. */
86 #define I2C_SLAVE_STATUS_DATA_READY        (1UL << 1)
87 /** Stop Received. */
88 #define I2C_SLAVE_STATUS_STOP_RECEIVED     (1UL << 2)
89 /** Clock Hold.
90  * \note Cannot be cleared, only valid when I2C_SLAVE_STATUS_ADDRESS_MATCH is
91  * set.
92  */
93 #define I2C_SLAVE_STATUS_CLOCK_HOLD        (1UL << 3)
94 /** SCL Low Timeout. */
95 #define I2C_SLAVE_STATUS_SCL_LOW_TIMEOUT   (1UL << 4)
96 /** Repeated Start.
97  * \note Cannot be cleared, only valid when I2C_SLAVE_STATUS_ADDRESS_MATCH is
98  * set.
99  */
100 #define I2C_SLAVE_STATUS_REPEATED_START    (1UL << 5)
101 /** Received not acknowledge.
102  * \note Cannot be cleared.
103  */
104 #define I2C_SLAVE_STATUS_RECEIVED_NACK     (1UL << 6)
105 /** Transmit Collision. */
106 #define I2C_SLAVE_STATUS_COLLISION         (1UL << 7)
107 /** Bus error. */
108 #define I2C_SLAVE_STATUS_BUS_ERROR         (1UL << 8)
109 
110 /** @} */
111 
112 /**
113  * \brief I<SUP>2</SUP>C slave packet for read/write
114  *
115  * Structure to be used when transferring I<SUP>2</SUP>C slave packets.
116  */
117 struct i2c_slave_packet {
118 	/** Length of data array */
119 	uint16_t data_length;
120 	/** Data array containing all data to be transferred */
121 	uint8_t *data;
122 };
123 
124 #if I2C_SLAVE_CALLBACK_MODE == true
125  /**
126  * \brief Callback types
127  *
128  * The available callback types for the I<SUP>2</SUP>C slave.
129  */
130 enum i2c_slave_callback {
131 	/** Callback for packet write complete */
132 	I2C_SLAVE_CALLBACK_WRITE_COMPLETE,
133 	/** Callback for packet read complete */
134 	I2C_SLAVE_CALLBACK_READ_COMPLETE,
135 	/**
136 	 * Callback for read request from master - can be used to
137 	 * issue a write
138 	 */
139 	I2C_SLAVE_CALLBACK_READ_REQUEST,
140 	/**
141 	 * Callback for write request from master - can be used to issue a read
142 	 */
143 	I2C_SLAVE_CALLBACK_WRITE_REQUEST,
144 	/** Callback for error */
145 	I2C_SLAVE_CALLBACK_ERROR,
146 	/**
147 	 * Callback for error in last transfer. Discovered on a new address
148 	 * interrupt.
149 	 */
150 	I2C_SLAVE_CALLBACK_ERROR_LAST_TRANSFER,
151 #  if !defined(__DOXYGEN__)
152 	/** Total number of callbacks */
153 	_I2C_SLAVE_CALLBACK_N,
154 #  endif
155 };
156 
157 #  if !defined(__DOXYGEN__)
158 /** Software module prototype */
159 struct i2c_slave_module;
160 
161 /** Callback type */
162 typedef void (*i2c_slave_callback_t)(
163 		struct i2c_slave_module *const module);
164 #  endif
165 #endif
166 
167 /**
168  * \brief Enum for the possible SDA hold times with respect to the negative
169  * edge of SCL
170  *
171  * Enum for the possible SDA hold times with respect to the negative edge
172  * of SCL.
173  */
174 enum i2c_slave_sda_hold_time {
175 	/** SDA hold time disabled */
176 	I2C_SLAVE_SDA_HOLD_TIME_DISABLED =
177 			((SERCOM_I2CS_CTRLA_SDAHOLD_Msk & ((0) << SERCOM_I2CS_CTRLA_SDAHOLD_Pos))),
178 	/** SDA hold time 50ns - 100ns */
179 	I2C_SLAVE_SDA_HOLD_TIME_50NS_100NS =
180 			((SERCOM_I2CS_CTRLA_SDAHOLD_Msk & ((1) << SERCOM_I2CS_CTRLA_SDAHOLD_Pos))),
181 	/** SDA hold time 300ns - 600ns */
182 	I2C_SLAVE_SDA_HOLD_TIME_300NS_600NS =
183 			((SERCOM_I2CS_CTRLA_SDAHOLD_Msk & ((2) << SERCOM_I2CS_CTRLA_SDAHOLD_Pos))),
184 	/** SDA hold time 400ns - 800ns */
185 	I2C_SLAVE_SDA_HOLD_TIME_400NS_800NS =
186 			((SERCOM_I2CS_CTRLA_SDAHOLD_Msk & ((3) << SERCOM_I2CS_CTRLA_SDAHOLD_Pos))),
187 };
188 
189 /**
190  * \brief Enum for the possible address modes
191  *
192  * Enum for the possible address modes.
193  */
194 enum i2c_slave_address_mode {
195 	/** Address match on address_mask used as a mask to address */
196 	I2C_SLAVE_ADDRESS_MODE_MASK = SERCOM_I2CS_CTRLB_AMODE(0),
197 	/** Address math on both address and address_mask */
198 	I2C_SLAVE_ADDRESS_MODE_TWO_ADDRESSES = SERCOM_I2CS_CTRLB_AMODE(1),
199 	/**
200 	 * Address match on range of addresses between and including address and
201 	 * address_mask
202 	 */
203 	I2C_SLAVE_ADDRESS_MODE_RANGE = SERCOM_I2CS_CTRLB_AMODE(2),
204 };
205 
206 /**
207  * \brief Enum for the direction of a request
208  *
209  * Enum for the direction of a request.
210  */
211 enum i2c_slave_direction {
212 	/** Read */
213 	I2C_SLAVE_DIRECTION_READ,
214 	/** Write */
215 	I2C_SLAVE_DIRECTION_WRITE,
216 	/** No direction */
217 	I2C_SLAVE_DIRECTION_NONE,
218 };
219 
220 #ifdef FEATURE_I2C_FAST_MODE_PLUS_AND_HIGH_SPEED
221 /**
222  * \brief Enum for the transfer speed
223  *
224  * Enum for the transfer speed.
225  */
226 enum i2c_slave_transfer_speed {
227 	/** Standard-mode (Sm) up to 100KHz and Fast-mode (Fm) up to 400KHz */
228 	I2C_SLAVE_SPEED_STANDARD_AND_FAST = SERCOM_I2CS_CTRLA_SPEED(0),
229 	/** Fast-mode Plus (Fm+) up to 1MHz */
230 	I2C_SLAVE_SPEED_FAST_MODE_PLUS = SERCOM_I2CS_CTRLA_SPEED(1),
231 	/** High-speed mode (Hs-mode) up to 3.4MHz */
232 	I2C_SLAVE_SPEED_HIGH_SPEED = SERCOM_I2CS_CTRLA_SPEED(2),
233 };
234 #endif
235 
236 /**
237  * \brief SERCOM I<SUP>2</SUP>C slave driver software device instance structure.
238  *
239  * SERCOM I<SUP>2</SUP>C slave driver software instance structure, used to
240  * retain software state information of an associated hardware module instance.
241  *
242  * \note The fields of this structure should not be altered by the user
243  *       application; they are reserved for module-internal use only.
244  */
245 struct i2c_slave_module {
246 #if !defined(__DOXYGEN__)
247 	/** Hardware instance initialized for the struct */
248 	Sercom *hw;
249 	/** Module lock */
250 	volatile bool locked;
251 	/** Timeout value for polled functions */
252 	uint16_t buffer_timeout;
253 #  ifdef FEATURE_I2C_10_BIT_ADDRESS
254 	/** Using 10-bit addressing for the slave */
255 	bool ten_bit_address;
256 #  endif
257 #  if I2C_SLAVE_CALLBACK_MODE == true
258 	/** Nack on address match */
259 	bool nack_on_address;
260 	/** Pointers to callback functions */
261 	volatile i2c_slave_callback_t callbacks[_I2C_SLAVE_CALLBACK_N];
262 	/** Mask for registered callbacks */
263 	volatile uint8_t registered_callback;
264 	/** Mask for enabled callbacks */
265 	volatile uint8_t enabled_callback;
266 	/** The total number of bytes to transfer */
267 	volatile uint16_t buffer_length;
268 	/**
269 	 * Counter used for bytes left to send in write and to count number of
270 	 * obtained bytes in read
271 	 */
272 	uint16_t buffer_remaining;
273 	/** Data buffer for packet write and read */
274 	volatile uint8_t *buffer;
275 	/** Save direction of request from master. 1 = read, 0 = write. */
276 	volatile enum i2c_transfer_direction transfer_direction;
277 	/** Status for status read back in error callback */
278 	volatile enum status_code status;
279 #  endif
280 #endif
281 };
282 
283 /**
284  * \brief Configuration structure for the I<SUP>2</SUP>C slave device
285  *
286  * This is the configuration structure for the I<SUP>2</SUP>C slave device. It is used
287  * as an argument for \ref i2c_slave_init to provide the desired
288  * configurations for the module. The structure should be initialized using the
289  * \ref i2c_slave_get_config_defaults.
290  */
291 struct i2c_slave_config {
292 	/** Set to enable the SCL low timeout */
293 	bool enable_scl_low_timeout;
294 	/** SDA hold time with respect to the negative edge of SCL */
295 	enum i2c_slave_sda_hold_time sda_hold_time;
296 	/** Timeout to wait for master in polled functions */
297 	uint16_t buffer_timeout;
298 	/** Addressing mode */
299 	enum i2c_slave_address_mode address_mode;
300 	/** Address or upper limit of address range */
301 	uint16_t address;
302 	/** Address mask, second address, or lower limit of address range */
303 	uint16_t address_mask;
304 #ifdef FEATURE_I2C_10_BIT_ADDRESS
305 	/** Enable 10-bit addressing */
306 	bool ten_bit_address;
307 #endif
308 	/**
309 	 * Enable general call address recognition (general call address
310 	 * is defined as 0000000 with direction bit 0).
311 	 */
312 	bool enable_general_call_address;
313 
314 #ifdef FEATURE_I2C_FAST_MODE_PLUS_AND_HIGH_SPEED
315 	/** Transfer speed mode */
316 	enum i2c_slave_transfer_speed transfer_speed;
317 #endif
318 
319 #if I2C_SLAVE_CALLBACK_MODE == true
320 	/**
321 	 * Enable NACK on address match (this can be changed after initialization
322 	 * via the \ref i2c_slave_enable_nack_on_address and
323 	 * \ref i2c_slave_disable_nack_on_address functions).
324 	 */
325 	bool enable_nack_on_address;
326 #endif
327 	/** GCLK generator to use as clock source */
328 	enum gclk_generator generator_source;
329 	/** Set to keep module active in sleep modes */
330 	bool run_in_standby;
331 	/** PAD0 (SDA) pinmux */
332 	uint32_t pinmux_pad0;
333 	/** PAD1 (SCL) pinmux */
334 	uint32_t pinmux_pad1;
335 	/** Set to enable SCL low time-out */
336 	bool scl_low_timeout;
337 #ifdef FEATURE_I2C_SCL_STRETCH_MODE
338 	/** Set to enable SCL stretch only after ACK bit (required for high speed) */
339 	bool scl_stretch_only_after_ack_bit;
340 #endif
341 #ifdef FEATURE_I2C_SCL_EXTEND_TIMEOUT
342 	/** Set to enable slave SCL low extend time-out */
343 	bool slave_scl_low_extend_timeout;
344 #endif
345 };
346 
347 
348 /**
349  * \name Lock/Unlock
350  * @{
351  */
352 
353 /**
354  * \brief Attempt to get lock on driver instance
355  *
356  * This function checks the instance's lock, which indicates whether or not it
357  * is currently in use, and sets the lock if it was not already set.
358  *
359  * The purpose of this is to enable exclusive access to driver instances, so
360  * that, e.g., transactions by different services will not interfere with each
361  * other.
362  *
363  * \param[in,out] module Pointer to the driver instance to lock
364  *
365  * \retval STATUS_OK If the module was locked
366  * \retval STATUS_BUSY If the module was already locked
367  */
i2c_slave_lock(struct i2c_slave_module * const module)368 static inline enum status_code i2c_slave_lock(
369 		struct i2c_slave_module *const module)
370 {
371 	enum status_code status;
372 
373 	system_interrupt_enter_critical_section();
374 
375 	if (module->locked) {
376 		status = STATUS_BUSY;
377 	} else {
378 		module->locked = true;
379 		status = STATUS_OK;
380 	}
381 
382 	system_interrupt_leave_critical_section();
383 
384 	return status;
385 }
386 
387 /**
388  * \brief Unlock driver instance
389  *
390  * This function clears the instance lock, indicating that it is available for
391  * use.
392  *
393  * \param[in,out] module Pointer to the driver instance to lock
394  *
395  * \retval STATUS_OK If the module was locked
396  * \retval STATUS_BUSY If the module was already locked
397  */
i2c_slave_unlock(struct i2c_slave_module * const module)398 static inline void i2c_slave_unlock(struct i2c_slave_module *const module)
399 {
400 	module->locked = false;
401 }
402 
403 /** @} */
404 
405 /**
406  * \name Configuration and Initialization
407  * @{
408  */
409 
410 /**
411  * \brief Returns the synchronization status of the module
412  *
413  * Returns the synchronization status of the module.
414  *
415  * \param[out] module  Pointer to software module structure
416  *
417  * \return Status of the synchronization.
418  * \retval true   Module is busy synchronizing
419  * \retval false  Module is not synchronizing
420  */
i2c_slave_is_syncing(const struct i2c_slave_module * const module)421 static inline bool i2c_slave_is_syncing(
422 		const struct i2c_slave_module *const module)
423 {
424 	/* Sanity check */
425 	Assert(module);
426 	Assert(module->hw);
427 
428 	SercomI2cs *const i2c_hw = &(module->hw->I2CS);
429 
430 	/* Return sync status */
431 #if defined(FEATURE_SERCOM_SYNCBUSY_SCHEME_VERSION_1)
432 	return (i2c_hw->STATUS.reg & SERCOM_I2CS_STATUS_SYNCBUSY);
433 #elif defined(FEATURE_SERCOM_SYNCBUSY_SCHEME_VERSION_2)
434 	return (i2c_hw->SYNCBUSY.reg & SERCOM_I2CS_SYNCBUSY_MASK);
435 #else
436 #  error Unknown SERCOM SYNCBUSY scheme!
437 #endif
438 }
439 
440 #if !defined(__DOXYGEN__)
441 /**
442  * \internal Wait for hardware module to sync
443  *
444  * \param[in]  module  Pointer to software module structure
445  */
_i2c_slave_wait_for_sync(const struct i2c_slave_module * const module)446 static void _i2c_slave_wait_for_sync(
447 		const struct i2c_slave_module *const module)
448 {
449 	/* Sanity check */
450 	Assert(module);
451 
452 	while (i2c_slave_is_syncing(module)) {
453 		/* Wait for I<SUP>2</SUP>C module to sync */
454 	}
455 }
456 #endif
457 
458 ///@cond INTERNAL
459 /**
460  * \internal Workaround for errata 13574
461  * Instead set ACK/NACK of CTRLB
462  *
463  * This errata exist in part revisions of SAM D20/D21/D09
464  * D10/D11/L21/L22/DA1/C20/C21/R30/HA1, but workaround can be works in all
465  * revision of those device. As this function operation
466  * should be use less cpu time as possible, so caller
467  * function can ignore to check revision number, and use
468  * this workaround in all revision of those device.
469  *
470  * \param[in,out] module  Pointer to software module structure
471  * \param[in] send_ack true send ACK, false send NACK
472  */
_i2c_slave_set_ctrlb_ackact(struct i2c_slave_module * const module,bool send_ack)473 static inline void _i2c_slave_set_ctrlb_ackact(
474 		struct i2c_slave_module *const module,
475 		bool send_ack)
476 {
477 	Assert(module);
478 	Assert(module->hw);
479 
480 	SercomI2cs *const i2c_hw = &(module->hw->I2CS);
481 
482 #if (SAMD20 || SAMD21 || SAMD09 || SAMD10 || SAMD11 || SAML21 || SAMDA1 ||  \
483 		SAML22 || SAMC20 || SAMC21 || SAMHA1 || SAMR30)
484 	/* Workaround, Following two write are atomic */
485 	system_interrupt_enter_critical_section();
486 	i2c_hw->STATUS.reg = 0;
487 
488 	if (send_ack == true) {
489 		i2c_hw->CTRLB.reg = 0;
490 	}
491 	else {
492 		i2c_hw->CTRLB.reg = SERCOM_I2CS_CTRLB_ACKACT;
493 	}
494 	system_interrupt_leave_critical_section();
495 #else
496 	/* Normal operation */
497 	if (send_ack == true) {
498 		i2c_hw->CTRLB.reg &= ~SERCOM_I2CS_CTRLB_ACKACT;
499 	}
500 	else {
501 		i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_ACKACT;
502 	}
503 #endif
504 	return;
505 }
506 
507 /**
508  * \internal Workaround for SAM0 errata 13574,
509  * instead Set CMD3 of CTRLB
510  *
511  * This errata exist in part revisions of SAM D20/D21/D09
512  * D10/D11/L21/DA1/C20/C21/R30/HA1, but workaround can be works in all
513  * revision of those device. As this function operation
514  * should be use less cpu time as possible, so caller
515  * function can ignore to check revision number, and use
516  * this workaround in all revision of those device.
517  *
518  * \param[in,out] module  Pointer to software module structure
519  */
_i2c_slave_set_ctrlb_cmd3(struct i2c_slave_module * const module)520 static inline void _i2c_slave_set_ctrlb_cmd3(
521 		struct i2c_slave_module *const module)
522 {
523 	Assert(module);
524 	Assert(module->hw);
525 
526 	SercomI2cs *const i2c_hw = &(module->hw->I2CS);
527 
528 #if (SAMD20 || SAMD21 || SAMD09 || SAMD10 || SAMD11 || SAML21 || SAML22 || \
529 		SAMDA1 || SAMC20 || SAMC21 || SAMR30 || SAMHA1)
530 	/* Workaround */
531 	/*
532 	 * Below code instead i2c_hw->CTRLB.reg = SERCOM_I2CS_CTRLB_CMD(0x3);
533 	 * CMD=0x3 clears all interrupts, so to keep the result similar
534 	 * PREC is cleared if it was set
535 	 */
536 	if (i2c_hw->INTFLAG.bit.PREC) {
537 		i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_PREC;
538 	}
539 	i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_AMATCH;
540 #else
541 	/* Normal operation */
542 	i2c_hw->CTRLB.reg = SERCOM_I2CS_CTRLB_CMD(0x3);
543 #endif
544 	return;
545 }
546 ///@endcond
547 
548 /**
549  * \brief Gets the I<SUP>2</SUP>C slave default configurations
550  *
551  * This will initialize the configuration structure to known default values.
552  *
553  * The default configuration is as follows:
554  * - Disable SCL low timeout
555  * - 300ns - 600ns SDA hold time
556  * - Buffer timeout = 65535
557  * - Address with mask
558  * - Address = 0
559  * - Address mask = 0 (one single address)
560  * - General call address disabled
561  * - Address nack disabled if the interrupt driver is used
562  * - GCLK generator 0
563  * - Do not run in standby
564  * - PINMUX_DEFAULT for SERCOM pads
565  *
566  * Those default configuration only available if the device supports it:
567  * - Not using 10-bit addressing
568  * - Standard-mode and Fast-mode transfer speed
569  * - SCL stretch disabled
570  * - Slave SCL low extend time-out disabled
571  *
572  * \param[out] config  Pointer to configuration structure to be initialized
573  */
i2c_slave_get_config_defaults(struct i2c_slave_config * const config)574 static inline void i2c_slave_get_config_defaults(
575 		struct i2c_slave_config *const config)
576 {
577 	/*Sanity check argument */
578 	Assert(config);
579 	config->enable_scl_low_timeout = false;
580 	config->sda_hold_time = I2C_SLAVE_SDA_HOLD_TIME_300NS_600NS;
581 	config->buffer_timeout = 65535;
582 	config->address_mode = I2C_SLAVE_ADDRESS_MODE_MASK;
583 	config->address = 0;
584 	config->address_mask = 0;
585 #ifdef FEATURE_I2C_10_BIT_ADDRESS
586 	config->ten_bit_address = false;
587 #endif
588 	config->enable_general_call_address = false;
589 #ifdef FEATURE_I2C_FAST_MODE_PLUS_AND_HIGH_SPEED
590 	config->transfer_speed = I2C_SLAVE_SPEED_STANDARD_AND_FAST;
591 #endif
592 #if I2C_SLAVE_CALLBACK_MODE == true
593 	config->enable_nack_on_address = false;
594 #endif
595 	config->generator_source = GCLK_GENERATOR_0;
596 	config->run_in_standby = false;
597 	config->pinmux_pad0 = PINMUX_DEFAULT;
598 	config->pinmux_pad1 = PINMUX_DEFAULT;
599 	config->scl_low_timeout  = false;
600 #ifdef FEATURE_I2C_SCL_STRETCH_MODE
601 	config->scl_stretch_only_after_ack_bit = false;
602 #endif
603 #ifdef FEATURE_I2C_SCL_EXTEND_TIMEOUT
604 	config->slave_scl_low_extend_timeout   = false;
605 #endif
606 }
607 
608 enum status_code i2c_slave_init(struct i2c_slave_module *const module,
609 		Sercom *const hw,
610 		const struct i2c_slave_config *const config);
611 
612 /**
613  * \brief Enables the I<SUP>2</SUP>C module
614  *
615  * This will enable the requested I<SUP>2</SUP>C module.
616  *
617  * \param[in]  module Pointer to the software module struct
618  */
i2c_slave_enable(const struct i2c_slave_module * const module)619 static inline void i2c_slave_enable(
620 		const struct i2c_slave_module *const module)
621 {
622 	/* Sanity check of arguments */
623 	Assert(module);
624 	Assert(module->hw);
625 
626 	SercomI2cs *const i2c_hw = &(module->hw->I2CS);
627 
628 #if I2C_SLAVE_CALLBACK_MODE == true
629 	/* Enable global interrupt for module */
630 	system_interrupt_enable(_sercom_get_interrupt_vector(module->hw));
631 #endif
632 
633 	/* Wait for module to sync */
634 	_i2c_slave_wait_for_sync(module);
635 
636 	/* Enable module */
637 	i2c_hw->CTRLA.reg |= SERCOM_I2CS_CTRLA_ENABLE;
638 }
639 
640 
641 /**
642  * \brief Disables the I<SUP>2</SUP>C module
643  *
644  * This will disable the I<SUP>2</SUP>C module specified in the provided software module
645  * structure.
646  *
647  * \param[in]  module  Pointer to the software module struct
648  */
i2c_slave_disable(const struct i2c_slave_module * const module)649 static inline void i2c_slave_disable(
650 		const struct i2c_slave_module *const module)
651 {
652 	/* Sanity check of arguments */
653 	Assert(module);
654 	Assert(module->hw);
655 
656 	SercomI2cs *const i2c_hw = &(module->hw->I2CS);
657 
658 #if I2C_SLAVE_CALLBACK_MODE == true
659 	/* Disable interrupts */
660 	i2c_hw->INTENCLR.reg = SERCOM_I2CS_INTENSET_PREC |
661 			SERCOM_I2CS_INTENSET_AMATCH | SERCOM_I2CS_INTENSET_DRDY;
662 
663 	/* Clear interrupt flags */
664 	i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_PREC | SERCOM_I2CS_INTFLAG_AMATCH |
665 			SERCOM_I2CS_INTFLAG_DRDY;
666 
667 	/* Disable global interrupt for module */
668 	system_interrupt_disable(_sercom_get_interrupt_vector(module->hw));
669 #endif
670 
671 	/* Wait for module to sync */
672 	_i2c_slave_wait_for_sync(module);
673 
674 	/* Disable module */
675 	i2c_hw->CTRLA.reg &= ~SERCOM_I2CS_CTRLA_ENABLE;
676 }
677 
678 void i2c_slave_reset(
679 		struct i2c_slave_module *const module);
680 
681 /** @} */
682 
683 /**
684  * \name Read and Write
685  * @{
686  */
687 
688 enum status_code i2c_slave_write_packet_wait(
689 		struct i2c_slave_module *const module,
690 		struct i2c_slave_packet *const packet);
691 enum status_code i2c_slave_read_packet_wait(
692 		struct i2c_slave_module *const module,
693 		struct i2c_slave_packet *const packet);
694 enum i2c_slave_direction i2c_slave_get_direction_wait(
695 		struct i2c_slave_module *const module);
696 
697 /** @} */
698 
699 /**
700  * \name Status Management
701  * @{
702  */
703 uint32_t i2c_slave_get_status(
704 		struct i2c_slave_module *const module);
705 void i2c_slave_clear_status(
706 		struct i2c_slave_module *const module,
707 		uint32_t status_flags);
708 /** @} */
709 
710 #ifdef FEATURE_I2C_DMA_SUPPORT
711 /**
712  * \name SERCOM I2C slave with DMA Interfaces
713  * @{
714  */
715 
716 /**
717  * \brief Read SERCOM I<SUP>2</SUP>C interrupt status.
718  *
719  * Read I<SUP>2</SUP>C interrupt status for DMA transfer.
720  *
721  * \param[in,out] module Pointer to the driver instance to lock
722  *
723  */
i2c_slave_dma_read_interrupt_status(struct i2c_slave_module * const module)724 static inline uint8_t i2c_slave_dma_read_interrupt_status(struct i2c_slave_module *const module)
725 {
726 	return (uint8_t)module->hw->I2CS.INTFLAG.reg;
727 }
728 
729 /**
730  * \brief Write SERCOM I<SUP>2</SUP>C interrupt status.
731  *
732  * Write I<SUP>2</SUP>C interrupt status for DMA transfer.
733  *
734  * \param[in,out] module Pointer to the driver instance to lock
735  * \param[in] flag Interrupt flag status
736  *
737  */
i2c_slave_dma_write_interrupt_status(struct i2c_slave_module * const module,uint8_t flag)738 static inline void i2c_slave_dma_write_interrupt_status(struct i2c_slave_module *const module,
739 		uint8_t flag)
740 {
741 	module->hw->I2CS.INTFLAG.reg = flag;
742 }
743 
744 /** @} */
745 #endif
746 
747 /** @} */
748 
749 #ifdef __cplusplus
750 }
751 #endif
752 
753 #endif /* I2C_SLAVE_H_INCLUDED */
754