Skip to content

Commit 8ab712a

Browse files
ChiHuaLkartben
authored andcommitted
drivers: i2c: npcx: prevent unexpected target address match ISR
This commit prevents the hardware from generating an unexpected target slave address match ISR by the following change: 1. Enable the New Match Interrupt Enable bit (NMINTEN) only when necessary. 2. Explicitly clear all SMBnADDRx registers because they are not cleared when the I2C hardware is disabled. It will cause the asynchrinization between SMBnADDRx and registered_target_mask if the system jumps from the RO image to the RW image. Signed-off-by: Jun Lin <[email protected]> Signed-off-by: Alvis Sun <[email protected]>
1 parent 8bfb08f commit 8ab712a

File tree

1 file changed

+42
-33
lines changed

1 file changed

+42
-33
lines changed

drivers/i2c/i2c_npcx_controller.c

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,37 @@ static inline void i2c_ctrl_fifo_clear_status(const struct device *dev)
403403
inst->SMBFIF_CTS |= BIT(NPCX_SMBFIF_CTS_CLR_FIFO);
404404
}
405405

406+
/* I2C target reg access */
407+
#ifdef CONFIG_I2C_TARGET
408+
static volatile uint8_t *npcx_i2c_ctrl_target_get_reg_smbaddr(const struct device *i2c_dev,
409+
int index)
410+
{
411+
struct smb_reg *const inst = HAL_I2C_INSTANCE(i2c_dev);
412+
413+
switch (index) {
414+
case 0:
415+
return &inst->SMBADDR1;
416+
case 1:
417+
return &inst->SMBADDR2;
418+
case 2:
419+
return &inst->SMBADDR3;
420+
case 3:
421+
return &inst->SMBADDR4;
422+
case 4:
423+
return &inst->SMBADDR5;
424+
case 5:
425+
return &inst->SMBADDR6;
426+
case 6:
427+
return &inst->SMBADDR7;
428+
case 7:
429+
return &inst->SMBADDR8;
430+
default:
431+
LOG_ERR("Invalid SMBADDR index: %d", index);
432+
return NULL;
433+
}
434+
}
435+
#endif /* CONFIG_I2C_TARGET */
436+
406437
/*
407438
* I2C local functions which touch the registers in 'Normal' bank. These
408439
* utilities will change bank back to FIFO mode when leaving themselves in case
@@ -433,6 +464,16 @@ static void i2c_ctrl_init_module(const struct device *dev)
433464
/* Enable module - before configuring CTL1 */
434465
inst->SMBCTL2 |= BIT(NPCX_SMBCTL2_ENABLE);
435466

467+
#ifdef CONFIG_I2C_TARGET
468+
volatile uint8_t *reg_smbaddr;
469+
470+
/* Clear all the SMBnADDR */
471+
for (int i = 0; i < NPCX_I2C_FLAG_COUNT; i++) {
472+
reg_smbaddr = npcx_i2c_ctrl_target_get_reg_smbaddr(dev, i);
473+
*reg_smbaddr = 0;
474+
}
475+
#endif
476+
436477
/* Enable SMB interrupt and 'New Address Match' interrupt source */
437478
inst->SMBCTL1 |= BIT(NPCX_SMBCTL1_NMINTE) | BIT(NPCX_SMBCTL1_INTEN);
438479

@@ -1194,33 +1235,6 @@ int npcx_i2c_ctrl_recover_bus(const struct device *dev)
11941235
}
11951236

11961237
#ifdef CONFIG_I2C_TARGET
1197-
static volatile uint8_t *npcx_i2c_ctrl_target_get_reg_smbaddr(const struct device *i2c_dev,
1198-
int index)
1199-
{
1200-
struct smb_reg *const inst = HAL_I2C_INSTANCE(i2c_dev);
1201-
1202-
switch (index) {
1203-
case 0:
1204-
return &inst->SMBADDR1;
1205-
case 1:
1206-
return &inst->SMBADDR2;
1207-
case 2:
1208-
return &inst->SMBADDR3;
1209-
case 3:
1210-
return &inst->SMBADDR4;
1211-
case 4:
1212-
return &inst->SMBADDR5;
1213-
case 5:
1214-
return &inst->SMBADDR6;
1215-
case 6:
1216-
return &inst->SMBADDR7;
1217-
case 7:
1218-
return &inst->SMBADDR8;
1219-
default:
1220-
LOG_ERR("Invalid SMBADDR index: %d", index);
1221-
return NULL;
1222-
}
1223-
}
12241238

12251239
int npcx_i2c_ctrl_target_register(const struct device *i2c_dev,
12261240
struct i2c_target_config *target_cfg, uint8_t port)
@@ -1372,7 +1386,7 @@ int npcx_i2c_ctrl_target_unregister(const struct device *i2c_dev,
13721386
i2c_ctrl_bank_sel(i2c_dev, NPCX_I2C_BANK_FIFO);
13731387

13741388
/* Reconfigure SMBCTL1 */
1375-
inst->SMBCTL1 |= BIT(NPCX_SMBCTL1_NMINTE) | BIT(NPCX_SMBCTL1_INTEN);
1389+
inst->SMBCTL1 |= BIT(NPCX_SMBCTL1_INTEN);
13761390

13771391
/* Disable irq of smb wake-up event */
13781392
if (IS_ENABLED(CONFIG_PM)) {
@@ -1392,14 +1406,9 @@ int npcx_i2c_ctrl_target_unregister(const struct device *i2c_dev,
13921406

13931407
static void i2c_target_wk_isr(const struct device *dev, struct npcx_wui *wui)
13941408
{
1395-
struct smb_reg *const inst = HAL_I2C_INSTANCE(dev);
1396-
13971409
/* Clear wake up detection event status */
13981410
npcx_i2c_target_clear_detection_event();
13991411

1400-
/* Reconfigure SMBCTL1 */
1401-
inst->SMBCTL1 |= BIT(NPCX_SMBCTL1_NMINTE) | BIT(NPCX_SMBCTL1_INTEN);
1402-
14031412
/*
14041413
* Suspend-to-idle stops SMB module clocks (derived from APB2/APB3), which must remain
14051414
* active during a transaction.

0 commit comments

Comments
 (0)