1 #include <string.h>
2 #include <drv/qspi.h>
3 #include <drv/tick.h>
4 #include <drv/irq.h>
5 
6 #define QSPI_DEFAULT_TRANSFER_SIZE   8U
7 
csi_qspi_init(csi_qspi_t * qspi,uint32_t idx)8 csi_error_t csi_qspi_init(csi_qspi_t *qspi, uint32_t idx)
9 {
10     CSI_PARAM_CHK(qspi, CSI_ERROR);
11 
12     csi_error_t ret = CSI_OK;
13 
14     ///< 获取中断号、基地址等相关信息
15     if (target_get(DEV_CD_QSPI_TAG, idx, &qspi->dev) != CSI_OK) {
16         ret = CSI_ERROR;
17     } else {
18         qspi->state.writeable = 1U;
19         qspi->state.readable  = 1U;
20         qspi->state.error     = 0U;
21         qspi->callback        = NULL;
22         qspi->arg             = NULL;
23         qspi->tx_data         = NULL;
24         qspi->rx_data         = NULL;
25         qspi->send            = NULL;
26         qspi->receive         = NULL;
27         qspi->send_receive    = NULL;
28         qspi->tx_dma          = NULL;
29         qspi->rx_dma          = NULL;
30     }
31 
32     return ret;
33 }
34 
csi_qspi_uninit(csi_qspi_t * qspi)35 void csi_qspi_uninit(csi_qspi_t *qspi)
36 {
37     CSI_PARAM_CHK_NORETVAL(qspi);
38 
39     ///< TODO:复位QSPI所有的寄存器
40 
41     ///< 禁止QSPI中断控制器对应的中断,注销QSPI中断服务函数
42     csi_irq_disable((uint32_t)qspi->dev.irq_num);
43     csi_irq_detach((uint32_t)qspi->dev.irq_num);
44 }
45 
csi_qspi_attach_callback(csi_qspi_t * qspi,void * callback,void * arg)46 csi_error_t csi_qspi_attach_callback(csi_qspi_t *qspi, void *callback, void *arg)
47 {
48     CSI_PARAM_CHK(qspi    , CSI_ERROR);
49     CSI_PARAM_CHK(callback, CSI_ERROR);
50 
51     qspi->callback  = callback;
52     qspi->arg       = arg;
53 
54     ///< 注册QSPI中断服务函数,使能QSPI中断控制器对应的中断
55     csi_irq_attach((uint32_t)qspi->dev.irq_num, NULL, &qspi->dev);
56     csi_irq_enable((uint32_t)qspi->dev.irq_num);
57 
58     return CSI_OK;
59 }
60 
csi_qspi_detach_callback(csi_qspi_t * qspi)61 void csi_qspi_detach_callback(csi_qspi_t *qspi)
62 {
63     CSI_PARAM_CHK_NORETVAL(qspi);
64 
65     qspi->callback  = NULL;
66     qspi->arg       = NULL;
67 
68     ///< 禁止QSPI中断控制器对应的中断,注销QSPI中断服务函数
69     csi_irq_disable((uint32_t)qspi->dev.irq_num);
70     csi_irq_detach((uint32_t)qspi->dev.irq_num);
71 }
72 
csi_qspi_frequence(csi_qspi_t * qspi,uint32_t hz)73 uint32_t csi_qspi_frequence(csi_qspi_t *qspi, uint32_t hz)
74 {
75     CSI_PARAM_CHK(qspi, 0U);
76     CSI_PARAM_CHK(hz,   0U);
77 
78     ///< TODO:配置QSPI的频率
79     ///< TODO:获取QSPI的分频到div
80     ///< TODO:根据QSPI的工作频率和div获取QSPI实际使用的频率到hz
81 
82     return hz;
83 }
84 
csi_qspi_mode(csi_qspi_t * qspi,csi_qspi_mode_t mode)85 csi_error_t csi_qspi_mode(csi_qspi_t *qspi, csi_qspi_mode_t mode)
86 {
87     CSI_PARAM_CHK(qspi, CSI_ERROR);
88 
89     csi_error_t ret = CSI_OK;
90 
91     switch (mode) {
92         case QSPI_CLOCK_MODE_0:
93             ///< TODO:配置QSPI时钟的极性和相位
94             break;
95 
96         case QSPI_CLOCK_MODE_1:
97             ///< TODO:配置QSPI时钟的极性和相位
98             break;
99 
100         case QSPI_CLOCK_MODE_2:
101             ///< TODO:配置QSPI时钟的极性和相位
102             break;
103 
104         case QSPI_CLOCK_MODE_3:
105             ///< TODO:配置QSPI时钟的极性和相位
106             break;
107 
108         default:
109             ret = CSI_ERROR;
110             break;
111     }
112 
113     return ret;
114 }
115 
qspi_config_command(csi_qspi_t * qspi,csi_qspi_command_t * cmd)116 void qspi_config_command(csi_qspi_t *qspi, csi_qspi_command_t *cmd)
117 {
118 
119     /* configure instruction */
120     if (cmd->instruction.disabled == (bool)false) {
121         ///< TODO:在QSPI的STIG模式下配置QSPI的命令操作码
122     }
123 
124     /* configure address */
125     if (cmd->address.disabled == (bool)false) {
126         ///< TODO:在QSPI的STIG模式下启用QSPI的命令地址
127         ///< TODO:在QSPI的STIG模式下设置QSPI的命令地址字节的大小
128         ///< TODO:在QSPI的STIG模式下设置QSPI的命令地址
129     }
130 
131     /* configure dummy cycles */
132     if (cmd->dummy_count) {
133         ///< TODO:在QSPI的STIG模式下设置QSPI的周期数
134     }
135 
136     /* configure mode */
137     if (cmd->alt.disabled == (bool)false) {
138         ///< TODO:在QSPI的STIG模式下使能mode bit
139         ///< TODO:在QSPI的STIG模式下配置QSPI的mode bits
140     }
141 
142     /* configure DDR */
143     if (cmd->ddr_enable) {
144         ///< TODO:使能QSPI的DDR位
145     }
146 }
147 
qspi_execute_stig_command(csi_qspi_t * qspi,uint32_t timeout)148 csi_error_t qspi_execute_stig_command(csi_qspi_t *qspi, uint32_t timeout)
149 {
150     CSI_PARAM_CHK(qspi, CSI_ERROR);
151 
152     csi_error_t ret = CSI_OK;
153 
154     ///< TODO:设置QSPI的执行命令
155 
156     ///< TODO:通过while循环等待QSPI进程结束处于空闲状态,超时则超时退出
157 
158     return ret;
159 }
160 
qspi_send(csi_qspi_t * qspi,uint32_t timeout)161 int32_t qspi_send(csi_qspi_t *qspi, uint32_t timeout)
162 {
163     int32_t ret = 0;
164 
165     ret = qspi_execute_stig_command(qspi, timeout);
166 
167     /* return actual send count */
168     if (ret == 0) {
169         ret = (int32_t)qspi->tx_size;
170     }
171 
172     qspi->tx_size = 0U;
173     return ret;
174 }
175 
csi_qspi_send(csi_qspi_t * qspi,csi_qspi_command_t * cmd,const void * data,uint32_t size,uint32_t timeout)176 int32_t csi_qspi_send(csi_qspi_t *qspi, csi_qspi_command_t *cmd, const void *data, uint32_t size, uint32_t timeout)
177 {
178     CSI_PARAM_CHK(qspi, CSI_ERROR);
179     CSI_PARAM_CHK(cmd,  CSI_ERROR);
180     CSI_PARAM_CHK(timeout, CSI_ERROR);
181 
182     int32_t  ret = CSI_OK;
183 
184     do {
185         if ((qspi->state.writeable == 0U) || (qspi->state.readable == 0U)) {
186             ret = CSI_BUSY;
187             break;
188         }
189 
190         ///< TODO:复位控制STIG生成的SPI事务的寄存器
191 
192         qspi_config_command(qspi, cmd);
193 
194         if (size == 0U) {
195 
196             ret = qspi_execute_stig_command(qspi, timeout);
197 
198             ///< TODO:复位控制STIG生成的SPI事务的寄存器
199             break;
200         }
201 
202         qspi->state.writeable = 0U;
203         qspi->tx_data         = (void *)data;
204         qspi->tx_size         = size;
205         ///< TODO:获取QSPI命令的地址
206 
207         /* TODU: transfer use indirect access mode, only support STIG mode */
208         if (qspi->tx_size > QSPI_DEFAULT_TRANSFER_SIZE) {
209             qspi->state.writeable = 1U;
210             ret = CSI_ERROR;
211             break;
212         }
213 
214         /* configure qspi registers */
215         ///< TODO:使能QSPI写数据
216         ///< TODO:配置QSPI写数据字节的大小
217         ///< TODO:配置QSPI命令地址
218         ///< TODO:写数据
219 
220         qspi->state.writeable = 1U;
221         ret = qspi_send(qspi, timeout);
222 
223     } while (0);
224 
225     return ret;
226 }
227 
228 
csi_qspi_receive(csi_qspi_t * qspi,csi_qspi_command_t * cmd,void * data,uint32_t size,uint32_t timeout)229 int32_t csi_qspi_receive(csi_qspi_t *qspi, csi_qspi_command_t *cmd, void *data, uint32_t size, uint32_t timeout)
230 {
231     CSI_PARAM_CHK(qspi, CSI_ERROR);
232     CSI_PARAM_CHK(cmd,  CSI_ERROR);
233     CSI_PARAM_CHK(timeout, CSI_ERROR);
234 
235     uint32_t address;
236     int32_t  ret   = CSI_OK;
237     uint32_t count = 0U;
238     uint32_t current_size = 0U;
239 
240     do {
241         if ((qspi->state.writeable == 0U) || (qspi->state.readable == 0U)) {
242             ret = CSI_BUSY;
243             break;
244         }
245 
246         qspi_config_command(qspi, cmd);
247 
248         if (size == 0U) {
249             ret = qspi_execute_stig_command(qspi, timeout);
250 
251             ///< TODO:复位控制STIG生成的SPI事务的寄存器
252             break;
253         }
254 
255 
256         qspi->rx_data        = data;
257         qspi->rx_size        = size;
258         qspi->state.readable = 0U;
259         ///< TODO:获取QSPI命令的地址到address
260 
261         /* transfer loop */
262         /* TODU: transfer use indirect access mode */
263         while (qspi->rx_size > 0U) {
264             current_size = (qspi->rx_size > QSPI_DEFAULT_TRANSFER_SIZE) ? (uint32_t) QSPI_DEFAULT_TRANSFER_SIZE : qspi->rx_size;
265 
266             /* configure qspi registers */
267             ///< TODO:配置QSPI读数据字节的大小
268             ///< TODO:使能QSPI读数据
269             ///< TODO:配置QSPI命令地址
270             ret = (int32_t)qspi_execute_stig_command(qspi, timeout);
271 
272             if (ret < 0) {
273                 break;
274             }
275 
276             ///< TODO:读数据到qspi->rx_data
277             qspi->rx_data  += current_size;
278             qspi->rx_size  -= current_size;
279             count   += current_size;
280             address +=  current_size;
281         }
282 
283         qspi->state.readable = 1U;
284 
285         ///< TODO:复位控制STIG生成的SPI事务的寄存器
286     } while (0);
287 
288     /* return actual sent count if no error occur */
289     if (ret >= 0) {
290         ret = (int32_t)count;
291     }
292 
293     return ret;
294 }
295 
csi_qspi_send_receive(csi_qspi_t * qspi,csi_qspi_command_t * cmd,const void * tx_data,void * rx_data,uint32_t size,uint32_t timeout)296 int32_t csi_qspi_send_receive(csi_qspi_t *qspi, csi_qspi_command_t *cmd, const void *tx_data, void *rx_data, uint32_t size, uint32_t timeout)
297 {
298     CSI_PARAM_CHK(qspi, CSI_ERROR);
299     CSI_PARAM_CHK(cmd,  CSI_ERROR);
300     CSI_PARAM_CHK(tx_data, CSI_ERROR);
301     CSI_PARAM_CHK(rx_data, CSI_ERROR);
302     CSI_PARAM_CHK(size,    CSI_ERROR);
303     CSI_PARAM_CHK(timeout, CSI_ERROR);
304 
305     return 0;
306 }
307 
csi_qspi_send_async(csi_qspi_t * qspi,csi_qspi_command_t * cmd,const void * data,uint32_t size)308 csi_error_t csi_qspi_send_async(csi_qspi_t *qspi, csi_qspi_command_t *cmd, const void *data, uint32_t size)
309 {
310     CSI_PARAM_CHK(qspi, CSI_ERROR);
311     CSI_PARAM_CHK(cmd,  CSI_ERROR);
312     CSI_PARAM_CHK(data, CSI_ERROR);
313     CSI_PARAM_CHK(size, CSI_ERROR);
314 
315     return CSI_UNSUPPORTED;
316 }
317 
csi_qspi_receive_async(csi_qspi_t * qspi,csi_qspi_command_t * cmd,void * data,uint32_t size)318 csi_error_t csi_qspi_receive_async(csi_qspi_t *qspi, csi_qspi_command_t *cmd, void *data, uint32_t size)
319 {
320     CSI_PARAM_CHK(qspi, CSI_ERROR);
321     CSI_PARAM_CHK(cmd,  CSI_ERROR);
322     CSI_PARAM_CHK(data, CSI_ERROR);
323     CSI_PARAM_CHK(size, CSI_ERROR);
324 
325     return CSI_UNSUPPORTED;
326 }
327 
csi_qspi_send_receive_async(csi_qspi_t * qspi,csi_qspi_command_t * cmd,const void * tx_data,void * rx_data,uint32_t size)328 csi_error_t csi_qspi_send_receive_async(csi_qspi_t *qspi, csi_qspi_command_t *cmd, const void *tx_data, void *rx_data, uint32_t size)
329 {
330     CSI_PARAM_CHK(qspi,    CSI_ERROR);
331     CSI_PARAM_CHK(cmd,     CSI_ERROR);
332     CSI_PARAM_CHK(tx_data, CSI_ERROR);
333     CSI_PARAM_CHK(rx_data, CSI_ERROR);
334     CSI_PARAM_CHK(size,    CSI_ERROR);
335 
336     return CSI_UNSUPPORTED;
337 }
338 
csi_qspi_get_state(csi_qspi_t * qspi,csi_state_t * state)339 csi_error_t csi_qspi_get_state(csi_qspi_t *qspi, csi_state_t *state)
340 {
341     CSI_PARAM_CHK(qspi, CSI_ERROR);
342     CSI_PARAM_CHK(state, CSI_ERROR);
343 
344     *state = qspi->state;
345     return CSI_OK;
346 }
347 
csi_qspi_link_dma(csi_qspi_t * qspi,csi_dma_ch_t * tx_dma,csi_dma_ch_t * rx_dma)348 csi_error_t csi_qspi_link_dma(csi_qspi_t *qspi, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma)
349 {
350     CSI_PARAM_CHK(qspi, CSI_ERROR);
351     CSI_PARAM_CHK(tx_dma, CSI_ERROR);
352     CSI_PARAM_CHK(rx_dma, CSI_ERROR);
353 
354     return CSI_UNSUPPORTED;
355 }
356 
csi_qspi_memory_mapped(csi_qspi_t * qspi,csi_qspi_command_t * cmd)357 csi_error_t csi_qspi_memory_mapped(csi_qspi_t *qspi, csi_qspi_command_t *cmd)
358 {
359     CSI_PARAM_CHK(qspi, CSI_ERROR);
360     CSI_PARAM_CHK(cmd,  CSI_ERROR);
361 
362     ///< TODO:配置读取操作码的宽度
363 
364     ///< TODO:配置指令类型
365 
366     ///< TODO:配置读数据地址的宽度
367     ///< TODO:配置读数据的宽度
368 
369     ///< TODO:配置读数据的周期
370 
371     if (cmd->alt.disabled == (bool)false) {
372         ///< TODO:使能读数据模式
373         ///< TODO:配置QSPI模式字节的大小
374     } else {
375         ///< TODO:禁止读数据模式
376     }
377 
378     if (cmd->ddr_enable) {
379         ///< TODO:使能QSPI的DDR位
380     }
381 
382     return CSI_OK;
383 }
384 
385 #ifdef CONFIG_PM
dw_qspi_pm_action(csi_dev_t * dev,csi_pm_dev_action_t action)386 static csi_error_t dw_qspi_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action)
387 {
388     CSI_PARAM_CHK(dev, CSI_ERROR);
389 
390     csi_error_t ret = CSI_OK;
391     csi_pm_dev_t *pm_dev = &dev->pm_dev;
392 
393     switch (action) {
394         case PM_DEV_SUSPEND:
395             ///< TODO:恢复QSPI寄存器
396             break;
397 
398         case PM_DEV_RESUME:
399             ///< TODO:保存QSPI寄存器
400             break;
401 
402         default:
403             ret = CSI_ERROR;
404             break;
405     }
406 
407     return ret;
408 }
409 
csi_qspi_enable_pm(csi_qspi_t * qspi)410 csi_error_t csi_qspi_enable_pm(csi_qspi_t *qspi)
411 {
412     ///< TODO:注册QSPI低功耗处理函数dw_qspi_pm_action
413 }
414 
csi_qspi_disable_pm(csi_qspi_t * qspi)415 void csi_qspi_disable_pm(csi_qspi_t *qspi)
416 {
417     csi_pm_dev_unregister(&qspi->dev);
418 }
419 #endif
420