Skip to content

Commit a45ece6

Browse files
Tom Burdicknashif
authored andcommitted
i2c: Adds i2c_transfer_async API for I2C
i2c_transfer_async is the asynchronous version of i2c_transfer where the completion of the transfer is notified to the caller using a callback. This can be used in conjuction with the common callbacks and datatypes in async.h for directly doing an async transfer with an IPC object to notify a thread. Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
1 parent 9a1b990 commit a45ece6

File tree

3 files changed

+122
-0
lines changed

3 files changed

+122
-0
lines changed

drivers/i2c/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ config I2C_STATS
2828
help
2929
Enable I2C Stats.
3030

31+
config I2C_CALLBACK
32+
bool "I2C asynchronous callback API"
33+
help
34+
API and implementations of i2c_transfer_cb.
35+
3136
# Include these first so that any properties (e.g. defaults) below can be
3237
# overridden (by defining symbols in multiple locations)
3338
source "drivers/i2c/Kconfig.b91"

drivers/i2c/i2c_common.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@
1414
#include <zephyr/logging/log.h>
1515
LOG_MODULE_REGISTER(i2c);
1616

17+
#if defined(CONFIG_I2C_CALLBACK) && defined(CONFIG_POLL)
18+
void z_i2c_transfer_signal_cb(const struct device *dev,
19+
int result,
20+
void *data)
21+
{
22+
struct k_poll_signal *sig = (struct k_poll_signal *)data;
23+
24+
k_poll_signal_raise(sig, result);
25+
}
26+
#endif
27+
1728
void i2c_dump_msgs(const char *name, const struct i2c_msg *msgs,
1829
uint8_t num_msgs, uint16_t addr)
1930
{

include/zephyr/drivers/i2c.h

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,15 @@ struct i2c_msg {
159159
uint8_t flags;
160160
};
161161

162+
/**
163+
* @brief I2C callback for asynchronous transfer requests
164+
*
165+
* @param dev I2C device which is notifying of transfer completion or error
166+
* @param result Result code of the transfer request. 0 is success, -errno for failure.
167+
* @param data Transfer requester supplied data which is passed along to the callback.
168+
*/
169+
typedef void (*i2c_callback_t)(const struct device *dev, int result, void *data);
170+
162171
/**
163172
* @cond INTERNAL_HIDDEN
164173
*
@@ -179,6 +188,14 @@ typedef int (*i2c_api_target_register_t)(const struct device *dev,
179188
struct i2c_target_config *cfg);
180189
typedef int (*i2c_api_target_unregister_t)(const struct device *dev,
181190
struct i2c_target_config *cfg);
191+
#ifdef CONFIG_I2C_CALLBACK
192+
typedef int (*i2c_api_transfer_cb_t)(const struct device *dev,
193+
struct i2c_msg *msgs,
194+
uint8_t num_msgs,
195+
uint16_t addr,
196+
i2c_callback_t cb,
197+
void *userdata);
198+
#endif /* CONFIG_I2C_CALLBACK */
182199
typedef int (*i2c_api_recover_bus_t)(const struct device *dev);
183200

184201
__subsystem struct i2c_driver_api {
@@ -187,6 +204,9 @@ __subsystem struct i2c_driver_api {
187204
i2c_api_full_io_t transfer;
188205
i2c_api_target_register_t target_register;
189206
i2c_api_target_unregister_t target_unregister;
207+
#ifdef CONFIG_I2C_CALLBACK
208+
i2c_api_transfer_cb_t transfer_cb;
209+
#endif
190210
i2c_api_recover_bus_t recover_bus;
191211
};
192212

@@ -602,6 +622,92 @@ static inline int z_impl_i2c_transfer(const struct device *dev,
602622
return res;
603623
}
604624

625+
#ifdef CONFIG_I2C_CALLBACK
626+
627+
/**
628+
* @brief Perform data transfer to another I2C device in controller mode.
629+
*
630+
* This routine provides a generic interface to perform data transfer
631+
* to another I2C device asynchronously with a callback completion.
632+
*
633+
* @see i2c_transfer()
634+
* @funcprop \isr_ok
635+
*
636+
* @param dev Pointer to the device structure for an I2C controller
637+
* driver configured in controller mode.
638+
* @param msgs Array of messages to transfer, must live until callback completes.
639+
* @param num_msgs Number of messages to transfer.
640+
* @param addr Address of the I2C target device.
641+
* @param cb Function pointer for completion callback.
642+
* @param userdata Userdata passed to callback.
643+
*
644+
* @retval 0 If successful.
645+
* @retval -EIO General input / output error.
646+
* @retval -ENOSYS If transfer async is not implemented
647+
* @retval -EWOULDBLOCK If the device is temporarily busy doing another transfer
648+
*/
649+
static inline int i2c_transfer_cb(const struct device *dev,
650+
struct i2c_msg *msgs,
651+
uint8_t num_msgs,
652+
uint16_t addr,
653+
i2c_callback_t cb,
654+
void *userdata)
655+
{
656+
const struct i2c_driver_api *api = (const struct i2c_driver_api *)dev->api;
657+
658+
if (api->transfer_cb == NULL) {
659+
return -ENOSYS;
660+
}
661+
662+
return api->transfer_cb(dev, msgs, num_msgs, addr, cb, userdata);
663+
}
664+
665+
#ifdef CONFIG_POLL
666+
667+
/** @cond INTERNAL_HIDDEN */
668+
void z_i2c_transfer_signal_cb(const struct device *dev, int result, void *userdata);
669+
/** @endcond */
670+
671+
/**
672+
* @brief Perform data transfer to another I2C device in controller mode.
673+
*
674+
* This routine provides a generic interface to perform data transfer
675+
* to another I2C device asynchronously with a k_poll_signal completion.
676+
*
677+
* @see i2c_transfer_cb()
678+
* @funcprop \isr_ok
679+
*
680+
* @param dev Pointer to the device structure for an I2C controller
681+
* driver configured in controller mode.
682+
* @param msgs Array of messages to transfer, must live until callback completes.
683+
* @param num_msgs Number of messages to transfer.
684+
* @param addr Address of the I2C target device.
685+
* @param signal Signal to notify of transfer completion.
686+
*
687+
* @retval 0 If successful.
688+
* @retval -EIO General input / output error.
689+
* @retval -ENOSYS If transfer async is not implemented
690+
* @retval -EWOULDBLOCK If the device is temporarily busy doing another transfer
691+
*/
692+
static inline int i2c_transfer_signal(const struct device *dev,
693+
struct i2c_msg *msgs,
694+
uint8_t num_msgs,
695+
uint16_t addr,
696+
struct k_poll_signal *sig)
697+
{
698+
const struct i2c_driver_api *api = (const struct i2c_driver_api *)dev->api;
699+
700+
if (api->transfer_cb == NULL) {
701+
return -ENOSYS;
702+
}
703+
704+
return api->transfer_cb(dev, msgs, num_msgs, addr, z_i2c_transfer_signal_cb, sig);
705+
}
706+
707+
#endif /* CONFIG_POLL */
708+
709+
#endif /* CONFIG_I2C_CALLBACK */
710+
605711
/**
606712
* @brief Perform data transfer to another I2C device in controller mode.
607713
*

0 commit comments

Comments
 (0)