@@ -1136,6 +1136,23 @@ static void dw_i3c_master_free_ibi(struct i3c_dev_desc *dev)
1136
1136
data -> ibi_pool = NULL ;
1137
1137
}
1138
1138
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
+
1139
1156
static void dw_i3c_master_set_sir_enabled (struct dw_i3c_master * master ,
1140
1157
struct i3c_dev_desc * dev ,
1141
1158
u8 idx , bool enable )
@@ -1170,23 +1187,34 @@ static void dw_i3c_master_set_sir_enabled(struct dw_i3c_master *master,
1170
1187
}
1171
1188
writel (reg , master -> regs + IBI_SIR_REQ_REJECT );
1172
1189
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
+
1186
1193
1187
1194
spin_unlock_irqrestore (& master -> devs_lock , flags );
1188
1195
}
1189
1196
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
+
1190
1218
static int dw_i3c_master_enable_ibi (struct i3c_dev_desc * dev )
1191
1219
{
1192
1220
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)
1326
1354
1327
1355
if (IBI_TYPE_SIRQ (reg )) {
1328
1356
dw_i3c_master_handle_ibi_sir (master , reg );
1357
+ } else if (IBI_TYPE_HJ (reg )) {
1358
+ queue_work (master -> base .wq , & master -> hj_work );
1329
1359
} else {
1330
1360
len = IBI_QUEUE_STATUS_DATA_LEN (reg );
1331
1361
dev_info (& master -> base .dev ,
@@ -1393,6 +1423,8 @@ static const struct i3c_master_controller_ops dw_mipi_i3c_ibi_ops = {
1393
1423
.enable_ibi = dw_i3c_master_enable_ibi ,
1394
1424
.disable_ibi = dw_i3c_master_disable_ibi ,
1395
1425
.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 ,
1396
1428
};
1397
1429
1398
1430
/* default platform ops implementations */
@@ -1412,6 +1444,14 @@ static const struct dw_i3c_platform_ops dw_i3c_platform_ops_default = {
1412
1444
.set_dat_ibi = dw_i3c_platform_set_dat_ibi_nop ,
1413
1445
};
1414
1446
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
+
1415
1455
int dw_i3c_common_probe (struct dw_i3c_master * master ,
1416
1456
struct platform_device * pdev )
1417
1457
{
@@ -1469,6 +1509,7 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
1469
1509
if (master -> ibi_capable )
1470
1510
ops = & dw_mipi_i3c_ibi_ops ;
1471
1511
1512
+ INIT_WORK (& master -> hj_work , dw_i3c_hj_work );
1472
1513
ret = i3c_master_register (& master -> base , & pdev -> dev , ops , false);
1473
1514
if (ret )
1474
1515
goto err_assert_rst ;
0 commit comments