Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

i3c: master: svc: Use manual response for IBI events

Driver wants to nack the IBI request when the target is not in the
known address list. In below code, svc_i3c_master_nack_ibi() will
cause undefined behavior when using AUTOIBI with auto response rule,
because hw always auto ack the IBI request.

switch (ibitype) {
case SVC_I3C_MSTATUS_IBITYPE_IBI:
dev = svc_i3c_master_dev_from_addr(master, ibiaddr);
if (!dev || !is_events_enabled(master, SVC_I3C_EVENT_IBI))
svc_i3c_master_nack_ibi(master);
...
break;

AutoIBI has another issue that the controller doesn't quit AutoIBI state
after IBIWON polling timeout when there is a SDA glitch(high->low->high).
1. SDA high->low: raising an interrupt to execute IBI ISR
2. SDA low->high
3. Driver writes an AutoIBI request
4. AutoIBI process does not start because SDA is not low
5. IBIWON polling times out
6. Controller reamins in AutoIBI state and doesn't accept EmitStop request

Emitting broadcast address with IBIRESP_MANUAL avoids both issues.

Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver")
Signed-off-by: Stanley Chu <yschu@nuvoton.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://lore.kernel.org/r/20250829012309.3562585-2-yschu@nuvoton.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>

authored by

Stanley Chu and committed by
Alexandre Belloni
a7869b0a a79ac2cd

+25 -5
+25 -5
drivers/i3c/master/svc-i3c-master.c
··· 517 517 */ 518 518 writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS); 519 519 520 - /* Acknowledge the incoming interrupt with the AUTOIBI mechanism */ 521 - writel(SVC_I3C_MCTRL_REQUEST_AUTO_IBI | 522 - SVC_I3C_MCTRL_IBIRESP_AUTO, 520 + /* 521 + * Write REQUEST_START_ADDR request to emit broadcast address for arbitration, 522 + * instend of using AUTO_IBI. 523 + * 524 + * Using AutoIBI request may cause controller to remain in AutoIBI state when 525 + * there is a glitch on SDA line (high->low->high). 526 + * 1. SDA high->low, raising an interrupt to execute IBI isr. 527 + * 2. SDA low->high. 528 + * 3. IBI isr writes an AutoIBI request. 529 + * 4. The controller will not start AutoIBI process because SDA is not low. 530 + * 5. IBIWON polling times out. 531 + * 6. Controller reamins in AutoIBI state and doesn't accept EmitStop request. 532 + */ 533 + writel(SVC_I3C_MCTRL_REQUEST_START_ADDR | 534 + SVC_I3C_MCTRL_TYPE_I3C | 535 + SVC_I3C_MCTRL_IBIRESP_MANUAL | 536 + SVC_I3C_MCTRL_DIR(SVC_I3C_MCTRL_DIR_WRITE) | 537 + SVC_I3C_MCTRL_ADDR(I3C_BROADCAST_ADDR), 523 538 master->regs + SVC_I3C_MCTRL); 524 539 525 540 /* Wait for IBIWON, should take approximately 100us */ ··· 554 539 switch (ibitype) { 555 540 case SVC_I3C_MSTATUS_IBITYPE_IBI: 556 541 dev = svc_i3c_master_dev_from_addr(master, ibiaddr); 557 - if (!dev || !is_events_enabled(master, SVC_I3C_EVENT_IBI)) 542 + if (!dev || !is_events_enabled(master, SVC_I3C_EVENT_IBI)) { 558 543 svc_i3c_master_nack_ibi(master); 559 - else 544 + } else { 545 + if (dev->info.bcr & I3C_BCR_IBI_PAYLOAD) 546 + svc_i3c_master_ack_ibi(master, true); 547 + else 548 + svc_i3c_master_ack_ibi(master, false); 560 549 svc_i3c_master_handle_ibi(master, dev); 550 + } 561 551 break; 562 552 case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN: 563 553 if (is_events_enabled(master, SVC_I3C_EVENT_HOTJOIN))