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