@@ -896,27 +896,35 @@ static int svc_i3c_master_do_daa(struct i3c_master_controller *m)
896
896
static int svc_i3c_master_read (struct svc_i3c_master * master ,
897
897
u8 * in , unsigned int len )
898
898
{
899
- int offset = 0 , i , ret ;
900
- u32 mdctrl ;
899
+ int offset = 0 , i ;
900
+ u32 mdctrl , mstatus ;
901
+ bool completed = false;
902
+ unsigned int count ;
903
+ unsigned long start = jiffies ;
901
904
902
- while (offset < len ) {
903
- unsigned int count ;
905
+ while (!completed ) {
906
+ mstatus = readl (master -> regs + SVC_I3C_MSTATUS );
907
+ if (SVC_I3C_MSTATUS_COMPLETE (mstatus ) != 0 )
908
+ completed = true;
904
909
905
- ret = readl_poll_timeout (master -> regs + SVC_I3C_MDATACTRL ,
906
- mdctrl ,
907
- !(mdctrl & SVC_I3C_MDATACTRL_RXEMPTY ),
908
- 0 , 1000 );
909
- if (ret )
910
- return ret ;
910
+ if (time_after (jiffies , start + msecs_to_jiffies (1000 ))) {
911
+ dev_dbg (master -> dev , "I3C read timeout\n" );
912
+ return - ETIMEDOUT ;
913
+ }
911
914
915
+ mdctrl = readl (master -> regs + SVC_I3C_MDATACTRL );
912
916
count = SVC_I3C_MDATACTRL_RXCOUNT (mdctrl );
917
+ if (offset + count > len ) {
918
+ dev_err (master -> dev , "I3C receive length too long!\n" );
919
+ return - EINVAL ;
920
+ }
913
921
for (i = 0 ; i < count ; i ++ )
914
922
in [offset + i ] = readl (master -> regs + SVC_I3C_MRDATAB );
915
923
916
924
offset += count ;
917
925
}
918
926
919
- return 0 ;
927
+ return offset ;
920
928
}
921
929
922
930
static int svc_i3c_master_write (struct svc_i3c_master * master ,
@@ -949,7 +957,7 @@ static int svc_i3c_master_write(struct svc_i3c_master *master,
949
957
static int svc_i3c_master_xfer (struct svc_i3c_master * master ,
950
958
bool rnw , unsigned int xfer_type , u8 addr ,
951
959
u8 * in , const u8 * out , unsigned int xfer_len ,
952
- unsigned int read_len , bool continued )
960
+ unsigned int * read_len , bool continued )
953
961
{
954
962
u32 reg ;
955
963
int ret ;
@@ -959,7 +967,7 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
959
967
SVC_I3C_MCTRL_IBIRESP_NACK |
960
968
SVC_I3C_MCTRL_DIR (rnw ) |
961
969
SVC_I3C_MCTRL_ADDR (addr ) |
962
- SVC_I3C_MCTRL_RDTERM (read_len ),
970
+ SVC_I3C_MCTRL_RDTERM (* read_len ),
963
971
master -> regs + SVC_I3C_MCTRL );
964
972
965
973
ret = readl_poll_timeout (master -> regs + SVC_I3C_MSTATUS , reg ,
@@ -971,17 +979,27 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
971
979
ret = svc_i3c_master_read (master , in , xfer_len );
972
980
else
973
981
ret = svc_i3c_master_write (master , out , xfer_len );
974
- if (ret )
982
+ if (ret < 0 )
975
983
goto emit_stop ;
976
984
985
+ if (rnw )
986
+ * read_len = ret ;
987
+
977
988
ret = readl_poll_timeout (master -> regs + SVC_I3C_MSTATUS , reg ,
978
989
SVC_I3C_MSTATUS_COMPLETE (reg ), 0 , 1000 );
979
990
if (ret )
980
991
goto emit_stop ;
981
992
982
- if (!continued )
993
+ writel (SVC_I3C_MINT_COMPLETE , master -> regs + SVC_I3C_MSTATUS );
994
+
995
+ if (!continued ) {
983
996
svc_i3c_master_emit_stop (master );
984
997
998
+ /* Wait idle if stop is sent. */
999
+ readl_poll_timeout (master -> regs + SVC_I3C_MSTATUS , reg ,
1000
+ SVC_I3C_MSTATUS_STATE_IDLE (reg ), 0 , 1000 );
1001
+ }
1002
+
985
1003
return 0 ;
986
1004
987
1005
emit_stop :
@@ -1039,12 +1057,15 @@ static void svc_i3c_master_start_xfer_locked(struct svc_i3c_master *master)
1039
1057
if (!xfer )
1040
1058
return ;
1041
1059
1060
+ svc_i3c_master_clear_merrwarn (master );
1061
+ svc_i3c_master_flush_fifo (master );
1062
+
1042
1063
for (i = 0 ; i < xfer -> ncmds ; i ++ ) {
1043
1064
struct svc_i3c_cmd * cmd = & xfer -> cmds [i ];
1044
1065
1045
1066
ret = svc_i3c_master_xfer (master , cmd -> rnw , xfer -> type ,
1046
1067
cmd -> addr , cmd -> in , cmd -> out ,
1047
- cmd -> len , cmd -> read_len ,
1068
+ cmd -> len , & cmd -> read_len ,
1048
1069
cmd -> continued );
1049
1070
if (ret )
1050
1071
break ;
@@ -1173,6 +1194,9 @@ static int svc_i3c_master_send_direct_ccc_cmd(struct svc_i3c_master *master,
1173
1194
if (!wait_for_completion_timeout (& xfer -> comp , msecs_to_jiffies (1000 )))
1174
1195
svc_i3c_master_dequeue_xfer (master , xfer );
1175
1196
1197
+ if (cmd -> read_len != xfer_len )
1198
+ ccc -> dests [0 ].payload .len = cmd -> read_len ;
1199
+
1176
1200
ret = xfer -> ret ;
1177
1201
svc_i3c_master_free_xfer (xfer );
1178
1202
0 commit comments