|
@@ -8,19 +8,26 @@
|
|
|
* http://www.rt-thread.org/license/LICENSE
|
|
|
*
|
|
|
* Change Logs:
|
|
|
- * Date Author Notes
|
|
|
- * 2007-12-02 Yi.Qiu the first version
|
|
|
- * 2010-01-01 Bernard Modify for mini2440
|
|
|
- * 2012-12-15 amr168 support SDHC
|
|
|
+ * Date Author Notes
|
|
|
+ * 2007-12-02 Yi.Qiu the first version
|
|
|
+ * 2010-01-01 Bernard Modify for mini2440
|
|
|
+ * 2012-12-15 amr168 support SDHC
|
|
|
+ * 2017-11-20 kuangdazzidd add csd cmd support
|
|
|
*/
|
|
|
|
|
|
#include "sdcard.h"
|
|
|
+#include "rtdef.h"
|
|
|
|
|
|
-extern rt_uint32_t PCLK;
|
|
|
-volatile rt_uint32_t rd_cnt;
|
|
|
-volatile rt_uint32_t wt_cnt;
|
|
|
-volatile rt_int32_t RCA;
|
|
|
-volatile rt_int32_t sd_type;
|
|
|
+extern rt_uint32_t PCLK;
|
|
|
+volatile rt_uint32_t rd_cnt;
|
|
|
+volatile rt_uint32_t wt_cnt;
|
|
|
+volatile rt_int32_t RCA;
|
|
|
+volatile rt_int32_t sd_type;
|
|
|
+
|
|
|
+struct sd_csd {
|
|
|
+ rt_uint16_t bsize;
|
|
|
+ rt_uint32_t nblks;
|
|
|
+}g_sd_csd;
|
|
|
|
|
|
static void sd_delay(rt_uint32_t ms)
|
|
|
{
|
|
@@ -118,9 +125,25 @@ static int sd_cmd55(void)
|
|
|
|
|
|
SDICSTA = 0xa00;
|
|
|
|
|
|
+
|
|
|
return RT_EOK;
|
|
|
}
|
|
|
|
|
|
+static int sd_cmd9(void *p_rsp)
|
|
|
+{
|
|
|
+SDICARG = RCA << 16;
|
|
|
+SDICCON = (1 << 10) | (1 << 9) | (0x1<<8) | (0x40 | 0x09);
|
|
|
+
|
|
|
+sd_cmd_end(9, 1);
|
|
|
+
|
|
|
+ ((rt_uint32_t *)p_rsp)[0] = SDIRSP3;
|
|
|
+ ((rt_uint32_t *)p_rsp)[1] = SDIRSP2;
|
|
|
+ ((rt_uint32_t *)p_rsp)[2] = SDIRSP1;
|
|
|
+ ((rt_uint32_t *)p_rsp)[3] = SDIRSP0;
|
|
|
+
|
|
|
+return RT_EOK;
|
|
|
+}
|
|
|
+
|
|
|
static void sd_sel_desel(char sel_desel)
|
|
|
{
|
|
|
if (sel_desel)
|
|
@@ -161,6 +184,75 @@ static void sd_setbus(void)
|
|
|
SDICSTA=0xa00; /* Clear cmd_end(with rsp) */
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+static rt_uint32_t bits_str (rt_uint32_t *str, rt_uint32_t start, rt_uint8_t len)
|
|
|
+{
|
|
|
+ rt_uint32_t mask;
|
|
|
+ rt_uint32_t index;
|
|
|
+ rt_uint8_t shift;
|
|
|
+ rt_uint32_t value;
|
|
|
+
|
|
|
+ mask = (int)((len < 32) ? (1 << len) : 0) - 1;
|
|
|
+ index = start / 32;
|
|
|
+ shift = start & 31;
|
|
|
+ value = str[index] >> shift;
|
|
|
+
|
|
|
+ if ((len + shift) > 32) {
|
|
|
+ value |= str[index + 1] << (32 - shift);
|
|
|
+ }
|
|
|
+ value &= mask;
|
|
|
+ return value;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static int sd_decode_csd (rt_uint32_t *p_csd)
|
|
|
+{
|
|
|
+ rt_uint32_t e, m, r;
|
|
|
+ rt_uint8_t structure;
|
|
|
+
|
|
|
+ structure = bits_str(p_csd, 126, 2);
|
|
|
+
|
|
|
+ switch (structure) {
|
|
|
+ case 0:
|
|
|
+ m = bits_str(p_csd, 99, 4);
|
|
|
+ e = bits_str(p_csd, 96, 3);
|
|
|
+ g_sd_csd.bsize = 512;
|
|
|
+ m = bits_str(p_csd, 62, 12);
|
|
|
+ e = bits_str(p_csd, 47, 3);
|
|
|
+ r = bits_str(p_csd, 80, 4);
|
|
|
+ g_sd_csd.nblks = ((1 + m) << (e + r - 7));
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 1:
|
|
|
+ m = bits_str(p_csd, 99, 4);
|
|
|
+ e = bits_str(p_csd, 96, 3);
|
|
|
+ g_sd_csd.bsize = 512;
|
|
|
+ m = bits_str(p_csd, 48, 22);
|
|
|
+ g_sd_csd.nblks = (1 + m) << 10;
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ return RT_ERROR;
|
|
|
+ }
|
|
|
+ return RT_EOK;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static int sd_send_csd(rt_uint32_t *p_csd)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+ rt_uint32_t rsp[4];
|
|
|
+
|
|
|
+ ret = sd_cmd9((void*)&rsp);
|
|
|
+
|
|
|
+ if (ret != 0) {
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ rt_memcpy((void*)p_csd, (void*)rsp, 16);
|
|
|
+ return RT_EOK;
|
|
|
+}
|
|
|
+
|
|
|
static int sd_ocr(void)
|
|
|
{
|
|
|
int i, ver=0;
|
|
@@ -213,7 +305,8 @@ rt_err_t sd_cmd8(void)
|
|
|
static rt_uint8_t sd_init(void)
|
|
|
{
|
|
|
//-- SD controller & card initialize
|
|
|
- int i;
|
|
|
+ int i;
|
|
|
+ rt_uint32_t csd[4];
|
|
|
/* Important notice for MMC test condition */
|
|
|
/* Cmd & Data lines must be enabled by pull up resister */
|
|
|
SDIPRE = PCLK / (INICLK) - 1;
|
|
@@ -256,6 +349,9 @@ RECMD3:
|
|
|
goto RECMD3;
|
|
|
SDICSTA=0xa00; /* Clear cmd_end(with rsp) */
|
|
|
|
|
|
+ sd_send_csd(csd);
|
|
|
+ sd_decode_csd(csd);
|
|
|
+
|
|
|
RCA = (SDIRSP0 & 0xffff0000) >> 16;
|
|
|
SDIPRE = PCLK / (SDCLK) - 1; /* Normal clock=25MHz */
|
|
|
if (SDIRSP0 & 0x1e00 != 0x600)
|
|
@@ -385,6 +481,10 @@ static rt_err_t rt_sdcard_close(rt_device_t dev)
|
|
|
|
|
|
static rt_err_t rt_sdcard_control(rt_device_t dev, int cmd, void *args)
|
|
|
{
|
|
|
+struct rt_device_blk_geometry *p_geometry = (struct rt_device_blk_geometry *)args;
|
|
|
+p_geometry->block_size = g_sd_csd.bsize;
|
|
|
+p_geometry->sector_count = g_sd_csd.nblks;
|
|
|
+p_geometry->bytes_per_sector = 512;
|
|
|
return RT_EOK;
|
|
|
}
|
|
|
|