1 /*
2  * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0.
5  *
6  * @Date: 2021-04-05 22:15:53
7  * @LastEditTime: 2021-05-25 16:45:36
8  * @Description:  Description of file
9  * @Modify History:
10  * * * Ver   Who        Date         Changes
11  * * ----- ------     --------    --------------------------------------
12  * *   1.00   hh        2021.04-06    init
13  */
14 
15 #include "ft_qspi.h"
16 #include "qspi_hw.h"
17 #include "ft_io.h"
18 #include "ft_assert.h"
19 #include "ft_types.h"
20 #include "string.h"
21 
22 #include "ft_debug.h"
23 
24 #define FTQSPI_DEBUG_TAG "FTQSPI"
25 
26 #define FTQSPI_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FTQSPI_DEBUG_TAG, format, ##__VA_ARGS__)
27 #define FTQSPI_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FTQSPI_DEBUG_TAG, format, ##__VA_ARGS__)
28 #define FTQSPI_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FTQSPI_DEBUG_TAG, format, ##__VA_ARGS__)
29 
FQSpi_CfgInitialize(FQSpi_t * pQspi,FQSpi_Config_t * pConfig)30 ft_error_t FQSpi_CfgInitialize(FQSpi_t *pQspi, FQSpi_Config_t *pConfig)
31 {
32     Ft_assertNonvoid(pQspi != NULL);
33     Ft_assertNonvoid(pConfig != NULL);
34 
35     pQspi->config = *pConfig;
36     pQspi->isReady = FT_COMPONENT_IS_READLY;
37 
38     FQSpi_Reset(pQspi);
39 
40     return FQSPI_SUCCESS;
41 }
42 
43 /**
44  * @name: FQSpi_MemcpyToReg
45  * @msg: Memory copy To Register
46  * @in param {FQSpi_t} *pQspi
47  * @in param {u8} *buf
48  * @in param {u32} length
49  * @return {ft_error_t}
50  */
FQSpi_MemcpyToReg(FQSpi_t * pQspi,FT_IN u8 * buf,u32 length)51 static ft_error_t FQSpi_MemcpyToReg(FQSpi_t *pQspi, FT_IN u8 *buf, u32 length)
52 {
53     u32 val = 0;
54     FQSpi_Config_t *pConfig = NULL;
55     Ft_assertNonvoid(pQspi != NULL);
56     Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
57     pConfig = &pQspi->config;
58     if (!buf || (length > 4))
59     {
60         return FQSPI_FAILURE;
61     }
62 
63     if (1 == length)
64     {
65         val = buf[0];
66     }
67     else if (2 == length)
68     {
69         val = buf[1];
70         val = (val << 8) + buf[0];
71     }
72     else if (3 == length)
73     {
74         val = buf[2];
75         val = (val << 8) + buf[1];
76         val = (val << 8) + buf[0];
77     }
78     else if (4 == length)
79     {
80         val = buf[3];
81         val = (val << 8) + buf[2];
82         val = (val << 8) + buf[1];
83         val = (val << 8) + buf[0];
84     }
85 
86     Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, val);
87     return FQSPI_SUCCESS;
88 }
89 
90 /**
91  * @name: FQSpi_MemcpyFromReg
92  * @msg:  Memory copy from Register
93  * @in param {FT_INFQSpi_t} *pQspi
94  * @out param {u8} *buf
95  * @in param {u32} length
96  * @return {*}
97  */
FQSpi_MemcpyFromReg(FQSpi_t * pQspi,u8 * buf,u32 length)98 static ft_error_t FQSpi_MemcpyFromReg(FQSpi_t *pQspi, u8 *buf, u32 length)
99 {
100     s32 i;
101     u32 val = 0;
102     FQSpi_Config_t *pConfig = NULL;
103     Ft_assertNonvoid(pQspi != NULL);
104     Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
105     pConfig = &pQspi->config;
106 
107     for (i = 0; i < length; i++)
108     {
109         /* code */
110         if (0 == i % 4)
111         {
112             val = Ft_in32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET);
113         }
114         buf[i] = (u8)(val >> (i % 4) * 8) & 0xff;
115     }
116 
117     return FQSPI_SUCCESS;
118 }
119 
120 /**
121  * @name: FQSpi_FlashRead
122  * @msg:   Reads bytes data from flash addr to buf
123  * @in param pQspi:
124  * @in param cmd:  Read the instruction byte of the command
125  * @in param addr: Read the data start character
126  * @out param rxBuf: Read buffer
127  * @in param length: need read length
128  * @return {*}
129  */
FQSpi_FlashRead(FQSpi_t * pQspi,FT_IN u8 cmd,FT_IN u32 addr,FT_OUT u8 * rxBuf,u32 length)130 ft_error_t FQSpi_FlashRead(FQSpi_t *pQspi,
131                            FT_IN u8 cmd,
132                            FT_IN u32 addr,
133                            FT_OUT u8 *rxBuf,
134                            u32 length)
135 {
136     FQSpi_Config_t *pConfig = NULL;
137     FQSpi_RdCfgReg_t rdCfgReg;
138     Ft_assertNonvoid(pQspi != NULL);
139     Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
140     pConfig = &pQspi->config;
141 
142     if ((NULL == rxBuf) || (0 == length))
143     {
144         return FQSPI_FAILURE;
145     }
146 
147     rdCfgReg.data = 0;
148 
149     rdCfgReg.val.rdCmd = cmd;
150     rdCfgReg.val.dBuffer = 1;
151     rdCfgReg.val.rdAddrSel = pConfig->addrMode;
152     rdCfgReg.val.rdSckSel = pConfig->clkDiv;
153     rdCfgReg.val.rdTransfer = pConfig->transMode;
154     Ft_out32(pConfig->baseAddress + FT_REG_QSPI_RD_CFG_OFFSET, rdCfgReg.data);
155 
156     memcpy(rxBuf, (char *)(addr), length);
157 
158     return FQSPI_SUCCESS;
159 }
160 
161 /**
162  * @name: FQSpi_FlashWrite
163  * @msg:  Writes one page into flash,changing bits from 1 to 0
164  * @in param pQspi:
165  * @in param cmd:  write the instruction byte of the command
166  * @in param addr: write the data start character
167  * @in param txBuf: write buffer
168  * @in param length: need write length
169  * @return {*}
170  */
FQSpi_FlashWrite(FQSpi_t * pQspi,FT_IN u8 cmd,FT_IN u32 addr,FT_IN u8 * txBuf,u32 length)171 ft_error_t FQSpi_FlashWrite(FQSpi_t *pQspi,
172                             FT_IN u8 cmd,
173                             FT_IN u32 addr,
174                             FT_IN u8 *txBuf,
175                             u32 length)
176 {
177 
178     FQSpi_Config_t *pConfig = NULL;
179     FQSpi_WrCfgReg_t wrCfgReg;
180     u32 index = 0;
181     u32 val = 0;
182     u32 *pu32Buf = NULL;
183     Ft_assertNonvoid(pQspi != NULL);
184     Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
185     pConfig = &pQspi->config;
186 
187     if ((NULL == txBuf) || (0 == length))
188     {
189         return FQSPI_FAILURE;
190     }
191 
192     pu32Buf = (u32 *)txBuf;
193 
194     wrCfgReg.data = 0;
195     wrCfgReg.val.wrCmd = cmd;
196     wrCfgReg.val.wrWait = 1;
197     wrCfgReg.val.wrSckSel = pConfig->clkDiv;
198     wrCfgReg.val.wrAddrsel = pConfig->addrMode;
199     wrCfgReg.val.wrTransfer = pConfig->transMode;
200     wrCfgReg.val.wrMode = 1;
201 
202     Ft_out32(pConfig->baseAddress + FT_REG_QSPI_WR_CFG_OFFSET, wrCfgReg.data);
203 
204     while (length)
205     {
206         if (length >= 4)
207         {
208             Ft_out32(addr + index, pu32Buf[index / 4]);
209             length -= 4;
210             index += 4;
211         }
212         else
213         {
214             if (1 == length)
215             {
216                 val = txBuf[index] | 0xFFFFFF00;
217             }
218             else if (2 == length)
219             {
220                 val = txBuf[index] | (txBuf[index + 1] << 8) | 0xFFFF0000;
221             }
222             else
223             {
224                 val = txBuf[index] | (txBuf[index + 1] << 8) | (txBuf[index + 2] << 8) | 0xFF000000;
225             }
226 
227             Ft_out32(addr + index, val);
228             length = 0;
229         }
230     }
231 
232     Ft_out32(pConfig->baseAddress + FT_REG_QSPI_FLUSH_OFFSET, 1);
233     return FQSPI_SUCCESS;
234 }
235 
236 /**
237  * @name: FQSpi_FlashRegSet
238  * @msg:  Set registers of flash
239  * @in param cmd:  Command byte
240  * @in param writebuf: write buffer
241  * @in param length: need write length
242  * @return {*}
243  */
FQSpi_FlashRegSet(FQSpi_t * pQspi,FT_IN u8 cmd,FT_IN u8 * writebuf,u32 length)244 ft_error_t FQSpi_FlashRegSet(FQSpi_t *pQspi,
245                              FT_IN u8 cmd,
246                              FT_IN u8 *writebuf,
247                              u32 length)
248 {
249     FQSpi_Config_t *pConfig = NULL;
250     FQSpi_CmdPortReg_t cmdPortReg;
251     Ft_assertNonvoid(pQspi != NULL);
252     Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
253     pConfig = &pQspi->config;
254 
255     cmdPortReg.data = 0;
256     cmdPortReg.val.cmd = cmd;
257     cmdPortReg.val.wait = 1;
258     cmdPortReg.val.sckSel = pConfig->clkDiv;
259     cmdPortReg.val.transfer = pConfig->transMode;
260     cmdPortReg.val.cs = pConfig->channel;
261 
262     if (length == 0)
263     {
264         Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
265         Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, 1);
266     }
267     else
268     {
269         cmdPortReg.val.dataTransfer = 1;
270         cmdPortReg.val.rwMum = length;
271         Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
272         FQSpi_MemcpyToReg(pQspi, writebuf, length);
273     }
274 
275     return FQSPI_SUCCESS;
276 }
277 
FQSpi_FlashRegSetWithaddr(FQSpi_t * pQspi,FT_IN u8 cmd,FT_IN u32 addr,FT_IN u8 * writebuf,u32 length)278 ft_error_t FQSpi_FlashRegSetWithaddr(FQSpi_t *pQspi,
279                                      FT_IN u8 cmd,
280                                      FT_IN u32 addr,
281                                      FT_IN u8 *writebuf,
282                                      u32 length)
283 {
284     FQSpi_Config_t *pConfig = NULL;
285     FQSpi_CmdPortReg_t cmdPortReg;
286     Ft_assertNonvoid(pQspi != NULL);
287     Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
288     pConfig = &pQspi->config;
289 
290     cmdPortReg.data = 0;
291     cmdPortReg.val.cmd = cmd;
292     cmdPortReg.val.wait = 1;
293     cmdPortReg.val.sckSel = pConfig->clkDiv;
294     cmdPortReg.val.transfer = pConfig->transMode;
295     cmdPortReg.val.cs = pConfig->channel;
296     cmdPortReg.val.cmdAddr = 1;
297     cmdPortReg.val.addrSel = pConfig->addrMode;
298 
299     Ft_out32(pConfig->baseAddress + FT_REG_QSPI_ADDR_PORT_OFFSET, addr);
300 
301     if (length == 0)
302     {
303         Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
304         Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, 0);
305     }
306     else
307     {
308         cmdPortReg.val.dataTransfer = 1;
309         cmdPortReg.val.rwMum = length;
310         Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
311         FQSpi_MemcpyToReg(pQspi, writebuf, length);
312     }
313 
314     return FQSPI_SUCCESS;
315 }
316 
FQSpi_FlashRegGet(FQSpi_t * pQspi,FT_IN u8 cmd,u8 * readbuf,u32 length)317 ft_error_t FQSpi_FlashRegGet(FQSpi_t *pQspi,
318                              FT_IN u8 cmd,
319                              u8 *readbuf,
320                              u32 length)
321 {
322     FQSpi_Config_t *pConfig = NULL;
323     FQSpi_CmdPortReg_t cmdPortReg;
324     Ft_assertNonvoid(pQspi != NULL);
325     Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
326     pConfig = &pQspi->config;
327 
328     cmdPortReg.data = 0;
329     cmdPortReg.val.cmd = cmd;
330     cmdPortReg.val.wait = 1;
331     cmdPortReg.val.sckSel = pConfig->clkDiv;
332     cmdPortReg.val.transfer = pConfig->transMode;
333     cmdPortReg.val.cs = pConfig->channel;
334     cmdPortReg.val.dataTransfer = 1;
335     cmdPortReg.val.pBuffer = 1;
336 
337     Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
338     FQSpi_MemcpyFromReg(pQspi, readbuf, length);
339     return FQSPI_SUCCESS;
340 }
341 
FQSpi_FlashRegGetWithAddr(FQSpi_t * pQspi,FT_IN u8 cmd,FT_IN u32 addr,FT_IN u32 dummyCycle,u8 * readbuf,u32 length)342 ft_error_t FQSpi_FlashRegGetWithAddr(FQSpi_t *pQspi,
343                                      FT_IN u8 cmd,
344                                      FT_IN u32 addr,
345                                      FT_IN u32 dummyCycle,
346                                      u8 *readbuf,
347                                      u32 length)
348 {
349     FQSpi_Config_t *pConfig = NULL;
350     FQSpi_CmdPortReg_t cmdPortReg;
351     Ft_assertNonvoid(pQspi != NULL);
352     Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
353     pConfig = &pQspi->config;
354 
355     cmdPortReg.data = 0;
356     cmdPortReg.val.cmd = cmd;
357     cmdPortReg.val.wait = 1;
358     cmdPortReg.val.sckSel = pConfig->clkDiv;
359     cmdPortReg.val.transfer = pConfig->transMode;
360     cmdPortReg.val.cs = pConfig->channel;
361     cmdPortReg.val.dataTransfer = 1;
362     cmdPortReg.val.pBuffer = 1;
363     cmdPortReg.val.cmdAddr = 1;
364 
365     cmdPortReg.val.addrSel = pConfig->addrMode;
366     cmdPortReg.val.latency = 1;
367     cmdPortReg.val.dummy = dummyCycle - 1;
368 
369     Ft_out32(pConfig->baseAddress + FT_REG_QSPI_ADDR_PORT_OFFSET, addr);
370     Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
371     FQSpi_MemcpyFromReg(pQspi, readbuf, length);
372     return FQSPI_SUCCESS;
373 }
374 
FQSpi_Write(FQSpi_t * pQspi,struct FQSpi_DataPack * pDataPack)375 ft_error_t FQSpi_Write(FQSpi_t *pQspi, struct FQSpi_DataPack *pDataPack)
376 {
377     FQSpi_Config_t *pConfig = NULL;
378     FQSpi_WrCfgReg_t wrCfgReg;
379     u32 length;
380     u32 index = 0;
381     u32 val = 0;
382     const u32 *pu32Buf = NULL;
383     Ft_assertNonvoid(pQspi != NULL);
384     Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
385     pConfig = &pQspi->config;
386 
387     if ((FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK) == (pDataPack->flags & (FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK)))
388     {
389         FTQSPI_DEBUG_E(" Two addresses are not allowed at the same time ");
390         return FQSPI_FAILURE;
391     }
392 
393     if (0 == (pDataPack->flags & (FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK)))
394     {
395         FTQSPI_DEBUG_E(" There is no address configuration ");
396         return FQSPI_FAILURE;
397     }
398 
399     if (NULL == pDataPack->txBuf)
400     {
401         FTQSPI_DEBUG_E("pDataPack->txBuf is null");
402         return FQSPI_FAILURE;
403     }
404 
405     pu32Buf = (const u32 *)pDataPack->txBuf;
406     wrCfgReg.data = 0;
407 
408     if (FQSPI_DATA_ADDRESS_3BYTE_MASK == (pDataPack->flags & FQSPI_DATA_ADDRESS_3BYTE_MASK))
409     {
410         wrCfgReg.val.wrAddrsel = FT_QSPI_ADDR_SEL_3;
411     }
412     else if (FQSPI_DATA_ADDRESS_4BYTE_MASK == (pDataPack->flags & FQSPI_DATA_ADDRESS_4BYTE_MASK))
413     {
414         wrCfgReg.val.wrAddrsel = FT_QSPI_ADDR_SEL_4;
415     }
416 
417     wrCfgReg.val.wrCmd = pDataPack->cmd;
418     wrCfgReg.val.wrWait = 1;
419     wrCfgReg.val.wrSckSel = pConfig->clkDiv;
420     wrCfgReg.val.wrTransfer = pConfig->transMode;
421     wrCfgReg.val.wrMode = 1;
422     length = pDataPack->length;
423 
424     Ft_out32(pConfig->baseAddress + FT_REG_QSPI_WR_CFG_OFFSET, wrCfgReg.data);
425 
426     while (length)
427     {
428         if (length >= 4)
429         {
430             Ft_out32(pDataPack->addr + index, pu32Buf[index / 4]);
431             length -= 4;
432             index += 4;
433         }
434         else
435         {
436             if (1 == length)
437             {
438                 val = pDataPack->txBuf[index] | 0xFFFFFF00;
439             }
440             else if (2 == length)
441             {
442                 val = pDataPack->txBuf[index] | (pDataPack->txBuf[index + 1] << 8) | 0xFFFF0000;
443             }
444             else
445             {
446                 val = pDataPack->txBuf[index] | (pDataPack->txBuf[index + 1] << 8) | (pDataPack->txBuf[index + 2] << 8) | 0xFF000000;
447             }
448             FTQSPI_DEBUG_I("val is 0x%x", val);
449             Ft_out32(pDataPack->addr + index, val);
450             length = 0;
451         }
452     }
453 
454     Ft_out32(pConfig->baseAddress + FT_REG_QSPI_FLUSH_OFFSET, 1);
455     return FQSPI_SUCCESS;
456 }
457 
FQSpi_Read(FQSpi_t * pQspi,struct FQSpi_DataPack * pDataPack)458 ft_error_t FQSpi_Read(FQSpi_t *pQspi, struct FQSpi_DataPack *pDataPack)
459 {
460     FQSpi_Config_t *pConfig = NULL;
461     FQSpi_RdCfgReg_t rdCfgReg;
462     Ft_assertNonvoid(pQspi != NULL);
463     Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
464     pConfig = &pQspi->config;
465 
466     if ((FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK) == (pDataPack->flags & (FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK)))
467     {
468         FTQSPI_DEBUG_E(" Two addresses are not allowed at the same time ");
469         return FQSPI_FAILURE;
470     }
471 
472     if (0 == (pDataPack->flags & (FQSPI_DATA_ADDRESS_3BYTE_MASK | FQSPI_DATA_ADDRESS_4BYTE_MASK)))
473     {
474         FTQSPI_DEBUG_E(" There is no address configuration ");
475         return FQSPI_FAILURE;
476     }
477 
478     if (NULL == pDataPack->rxBuf)
479     {
480         FTQSPI_DEBUG_E("pDataPack->rxBuf is null");
481         return FQSPI_FAILURE;
482     }
483 
484     rdCfgReg.data = 0;
485 
486     if (FQSPI_DATA_NEED_DUMMY_MASK == (pDataPack->flags & FQSPI_DATA_NEED_DUMMY_MASK))
487     {
488         rdCfgReg.val.rdLatency = 1;
489         rdCfgReg.val.dummy = pDataPack->dummyCycle - 1;
490     }
491 
492     if (FQSPI_DATA_ADDRESS_3BYTE_MASK == (pDataPack->flags & FQSPI_DATA_ADDRESS_3BYTE_MASK))
493     {
494         rdCfgReg.val.rdAddrSel = FT_QSPI_ADDR_SEL_3;
495     }
496     else if (FQSPI_DATA_ADDRESS_4BYTE_MASK == (pDataPack->flags & FQSPI_DATA_ADDRESS_4BYTE_MASK))
497     {
498         rdCfgReg.val.rdAddrSel = FT_QSPI_ADDR_SEL_4;
499     }
500 
501     rdCfgReg.val.rdCmd = pDataPack->cmd;
502     rdCfgReg.val.dBuffer = 1;
503     rdCfgReg.val.rdSckSel = pConfig->clkDiv;
504     rdCfgReg.val.rdTransfer = pConfig->transMode;
505 
506     Ft_out32(pConfig->baseAddress + FT_REG_QSPI_RD_CFG_OFFSET, rdCfgReg.data);
507 
508     memcpy(pDataPack->rxBuf, (char *)(pDataPack->addr), pDataPack->length);
509 
510     return FQSPI_SUCCESS;
511 }
512 
513 ft_error_t
FQSpi_CmdOperation(FQSpi_t * pQspi,struct FQSpi_CmdPack * pCmdPack)514 FQSpi_CmdOperation(FQSpi_t *pQspi, struct FQSpi_CmdPack *pCmdPack)
515 {
516     FQSpi_Config_t *pConfig = NULL;
517     FQSpi_CmdPortReg_t cmdPortReg;
518     Ft_assertNonvoid(pQspi != NULL);
519     Ft_assertNonvoid(pQspi->isReady == FT_COMPONENT_IS_READLY);
520     pConfig = &pQspi->config;
521     if ((FQSPI_CMD_ADDRESS_3BYTE_MASK | FQSPI_CMD_ADDRESS_4BYTE_MASK) == (pCmdPack->flags & (FQSPI_CMD_ADDRESS_3BYTE_MASK | FQSPI_CMD_ADDRESS_4BYTE_MASK)))
522     {
523         FTQSPI_DEBUG_E(" Two addresses are not allowed at the same time ");
524         return FQSPI_FAILURE;
525     }
526 
527     cmdPortReg.data = 0;
528     cmdPortReg.val.cmd = pCmdPack->cmd;
529     cmdPortReg.val.wait = 1;
530     cmdPortReg.val.sckSel = pConfig->clkDiv;
531     cmdPortReg.val.transfer = pConfig->transMode;
532     cmdPortReg.val.cs = pConfig->channel;
533 
534     if (FQSPI_CMD_NEED_ADDR_MASK == (pCmdPack->flags & FQSPI_CMD_NEED_ADDR_MASK))
535     {
536         // FTQSPI_DEBUG_I(" send addr is 0x%x ", pCmdPack->addr);
537         cmdPortReg.val.cmdAddr = 1;
538         Ft_out32(pConfig->baseAddress + FT_REG_QSPI_ADDR_PORT_OFFSET, pCmdPack->addr);
539     }
540 
541     if (FQSPI_CMD_NEED_DUMMY_MASK == (pCmdPack->flags & FQSPI_CMD_NEED_DUMMY_MASK))
542     {
543         cmdPortReg.val.latency = 1;
544         cmdPortReg.val.dummy = pCmdPack->dummyCycle - 1;
545     }
546 
547     if (FQSPI_CMD_ADDRESS_3BYTE_MASK == (pCmdPack->flags & FQSPI_CMD_ADDRESS_3BYTE_MASK))
548     {
549         cmdPortReg.val.addrSel = FT_QSPI_ADDR_SEL_3;
550     }
551     else if (FQSPI_CMD_ADDRESS_4BYTE_MASK == (pCmdPack->flags & FQSPI_CMD_ADDRESS_4BYTE_MASK))
552     {
553         cmdPortReg.val.addrSel = FT_QSPI_ADDR_SEL_4;
554     }
555 
556     if (FQSPI_CMD_NEED_SET_MASK == (pCmdPack->flags & (FQSPI_CMD_NEED_SET_MASK)))
557     {
558         cmdPortReg.val.dataTransfer = 1;
559         cmdPortReg.val.rwMum = pCmdPack->length;
560         Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
561         FQSpi_MemcpyToReg(pQspi, pCmdPack->txBuf, pCmdPack->length);
562     }
563     else if (FQSPI_CMD_NEED_GET_MASK == (pCmdPack->flags & (FQSPI_CMD_NEED_GET_MASK)))
564     {
565         cmdPortReg.val.dataTransfer = 1;
566         cmdPortReg.val.pBuffer = 1;
567         Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
568         FQSpi_MemcpyFromReg(pQspi, pCmdPack->rxBuf, pCmdPack->length);
569     }
570     else
571     {
572         Ft_out32(pConfig->baseAddress + FT_REG_QSPI_CMD_PORT_OFFSET, cmdPortReg.data);
573 
574         if (FQSPI_CMD_NEED_ADDR_MASK == (pCmdPack->flags & FQSPI_CMD_NEED_ADDR_MASK))
575         {
576             Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, 0);
577         }
578         else
579         {
580             Ft_out32(pConfig->baseAddress + FT_REG_QSPI_LD_PORT_OFFSET, 1);
581         }
582     }
583 
584     return FQSPI_SUCCESS;
585 }
586