128
128
/* This parameter depends on the implementation and may be tuned */
129
129
#define SVC_I3C_FIFO_SIZE 16
130
130
131
+ #define SVC_I3C_EVENT_IBI BIT(0)
132
+ #define SVC_I3C_EVENT_HOTJOIN BIT(1)
133
+
131
134
struct svc_i3c_cmd {
132
135
u8 addr ;
133
136
bool rnw ;
@@ -177,6 +180,7 @@ struct svc_i3c_regs_save {
177
180
* @ibi.tbq_slot: To be queued IBI slot
178
181
* @ibi.lock: IBI lock
179
182
* @lock: Transfer lock, protect between IBI work thread and callbacks from master
183
+ * @enabled_events: Bit masks for enable events (IBI, HotJoin).
180
184
*/
181
185
struct svc_i3c_master {
182
186
struct i3c_master_controller base ;
@@ -206,6 +210,7 @@ struct svc_i3c_master {
206
210
spinlock_t lock ;
207
211
} ibi ;
208
212
struct mutex lock ;
213
+ int enabled_events ;
209
214
};
210
215
211
216
/**
@@ -220,6 +225,11 @@ struct svc_i3c_i2c_dev_data {
220
225
struct i3c_generic_ibi_pool * ibi_pool ;
221
226
};
222
227
228
+ static inline bool is_events_enabled (struct svc_i3c_master * master , u32 mask )
229
+ {
230
+ return !!(master -> enabled_events & mask );
231
+ }
232
+
223
233
static bool svc_i3c_master_error (struct svc_i3c_master * master )
224
234
{
225
235
u32 mstatus , merrwarn ;
@@ -429,13 +439,16 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
429
439
switch (ibitype ) {
430
440
case SVC_I3C_MSTATUS_IBITYPE_IBI :
431
441
dev = svc_i3c_master_dev_from_addr (master , ibiaddr );
432
- if (!dev )
442
+ if (!dev || ! is_events_enabled ( master , SVC_I3C_EVENT_IBI ) )
433
443
svc_i3c_master_nack_ibi (master );
434
444
else
435
445
svc_i3c_master_handle_ibi (master , dev );
436
446
break ;
437
447
case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN :
438
- svc_i3c_master_ack_ibi (master , false);
448
+ if (is_events_enabled (master , SVC_I3C_EVENT_HOTJOIN ))
449
+ svc_i3c_master_ack_ibi (master , false);
450
+ else
451
+ svc_i3c_master_nack_ibi (master );
439
452
break ;
440
453
case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST :
441
454
svc_i3c_master_nack_ibi (master );
@@ -472,7 +485,9 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
472
485
svc_i3c_master_emit_stop (master );
473
486
break ;
474
487
case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN :
475
- queue_work (master -> base .wq , & master -> hj_work );
488
+ svc_i3c_master_emit_stop (master );
489
+ if (is_events_enabled (master , SVC_I3C_EVENT_HOTJOIN ))
490
+ queue_work (master -> base .wq , & master -> hj_work );
476
491
break ;
477
492
case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST :
478
493
default :
@@ -1472,6 +1487,7 @@ static int svc_i3c_master_enable_ibi(struct i3c_dev_desc *dev)
1472
1487
return ret ;
1473
1488
}
1474
1489
1490
+ master -> enabled_events |= SVC_I3C_EVENT_IBI ;
1475
1491
svc_i3c_master_enable_interrupts (master , SVC_I3C_MINT_SLVSTART );
1476
1492
1477
1493
return i3c_master_enec_locked (m , dev -> info .dyn_addr , I3C_CCC_EVENT_SIR );
@@ -1483,7 +1499,9 @@ static int svc_i3c_master_disable_ibi(struct i3c_dev_desc *dev)
1483
1499
struct svc_i3c_master * master = to_svc_i3c_master (m );
1484
1500
int ret ;
1485
1501
1486
- svc_i3c_master_disable_interrupts (master );
1502
+ master -> enabled_events &= ~SVC_I3C_EVENT_IBI ;
1503
+ if (!master -> enabled_events )
1504
+ svc_i3c_master_disable_interrupts (master );
1487
1505
1488
1506
ret = i3c_master_disec_locked (m , dev -> info .dyn_addr , I3C_CCC_EVENT_SIR );
1489
1507
@@ -1493,6 +1511,39 @@ static int svc_i3c_master_disable_ibi(struct i3c_dev_desc *dev)
1493
1511
return ret ;
1494
1512
}
1495
1513
1514
+ static int svc_i3c_master_enable_hotjoin (struct i3c_master_controller * m )
1515
+ {
1516
+ struct svc_i3c_master * master = to_svc_i3c_master (m );
1517
+ int ret ;
1518
+
1519
+ ret = pm_runtime_resume_and_get (master -> dev );
1520
+ if (ret < 0 ) {
1521
+ dev_err (master -> dev , "<%s> Cannot get runtime PM.\n" , __func__ );
1522
+ return ret ;
1523
+ }
1524
+
1525
+ master -> enabled_events |= SVC_I3C_EVENT_HOTJOIN ;
1526
+
1527
+ svc_i3c_master_enable_interrupts (master , SVC_I3C_MINT_SLVSTART );
1528
+
1529
+ return 0 ;
1530
+ }
1531
+
1532
+ static int svc_i3c_master_disable_hotjoin (struct i3c_master_controller * m )
1533
+ {
1534
+ struct svc_i3c_master * master = to_svc_i3c_master (m );
1535
+
1536
+ master -> enabled_events &= ~SVC_I3C_EVENT_HOTJOIN ;
1537
+
1538
+ if (!master -> enabled_events )
1539
+ svc_i3c_master_disable_interrupts (master );
1540
+
1541
+ pm_runtime_mark_last_busy (master -> dev );
1542
+ pm_runtime_put_autosuspend (master -> dev );
1543
+
1544
+ return 0 ;
1545
+ }
1546
+
1496
1547
static void svc_i3c_master_recycle_ibi_slot (struct i3c_dev_desc * dev ,
1497
1548
struct i3c_ibi_slot * slot )
1498
1549
{
@@ -1519,6 +1570,8 @@ static const struct i3c_master_controller_ops svc_i3c_master_ops = {
1519
1570
.recycle_ibi_slot = svc_i3c_master_recycle_ibi_slot ,
1520
1571
.enable_ibi = svc_i3c_master_enable_ibi ,
1521
1572
.disable_ibi = svc_i3c_master_disable_ibi ,
1573
+ .enable_hotjoin = svc_i3c_master_enable_hotjoin ,
1574
+ .disable_hotjoin = svc_i3c_master_disable_hotjoin ,
1522
1575
};
1523
1576
1524
1577
static int svc_i3c_master_prepare_clks (struct svc_i3c_master * master )
0 commit comments