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