1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2021-03-18     Carl      the first version
9  */
10 
11 #include "drv_sdctrl.h"
12 #include "ft_sdctrl_hw.h"
13 #include "ft_sdctrl.h"
14 #include "ft_debug.h"
15 #include "ft_types.h"
16 #include "ft_generic_timer.h"
17 #include <drivers/dev_mmcsd_core.h>
18 #include "interrupt.h"
19 #include "rtconfig.h"
20 #include "ft_cache.h"
21 
22 #ifdef BSP_USING_SDC
23 
24 #define LOG_TAG "drv.sdmmc"
25 #include <drv_log.h>
26 
27 #define RTHW_SDCTRL_LOCK(_sdctrl) rt_mutex_take(&_sdctrl->mutex, RT_WAITING_FOREVER)
28 #define RTHW_SDCTRL_UNLOCK(_sdctrl) rt_mutex_release(&_sdctrl->mutex);
29 
30 struct mmcsd_pkg
31 {
32     struct rt_mmcsd_cmd *cmd;
33     void *buff;
34     rt_uint32_t flag;
35 };
36 
37 typedef struct
38 {
39     FtsdCtrl_t ft_sdctrl;
40     struct rt_mmcsd_host *host;
41     struct rt_event event;
42     struct rt_mutex mutex;
43     struct mmcsd_pkg *pkg;
44 } ft_sdctrl_class_t;
45 
46 ft_sdctrl_class_t sdctrl_class;
47 
48 rt_align(SDCTR_ALIGN_LEN)
49 static rt_uint8_t cache_buf[SDCTR_BUFF_SIZE];
50 
51 static void rthw_sdctrl_send_command(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg);
52 
demo_dump_sdc(void)53 static void demo_dump_sdc(void)
54 {
55     Ft_DumpHexWord((const rt_uint32_t *)(0x28207C00), 256);
56 }
57 MSH_CMD_EXPORT_ALIAS(demo_dump_sdc, dump_sdc, output all dump_sdc);
58 
rthw_sdctrl_delay(u32 delayCnt)59 static void rthw_sdctrl_delay(u32 delayCnt)
60 {
61     Ft_GenericTimer_UsDelay(delayCnt);
62 }
63 
rthw_sdctrl_rasp2type(u32 rasp)64 static u32 rthw_sdctrl_rasp2type(u32 rasp)
65 {
66 
67     switch (rasp)
68     {
69     case RESP_NONE:
70         return FTSDCTRL_CMD_RES_NONE;
71     case RESP_R2:
72         return FTSDCTRL_CMD_RES_LONG;
73     default:
74         return FTSDCTRL_CMD_RES_SHORT;
75     }
76 
77     return FTSDCTRL_CMD_RES_SHORT;
78 }
79 
rthw_sdctrl_transfer_by_dma(ft_sdctrl_class_t * class_p,struct mmcsd_pkg * pkg)80 static void rthw_sdctrl_transfer_by_dma(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg)
81 {
82     struct rt_mmcsd_data *data;
83     struct rt_mmcsd_cmd *cmd;
84     u32 rasp;
85     u32 *buff;
86     FtsdCtrl_t *ft_sdctrl_p;
87 
88     if ((RT_NULL == class_p))
89     {
90         LOG_E("rthw_sdctrl_transfer_by_dma invalid class_p");
91         return;
92     }
93     ft_sdctrl_p = &class_p->ft_sdctrl;
94 
95     if ((RT_NULL == pkg))
96     {
97         LOG_E("rthw_sdctrl_transfer_by_dma invalid args");
98         return;
99     }
100 
101     data = pkg->cmd->data;
102     if (RT_NULL == data)
103     {
104         LOG_E("rthw_sdctrl_transfer_by_dma invalid args");
105         return;
106     }
107 
108     buff = pkg->buff;
109     if (RT_NULL == buff)
110     {
111         LOG_E("rthw_sdctrl_transfer_by_dma invalid args");
112         return;
113     }
114 
115     cmd = pkg->cmd;
116     rasp = resp_type(pkg->cmd);
117     rasp = rthw_sdctrl_rasp2type(rasp);
118 
119     if (data->flags & DATA_DIR_WRITE)
120     {
121 #ifdef BSP_SDC_DEBUG_PRINT
122         rt_kprintf("DATA_DIR_WRITE %x \r\n", cmd->arg);
123 #endif
124         FCache_cpuDcacheClean(buff, data->blks * data->blksize);
125 
126         /* data, card, blk:  card : data + blk */
127         FSdCtrl_WriteData(ft_sdctrl_p, (UINTPTR)buff, cmd->arg, data->blks);
128         cmd->err = FSdCtrl_WaitCmdEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, rasp, cmd->resp);
129 
130 #ifdef BSP_SDC_DEBUG_PRINT
131         for (int i = 0; i < 4; i++)
132         {
133             rt_kprintf("cmdRsp[%d] %x \r\n", i, cmd->resp[i]);
134         }
135         Ft_DumpHexWord(buff, 256);
136 #endif
137         FSdCtrl_WaitWriteDataEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, data->blks);
138         FCache_cpuDcacheInvalidate(buff, data->blks * data->blksize);
139     }
140     else if (data->flags & DATA_DIR_READ)
141     {
142 #ifdef BSP_SDC_DEBUG_PRINT
143         rt_kprintf("DATA_DIR_READ %x \r\n", cmd->arg);
144 #endif
145         if ((cmd->flags & CMD_ADTC) && (data->blksize < 512))
146         {
147 #ifdef BSP_SDC_DEBUG_PRINT
148             LOG_E("CMD_ADTC \r\n");
149 #endif
150             FSdCtrl_DoACmd(ft_sdctrl_p, cmd->cmd_code, rasp, cmd->arg);
151             rt_thread_mdelay(10);
152         }
153 
154         FCache_cpuDcacheInvalidate(buff, data->blks * data->blksize);
155         FSdCtrl_ReadData(ft_sdctrl_p, (UINTPTR)buff, cmd->arg, data->blks);
156         cmd->err = FSdCtrl_WaitCmdEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, rasp, cmd->resp);
157 #ifdef BSP_SDC_DEBUG_PRINT
158         for (int i = 0; i < 4; i++)
159         {
160             rt_kprintf("cmdRsp[%d] %x \r\n", i, cmd->resp[i]);
161         }
162 #endif
163         FSdCtrl_WaitReadDataEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, data->blks);
164         FCache_cpuDcacheClean(buff, data->blks * data->blksize);
165 #ifdef BSP_SDC_DEBUG_PRINT
166         Ft_DumpHexWord(buff, data->blks * data->blksize);
167 #endif
168     }
169 }
170 
rthw_sdctrl_docmd(ft_sdctrl_class_t * class_p,struct mmcsd_pkg * pkg)171 static void rthw_sdctrl_docmd(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg)
172 {
173     struct rt_mmcsd_cmd *cmd;
174     u32 rasp;
175     FtsdCtrl_t *ft_sdctrl_p;
176 
177     if ((RT_NULL == class_p))
178     {
179         LOG_E("rthw_sdctrl_docmd invalid class_p");
180         return;
181     }
182 
183     ft_sdctrl_p = &class_p->ft_sdctrl;
184 
185     if ((RT_NULL == pkg))
186     {
187         LOG_E("rthw_sdctrl_docmd invalid args");
188         return;
189     }
190 
191     cmd = pkg->cmd;
192     rasp = resp_type(pkg->cmd);
193     rasp = rthw_sdctrl_rasp2type(rasp);
194     FSdCtrl_DoCmd(ft_sdctrl_p, pkg->cmd->cmd_code, rasp, cmd->arg);
195     cmd->err = FSdCtrl_WaitCmdEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, rasp, cmd->resp);
196 
197 #ifdef BSP_SDC_DEBUG_PRINT
198     for (int i = 0; i < 4; i++)
199     {
200         rt_kprintf("cmdRsp[%d] %x \r\n", i, cmd->resp[i]);
201     }
202 #endif
203 }
204 
rthw_sdctrl_send_command(ft_sdctrl_class_t * class_p,struct mmcsd_pkg * pkg)205 static void rthw_sdctrl_send_command(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg)
206 {
207     struct rt_mmcsd_cmd *cmd = pkg->cmd;
208     struct rt_mmcsd_data *data = cmd->data;
209     /* save pkg */
210     class_p->pkg = pkg;
211 
212     /* config data reg */
213     if (data != RT_NULL && data->blks)
214     {
215         /* transfer config */
216         rthw_sdctrl_transfer_by_dma(class_p, pkg);
217     }
218     else
219     {
220         rthw_sdctrl_docmd(class_p, pkg);
221     }
222 }
223 
224 /**
225   * @brief  This function send sdio request.
226   * @param  host  rt_mmcsd_host
227   * @param  req   request
228   * @retval None
229   */
rthw_sdctrl_request(struct rt_mmcsd_host * host,struct rt_mmcsd_req * req)230 static void rthw_sdctrl_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
231 {
232     struct mmcsd_pkg pkg;
233     ft_sdctrl_class_t *class_p = host->private_data;
234     struct rt_mmcsd_data *data;
235 
236     RTHW_SDCTRL_LOCK(class_p);
237     if (req->cmd != RT_NULL)
238     {
239         rt_memset(&pkg, 0, sizeof(pkg));
240         data = req->cmd->data;
241         pkg.cmd = req->cmd;
242 
243         if (pkg.cmd->cmd_code == 5 || pkg.cmd->cmd_code == 1)
244         {
245             rt_kprintf("cmd_code is not vaild %x \r\n", pkg.cmd->cmd_code);
246             pkg.cmd->err = -RT_EINVAL;
247             goto _exit;
248         }
249 
250 #ifdef BSP_SDC_DEBUG_PRINT
251         struct rt_mmcsd_cmd *cmd;
252         cmd = req->cmd;
253         LOG_E("CMD:%d ARG:0x%08x RES:%s%s%s%s%s%s%s%s%s rw:%c len:%d blksize:%d",
254               cmd->cmd_code,
255               cmd->arg,
256               resp_type(cmd) == RESP_NONE ? "NONE" : "",
257               resp_type(cmd) == RESP_R1 ? "R1" : "",
258               resp_type(cmd) == RESP_R1B ? "R1B" : "",
259               resp_type(cmd) == RESP_R2 ? "R2" : "",
260               resp_type(cmd) == RESP_R3 ? "R3" : "",
261               resp_type(cmd) == RESP_R4 ? "R4" : "",
262               resp_type(cmd) == RESP_R5 ? "R5" : "",
263               resp_type(cmd) == RESP_R6 ? "R6" : "",
264               resp_type(cmd) == RESP_R7 ? "R7" : "",
265               data ? (data->flags & DATA_DIR_WRITE ? 'w' : 'r') : '-',
266               data ? data->blks * data->blksize : 0,
267               data ? data->blksize : 0);
268 #endif
269 
270         if (data != RT_NULL)
271         {
272             rt_uint32_t size = data->blks * data->blksize;
273 
274             RT_ASSERT(size <= SDCTR_BUFF_SIZE);
275             pkg.buff = data->buf;
276             if ((rt_uint32_t)data->buf & (SDCTR_ALIGN_LEN - 1))
277             {
278                 pkg.buff = cache_buf;
279                 if (data->flags & DATA_DIR_WRITE)
280                 {
281                     rt_memcpy(cache_buf, data->buf, size);
282                 }
283             }
284         }
285 
286         rthw_sdctrl_send_command(class_p, &pkg);
287 
288         if ((data != RT_NULL) && (data->flags & DATA_DIR_READ) && ((rt_uint32_t)data->buf & (SDCTR_ALIGN_LEN - 1)))
289         {
290             rt_memcpy(data->buf, cache_buf, data->blksize * data->blks);
291         }
292     }
293 
294     if (req->stop != RT_NULL)
295     {
296         rt_memset(&pkg, 0, sizeof(pkg));
297         pkg.cmd = req->stop;
298         rthw_sdctrl_send_command(class_p, &pkg);
299     }
300 
301 _exit:
302 
303     RTHW_SDCTRL_UNLOCK(class_p);
304     mmcsd_req_complete(class_p->host);
305 }
306 
rthw_sdctrl_clk_divider(struct rt_mmcsd_host * host,struct rt_mmcsd_io_cfg * io_cfg)307 static void rthw_sdctrl_clk_divider(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
308 {
309     ft_sdctrl_class_t *class_p = host->private_data;
310     FtsdCtrl_t *sd_ctrl = &(class_p->ft_sdctrl);
311 
312     /* bus mode is pull push */
313     FSdCtrl_ClkFreqSetup(sd_ctrl, io_cfg->clock);
314     return;
315 }
316 
rthw_sdctrl_iocfg(struct rt_mmcsd_host * host,struct rt_mmcsd_io_cfg * io_cfg)317 static void rthw_sdctrl_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
318 {
319     ft_sdctrl_class_t *class_p = host->private_data;
320     RTHW_SDCTRL_LOCK(class_p);
321 
322     /* calculate and set clk divider */
323     rthw_sdctrl_clk_divider(host, io_cfg);
324 
325     RTHW_SDCTRL_UNLOCK(class_p);
326 }
327 
rthw_sdctrl_detect(struct rt_mmcsd_host * host)328 rt_int32_t rthw_sdctrl_detect(struct rt_mmcsd_host *host)
329 {
330     ft_sdctrl_class_t *class_p = host->private_data;
331 
332     return FSdCtrl_CardDetect(&class_p->ft_sdctrl);
333 }
334 
335 static const struct rt_mmcsd_host_ops ops =
336     {
337         rthw_sdctrl_request,
338         rthw_sdctrl_iocfg,
339         rthw_sdctrl_detect,
340         RT_NULL,
341 };
342 
rthw_sdctrl_nomarl_callback(void * args)343 void rthw_sdctrl_nomarl_callback(void *args)
344 {
345     FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)args;
346     rt_uint32_t status;
347     ft_sdctrl_class_t *class_p;
348     if (RT_NULL == pFtsdCtrl)
349     {
350         return;
351     }
352 
353     class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
354 
355     status = FSdCtrl_GetNormalIrqStatus(pFtsdCtrl);
356 
357     if (status & NORMAL_INT_STATUS_CR)
358     {
359         rt_event_send(&class_p->event, SDCTR_CARD_REMOVE_FLG);
360     }
361     else if (status & NORMAL_INT_STATUS_CC)
362     {
363         rt_event_send(&class_p->event, SDCTR_CMD_IS_COMPLETE_FLG);
364     }
365     else if (status & NORMAL_INT_STATUS_EI)
366     {
367         rt_event_send(&class_p->event, SDCTR_CMD_IS_ERROR_FLG);
368     }
369 
370     return;
371 }
372 
rthw_sdctrl_dma_callback(void * args)373 void rthw_sdctrl_dma_callback(void *args)
374 {
375     FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)args;
376     rt_uint32_t status;
377     ft_sdctrl_class_t *class_p;
378 
379     if (RT_NULL == pFtsdCtrl)
380     {
381         return;
382     }
383 
384     class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
385 
386     status = FSdCtrl_GetDataIrqStatus(pFtsdCtrl);
387 
388     if (status & BD_ISR_REG_TRS)
389     {
390         /* send write complete event */
391         rt_event_send(&class_p->event, SDCTR_WRITE_IS_COMPLETE_FLG);
392     }
393 
394     if (status & BD_ISR_REG_RESPE)
395     {
396         /* send read complete event */
397         rt_event_send(&class_p->event, SDCTR_READ_IS_COMPLETE_FLG);
398     }
399 
400     if (status & BD_ISR_REG_DAIS)
401     {
402         /* send dma errror event */
403         rt_event_send(&class_p->event, SDCTR_DMA_IS_ERROR_FLG);
404     }
405 }
406 
rthw_sdctrl_error_callback(void * args)407 void rthw_sdctrl_error_callback(void *args)
408 {
409     FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)args;
410     rt_uint32_t status;
411     ft_sdctrl_class_t *class_p;
412 
413     if (RT_NULL == pFtsdCtrl)
414     {
415         return;
416     }
417 
418     class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
419 
420     status = FSdCtrl_GetErrorIrqStatus(pFtsdCtrl);
421 
422     if (status & SDCTR_CMD_TIMEOUT_FLG)
423     {
424         rt_event_send(&class_p->event, SDCTR_CMD_TIMEOUT_FLG);
425     }
426 
427     if (status & ERROR_INT_EN_CNR)
428     {
429         rt_event_send(&class_p->event, SDCTR_CMD_RECEIVE_IS_ERROR_FLG);
430     }
431 
432     if (status & ERROR_INT_EN_CCRCE)
433     {
434         rt_event_send(&class_p->event, SDCTR_CMD_CRC_IS_ERROR_FLG);
435     }
436 }
437 
rthw_sdctrl_normal_irq(int vector,void * param)438 void rthw_sdctrl_normal_irq(int vector, void *param)
439 {
440     FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)param;
441     FSdCtrl_NormalIrq(pFtsdCtrl);
442 }
443 
rthw_sdctrl_dma_irq(int vector,void * param)444 void rthw_sdctrl_dma_irq(int vector, void *param)
445 {
446     FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)param;
447     FSdCtrl_DmaIrq(pFtsdCtrl);
448 }
449 
rthw_sdctrl_err_irq(int vector,void * param)450 void rthw_sdctrl_err_irq(int vector, void *param)
451 {
452     FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)param;
453     FSdCtrl_ErrIrq(pFtsdCtrl);
454 }
455 
rthw_sdctrl_cmd_wait(FtsdCtrl_t * pFtsdCtrl)456 ft_error_t rthw_sdctrl_cmd_wait(FtsdCtrl_t *pFtsdCtrl)
457 {
458     rt_uint32_t status;
459     ft_sdctrl_class_t *class_p;
460 
461     if (RT_NULL == pFtsdCtrl)
462     {
463         return FTSDC_INVALID_PARAM;
464     }
465 
466     class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
467 
468     if (rt_event_recv(&class_p->event, SDCTR_CMD_IS_COMPLETE_FLG | SDCTR_CMD_IS_ERROR_FLG | SDCTR_CMD_CRC_IS_ERROR_FLG, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
469                       rt_tick_from_millisecond(50000), &status) != RT_EOK)
470     {
471         /* wait cmd completed timeout */
472         LOG_E("wait cmd completed timeout");
473         return FTSDC_TIMEOUT;
474     }
475 
476     if (SDCTR_CMD_IS_COMPLETE_FLG == (status & SDCTR_CMD_IS_COMPLETE_FLG))
477     {
478         return FTSDC_SUCCESS;
479     }
480     else
481     {
482         LOG_E("wait cmd is error %x ", status);
483         return FTSDC_FAILURE;
484     }
485 }
486 
rthw_sdctrl_read_wait(FtsdCtrl_t * pFtsdCtrl)487 ft_error_t rthw_sdctrl_read_wait(FtsdCtrl_t *pFtsdCtrl)
488 {
489     rt_uint32_t status;
490     ft_sdctrl_class_t *class_p;
491 
492     if (RT_NULL == pFtsdCtrl)
493     {
494         return FTSDC_INVALID_PARAM;
495     }
496 
497     class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
498 
499     if (rt_event_recv(&class_p->event, SDCTR_READ_IS_COMPLETE_FLG | SDCTR_CMD_RECEIVE_IS_ERROR_FLG,
500                       RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
501                       rt_tick_from_millisecond(50000), &status) != RT_EOK)
502     {
503         /* wait read completed timeout */
504         LOG_E("wait read completed timeout");
505         return FTSDC_TIMEOUT;
506     }
507 
508     if (SDCTR_READ_IS_COMPLETE_FLG == (status & SDCTR_READ_IS_COMPLETE_FLG))
509     {
510         return FTSDC_SUCCESS;
511     }
512     else
513     {
514         LOG_E("wait read is error %x ", status);
515         return FTSDC_FAILURE;
516     }
517 }
518 
rthw_sdctrl_write_wait(FtsdCtrl_t * pFtsdCtrl)519 ft_error_t rthw_sdctrl_write_wait(FtsdCtrl_t *pFtsdCtrl)
520 {
521     rt_uint32_t status;
522     ft_sdctrl_class_t *class_p;
523 
524     if (RT_NULL == pFtsdCtrl)
525     {
526         return FTSDC_INVALID_PARAM;
527     }
528 
529     class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
530 
531     if (rt_event_recv(&class_p->event, SDCTR_WRITE_IS_COMPLETE_FLG, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
532                       rt_tick_from_millisecond(50000), &status) != RT_EOK)
533     {
534         /* wait write completed timeout */
535         LOG_E("wait write completed timeout");
536         return FTSDC_TIMEOUT;
537     }
538 
539     if (SDCTR_WRITE_IS_COMPLETE_FLG == (status & SDCTR_WRITE_IS_COMPLETE_FLG))
540     {
541         return FTSDC_SUCCESS;
542     }
543     else
544     {
545         LOG_E("wait write is error %x ", status);
546         return FTSDC_FAILURE;
547     }
548 }
549 
rthw_sdctrl_create(ft_sdctrl_class_t * class_p)550 static rt_err_t rthw_sdctrl_create(ft_sdctrl_class_t *class_p)
551 {
552     struct rt_mmcsd_host *host;
553 
554     host = mmcsd_alloc_host();
555     if (host == RT_NULL)
556     {
557         LOG_E("L:%d F:%s mmcsd alloc host fail");
558         return -RT_ENOMEM;
559     }
560 
561     class_p->ft_sdctrl.config = *(FSdCtrl_Config_t *)FSdCtrl_LookupConfig(0);
562     rt_event_init(&class_p->event, "sdctrl", RT_IPC_FLAG_FIFO);
563     rt_mutex_init(&class_p->mutex, "sdctrl", RT_IPC_FLAG_PRIO);
564 
565     class_p->host = host;
566     host->ops = &ops;
567     /* range of sd work speed */
568     host->freq_min = 400 * 1000;
569     host->freq_max = 48 * 1000000;
570     host->valid_ocr = 0X00FFFF80; /* The voltage range supported is 1.65v-3.6v */
571     host->flags = MMCSD_BUSWIDTH_4;
572     host->private_data = class_p;
573     /* ready to change */
574 
575     return RT_EOK;
576 }
577 
rthw_sdctrl_init(void)578 int rthw_sdctrl_init(void)
579 {
580 
581     FtsdCtrl_t *ft_sdctrl_p;
582 #ifdef BSP_SDC_USE_IRQ
583     FSdCtrl_Config_t *config_p;
584     FSdCtrl_NormalIrqSelect_t normalIrqFlgs = 0;
585 #endif
586 
587     rt_kprintf("rthw_sdctrl_init \r\n");
588     RT_ASSERT(rthw_sdctrl_create(&sdctrl_class) == RT_EOK);
589     ft_sdctrl_p = &sdctrl_class.ft_sdctrl;
590 
591     FSdCtrl_Reset(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay);
592     FsdCtrl_Init(ft_sdctrl_p);
593 
594 #ifdef BSP_SDC_USE_IRQ
595     config_p = &ft_sdctrl_p->config;
596 #ifdef BSP_SDC_IRQ_CARD_REMOVE
597     normalIrqFlgs |= NORMAL_IRQ_CR;
598 
599 #endif
600     normalIrqFlgs |= NORMAL_IRQ_CC;
601     /* register handler irq enable bit and wait callback */
602     FSdCtrl_SetHandler(ft_sdctrl_p, FTSDCTRL_CMDIRQID, rthw_sdctrl_nomarl_callback, ft_sdctrl_p);
603     FSdCtrl_NormalIrqSet(ft_sdctrl_p, normalIrqFlgs);
604     FSdCtrl_CmdWaitRegister(ft_sdctrl_p, rthw_sdctrl_cmd_wait);
605 
606     FSdCtrl_SetHandler(ft_sdctrl_p, FTSDCTRL_DMADATAIRQID, rthw_sdctrl_dma_callback, ft_sdctrl_p);
607     FSdCtrl_BdIrqSet(ft_sdctrl_p, BD_IRQ_TRS | BD_IRQ_RESPE);
608     FSdCtrl_WriteWaitRegister(ft_sdctrl_p, rthw_sdctrl_write_wait);
609     FSdCtrl_ReadWaitRegister(ft_sdctrl_p, rthw_sdctrl_read_wait);
610 
611     config_p->workMode = FTSDCTRL_CMD_IRQ_MASK | FTSDCTRL_DATA_WRITE_IRQ_MASK | FTSDCTRL_DATA_READ_IRQ_MASK;
612 
613 #else
614 
615 #endif
616 
617     /* install normal irq */
618 
619     rt_hw_interrupt_install(ft_sdctrl_p->config.normalIrqNum, rthw_sdctrl_normal_irq,
620                             &sdctrl_class.ft_sdctrl, "normalIrq");
621     rt_hw_interrupt_umask(ft_sdctrl_p->config.normalIrqNum);
622 
623     rt_hw_interrupt_install(ft_sdctrl_p->config.dmaIrqNum, rthw_sdctrl_dma_irq,
624                             &sdctrl_class.ft_sdctrl, "dmaIrq");
625     rt_hw_interrupt_umask(ft_sdctrl_p->config.dmaIrqNum);
626 
627     return 0;
628 }
629 
630 INIT_DEVICE_EXPORT(rthw_sdctrl_init);
631 
ft2004_mmcsd_change(void)632 void ft2004_mmcsd_change(void)
633 {
634     mmcsd_change(sdctrl_class.host);
635 }
636 
ft2004_card_status(void)637 rt_bool_t ft2004_card_status(void)
638 {
639     return FSdCtrl_CardDetect(&sdctrl_class.ft_sdctrl);
640 }
641 
ft2004_card_remove_check(rt_int32_t timeout,rt_uint32_t * status)642 rt_err_t ft2004_card_remove_check(rt_int32_t timeout, rt_uint32_t *status)
643 {
644     return rt_event_recv(&sdctrl_class.event, SDCTR_CARD_REMOVE_FLG, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
645                          timeout, status);
646 }
647 
ft2004_sdctrl_reset(void)648 void ft2004_sdctrl_reset(void)
649 {
650     FSdCtrl_Reset(&sdctrl_class.ft_sdctrl, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay);
651     FsdCtrl_Init(&sdctrl_class.ft_sdctrl);
652 
653 #ifdef BSP_SDC_USE_IRQ
654     FSdCtrl_NormalIrqSet(&sdctrl_class.ft_sdctrl, NORMAL_IRQ_CC | NORMAL_IRQ_CR | NORMAL_IRQ_EI);
655     FSdCtrl_BdIrqSet(&sdctrl_class.ft_sdctrl, BD_IRQ_TRS | BD_IRQ_RESPE);
656 #endif
657 }
658 
659 #endif
660