@@ -36,6 +36,14 @@ struct i2c_mcux_data {
3636 struct k_sem lock ;
3737 struct k_sem device_sync_sem ;
3838 status_t callback_status ;
39+ #ifdef CONFIG_I2C_CALLBACK
40+ uint16_t addr ;
41+ uint32_t msg ;
42+ struct i2c_msg * msgs ;
43+ uint32_t num_msgs ;
44+ i2c_callback_t cb ;
45+ void * userdata ;
46+ #endif /* CONFIG_I2C_CALLBACK */
3947};
4048
4149static int i2c_mcux_configure (const struct device * dev ,
@@ -77,16 +85,42 @@ static int i2c_mcux_configure(const struct device *dev,
7785 return 0 ;
7886}
7987
88+ #ifdef CONFIG_I2C_CALLBACK
89+
90+ static void i2c_mcux_async_done (const struct device * dev , struct i2c_mcux_data * data , int result );
91+ static void i2c_mcux_async_iter (const struct device * dev );
92+
93+ #endif
94+
8095static void i2c_mcux_master_transfer_callback (I2C_Type * base ,
8196 i2c_master_handle_t * handle ,
82- status_t status , void * userData )
97+ status_t status , void * userdata )
8398{
84- struct i2c_mcux_data * data = userData ;
8599
86100 ARG_UNUSED (handle );
87101 ARG_UNUSED (base );
88102
103+ struct device * dev = userdata ;
104+ struct i2c_mcux_data * data = dev -> data ;
105+
106+ #ifdef CONFIG_I2C_CALLBACK
107+ if (data -> cb != NULL ) {
108+ /* Async transfer */
109+ if (status != kStatus_Success ) {
110+ I2C_MasterTransferAbort (base , & data -> handle );
111+ i2c_mcux_async_done (dev , data , - EIO );
112+ } else if (data -> msg == data -> num_msgs - 1 ) {
113+ i2c_mcux_async_done (dev , data , 0 );
114+ } else {
115+ data -> msg ++ ;
116+ i2c_mcux_async_iter (dev );
117+ }
118+ return ;
119+ }
120+ #endif /* CONFIG_I2C_CALLBACK */
121+
89122 data -> callback_status = status ;
123+
90124 k_sem_give (& data -> device_sync_sem );
91125}
92126
@@ -174,6 +208,95 @@ static int i2c_mcux_transfer(const struct device *dev, struct i2c_msg *msgs,
174208 return ret ;
175209}
176210
211+ #ifdef CONFIG_I2C_CALLBACK
212+
213+ static void i2c_mcux_async_done (const struct device * dev , struct i2c_mcux_data * data , int result )
214+ {
215+
216+ i2c_callback_t cb = data -> cb ;
217+ void * userdata = data -> userdata ;
218+
219+ data -> msg = 0 ;
220+ data -> msgs = NULL ;
221+ data -> num_msgs = 0 ;
222+ data -> cb = NULL ;
223+ data -> userdata = NULL ;
224+ data -> addr = 0 ;
225+
226+ k_sem_give (& data -> lock );
227+
228+ /* Callback may wish to start another transfer */
229+ cb (dev , result , userdata );
230+ }
231+
232+ /* Start a transfer asynchronously */
233+ static void i2c_mcux_async_iter (const struct device * dev )
234+ {
235+ I2C_Type * base = DEV_BASE (dev );
236+ struct i2c_mcux_data * data = dev -> data ;
237+ i2c_master_transfer_t transfer ;
238+ status_t status ;
239+ struct i2c_msg * msg = & data -> msgs [data -> msg ];
240+
241+ if (I2C_MSG_ADDR_10_BITS & msg -> flags ) {
242+ i2c_mcux_async_done (dev , data , - ENOTSUP );
243+ return ;
244+ }
245+
246+ /* Initialize the transfer descriptor */
247+ transfer .flags = i2c_mcux_convert_flags (msg -> flags );
248+ transfer .slaveAddress = data -> addr ;
249+ transfer .direction = (msg -> flags & I2C_MSG_READ ) ? kI2C_Read : kI2C_Write ;
250+ transfer .subaddress = 0 ;
251+ transfer .subaddressSize = 0 ;
252+ transfer .data = msg -> buf ;
253+ transfer .dataSize = msg -> len ;
254+
255+ /* Prevent the controller to send a start condition between
256+ * messages, except if explicitly requested.
257+ */
258+ if (data -> msg != 0 && !(msg -> flags & I2C_MSG_RESTART )) {
259+ transfer .flags |= kI2C_TransferNoStartFlag ;
260+ }
261+
262+ /* Start the transfer */
263+ status = I2C_MasterTransferNonBlocking (base , & data -> handle , & transfer );
264+
265+ /* Return an error if the transfer didn't start successfully
266+ * e.g., if the bus was busy
267+ */
268+ if (status != kStatus_Success ) {
269+ I2C_MasterTransferAbort (base , & data -> handle );
270+ i2c_mcux_async_done (dev , data , - EIO );
271+ }
272+ }
273+
274+ static int i2c_mcux_transfer_cb (const struct device * dev , struct i2c_msg * msgs , uint8_t num_msgs ,
275+ uint16_t addr , i2c_callback_t cb , void * userdata )
276+ {
277+ struct i2c_mcux_data * data = dev -> data ;
278+
279+ int res = k_sem_take (& data -> lock , K_NO_WAIT );
280+
281+ if (res != 0 ) {
282+ return - EWOULDBLOCK ;
283+ }
284+
285+ data -> msg = 0 ;
286+ data -> msgs = msgs ;
287+ data -> num_msgs = num_msgs ;
288+ data -> addr = addr ;
289+ data -> cb = cb ;
290+ data -> userdata = userdata ;
291+ data -> addr = addr ;
292+
293+ i2c_mcux_async_iter (dev );
294+
295+ return 0 ;
296+ }
297+
298+ #endif /* CONFIG_I2C_CALLBACK */
299+
177300static void i2c_mcux_isr (const struct device * dev )
178301{
179302 I2C_Type * base = DEV_BASE (dev );
@@ -198,7 +321,7 @@ static int i2c_mcux_init(const struct device *dev)
198321 I2C_MasterGetDefaultConfig (& master_config );
199322 I2C_MasterInit (base , & master_config , clock_freq );
200323 I2C_MasterTransferCreateHandle (base , & data -> handle ,
201- i2c_mcux_master_transfer_callback , data );
324+ i2c_mcux_master_transfer_callback , ( void * ) dev );
202325
203326 bitrate_cfg = i2c_map_dt_bitrate (config -> bitrate );
204327
@@ -220,6 +343,9 @@ static int i2c_mcux_init(const struct device *dev)
220343static const struct i2c_driver_api i2c_mcux_driver_api = {
221344 .configure = i2c_mcux_configure ,
222345 .transfer = i2c_mcux_transfer ,
346+ #ifdef CONFIG_I2C_CALLBACK
347+ .transfer_cb = i2c_mcux_transfer_cb ,
348+ #endif
223349};
224350
225351#define I2C_DEVICE_INIT_MCUX (n ) \
0 commit comments