4040#define SVC_I3C_MCTRL_REQUEST_NONE 0
4141#define SVC_I3C_MCTRL_REQUEST_START_ADDR 1
4242#define SVC_I3C_MCTRL_REQUEST_STOP 2
43+ #define SVC_I3C_MCTRL_REQUEST_FORCE_EXIT 6
4344#define SVC_I3C_MCTRL_REQUEST_IBI_ACKNACK 3
4445#define SVC_I3C_MCTRL_REQUEST_PROC_DAA 4
4546#define SVC_I3C_MCTRL_REQUEST_AUTO_IBI 7
4647#define SVC_I3C_MCTRL_TYPE_I3C 0
4748#define SVC_I3C_MCTRL_TYPE_I2C BIT(4)
49+ #define SVC_I3C_MCTRL_TYPE_DDR BIT(5)
4850#define SVC_I3C_MCTRL_IBIRESP_AUTO 0
4951#define SVC_I3C_MCTRL_IBIRESP_ACK_WITHOUT_BYTE 0
5052#define SVC_I3C_MCTRL_IBIRESP_ACK_WITH_BYTE BIT(7)
9597#define SVC_I3C_MINTMASKED 0x098
9698#define SVC_I3C_MERRWARN 0x09C
9799#define SVC_I3C_MERRWARN_NACK BIT(2)
100+ #define SVC_I3C_MERRWARN_CRC BIT(10)
98101#define SVC_I3C_MERRWARN_TIMEOUT BIT(20)
99102#define SVC_I3C_MDMACTRL 0x0A0
100103#define SVC_I3C_MDATACTRL 0x0AC
@@ -174,7 +177,7 @@ struct svc_i3c_cmd {
174177 const void * out ;
175178 unsigned int len ;
176179 unsigned int actual_len ;
177- struct i3c_priv_xfer * xfer ;
180+ struct i3c_xfer * xfer ;
178181 bool continued ;
179182};
180183
@@ -389,7 +392,32 @@ svc_i3c_master_dev_from_addr(struct svc_i3c_master *master,
389392
390393static bool svc_cmd_is_read (u32 rnw_cmd , u32 type )
391394{
392- return rnw_cmd ;
395+ return (type == SVC_I3C_MCTRL_TYPE_DDR ) ? (rnw_cmd & 0x80 ) : rnw_cmd ;
396+ }
397+
398+ static void svc_i3c_master_emit_force_exit (struct svc_i3c_master * master )
399+ {
400+ u32 reg ;
401+
402+ writel (SVC_I3C_MCTRL_REQUEST_FORCE_EXIT , master -> regs + SVC_I3C_MCTRL );
403+
404+ /*
405+ * Not need check error here because it is never happen at hardware.
406+ * IP just wait for few fclk cycle to complete DDR exit pattern. Even
407+ * though fclk stop, timeout happen here, the whole data actually
408+ * already finish transfer. The next command will be timeout because
409+ * wrong hardware state.
410+ */
411+ readl_poll_timeout_atomic (master -> regs + SVC_I3C_MSTATUS , reg ,
412+ SVC_I3C_MSTATUS_MCTRLDONE (reg ), 0 , 1000 );
413+
414+ /*
415+ * This delay is necessary after the emission of a stop, otherwise eg.
416+ * repeating IBIs do not get detected. There is a note in the manual
417+ * about it, stating that the stop condition might not be settled
418+ * correctly if a start condition follows too rapidly.
419+ */
420+ udelay (1 );
393421}
394422
395423static void svc_i3c_master_emit_stop (struct svc_i3c_master * master )
@@ -527,7 +555,7 @@ static void svc_i3c_master_ibi_isr(struct svc_i3c_master *master)
527555 * cycle, leading to missed client IBI handlers.
528556 *
529557 * A typical scenario is when IBIWON occurs and bus arbitration is lost
530- * at svc_i3c_master_priv_xfers ().
558+ * at svc_i3c_master_i3c_xfers ().
531559 *
532560 * Clear SVC_I3C_MINT_IBIWON before sending SVC_I3C_MCTRL_REQUEST_AUTO_IBI.
533561 */
@@ -807,6 +835,8 @@ static int svc_i3c_master_bus_init(struct i3c_master_controller *m)
807835
808836 info .dyn_addr = ret ;
809837
838+ info .hdr_cap = I3C_CCC_HDR_MODE (I3C_HDR_DDR );
839+
810840 writel (SVC_MDYNADDR_VALID | SVC_MDYNADDR_ADDR (info .dyn_addr ),
811841 master -> regs + SVC_I3C_MDYNADDR );
812842
@@ -1320,6 +1350,16 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
13201350 /* clean SVC_I3C_MINT_IBIWON w1c bits */
13211351 writel (SVC_I3C_MINT_IBIWON , master -> regs + SVC_I3C_MSTATUS );
13221352
1353+ if (xfer_type == SVC_I3C_MCTRL_TYPE_DDR ) {
1354+ /* DDR command need prefill into FIFO */
1355+ writel (rnw_cmd , master -> regs + SVC_I3C_MWDATAB );
1356+ if (!rnw ) {
1357+ /* write data also need prefill into FIFO */
1358+ ret = svc_i3c_master_write (master , out , xfer_len );
1359+ if (ret )
1360+ goto emit_stop ;
1361+ }
1362+ }
13231363
13241364 while (retry -- ) {
13251365 writel (SVC_I3C_MCTRL_REQUEST_START_ADDR |
@@ -1413,7 +1453,7 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
14131453
14141454 if (rnw )
14151455 ret = svc_i3c_master_read (master , in , xfer_len );
1416- else
1456+ else if ( xfer_type != SVC_I3C_MCTRL_TYPE_DDR )
14171457 ret = svc_i3c_master_write (master , out , xfer_len );
14181458 if (ret < 0 )
14191459 goto emit_stop ;
@@ -1426,10 +1466,19 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
14261466 if (ret )
14271467 goto emit_stop ;
14281468
1469+ if (xfer_type == SVC_I3C_MCTRL_TYPE_DDR &&
1470+ (readl (master -> regs + SVC_I3C_MERRWARN ) & SVC_I3C_MERRWARN_CRC )) {
1471+ ret = - ENXIO ;
1472+ goto emit_stop ;
1473+ }
1474+
14291475 writel (SVC_I3C_MINT_COMPLETE , master -> regs + SVC_I3C_MSTATUS );
14301476
14311477 if (!continued ) {
1432- svc_i3c_master_emit_stop (master );
1478+ if (xfer_type != SVC_I3C_MCTRL_TYPE_DDR )
1479+ svc_i3c_master_emit_stop (master );
1480+ else
1481+ svc_i3c_master_emit_force_exit (master );
14331482
14341483 /* Wait idle if stop is sent. */
14351484 readl_poll_timeout (master -> regs + SVC_I3C_MSTATUS , reg ,
@@ -1439,7 +1488,11 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
14391488 return 0 ;
14401489
14411490emit_stop :
1442- svc_i3c_master_emit_stop (master );
1491+ if (xfer_type != SVC_I3C_MCTRL_TYPE_DDR )
1492+ svc_i3c_master_emit_stop (master );
1493+ else
1494+ svc_i3c_master_emit_force_exit (master );
1495+
14431496 svc_i3c_master_clear_merrwarn (master );
14441497 svc_i3c_master_flush_fifo (master );
14451498
@@ -1486,6 +1539,11 @@ static void svc_i3c_master_dequeue_xfer(struct svc_i3c_master *master,
14861539 spin_unlock_irqrestore (& master -> xferqueue .lock , flags );
14871540}
14881541
1542+ static int i3c_mode_to_svc_type (enum i3c_xfer_mode mode )
1543+ {
1544+ return (mode == I3C_SDR ) ? SVC_I3C_MCTRL_TYPE_I3C : SVC_I3C_MCTRL_TYPE_DDR ;
1545+ }
1546+
14891547static void svc_i3c_master_start_xfer_locked (struct svc_i3c_master * master )
14901548{
14911549 struct svc_i3c_xfer * xfer = master -> xferqueue .cur ;
@@ -1675,29 +1733,41 @@ static int svc_i3c_master_send_ccc_cmd(struct i3c_master_controller *m,
16751733 return ret ;
16761734}
16771735
1678- static int svc_i3c_master_priv_xfers (struct i3c_dev_desc * dev ,
1679- struct i3c_priv_xfer * xfers ,
1680- int nxfers )
1736+ static int svc_i3c_master_i3c_xfers (struct i3c_dev_desc * dev , struct i3c_xfer * xfers ,
1737+ int nxfers , enum i3c_xfer_mode mode )
16811738{
16821739 struct i3c_master_controller * m = i3c_dev_get_master (dev );
16831740 struct svc_i3c_master * master = to_svc_i3c_master (m );
16841741 struct svc_i3c_i2c_dev_data * data = i3c_dev_get_master_data (dev );
16851742 struct svc_i3c_xfer * xfer ;
16861743 int ret , i ;
16871744
1745+ if (mode != I3C_SDR ) {
1746+ /*
1747+ * Only support data size less than FIFO SIZE when using DDR
1748+ * mode. First entry is cmd in FIFO, so actual available FIFO
1749+ * for data is SVC_I3C_FIFO_SIZE - 2 since DDR only supports
1750+ * even length.
1751+ */
1752+ for (i = 0 ; i < nxfers ; i ++ )
1753+ if (xfers [i ].len > SVC_I3C_FIFO_SIZE - 2 )
1754+ return - EINVAL ;
1755+ }
1756+
16881757 xfer = svc_i3c_master_alloc_xfer (master , nxfers );
16891758 if (!xfer )
16901759 return - ENOMEM ;
16911760
1692- xfer -> type = SVC_I3C_MCTRL_TYPE_I3C ;
1761+ xfer -> type = i3c_mode_to_svc_type ( mode ) ;
16931762
16941763 for (i = 0 ; i < nxfers ; i ++ ) {
1764+ u32 rnw_cmd = (mode == I3C_SDR ) ? xfers [i ].rnw : xfers [i ].cmd ;
1765+ bool rnw = svc_cmd_is_read (rnw_cmd , xfer -> type );
16951766 struct svc_i3c_cmd * cmd = & xfer -> cmds [i ];
1696- bool rnw = xfers [i ].rnw ;
16971767
16981768 cmd -> xfer = & xfers [i ];
16991769 cmd -> addr = master -> addrs [data -> index ];
1700- cmd -> rnw = rnw ;
1770+ cmd -> rnw_cmd = rnw_cmd ;
17011771 cmd -> in = rnw ? xfers [i ].data .in : NULL ;
17021772 cmd -> out = rnw ? NULL : xfers [i ].data .out ;
17031773 cmd -> len = xfers [i ].len ;
@@ -1896,7 +1966,7 @@ static const struct i3c_master_controller_ops svc_i3c_master_ops = {
18961966 .do_daa = svc_i3c_master_do_daa ,
18971967 .supports_ccc_cmd = svc_i3c_master_supports_ccc_cmd ,
18981968 .send_ccc_cmd = svc_i3c_master_send_ccc_cmd ,
1899- .priv_xfers = svc_i3c_master_priv_xfers ,
1969+ .i3c_xfers = svc_i3c_master_i3c_xfers ,
19001970 .i2c_xfers = svc_i3c_master_i2c_xfers ,
19011971 .request_ibi = svc_i3c_master_request_ibi ,
19021972 .free_ibi = svc_i3c_master_free_ibi ,
0 commit comments