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 * 2007-12-02 Yi.Qiu the first version
9 * 2010-01-01 Bernard Modify for mini2440
10 * 2010-10-13 Wangmeng Added sep4020 support
11 */
12
13 #include <rtthread.h>
14
15 #include "sdcard.h"
16
17 #ifdef RT_USING_DFS
18 volatile rt_int32_t RCA;
19
20 /* RT-Thread Device Driver Interface */
21 #include <dfs_fs.h>
22
23 /*GLOBAL SD DEVICE PONITER*/
24 static struct sd_device *ptr_sddev;
25 static rt_uint8_t gsec_buf[SECTOR_SIZE];
26
27 #define USE_TIMEOUT
28
29 /*This file is to power on/off the SEP4020 SDC*/
30 /**
31 * This function will power on/off the SEP4020 SDC
32 *
33 * @param sd_ctl: 0/power on; 1/power off
34 * @return none
35 *
36 */
sd_pwr(int sd_ctl)37 static void sd_pwr(int sd_ctl)
38 {
39 if (sd_ctl)
40 {
41 *(RP)GPIO_PORTA_SEL |= 0x0200;
42 *(RP)GPIO_PORTA_DIR &= (~0x0200);
43 *(RP)GPIO_PORTA_DATA |= 0x0200;
44 }
45 else
46 {
47
48 *(RP)GPIO_PORTA_SEL |= 0x0200;
49 *(RP)GPIO_PORTA_DIR &= (~0x0200);
50 *(RP)GPIO_PORTA_DATA &= (~0x0200);
51 }
52 }
53
54 /*a nop operation to delay*/
delay(U32 j)55 static void delay(U32 j)
56 {
57 U32 i;
58
59 for (i = 0; i < j; i++)
60 {
61 /* nothing */
62 }
63 }
64
65 /*
66 * Send the command to set the data transfer mode
67 * @param cmd:the command to sent
68 * @param arg:the argument of the command
69 * @param mode:SDC transfer mode
70 * @param blk_len:the block size of each data
71 * @param num:number of blocks
72 * @param mask:sdc interrupt mask
73 */
cmd_data(U16 cmd,U32 arg,U16 mode,U16 blk_len,U16 num,U16 mask)74 static rt_err_t cmd_data(U16 cmd, U32 arg, U16 mode, U16 blk_len, U16 num, U16 mask)
75 {
76 U32 i;
77 #ifdef USE_TIMEOUT
78 U32 to = 10000;
79 #endif
80
81 *(RP)SDC_CLOCK_CONTROL = 0Xff00;
82 *(RP)SDC_CLOCK_CONTROL = 0Xff04;
83 *(RP)SDC_INTERRUPT_STATUS_MASK = mask;
84
85 *(RP)SDC_TRANSFER_MODE = mode;
86
87 *(RP)SDC_BLOCK_SIZE = blk_len;
88 *(RP)SDC_BLOCK_COUNT = num;
89 *(RP)SDC_ARGUMENT = arg;
90 *(RP)SDC_COMMAND = cmd;
91
92 delay(10);
93
94 i = *(RP)SDC_INTERRUPT_STATUS & 0x1000;
95
96 while (i != 0x1000)
97 {
98 i = *(RP)SDC_INTERRUPT_STATUS & 0x1000;
99 #ifdef USE_TIMEOUT
100 to --;
101 if (!to)
102 {
103 EOUT("%s TIMEOUT\n", __FUNCTION__);
104 return -RT_ETIMEOUT;
105 }
106 #endif
107 }
108 delay(160);
109
110 return *(RP)SDC_RESPONSE0;
111 }
112
cmd_response(U16 Cmd,U32 Arg,U16 TransMode,U16 BlkLen,U16 Nob,U16 IntMask)113 static rt_err_t cmd_response(U16 Cmd, U32 Arg, U16 TransMode, U16 BlkLen, U16 Nob, U16 IntMask)
114 {
115 U32 i;
116 #ifdef USE_TIMEOUT
117 U32 to = 50000;
118 #endif
119
120 *(RP)SDC_CLOCK_CONTROL = 0Xff00;
121
122 *(RP)SDC_CLOCK_CONTROL = 0Xff04;
123
124
125 *(RP)SDC_INTERRUPT_STATUS_MASK = IntMask;
126 *(RP)SDC_TRANSFER_MODE = TransMode;
127 *(RP)SDC_BLOCK_SIZE = BlkLen;
128 *(RP)SDC_BLOCK_COUNT = Nob;
129 *(RP)SDC_ARGUMENT = Arg;
130 *(RP)SDC_COMMAND = Cmd;
131
132 delay(10);
133
134 i = *(RP)SDC_INTERRUPT_STATUS & 0x1040;
135
136 while (i != 0x1040)
137 {
138 i = *(RP)SDC_INTERRUPT_STATUS & 0x1040;
139 #ifdef USE_TIMEOUT
140 to--;
141 if (!to)
142 {
143 EOUT("%s Timeout\n", __FUNCTION__);
144 return -RT_ETIMEOUT;
145 }
146 #endif
147 }
148
149 //DBOUT("cmd_response TO is %d\n",to);
150 delay(100);
151
152 return RT_EOK;
153 }
154
cmd_wait(U16 Cmd,U32 Arg,U16 IntMask)155 static rt_err_t cmd_wait(U16 Cmd, U32 Arg, U16 IntMask)
156 {
157 int i;
158 #ifdef USE_TIMEOUT
159 U32 to = 200000;
160 #endif
161
162 *(RP)SDC_CLOCK_CONTROL = 0Xff00;
163
164 *(RP)SDC_CLOCK_CONTROL = 0Xff04;
165
166 *(RP)SDC_COMMAND = Cmd;
167
168 *(RP)SDC_INTERRUPT_STATUS_MASK = IntMask;
169
170 *(RP)SDC_ARGUMENT = Arg;
171
172 i = *(RP)SDC_INTERRUPT_STATUS & 0x1000;
173
174 while (i != 0x1000)
175 {
176 i = *(RP)SDC_INTERRUPT_STATUS & 0x1000;
177 #ifdef USE_TIMEOUT
178 to--;
179 if (!to)
180 {
181 EOUT("%s Timeout\n", __FUNCTION__);
182 return -RT_ETIMEOUT;
183 }
184 #endif
185
186 }
187
188 //DBOUT("cmd_wait TO is %d\n",to);
189
190 delay(10);
191
192 return RT_EOK;
193 }
194
195 /**
196 * This function will set a hook function, which will be invoked when a memory
197 * block is allocated from heap memory.
198 *
199 * @param hook the hook function
200 */
sd_init(void)201 static rt_err_t sd_init(void)
202 {
203 rt_err_t err;
204 #ifdef USE_TIMEOUT
205 rt_uint32_t to = 1000;
206 #endif
207 sd_pwr(1);
208
209 *(RP)SDC_SOFTWARE_RESET = 0x0;
210 delay(200);
211 *(RP)SDC_SOFTWARE_RESET = 0x1;
212 delay(200);
213
214 cmd_wait(0x08, 0x0, 0xfff);
215
216 do
217 {
218 err = cmd_wait(0x6ea, 0x0, 0xfff);
219
220 #ifdef USE_TIMEOUT
221 if (err != RT_EOK)
222 {
223 EOUT("cmd_wait err in %s\n", __FUNCTION__);
224 return -RT_ETIMEOUT;
225 }
226 #endif
227
228 delay(3);
229 err = cmd_wait(0x52a, 0x80ff8000, 0xfff);
230 if (err != RT_EOK)
231 {
232 EOUT("cmd_wait err in %s\n", __FUNCTION__);
233 return -RT_ETIMEOUT;
234 }
235 #ifdef USE_TIMEOUT
236 to--;
237 if (!to)
238 {
239 EOUT("%s timeout\n", __FUNCTION__);
240 return -RT_ETIMEOUT;
241 }
242 #endif
243
244 }
245 while (*(RP)SDC_RESPONSE0 < 0X80008000);
246
247 cmd_data(0x49, 0X0, 0X0, 0x0, 0x0, 0Xfff);
248 cmd_data(0x6a, 0X0, 0X0, 0x0, 0x0, 0Xfff);
249 RCA = *(RP)SDC_RESPONSE0;
250 cmd_data(0xea, RCA, 0X0, 0x0, 0x0, 0Xfff);
251
252 return RT_EOK;
253 }
254
255 /**
256 * This function will set a hook function, which will be invoked when a memory
257 * block is allocated from heap memory.
258 *
259 * @param hook the hook function
260 */
sd_readblock(rt_uint32_t address,rt_uint8_t * buf)261 static rt_err_t sd_readblock(rt_uint32_t address, rt_uint8_t *buf)
262 {
263 U32 complete, i;
264 rt_uint8_t temp;
265 rt_err_t err;
266 rt_uint32_t discard;
267 #ifdef USE_TIMEOUT
268 rt_uint32_t to = 10;
269 #endif
270
271 RT_UNUSED(discard);
272
273 //rt_kprintf("in readblock:%x\n",address);
274 //Clear all the errors & interrups
275 *(RP)DMAC_INTINTERRCLR |= 0x1;
276 *(RP)DMAC_INTINTERRCLR &= ~0x1;
277 *(RP)DMAC_INTTCCLEAR |= 0x1;
278 *(RP)DMAC_INTTCCLEAR &= ~0x1;
279
280 /*Clear read fifo*/
281 *(RP)(SDC_INTERRUPT_STATUS_MASK) = ~(0x1 << 9); //don't mask fifo empty
282 while ((*(RP)SDC_INTERRUPT_STATUS) & 0x200 != 0x200)
283 discard = *(RP)SDC_READ_BUFER_ACCESS;
284
285 /*DMAC2,word,size=0x80*/
286 *(RP)DMAC_C2SRCADDR = SDC_READ_BUFER_ACCESS;
287 *(RP)DMAC_C2DESTADDR = (rt_uint32_t)buf;
288 *(RP)DMAC_C2CONTROL = 0x20249b;
289 *(RP)DMAC_C2CONFIGURATION = 0x38d;
290
291 err = cmd_wait(0x6ea, RCA, 0xfff);
292 if (err != RT_EOK)
293 {
294 rt_set_errno(err);
295 return err;
296 }
297
298 err = cmd_wait(0xca, 0x2, 0xfff);
299 if (err != RT_EOK)
300 {
301 rt_set_errno(err);
302 return err;
303 }
304
305 err = cmd_response(0x22e, address, 0X1, 0x0200, 0x1, 0Xfff); //CMD17 4bit mode
306 if (err != RT_EOK)
307 {
308 rt_set_errno(err);
309 return err;
310 }
311
312 complete = *(RP)SDC_INTERRUPT_STATUS;
313
314 /*CRC*/
315 if ((complete | 0xfffffffd) != 0xfffffffd)
316 {
317 rt_kprintf("CRC ERROR!!!\n");
318 complete = *(RP)SDC_INTERRUPT_STATUS;
319 }
320 while (((*(RP)(DMAC_INTTCSTATUS)) & 0x4) != 0x4)
321 {
322 delay(10);
323 #ifdef USE_TIMEOUT
324 to--;
325 if (!to)
326 {
327 EOUT("%s TIMEOUT\n", __FUNCTION__);
328 return -RT_ETIMEOUT;
329 }
330 #endif
331 }
332 #ifdef USE_TIMEOUT
333 //DBOUT("%s timeout is %d\n",__FUNCTION__,to);
334 #endif
335 /*for the buf is big-endian we must reverse it*/
336 for (i = 0; i < 0x80; i++)
337 {
338 temp = buf[0];
339 buf[0] = buf[3];
340 buf[3] = temp;
341
342 temp = buf[1];
343 buf[1] = buf[2];
344 buf[2] = temp;
345
346 buf += 4;
347 }
348
349 return RT_EOK;
350 }
351
sd_readmultiblock(rt_uint32_t address,rt_uint8_t * buf,rt_uint32_t size)352 static rt_uint8_t sd_readmultiblock(rt_uint32_t address, rt_uint8_t *buf, rt_uint32_t size)
353 {
354 rt_int32_t index;
355 rt_uint8_t status = RT_EOK;
356
357 for (index = 0; index < size; index++)
358 {
359 status = sd_readblock(address + index * SECTOR_SIZE, buf + index * SECTOR_SIZE);
360 if (status != RT_EOK)
361 break;
362 }
363 return status;
364 }
365
366 /**
367 * This function will set a hook function, which will be invoked when a memory
368 * block is allocated from heap memory.
369 *
370 * @param hook the hook function
371 */
sd_writeblock(rt_uint32_t address,rt_uint8_t * buf)372 static rt_uint8_t sd_writeblock(rt_uint32_t address, rt_uint8_t *buf)
373 {
374 U32 complete;
375 rt_uint8_t temp;
376 rt_uint8_t *ptr = buf;
377 rt_err_t err;
378 #ifdef USE_TIMEOUT
379 rt_uint32_t to = 10;
380 #endif
381
382 int i;
383
384 rt_kprintf("in writeblock:%x\n", address);
385
386 /*for the buf is big-endian we must reverse it*/
387 for (i = 0; i < 0x80; i++)
388 {
389 temp = ptr[0];
390 ptr[0] = ptr[3];
391 ptr[3] = temp;
392
393 temp = ptr[1];
394 ptr[1] = ptr[2];
395 ptr[2] = temp;
396
397 ptr += 4;
398 }
399 //Clear all the errors & interrups
400 *(RP)DMAC_INTINTERRCLR |= 0x1;
401 *(RP)DMAC_INTINTERRCLR &= ~0x1;
402 *(RP)DMAC_INTTCCLEAR |= 0x1;
403 *(RP)DMAC_INTTCCLEAR &= ~0x1;
404
405 *(RP)DMAC_C2SRCADDR = (U32)buf;
406 *(RP)DMAC_C2DESTADDR = SDC_WRITE_BUFER_ACCESS;
407 *(RP)DMAC_C2CONTROL = 0x20149b;
408 *(RP)DMAC_C2CONFIGURATION = 0x380b;
409
410
411 err = cmd_wait(0x6ea, RCA, 0xfff);
412 if (err != RT_EOK)
413 {
414 rt_set_errno(err);
415 return err;
416 }
417
418 err = cmd_wait(0xca, 0x2, 0xfff);
419 if (err != RT_EOK)
420 {
421 rt_set_errno(err);
422 return err;
423 }
424
425 err = cmd_response(0x30e, address, 0X3, 0x0200, 0x1, 0Xfff); //CMD24 1bit mode
426 if (err != RT_EOK)
427 {
428 rt_set_errno(err);
429 return err;
430 }
431
432 complete = *(RP)SDC_INTERRUPT_STATUS;
433
434 if ((complete | 0xfffffffe) != 0xfffffffe)
435 {
436 //printf("CRC ERROR");
437 complete = *(RP)SDC_INTERRUPT_STATUS;
438 }
439
440 while (((*(RP)(DMAC_INTTCSTATUS)) & 0x4) != 0x4)
441 {
442 delay(10);
443 #ifdef USE_TIMEOUT
444 to--;
445 if (!to)
446 {
447 EOUT("%s TIMEOUT\n", __FUNCTION__);
448 }
449 #endif
450 }
451 #ifdef USE_TIMEOUT
452 //DBOUT("%s timeout is %d\n",__FUNCTION__,to);
453 #endif
454
455 return RT_EOK;
456 }
457
458
459 /**
460 * This function will set a hook function, which will be invoked when a memory
461 * block is allocated from heap memory.
462 *
463 * @param hook the hook function
464 */
rt_sdcard_init(rt_device_t dev)465 static rt_err_t rt_sdcard_init(rt_device_t dev)
466 {
467 return 0;
468 }
469
470 /**
471 * This function will set a hook function, which will be invoked when a memory
472 * block is allocated from heap memory.
473 *
474 * @param hook the hook function
475 */
rt_sdcard_open(rt_device_t dev,rt_uint16_t oflag)476 static rt_err_t rt_sdcard_open(rt_device_t dev, rt_uint16_t oflag)
477 {
478 return 0;
479 }
480
481 /**
482 * This function will set a hook function, which will be invoked when a memory
483 * block is allocated from heap memory.
484 *
485 * @param hook the hook function
486 */
rt_sdcard_close(rt_device_t dev)487 static rt_err_t rt_sdcard_close(rt_device_t dev)
488 {
489 return 0;
490 }
491
492 /**
493 * This function will set a hook function, which will be invoked when a memory
494 * block is allocated from heap memory.
495 *
496 * @param hook the hook function
497 */
rt_sdcard_control(rt_device_t dev,int cmd,void * args)498 static rt_err_t rt_sdcard_control(rt_device_t dev, int cmd, void *args)
499 {
500 rt_kprintf("cmd = %d\n", cmd);
501 RT_ASSERT(dev != RT_NULL);
502
503 if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
504 {
505 struct rt_device_blk_geometry *geometry;
506
507 geometry = (struct rt_device_blk_geometry *)args;
508 if (geometry == RT_NULL) return -RT_ERROR;
509
510 geometry->bytes_per_sector = 512;
511 geometry->block_size = 0x200000;
512 //if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
513 // geometry->sector_count = (SDCardInfo.SD_csd.DeviceSize + 1) * 1024;
514 //else
515 geometry->sector_count = 0x200000;//SDCardInfo.CardCapacity/SDCardInfo.CardBlockSize;
516 }
517
518 return RT_EOK;
519 }
520
521 /**
522 * This function will set a hook function, which will be invoked when a memory
523 * block is allocated from heap memory.
524 *
525 * @param hook the hook function
526 */
rt_sdcard_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)527 static rt_ssize_t rt_sdcard_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
528 {
529 rt_uint32_t retry = 3;
530 rt_uint8_t status;
531 rt_uint32_t index;
532
533 struct dfs_partition *part;
534
535 if (dev == RT_NULL)
536 {
537 rt_set_errno(-DFS_STATUS_EINVAL);
538 return 0;
539 }
540
541 part = (struct dfs_partition *)dev->user_data;
542 // take the semaphore
543 rt_sem_take(part->lock, RT_WAITING_FOREVER);
544 while (retry--)
545 {
546 if (((rt_uint32_t)buffer % 4 != 0) ||
547 ((rt_uint32_t)buffer > 0x20080000))
548 {
549 for (index = 0; index < size; index++)
550 {
551 status = sd_readblock((part->offset + pos) * SECTOR_SIZE, ptr_sddev->sec_buf);
552 if (status != RT_EOK)
553 break;
554
555 rt_memcpy((rt_uint8_t *)buffer + (index * SECTOR_SIZE), ptr_sddev->sec_buf, SECTOR_SIZE);
556 }
557 }
558 else
559 {
560 for (index = 0; index < size; index++)
561 {
562 status = sd_readblock((pos) * SECTOR_SIZE, (rt_uint8_t *)buffer + index * SECTOR_SIZE);
563 if (status != RT_EOK)
564 break;
565 }
566 }
567
568 }
569 rt_sem_release(part->lock);
570
571 if (status == RT_EOK)
572 return size;
573
574 rt_kprintf("read failed: %d, buffer 0x%08x\n", status, buffer);
575 return 0;
576
577 }
578
579 /**
580 * This function will set a hook function, which will be invoked when a memory
581 * block is allocated from heap memory.
582 *
583 * @param hook the hook function
584 */
rt_sdcard_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)585 static rt_ssize_t rt_sdcard_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
586 {
587 int i;
588 rt_uint8_t status;
589 struct dfs_partition *part;
590
591 if (dev == RT_NULL)
592 {
593 rt_set_errno(-DFS_STATUS_EINVAL);
594 return 0;
595 }
596
597 part = (struct dfs_partition *)dev->user_data;
598
599 rt_sem_take(part->lock, RT_WAITING_FOREVER);
600
601 if (((rt_uint32_t)buffer % 4 != 0) ||
602 ((rt_uint32_t)buffer > 0x20080000))
603 {
604 rt_uint32_t index;
605
606 for (index = 0; index < size; index++)
607 {
608 rt_memcpy(ptr_sddev->sec_buf, ((rt_uint8_t *)buffer + index * SECTOR_SIZE), SECTOR_SIZE);
609 status = sd_writeblock((part->offset + index + pos) * SECTOR_SIZE, ptr_sddev->sec_buf);
610 }
611 }
612 else
613 {
614
615 for (i = 0; i < size; i++)
616 {
617 status = sd_writeblock((part->offset + i + pos) * SECTOR_SIZE,
618 (rt_uint8_t *)((rt_uint8_t *)buffer + i * SECTOR_SIZE));
619 if (status != RT_EOK) break;
620 }
621 }
622
623 rt_sem_release(part->lock);
624
625 if (status == RT_EOK)
626 return size;
627
628 rt_kprintf("read failed: %d, buffer 0x%08x\n", status, buffer);
629 return 0;
630 }
631
632
rt_hw_sdcard_exit()633 rt_err_t rt_hw_sdcard_exit()
634 {
635 if (ptr_sddev->device != RT_NULL)
636 rt_free(ptr_sddev->device);
637 if (ptr_sddev->part != RT_NULL)
638 rt_free(ptr_sddev->part);
639 if (ptr_sddev != RT_NULL)
640 rt_free(ptr_sddev);
641
642 return RT_EOK;
643 }
644
645 /**
646 * This function will init sd card
647 *
648 * @param void
649 */
rt_hw_sdcard_init()650 rt_err_t rt_hw_sdcard_init()
651 {
652 /*For test*/
653 rt_err_t err;
654 rt_int32_t i;
655
656 char dname[4];
657 char sname[8];
658
659 /*Initialize structure*/
660
661 ptr_sddev = (struct sd_device *)rt_malloc(sizeof(struct sd_device));
662 if (ptr_sddev == RT_NULL)
663 {
664 EOUT("Failed to allocate sdcard device structure\n");
665 return -RT_ENOMEM;
666 }
667
668 /*sdcard intialize*/
669 err = sd_init();
670 if (err != RT_EOK)
671 goto FAIL2;
672
673 /*set sector buffer*/
674 ptr_sddev->sec_buf = gsec_buf;
675 ptr_sddev->buf_size = SECTOR_SIZE;
676 ptr_sddev->sdc = (struct sd_c *)SD_BASE;
677
678 //DBOUT("allocate partition sector buffer OK!");
679
680 err = sd_readblock(0, ptr_sddev->sec_buf);
681 if (err != RT_EOK)
682 {
683 EOUT("read first block error\n");
684 goto FAIL2;
685 }
686
687 /*sdcard driver initialize*/
688 ptr_sddev->part = (struct dfs_partition *)rt_malloc(4 * sizeof(struct dfs_partition));
689 if (ptr_sddev->part == RT_NULL)
690 {
691 EOUT("allocate partition failed\n");
692 err = -RT_ENOMEM;
693 goto FAIL2;
694 }
695
696 /*alloc device buffer*/
697 ptr_sddev->device = (struct rt_device *)rt_malloc(4 * sizeof(struct rt_device));
698 if (ptr_sddev->device == RT_NULL)
699 {
700 EOUT("allocate device failed\n");
701 err = -RT_ENOMEM;
702 goto FAIL1;
703 }
704
705 ptr_sddev->part_num = 0;
706
707 err = sd_readblock(0, ptr_sddev->sec_buf);
708
709 if (err != RT_EOK)
710 {
711 EOUT("Read block 0 to initialize ERROR\n");
712 goto FAIL1;
713 }
714
715 for (i = 0; i < 4; i++)
716 {
717 /* get the first partition */
718 err = dfs_filesystem_get_partition(&(ptr_sddev->part[i]), ptr_sddev->sec_buf, i);
719 if (err == RT_EOK)
720 {
721 rt_snprintf(dname, 4, "sd%d", i);
722 rt_snprintf(sname, 8, "sem_sd%d", i);
723 ptr_sddev->part[i].lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO);
724
725 /* register sdcard device */
726 ptr_sddev->device[i].init = rt_sdcard_init;
727 ptr_sddev->device[i].open = rt_sdcard_open;
728 ptr_sddev->device[i].close = rt_sdcard_close;
729 ptr_sddev->device[i].read = rt_sdcard_read;
730 ptr_sddev->device[i].write = rt_sdcard_write;
731 ptr_sddev->device[i].control = rt_sdcard_control;
732 ptr_sddev->device[i].user_data = &ptr_sddev->part[i];
733
734 err = rt_device_register(&ptr_sddev->device[i], dname,
735 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
736
737 if (err == RT_EOK)
738 ptr_sddev->part_num++;
739 }
740 else
741 {
742 if (i == 0)
743 {
744 /* there is no partition table */
745 ptr_sddev->part[0].offset = 0;
746 ptr_sddev->part[0].size = 0;
747 ptr_sddev->part[0].lock = rt_sem_create("sem_sd0", 1, RT_IPC_FLAG_FIFO);
748
749 /* register sdcard device */
750 ptr_sddev->device[0].init = rt_sdcard_init;
751 ptr_sddev->device[0].open = rt_sdcard_open;
752 ptr_sddev->device[0].close = rt_sdcard_close;
753 ptr_sddev->device[0].read = rt_sdcard_read;
754 ptr_sddev->device[0].write = rt_sdcard_write;
755 ptr_sddev->device[0].control = rt_sdcard_control;
756 ptr_sddev->device[0].user_data = &ptr_sddev->part[0];
757
758 err = rt_device_register(&ptr_sddev->device[0], "sd0",
759 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
760
761 if (err == RT_EOK)
762 ptr_sddev->part_num++;
763
764 break;
765 }
766 }
767 }
768
769 if (ptr_sddev->part_num == 0)
770 goto FAIL0;
771
772 return err;
773
774 FAIL0:
775 rt_free(ptr_sddev->device);
776 ptr_sddev->device = RT_NULL;
777
778 FAIL1:
779 rt_free(ptr_sddev->part);
780 ptr_sddev->part = RT_NULL;
781
782 FAIL2:
783 rt_free(ptr_sddev);
784 ptr_sddev = RT_NULL;
785
786 return err;
787 }
788
789 #endif
790