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  * 2020-11-24     WangHuachen  the first version
9  */
10 #include <rthw.h>
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include <dfs_fs.h>
14 #include <drivers/dev_mmcsd_core.h>
15 
16 #include <stdint.h>
17 #include <stdio.h>
18 
19 #include "drv_sdcard.h"
20 #include "xsdps_core.h"
21 
22 #define DBG_TAG "drv.sdcard"
23 #define DBG_LVL DBG_INFO
24 #include "rtdbg.h"
25 
26 #define FILE_SYSTEM_INTERFACE_SD
27 #define SD_CD_DELAY 10000U
28 
29 typedef rt_uint8_t BYTE;
30 typedef rt_uint32_t DWORD;
31 typedef unsigned int UINT;
32 
33 /* Status of Disk Functions */
34 typedef rt_uint8_t DSTATUS;
35 
36 /* Results of Disk Functions */
37 typedef enum
38 {
39     RES_OK = 0, /* 0: Successful */
40     RES_ERROR,  /* 1: R/W Error */
41     RES_WRPRT,  /* 2: Write Protected */
42     RES_NOTRDY, /* 3: Not Ready */
43     RES_PARERR  /* 4: Invalid Parameter */
44 } DRESULT;
45 
46 /* Disk Status Bits (DSTATUS) */
47 
48 #define STA_NOINIT 0x01  /* Drive not initialized */
49 #define STA_NODISK 0x02  /* No medium in the drive */
50 #define STA_PROTECT 0x04 /* Write protected */
51 
52 static DSTATUS Stat[2] = {STA_NOINIT, STA_NOINIT}; /* Disk status */
53 
54 #ifdef FILE_SYSTEM_INTERFACE_SD
55 static XSdPs SdInstance[2];
56 static u32 BaseAddress;
57 static u32 CardDetect;
58 static u32 WriteProtect;
59 static u32 SlotType[2];
60 static u8 HostCntrlrVer[2];
61 #endif
62 
63 static BYTE sdcard_drvnum = 0;
64 static struct rt_device sdcard_device;
65 static struct dfs_partition part;
66 static struct rt_mutex sd_lock[2];
67 
disk_status(BYTE pdrv)68 static DSTATUS disk_status(
69     BYTE pdrv /* Drive number (0) */
70 )
71 {
72     DSTATUS s = Stat[pdrv];
73 #ifdef FILE_SYSTEM_INTERFACE_SD
74     u32 StatusReg;
75     u32 DelayCount = 0;
76 
77     if (SdInstance[pdrv].Config.BaseAddress == (u32)0)
78     {
79 #ifdef XPAR_XSDPS_1_DEVICE_ID
80         if (pdrv == 1)
81         {
82             BaseAddress = XPAR_XSDPS_1_BASEADDR;
83             CardDetect = XPAR_XSDPS_1_HAS_CD;
84             WriteProtect = XPAR_XSDPS_1_HAS_WP;
85         }
86         else
87         {
88 #endif
89             BaseAddress = XPAR_XSDPS_0_BASEADDR;
90             CardDetect = XPAR_XSDPS_0_HAS_CD;
91             WriteProtect = XPAR_XSDPS_0_HAS_WP;
92 #ifdef XPAR_XSDPS_1_DEVICE_ID
93         }
94 #endif
95         HostCntrlrVer[pdrv] = (u8)(XSdPs_ReadReg16(BaseAddress,
96                                                    XSDPS_HOST_CTRL_VER_OFFSET) &
97                                    XSDPS_HC_SPEC_VER_MASK);
98         if (HostCntrlrVer[pdrv] == XSDPS_HC_SPEC_V3)
99         {
100             SlotType[pdrv] = XSdPs_ReadReg(BaseAddress,
101                                            XSDPS_CAPS_OFFSET) &
102                              XSDPS_CAPS_SLOT_TYPE_MASK;
103         }
104         else
105         {
106             SlotType[pdrv] = 0;
107         }
108     }
109 
110     /* If SD is not powered up then mark it as not initialized */
111     if ((XSdPs_ReadReg8((u32)BaseAddress, XSDPS_POWER_CTRL_OFFSET) &
112          XSDPS_PC_BUS_PWR_MASK) == 0U)
113     {
114         s |= STA_NOINIT;
115     }
116 
117     StatusReg = XSdPs_GetPresentStatusReg((u32)BaseAddress);
118     if (SlotType[pdrv] != XSDPS_CAPS_EMB_SLOT)
119     {
120         if (CardDetect)
121         {
122             while ((StatusReg & XSDPS_PSR_CARD_INSRT_MASK) == 0U)
123             {
124                 if (DelayCount == 500U)
125                 {
126                     s = STA_NODISK | STA_NOINIT;
127                     goto Label;
128                 }
129                 else
130                 {
131                     /* Wait for 10 msec */
132                     usleep(SD_CD_DELAY);
133                     DelayCount++;
134                     StatusReg = XSdPs_GetPresentStatusReg((u32)BaseAddress);
135                 }
136             }
137         }
138         s &= ~STA_NODISK;
139         if (WriteProtect)
140         {
141             if ((StatusReg & XSDPS_PSR_WPS_PL_MASK) == 0U)
142             {
143                 s |= STA_PROTECT;
144                 goto Label;
145             }
146         }
147         s &= ~STA_PROTECT;
148     }
149     else
150     {
151         s &= ~STA_NODISK & ~STA_PROTECT;
152     }
153 
154 Label:
155     Stat[pdrv] = s;
156 #endif
157 
158     return s;
159 }
160 
disk_initialize(BYTE pdrv)161 static DSTATUS disk_initialize(
162     BYTE pdrv /* Physical drive number (0) */
163 )
164 {
165     DSTATUS s;
166 #ifdef FILE_SYSTEM_INTERFACE_SD
167     s32 Status = XST_FAILURE;
168     XSdPs_Config *SdConfig;
169 #endif
170 
171     s = disk_status(pdrv);
172     if ((s & STA_NODISK) != 0U)
173     {
174         return s;
175     }
176 
177     /* If disk is already initialized */
178     if ((s & STA_NOINIT) == 0U)
179     {
180         return s;
181     }
182 
183 #ifdef FILE_SYSTEM_INTERFACE_SD
184     if (CardDetect)
185     {
186         /*
187              * Card detection check
188              * If the HC detects the No Card State, power will be cleared
189              */
190         while (!((XSDPS_PSR_CARD_DPL_MASK |
191                   XSDPS_PSR_CARD_STABLE_MASK |
192                   XSDPS_PSR_CARD_INSRT_MASK) ==
193                  (XSdPs_GetPresentStatusReg((u32)BaseAddress) &
194                   (XSDPS_PSR_CARD_DPL_MASK |
195                    XSDPS_PSR_CARD_STABLE_MASK |
196                    XSDPS_PSR_CARD_INSRT_MASK))))
197             ;
198     }
199 
200     /*
201      * Initialize the host controller
202      */
203     SdConfig = XSdPs_LookupConfig((u16)pdrv);
204     if (NULL == SdConfig)
205     {
206         s |= STA_NOINIT;
207         return s;
208     }
209 
210     Status = XSdPs_CfgInitialize(&SdInstance[pdrv], SdConfig,
211                                  SdConfig->BaseAddress);
212     if (Status != XST_SUCCESS)
213     {
214         s |= STA_NOINIT;
215         return s;
216     }
217 
218     Status = XSdPs_CardInitialize(&SdInstance[pdrv]);
219     if (Status != XST_SUCCESS)
220     {
221         s |= STA_NOINIT;
222         return s;
223     }
224 
225     /*
226      * Disk is initialized.
227      * Store the same in Stat.
228      */
229     s &= (~STA_NOINIT);
230 
231     Stat[pdrv] = s;
232 #endif
233 
234 #ifdef FILE_SYSTEM_INTERFACE_RAM
235     /* Assign RAMFS address value from xparameters.h */
236     dataramfs = (char *)RAMFS_START_ADDR;
237 
238     /* Clearing No init Status for RAM */
239     s &= (~STA_NOINIT);
240     Stat[pdrv] = s;
241 #endif
242 
243     return s;
244 }
245 
disk_read(BYTE pdrv,BYTE * buff,DWORD sector,UINT count)246 static DRESULT disk_read(
247     BYTE pdrv,    /* Physical drive number (0) */
248     BYTE *buff,   /* Pointer to the data buffer to store read data */
249     DWORD sector, /* Start sector number (LBA) */
250     UINT count    /* Sector count (1..128) */
251 )
252 {
253     DSTATUS s;
254 #ifdef FILE_SYSTEM_INTERFACE_SD
255     s32 Status = XST_FAILURE;
256     DWORD LocSector = sector;
257 #endif
258 
259     s = disk_status(pdrv);
260 
261     if ((s & STA_NOINIT) != 0U)
262     {
263         return RES_NOTRDY;
264     }
265     if (count == 0U)
266     {
267         return RES_PARERR;
268     }
269 
270 #ifdef FILE_SYSTEM_INTERFACE_SD
271     /* Convert LBA to byte address if needed */
272     if ((SdInstance[pdrv].HCS) == 0U)
273     {
274         LocSector *= (DWORD)XSDPS_BLK_SIZE_512_MASK;
275     }
276 
277     Status = XSdPs_ReadPolled(&SdInstance[pdrv], (u32)LocSector, count, buff);
278     if (Status != XST_SUCCESS)
279     {
280         return RES_ERROR;
281     }
282 #endif
283 
284 #ifdef FILE_SYSTEM_INTERFACE_RAM
285     memcpy(buff, dataramfs + (sector * SECTORSIZE), count * SECTORSIZE);
286 #endif
287 
288     return RES_OK;
289 }
290 
disk_write(BYTE pdrv,const BYTE * buff,DWORD sector,UINT count)291 static DRESULT disk_write(
292     BYTE pdrv,        /* Physical drive nmuber (0..) */
293     const BYTE *buff, /* Data to be written */
294     DWORD sector,     /* Sector address (LBA) */
295     UINT count        /* Number of sectors to write (1..128) */
296 )
297 {
298     DSTATUS s;
299 #ifdef FILE_SYSTEM_INTERFACE_SD
300     s32 Status = XST_FAILURE;
301     DWORD LocSector = sector;
302 #endif
303 
304     s = disk_status(pdrv);
305     if ((s & STA_NOINIT) != 0U)
306     {
307         return RES_NOTRDY;
308     }
309     if (count == 0U)
310     {
311         return RES_PARERR;
312     }
313 
314 #ifdef FILE_SYSTEM_INTERFACE_SD
315     /* Convert LBA to byte address if needed */
316     if ((SdInstance[pdrv].HCS) == 0U)
317     {
318         LocSector *= (DWORD)XSDPS_BLK_SIZE_512_MASK;
319     }
320 
321     Status = XSdPs_WritePolled(&SdInstance[pdrv], (u32)LocSector, count, buff);
322     if (Status != XST_SUCCESS)
323     {
324         return RES_ERROR;
325     }
326 
327 #endif
328 
329 #ifdef FILE_SYSTEM_INTERFACE_RAM
330     memcpy(dataramfs + (sector * SECTORSIZE), buff, count * SECTORSIZE);
331 #endif
332 
333     return RES_OK;
334 }
335 
rt_sdcard_init(rt_device_t dev)336 static rt_err_t rt_sdcard_init(rt_device_t dev)
337 {
338     char sdlock_name[20];
339     BYTE drvnum = *((BYTE *)dev->user_data);
340 
341     rt_snprintf(sdlock_name, sizeof(sdlock_name), "sdlock%d", drvnum);
342     if (rt_mutex_init(&sd_lock[drvnum], sdlock_name, RT_IPC_FLAG_PRIO) != RT_EOK)
343     {
344         LOG_E("init sdlock semaphore failed\n");
345     }
346     else
347         LOG_D("sdcard init OK\n");
348 
349     return RT_EOK;
350 }
351 
rt_sdcard_open(rt_device_t dev,rt_uint16_t oflag)352 static rt_err_t rt_sdcard_open(rt_device_t dev, rt_uint16_t oflag)
353 {
354     return RT_EOK;
355 }
356 
rt_sdcard_close(rt_device_t dev)357 static rt_err_t rt_sdcard_close(rt_device_t dev)
358 {
359     return RT_EOK;
360 }
361 
rt_sdcard_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)362 static rt_ssize_t rt_sdcard_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
363 {
364     RT_ASSERT(((rt_uint32_t)buffer % 4) == 0);
365     DRESULT status;
366     BYTE drvnum = *((BYTE *)dev->user_data);
367 
368     rt_mutex_take(&sd_lock[drvnum], RT_WAITING_FOREVER);
369     status = disk_read(drvnum, buffer, part.offset + pos, size);
370     rt_mutex_release(&sd_lock[drvnum]);
371 
372     if (status == RES_OK)
373         return size;
374 
375     LOG_E("sdcard read failed\n");
376     return 0;
377 }
378 
rt_sdcard_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)379 static rt_ssize_t rt_sdcard_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
380 {
381     RT_ASSERT(((rt_uint32_t)buffer % 4) == 0);
382     DRESULT status;
383     BYTE drvnum = *((BYTE *)dev->user_data);
384 
385     rt_mutex_take(&sd_lock[drvnum], RT_WAITING_FOREVER);
386     status = disk_write(drvnum, buffer, part.offset + pos, size);
387     rt_mutex_release(&sd_lock[drvnum]);
388 
389     if (status == RES_OK)
390         return size;
391 
392     LOG_E("sdcard write failed\n");
393     return 0;
394 }
395 
rt_sdcard_control(rt_device_t dev,int cmd,void * args)396 static rt_err_t rt_sdcard_control(rt_device_t dev, int cmd, void *args)
397 {
398     RT_ASSERT(dev != RT_NULL);
399 
400     BYTE drvnum = *((BYTE *)dev->user_data);
401 
402     if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
403     {
404         struct rt_device_blk_geometry *geometry;
405 
406         geometry = (struct rt_device_blk_geometry *)args;
407         if (geometry == RT_NULL)
408             return -RT_ERROR;
409 
410         geometry->bytes_per_sector = 512;
411         geometry->block_size = 128;
412         geometry->sector_count = SdInstance[drvnum].SectorCount;
413     }
414 
415     return RT_EOK;
416 }
417 
418 #ifdef BSP_USING_SD0
rh_hw_emmc_init(void)419 static int rh_hw_emmc_init(void)
420 {
421     if (disk_initialize(sdcard_drvnum) == RES_OK)
422     {
423         DRESULT status;
424         rt_uint8_t *sector;
425 
426         /* get the first sector to read partition table */
427         sector = (rt_uint8_t *)rt_malloc(512);
428         if (sector == RT_NULL)
429         {
430             LOG_E("allocate partition sector buffer failed\n");
431             return -RT_ERROR;
432         }
433         status = disk_read(0, sector, 0, 1);
434         if (status == RES_OK)
435         {
436             /* get the first partition */
437             if (dfs_filesystem_get_partition(&part, sector, 0) != 0)
438             {
439                 /* there is no partition */
440                 part.offset = 0;
441                 part.size = 0;
442             }
443         }
444         else
445         {
446             /* there is no partition table */
447             part.offset = 0;
448             part.size = 0;
449         }
450 
451         /* release sector buffer */
452         rt_free(sector);
453 
454         /* register sdcard device */
455         sdcard_device.type = RT_Device_Class_Block;
456         sdcard_device.init = rt_sdcard_init;
457         sdcard_device.open = rt_sdcard_open;
458         sdcard_device.close = rt_sdcard_close;
459         sdcard_device.read = rt_sdcard_read;
460         sdcard_device.write = rt_sdcard_write;
461         sdcard_device.control = rt_sdcard_control;
462 
463         /* no private */
464         sdcard_device.user_data = &sdcard_drvnum;
465         rt_device_register(&sdcard_device, "sd0", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
466         return RT_EOK;
467     }
468 
469     return -RT_ERROR;
470 }
471 INIT_DEVICE_EXPORT(rh_hw_emmc_init);
472 #endif
473