support SDHC in mini2440

contributed by amr168

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2498 bbd45198-f89e-11dd-88c7-29a3b14d5316
This commit is contained in:
dzzxzz@gmail.com 2012-12-19 03:56:11 +00:00
parent bcc4893d23
commit 7672426550

View File

@ -11,6 +11,7 @@
* Date Author Notes
* 2007-12-02 Yi.Qiu the first version
* 2010-01-01 Bernard Modify for mini2440
* 2012-12-15 amr168 support SDHC
*/
#include "sdcard.h"
@ -19,6 +20,7 @@ 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;
static void sd_delay(rt_uint32_t ms)
{
@ -53,7 +55,7 @@ static int sd_cmd_end(int cmd, int be_resp)
if ((finish0 & 0xf00) != 0xa00)
{
SDICSTA = finish0;
if(((finish0&0x400)==0x400))
if ((finish0&0x400) == 0x400)
return RT_ERROR;
}
SDICSTA = finish0;
@ -62,12 +64,9 @@ static int sd_cmd_end(int cmd, int be_resp)
{
if ((finish0 & 0x1f00) != 0xa00)
{
/*
rt_kprintf("CMD%d:SDICSTA=0x%x, SDIRSP0=0x%x\n",
cmd, SDICSTA, SDIRSP0);
*/
/* rt_kprintf("CMD%d:SDICSTA=0x%x, SDIRSP0=0x%x\n", cmd, SDICSTA, SDIRSP0); */
SDICSTA = finish0;
if(((finish0&0x400)==0x400))
if ((finish0 & 0x400) == 0x400)
return RT_ERROR;
}
SDICSTA = finish0;
@ -90,8 +89,10 @@ static int sd_data_end(void)
if ((finish & 0xfc) != 0x10)
{
SDIDSTA = 0xec;
return RT_ERROR;
}
return RT_EOK;
}
@ -116,6 +117,7 @@ static int sd_cmd55(void)
}
SDICSTA = 0xa00;
return RT_EOK;
}
@ -161,28 +163,50 @@ static void sd_setbus(void)
static int sd_ocr(void)
{
int i;
int i, ver=0;
/* Negotiate operating condition for SD, it makes card ready state */
for (i = 0; i < 50; i ++)
{
sd_cmd55();
SDICARG=0xff8000;
SDICARG = 0x40ff8000; /* HCS=1, compatible v1.x and v2.0 */
SDICCON = (0x1<<9) | (0x1<<8) | 0x69;
/* if using real board, should replace code here. need to modify qemu in near future*/
/* Check end of ACMD41 */
if( (sd_cmd_end(41, 1)==RT_EOK) & SDIRSP0==0x80ff8000 )
if (sd_cmd_end(41, 1) == RT_EOK)
{
SDICSTA=0xa00;
return RT_EOK;
if (SDIRSP0 == 0x80ff8000)
{
ver = 1; /* SD V1.x, CCS=0 */
break;
}
else if (SDIRSP0 == 0xc0ff8000)
{
ver = 2; /* SD V2.0, CCS=1 */
break;
}
}
sd_delay(200);
}
SDICSTA = 0xa00;
return ver;
}
rt_err_t sd_cmd8(void)
{
SDICARG = 0x000001AA;
SDICCON = (0x1<<9) | (0x1<<8) | 0x48; //sht_resp, wait_resp, start
if (sd_cmd_end(8, 1) == RT_ERROR)
return RT_ERROR;
SDICSTA = 0xa00;
if ((SDIRSP0&0x1aa) == 0x1aa)
return RT_EOK;
else
return RT_ERROR;
}
@ -202,15 +226,18 @@ static rt_uint8_t sd_init(void)
for (i = 0; i < 0x1000; i ++);
sd_cmd0();
sd_cmd8(); /* Must be use it, Host shall supports high capacity */
/* Check SD card OCR */
if(sd_ocr() == RT_EOK)
sd_type = sd_ocr();
if (sd_type > 0)
{
rt_kprintf("In SD ready\n");
}
else
{
rt_kprintf("Initialize fail\nNo Card assertion\n");
return RT_ERROR;
}
@ -280,6 +307,7 @@ RERDCMD:
if (sd_data_end() == RT_ERROR)
{
rt_kprintf("Dat error\n");
return RT_ERROR;
}
@ -296,6 +324,7 @@ static rt_uint8_t sd_writeblock(rt_uint32_t address, rt_uint8_t* buf)
wt_cnt = 0;
SDIFSTA = SDIFSTA | (1 << 16);
SDIDCON = (2 << 22) | (1 << 20) | (1 << 17) | (1 << 16) | (1 << 14) | (3 << 12) | (1 << 0);
SDICARG = address;
@ -307,7 +336,7 @@ REWTCMD:
SDICSTA = 0xa00;
while(wt_cnt < 128*1)
while (wt_cnt < 128)
{
status = SDIFSTA;
if ((status & 0x2000) == 0x2000)
@ -321,6 +350,7 @@ REWTCMD:
if (sd_data_end() == RT_ERROR)
{
rt_kprintf("Data Error\n");
return RT_ERROR;
}
SDIDCON = SDIDCON &~ (7<<12);
@ -358,14 +388,18 @@ static rt_err_t rt_sdcard_control(rt_device_t dev, rt_uint8_t cmd, void *args)
return RT_EOK;
}
static rt_size_t rt_sdcard_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
static rt_size_t rt_sdcard_read(rt_device_t dev,
rt_off_t pos,
void *buffer,
rt_size_t size)
{
int i;
int i, addr;
struct dfs_partition *part = (struct dfs_partition *)dev->user_data;
if (dev == RT_NULL)
{
rt_set_errno(-DFS_STATUS_EINVAL);
return 0;
}
@ -373,8 +407,11 @@ static rt_size_t rt_sdcard_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_
for (i = 0; i < size; i ++)
{
rt_sem_take(part->lock, RT_WAITING_FOREVER);
sd_readblock((part->offset + i + pos)*SECTOR_SIZE,
(rt_uint8_t*)((rt_uint8_t*)buffer + i * SECTOR_SIZE));
if (sd_type == 1)
addr = (part->offset + i + pos)*SECTOR_SIZE;
else
addr = (part->offset + i + pos);
sd_readblock(addr, (rt_uint8_t *)((rt_uint8_t *)buffer + i * SECTOR_SIZE));
rt_sem_release(part->lock);
}
@ -382,14 +419,18 @@ static rt_size_t rt_sdcard_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_
return size;
}
static rt_size_t rt_sdcard_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
static rt_size_t rt_sdcard_write(rt_device_t dev,
rt_off_t pos,
const void *buffer,
rt_size_t size)
{
int i;
int i, addr;
struct dfs_partition *part = (struct dfs_partition *)dev->user_data;
if (dev == RT_NULL)
{
rt_set_errno(-DFS_STATUS_EINVAL);
return 0;
}
@ -397,8 +438,11 @@ static rt_size_t rt_sdcard_write (rt_device_t dev, rt_off_t pos, const void* buf
for (i = 0; i < size; i++)
{
rt_sem_take(part->lock, RT_WAITING_FOREVER);
sd_writeblock((part->offset + i + pos)*SECTOR_SIZE,
(rt_uint8_t*)((rt_uint8_t*)buffer + i * SECTOR_SIZE));
if (sd_type == 1)
addr = (part->offset + i + pos)*SECTOR_SIZE;
else
addr = (part->offset + i + pos);
sd_writeblock(addr, (rt_uint8_t*)((rt_uint8_t*)buffer + i * SECTOR_SIZE));
rt_sem_release(part->lock);
}
@ -429,6 +473,7 @@ void rt_hw_sdcard_init(void)
if (sector == RT_NULL)
{
rt_kprintf("allocate partition sector buffer failed\n");
return;
}
status = sd_readblock(0, sector);