1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2020-05-23     liuduanfei   first version
9  * 2022-03-16     Miaowulue    change prompt message
10  */
11 
12 #include "board.h"
13 #include "drv_sdio.h"
14 #include <dfs_fs.h>
15 
16 #ifdef BSP_USING_SDMMC
17 
18 #define DBG_TAG              "drv.sdio"
19 #ifdef DRV_DEBUG
20 #define DBG_LVL               DBG_LOG
21 #else
22 #define DBG_LVL               DBG_INFO
23 #endif /* DRV_DEBUG */
24 #include <rtdbg.h>
25 
26 static struct rt_mmcsd_host *host;
27 #define SDIO_TX_RX_COMPLETE_TIMEOUT_LOOPS    (100000)
28 
29 struct sdio_pkg
30 {
31     struct rt_mmcsd_cmd *cmd;
32     void *buff;
33     rt_uint32_t flag;
34 };
35 
36 struct rthw_sdio
37 {
38     struct rt_mmcsd_host *host;
39     struct stm32_sdio_des sdio_des;
40     struct rt_event event;
41     struct sdio_pkg *pkg;
42 };
43 
rt_align(SDIO_ALIGN_LEN)44 rt_align(SDIO_ALIGN_LEN)
45 static rt_uint8_t cache_buf[SDIO_BUFF_SIZE];
46 
47 /**
48   * @brief  This function get order from sdio.
49   * @param  data
50   * @retval sdio order
51   */
52 static int get_order(rt_uint32_t data)
53 {
54     int order = 0;
55 
56     switch (data)
57     {
58     case 1:
59         order = 0;
60         break;
61     case 2:
62         order = 1;
63         break;
64     case 4:
65         order = 2;
66         break;
67     case 8:
68         order = 3;
69         break;
70     case 16:
71         order = 4;
72         break;
73     case 32:
74         order = 5;
75         break;
76     case 64:
77         order = 6;
78         break;
79     case 128:
80         order = 7;
81         break;
82     case 256:
83         order = 8;
84         break;
85     case 512:
86         order = 9;
87         break;
88     case 1024:
89         order = 10;
90         break;
91     case 2048:
92         order = 11;
93         break;
94     case 4096:
95         order = 12;
96         break;
97     case 8192:
98         order = 13;
99         break;
100     case 16384:
101         order = 14;
102         break;
103     default :
104         order = 0;
105         break;
106     }
107     return order;
108 }
109 
110 /**
111   * @brief  This function wait sdio cmd completed.
112   * @param  sdio rthw_sdio
113   * @retval None
114   */
rthw_sdio_wait_completed(struct rthw_sdio * sdio)115 static void rthw_sdio_wait_completed(struct rthw_sdio *sdio)
116 {
117     rt_uint32_t status;
118     struct rt_mmcsd_cmd *cmd = sdio->pkg->cmd;
119     struct stm32_sdio *hw_sdio = sdio->sdio_des.hw_sdio;
120 
121     if (rt_event_recv(&sdio->event, 0xffffffff, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
122                       rt_tick_from_millisecond(5000), &status) != RT_EOK)
123     {
124         LOG_E("wait cmd completed timeout");
125         cmd->err = -RT_ETIMEOUT;
126         return;
127     }
128 
129     cmd->resp[0] = hw_sdio->resp1;
130     if (resp_type(cmd) == RESP_R2)
131     {
132         cmd->resp[1] = hw_sdio->resp2;
133         cmd->resp[2] = hw_sdio->resp3;
134         cmd->resp[3] = hw_sdio->resp4;
135     }
136 
137     if (status & SDIO_ERRORS)
138     {
139         if ((status & SDMMC_STA_CCRCFAIL) && (resp_type(cmd) & (RESP_R3 | RESP_R4)))
140         {
141             cmd->err = RT_EOK;
142         }
143         else
144         {
145             cmd->err = -RT_ERROR;
146         }
147     }
148 
149     if (cmd->err == RT_EOK)
150     {
151         LOG_D("sta:0x%08X [%08X %08X %08X %08X]", status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
152     }
153     else
154     {
155         LOG_D("send command error = %d", cmd->err);
156     }
157 }
158 
159 /**
160   * @brief  This function send command.
161   * @param  sdio rthw_sdio
162   * @param  pkg  sdio package
163   * @retval None
164   */
rthw_sdio_send_command(struct rthw_sdio * sdio,struct sdio_pkg * pkg)165 static void rthw_sdio_send_command(struct rthw_sdio *sdio, struct sdio_pkg *pkg)
166 {
167     struct rt_mmcsd_cmd *cmd = pkg->cmd;
168     struct rt_mmcsd_data *data = cmd->data;
169     struct stm32_sdio *hw_sdio = sdio->sdio_des.hw_sdio;
170     rt_uint32_t reg_cmd;
171 
172     /* save pkg */
173     sdio->pkg = pkg;
174 
175     LOG_D("CMD:%d ARG:0x%08x RES:%s%s%s%s%s%s%s%s%s rw:%c len:%d blksize:%d\n",
176           cmd->cmd_code,
177           cmd->arg,
178           resp_type(cmd) == RESP_NONE ? "NONE"  : "",
179           resp_type(cmd) == RESP_R1  ? "R1"  : "",
180           resp_type(cmd) == RESP_R1B ? "R1B"  : "",
181           resp_type(cmd) == RESP_R2  ? "R2"  : "",
182           resp_type(cmd) == RESP_R3  ? "R3"  : "",
183           resp_type(cmd) == RESP_R4  ? "R4"  : "",
184           resp_type(cmd) == RESP_R5  ? "R5"  : "",
185           resp_type(cmd) == RESP_R6  ? "R6"  : "",
186           resp_type(cmd) == RESP_R7  ? "R7"  : "",
187           data ? (data->flags & DATA_DIR_WRITE ?  'w' : 'r') : '-',
188           data ? data->blks * data->blksize : 0,
189           data ? data->blksize : 0
190          );
191 
192     hw_sdio->mask |= SDIO_MASKR_ALL;
193     reg_cmd = cmd->cmd_code | SDMMC_CMD_CPSMEN;
194 
195     /* data pre configuration */
196     if (data != RT_NULL)
197     {
198         SCB_CleanInvalidateDCache();
199 
200         reg_cmd |= SDMMC_CMD_CMDTRANS;
201         hw_sdio->mask &= ~(SDMMC_MASK_CMDRENDIE | SDMMC_MASK_CMDSENTIE);
202         hw_sdio->dtimer = HW_SDIO_DATATIMEOUT;
203         hw_sdio->dlen = data->blks * data->blksize;
204         hw_sdio->dctrl = (get_order(data->blksize)<<4) | (data->flags & DATA_DIR_READ ? SDMMC_DCTRL_DTDIR : 0);
205         hw_sdio->idmabase0r = (rt_uint32_t)cache_buf;
206         hw_sdio->idmatrlr = SDMMC_IDMA_IDMAEN;
207     }
208 
209     if (resp_type(cmd) == RESP_R2)
210         reg_cmd |= SDMMC_CMD_WAITRESP;
211     else if(resp_type(cmd) != RESP_NONE)
212         reg_cmd |= SDMMC_CMD_WAITRESP_0;
213 
214     hw_sdio->arg = cmd->arg;
215     hw_sdio->cmd = reg_cmd;
216     /* wait completed */
217     rthw_sdio_wait_completed(sdio);
218 
219     /* Waiting for data to be sent to completion */
220     if (data != RT_NULL)
221     {
222         volatile rt_uint32_t count = SDIO_TX_RX_COMPLETE_TIMEOUT_LOOPS;
223 
224         while (count && (hw_sdio->sta & SDMMC_STA_DPSMACT))
225         {
226             count--;
227         }
228         if ((count == 0) || (hw_sdio->sta & SDIO_ERRORS))
229         {
230             cmd->err = -RT_ERROR;
231         }
232     }
233 
234     /* data post configuration */
235     if (data != RT_NULL)
236     {
237         if (data->flags & DATA_DIR_READ)
238         {
239             rt_memcpy(data->buf, cache_buf, data->blks * data->blksize);
240             SCB_CleanInvalidateDCache();
241         }
242     }
243 }
244 
245 /**
246   * @brief  This function send sdio request.
247   * @param  sdio  rthw_sdio
248   * @param  req   request
249   * @retval None
250   */
rthw_sdio_request(struct rt_mmcsd_host * host,struct rt_mmcsd_req * req)251 static void rthw_sdio_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
252 {
253     struct sdio_pkg pkg;
254     struct rthw_sdio *sdio = host->private_data;
255     struct rt_mmcsd_data *data;
256 
257     if (req->cmd != RT_NULL)
258     {
259         rt_memset(&pkg, 0, sizeof(pkg));
260         data = req->cmd->data;
261         pkg.cmd = req->cmd;
262 
263         if (data != RT_NULL)
264         {
265             rt_uint32_t size = data->blks * data->blksize;
266 
267             RT_ASSERT(size <= SDIO_BUFF_SIZE);
268 
269             if (data->flags & DATA_DIR_WRITE)
270             {
271                 rt_memcpy(cache_buf, data->buf, size);
272             }
273         }
274 
275         rthw_sdio_send_command(sdio, &pkg);
276     }
277 
278     if (req->stop != RT_NULL)
279     {
280         rt_memset(&pkg, 0, sizeof(pkg));
281         pkg.cmd = req->stop;
282         rthw_sdio_send_command(sdio, &pkg);
283     }
284 
285     mmcsd_req_complete(sdio->host);
286 }
287 
288 
289 /**
290   * @brief  This function interrupt process function.
291   * @param  host  rt_mmcsd_host
292   * @retval None
293   */
rthw_sdio_irq_process(struct rt_mmcsd_host * host)294 void rthw_sdio_irq_process(struct rt_mmcsd_host *host)
295 {
296     struct rthw_sdio *sdio = host->private_data;
297     struct stm32_sdio *hw_sdio = sdio->sdio_des.hw_sdio;
298     rt_uint32_t intstatus = hw_sdio->sta;
299 
300     /* clear irq flag*/
301     hw_sdio->icr = intstatus;
302 
303     rt_event_send(&sdio->event, intstatus);
304 }
305 
306 /**
307   * @brief  This function config sdio.
308   * @param  host    rt_mmcsd_host
309   * @param  io_cfg  rt_mmcsd_io_cfg
310   * @retval None
311   */
rthw_sdio_iocfg(struct rt_mmcsd_host * host,struct rt_mmcsd_io_cfg * io_cfg)312 static void rthw_sdio_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
313 {
314     rt_uint32_t temp, clk_src;
315     rt_uint32_t clk = io_cfg->clock;
316     struct rthw_sdio *sdio = host->private_data;
317     struct stm32_sdio *hw_sdio = sdio->sdio_des.hw_sdio;
318 
319     LOG_D("clk:%dK width:%s%s%s power:%s%s%s",
320           clk/1000,
321           io_cfg->bus_width == MMCSD_BUS_WIDTH_8 ? "8" : "",
322           io_cfg->bus_width == MMCSD_BUS_WIDTH_4 ? "4" : "",
323           io_cfg->bus_width == MMCSD_BUS_WIDTH_1 ? "1" : "",
324           io_cfg->power_mode == MMCSD_POWER_OFF ? "OFF" : "",
325           io_cfg->power_mode == MMCSD_POWER_UP ? "UP" : "",
326           io_cfg->power_mode == MMCSD_POWER_ON ? "ON" : ""
327          );
328 
329     clk_src = SDIO_CLOCK_FREQ;
330 
331     if (clk > 0)
332     {
333         if (clk > host->freq_max)
334             clk = host->freq_max;
335         temp = DIV_ROUND_UP(clk_src, 2 * clk);
336         if (temp > 0x3FF)
337          temp = 0x3FF;
338     }
339 
340     if (io_cfg->bus_width == MMCSD_BUS_WIDTH_4)
341         temp |= SDMMC_CLKCR_WIDBUS_0;
342     else if (io_cfg->bus_width == MMCSD_BUS_WIDTH_8)
343         temp |= SDMMC_CLKCR_WIDBUS_1;
344 
345     hw_sdio->clkcr = temp;
346 
347     if (io_cfg->power_mode == MMCSD_POWER_ON)
348         hw_sdio->power |= SDMMC_POWER_PWRCTRL;
349 }
350 
351 static const struct rt_mmcsd_host_ops ops =
352 {
353     rthw_sdio_request,
354     rthw_sdio_iocfg,
355     RT_NULL,
356     RT_NULL,
357 };
358 
359 /**
360   * @brief  This function create mmcsd host.
361   * @param  sdio_des stm32_sdio_des
362   * @retval rt_mmcsd_host
363   */
sdio_host_create(struct stm32_sdio_des * sdio_des)364 struct rt_mmcsd_host *sdio_host_create(struct stm32_sdio_des *sdio_des)
365 {
366     struct rt_mmcsd_host *host;
367     struct rthw_sdio *sdio = RT_NULL;
368 
369     if (sdio_des == RT_NULL)
370     {
371         return RT_NULL;
372     }
373 
374     sdio = rt_malloc(sizeof(struct rthw_sdio));
375     if (sdio == RT_NULL)
376     {
377         LOG_E("malloc rthw_sdio fail");
378         return RT_NULL;
379     }
380     rt_memset(sdio, 0, sizeof(struct rthw_sdio));
381 
382     host = mmcsd_alloc_host();
383     if (host == RT_NULL)
384     {
385         LOG_E("alloc host fail");
386         goto err;
387     }
388 
389     rt_memcpy(&sdio->sdio_des, sdio_des, sizeof(struct stm32_sdio_des));
390 
391     sdio->sdio_des.hw_sdio = (struct stm32_sdio *)SDIO_BASE_ADDRESS;
392 
393     rt_event_init(&sdio->event, "sdio", RT_IPC_FLAG_FIFO);
394 
395     /* set host default attributes */
396     host->ops = &ops;
397     host->freq_min = 400 * 1000;
398     host->freq_max = SDIO_MAX_FREQ;
399     host->valid_ocr = VDD_32_33 | VDD_33_34;/* The voltage range supported is 3.2v-3.4v */
400 #ifndef SDIO_USING_1_BIT
401     host->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED;
402 #else
403     host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED;
404 #endif
405 
406     host->max_seg_size = SDIO_BUFF_SIZE;
407     host->max_dma_segs = 1;
408     host->max_blk_size = 512;
409     host->max_blk_count = 512;
410 
411     /* link up host and sdio */
412     sdio->host = host;
413     host->private_data = sdio;
414 
415     /* ready to change */
416     mmcsd_change(host);
417 
418     return host;
419 
420 err:
421     if (sdio) rt_free(sdio);
422 
423     return RT_NULL;
424 }
425 
SDMMC1_IRQHandler(void)426 void SDMMC1_IRQHandler(void)
427 {
428     /* enter interrupt */
429     rt_interrupt_enter();
430     /* Process All SDIO Interrupt Sources */
431     rthw_sdio_irq_process(host);
432     /* leave interrupt */
433     rt_interrupt_leave();
434 }
435 
rt_hw_sdio_init(void)436 int rt_hw_sdio_init(void)
437 {
438     struct stm32_sdio_des sdio_des;
439     SD_HandleTypeDef hsd;
440     hsd.Instance = SDMMC1;
441     HAL_SD_MspInit(&hsd);
442 
443     host = sdio_host_create(&sdio_des);
444     if (host == RT_NULL)
445     {
446         LOG_E("host create fail");
447         return RT_NULL;
448     }
449     return 0;
450 }
451 INIT_DEVICE_EXPORT(rt_hw_sdio_init);
452 
mnt_init(void)453 int mnt_init(void)
454 {
455     rt_thread_delay(RT_TICK_PER_SECOND);
456 
457     if (dfs_mount("sd0", "/", "elm", 0, 0) != 0)
458     {
459         rt_kprintf("Mount sd card fail!\n");
460     }
461     else
462     {
463         rt_kprintf("Mount sd card successfully!\n");
464     }
465 
466     return 0;
467 }
468 INIT_ENV_EXPORT(mnt_init);
469 
470 #endif /* BSP_USING_SDMMC */
471