@@ -46,6 +46,14 @@ struct i2c_mcux_data {
4646 i2c_callback_t cb ;
4747 void * userdata ;
4848#endif /* CONFIG_I2C_CALLBACK */
49+ #ifdef CONFIG_I2C_TARGET
50+ i2c_slave_handle_t target_handle ;
51+ struct i2c_target_config * target_cfg ;
52+ uint8_t target_buffer ;
53+ bool target_attached ;
54+ bool target_receiving ;
55+ bool target_first_rxtx ;
56+ #endif
4957};
5058
5159static int i2c_mcux_configure (const struct device * dev ,
@@ -299,12 +307,170 @@ static int i2c_mcux_transfer_cb(const struct device *dev, struct i2c_msg *msgs,
299307
300308#endif /* CONFIG_I2C_CALLBACK */
301309
310+ #if CONFIG_I2C_TARGET
311+ static void i2c_mcux_target_transfer_cb (I2C_Type * base , i2c_slave_transfer_t * transfer , void * userData )
312+ {
313+ const struct device * dev = (const struct device * )userData ;
314+ struct i2c_mcux_data * data = dev -> data ;
315+ const struct i2c_target_callbacks * target_cb = data -> target_cfg -> callbacks ;
316+ int ret = 0 ;
317+
318+ ARG_UNUSED (base );
319+
320+ if (transfer -> event & kI2C_SlaveStartEvent ) {
321+ /* start or repeated start of a transfer */
322+ transfer -> dataSize = 0 ;
323+ data -> target_first_rxtx = true;
324+
325+ if (data -> target_receiving ) {
326+ /* In case of a repeated start after a kI2C_SlaveReceiveEvent,
327+ * the kI2C_SlaveCompletionEvent is not fired. We need to fetch the last
328+ * byte here. */
329+ data -> target_receiving = false;
330+ if (target_cb -> write_received ) {
331+ target_cb -> write_received (data -> target_cfg , data -> target_buffer );
332+ }
333+ }
334+ }
335+
336+ if (transfer -> event & kI2C_SlaveReceiveEvent ) {
337+ /* request to provide a buffer in which to place received data */
338+ data -> target_receiving = true;
339+
340+ transfer -> data = & data -> target_buffer ;
341+ transfer -> dataSize = 1 ;
342+
343+ if (data -> target_first_rxtx ) {
344+ data -> target_first_rxtx = false;
345+ if (target_cb -> write_requested ) {
346+ ret = target_cb -> write_requested (data -> target_cfg );
347+ }
348+ } else {
349+ if (target_cb -> write_received ) {
350+ ret = target_cb -> write_received (data -> target_cfg ,
351+ data -> target_buffer );
352+ }
353+ }
354+
355+ if (ret < 0 ) {
356+ /* abort communication by not providing a buffer in case of an error */
357+ transfer -> dataSize = 0 ;
358+ }
359+ }
360+
361+ if (transfer -> event & kI2C_SlaveTransmitEvent ) {
362+ /* request to provide data to transmit */
363+ transfer -> data = & data -> target_buffer ;
364+ transfer -> dataSize = 1 ;
365+
366+ if (data -> target_first_rxtx ) {
367+ data -> target_first_rxtx = false;
368+ if (target_cb -> read_requested ) {
369+ ret = target_cb -> read_requested (data -> target_cfg ,
370+ & data -> target_buffer );
371+ }
372+ } else {
373+ if (target_cb -> read_processed ) {
374+ ret = target_cb -> read_processed (data -> target_cfg ,
375+ & data -> target_buffer );
376+ }
377+ }
378+
379+ if (ret < 0 ) {
380+ /* abort communication by not providing a buffer in case of an error */
381+ transfer -> dataSize = 0 ;
382+ }
383+ }
384+
385+ if (transfer -> event & kI2C_SlaveCompletionEvent ) {
386+ /* transfer finished */
387+ data -> target_first_rxtx = false;
388+
389+ if (data -> target_receiving ) {
390+ /* fetch last received byte */
391+ data -> target_receiving = false;
392+ if (target_cb -> write_received ) {
393+ target_cb -> write_received (data -> target_cfg , data -> target_buffer );
394+ }
395+ }
396+
397+ if (target_cb -> stop ) {
398+ target_cb -> stop (data -> target_cfg );
399+ }
400+ }
401+ }
402+
403+ static int i2c_mcux_target_register (const struct device * dev ,
404+ struct i2c_target_config * target_config )
405+ {
406+ I2C_Type * base = DEV_BASE (dev );
407+ const struct i2c_mcux_config * config = dev -> config ;
408+ struct i2c_mcux_data * data = dev -> data ;
409+ i2c_slave_config_t slave_config ;
410+ uint32_t clock_freq ;
411+
412+ I2C_MasterDeinit (base );
413+
414+ if (!target_config ) {
415+ return - EINVAL ;
416+ }
417+
418+ if (data -> target_attached ) {
419+ return - EBUSY ;
420+ }
421+
422+ data -> target_attached = true;
423+ data -> target_cfg = target_config ;
424+ data -> target_first_rxtx = true;
425+ data -> target_receiving = false;
426+
427+ I2C_SlaveGetDefaultConfig (& slave_config );
428+ slave_config .slaveAddress = target_config -> address ;
429+
430+ clock_freq = CLOCK_GetFreq (config -> clock_source );
431+
432+ I2C_SlaveInit (base , & slave_config , clock_freq );
433+ I2C_SlaveClearStatusFlags (base , kClearFlags );
434+ I2C_SlaveTransferCreateHandle (base , & data -> target_handle , i2c_mcux_target_transfer_cb ,
435+ (void * )dev );
436+ I2C_SlaveTransferNonBlocking (base , & data -> target_handle , kI2C_SlaveAllEvents );
437+
438+ return 0 ;
439+ }
440+
441+ static int i2c_mcux_target_unregister (const struct device * dev ,
442+ struct i2c_target_config * target_config )
443+ {
444+ I2C_Type * base = DEV_BASE (dev );
445+ struct i2c_mcux_data * data = dev -> data ;
446+
447+ if (!data -> target_attached ) {
448+ return - EINVAL ;
449+ }
450+
451+ data -> target_cfg = NULL ;
452+ data -> target_attached = false;
453+
454+ I2C_SlaveDeinit (base );
455+
456+ return 0 ;
457+ }
458+ #endif /* CONFIG_I2C_TARGET */
459+
302460static void i2c_mcux_isr (const struct device * dev )
303461{
304462 I2C_Type * base = DEV_BASE (dev );
305463 struct i2c_mcux_data * data = dev -> data ;
306464
465+ #ifdef CONFIG_I2C_TARGET
466+ if (data -> target_attached ) {
467+ I2C_SlaveTransferHandleIRQ (base , & data -> target_handle );
468+ } else {
469+ I2C_MasterTransferHandleIRQ (base , & data -> handle );
470+ }
471+ #else
307472 I2C_MasterTransferHandleIRQ (base , & data -> handle );
473+ #endif /* CONFIG_I2C_TARGET */
308474}
309475
310476static int i2c_mcux_init (const struct device * dev )
@@ -351,6 +517,10 @@ static DEVICE_API(i2c, i2c_mcux_driver_api) = {
351517#ifdef CONFIG_I2C_RTIO
352518 .iodev_submit = i2c_iodev_submit_fallback ,
353519#endif
520+ #if CONFIG_I2C_TARGET
521+ .target_register = i2c_mcux_target_register ,
522+ .target_unregister = i2c_mcux_target_unregister ,
523+ #endif
354524};
355525
356526#define I2C_DEVICE_INIT_MCUX (n ) \
0 commit comments