Skip to content

Commit ae63c62

Browse files
XenuIsWatchingnashif
authored andcommitted
drivers: i3c: implement support for ibi thr interrupts
Some IBI TIR packets can be larger than the ibi data fifo size which can prevent it from receiving the full packet. This adds a data struct in to the driver data where data can be pushed to as data is being transfered. Signed-off-by: Ryan McClelland <[email protected]>
1 parent 31e821b commit ae63c62

File tree

2 files changed

+58
-34
lines changed

2 files changed

+58
-34
lines changed

drivers/i3c/i3c_cdns.c

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,14 @@ struct cdns_i3c_xfer {
547547
struct cdns_i3c_cmd cmds[I3C_MAX_MSGS];
548548
};
549549

550+
#ifdef CONFIG_I3C_USE_IBI
551+
/* IBI transferred data */
552+
struct cdns_i3c_ibi_buf {
553+
uint8_t ibi_data[CONFIG_I3C_IBI_MAX_PAYLOAD_SIZE];
554+
uint8_t ibi_data_cnt;
555+
};
556+
#endif
557+
550558
/* Driver config */
551559
struct cdns_i3c_config {
552560
struct i3c_driver_config common;
@@ -556,12 +564,17 @@ struct cdns_i3c_config {
556564
uint32_t input_frequency;
557565
/** Interrupt configuration function. */
558566
void (*irq_config_func)(const struct device *dev);
567+
/** IBID Threshold value */
568+
uint8_t ibid_thr;
559569
};
560570

561571
/* Driver instance data */
562572
struct cdns_i3c_data {
563573
struct i3c_driver_data common;
564574
struct cdns_i3c_hw_config hw_cfg;
575+
#ifdef CONFIG_I3C_USE_IBI
576+
struct cdns_i3c_ibi_buf ibi_buf;
577+
#endif
565578
struct k_mutex bus_lock;
566579
struct cdns_i3c_i2c_dev_data cdns_i3c_i2c_priv_data[I3C_MAX_DEVS];
567580
struct cdns_i3c_xfer xfer;
@@ -2298,7 +2311,7 @@ static int cdns_i3c_read_ibi_fifo(const struct cdns_i3c_config *config, void *bu
22982311
static void cdns_i3c_handle_ibi(const struct device *dev, uint32_t ibir)
22992312
{
23002313
const struct cdns_i3c_config *config = dev->config;
2301-
uint8_t ibi_data[CONFIG_I3C_IBI_MAX_PAYLOAD_SIZE];
2314+
struct cdns_i3c_data *data = dev->data;
23022315

23032316
/* The slave ID returned here is the device ID in the SIR map NOT the device ID
23042317
* in the RR map.
@@ -2326,20 +2339,25 @@ static void cdns_i3c_handle_ibi(const struct device *dev, uint32_t ibir)
23262339
return;
23272340
}
23282341
if (ibir & IBIR_ERROR) {
2329-
LOG_ERR("%s: Data overflow", dev->name);
2330-
return;
2342+
/* Controller issued an Abort */
2343+
LOG_ERR("%s: IBI Data overflow", dev->name);
23312344
}
23322345

23332346
/* Read out any payload bytes */
23342347
uint8_t ibi_len = IBIR_XFER_BYTES(ibir);
23352348

23362349
if (ibi_len > 0) {
2337-
if (cdns_i3c_read_ibi_fifo(config, ibi_data, ibi_len) < 0) {
2338-
LOG_ERR("%s: Failed to get payload", dev->name);
2350+
if (ibi_len - data->ibi_buf.ibi_data_cnt > 0) {
2351+
if (cdns_i3c_read_ibi_fifo(
2352+
config, &data->ibi_buf.ibi_data[data->ibi_buf.ibi_data_cnt],
2353+
ibi_len - data->ibi_buf.ibi_data_cnt) < 0) {
2354+
LOG_ERR("%s: Failed to get payload", dev->name);
2355+
}
23392356
}
2357+
data->ibi_buf.ibi_data_cnt = 0;
23402358
}
23412359

2342-
if (i3c_ibi_work_enqueue_target_irq(desc, ibi_data, ibi_len) != 0) {
2360+
if (i3c_ibi_work_enqueue_target_irq(desc, data->ibi_buf.ibi_data, ibi_len) != 0) {
23432361
LOG_ERR("%s: Error enqueue IBI IRQ work", dev->name);
23442362
}
23452363
}
@@ -2445,66 +2463,64 @@ static void cdns_i3c_target_sdr_tx_thr_int_handler(const struct device *dev,
24452463
static void cdns_i3c_irq_handler(const struct device *dev)
24462464
{
24472465
const struct cdns_i3c_config *config = dev->config;
2466+
struct cdns_i3c_data *data = dev->data;
24482467

24492468
if (sys_read32(config->base + MST_STATUS0) & MST_STATUS0_MASTER_MODE) {
24502469
uint32_t int_st = sys_read32(config->base + MST_ISR);
2470+
sys_write32(int_st, config->base + MST_ICR);
24512471

24522472
/* Command queue empty */
24532473
if (int_st & MST_INT_HALTED) {
24542474
LOG_WRN("Core Halted, 2 read aborts");
2455-
sys_write32(MST_INT_HALTED, config->base + MST_ICR);
24562475
}
24572476

24582477
/* Command queue empty */
24592478
if (int_st & MST_INT_CMDD_EMP) {
24602479
cdns_i3c_complete_transfer(dev);
2461-
sys_write32(MST_INT_CMDD_EMP, config->base + MST_ICR);
2462-
}
2463-
2464-
/* Command queue threshold */
2465-
if (int_st & MST_INT_CMDD_THR) {
2466-
sys_write32(MST_INT_CMDD_THR, config->base + MST_ICR);
2467-
}
2468-
2469-
/* Command response threshold hit */
2470-
if (int_st & MST_INT_CMDR_THR) {
2471-
sys_write32(MST_INT_CMDR_THR, config->base + MST_ICR);
2472-
}
2473-
2474-
/* RX data ready */
2475-
if (int_st & MST_INT_RX_THR) {
2476-
sys_write32(MST_INT_RX_THR, config->base + MST_ICR);
24772480
}
24782481

24792482
/* In-band interrupt */
24802483
if (int_st & MST_INT_IBIR_THR) {
2481-
sys_write32(MST_INT_IBIR_THR, config->base + MST_ICR);
24822484
#ifdef CONFIG_I3C_USE_IBI
24832485
cnds_i3c_master_demux_ibis(dev);
24842486
#else
24852487
LOG_ERR("%s: IBI received - Kconfig for using IBIs is not enabled",
24862488
dev->name);
24872489
#endif
24882490
}
2491+
2492+
/* In-band interrupt data threshold */
2493+
if (int_st & MST_INT_IBID_THR) {
2494+
#ifdef CONFIG_I3C_USE_IBI
2495+
/* pop data out of the IBI FIFO */
2496+
while (!cdns_i3c_ibi_fifo_empty(config)) {
2497+
uint32_t *ptr = (uint32_t *)&data->ibi_buf
2498+
.ibi_data[data->ibi_buf.ibi_data_cnt];
2499+
*ptr = sys_le32_to_cpu(sys_read32(config->base + IBI_DATA_FIFO));
2500+
data->ibi_buf.ibi_data_cnt += 4;
2501+
}
2502+
#else
2503+
LOG_ERR("%s: IBI received - Kconfig for using IBIs is not enabled",
2504+
dev->name);
2505+
#endif
2506+
}
2507+
2508+
/* In-band interrupt response overflow */
2509+
if (int_st & MST_INT_IBIR_OVF) {
2510+
LOG_ERR("%s: controller ibir overflow,", dev->name);
2511+
}
2512+
24892513
/* In-band interrupt data */
24902514
if (int_st & MST_INT_TX_OVF) {
2491-
sys_write32(MST_INT_TX_OVF, config->base + MST_ICR);
24922515
LOG_ERR("%s: controller tx buffer overflow,", dev->name);
24932516
}
24942517

24952518
/* In-band interrupt data */
24962519
if (int_st & MST_INT_RX_UNF) {
2497-
sys_write32(MST_INT_RX_UNF, config->base + MST_ICR);
24982520
LOG_ERR("%s: controller rx buffer underflow,", dev->name);
24992521
}
2500-
2501-
/* In-band interrupt data */
2502-
if (int_st & MST_INT_IBID_THR) {
2503-
sys_write32(MST_INT_IBID_THR, config->base + MST_ICR);
2504-
}
25052522
} else {
25062523
uint32_t int_sl = sys_read32(config->base + SLV_ISR);
2507-
struct cdns_i3c_data *data = dev->data;
25082524
const struct i3c_target_callbacks *target_cb =
25092525
data->target_config ? data->target_config->callbacks : NULL;
25102526
/* Clear interrupts */
@@ -3185,7 +3201,7 @@ static int cdns_i3c_bus_init(const struct device *dev)
31853201

31863202
/* Set fifo thresholds. */
31873203
sys_write32(CMD_THR(I3C_CMDD_THR) | IBI_THR(I3C_IBID_THR) | CMDR_THR(I3C_CMDR_THR) |
3188-
IBIR_THR(I3C_IBIR_THR),
3204+
IBIR_THR(config->ibid_thr),
31893205
config->base + CMD_IBI_THR_CTRL);
31903206

31913207
/* Set TX/RX interrupt thresholds. */
@@ -3197,6 +3213,7 @@ static int cdns_i3c_bus_init(const struct device *dev)
31973213
sys_write32(SLV_DDR_TX_THR(0) | SLV_DDR_RX_THR(1),
31983214
config->base + SLV_DDR_TX_RX_THR_CTRL);
31993215
}
3216+
32003217
/* enable target interrupts */
32013218
sys_write32(SLV_INT_DA_UPD | SLV_INT_SDR_RD_COMP | SLV_INT_SDR_WR_COMP |
32023219
SLV_INT_SDR_RX_THR | SLV_INT_SDR_TX_THR | SLV_INT_SDR_RX_UNF |
@@ -3205,7 +3222,8 @@ static int cdns_i3c_bus_init(const struct device *dev)
32053222
config->base + SLV_IER);
32063223

32073224
/* Enable IBI interrupts. */
3208-
sys_write32(MST_INT_IBIR_THR | MST_INT_RX_UNF | MST_INT_HALTED | MST_INT_TX_OVF,
3225+
sys_write32(MST_INT_IBIR_THR | MST_INT_RX_UNF | MST_INT_HALTED | MST_INT_TX_OVF |
3226+
MST_INT_IBIR_OVF | MST_INT_IBID_THR,
32093227
config->base + MST_IER);
32103228

32113229
int ret = i3c_addr_slots_init(dev);
@@ -3272,6 +3290,7 @@ static struct i3c_driver_api api = {
32723290
.base = DT_INST_REG_ADDR(n), \
32733291
.input_frequency = DT_INST_PROP(n, input_clock_frequency), \
32743292
.irq_config_func = cdns_i3c_config_func_##n, \
3293+
.ibid_thr = DT_INST_PROP(n, ibid_thr), \
32753294
.common.dev_list.i3c = cdns_i3c_device_array_##n, \
32763295
.common.dev_list.num_i3c = ARRAY_SIZE(cdns_i3c_device_array_##n), \
32773296
.common.dev_list.i2c = cdns_i3c_i2c_device_array_##n, \

dts/bindings/i3c/cdns,i3c.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,8 @@ properties:
1919
type: int
2020
required: true
2121
description: The controller input clock frequency
22+
23+
ibid-thr:
24+
type: int
25+
default: 1
26+
description: IBI Data Fifo Threashold Value

0 commit comments

Comments
 (0)