Message ID | 20241001-svc-i3c-hj-v5-5-480ab8aed849@nxp.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | I3C: master: svc: collect all patches to improve hotjoin stability | expand |
Hi Frank, Frank.Li@nxp.com wrote on Tue, 01 Oct 2024 12:02:54 -0400: > Wait for the controller to complete emitting ACK/NACK, otherwise the next > command may be omitted by the hardware. > > A "command done" check in svc_i3c_master_nack(ack)_ibi() and change the Add a? > return type to int to flag possible timeouts. > > Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com> > Signed-off-by: Frank Li <Frank.Li@nxp.com> > --- > Change from v3 to v4 > - rework commit message > - add miquel's review tag > - directly return readl(...) > --- > drivers/i3c/master/svc-i3c-master.c | 29 +++++++++++++++++++++++------ > 1 file changed, 23 insertions(+), 6 deletions(-) > > diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c > index 1ee6ce186195c..3388c9af63fcc 100644 > --- a/drivers/i3c/master/svc-i3c-master.c > +++ b/drivers/i3c/master/svc-i3c-master.c > @@ -388,10 +388,11 @@ static int svc_i3c_master_handle_ibi(struct svc_i3c_master *master, > return 0; > } > > -static void svc_i3c_master_ack_ibi(struct svc_i3c_master *master, > +static int svc_i3c_master_ack_ibi(struct svc_i3c_master *master, > bool mandatory_byte) > { > unsigned int ibi_ack_nack; > + u32 reg; > > ibi_ack_nack = SVC_I3C_MCTRL_REQUEST_IBI_ACKNACK; > if (mandatory_byte) > @@ -400,18 +401,30 @@ static void svc_i3c_master_ack_ibi(struct svc_i3c_master *master, > ibi_ack_nack |= SVC_I3C_MCTRL_IBIRESP_ACK_WITHOUT_BYTE; > > writel(ibi_ack_nack, master->regs + SVC_I3C_MCTRL); > + > + return readl_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS, reg, > + SVC_I3C_MSTATUS_MCTRLDONE(reg), 1, 1000); > + > } > > -static void svc_i3c_master_nack_ibi(struct svc_i3c_master *master) > +static int svc_i3c_master_nack_ibi(struct svc_i3c_master *master) > { > + int ret; > + u32 reg; > + > writel(SVC_I3C_MCTRL_REQUEST_IBI_ACKNACK | > SVC_I3C_MCTRL_IBIRESP_NACK, > master->regs + SVC_I3C_MCTRL); > + > + ret = readl_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS, reg, > + SVC_I3C_MSTATUS_MCTRLDONE(reg), 1, 1000); > + return ret; > } > > static int svc_i3c_master_handle_ibi_won(struct svc_i3c_master *master, u32 mstatus) > { > u32 ibitype; > + int ret = 0; > > ibitype = SVC_I3C_MSTATUS_IBITYPE(mstatus); > > @@ -421,10 +434,10 @@ static int svc_i3c_master_handle_ibi_won(struct svc_i3c_master *master, u32 msta > switch (ibitype) { > case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN: > case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST: > - svc_i3c_master_nack_ibi(master); > + ret = svc_i3c_master_nack_ibi(master); > } > > - return 0; > + return ret; > } > > static void svc_i3c_master_ibi_work(struct work_struct *work) > @@ -935,7 +948,9 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master, > if (ret) > break; > } else if (SVC_I3C_MSTATUS_IBIWON(reg)) { > - svc_i3c_master_handle_ibi_won(master, reg); > + ret = svc_i3c_master_handle_ibi_won(master, reg); > + if (ret) > + break; > continue; > } else if (SVC_I3C_MSTATUS_MCTRLDONE(reg)) { > if (SVC_I3C_MSTATUS_STATE_IDLE(reg) && > @@ -1209,7 +1224,9 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master, > * start. > */ > if (SVC_I3C_MSTATUS_IBIWON(reg)) { > - svc_i3c_master_handle_ibi_won(master, reg); > + ret = svc_i3c_master_handle_ibi_won(master, reg); > + if (ret) > + goto emit_stop; > continue; > } > > Thanks, Miquèl
diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c index 1ee6ce186195c..3388c9af63fcc 100644 --- a/drivers/i3c/master/svc-i3c-master.c +++ b/drivers/i3c/master/svc-i3c-master.c @@ -388,10 +388,11 @@ static int svc_i3c_master_handle_ibi(struct svc_i3c_master *master, return 0; } -static void svc_i3c_master_ack_ibi(struct svc_i3c_master *master, +static int svc_i3c_master_ack_ibi(struct svc_i3c_master *master, bool mandatory_byte) { unsigned int ibi_ack_nack; + u32 reg; ibi_ack_nack = SVC_I3C_MCTRL_REQUEST_IBI_ACKNACK; if (mandatory_byte) @@ -400,18 +401,30 @@ static void svc_i3c_master_ack_ibi(struct svc_i3c_master *master, ibi_ack_nack |= SVC_I3C_MCTRL_IBIRESP_ACK_WITHOUT_BYTE; writel(ibi_ack_nack, master->regs + SVC_I3C_MCTRL); + + return readl_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS, reg, + SVC_I3C_MSTATUS_MCTRLDONE(reg), 1, 1000); + } -static void svc_i3c_master_nack_ibi(struct svc_i3c_master *master) +static int svc_i3c_master_nack_ibi(struct svc_i3c_master *master) { + int ret; + u32 reg; + writel(SVC_I3C_MCTRL_REQUEST_IBI_ACKNACK | SVC_I3C_MCTRL_IBIRESP_NACK, master->regs + SVC_I3C_MCTRL); + + ret = readl_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS, reg, + SVC_I3C_MSTATUS_MCTRLDONE(reg), 1, 1000); + return ret; } static int svc_i3c_master_handle_ibi_won(struct svc_i3c_master *master, u32 mstatus) { u32 ibitype; + int ret = 0; ibitype = SVC_I3C_MSTATUS_IBITYPE(mstatus); @@ -421,10 +434,10 @@ static int svc_i3c_master_handle_ibi_won(struct svc_i3c_master *master, u32 msta switch (ibitype) { case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN: case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST: - svc_i3c_master_nack_ibi(master); + ret = svc_i3c_master_nack_ibi(master); } - return 0; + return ret; } static void svc_i3c_master_ibi_work(struct work_struct *work) @@ -935,7 +948,9 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master, if (ret) break; } else if (SVC_I3C_MSTATUS_IBIWON(reg)) { - svc_i3c_master_handle_ibi_won(master, reg); + ret = svc_i3c_master_handle_ibi_won(master, reg); + if (ret) + break; continue; } else if (SVC_I3C_MSTATUS_MCTRLDONE(reg)) { if (SVC_I3C_MSTATUS_STATE_IDLE(reg) && @@ -1209,7 +1224,9 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master, * start. */ if (SVC_I3C_MSTATUS_IBIWON(reg)) { - svc_i3c_master_handle_ibi_won(master, reg); + ret = svc_i3c_master_handle_ibi_won(master, reg); + if (ret) + goto emit_stop; continue; }