1 /*
2  * Copyright (C) 2017 ALLWINNERTECH TECHNOLOGY CO., LTD. All rights reserved.
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions
6  *  are met:
7  *    1. Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *    2. Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the
12  *       distribution.
13  *    3. Neither the name of ALLWINNERTECH TECHNOLOGY CO., LTD. nor the names of
14  *       its contributors may be used to endorse or promote products derived
15  *       from this software without specific prior written permission.
16  *
17  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <string.h>
31 #include <stdio.h>
32 
33 
34 #include "sys/sys_debug.h"
35 
36 #include "os_time.h"
37 //#include "FreeRTOS.h"
38 #include "os_semaphore.h"
39 
40 #include "hal_def.h"
41 #include "hal_ccm.h"
42 #include "hal_sdhost.h"
43 #include "sdmmc.h"
44 #include "sdio.h"
45 
46 #include "_sd_define.h"
47 #include "_sdhost.h"
48 
49 
50 #define TEST_SD
51 #define TEST_SD_WRITE
52 
53 #ifdef TEST_SD
54 
55 #define SIZE_1K     (1024)
56 #define SIZE_1M         (SIZE_1K*SIZE_1K)
57 
58 #define READ_WRITE_SINGLE_SIZE  (16*SIZE_1K)
59 #define READ_WRITE_TOTAL_SIZE   (8*SIZE_1M)
60 
61 struct sdmmc_tester {
62     struct mmc_card *card;
63     SDCard_InitTypeDef card_param;
64     SDC_InitTypeDef sdc_param;
65     uint16_t sdc_id;
66     uint16_t card_id;
67     uint8_t wbuf[READ_WRITE_SINGLE_SIZE];
68     uint8_t rbuf[READ_WRITE_SINGLE_SIZE];
69 #ifdef CONFIG_DETECT_CARD
70     OS_Semaphore_t card_present_sem;
71 #endif
72 };
73 
74 static struct sdmmc_tester *sdmmc_test = NULL;
75 
76 #ifdef CONFIG_DETECT_CARD
77 static int detect_status = -1;
card_detect(uint32_t present)78 void card_detect(uint32_t present)
79 {
80     if (present) {
81         detect_status = 0;
82         rt_kprintf("%s insert\n", __func__);
83         if (mmc_card_create(sdmmc_test->card_id, &sdmmc_test->card_param) != 0) {
84             rt_kprintf("mmc create fail\n");
85             return ;
86         }
87         sdmmc_test->card = mmc_card_open(sdmmc_test->card_id);
88         if (sdmmc_test->card == NULL) {
89             rt_kprintf("mmc open fail\n");
90             return ;
91         }
92         /* scan card for detect card is exist? */
93         if (!mmc_card_present(sdmmc_test->card)) {
94         //  if (mmc_rescan(sdmmc_test->card, sdmmc_test->card->id)) {
95             sdmmc_test->card->type = MMC_TYPE_SD;
96             if (mmc_rescan(sdmmc_test->card, sdmmc_test->sdc_id)) {
97                 rt_kprintf("Initial card failed!!\n");
98                 mmc_card_close(sdmmc_test->card_id);
99                 detect_status = -1;
100                 return ;
101             } else {
102                 rt_kprintf("Initial card success. capacity :%dMB\n", sdmmc_test->card->csd.capacity / 1024);
103                 mmc_card_close(sdmmc_test->card_id);
104 #ifndef CONFIG_KERNEL_FREERTOS
105                 // void mount_sdmmc_filesystem(int card_id);
106                 // mount_sdmmc_filesystem((int)sdmmc_test->card_id);
107 #endif
108                 SDC_SemPost(&sdmmc_test->card_present_sem);
109             }
110         } else {
111             rt_kprintf("%s not eixst\n", __func__);
112             mmc_card_close(sdmmc_test->card_id);
113             return ;
114         }
115     } else {
116         struct mmc_card *card;
117 
118         rt_kprintf("%s removed\n", __func__);
119         card = mmc_card_open(sdmmc_test->card_id);
120         if (card == NULL) {
121             rt_kprintf("card open fail\n");
122         } else {
123             if (mmc_card_present(card)) {
124                 mmc_card_deinit(card);
125             }
126             mmc_card_close(sdmmc_test->card_id);
127 #ifndef CONFIG_KERNEL_FREERTOS
128             // void unmount_sdmmc_filesystem(void);
129             // unmount_sdmmc_filesystem();
130 #endif
131             mmc_card_delete(sdmmc_test->card_id);
132         }
133     }
134 }
135 #endif
136 //#define WIFI_DEBUG 0
137 // #define DETECT_BY_GPIO 1
mmc_test_init(uint32_t host_id,SDC_InitTypeDef * sdc_param,uint32_t scan)138 int32_t mmc_test_init(uint32_t host_id, SDC_InitTypeDef *sdc_param, uint32_t scan)
139 {
140     struct mmc_host *host;
141 
142     if (!sdmmc_test) {
143         sdmmc_test = malloc(sizeof(struct sdmmc_tester));
144         if (!sdmmc_test) {
145             rt_kprintf("malloc faild!\n");
146             return -1;
147         }
148         memset(sdmmc_test, 0, sizeof(struct sdmmc_tester));
149     }
150 
151     if (sdc_param)
152         memcpy(&sdmmc_test->sdc_param, sdc_param, sizeof(SDC_InitTypeDef));
153 
154 #ifdef CONFIG_DETECT_CARD
155     OS_SemaphoreCreate(&sdmmc_test->card_present_sem, 0, OS_SEMAPHORE_MAX_COUNT);
156 
157     if (!sdc_param) {
158 #ifndef DETECT_BY_GPIO
159         sdmmc_test->sdc_param.cd_mode = CARD_ALWAYS_PRESENT;
160 #else
161         sdmmc_test->sdc_param.cd_mode = CARD_DETECT_BY_GPIO_IRQ;
162 #endif
163         sdmmc_test->sdc_param.cd_cb = &card_detect;
164 #ifndef WIFI_DEBUG
165         sdmmc_test->sdc_param.debug_mask = (ROM_INF_MASK | \
166                 ROM_WRN_MASK | ROM_ERR_MASK | ROM_ANY_MASK);
167 #else
168         sdmmc_test->sdc_param.debug_mask = (ROM_DUMP_MASK | ROM_DBG_MASK | ROM_INF_MASK | \
169                 ROM_WRN_MASK | ROM_ERR_MASK | ROM_ANY_MASK);
170 #endif
171         sdmmc_test->sdc_param.dma_use = 1;
172     }
173 #endif
174     if (!sdc_param)
175         sdc_param = &sdmmc_test->sdc_param;
176 #ifdef WIFI_DEBUG
177     sdmmc_test->card_param.debug_mask = (ROM_DUMP_MASK | ROM_DBG_MASK | ROM_INF_MASK | \
178                          ROM_WRN_MASK | ROM_ERR_MASK | ROM_ANY_MASK);
179 #else
180     sdmmc_test->card_param.debug_mask = (ROM_INF_MASK | \
181                          ROM_WRN_MASK | ROM_ERR_MASK | ROM_ANY_MASK);
182 #endif
183     host = hal_sdc_create(host_id, sdc_param);
184     host->State = SDC_STATE_RESET;
185     hal_sdc_init(host);
186     //HAL_SDC_SetHighSpeed(host);
187     sdmmc_test->sdc_id = host_id;
188     sdmmc_test->card_id = host_id;
189 
190     if (scan && sdmmc_test->sdc_param.cd_mode == CARD_ALWAYS_PRESENT) {
191         card_detect(1);
192         return detect_status;
193     }
194 
195     return 0;
196 }
197 
mmc_test_exit(uint16_t sd_id,uint16_t host_id)198 int32_t mmc_test_exit(uint16_t sd_id, uint16_t host_id)
199 {
200     struct mmc_card *card;
201     struct mmc_host *host;
202 
203     if (!sdmmc_test->card || !sdmmc_test->card->host ||
204         sdmmc_test->card->id != sd_id || sdmmc_test->sdc_id != host_id) {
205         if (!sdmmc_test->card || !sdmmc_test->card->host)
206             rt_kprintf("no card found\n");
207         else
208             rt_kprintf("wrong card id:%d<->%d host id:%ld<->%d\n", sd_id, host_id,
209                    HAL_PR_SZ_L(sdmmc_test->card->id), sdmmc_test->sdc_id);
210         return 0;
211     }
212 
213     card = mmc_card_open(sdmmc_test->card_id);
214     if (card == NULL) {
215         rt_kprintf("card open fail\n");
216     } else {
217         if (mmc_card_present(card)) {
218             mmc_card_deinit(card);
219         }
220         mmc_card_close(sdmmc_test->card_id);
221         mmc_card_delete(sdmmc_test->card_id);
222     }
223 
224 #if 0
225     host = HAL_SDC_Open(host_id);
226     HAL_SDC_Close(host_id);
227 #endif
228     hal_sdc_deinit(sd_id);
229 #if 0
230     HAL_SDC_Destory(host);
231 #endif
232 
233 #ifdef CONFIG_DETECT_CARD
234     OS_SemaphoreDelete(&sdmmc_test->card_present_sem);
235 #endif
236 
237     if (sdmmc_test) {
238         free(sdmmc_test);
239         sdmmc_test = NULL;
240     }
241 
242 
243     return 0;
244 }
245 
mmc_scan_init(uint16_t sd_id,uint16_t sdc_id,SDCard_InitTypeDef * card_param)246 struct mmc_card *mmc_scan_init(uint16_t sd_id, uint16_t sdc_id, SDCard_InitTypeDef *card_param)
247 {
248     struct mmc_card *card;
249 
250     if (!card_param) {
251         card_param = &sdmmc_test->card_param;
252         sdmmc_test->card_param.debug_mask = ROM_WRN_MASK | ROM_ERR_MASK | ROM_ANY_MASK;
253     }
254     if (mmc_card_create(sd_id, card_param) != 0) {
255         rt_kprintf("mmc create fail\n");
256         return NULL;
257     }
258     card = mmc_card_open(sd_id);
259     if (card == NULL) {
260         rt_kprintf("mmc open fail\n");
261         return NULL;
262     }
263     if (!mmc_card_present(card)) {
264         int mmc_ret = mmc_rescan(card, sdc_id);
265         if (mmc_ret != 0) {
266             rt_kprintf("mmc scan fail\n");
267             mmc_card_close(sd_id);
268             return NULL;
269         } else {
270             rt_kprintf("mmc init\n");
271         }
272     }
273     mmc_card_close(sd_id);
274     sdmmc_test->card = card;
275 
276     return card;
277 }
278 
mmc_test(uint32_t host_id,uint32_t cd_mode,uint32_t sdc_degmask,uint32_t card_dbgmask)279 int32_t mmc_test(uint32_t host_id, uint32_t cd_mode, uint32_t sdc_degmask, uint32_t card_dbgmask)
280 {
281     int32_t err;
282     uint32_t i, cnt = 0;
283     SDC_InitTypeDef sdc_param = { 0 };
284 
285     sdc_param.cd_mode = cd_mode;
286     sdc_param.cd_cb = &card_detect;
287     sdc_param.debug_mask = sdc_degmask;
288     sdc_param.dma_use = 1;
289 
290     //if (mmc_test_init(host_id, &sdc_param, 1)) {
291     if (mmc_test_init(host_id, &sdc_param, 1)) {
292         return -1;
293     }
294 
295     memset((void *)sdmmc_test->wbuf, 0x55, 128);
296     memset((void *)&sdmmc_test->wbuf[128], 0xaa, 128);
297 
298     for (i = 0; i < 256; i ++)
299         sdmmc_test->wbuf[256 + i] = i;
300 
301     memcpy((void *)&sdmmc_test->wbuf[512], (void *)sdmmc_test->wbuf, 512);
302 
303     sdmmc_test->card_param.debug_mask = card_dbgmask;
304 
305 
306 //  if (mmc_test_init(host_id, &sdc_param, 1)) {
307 //      return -1;
308 //  }
309 
310 
311     sdmmc_test->card_param.type = MMC_TYPE_SD;
312 
313     while (cnt++ < 1) {
314         uint32_t throuth_mb, throuth_kb;
315         OS_Time_t tick_use;
316 
317         rt_kprintf("%s,%d count:%lu\n", __func__, __LINE__, HAL_PR_SZ_L(cnt));
318 
319 #ifdef CONFIG_DETECT_CARD
320         if (!mmc_card_present(sdmmc_test->card) || (cd_mode != CARD_ALWAYS_PRESENT))
321             OS_SemaphoreWait(&sdmmc_test->card_present_sem, OS_WAIT_FOREVER);
322 #endif
323 
324         struct mmc_card *card = mmc_card_open(sdmmc_test->card_id);
325         card->debug_mask = card_dbgmask;
326         if (card == NULL) {
327             rt_kprintf("mmc open fail\n");
328             goto err_out;
329         }
330 
331 #ifdef TEST_SD_WRITE
332         tick_use = OS_GetTicks();
333         err = mmc_block_write(sdmmc_test->card, sdmmc_test->wbuf, 0, 1);
334         tick_use = OS_GetTicks() - tick_use;
335         if (err) {
336             goto err_out;
337         } else {
338             rt_kprintf("%s 1 block write ok, 512B use:%lu ms\n", __func__,
339                   HAL_PR_SZ_L((uint32_t)OS_TicksToMSecs(tick_use)));
340         }
341 #endif
342         memset((void *)sdmmc_test->rbuf, 0, 512);
343         tick_use = OS_GetTicks();
344         err = mmc_block_read(sdmmc_test->card, sdmmc_test->rbuf, 0, 1);
345         tick_use = OS_GetTicks() - tick_use;
346         if (err) {
347             goto err_out;
348         } else {
349             rt_kprintf("%s 1 block read ok, 512B use:%lu ms\n", __func__,
350                    HAL_PR_SZ_L((uint32_t)OS_TicksToMSecs(tick_use)));
351 #ifndef TEST_SD_WRITE
352             print_hex_dump_words(sdmmc_test->rbuf, 512);
353 #endif
354         }
355 #ifdef TEST_SD_WRITE
356         if (memcmp((void *)sdmmc_test->wbuf, (void *)sdmmc_test->rbuf, 512)) {
357             goto err_out;
358         } else
359             rt_kprintf("%s,%d mmc 1 block rw ok\n", __func__, __LINE__);
360 
361         tick_use = OS_GetTicks();
362         for (i = 0; i < READ_WRITE_TOTAL_SIZE/READ_WRITE_SINGLE_SIZE; i++) {
363             err = mmc_block_write(sdmmc_test->card, sdmmc_test->wbuf, 3 + i * (READ_WRITE_SINGLE_SIZE/512),
364                                   READ_WRITE_SINGLE_SIZE/512);
365             if (err)
366                 break;
367             if (i % 50 == 0)
368                 rt_kprintf("%s, wirite cnt:%lu\n", __func__, HAL_PR_SZ_L(i));
369         }
370         tick_use = OS_GetTicks() - tick_use;
371         if (err) {
372             rt_kprintf("%s,%d mmc mult blocks write err!\n", __func__, __LINE__);
373             goto err_out;
374         } else {
375             throuth_kb = READ_WRITE_TOTAL_SIZE/SIZE_1K*1000/(uint32_t)OS_TicksToMSecs(tick_use);
376             throuth_mb = throuth_kb/1000;
377             rt_kprintf("%s mult blocks write ok, %d MB use:%lu ms, throughput:%lu.%lu MB/S\n",
378                    __func__, READ_WRITE_TOTAL_SIZE/SIZE_1M, HAL_PR_SZ_L((uint32_t)OS_TicksToMSecs(tick_use)),
379                    HAL_PR_SZ_L(throuth_mb), HAL_PR_SZ_L(throuth_kb - throuth_mb));
380         }
381 #endif
382 
383         tick_use = OS_GetTicks();
384         for (i = 0; i < READ_WRITE_TOTAL_SIZE/READ_WRITE_SINGLE_SIZE; i++) {
385             err = mmc_block_read(sdmmc_test->card, sdmmc_test->rbuf, 3 + i * (READ_WRITE_SINGLE_SIZE/512),
386                                  READ_WRITE_SINGLE_SIZE/512);
387             if (err)
388                 break;
389         }
390         tick_use = OS_GetTicks() - tick_use;
391         if (err) {
392             rt_kprintf("%s,%d mmc mult blocks read err!\n", __func__, __LINE__);
393             goto err_out;
394         } else {
395             throuth_kb = READ_WRITE_TOTAL_SIZE/SIZE_1K*1000/(uint32_t)OS_TicksToMSecs(tick_use);
396             throuth_mb = throuth_kb/1000;
397             rt_kprintf("%s mult blocks read ok, %d MB use:%lu ms, throughput:%lu.%lu MB/S\n",
398                    __func__, READ_WRITE_TOTAL_SIZE/SIZE_1M, HAL_PR_SZ_L((uint32_t)OS_TicksToMSecs(tick_use)),
399                    HAL_PR_SZ_L(throuth_mb), HAL_PR_SZ_L(throuth_kb - throuth_mb));
400         }
401 
402         memset((void *)sdmmc_test->rbuf, 0, READ_WRITE_SINGLE_SIZE);
403         err = mmc_block_read(sdmmc_test->card, sdmmc_test->rbuf, 3, READ_WRITE_SINGLE_SIZE/512);
404         if (err) {
405             goto err_out;
406         } else
407             rt_kprintf("%s %d blocks read ok\n", __func__, READ_WRITE_SINGLE_SIZE/512);
408 
409 #ifdef TEST_SD_WRITE
410         if (memcmp((void *)sdmmc_test->wbuf, (void *)sdmmc_test->rbuf, 1024)) { /* check 1024B */
411             rt_kprintf("%s %d mmc blocks rw failed\n", __func__, READ_WRITE_SINGLE_SIZE/512);
412             goto err_out;
413         } else
414             rt_kprintf("%s %d mmc blocks rw ok\n", __func__, READ_WRITE_SINGLE_SIZE/512);
415 #endif
416         mmc_card_close(sdmmc_test->card_id);
417 
418         OS_MSleep(1000);
419     }
420 
421     mmc_test_exit(host_id, sdmmc_test->card_id);
422 
423     return 0;
424 
425 err_out:
426 #ifdef TEST_SD_WRITE
427     rt_kprintf("%s,%d mmc block rw failed\n", __func__, __LINE__);
428     rt_kprintf("rbuf:\n");
429     print_hex_dump_words(sdmmc_test->rbuf, SIZE_1K);
430     rt_kprintf("wbuf:\n");
431     print_hex_dump_words(sdmmc_test->wbuf, 512);
432 #endif
433 #ifndef CONFIG_DETECT_CARD
434 out:
435 #endif
436     mmc_test_exit(host_id, sdmmc_test->card_id);
437     return -1;
438 }
439 #endif /* TEST_SD */
440