128128/* This parameter depends on the implementation and may be tuned */
129129#define SVC_I3C_FIFO_SIZE 16
130130
131+ #define SVC_I3C_EVENT_IBI BIT(0)
132+ #define SVC_I3C_EVENT_HOTJOIN BIT(1)
133+
131134struct svc_i3c_cmd {
132135 u8 addr ;
133136 bool rnw ;
@@ -177,6 +180,7 @@ struct svc_i3c_regs_save {
177180 * @ibi.tbq_slot: To be queued IBI slot
178181 * @ibi.lock: IBI lock
179182 * @lock: Transfer lock, protect between IBI work thread and callbacks from master
183+ * @enabled_events: Bit masks for enable events (IBI, HotJoin).
180184 */
181185struct svc_i3c_master {
182186 struct i3c_master_controller base ;
@@ -206,6 +210,7 @@ struct svc_i3c_master {
206210 spinlock_t lock ;
207211 } ibi ;
208212 struct mutex lock ;
213+ int enabled_events ;
209214};
210215
211216/**
@@ -220,6 +225,11 @@ struct svc_i3c_i2c_dev_data {
220225 struct i3c_generic_ibi_pool * ibi_pool ;
221226};
222227
228+ static inline bool is_events_enabled (struct svc_i3c_master * master , u32 mask )
229+ {
230+ return !!(master -> enabled_events & mask );
231+ }
232+
223233static bool svc_i3c_master_error (struct svc_i3c_master * master )
224234{
225235 u32 mstatus , merrwarn ;
@@ -429,13 +439,16 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
429439 switch (ibitype ) {
430440 case SVC_I3C_MSTATUS_IBITYPE_IBI :
431441 dev = svc_i3c_master_dev_from_addr (master , ibiaddr );
432- if (!dev )
442+ if (!dev || ! is_events_enabled ( master , SVC_I3C_EVENT_IBI ) )
433443 svc_i3c_master_nack_ibi (master );
434444 else
435445 svc_i3c_master_handle_ibi (master , dev );
436446 break ;
437447 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 );
439452 break ;
440453 case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST :
441454 svc_i3c_master_nack_ibi (master );
@@ -472,7 +485,9 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
472485 svc_i3c_master_emit_stop (master );
473486 break ;
474487 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 );
476491 break ;
477492 case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST :
478493 default :
@@ -1472,6 +1487,7 @@ static int svc_i3c_master_enable_ibi(struct i3c_dev_desc *dev)
14721487 return ret ;
14731488 }
14741489
1490+ master -> enabled_events |= SVC_I3C_EVENT_IBI ;
14751491 svc_i3c_master_enable_interrupts (master , SVC_I3C_MINT_SLVSTART );
14761492
14771493 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)
14831499 struct svc_i3c_master * master = to_svc_i3c_master (m );
14841500 int ret ;
14851501
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 );
14871505
14881506 ret = i3c_master_disec_locked (m , dev -> info .dyn_addr , I3C_CCC_EVENT_SIR );
14891507
@@ -1493,6 +1511,39 @@ static int svc_i3c_master_disable_ibi(struct i3c_dev_desc *dev)
14931511 return ret ;
14941512}
14951513
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+
14961547static void svc_i3c_master_recycle_ibi_slot (struct i3c_dev_desc * dev ,
14971548 struct i3c_ibi_slot * slot )
14981549{
@@ -1519,6 +1570,8 @@ static const struct i3c_master_controller_ops svc_i3c_master_ops = {
15191570 .recycle_ibi_slot = svc_i3c_master_recycle_ibi_slot ,
15201571 .enable_ibi = svc_i3c_master_enable_ibi ,
15211572 .disable_ibi = svc_i3c_master_disable_ibi ,
1573+ .enable_hotjoin = svc_i3c_master_enable_hotjoin ,
1574+ .disable_hotjoin = svc_i3c_master_disable_hotjoin ,
15221575};
15231576
15241577static int svc_i3c_master_prepare_clks (struct svc_i3c_master * master )
0 commit comments