drivers: i3c: cdns: use deterministic timeout for idle
Previously, the idle bit would be read for X amount of times. This could vary alot depend on the CPU speed. Timeout is now to happen from the cycle time. Signed-off-by: Ryan McClelland <ryanmcclelland@meta.com>
This commit is contained in:
parent
a8d2feef83
commit
1e91453005
|
@ -375,9 +375,11 @@
|
|||
#define I3C_MAX_MSGS 10
|
||||
#define I3C_SIR_DEFAULT_DA 0x7F
|
||||
#define I3C_MAX_IDLE_CANCEL_WAIT_RETRIES 50
|
||||
#define I3C_MAX_IDLE_WAIT_RETRIES 5000
|
||||
#define I3C_PRESCL_REG_SCALE (4)
|
||||
#define I2C_PRESCL_REG_SCALE (5)
|
||||
#define I3C_WAIT_FOR_IDLE_STATE_US 100
|
||||
#define I3C_IDLE_TIMEOUT_CYC \
|
||||
(I3C_WAIT_FOR_IDLE_STATE_US * (sys_clock_hw_cycles_per_sec() / USEC_PER_SEC))
|
||||
|
||||
/* Target T_LOW period in open-drain mode. */
|
||||
#define I3C_BUS_TLOW_OD_MIN_NS 200
|
||||
|
@ -613,6 +615,25 @@ static int cdns_i3c_read_rx_fifo(const struct cdns_i3c_config *config, void *buf
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int cdns_i3c_wait_for_idle(const struct device *dev)
|
||||
{
|
||||
const struct cdns_i3c_config *config = dev->config;
|
||||
uint32_t start_time = k_cycle_get_32();
|
||||
|
||||
/**
|
||||
* Spin waiting for device to go idle. It is unlikely that this will
|
||||
* actually take any time unless if the last transaction came immediately
|
||||
* after an error condition.
|
||||
*/
|
||||
while (!(sys_read32(config->base + MST_STATUS0) & MST_STATUS0_IDLE)) {
|
||||
if (k_cycle_get_32() - start_time > I3C_IDLE_TIMEOUT_CYC) {
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cdns_i3c_set_prescalers(const struct device *dev)
|
||||
{
|
||||
struct cdns_i3c_data *data = dev->data;
|
||||
|
@ -995,19 +1016,9 @@ static int cdns_i3c_do_ccc(const struct device *dev, struct i3c_ccc_payload *pay
|
|||
|
||||
k_mutex_lock(&data->bus_lock, K_FOREVER);
|
||||
|
||||
/**
|
||||
* Spin waiting for device to go idle. It is unlikely that this will
|
||||
* actually take any time unless if the last transaction came immediately
|
||||
* after an error condition.
|
||||
*/
|
||||
uint32_t retry_count = I3C_MAX_IDLE_WAIT_RETRIES;
|
||||
|
||||
while (!(sys_read32(config->base + MST_STATUS0) & MST_STATUS0_IDLE) && (retry_count > 0)) {
|
||||
retry_count--;
|
||||
}
|
||||
if (retry_count == 0) {
|
||||
LOG_ERR("%s: Unable to start transfer, device not idle", dev->name);
|
||||
ret = -EAGAIN;
|
||||
/* wait for idle */
|
||||
ret = cdns_i3c_wait_for_idle(dev);
|
||||
if (ret != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -1383,19 +1394,9 @@ static int cdns_i3c_i2c_transfer(const struct device *dev, struct i3c_i2c_device
|
|||
|
||||
k_mutex_lock(&data->bus_lock, K_FOREVER);
|
||||
|
||||
/**
|
||||
* Spin waiting for device to go idle. It is unlikely that this will
|
||||
* actually take any time unless if the last transaction came immediately
|
||||
* after an error condition.
|
||||
*/
|
||||
uint32_t retry_count = I3C_MAX_IDLE_WAIT_RETRIES;
|
||||
|
||||
while (!(sys_read32(config->base + MST_STATUS0) & MST_STATUS0_IDLE) && (retry_count > 0)) {
|
||||
retry_count--;
|
||||
}
|
||||
if (retry_count == 0) {
|
||||
LOG_ERR("%s: Unable to start transfer, device not idle", dev->name);
|
||||
ret = -EAGAIN;
|
||||
/* wait for idle */
|
||||
ret = cdns_i3c_wait_for_idle(dev);
|
||||
if (ret != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -1676,19 +1677,9 @@ static int cdns_i3c_transfer(const struct device *dev, struct i3c_device_desc *t
|
|||
|
||||
k_mutex_lock(&data->bus_lock, K_FOREVER);
|
||||
|
||||
/**
|
||||
* Spin waiting for device to go idle. It is unlikely that this will
|
||||
* actually take any time unless if the last transaction came immediately
|
||||
* after an error condition.
|
||||
*/
|
||||
uint32_t retry_count = I3C_MAX_IDLE_WAIT_RETRIES;
|
||||
|
||||
while (!(sys_read32(config->base + MST_STATUS0) & MST_STATUS0_IDLE) && (retry_count > 0)) {
|
||||
retry_count--;
|
||||
}
|
||||
if (retry_count == 0) {
|
||||
LOG_ERR("%s: Unable to start transfer, device not idle", dev->name);
|
||||
ret = -EAGAIN;
|
||||
/* wait for idle */
|
||||
ret = cdns_i3c_wait_for_idle(dev);
|
||||
if (ret != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue