Skip to content

Commit af1ba95

Browse files
XenuIsWatchingnashif
authored andcommitted
drivers: i3c: cdns: add busy status
Add busy status for cadence i3c. Signed-off-by: Ryan McClelland <[email protected]>
1 parent bb797ab commit af1ba95

File tree

1 file changed

+84
-41
lines changed

1 file changed

+84
-41
lines changed

drivers/i3c/i3c_cdns.c

Lines changed: 84 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <zephyr/sys/byteorder.h>
1414
#include <zephyr/sys/sys_io.h>
1515
#include <zephyr/sys/util.h>
16+
#include <zephyr/pm/device.h>
1617

1718
#include <stdlib.h>
1819

@@ -1254,33 +1255,47 @@ static int cdns_i3c_target_ibi_raise(const struct device *dev, struct i3c_ibi *r
12541255
{
12551256
const struct cdns_i3c_config *config = dev->config;
12561257
struct cdns_i3c_data *data = dev->data;
1258+
int ret;
12571259

12581260
__ASSERT_NO_MSG(request != NULL);
12591261

1262+
k_mutex_lock(&data->bus_lock, K_FOREVER);
1263+
pm_device_busy_set(dev);
1264+
12601265
/* make sure we are not currently the active controller */
12611266
if (sys_read32(config->base + MST_STATUS0) & MST_STATUS0_MASTER_MODE) {
1262-
return -EACCES;
1267+
ret = -EACCES;
1268+
goto error;
12631269
}
12641270

12651271
switch (request->ibi_type) {
12661272
case I3C_IBI_TARGET_INTR:
12671273
/* Check IP Revision since older versions of CDNS IP do not support IBI interrupt*/
12681274
if (REV_ID_REV(data->hw_cfg.rev_id) >= REV_ID_VERSION(1, 7)) {
1269-
return cdns_i3c_target_ibi_raise_intr(dev, request);
1275+
ret = cdns_i3c_target_ibi_raise_intr(dev, request);
12701276
} else {
1271-
return -ENOTSUP;
1277+
ret = -ENOTSUP;
12721278
}
1279+
break;
12731280
case I3C_IBI_CONTROLLER_ROLE_REQUEST:
12741281
#ifdef CONFIG_I3C_CONTROLLER
1275-
return cdns_i3c_target_ibi_raise_cr(dev);
1282+
ret = cdns_i3c_target_ibi_raise_cr(dev);
12761283
#else
1277-
return -ENOTSUP;
1284+
ret = -ENOTSUP;
12781285
#endif
1286+
break;
12791287
case I3C_IBI_HOTJOIN:
1280-
return cdns_i3c_target_ibi_raise_hj(dev);
1288+
ret = cdns_i3c_target_ibi_raise_hj(dev);
1289+
break;
12811290
default:
1282-
return -EINVAL;
1291+
ret = -EINVAL;
1292+
break;
12831293
}
1294+
error:
1295+
pm_device_busy_clear(dev);
1296+
k_mutex_unlock(&data->bus_lock);
1297+
1298+
return ret;
12841299
}
12851300
#endif /* CONFIG_I3C_TARGET */
12861301
#endif /* CONFIG_I3C_USE_IBI */
@@ -1439,14 +1454,7 @@ static int cdns_i3c_do_ccc(const struct device *dev, struct i3c_ccc_payload *pay
14391454
int ret = 0;
14401455
uint8_t num_cmds = 0;
14411456

1442-
/* make sure we are currently the active controller */
1443-
if (!(sys_read32(config->base + MST_STATUS0) & MST_STATUS0_MASTER_MODE)) {
1444-
return -EACCES;
1445-
}
1446-
1447-
if (payload == NULL) {
1448-
return -EINVAL;
1449-
}
1457+
__ASSERT_NO_MSG(payload != NULL);
14501458

14511459
/*
14521460
* Ensure data will fit within FIFOs.
@@ -1480,9 +1488,16 @@ static int cdns_i3c_do_ccc(const struct device *dev, struct i3c_ccc_payload *pay
14801488
return -ENOMEM;
14811489
}
14821490

1483-
LOG_DBG("%s: CCC[0x%02x]", dev->name, payload->ccc.id);
1484-
14851491
k_mutex_lock(&data->bus_lock, K_FOREVER);
1492+
pm_device_busy_set(dev);
1493+
1494+
/* make sure we are currently the active controller */
1495+
if (!(sys_read32(config->base + MST_STATUS0) & MST_STATUS0_MASTER_MODE)) {
1496+
ret = -EACCES;
1497+
goto error;
1498+
}
1499+
1500+
LOG_DBG("%s: CCC[0x%02x]", dev->name, payload->ccc.id);
14861501

14871502
/* wait for idle */
14881503
ret = cdns_i3c_wait_for_idle(dev);
@@ -1589,6 +1604,7 @@ static int cdns_i3c_do_ccc(const struct device *dev, struct i3c_ccc_payload *pay
15891604
}
15901605
#endif /* CONFIG_I3C_CONTROLLER && CONFIG_I3C_TARGET */
15911606
error:
1607+
pm_device_busy_clear(dev);
15921608
k_mutex_unlock(&data->bus_lock);
15931609

15941610
return ret;
@@ -1765,7 +1781,11 @@ static int cdns_i3c_i2c_api_configure(const struct device *dev, uint32_t config)
17651781
}
17661782

17671783
k_mutex_lock(&data->bus_lock, K_FOREVER);
1784+
pm_device_busy_set(dev);
1785+
17681786
cdns_i3c_set_prescalers(dev);
1787+
1788+
pm_device_busy_clear(dev);
17691789
k_mutex_unlock(&data->bus_lock);
17701790

17711791
return 0;
@@ -1800,7 +1820,11 @@ static int cdns_i3c_configure(const struct device *dev, enum i3c_config_type typ
18001820
data->common.ctrl_config.scl.i2c = ctrl_cfg->scl.i2c;
18011821

18021822
k_mutex_lock(&data->bus_lock, K_FOREVER);
1823+
pm_device_busy_set(dev);
1824+
18031825
cdns_i3c_set_prescalers(dev);
1826+
1827+
pm_device_busy_clear(dev);
18041828
k_mutex_unlock(&data->bus_lock);
18051829
#else
18061830
return -ENOTSUP;
@@ -2023,14 +2047,7 @@ static int cdns_i3c_i2c_transfer(const struct device *dev, struct i3c_i2c_device
20232047
uint32_t rxsize = 0;
20242048
int ret;
20252049

2026-
/* make sure we are currently the active controller */
2027-
if (!(sys_read32(config->base + MST_STATUS0) & MST_STATUS0_MASTER_MODE)) {
2028-
return -EACCES;
2029-
}
2030-
2031-
if (num_msgs == 0) {
2032-
return 0;
2033-
}
2050+
__ASSERT_NO_MSG(num_msgs > 0);
20342051

20352052
if (num_msgs > data->hw_cfg.cmd_mem_depth || num_msgs > data->hw_cfg.cmdr_mem_depth) {
20362053
LOG_ERR("%s: Too many messages", dev->name);
@@ -2053,6 +2070,13 @@ static int cdns_i3c_i2c_transfer(const struct device *dev, struct i3c_i2c_device
20532070
}
20542071

20552072
k_mutex_lock(&data->bus_lock, K_FOREVER);
2073+
pm_device_busy_set(dev);
2074+
2075+
/* make sure we are currently the active controller */
2076+
if (!(sys_read32(config->base + MST_STATUS0) & MST_STATUS0_MASTER_MODE)) {
2077+
ret = -EACCES;
2078+
goto error;
2079+
}
20562080

20572081
/* wait for idle */
20582082
ret = cdns_i3c_wait_for_idle(dev);
@@ -2100,6 +2124,7 @@ static int cdns_i3c_i2c_transfer(const struct device *dev, struct i3c_i2c_device
21002124

21012125
ret = data->xfer.ret;
21022126
error:
2127+
pm_device_busy_clear(dev);
21032128
k_mutex_unlock(&data->bus_lock);
21042129

21052130
return ret;
@@ -2154,16 +2179,20 @@ static int cdns_i3c_attach_device(const struct device *dev, struct i3c_device_de
21542179
if ((desc->static_addr != 0) || (desc->dynamic_addr != 0)) {
21552180
const struct cdns_i3c_config *config = dev->config;
21562181
struct cdns_i3c_data *data = dev->data;
2182+
int slot;
2183+
2184+
k_mutex_lock(&data->bus_lock, K_FOREVER);
2185+
pm_device_busy_set(dev);
21572186

2158-
int slot = cdns_i3c_master_get_rr_slot(dev, desc->dynamic_addr);
2187+
slot = cdns_i3c_master_get_rr_slot(dev, desc->dynamic_addr);
21592188

21602189
if (slot < 0) {
21612190
LOG_ERR("%s: no space for i3c device: %s", dev->name, desc->dev->name);
2191+
pm_device_busy_clear(dev);
2192+
k_mutex_unlock(&data->bus_lock);
21622193
return slot;
21632194
}
21642195

2165-
k_mutex_lock(&data->bus_lock, K_FOREVER);
2166-
21672196
sys_write32(sys_read32(config->base + DEVS_CTRL) | DEVS_CTRL_DEV_ACTIVE(slot),
21682197
config->base + DEVS_CTRL);
21692198

@@ -2182,6 +2211,7 @@ static int cdns_i3c_attach_device(const struct device *dev, struct i3c_device_de
21822211
sys_write32(dev_id_rr1, config->base + DEV_ID_RR1(slot));
21832212
sys_write32(dev_id_rr2, config->base + DEV_ID_RR2(slot));
21842213

2214+
pm_device_busy_clear(dev);
21852215
k_mutex_unlock(&data->bus_lock);
21862216
}
21872217

@@ -2201,6 +2231,7 @@ static int cdns_i3c_reattach_device(const struct device *dev, struct i3c_device_
22012231
}
22022232

22032233
k_mutex_lock(&data->bus_lock, K_FOREVER);
2234+
pm_device_busy_set(dev);
22042235

22052236
uint32_t dev_id_rr0 = DEV_ID_RR0_IS_I3C | prepare_rr0_dev_address(desc->dynamic_addr);
22062237
uint32_t dev_id_rr1 = DEV_ID_RR1_PID_MSB((desc->pid & 0xFFFFFFFF0000) >> 16);
@@ -2211,6 +2242,7 @@ static int cdns_i3c_reattach_device(const struct device *dev, struct i3c_device_
22112242
sys_write32(dev_id_rr1, config->base + DEV_ID_RR1(cdns_i3c_device_data->id));
22122243
sys_write32(dev_id_rr2, config->base + DEV_ID_RR2(cdns_i3c_device_data->id));
22132244

2245+
pm_device_busy_clear(dev);
22142246
k_mutex_unlock(&data->bus_lock);
22152247

22162248
return 0;
@@ -2228,13 +2260,15 @@ static int cdns_i3c_detach_device(const struct device *dev, struct i3c_device_de
22282260
}
22292261

22302262
k_mutex_lock(&data->bus_lock, K_FOREVER);
2263+
pm_device_busy_set(dev);
22312264

22322265
sys_write32(sys_read32(config->base + DEVS_CTRL) |
22332266
DEVS_CTRL_DEV_CLR(cdns_i3c_device_data->id),
22342267
config->base + DEVS_CTRL);
22352268
data->free_rr_slots |= BIT(cdns_i3c_device_data->id);
22362269
desc->controller_priv = NULL;
22372270

2271+
pm_device_busy_clear(dev);
22382272
k_mutex_unlock(&data->bus_lock);
22392273

22402274
return 0;
@@ -2253,6 +2287,7 @@ static int cdns_i3c_i2c_attach_device(const struct device *dev, struct i3c_i2c_d
22532287
}
22542288

22552289
k_mutex_lock(&data->bus_lock, K_FOREVER);
2290+
pm_device_busy_set(dev);
22562291

22572292
uint32_t dev_id_rr0 = prepare_rr0_dev_address(desc->addr);
22582293
uint32_t dev_id_rr2 = DEV_ID_RR2_LVR(desc->lvr);
@@ -2268,6 +2303,7 @@ static int cdns_i3c_i2c_attach_device(const struct device *dev, struct i3c_i2c_d
22682303
sys_write32(sys_read32(config->base + DEVS_CTRL) | DEVS_CTRL_DEV_ACTIVE(slot),
22692304
config->base + DEVS_CTRL);
22702305

2306+
pm_device_busy_clear(dev);
22712307
k_mutex_unlock(&data->bus_lock);
22722308

22732309
return 0;
@@ -2285,13 +2321,15 @@ static int cdns_i3c_i2c_detach_device(const struct device *dev, struct i3c_i2c_d
22852321
}
22862322

22872323
k_mutex_lock(&data->bus_lock, K_FOREVER);
2324+
pm_device_busy_set(dev);
22882325

22892326
sys_write32(sys_read32(config->base + DEVS_CTRL) |
22902327
DEVS_CTRL_DEV_CLR(cdns_i2c_device_data->id),
22912328
config->base + DEVS_CTRL);
22922329
data->free_rr_slots |= BIT(cdns_i2c_device_data->id);
22932330
desc->controller_priv = NULL;
22942331

2332+
pm_device_busy_clear(dev);
22952333
k_mutex_unlock(&data->bus_lock);
22962334

22972335
return 0;
@@ -2318,14 +2356,7 @@ static int cdns_i3c_transfer(const struct device *dev, struct i3c_device_desc *t
23182356
int rxsize = 0;
23192357
int ret;
23202358

2321-
/* make sure we are currently the active controller */
2322-
if (!(sys_read32(config->base + MST_STATUS0) & MST_STATUS0_MASTER_MODE)) {
2323-
return -EACCES;
2324-
}
2325-
2326-
if (num_msgs == 0) {
2327-
return 0;
2328-
}
2359+
__ASSERT_NO_MSG(num_msgs > 0);
23292360

23302361
if (num_msgs > data->hw_cfg.cmd_mem_depth || num_msgs > data->hw_cfg.cmdr_mem_depth) {
23312362
LOG_ERR("%s: Too many messages", dev->name);
@@ -2352,6 +2383,13 @@ static int cdns_i3c_transfer(const struct device *dev, struct i3c_device_desc *t
23522383
}
23532384

23542385
k_mutex_lock(&data->bus_lock, K_FOREVER);
2386+
pm_device_busy_set(dev);
2387+
2388+
/* make sure we are currently the active controller */
2389+
if (!(sys_read32(config->base + MST_STATUS0) & MST_STATUS0_MASTER_MODE)) {
2390+
ret = -EACCES;
2391+
goto error;
2392+
}
23552393

23562394
/* wait for idle */
23572395
ret = cdns_i3c_wait_for_idle(dev);
@@ -2484,6 +2522,7 @@ static int cdns_i3c_transfer(const struct device *dev, struct i3c_device_desc *t
24842522

24852523
ret = data->xfer.ret;
24862524
error:
2525+
pm_device_busy_clear(dev);
24872526
k_mutex_unlock(&data->bus_lock);
24882527

24892528
return ret;
@@ -3171,18 +3210,21 @@ static int cdns_i3c_target_tx_write(const struct device *dev, uint8_t *buf, uint
31713210
uint32_t val = 0;
31723211
uint16_t remain = len;
31733212

3213+
k_mutex_lock(&data->bus_lock, K_FOREVER);
3214+
pm_device_busy_set(dev);
3215+
31743216
/* check if we are currently a target */
31753217
if (sys_read32(config->base + MST_STATUS0) & MST_STATUS0_MASTER_MODE) {
3176-
return -EACCES;
3218+
i = -EACCES;
3219+
goto error;
31773220
}
31783221

31793222
/* check if there is space available in the tx fifo */
31803223
if (sys_read32(config->base + SLV_STATUS1) & SLV_STATUS1_SDR_TX_FULL) {
3181-
return -ENOSPC;
3224+
i = -ENOSPC;
3225+
goto error;
31823226
}
31833227

3184-
k_mutex_lock(&data->bus_lock, K_FOREVER);
3185-
31863228
/* rev 1p7 requires the length be written to the SLV_CTRL reg */
31873229
if (REV_ID_REV(data->hw_cfg.rev_id) >= REV_ID_VERSION(1, 7)) {
31883230
sys_write32(len, config->base + SLV_CTRL);
@@ -3233,7 +3275,8 @@ static int cdns_i3c_target_tx_write(const struct device *dev, uint8_t *buf, uint
32333275
LOG_ERR("%s: Unsupported HDR Mode %d", dev->name, hdr_mode);
32343276
i = -ENOTSUP;
32353277
}
3236-
3278+
error:
3279+
pm_device_busy_clear(dev);
32373280
k_mutex_unlock(&data->bus_lock);
32383281

32393282
/* return total bytes written */

0 commit comments

Comments
 (0)