|
58 | 58 | #define SVC_I3C_MSTATUS 0x088
|
59 | 59 | #define SVC_I3C_MSTATUS_STATE(x) FIELD_GET(GENMASK(2, 0), (x))
|
60 | 60 | #define SVC_I3C_MSTATUS_STATE_DAA(x) (SVC_I3C_MSTATUS_STATE(x) == 5)
|
| 61 | +#define SVC_I3C_MSTATUS_STATE_SLVREQ(x) (SVC_I3C_MSTATUS_STATE(x) == 1) |
61 | 62 | #define SVC_I3C_MSTATUS_STATE_IDLE(x) (SVC_I3C_MSTATUS_STATE(x) == 0)
|
62 | 63 | #define SVC_I3C_MSTATUS_BETWEEN(x) FIELD_GET(BIT(4), (x))
|
63 | 64 | #define SVC_I3C_MSTATUS_NACKED(x) FIELD_GET(BIT(5), (x))
|
|
143 | 144 | * Fill the FIFO in advance to prevent FIFO from becoming empty.
|
144 | 145 | */
|
145 | 146 | #define SVC_I3C_QUIRK_FIFO_EMPTY BIT(0)
|
| 147 | +/* |
| 148 | + * SVC_I3C_QUIRK_FLASE_SLVSTART: |
| 149 | + * I3C HW may generate an invalid SlvStart event when emitting a STOP. |
| 150 | + * If it is a true SlvStart, the MSTATUS state is SLVREQ. |
| 151 | + */ |
| 152 | +#define SVC_I3C_QUIRK_FALSE_SLVSTART BIT(1) |
146 | 153 |
|
147 | 154 | struct svc_i3c_cmd {
|
148 | 155 | u8 addr;
|
@@ -586,6 +593,11 @@ static irqreturn_t svc_i3c_master_irq_handler(int irq, void *dev_id)
|
586 | 593 | /* Clear the interrupt status */
|
587 | 594 | writel(SVC_I3C_MINT_SLVSTART, master->regs + SVC_I3C_MSTATUS);
|
588 | 595 |
|
| 596 | + /* Ignore the false event */ |
| 597 | + if (svc_has_quirk(master, SVC_I3C_QUIRK_FALSE_SLVSTART) && |
| 598 | + !SVC_I3C_MSTATUS_STATE_SLVREQ(active)) |
| 599 | + return IRQ_HANDLED; |
| 600 | + |
589 | 601 | svc_i3c_master_disable_interrupts(master);
|
590 | 602 |
|
591 | 603 | /* Handle the interrupt in a non atomic context */
|
@@ -2020,7 +2032,8 @@ static const struct dev_pm_ops svc_i3c_pm_ops = {
|
2020 | 2032 | };
|
2021 | 2033 |
|
2022 | 2034 | static const struct svc_i3c_drvdata npcm845_drvdata = {
|
2023 |
| - .quirks = SVC_I3C_QUIRK_FIFO_EMPTY, |
| 2035 | + .quirks = SVC_I3C_QUIRK_FIFO_EMPTY | |
| 2036 | + SVC_I3C_QUIRK_FALSE_SLVSTART, |
2024 | 2037 | };
|
2025 | 2038 |
|
2026 | 2039 | static const struct svc_i3c_drvdata svc_default_drvdata = {};
|
|
0 commit comments