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