@@ -1136,6 +1136,23 @@ static void dw_i3c_master_free_ibi(struct i3c_dev_desc *dev)
11361136 data -> ibi_pool = NULL ;
11371137}
11381138
1139+ static void dw_i3c_master_enable_sir_signal (struct dw_i3c_master * master , bool enable )
1140+ {
1141+ u32 reg ;
1142+
1143+ reg = readl (master -> regs + INTR_STATUS_EN );
1144+ reg &= ~INTR_IBI_THLD_STAT ;
1145+ if (enable )
1146+ reg |= INTR_IBI_THLD_STAT ;
1147+ writel (reg , master -> regs + INTR_STATUS_EN );
1148+
1149+ reg = readl (master -> regs + INTR_SIGNAL_EN );
1150+ reg &= ~INTR_IBI_THLD_STAT ;
1151+ if (enable )
1152+ reg |= INTR_IBI_THLD_STAT ;
1153+ writel (reg , master -> regs + INTR_SIGNAL_EN );
1154+ }
1155+
11391156static void dw_i3c_master_set_sir_enabled (struct dw_i3c_master * master ,
11401157 struct i3c_dev_desc * dev ,
11411158 u8 idx , bool enable )
@@ -1170,23 +1187,34 @@ static void dw_i3c_master_set_sir_enabled(struct dw_i3c_master *master,
11701187 }
11711188 writel (reg , master -> regs + IBI_SIR_REQ_REJECT );
11721189
1173- if (global ) {
1174- reg = readl (master -> regs + INTR_STATUS_EN );
1175- reg &= ~INTR_IBI_THLD_STAT ;
1176- if (enable )
1177- reg |= INTR_IBI_THLD_STAT ;
1178- writel (reg , master -> regs + INTR_STATUS_EN );
1179-
1180- reg = readl (master -> regs + INTR_SIGNAL_EN );
1181- reg &= ~INTR_IBI_THLD_STAT ;
1182- if (enable )
1183- reg |= INTR_IBI_THLD_STAT ;
1184- writel (reg , master -> regs + INTR_SIGNAL_EN );
1185- }
1190+ if (global )
1191+ dw_i3c_master_enable_sir_signal (master , enable );
1192+
11861193
11871194 spin_unlock_irqrestore (& master -> devs_lock , flags );
11881195}
11891196
1197+ static int dw_i3c_master_enable_hotjoin (struct i3c_master_controller * m )
1198+ {
1199+ struct dw_i3c_master * master = to_dw_i3c_master (m );
1200+
1201+ dw_i3c_master_enable_sir_signal (master , true);
1202+ writel (readl (master -> regs + DEVICE_CTRL ) & ~DEV_CTRL_HOT_JOIN_NACK ,
1203+ master -> regs + DEVICE_CTRL );
1204+
1205+ return 0 ;
1206+ }
1207+
1208+ static int dw_i3c_master_disable_hotjoin (struct i3c_master_controller * m )
1209+ {
1210+ struct dw_i3c_master * master = to_dw_i3c_master (m );
1211+
1212+ writel (readl (master -> regs + DEVICE_CTRL ) | DEV_CTRL_HOT_JOIN_NACK ,
1213+ master -> regs + DEVICE_CTRL );
1214+
1215+ return 0 ;
1216+ }
1217+
11901218static int dw_i3c_master_enable_ibi (struct i3c_dev_desc * dev )
11911219{
11921220 struct dw_i3c_i2c_dev_data * data = i3c_dev_get_master_data (dev );
@@ -1326,6 +1354,8 @@ static void dw_i3c_master_irq_handle_ibis(struct dw_i3c_master *master)
13261354
13271355 if (IBI_TYPE_SIRQ (reg )) {
13281356 dw_i3c_master_handle_ibi_sir (master , reg );
1357+ } else if (IBI_TYPE_HJ (reg )) {
1358+ queue_work (master -> base .wq , & master -> hj_work );
13291359 } else {
13301360 len = IBI_QUEUE_STATUS_DATA_LEN (reg );
13311361 dev_info (& master -> base .dev ,
@@ -1393,6 +1423,8 @@ static const struct i3c_master_controller_ops dw_mipi_i3c_ibi_ops = {
13931423 .enable_ibi = dw_i3c_master_enable_ibi ,
13941424 .disable_ibi = dw_i3c_master_disable_ibi ,
13951425 .recycle_ibi_slot = dw_i3c_master_recycle_ibi_slot ,
1426+ .enable_hotjoin = dw_i3c_master_enable_hotjoin ,
1427+ .disable_hotjoin = dw_i3c_master_disable_hotjoin ,
13961428};
13971429
13981430/* default platform ops implementations */
@@ -1412,6 +1444,14 @@ static const struct dw_i3c_platform_ops dw_i3c_platform_ops_default = {
14121444 .set_dat_ibi = dw_i3c_platform_set_dat_ibi_nop ,
14131445};
14141446
1447+ static void dw_i3c_hj_work (struct work_struct * work )
1448+ {
1449+ struct dw_i3c_master * master =
1450+ container_of (work , typeof (* master ), hj_work );
1451+
1452+ i3c_master_do_daa (& master -> base );
1453+ }
1454+
14151455int dw_i3c_common_probe (struct dw_i3c_master * master ,
14161456 struct platform_device * pdev )
14171457{
@@ -1469,6 +1509,7 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
14691509 if (master -> ibi_capable )
14701510 ops = & dw_mipi_i3c_ibi_ops ;
14711511
1512+ INIT_WORK (& master -> hj_work , dw_i3c_hj_work );
14721513 ret = i3c_master_register (& master -> base , & pdev -> dev , ops , false);
14731514 if (ret )
14741515 goto err_assert_rst ;
0 commit comments