@@ -547,6 +547,14 @@ struct cdns_i3c_xfer {
547
547
struct cdns_i3c_cmd cmds [I3C_MAX_MSGS ];
548
548
};
549
549
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
+
550
558
/* Driver config */
551
559
struct cdns_i3c_config {
552
560
struct i3c_driver_config common ;
@@ -556,12 +564,17 @@ struct cdns_i3c_config {
556
564
uint32_t input_frequency ;
557
565
/** Interrupt configuration function. */
558
566
void (* irq_config_func )(const struct device * dev );
567
+ /** IBID Threshold value */
568
+ uint8_t ibid_thr ;
559
569
};
560
570
561
571
/* Driver instance data */
562
572
struct cdns_i3c_data {
563
573
struct i3c_driver_data common ;
564
574
struct cdns_i3c_hw_config hw_cfg ;
575
+ #ifdef CONFIG_I3C_USE_IBI
576
+ struct cdns_i3c_ibi_buf ibi_buf ;
577
+ #endif
565
578
struct k_mutex bus_lock ;
566
579
struct cdns_i3c_i2c_dev_data cdns_i3c_i2c_priv_data [I3C_MAX_DEVS ];
567
580
struct cdns_i3c_xfer xfer ;
@@ -2298,7 +2311,7 @@ static int cdns_i3c_read_ibi_fifo(const struct cdns_i3c_config *config, void *bu
2298
2311
static void cdns_i3c_handle_ibi (const struct device * dev , uint32_t ibir )
2299
2312
{
2300
2313
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 ;
2302
2315
2303
2316
/* The slave ID returned here is the device ID in the SIR map NOT the device ID
2304
2317
* in the RR map.
@@ -2326,20 +2339,25 @@ static void cdns_i3c_handle_ibi(const struct device *dev, uint32_t ibir)
2326
2339
return ;
2327
2340
}
2328
2341
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 ) ;
2331
2344
}
2332
2345
2333
2346
/* Read out any payload bytes */
2334
2347
uint8_t ibi_len = IBIR_XFER_BYTES (ibir );
2335
2348
2336
2349
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
+ }
2339
2356
}
2357
+ data -> ibi_buf .ibi_data_cnt = 0 ;
2340
2358
}
2341
2359
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 ) {
2343
2361
LOG_ERR ("%s: Error enqueue IBI IRQ work" , dev -> name );
2344
2362
}
2345
2363
}
@@ -2445,66 +2463,64 @@ static void cdns_i3c_target_sdr_tx_thr_int_handler(const struct device *dev,
2445
2463
static void cdns_i3c_irq_handler (const struct device * dev )
2446
2464
{
2447
2465
const struct cdns_i3c_config * config = dev -> config ;
2466
+ struct cdns_i3c_data * data = dev -> data ;
2448
2467
2449
2468
if (sys_read32 (config -> base + MST_STATUS0 ) & MST_STATUS0_MASTER_MODE ) {
2450
2469
uint32_t int_st = sys_read32 (config -> base + MST_ISR );
2470
+ sys_write32 (int_st , config -> base + MST_ICR );
2451
2471
2452
2472
/* Command queue empty */
2453
2473
if (int_st & MST_INT_HALTED ) {
2454
2474
LOG_WRN ("Core Halted, 2 read aborts" );
2455
- sys_write32 (MST_INT_HALTED , config -> base + MST_ICR );
2456
2475
}
2457
2476
2458
2477
/* Command queue empty */
2459
2478
if (int_st & MST_INT_CMDD_EMP ) {
2460
2479
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 );
2477
2480
}
2478
2481
2479
2482
/* In-band interrupt */
2480
2483
if (int_st & MST_INT_IBIR_THR ) {
2481
- sys_write32 (MST_INT_IBIR_THR , config -> base + MST_ICR );
2482
2484
#ifdef CONFIG_I3C_USE_IBI
2483
2485
cnds_i3c_master_demux_ibis (dev );
2484
2486
#else
2485
2487
LOG_ERR ("%s: IBI received - Kconfig for using IBIs is not enabled" ,
2486
2488
dev -> name );
2487
2489
#endif
2488
2490
}
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
+
2489
2513
/* In-band interrupt data */
2490
2514
if (int_st & MST_INT_TX_OVF ) {
2491
- sys_write32 (MST_INT_TX_OVF , config -> base + MST_ICR );
2492
2515
LOG_ERR ("%s: controller tx buffer overflow," , dev -> name );
2493
2516
}
2494
2517
2495
2518
/* In-band interrupt data */
2496
2519
if (int_st & MST_INT_RX_UNF ) {
2497
- sys_write32 (MST_INT_RX_UNF , config -> base + MST_ICR );
2498
2520
LOG_ERR ("%s: controller rx buffer underflow," , dev -> name );
2499
2521
}
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
- }
2505
2522
} else {
2506
2523
uint32_t int_sl = sys_read32 (config -> base + SLV_ISR );
2507
- struct cdns_i3c_data * data = dev -> data ;
2508
2524
const struct i3c_target_callbacks * target_cb =
2509
2525
data -> target_config ? data -> target_config -> callbacks : NULL ;
2510
2526
/* Clear interrupts */
@@ -3185,7 +3201,7 @@ static int cdns_i3c_bus_init(const struct device *dev)
3185
3201
3186
3202
/* Set fifo thresholds. */
3187
3203
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 ),
3189
3205
config -> base + CMD_IBI_THR_CTRL );
3190
3206
3191
3207
/* Set TX/RX interrupt thresholds. */
@@ -3197,6 +3213,7 @@ static int cdns_i3c_bus_init(const struct device *dev)
3197
3213
sys_write32 (SLV_DDR_TX_THR (0 ) | SLV_DDR_RX_THR (1 ),
3198
3214
config -> base + SLV_DDR_TX_RX_THR_CTRL );
3199
3215
}
3216
+
3200
3217
/* enable target interrupts */
3201
3218
sys_write32 (SLV_INT_DA_UPD | SLV_INT_SDR_RD_COMP | SLV_INT_SDR_WR_COMP |
3202
3219
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)
3205
3222
config -> base + SLV_IER );
3206
3223
3207
3224
/* 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 ,
3209
3227
config -> base + MST_IER );
3210
3228
3211
3229
int ret = i3c_addr_slots_init (dev );
@@ -3272,6 +3290,7 @@ static struct i3c_driver_api api = {
3272
3290
.base = DT_INST_REG_ADDR(n), \
3273
3291
.input_frequency = DT_INST_PROP(n, input_clock_frequency), \
3274
3292
.irq_config_func = cdns_i3c_config_func_##n, \
3293
+ .ibid_thr = DT_INST_PROP(n, ibid_thr), \
3275
3294
.common.dev_list.i3c = cdns_i3c_device_array_##n, \
3276
3295
.common.dev_list.num_i3c = ARRAY_SIZE(cdns_i3c_device_array_##n), \
3277
3296
.common.dev_list.i2c = cdns_i3c_i2c_device_array_##n, \
0 commit comments