Skip to content

Commit 915d074

Browse files
nxpfranklialexandrebelloni
authored andcommitted
i3c: master: svc: Improve DAA STOP handle code logic
The REQUEST_PROC_DAA command behaves differently from other commands. Sometimes the hardware can auto emit STOP, but in other conditions, it cannot. Improves the code logic to better handle these situations. Hardware can auto emit STOP only when the following conditions are met: - The previous I3C device correctly returns a PID and ACKs an I3C address. - A NACK is received when emitting 7E to try to get the next I3C device's PID. In all other cases, a manual STOP emission is needed. The code is changed to emit STOP when break the while loop and 'return 0' only when the hardware can auto emit STOP. Signed-off-by: Frank Li <[email protected]> Reviewed-by: Miquel Raynal <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexandre Belloni <[email protected]>
1 parent a0d48eb commit 915d074

File tree

1 file changed

+43
-18
lines changed

1 file changed

+43
-18
lines changed

drivers/i3c/master/svc-i3c-master.c

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,20 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
790790
int ret, i;
791791

792792
while (true) {
793-
/* Enter/proceed with DAA */
793+
/* SVC_I3C_MCTRL_REQUEST_PROC_DAA have two mode, ENTER DAA or PROCESS DAA.
794+
*
795+
* ENTER DAA:
796+
* 1 will issue START, 7E, ENTDAA, and then emits 7E/R to process first target.
797+
* 2 Stops just before the new Dynamic Address (DA) is to be emitted.
798+
*
799+
* PROCESS DAA:
800+
* 1 The DA is written using MWDATAB or ADDR bits 6:0.
801+
* 2 ProcessDAA is requested again to write the new address, and then starts the
802+
* next (START, 7E, ENTDAA) unless marked to STOP; an MSTATUS indicating NACK
803+
* means DA was not accepted (e.g. parity error). If PROCESSDAA is NACKed on the
804+
* 7E/R, which means no more Slaves need a DA, then a COMPLETE will be signaled
805+
* (along with DONE), and a STOP issued automatically.
806+
*/
794807
writel(SVC_I3C_MCTRL_REQUEST_PROC_DAA |
795808
SVC_I3C_MCTRL_TYPE_I3C |
796809
SVC_I3C_MCTRL_IBIRESP_NACK |
@@ -807,7 +820,7 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
807820
SVC_I3C_MSTATUS_MCTRLDONE(reg),
808821
1, 1000);
809822
if (ret)
810-
return ret;
823+
break;
811824

812825
if (SVC_I3C_MSTATUS_RXPEND(reg)) {
813826
u8 data[6];
@@ -819,28 +832,39 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
819832
*/
820833
ret = svc_i3c_master_readb(master, data, 6);
821834
if (ret)
822-
return ret;
835+
break;
823836

824837
for (i = 0; i < 6; i++)
825838
prov_id[dev_nb] |= (u64)(data[i]) << (8 * (5 - i));
826839

827840
/* We do not care about the BCR and DCR yet */
828841
ret = svc_i3c_master_readb(master, data, 2);
829842
if (ret)
830-
return ret;
843+
break;
831844
} else if (SVC_I3C_MSTATUS_MCTRLDONE(reg)) {
832845
if (SVC_I3C_MSTATUS_STATE_IDLE(reg) &&
833846
SVC_I3C_MSTATUS_COMPLETE(reg)) {
834847
/*
835848
* All devices received and acked they dynamic
836849
* address, this is the natural end of the DAA
837850
* procedure.
851+
*
852+
* Hardware will auto emit STOP at this case.
838853
*/
839-
break;
854+
*count = dev_nb;
855+
return 0;
856+
840857
} else if (SVC_I3C_MSTATUS_NACKED(reg)) {
841858
/* No I3C devices attached */
842-
if (dev_nb == 0)
859+
if (dev_nb == 0) {
860+
/*
861+
* Hardware can't treat first NACK for ENTAA as normal
862+
* COMPLETE. So need manual emit STOP.
863+
*/
864+
ret = 0;
865+
*count = 0;
843866
break;
867+
}
844868

845869
/*
846870
* A slave device nacked the address, this is
@@ -849,16 +873,18 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
849873
* answer again immediately and shall ack the
850874
* address this time.
851875
*/
852-
if (prov_id[dev_nb] == nacking_prov_id)
853-
return -EIO;
876+
if (prov_id[dev_nb] == nacking_prov_id) {
877+
ret = EIO;
878+
break;
879+
}
854880

855881
dev_nb--;
856882
nacking_prov_id = prov_id[dev_nb];
857883
svc_i3c_master_emit_stop(master);
858884

859885
continue;
860886
} else {
861-
return -EIO;
887+
break;
862888
}
863889
}
864890

@@ -870,12 +896,12 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
870896
SVC_I3C_MSTATUS_BETWEEN(reg),
871897
0, 1000);
872898
if (ret)
873-
return ret;
899+
break;
874900

875901
/* Give the slave device a suitable dynamic address */
876902
ret = i3c_master_get_free_addr(&master->base, last_addr + 1);
877903
if (ret < 0)
878-
return ret;
904+
break;
879905

880906
addrs[dev_nb] = ret;
881907
dev_dbg(master->dev, "DAA: device %d assigned to 0x%02x\n",
@@ -885,9 +911,9 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
885911
last_addr = addrs[dev_nb++];
886912
}
887913

888-
*count = dev_nb;
889-
890-
return 0;
914+
/* Need manual issue STOP except for Complete condition */
915+
svc_i3c_master_emit_stop(master);
916+
return ret;
891917
}
892918

893919
static int svc_i3c_update_ibirules(struct svc_i3c_master *master)
@@ -961,11 +987,10 @@ static int svc_i3c_master_do_daa(struct i3c_master_controller *m)
961987
spin_lock_irqsave(&master->xferqueue.lock, flags);
962988
ret = svc_i3c_master_do_daa_locked(master, addrs, &dev_nb);
963989
spin_unlock_irqrestore(&master->xferqueue.lock, flags);
964-
if (ret) {
965-
svc_i3c_master_emit_stop(master);
966-
svc_i3c_master_clear_merrwarn(master);
990+
991+
svc_i3c_master_clear_merrwarn(master);
992+
if (ret)
967993
goto rpm_out;
968-
}
969994

970995
/* Register all devices who participated to the core */
971996
for (i = 0; i < dev_nb; i++) {

0 commit comments

Comments
 (0)