diff --git a/bsp/mini2440/sdcard.c b/bsp/mini2440/sdcard.c index 1cf9a122c451d9ce73cc38c6c11b836cfa907fb5..e75e983801a5aab80e227134e1f7a905836ce44a 100644 --- a/bsp/mini2440/sdcard.c +++ b/bsp/mini2440/sdcard.c @@ -1,503 +1,548 @@ -/* - * File : sd.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006, 2007, RT-Thread Develop Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * 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 - */ - -#include "sdcard.h" - -extern rt_uint32_t PCLK; -volatile rt_uint32_t rd_cnt; -volatile rt_uint32_t wt_cnt; -volatile rt_int32_t RCA; - -static void sd_delay(rt_uint32_t ms) -{ - ms *= 7326; - while(--ms); -} - -static int sd_cmd_end(int cmd, int be_resp) -{ - int finish0; - - if(!be_resp) - { - finish0=SDICSTA; - - while((finish0&0x800)!=0x800) - finish0=SDICSTA; - - SDICSTA=finish0; - - return RT_EOK; - } - else - { - finish0=SDICSTA; - - while( !( ((finish0&0x200)==0x200) | ((finish0&0x400)==0x400) )) - finish0=SDICSTA; - - if(cmd==1 || cmd==41) - { - if( (finish0&0xf00) != 0xa00 ) - { - SDICSTA=finish0; - if(((finish0&0x400)==0x400)) - return RT_ERROR; - } - SDICSTA=finish0; - } - else - { - if( (finish0&0x1f00) != 0xa00 ) - { - /* - rt_kprintf("CMD%d:SDICSTA=0x%x, SDIRSP0=0x%x\n", - cmd, SDICSTA, SDIRSP0); - */ - SDICSTA=finish0; - if(((finish0&0x400)==0x400)) - return RT_ERROR; - } - SDICSTA=finish0; - } - return RT_EOK; - } -} - -static int sd_data_end(void) -{ - int finish; - - finish=SDIDSTA; - - while( !( ((finish&0x10)==0x10) | ((finish&0x20)==0x20) )) - { - finish=SDIDSTA; - } - - if( (finish&0xfc) != 0x10 ) - { - SDIDSTA=0xec; - return RT_ERROR; - } - return RT_EOK; -} - -static void sd_cmd0(void) -{ - SDICARG=0x0; - SDICCON=(1<<8)|0x40; - - sd_cmd_end(0, 0); - SDICSTA=0x800; /* Clear cmd_end(no rsp) */ -} - -static int sd_cmd55(void) -{ - SDICARG = RCA << 16; - SDICCON = (0x1 << 9) | (0x1 << 8) | 0x77; - - if(sd_cmd_end(55, 1) == RT_ERROR) - { - /* rt_kprintf("CMD55 error\n"); */ - return RT_ERROR; - } - - SDICSTA=0xa00; - return RT_EOK; -} - -static void sd_sel_desel(char sel_desel) -{ - if(sel_desel) - { -RECMDS7: - SDICARG =RCA << 16; - SDICCON = (0x1 << 9) | (0x1 << 8) | 0x47; - if(sd_cmd_end(7, 1) == RT_ERROR) - goto RECMDS7; - - SDICSTA = 0xa00; - - if(SDIRSP0 & 0x1e00 != 0x800) - goto RECMDS7; - } - else - { -RECMDD7: - SDICARG=0<<16; - SDICCON=(0x1<<8)|0x47; - - if(sd_cmd_end(7, 0) == RT_ERROR) - goto RECMDD7; - SDICSTA = 0x800; - } -} - -static void sd_setbus(void) -{ - do - { - sd_cmd55(); - - SDICARG = 1<<1; /* 4bit bus */ - SDICCON=(0x1<<9)|(0x1<<8)|0x46; /* sht_resp, wait_resp, start, CMD55 */ - }while (sd_cmd_end(6, 1) == RT_ERROR); - - SDICSTA=0xa00; /* Clear cmd_end(with rsp) */ -} - -static int sd_ocr(void) -{ - int i; - - /* Negotiate operating condition for SD, it makes card ready state */ - for(i=0;i<50;i++) - { - sd_cmd55(); - - SDICARG=0xff8000; - 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 ) - { - SDICSTA=0xa00; - return RT_EOK; - } - - sd_delay(200); - } - SDICSTA=0xa00; - - return RT_ERROR; -} - -static rt_uint8_t sd_init(void) -{ - //-- SD controller & card initialize - int i; - /* Important notice for MMC test condition */ - /* Cmd & Data lines must be enabled by pull up resister */ - SDIPRE = PCLK/(INICLK)-1; - SDICON = (0<<4) | 1; // Type A, clk enable - SDIFSTA = SDIFSTA | (1<<16); - SDIBSIZE = 0x200; /* 512byte per one block */ - SDIDTIMER=0x7fffff; /* timeout count */ - - /* Wait 74SDCLK for MMC card */ - for(i=0; i<0x1000; i++); - - sd_cmd0(); - - /* Check SD card OCR */ - if(sd_ocr() == RT_EOK) - { - rt_kprintf("In SD ready\n"); - } - else - { - rt_kprintf("Initialize fail\nNo Card assertion\n"); - return RT_ERROR; - } - -RECMD2: - SDICARG = 0x0; - SDICCON = (0x1<<10)|(0x1<<9)|(0x1<<8)|0x42; /* lng_resp, wait_resp, start, CMD2 */ - if(sd_cmd_end(2, 1) == RT_ERROR) - goto RECMD2; - - SDICSTA = 0xa00; /* Clear cmd_end(with rsp) */ - -RECMD3: - SDICARG = 0<<16; /* CMD3(MMC:Set RCA, SD:Ask RCA-->SBZ) */ - SDICCON = (0x1<<9)|(0x1<<8)|0x43; /* sht_resp, wait_resp, start, CMD3 */ - if(sd_cmd_end(3, 1) == RT_ERROR) - goto RECMD3; - SDICSTA=0xa00; /* Clear cmd_end(with rsp) */ - - RCA = (SDIRSP0 & 0xffff0000 )>>16; - SDIPRE=PCLK/(SDCLK)-1; /* Normal clock=25MHz */ - if( SDIRSP0 & 0x1e00 != 0x600 ) - goto RECMD3; - - sd_sel_desel(1); - sd_delay(200); - sd_setbus(); - - return RT_EOK; -} - -static rt_uint8_t sd_readblock(rt_uint32_t address, rt_uint8_t* buf) -{ - rt_uint32_t status, tmp; - - rd_cnt=0; - SDIFSTA = SDIFSTA | (1<<16); - - SDIDCON = (2 << 22) | (1 << 19) | (1 << 17) | (1 << 16) | (1 << 14) | (2 << 12) | (1 << 0); - SDICARG = address; - -RERDCMD: - SDICCON = (0x1 << 9 ) | (0x1 << 8) | 0x51; - if(sd_cmd_end(17, 1) == RT_ERROR) - { - rt_kprintf("Read CMD Error\n"); - goto RERDCMD; - } - - SDICSTA = 0xa00; - - while(rd_cnt < 128) - { - if((SDIDSTA & 0x20) == 0x20) - { - SDIDSTA = (0x1 << 0x5); - break; - } - status = SDIFSTA; - if((status & 0x1000) == 0x1000) - { - tmp = SDIDAT; - rt_memcpy(buf, &tmp, sizeof(rt_uint32_t)); - rd_cnt++; - buf += 4; - } - } - if(sd_data_end() == RT_ERROR) - { - rt_kprintf("Dat error\n"); - return RT_ERROR; - } - - SDIDCON = SDIDCON &~ (7<<12); - SDIFSTA = SDIFSTA & 0x200; - SDIDSTA = 0x10; - - return RT_EOK; -} - -static rt_uint8_t sd_writeblock(rt_uint32_t address, rt_uint8_t* buf) -{ - rt_uint32_t status, tmp; - - wt_cnt=0; - SDIFSTA = SDIFSTA | (1 << 16); - SDIDCON = (2 << 22) | (1 << 20) | (1 << 17) | (1 << 16) | (1 << 14) | (3 << 12) | (1 << 0); - SDICARG = address; - -REWTCMD: - SDICCON = (0x1 << 9) | (0x1 << 8) |0x58; - - if(sd_cmd_end(24, 1) == RT_ERROR) - goto REWTCMD; - - SDICSTA=0xa00; - - while(wt_cnt < 128*1) - { - status = SDIFSTA; - if((status & 0x2000) == 0x2000) - { - rt_memcpy(&tmp, buf, sizeof(rt_uint32_t)); - SDIDAT = tmp; - wt_cnt++; - buf += 4; - } - } - if(sd_data_end() == RT_ERROR) - { - rt_kprintf("Data Error\n"); - return RT_ERROR; - } - SDIDCON = SDIDCON &~ (7<<12); - SDIDSTA = 0x10; - - return RT_EOK; -} - -#ifdef RT_USING_DFS -/* RT-Thread Device Driver Interface */ -#include - -#include - -struct rt_device sdcard_device[4]; -struct dfs_partition part[4]; - -static rt_err_t rt_sdcard_init(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t rt_sdcard_open(rt_device_t dev, rt_uint16_t oflag) -{ - return RT_EOK; -} - -static rt_err_t rt_sdcard_close(rt_device_t dev) -{ - return RT_EOK; -} - -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) -{ - int i; - struct dfs_partition *part = (struct dfs_partition *)dev->user_data; - - if ( dev == RT_NULL ) - { - rt_set_errno(-DFS_STATUS_EINVAL); - return 0; - } - - /* read all sectors */ - 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)); - rt_sem_release(part->lock); - } - - /* the length of reading must align to SECTOR SIZE */ - return 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; - struct dfs_partition *part = (struct dfs_partition *)dev->user_data; - - if ( dev == RT_NULL ) - { - rt_set_errno(-DFS_STATUS_EINVAL); - return 0; - } - - /* read all sectors */ - 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)); - rt_sem_release(part->lock); - } - - /* the length of reading must align to SECTOR SIZE */ - return size; -} - -void rt_hw_sdcard_init(void) -{ - rt_uint8_t i, status; - rt_uint8_t *sector; - char dname[4]; - char sname[8]; - - /* Enable PCLK into SDI Block */ - CLKCON |= 1 << 9; - - /* Setup GPIO as SD and SDCMD, SDDAT[3:0] Pull up En */ - GPEUP = GPEUP & (~(0x3f << 5)) | (0x01 << 5); - GPECON = GPECON & (~(0xfff << 10)) | (0xaaa << 10); - - RCA = 0; - - if (sd_init() == RT_EOK) - { - /* get the first sector to read partition table */ - sector = (rt_uint8_t*) rt_malloc (512); - if (sector == RT_NULL) - { - rt_kprintf("allocate partition sector buffer failed\n"); - return; - } - status = sd_readblock(0, sector); - if (status == RT_EOK) - { - for(i=0; i<4; i++) - { - /* get the first partition */ - status = dfs_filesystem_get_partition(&part[i], sector, i); - if (status == RT_EOK) - { - rt_snprintf(dname, 4, "sd%d", i); - rt_snprintf(sname, 8, "sem_sd%d", i); - part[i].lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO); - - /* register sdcard device */ - sdcard_device[i].type = RT_Device_Class_Block; - sdcard_device[i].init = rt_sdcard_init; - sdcard_device[i].open = rt_sdcard_open; - sdcard_device[i].close = rt_sdcard_close; - sdcard_device[i].read = rt_sdcard_read; - sdcard_device[i].write = rt_sdcard_write; - sdcard_device[i].control = rt_sdcard_control; - sdcard_device[i].user_data = &part[i]; - - rt_device_register(&sdcard_device[i], dname, - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE); - } - else - { - if(i == 0) - { - /* there is no partition table */ - part[0].offset = 0; - part[0].size = 0; - part[0].lock = rt_sem_create("sem_sd0", 1, RT_IPC_FLAG_FIFO); - - /* register sdcard device */ - sdcard_device[0].type = RT_Device_Class_Block; - sdcard_device[0].init = rt_sdcard_init; - sdcard_device[0].open = rt_sdcard_open; - sdcard_device[0].close = rt_sdcard_close; - sdcard_device[0].read = rt_sdcard_read; - sdcard_device[0].write = rt_sdcard_write; - sdcard_device[0].control = rt_sdcard_control; - sdcard_device[0].user_data = &part[0]; - - rt_device_register(&sdcard_device[0], "sd0", - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE); - - break; - } - } - } - } - else - { - rt_kprintf("read sdcard first sector failed\n"); - } - - /* release sector buffer */ - rt_free(sector); - - return; - } - else - { - rt_kprintf("sdcard init failed\n"); - } -} - -#endif +/* + * File : sd.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, 2007, RT-Thread Develop Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * 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 + */ + +#include "sdcard.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; + +static void sd_delay(rt_uint32_t ms) +{ + ms *= 7326; + while(--ms); +} + +static int sd_cmd_end(int cmd, int be_resp) +{ + int finish0; + + if (!be_resp) + { + finish0 = SDICSTA; + + while ((finish0&0x800) != 0x800) + finish0 = SDICSTA; + + SDICSTA = finish0; + + return RT_EOK; + } + else + { + finish0 = SDICSTA; + + while (!(((finish0&0x200)==0x200) | ((finish0&0x400) == 0x400))) + finish0=SDICSTA; + + if (cmd == 1 || cmd == 41) + { + if ((finish0 & 0xf00) != 0xa00) + { + SDICSTA = finish0; + if ((finish0&0x400) == 0x400) + return RT_ERROR; + } + SDICSTA = finish0; + } + else + { + if ((finish0 & 0x1f00) != 0xa00) + { + /* rt_kprintf("CMD%d:SDICSTA=0x%x, SDIRSP0=0x%x\n", cmd, SDICSTA, SDIRSP0); */ + SDICSTA = finish0; + if ((finish0 & 0x400) == 0x400) + return RT_ERROR; + } + SDICSTA = finish0; + } + return RT_EOK; + } +} + +static int sd_data_end(void) +{ + int finish; + + finish = SDIDSTA; + + while (!(((finish & 0x10) == 0x10) | ((finish & 0x20) == 0x20))) + { + finish = SDIDSTA; + } + + if ((finish & 0xfc) != 0x10) + { + SDIDSTA = 0xec; + + return RT_ERROR; + } + + return RT_EOK; +} + +static void sd_cmd0(void) +{ + SDICARG = 0x0; + SDICCON = (1<<8) | 0x40; + + sd_cmd_end(0, 0); + SDICSTA = 0x800; /* Clear cmd_end(no rsp) */ +} + +static int sd_cmd55(void) +{ + SDICARG = RCA << 16; + SDICCON = (0x1 << 9) | (0x1 << 8) | 0x77; + + if (sd_cmd_end(55, 1) == RT_ERROR) + { + /* rt_kprintf("CMD55 error\n"); */ + return RT_ERROR; + } + + SDICSTA = 0xa00; + + return RT_EOK; +} + +static void sd_sel_desel(char sel_desel) +{ + if (sel_desel) + { +RECMDS7: + SDICARG = RCA << 16; + SDICCON = (0x1 << 9) | (0x1 << 8) | 0x47; + if (sd_cmd_end(7, 1) == RT_ERROR) + goto RECMDS7; + + SDICSTA = 0xa00; + + if (SDIRSP0 & 0x1e00 != 0x800) + goto RECMDS7; + } + else + { +RECMDD7: + SDICARG = 0 << 16; + SDICCON = (0x1 << 8) | 0x47; + + if (sd_cmd_end(7, 0) == RT_ERROR) + goto RECMDD7; + SDICSTA = 0x800; + } +} + +static void sd_setbus(void) +{ + do + { + sd_cmd55(); + + SDICARG = 1 << 1; /* 4bit bus */ + SDICCON = (0x1<<9) | (0x1<<8) | 0x46; /* sht_resp, wait_resp, start, CMD55 */ + }while (sd_cmd_end(6, 1) == RT_ERROR); + + SDICSTA=0xa00; /* Clear cmd_end(with rsp) */ +} + +static int sd_ocr(void) +{ + int i, ver=0; + + /* Negotiate operating condition for SD, it makes card ready state */ + for (i = 0; i < 50; i ++) + { + sd_cmd55(); + + 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) + { + 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; +} + +static rt_uint8_t sd_init(void) +{ + //-- SD controller & card initialize + int i; + /* Important notice for MMC test condition */ + /* Cmd & Data lines must be enabled by pull up resister */ + SDIPRE = PCLK / (INICLK) - 1; + SDICON = (0<<4) | 1; // Type A, clk enable + SDIFSTA = SDIFSTA | (1<<16); + SDIBSIZE = 0x200; /* 512byte per one block */ + SDIDTIMER = 0x7fffff; /* timeout count */ + + /* Wait 74SDCLK for MMC card */ + for (i = 0; i < 0x1000; i ++); + + sd_cmd0(); + sd_cmd8(); /* Must be use it, Host shall supports high capacity */ + + /* Check SD card OCR */ + 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; + } + +RECMD2: + SDICARG = 0x0; + SDICCON = (0x1<<10)|(0x1<<9)|(0x1<<8)|0x42; /* lng_resp, wait_resp, start, CMD2 */ + if (sd_cmd_end(2, 1) == RT_ERROR) + goto RECMD2; + + SDICSTA = 0xa00; /* Clear cmd_end(with rsp) */ + +RECMD3: + SDICARG = 0<<16; /* CMD3(MMC:Set RCA, SD:Ask RCA-->SBZ) */ + SDICCON = (0x1<<9)|(0x1<<8)|0x43; /* sht_resp, wait_resp, start, CMD3 */ + if (sd_cmd_end(3, 1) == RT_ERROR) + goto RECMD3; + SDICSTA=0xa00; /* Clear cmd_end(with rsp) */ + + RCA = (SDIRSP0 & 0xffff0000) >> 16; + SDIPRE = PCLK / (SDCLK) - 1; /* Normal clock=25MHz */ + if (SDIRSP0 & 0x1e00 != 0x600) + goto RECMD3; + + sd_sel_desel(1); + sd_delay(200); + sd_setbus(); + + return RT_EOK; +} + +static rt_uint8_t sd_readblock(rt_uint32_t address, rt_uint8_t *buf) +{ + rt_uint32_t status, tmp; + + rd_cnt = 0; + SDIFSTA = SDIFSTA | (1<<16); + + SDIDCON = (2 << 22) | (1 << 19) | (1 << 17) | (1 << 16) | (1 << 14) | (2 << 12) | (1 << 0); + SDICARG = address; + +RERDCMD: + SDICCON = (0x1 << 9 ) | (0x1 << 8) | 0x51; + if (sd_cmd_end(17, 1) == RT_ERROR) + { + rt_kprintf("Read CMD Error\n"); + goto RERDCMD; + } + + SDICSTA = 0xa00; + + while (rd_cnt < 128) + { + if ((SDIDSTA & 0x20) == 0x20) + { + SDIDSTA = (0x1 << 0x5); + break; + } + status = SDIFSTA; + if ((status & 0x1000) == 0x1000) + { + tmp = SDIDAT; + rt_memcpy(buf, &tmp, sizeof(rt_uint32_t)); + rd_cnt ++; + buf += 4; + } + } + if (sd_data_end() == RT_ERROR) + { + rt_kprintf("Dat error\n"); + + return RT_ERROR; + } + + SDIDCON = SDIDCON &~ (7<<12); + SDIFSTA = SDIFSTA & 0x200; + SDIDSTA = 0x10; + + return RT_EOK; +} + +static rt_uint8_t sd_writeblock(rt_uint32_t address, rt_uint8_t *buf) +{ + rt_uint32_t status, tmp; + + wt_cnt = 0; + SDIFSTA = SDIFSTA | (1 << 16); + + SDIDCON = (2 << 22) | (1 << 20) | (1 << 17) | (1 << 16) | (1 << 14) | (3 << 12) | (1 << 0); + SDICARG = address; + +REWTCMD: + SDICCON = (0x1 << 9) | (0x1 << 8) |0x58; + + if (sd_cmd_end(24, 1) == RT_ERROR) + goto REWTCMD; + + SDICSTA = 0xa00; + + while (wt_cnt < 128) + { + status = SDIFSTA; + if ((status & 0x2000) == 0x2000) + { + rt_memcpy(&tmp, buf, sizeof(rt_uint32_t)); + SDIDAT = tmp; + wt_cnt ++; + buf += 4; + } + } + if (sd_data_end() == RT_ERROR) + { + rt_kprintf("Data Error\n"); + + return RT_ERROR; + } + SDIDCON = SDIDCON &~ (7<<12); + SDIDSTA = 0x10; + + return RT_EOK; +} + +#ifdef RT_USING_DFS +/* RT-Thread Device Driver Interface */ +#include + +#include + +struct rt_device sdcard_device[4]; +struct dfs_partition part[4]; + +static rt_err_t rt_sdcard_init(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_err_t rt_sdcard_open(rt_device_t dev, rt_uint16_t oflag) +{ + return RT_EOK; +} + +static rt_err_t rt_sdcard_close(rt_device_t dev) +{ + return RT_EOK; +} + +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) +{ + 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; + } + + /* read all sectors */ + for (i = 0; i < size; i ++) + { + rt_sem_take(part->lock, RT_WAITING_FOREVER); + 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); + } + + /* the length of reading must align to SECTOR SIZE */ + return 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, addr; + struct dfs_partition *part = (struct dfs_partition *)dev->user_data; + + if (dev == RT_NULL) + { + rt_set_errno(-DFS_STATUS_EINVAL); + + return 0; + } + + /* read all sectors */ + for (i = 0; i < size; i++) + { + rt_sem_take(part->lock, RT_WAITING_FOREVER); + 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); + } + + /* the length of reading must align to SECTOR SIZE */ + return size; +} + +void rt_hw_sdcard_init(void) +{ + rt_uint8_t i, status; + rt_uint8_t *sector; + char dname[4]; + char sname[8]; + + /* Enable PCLK into SDI Block */ + CLKCON |= 1 << 9; + + /* Setup GPIO as SD and SDCMD, SDDAT[3:0] Pull up En */ + GPEUP = GPEUP & (~(0x3f << 5)) | (0x01 << 5); + GPECON = GPECON & (~(0xfff << 10)) | (0xaaa << 10); + + RCA = 0; + + if (sd_init() == RT_EOK) + { + /* get the first sector to read partition table */ + sector = (rt_uint8_t*) rt_malloc (512); + if (sector == RT_NULL) + { + rt_kprintf("allocate partition sector buffer failed\n"); + + return; + } + status = sd_readblock(0, sector); + if (status == RT_EOK) + { + for (i = 0; i < 4; i ++) + { + /* get the first partition */ + status = dfs_filesystem_get_partition(&part[i], sector, i); + if (status == RT_EOK) + { + rt_snprintf(dname, 4, "sd%d", i); + rt_snprintf(sname, 8, "sem_sd%d", i); + part[i].lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO); + + /* register sdcard device */ + sdcard_device[i].type = RT_Device_Class_Block; + sdcard_device[i].init = rt_sdcard_init; + sdcard_device[i].open = rt_sdcard_open; + sdcard_device[i].close = rt_sdcard_close; + sdcard_device[i].read = rt_sdcard_read; + sdcard_device[i].write = rt_sdcard_write; + sdcard_device[i].control = rt_sdcard_control; + sdcard_device[i].user_data = &part[i]; + + rt_device_register(&sdcard_device[i], dname, + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE); + } + else + { + if (i == 0) + { + /* there is no partition table */ + part[0].offset = 0; + part[0].size = 0; + part[0].lock = rt_sem_create("sem_sd0", 1, RT_IPC_FLAG_FIFO); + + /* register sdcard device */ + sdcard_device[0].type = RT_Device_Class_Block; + sdcard_device[0].init = rt_sdcard_init; + sdcard_device[0].open = rt_sdcard_open; + sdcard_device[0].close = rt_sdcard_close; + sdcard_device[0].read = rt_sdcard_read; + sdcard_device[0].write = rt_sdcard_write; + sdcard_device[0].control = rt_sdcard_control; + sdcard_device[0].user_data = &part[0]; + + rt_device_register(&sdcard_device[0], "sd0", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE); + + break; + } + } + } + } + else + { + rt_kprintf("read sdcard first sector failed\n"); + } + + /* release sector buffer */ + rt_free(sector); + + return; + } + else + { + rt_kprintf("sdcard init failed\n"); + } +} + +#endif