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 * 2021-10-29 JasonHu first version
9 */
10
11 #define DBG_TAG "drv-sdmmc"
12 #include <rtdbg.h>
13
14 #include <stddef.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <errno.h>
18 #include <stdint.h>
19 #include <stdio.h>
20 #include <rtthread.h>
21
22 #ifdef BSP_USING_SDMMC
23
24 #include <typedef.h>
25 #include <kapi.h>
26 #include <init.h>
27 #include <blkpart.h>
28 #include <sdmmc/hal_sdhost.h>
29 #include <sdmmc/card.h>
30 #include <sdmmc/sys/sys_debug.h>
31 #include <sdmmc/sdmmc.h>
32 #include <sdmmc/sd_test.h>
33 #include <drv_sdmmc.h>
34
35 #include <dfs_file.h>
36 #include <unistd.h>
37 #include <stdio.h> /* rename() */
38 #include <sys/stat.h>
39 #include <sys/statfs.h> /* statfs() */
40 #include "partition.h"
41
42 #ifdef CONFIG_SUPPORT_SDMMC_CACHE
43 #include "sdmmc_cache.h"
44 #endif
45
46 // #define DETECT_BY_GPIO
47
48 #ifndef CONFIG_SDC_DMA_BUF_SIZE
49 #define SDC_ALIGN_DMA_BUF_SIZE (64 * 1024)
50 #else
51 #define SDC_ALIGN_DMA_BUF_SIZE (CONFIG_SDC_DMA_BUF_SIZE * 1024)
52 #endif
53
54 #define SDXC_MAX_TRANS_LEN SDC_ALIGN_DMA_BUF_SIZE
55
56 #ifndef ALIGN_DOWN
57 #define ALIGN_DOWN(size, align) ((size) & ~((align)-1))
58 #endif
59
60 #ifndef MIN
61 #define MIN(a, b) (a > b ? b : a)
62 #endif
63
_register_blk_part_device(rt_device_t dev,const char * dev_name)64 static int _register_blk_part_device(rt_device_t dev, const char *dev_name)
65 {
66 uint8_t *mbr_buf = NULL;
67 int ret = 0;
68 int i = 0;
69 struct rt_partition *part_table;
70 int part_count = 0;
71 int alloc_part_count = 2;
72
73 /* NOTICE: get block geometry fisrt time here, then you can read/write sdmmc. */
74 struct dev_sdmmc *dev_sdmmc = (struct dev_sdmmc *)dev->user_data;
75 if (rt_dev_control(dev, RT_DEVICE_CTRL_BLK_GETGEOME, &dev_sdmmc->geometry) != RT_EOK)
76 {
77 LOG_E("device get geometry failed!");
78 return -RT_EIO;
79 }
80
81 rt_kprintf("sdmmc bytes_per_secotr:%x, sector count:%x\n", dev_sdmmc->geometry.bytes_per_sector, dev_sdmmc->geometry.sector_count);
82
83 /*read the mbr*/
84 mbr_buf = rt_malloc(dev_sdmmc->geometry.bytes_per_sector);
85 if (!mbr_buf)
86 {
87 return -RT_ENOMEM;
88 }
89 rt_memset(mbr_buf, 0, dev_sdmmc->geometry.bytes_per_sector);
90
91 part_table = rt_malloc(sizeof(struct rt_partition) * alloc_part_count);
92 if (!part_table)
93 {
94 return -RT_ENOMEM;
95 }
96
97 if (rt_dev_read(dev, 0, mbr_buf, 1) != 1)
98 {
99 LOG_E("device read mbr 1-sector failure\n");
100 ret = -RT_ERROR;
101 goto err;
102 }
103
104 for (i = 0;; i++)
105 {
106 rt_err_t status;
107 struct dfs_partition part;
108
109 status = dfs_filesystem_get_partition(&part, mbr_buf, i);
110 if (status != RT_EOK)
111 {
112 if (i == 0)
113 {
114 snprintf(part_table[0].name, 6, "sd%dp%d", dev_sdmmc->host_id, i);
115 part_table[0].offset = 8 * 1024 * 1024;
116 part_table[0].size = dev_sdmmc->geometry.bytes_per_sector * dev_sdmmc->geometry.sector_count - part_table[0].offset;
117 part_table[0].flags = PARTITION_WRITEABLE;
118 part_count = 1;
119
120 rt_kprintf("not found partition of mbr, construct sd0 at offset 8M, size:%p\n", part_table[0].size);
121 }
122 break;
123 }
124 else
125 {
126 if (part_count >= alloc_part_count)
127 {
128 rt_kprintf("part_count1:%d\n", part_count);
129
130 struct rt_partition *new_part_table;
131
132 alloc_part_count *= 2;
133
134 new_part_table = rt_realloc(part_table, alloc_part_count * sizeof(struct rt_partition));
135 if (new_part_table != RT_NULL)
136 {
137 part_table = new_part_table;
138 }
139 else
140 {
141 break;
142 }
143 }
144 rt_kprintf("found partition:sd%d of mbr at offset %p, size:%p\n", i, part.offset, part.size);
145 snprintf(part_table[part_count].name, 6, "sd%dp%d", dev_sdmmc->host_id, i);
146 part_table[part_count].offset = part.offset * dev_sdmmc->geometry.bytes_per_sector;
147 // rt_kprintf("bytes_per_sector:%d\n", dev_sdmmc->geometry.bytes_per_sector);
148 // rt_kprintf("part_table_offset:%d\n", part.offset * dev_sdmmc->geometry.bytes_per_sector);
149 part_table[part_count].size = part.size * dev_sdmmc->geometry.bytes_per_sector;
150 part_table[part_count].flags = PARTITION_WRITEABLE;
151 part_count++;
152 }
153 }
154
155 err:
156 if (part_count > 0)
157 {
158 ret = rt_partition_init(dev_name, part_table, part_count);
159 }
160 if (mbr_buf != NULL)
161 {
162 rt_free(mbr_buf);
163 }
164
165 if (ret != 0)
166 {
167 if (part_table != NULL)
168 {
169 rt_free(part_table);
170 }
171 }
172
173 return ret;
174 }
175
sdmmc_init(rt_device_t dev)176 rt_err_t sdmmc_init(rt_device_t dev)
177 {
178 int ret = -1;
179
180 struct dev_sdmmc *dev_priv = (struct dev_sdmmc *)dev->user_data;
181 int host_id = dev_priv->host_id;
182
183 dev->flag |= RT_DEVICE_FLAG_ACTIVATED;
184 int32_t internal_card = 0x00;
185
186 SDC_InitTypeDef sdc_param = {0};
187 sdc_param.debug_mask = (ROM_INF_MASK |
188 ROM_WRN_MASK | ROM_ERR_MASK | ROM_ANY_MASK);
189
190 esCFG_GetKeyValue("sdcard_global", "internal_card", (int32_t *)&internal_card, 1);
191
192 if (((internal_card >> host_id) & 0x01) == 1)
193 {
194 sdc_param.cd_mode = CARD_ALWAYS_PRESENT;
195 LOG_D("cd_mode CARD_ALWAYS_PRESENT!");
196 }
197 else
198 {
199 #ifndef DETECT_BY_GPIO
200 sdc_param.cd_mode = CARD_ALWAYS_PRESENT;
201 #else
202 sdc_param.cd_mode = CARD_DETECT_BY_GPIO_IRQ;
203 #endif
204 }
205 sdc_param.cd_cb = &card_detect;
206 sdc_param.dma_use = 1;
207
208 if (mmc_test_init(host_id, &sdc_param, 1))
209 {
210 dev->flag &= ~RT_DEVICE_FLAG_ACTIVATED;
211 LOG_E("init sdmmc failed!");
212 return ret;
213 }
214 LOG_D("host_id =%d!", host_id);
215
216 /* wait timeout to sync with sdmmc init done */
217 int mdelay = 500;
218 while (!hal_sdc_init_timeout() && mdelay > 0)
219 {
220 rt_thread_mdelay(50);
221 mdelay -= 50;
222 }
223 return 0;
224 }
225
sdmmc_deinit(rt_device_t dev)226 rt_err_t sdmmc_deinit(rt_device_t dev)
227 {
228 struct dev_sdmmc *dev_priv = (struct dev_sdmmc *)dev->user_data;
229 int host_id = dev_priv->host_id;
230 mmc_test_exit(host_id, host_id);
231 return 0;
232 }
233
sdmmc_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)234 static rt_ssize_t sdmmc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
235 {
236 ssize_t ret, rsz, trsz, msz = 0;
237 struct rt_device_blk_geometry *geometry;
238 uint8_t *data = buffer;
239 struct dev_sdmmc *dev_priv = (struct dev_sdmmc *)dev->user_data;
240 struct mmc_card *card = mmc_card_open(dev_priv->host_id);
241
242 if (card == NULL)
243 {
244 LOG_E("mmc open fail");
245 return 0;
246 }
247
248 if (size == 0)
249 {
250 return 0;
251 }
252
253 // rt_kprintf("sd read, pos:%llu, blkcnt:%llu\n", pos, size);
254
255 geometry = &dev_priv->geometry;
256
257 if (pos >= geometry->sector_count)
258 {
259 LOG_E("read offset %lu over part sector %llu", pos, geometry->sector_count);
260 return 0;
261 }
262
263 if (pos + size > geometry->sector_count)
264 {
265 LOG_E("over limit: offset %lu + size %lu over %llu",
266 pos, size, geometry->sector_count);
267 return 0;
268 }
269
270 trsz = 0;
271 msz = SDXC_MAX_TRANS_LEN / geometry->bytes_per_sector;
272 while (size > 0)
273 {
274 if (size < msz)
275 {
276 rsz = size;
277 }
278 else
279 {
280 rsz = msz;
281 }
282
283 ret = mmc_block_read(card, data, pos, rsz);
284 if (ret)
285 {
286 LOG_E("read failed - %d", (int)ret);
287 break;
288 }
289
290 trsz += rsz;
291 size -= rsz;
292 data += rsz * geometry->bytes_per_sector;
293 pos += rsz;
294 }
295
296 mmc_card_close(dev_priv->host_id);
297
298 return trsz;
299 }
300
sdmmc_open(rt_device_t dev,rt_uint16_t oflag)301 static rt_err_t sdmmc_open(rt_device_t dev, rt_uint16_t oflag)
302 {
303 return 0;
304 }
305
sdmmc_close(rt_device_t dev)306 static rt_err_t sdmmc_close(rt_device_t dev)
307 {
308 return 0;
309 }
310
sdmmc_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)311 static rt_ssize_t sdmmc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
312 {
313 int err = -1;
314 ssize_t ret, wsz, twsz, msz = 0;
315 struct rt_device_blk_geometry *geometry;
316 uint8_t *data = (uint8_t *)buffer;
317
318 struct dev_sdmmc *dev_priv = (struct dev_sdmmc *)dev->user_data;
319 struct mmc_card *card = mmc_card_open(dev_priv->host_id);
320 if (card == NULL)
321 {
322 LOG_E("mmc open fail");
323 return -EIO;
324 }
325
326 if (size == 0)
327 {
328 return 0;
329 }
330
331 geometry = &dev_priv->geometry;
332
333 if (pos >= geometry->sector_count)
334 {
335 LOG_E("read offset %lu over part size %llu", pos, geometry->sector_count);
336 return 0;
337 }
338
339 if (pos + size > geometry->sector_count)
340 {
341 LOG_E("over limit: offset %lu + size %lu over %llu",
342 pos, size, geometry->sector_count);
343 return 0;
344 }
345
346 twsz = 0;
347 msz = SDXC_MAX_TRANS_LEN / geometry->bytes_per_sector;
348 while (size > 0)
349 {
350 if (size < msz)
351 {
352 wsz = size;
353 }
354 else
355 {
356 wsz = msz;
357 }
358
359 ret = mmc_block_write(card, data, pos, wsz);
360 if (ret)
361 {
362 LOG_E("read failed - %d", (int)ret);
363 break;
364 }
365
366 twsz += wsz;
367 size -= wsz;
368 data += wsz * geometry->bytes_per_sector;
369 pos += wsz;
370 }
371
372 mmc_card_close(dev_priv->host_id);
373
374 return twsz;
375 }
376
sdmmc_control(rt_device_t dev,int cmd,void * args)377 static rt_err_t sdmmc_control(rt_device_t dev, int cmd, void *args)
378 {
379 int ret = -RT_ERROR;
380 struct rt_device_blk_geometry *geometry;
381 int flag = 0;
382 if (!dev)
383 {
384 return -EINVAL;
385 }
386
387 struct dev_sdmmc *dev_priv = (struct dev_sdmmc *)dev->user_data;
388 struct mmc_card *card = mmc_card_open(dev_priv->host_id);
389 if (!card)
390 {
391 return ret;
392 }
393
394 switch (cmd)
395 {
396 case BLOCK_DEVICE_CMD_ERASE_ALL:
397 break;
398 case BLOCK_DEVICE_CMD_ERASE_SECTOR:
399 break;
400 case BLOCK_DEVICE_CMD_GET_TOTAL_SIZE:
401 *(uint64_t *)args = card->csd.capacity * 1024ull;
402 ret = 0;
403 break;
404 case BLOCK_DEVICE_CMD_GET_PAGE_SIZE:
405 *(uint32_t *)args = 512;
406 ret = 0;
407 break;
408 case BLOCK_DEVICE_CMD_GET_BLOCK_SIZE:
409 *(uint32_t *)args = 512;
410 ret = 0;
411 break;
412 case RT_DEVICE_CTRL_BLK_GETGEOME:
413 geometry = (struct rt_device_blk_geometry *)args;
414 rt_memset(geometry, 0, sizeof(struct rt_device_blk_geometry));
415 geometry->block_size = 512;
416 geometry->bytes_per_sector = 512;
417 geometry->sector_count = (card->csd.capacity * 1024ull) / geometry->bytes_per_sector;
418 LOG_D("[sdmmc] getgeome: bytes_per_sector:%ld, block_size:%ld, sector_count:%ld",
419 geometry->bytes_per_sector, geometry->block_size, geometry->sector_count);
420 ret = RT_EOK;
421 break;
422
423 default:
424 break;
425 }
426
427 mmc_card_close(dev_priv->host_id);
428 return ret;
429 }
430
431 #ifdef RT_USING_DEVICE_OPS
432 const static struct rt_device_ops _sdmmc_ops =
433 {
434 .init = sdmmc_init,
435 .open = sdmmc_open,
436 .close = sdmmc_close,
437 .read = sdmmc_read,
438 .write = sdmmc_write,
439 .control = sdmmc_control
440 };
441 #endif /* RT_USING_DEVICE_OPS */
442
init_sdmmc_device(rt_device_t device,void * usr_data,char * dev_name)443 static int init_sdmmc_device(rt_device_t device, void *usr_data, char *dev_name)
444 {
445 int ret = -1;
446
447 device = rt_device_create(RT_Device_Class_Block, 0);
448 if (!device)
449 {
450 return ret;
451 }
452
453 #ifndef RT_USING_DEVICE_OPS
454 device->init = sdmmc_init;
455 device->open = sdmmc_open;
456 device->close = sdmmc_close;
457 device->read = sdmmc_read;
458 device->write = sdmmc_write;
459 device->control = sdmmc_control;
460 #else
461 device->ops = &_sdmmc_ops;
462 #endif /* RT_USING_DEVICE_OPS */
463 device->user_data = usr_data;
464
465 ret = rt_device_register(device, dev_name, RT_DEVICE_FLAG_RDWR);
466 if (ret != RT_EOK)
467 {
468 rt_device_destroy(device);
469 return ret;
470 }
471
472 // int sdmmc_blkpart_init(const char *name);
473 // ret = sdmmc_blkpart_init(dev_name);
474 if (sdmmc_init(device))
475 {
476 LOG_E("sdmmc_init failed!");
477 return -1;
478 }
479
480 /* NOTICE: get block geometry fisrt time here, then you can read/write sdmmc. */
481 struct dev_sdmmc *dev_sdmmc = (struct dev_sdmmc *)device->user_data;
482 if (rt_dev_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &dev_sdmmc->geometry) != RT_EOK)
483 {
484 LOG_E("device get geometry failed!");
485 ret = -ENOSYS;
486 }
487
488 _register_blk_part_device(device, dev_name);
489
490 return ret;
491 }
492
493 static struct dev_sdmmc dev_sdmmc[SDMMC_CARD_NR];
494
driver_sdmmc_init(void)495 int driver_sdmmc_init(void)
496 {
497 int ret = -1;
498 int i = 0;
499 rt_device_t device[SDMMC_CARD_NR];
500 int32_t used_card_no = 0x01;
501 char name[12];
502
503 ret = esCFG_GetKeyValue("sdcard_global", "used_card_no", (int32_t *)&used_card_no, 1);
504 if (ret)
505 {
506 used_card_no = 0x00;
507 LOG_E("get card no failed, card no: %d", used_card_no);
508 return ret;
509 }
510
511 for (i = 0; i < SDMMC_CARD_NR; ++i)
512 {
513 rt_sprintf(name, "sdmmc%d", i);
514 dev_sdmmc[i].host_id = i;
515 ret = init_sdmmc_device(device[i], (void *)&dev_sdmmc[i], name);
516 }
517 return ret;
518 }
519
sd_mmc1_init(void)520 void sd_mmc1_init(void)
521 {
522 rt_device_t device = NULL;
523 device = rt_device_find("sdmmc1");
524 sdmmc_init(device);
525
526 _register_blk_part_device(device, "sdmmc1");
527 }
528
sd_mmc1_deinit(void)529 void sd_mmc1_deinit(void)
530 {
531 rt_device_t device = NULL;
532 device = rt_device_find("sdmmc1");
533 sdmmc_deinit(device);
534 }
535
536 INIT_DEVICE_EXPORT(driver_sdmmc_init);
537
538 #endif
539