《基于S3C2440的嵌入式Linux開發(fā)實例》課件第4章_第1頁
《基于S3C2440的嵌入式Linux開發(fā)實例》課件第4章_第2頁
《基于S3C2440的嵌入式Linux開發(fā)實例》課件第4章_第3頁
《基于S3C2440的嵌入式Linux開發(fā)實例》課件第4章_第4頁
《基于S3C2440的嵌入式Linux開發(fā)實例》課件第4章_第5頁
已閱讀5頁,還剩144頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

4.1SD/MMC概述4.2S3C2440SD/MMC接口寄存器介紹4.3LinuxSD/MMC驅(qū)動程序分析4.1.1SD卡總線協(xié)議及工作原理

作為一種新型的存儲設(shè)備,SD卡具有以下特點:內(nèi)置加密技術(shù),適應(yīng)基于SDMI協(xié)議的著作版權(quán)保護(hù)功能;高速數(shù)據(jù)傳送;高存儲容量;體積小,便于攜帶,具有很強的抗沖擊能力。

SD卡的電氣參數(shù)如下:

(1)物理特性。4.1SD/MMC概述(2)電源要求。

(3)數(shù)據(jù)傳輸速度:2?Mb/s。

(4)使用環(huán)境。

SD卡基于9針接口,最大可工作在25?MHz。SD卡的結(jié)構(gòu)如圖4-1所示。SD卡內(nèi)部的結(jié)構(gòu)分為外接口驅(qū)動、SD卡接口驅(qū)動、電源檢測、存儲器內(nèi)核接口及內(nèi)存儲器內(nèi)核5部分。圖4-1SD卡結(jié)構(gòu)示意圖4.1.2SD卡引腳及接口電路

1.?SD卡引腳說明

SD卡引腳如表4-1所示。表4-1SD卡引腳說明

2.S3C2410的SD卡接口電路

圖4-2為SD卡接口原理圖,SD卡的數(shù)據(jù)和命令線用上拉電阻。

S3C2410的SD卡兼容SD存儲卡(1.0版)/MMC(2.11版);兼容SDIO卡(1.0版);16字(64字節(jié))的FIFO寄存器,用于接收/發(fā)送數(shù)據(jù);40位的命令寄存器;136位的應(yīng)答寄存器;8位的預(yù)分頻邏輯電路(Freq=SystemClock/(P+1));支持普通和DMA傳送模式(字節(jié)、半字、字傳輸);1位或4位線寬模式,區(qū)塊/串流(block/stream)的傳輸模式。圖4-2SD卡接口原理圖

1.?SDI控制寄存器

SDI控制寄存器各位定義如表4-2和表4-3所示。4.2S3C2440SD/MMC接口寄存器介紹表4-2SDI控制寄存器表4-3SDI控制寄存器位定義

2.SDI預(yù)設(shè)分頻寄存器

SDI預(yù)設(shè)分頻寄存器各位定義如表4-4和表4-5所示。

3.SDI命令參數(shù)寄存器

SDI命令參數(shù)寄存器各位定義如表4-6和表4-7所示。表4-4SDI預(yù)設(shè)分頻寄存器表4-5SDI預(yù)設(shè)分頻寄存器位定義表4-6SDI命令參數(shù)寄存器表4-7SDI命令參數(shù)寄存器位定義4.SDI命令控制寄存器

SDI命令控制寄存器各位定義如表4-8和4-9所示。表4-8SDI命令控制寄存器表4-9SDI命令控制寄存器位定義5.?SDI命令狀態(tài)寄存器

SDI命令狀態(tài)寄存器各位定義如表4-10和表4-11所示。

6.?SDI應(yīng)答寄存器

SDI應(yīng)答寄存器各位定義如表4-12和表4-13所示。表4-10SDI命令狀態(tài)寄存器表4-11SDI命令狀態(tài)寄存器位定義表4-12SDI應(yīng)答寄存器表4-13SDI應(yīng)答寄存器位定義7.SDI應(yīng)答寄存器1(SDIRSP1)

SDI應(yīng)答寄存器各位定義如表4-14和表4-15所示。

8.SDI應(yīng)答寄存器2(SDIRSP2)

SDI應(yīng)答寄存器2各位定義如表4-16和表4-17所示。表4-14SDI應(yīng)答寄存器1表4-15SDI應(yīng)答寄存器1位定義表4-16SDI應(yīng)答寄存器2表4-17SDI響應(yīng)寄存器2位定義9.SDI響應(yīng)寄存器3(SDIRSP3)

SDI應(yīng)答寄存器3各位定義如表4-18和表4-19所示。

10.?dāng)?shù)據(jù)/測忙定時寄存器(SDIDTimer)

數(shù)據(jù)/測忙定時寄存器各位定義如表4-20和表4-21所示。表4-18SDI應(yīng)答寄存器3表4-19SDI應(yīng)答寄存器3位定義表4-20數(shù)據(jù)/測忙定時寄存器表4-21數(shù)據(jù)/測忙定時寄存器位定義11.SDI塊大小寄存器(SDIBSize)

SDI塊大小寄存器各位定義如表4-22和表4-23所示。

12.數(shù)據(jù)控制寄存器(SDIDatCon)

數(shù)據(jù)控制寄存器各位定義如表4-24和表4-25所示。表4-22SDI塊大小寄存器表4-23SDI塊大小寄存器位定義表4-24數(shù)據(jù)控制寄存器位定義表4-25數(shù)據(jù)控制寄存器4.3.1寄存器地址和功能定義

S3C2440SDI控制器相關(guān)寄存器地址及初始值定義如下:

#defineS3C2410_SDICON (0x00)

#defineS3C2410_SDIPRE (0x04)

#defineS3C2410_SDICMDARG (0x08)

#defineS3C2410_SDICMDCON (0x0C)

#defineS3C2410_SDICMDSTAT (0x10)

#defineS3C2410_SDIRSP0 (0x14)4.3LinuxSD/MMC驅(qū)動程序分析#defineS3C2410_SDIRSP1 (0x18)

#defineS3C2410_SDIRSP2 (0x1C)

#defineS3C2410_SDIRSP3 (0x20)

#defineS3C2410_SDITIMER (0x24)

#defineS3C2410_SDIBSIZE (0x28)

#defineS3C2410_SDIDCON (0x2C)

#defineS3C2410_SDIDCNT (0x30)

#defineS3C2410_SDIDSTA (0x34)

#defineS3C2410_SDIFSTA (0x38)#ifdefCONFIG_CPU_S3C2440

#defineS3C2410_SDIDATA (0x40)

#defineS3C2410_SDIIMSK (0x3c)

#else

#defineS3C2410_SDIDATA (0x3C)

#defineS3C2410_SDIIMSK (0x40)

#endif#defineS3C2410_SDICON_MMCRESET (1<<8)

#defineS3C2410_SDICON_CLOCKTYPE (1<<5)

#defineS3C2410_SDICON_BYTEORDER (1<<4)

#defineS3C2410_SDICON_SDIOIRQ (1<<3)

#defineS3C2410_SDICON_RWAITEN (1<<2)

#defineS3C2410_SDICON_CLKEN (1<<0)#defineS3C2410_SDICMDCON_ABORT (1<<12)

#defineS3C2410_SDICMDCON_WITHDATA (1<<11)

#defineS3C2410_SDICMDCON_LONGRSP (1<<10)

#defineS3C2410_SDICMDCON_WAITRSP (1<<9)

#defineS3C2410_SDICMDCON_CMDSTART (1<<8)

#defineS3C2410_SDICMDCON_SENDERHOST (1<<6)

#defineS3C2410_SDICMDCON_INDEX (0xff)#defineS3C2410_SDICMDSTAT_CRCFAIL (1<<12)

#defineS3C2410_SDICMDSTAT_CMDSENT (1<<11)

#defineS3C2410_SDICMDSTAT_CMDTIMEOUT(1<<10)

#defineS3C2410_SDICMDSTAT_RSPFIN (1<<9)

#defineS3C2410_SDICMDSTAT_XFERING (1<<8)

#defineS3C2410_SDICMDSTAT_INDEX (0xff)#defineS3C2410_SDIDCON_BURST4 (1<<24)//FOR2440

#defineS3C2410_SDIDCON_DATASIZE (3<<22)//FOR2440

#defineS3C2410_SDIDCON_IRQPERIOD (1<<21)

#defineS3C2410_SDIDCON_TXAFTERRESP (1<<20)

#defineS3C2410_SDIDCON_RXAFTERCMD (1<<19)

#defineS3C2410_SDIDCON_BUSYAFTERCMD(1<<18)

#defineS3C2410_SDIDCON_BLOCKMODE (1<<17)#defineS3C2410_SDIDCON_WIDEBUS (1<<16)

#defineS3C2410_SDIDCON_DMAEN (1<<15)

//#defineS3C2410_SDIDCON_STOP (1<<14)

#defineS3C2410_SDIDCON_DTST (1<<14)

#defineS3C2410_SDIDCON_DATMODE (3<<12)

#defineS3C2410_SDIDCON_BLKNUM (0x7ff)/*constantsforS3C2410_SDIDCON_DATMODE*/

#defineS3C2410_SDIDCON_XFER_READY (0<<12)

#defineS3C2410_SDIDCON_XFER_CHKSTART (1<<12)

#defineS3C2410_SDIDCON_XFER_RXSTART (2<<12)

#defineS3C2410_SDIDCON_XFER_TXSTART (3<<12)#defineS3C2410_SDIDCON_DAT_BYTE(0<<22)//FOR2440

#defineS3C2410_SDIDCON_DAT_HW (1<<22)//FOR2440

#defineS3C2410_SDIDCON_DAT_WD(2<<22)//FOR2440

#defineS3C2410_SDIDCON_BLKNUM_MASK (0xFFF)

#defineS3C2410_SDIDCNT_BLKNUM_SHIFT

(12)#defineS3C2410_SDIDSTA_RDYWAITREQ (1<<10)

#defineS3C2410_SDIDSTA_SDIOIRQDETECT (1<<9)

#defineS3C2410_SDIDSTA_FIFOFAIL (1<<8) /*reservedon2440*/

#defineS3C2410_SDIDSTA_CRCFAIL

(1<<7)

#defineS3C2410_SDIDSTA_RXCRCFAIL

(1<<6)

#defineS3C2410_SDIDSTA_DATATIMEOUT (1<<5)#defineS3C2410_SDIDSTA_XFERFINISH (1<<4)

#defineS3C2410_SDIDSTA_BUSYFINISH (1<<3)

#defineS3C2410_SDIDSTA_SBITERR (1<<2) /*reservedon2410a/2440*/

#defineS3C2410_SDIDSTA_TXDATAON (1<<1)

#defineS3C2410_SDIDSTA_RXDATAON (1<<0)#defineS3C2410_SDICON_FIFORESET (1<<16)//fors3c2440

#defineS3C2410_SDIFSTA_TFDET (1<<13)

#defineS3C2410_SDIFSTA_RFDET (1<<12)

#defineS3C2410_SDIFSTA_TXHALF (1<<11)

#defineS3C2410_SDIFSTA_TXEMPTY(1<<10)

#defineS3C2410_SDIFSTA_RFLAST (1<<9)

#defineS3C2410_SDIFSTA_RFFULL (1<<8)

#defineS3C2410_SDIFSTA_RFHALF (1<<7)

#defineS3C2410_SDIFSTA_COUNTMASK (0x7f)#defineS3C2410_SDIIMSK_RESPONSECRC(1<<17)

#defineS3C2410_SDIIMSK_CMDSENT (1<<16)

#defineS3C2410_SDIIMSK_CMDTIMEOUT (1<<15)

#defineS3C2410_SDIIMSK_RESPONSEND (1<<14)

#defineS3C2410_SDIIMSK_READWAIT (1<<13)

#defineS3C2410_SDIIMSK_SDIOIRQ (1<<12)

#defineS3C2410_SDIIMSK_FIFOFAIL

(1<<11)

#defineS3C2410_SDIIMSK_CRCSTATUS (1<<10)#defineS3C2410_SDIIMSK_DATACRC (1<<9)

#defineS3C2410_SDIIMSK_DATATIMEOUT (1<<8)

#defineS3C2410_SDIIMSK_DATAFINISH (1<<7)

#defineS3C2410_SDIIMSK_BUSYFINISH (1<<6)

#defineS3C2410_SDIIMSK_SBITERR (1<<5) /*reserved2440/2410a*/#defineS3C2410_SDIIMSK_TXFIFOHALF (1<<4)

#defineS3C2410_SDIIMSK_TXFIFOEMPTY (1<<3)

#defineS3C2410_SDIIMSK_RXFIFOLAST (1<<2)

#defineS3C2410_SDIIMSK_RXFIFOFULL (1<<1)

#defineS3C2410_SDIIMSK_RXFIFOHALF (1<<0)4.3.2數(shù)據(jù)結(jié)構(gòu)和變量描述

1.結(jié)構(gòu)體mmc_blk_data

SD/MMC設(shè)備由控制器及插卡組成,對應(yīng)設(shè)備結(jié)構(gòu)為mmc_host結(jié)構(gòu)和mmc_card結(jié)構(gòu)體。每個卡的插槽都對應(yīng)一個塊的數(shù)據(jù)結(jié)構(gòu)體mmc_blk_data,其結(jié)構(gòu)體代碼描述如下:

structmmc_blk_data

{

spinlock_t lock;

structgendisk *disk; /*通用硬盤結(jié)構(gòu)*/

structmmc_queuequeue; /*MMC請求隊列結(jié)構(gòu)*/

unsignedint usage;

unsignedint block_bits; /*卡每一塊大小所占的bit位*/

};2.結(jié)構(gòu)體mmc_card

結(jié)構(gòu)體mmc_card描述了插卡的特性,它帶有一個插卡,代碼描述如下:

structmmc_card

{

structlist_head node; /*在主設(shè)備鏈表中的節(jié)點*/

structmmc_host *host;/*卡所屬的控制器*/

structdevice dev; /*通用設(shè)備結(jié)構(gòu)*/unsignedchar sd;

unsignedint rca; /*設(shè)備相對本地系統(tǒng)的地址*/

unsignedint state; /*卡的狀態(tài)*/

u8 bus_width; /*總線寬度*/

#defineMMC_STATE_PRESENT (1<<0)

/*卡出現(xiàn)在sys文件系統(tǒng)中*/

#defineMMC_STATE_DEAD(1<<1)

/*卡不在工作狀態(tài)*/

#defineMMC_STATE_BAD (1<<2) /*不認(rèn)識的設(shè)備*/

u32 raw_cid[4]; /*raw-card

cid*/

u32 raw_csd[4]; /*rawcardCSD*/

structmmc_cid cid;

/*卡身份鑒別,值來自卡的CID寄存器*/

structmmc_csd csd;

/*卡特定信息,值來自卡的CSD寄存器*/

};3.結(jié)構(gòu)體mmc_host

結(jié)構(gòu)體mmc_host描述了一個MMC卡控制器的特性及操作等,代碼描述如下:

structmmc_host

{

structdevice*dev; /*通用設(shè)備結(jié)構(gòu)*/

structmmc_host_ops*ops;/*控制器操作函數(shù)集結(jié)構(gòu)*/

void*priv;unsignedintf_min;

unsignedintf_max;

u32

ocr_avail; /*卡可用的ocr寄存器*/

charhost_name[8]; /*控制器名字*/

/*私有數(shù)據(jù)*/

structmmc_iosios; /*當(dāng)前io總線設(shè)置*/

u32ocr; /*當(dāng)前OCR設(shè)置*/structlist_head cards; /*接在主控制器的卡*/

wait_queue_head_twq; /*等待隊列*/

spinlock_tlock; /*卡忙的鎖*/

structmmc_card*card_busy;

/*theMMCcardclaiminghost*/

structmmc_card*card_selected; /*選擇MMC卡*/

structwork_struct detect;

};4.結(jié)構(gòu)體s3c2410sdi_host

結(jié)構(gòu)體s3c2410sdi_host描述了s3c2440控制器的相關(guān)特性,代碼描述如下:

structs3c2410sdi_host

{

structmmc_host*mmc;/*通用mmc_host結(jié)構(gòu)體指針*/

s3c24xx_mmc_pdata_t*pdata;

structresource *mem; /*設(shè)備內(nèi)存資源*/structclk*clk;/*設(shè)備時鐘*/

void__iomem *base; /*設(shè)備d端口I/O基地址*/

intirq; /*中斷號*/

intirq_cd;

intdma;structscatterlist*cur_sg;

unsignedintnum_sg;

void*mapped_sg;

unsignedintoffset;

unsignedintremain;

intsize; /*傳輸?shù)拇笮?/

structmmc_request*mrq;

unsignedcharbus_width; /*總線寬度*/

spinlock_tcomplete_lock;

structcompletioncomplete_request;

structcompletioncomplete_dma;

enums3c2410sdi_waitfor complete_what;

};5.?s3c2410sdi_ops變量

s3c2410sdi_ops變量定義了mmchost相關(guān)操作,代碼描述如下:

staticstructmmc_host_opss3c2410sdi_ops=

{

.request=s3c2410sdi_request,

.set_ios=s3c2410sdi_set_ios,

};6.結(jié)構(gòu)體mmc_ios

結(jié)構(gòu)體mmc_ios描述了控制器對卡的I/O狀態(tài),代碼描述如下:

structmmc_ios

{

unsignedint clock; /*時鐘頻率*/

unsignedshort vdd; /*SD工作電壓值*/

unsignedchar bus_mode; /*命令輸出模式*/

unsignedchar chip_select;/*芯片選擇*/

unsignedchar power_mode;/*電源模式*/

unsignedchar bus_width; /*數(shù)據(jù)總線寬度*/

}7.結(jié)構(gòu)體變量s3c2410sdi_driver

結(jié)構(gòu)體變量s3c2410sdi_driver描述了sd/mmc初始化和移除的操作,代碼描述如下:

staticstructdevice_drivers3c2410sdi_driver=

{

.name=“s3c2440-sdi”,

.bus=&platform_bus_type,

.probe=s3c2410sdi_probe,

.remove=s3c2410sdi_remove,

};4.3.3主要函數(shù)描述

驅(qū)動程序結(jié)構(gòu)如圖4-3所示。圖4-3驅(qū)動程序結(jié)構(gòu)圖

1.模塊初始化函數(shù)s3c2410sdi_init()

模塊初始化函數(shù)s3c2410sdi_init()代碼描述如下:

staticint_inits3c2410sdi_init(void)

{

returndriver_register(&s3c2410sdi_driver);

}2.?SD/MMC驅(qū)動卸載函數(shù)s3c2410sdi_exit()

SD/MMC驅(qū)動卸載函數(shù)s3c2410sdi_exit()代碼描述如下:

staticvoid__exits3c2410sdi_exit(void)

{

driver_unregister(&s3c2410sdi_driver);

}

3.?SD/MMC探測函數(shù)s3c2410sdi_probe()

s3c2410sdi_probe()函數(shù)主要完成SD控制器驅(qū)動結(jié)構(gòu)分配、GPIO中的的配置、IO地址空間分配、中斷的分配、時鐘的設(shè)置等。其主要流程如圖4-4所示。圖4-4SD/MMC探測函數(shù)流程圖代碼描述如下:

staticints3c2410sdi_probe(structdevice*dev)

{

structplatform_device*pdev=to_platform_device(dev);

structmmc_host*mmc;

s3c24xx_mmc_pdata_t*pdata;

structs3c2410sdi_host*host;

intret;/*分配mmchost*/

mmc=mmc_alloc_host(sizeof(structs3c2410sdi_host),dev);

if(!mmc)

{

ret=-ENOMEM;

gotoprobe_out;

}

/*獲得mmc私有數(shù)據(jù)*/

host=mmc_priv(mmc);spin_lock_init(&host->complete_lock);

host->complete_what=COMPLETION_NONE;

host->mmc=mmc;

host->dma=S3C2410SDI_DMA;

/*得到平臺數(shù)據(jù)*/

pdata=dev->platform_data;

if(!pdata)

{

dev->platform_data=&s3c2410_mmc_defplat;

pdata=&s3c2410_mmc_defplat;

}

host->pdata=pdata;

/*得到SD/MMC檢測卡gpio中斷號*/

host->irq_cd=s3c2410_gpio_getirq(pdata->gpio_detect);/*配置SD/MMCGPIO管腳*/

s3c2410_gpio_cfgpin(pdata->gpio_detect,S3C2410_GPG8_EINT16);

/*分配內(nèi)存空間*/

host->mem=platform_get_resource(pdev,IORESOURCE_MEM,0);

if(!host->mem)

{

gotoprobe_free_host;

}/*IO地址空間分配*/

host->mem=request_mem_region(host->mem->start,

RESSIZE(host->mem),pdev->name);

if(!host->mem)

{

printk(KERN_INFOPFX“failedtorequestiomemory

region.\n”);

ret=-ENOENT;

gotoprobe_free_host;

}/*io地址映射*/

host->base=ioremap(host->mem->start,RESSIZE(host->mem));

if(host->base==0)

{

printk(KERN_INFOPFX“failedtoioremap()iomemoryregion.\n”);

ret=-EINVAL;

gotoprobe_free_mem_region;

}/*得到中斷號*/

host->irq=platform_get_irq(pdev,0);

if(host->irq==0)

{

printk(KERN_INFOPFX“failedtogetinterruptresouce.\n”);

ret=-EINVAL;

gotoprobe_iounmap;

}/*系統(tǒng)申請中斷*/

if(request_irq(host->irq,s3c2410sdi_irq,0,DRIVER_NAME,host))

{

printk(KERN_INFOPFX“failedtorequestsdiinterrupt.\n”);

ret=-ENOENT;

gotoprobe_iounmap;

}/*設(shè)置中斷類型*/

set_irq_type(host->irq_cd,IRQT_BOTHEDGE);

/*申請卡插入拔出檢測中斷*/

if(request_irq(host->irq_cd,s3c2410sdi_irq_cd,0,DRIVER_NAME,host))

{

printk(KERN_WARNINGPFX“failedtorequestcarddetectinterrupt.\n”);

ret=-ENOENT;

gotoprobe_free_irq;}

/*DMA申請*/

if(s3c2410_dma_request(S3C2410SDI_DMA,&s3c2410sdi_dma_client,NULL))

{

printk(KERN_WARNINGPFX“unabletogetDMAchannel.\n”);

ret=-EBUSY;

gotoprobe_free_irq_cd;

}/*得到SD/MMC時鐘*/

host->clk=clk_get(dev,“sdi”);

if(IS_ERR(host->clk))

{

printk(KERN_INFOPFX“failedtofindclocksource.\n”);

ret=PTR_ERR(host->clk);

host->clk=NULL;

gotoprobe_free_host;}

if((ret=clk_use(host->clk)))

{

printk(KERN_INFOPFX“failedtouseclocksource.\n”);

gotoclk_free;

}if((ret=clk_enable(host->clk)))

{

printk(KERN_INFOPFX“failedtoenableclocksource.\n”);

gotoclk_unuse;

}

s3c2410_sdi_test(mmc);mmc->ops=&s3c2410sdi_ops;

mmc->ocr_avail=MMC_VDD_32_33;

mmc->f_min=clk_get_rate(host->clk)/512;

mmc->f_max =clk_get_rate(host->clk)/2;

mmc->caps=MMC_CAP_4_BIT_DATA;

//HACK:ThereseemstobeahardwarebuginTomTomGO.

if(mmc->f_max>3000000)mmc->f_max=3000000;mmc->max_sectors=64;

mmc->max_seg_size=mmc->max_sectors<<9;

if((ret=mmc_add_host(mmc)))

{

printk(KERN_INFOPFX“failedtoaddmmchost.\n”);

gotoclk_disable;

}dev_set_drvdata(dev,mmc);

return0;

clk_disable:

clk_disable(host->clk);

clk_unuse:

clk_unuse(host->clk);

clk_free:

clk_put(host->clk);probe_free_irq_cd:

free_irq(host->irq_cd,host);

probe_free_irq:

free_irq(host->irq,host);

probe_iounmap:

iounmap(host->base);

probe_free_mem_region:

release_mem_region(host->mem->start,RESSIZE(host->mem));

probe_free_host:

mmc_free_host(mmc);

probe_out:

returnret;

}4.?SD/MMC驅(qū)動移除函數(shù)s3c2410sdi_remove()

SD/MMC驅(qū)動移除函數(shù)s3c2410sdi_remove()代碼描述如下:

staticints3c2410sdi_remove(structdevice*dev)

{

structmmc_host*mmc=dev_get_drvdata(dev);

structs3c2410sdi_host*host=mmc_priv(mmc);mmc_remove_host(mmc);

clk_disable(host->clk);

clk_unuse(host->clk);

clk_put(host->clk);

free_irq(host->irq_cd,host);

free_irq(host->irq,host);

iounmap(host->base);

release_mem_region(host->mem->start,RESSIZE(host->mem));

mmc_free_host(mmc);

return0;

}

5.?SD/MMC中斷處理函數(shù)s3c2410sdi_irq()

s3c2410sdi_irq()函數(shù)主要根據(jù)SD卡相關(guān)寄存器,完成SD控制器中的的處理,如判斷數(shù)據(jù)的收發(fā),校驗等。其主要流程如圖4-5所示。圖4-5SD/MMC中斷處理函數(shù)流程圖代碼描述如下:

staticirqreturn_ts3c2410sdi_irq(intirq,void*dev_id,structpt_regs*regs)

{

structs3c2410sdi_host*host;

u32sdi_csta,sdi_dsta,sdi_dcnt;

u32sdi_cclear,sdi_dclear;

unsignedlongiflags;

host=(structs3c2410sdi_host*)dev_id;

if(!host)returnIRQ_HANDLED;/*讀取SD命令狀態(tài)卡的的寄存器*/

sdi_csta=readl(host->base+S3C2410_SDICMDSTAT);

sdi_dsta=readl(host->base+S3C2410_SDIDSTA);

sdi_dcnt=readl(host->base+S3C2410_SDIDCNT);

spin_lock_irqsave(&host->complete_lock,iflags);

/*判斷中斷是否處理完成*/

if(host->complete_what==COMPLETION_NONE)

{

gotoclear_imask;

}if(!host->mrq)

{

gotoclear_imask;

}

sdi_cclear=0;

sdi_dclear=0;

/*判斷命令超時狀態(tài)*/

if(sdi_csta&S3C2410_SDICMDSTAT_CMDTIMEOUT)

{

host->mrq->cmd->error=MMC_ERR_TIMEOUT;

gototransfer_closed;

}/*判斷否處于發(fā)送狀態(tài)*/

if(sdi_csta&S3C2410_SDICMDSTAT_CMDSENT)

{

if(host->complete_what==COMPLETION_CMDSENT)

{

host->mrq->cmd->error=MMC_ERR_NONE;

gototransfer_closed;

}

sdi_cclear|=S3C2410_SDICMDSTAT_CMDSENT;

}/*判斷CRC校驗是否成功*/

if(sdi_csta&S3C2410_SDICMDSTAT_CRCFAIL)

{

if(host->mrq->cmd->flags&MMC_RSP_LONG)

{

DBG(PFX"s3c2410fixup:ignoreCRCfailwithlongrsp\n");

}

else

{

DBG(PFX“COMMANDCRCFAILED%x\n”,sdi_csta);

if(host->mrq->cmd->flags&MMC_RSP_CRC)

{

host->mrq->cmd->error=MMC_ERR_BADCRC;

gototransfer_closed;

}

}

sdi_cclear|=S3C2410_SDICMDSTAT_CRCFAIL;

}/*判斷是否有響應(yīng)*/

if(sdi_csta&S3C2410_SDICMDSTAT_RSPFIN)

{

if(host->complete_what==COMPLETION_RSPFIN)

{

host->mrq->cmd->error=MMC_ERR_NONE;

gototransfer_closed;

}if(host->complete_what==COMPLETION_XFERFINISH_RSPFIN)

{

host->mrq->cmd->error=MMC_ERR_NONE;

host->complete_what=COMPLETION_XFERFINISH;

}

sdi_cclear|=S3C2410_SDICMDSTAT_RSPFIN;

}

/*判斷FIFO響應(yīng)是否成功*./if(sdi_dsta&S3C2410_SDIDSTA_FIFOFAIL)

{

host->mrq->cmd->error=MMC_ERR_NONE;

host->mrq->data->error=MMC_ERR_FIFO;

gototransfer_closed;

}/*判斷發(fā)送校驗是否成功*/

if(sdi_dsta&S3C2410_SDIDSTA_RXCRCFAIL)

{

host->mrq->cmd->error=MMC_ERR_NONE;

host->mrq->data->error=MMC_ERR_BADCRC;

gototransfer_closed;

}

/*判斷CRC校驗是否成功*if(sdi_dsta&S3C2410_SDIDSTA_CRCFAIL)

{

host->mrq->cmd->error=MMC_ERR_NONE;

host->mrq->data->error=MMC_ERR_BADCRC;

gototransfer_closed;

}/*判斷數(shù)據(jù)是否超時*/

if(sdi_dsta&S3C2410_SDIDSTA_DATATIMEOUT)

{

host->mrq->cmd->error=MMC_ERR_NONE;

host->mrq->data->error=MMC_ERR_TIMEOUT;

gototransfer_closed;

}if(sdi_dsta&S3C2410_SDIDSTA_XFERFINISH)

{

if(host->complete_what==COMPLETION_XFERFINISH)

{

host->mrq->cmd->error=MMC_ERR_NONE;

host->mrq->data->error=MMC_ERR_NONE;

gototransfer_closed;

}if(host->complete_what==COMPLETION_XFERFINISH_RSPFIN)

{

host->mrq->data->error=MMC_ERR_NONE;

host->complete_what=COMPLETION_RSPFIN;

}

sdi_dclear|=S3C2410_SDIDSTA_XFERFINISH;

}writel(sdi_cclear,host->base+S3C2410_SDICMDSTAT);

writel(sdi_dclear,host->base+S3C2410_SDIDSTA);

spin_unlock_irqrestore(&host->complete_lock,iflags);

?DBG(PFX"IRQstillwaiting.\n");

returnIRQ_HANDLED;

transfer_closed:writel(sdi_cclear,host->base+S3C2410_SDICMDSTAT);

writel(sdi_dclear,host->base+S3C2410_SDIDSTA);

host->complete_what=COMPLETION_NONE;

complete(&host->complete_request);

writel(0,host->base+S3C2410_SDIIMSK);

spin_unlock_irqrestore(&host->complete_lock,iflags);

DBG(PFX"IRQtransferclosed.\n");

returnIRQ_HANDLED;clear_imask:

writel(0,host->base+S3C2410_SDIIMSK);

spin_unlock_irqrestore(&host->complete_lock,iflags);

DBG(PFX“IRQclearimask.\n”);

returnIRQ_HANDLED;

}6.?s3c2410sdi_dma_done_callback()函數(shù)

s3c2410sdi_dma_done_callback()函數(shù)用于處理SD/MMC的dma操作,代碼描述如下:

voids3c2410sdi_dma_done_callback(s3c2410_dma_chan_t*dma_ch,void*buf_id,

intsize,s3c2410_dma_buffresult_tresult)

{

unsignedlongiflags;

u32sdi_csta,sdi_dsta,sdi_dcnt;

structs3c2410sdi_host*host=(structs3c2410sdi_host*)buf_id;//讀取SD/MMC卡寄存器值

sdi_csta=readl(host->base+S3C2410_SDICMDSTAT);

sdi_dsta=readl(host->base+S3C2410_SDIDSTA);

sdi_dcnt=readl(host->base+S3C2410_SDIDCNT);

spin_lock_irqsave(&host->complete_lock,iflags);

if(!host->mrq)gotoout;

if(!host->mrq->data)gotoout;sdi_csta=readl(host->base+S3C2410_SDICMDSTAT);

sdi_dsta=readl(host->base+S3C2410_SDIDSTA);

sdi_dcnt=readl(host->base+S3C2410_SDIDCNT);

if(result!=S3C2410_RES_OK)

{

printk(“result!=S3C2410_RES_OK\n”);

gotofail_request;

}if(host->mrq->data->flags&MMC_DATA_READ)

{

if(sdi_dcnt>0)

{

printk(“MMC_DATA_READ:sdi_dcnt>0\n”);

gotofail_request;

}

}out:

complete(&host->complete_dma);

spin_unlock_irqrestore(&host->complete_lock,iflags);

return;

fail_request:

host->mrq->data->error=MMC_ERR_FAILED;

host->complete_what=COMPLETION_NONE;

complete(&host->complete_request);

writel(0,host->base+S3C2410_SDIIMSK);

gotoout;

}7.?s3c2410sdi_request()函數(shù)

s3c2410sdi_reques()函數(shù),主要處理SD卡的請求,包括命令、數(shù)據(jù)等,代碼描述如下:

staticvoids3c2410sdi_request(structmmc_host*mmc,structmmc_request*mrq)

{

structs3c2410sdi_host*host=mmc_priv(mmc);

structdevice*dev=mmc_dev(host->mmc);

structplatform_device*pdev=to_platform_device(dev);

u32sdi_carg,sdi_ccon,sdi_timer;

u32sdi_bsize,sdi_dcon,sdi_imsk;

intdma_len=0;

u32sdifsta;sdi_ccon=mrq->cmd->opcode&S3C2410_SDICMDCON_INDEX;

sdi_ccon|=S3C2410_SDICMDCON_SENDERHOST;

sdi_ccon|=S3C2410_SDICMDCON_CMDSTART;

sdi_carg=mrq->cmd->arg;

sdi_timer=0x007FFFFF;sdi_bsize=0;

sdi_dcon=0;

sdi_imsk=0;

/*使能傳輸錯誤中斷*/

sdi_imsk|=S3C2410_SDIIMSK_RESPONSEND;

sdi_imsk|=S3C2410_SDIIMSK_CRCSTATUS;

host->complete_what=COMPLETION_CMDSENT;if(mrq->cmd->flags&MMC_RSP_MASK)

{

host->complete_what=COMPLETION_RSPFIN;

sdi_ccon|=S3C2410_SDICMDCON_WAITRSP;

sdi_imsk|=S3C2410_SDIIMSK_CMDTIMEOUT;

}

else

{

sdi_imsk|=S3C2410_SDIIMSK_CMDSENT;

}if(mrq->cmd->flags&MMC_RSP_LONG)

{

sdi_ccon|=S3C2410_SDICMDCON_LONGRSP;

}

if(mrq->cmd->flags&MMC_RSP_CRC)

{

sdi_imsk|=S3C2410_SDIIMSK_RESPONSECRC;

}if(mrq->data)

{

sdifsta=readl(host->base+S3C2410_SDIFSTA);

sdifsta|=S3C2410_SDICON_FIFORESET;

writel(sdifsta,host->base+S3C2410_SDIFSTA);

host->complete_what=COMPLETION_XFERFINISH_RSPFIN;

sdi_bsize=(1<<mrq->data->blksz_bits);sdi_dcon=(mrq->data->blocks&S3C2410_SDIDCON_BLKNUM_MASK);

sdi_dcon|=S3C2410_SDIDCON_DMAEN;

sdi_dcon|=S3C2410_SDIDCON_DTST;

sdi_imsk|=S3C2410_SDIIMSK_FIFOFAIL;

sdi_imsk|=S3C2410_SDIIMSK_DATACRC;

sdi_imsk|=S3C2410_SDIIMSK_DATATIMEOUT;

sdi_imsk|=S3C2410_SDIIMSK_DATAFINISH;

sdi_imsk|=0xFFFFFFE0;if(host->bus_width==MMC_BUS_WIDTH_4)

{

DBG(PFX“MMC_BUS_WIDTH_4\n”);

sdi_dcon|=S3C2410_SDIDCON_WIDEBUS;

}

if(!(mrq->data->flags&MMC_DATA_STREAM))

{

sdi_dcon|=S3C2410_SDIDCON_BLOCKMODE;

DBG(PFX“MMC_DATA_BLOCK\n”);

}

if(mrq->data->flags&MMC_DATA_WRITE)

{

DBG(PFX“MMC_DATA_WRITE\n”);

sdi_dcon|=S3C2410_SDIDCON_TXAFTERRESP;

sdi_dcon|=S3C2410_SDIDCON_XFER_TXSTART;

sdi_dcon|=S3C2410_SDIDCON_DAT_WD;

sdi_dcon|=S3C2410_SDIDCON_BURST4;

}

if(mrq->data->flags&MMC_DATA_READ)

{

DBG(PFX“MMC_DATA_READ\n”);

sdi_dcon|=S3C2410_SDIDCON_RXAFTERCMD;

sdi_dcon|=S3C2410_SDIDCON_XFER_RXSTART;

sdi_dcon|=S3C2410_SDIDCON_DAT_WD;

//sdi_dcon|=S3C2410_SDIDCON_BURST4;

}

s3c2410sdi_dma_setup(host,mrq->data->flags&MMC_DATA_WRITE?

S3C2410_DMASRC_MEM:S3C2410_DMASRC_HW);dma_len=dma_map_sg(&pdev->dev,mrq->data->sg,mrq->data->sg_len,mrq->data->flags

&MMC_DATA_READ?DMA_FROM_DEVICE:DMA_TO_DEVICE);

DBG(PFX"dma_len:0x%08x\n",dma_len);

/*開始DMA*/

s3c2410_dma_enqueue(host->dma,(void*)host,

sg_dma_address(&mrq->data->sg[0]),

(mrq->data->blocks<<mrq->data->blksz_bits));

}host->mrq=mrq;

init_completion(&host->complete_request);

init_completion(&host->complete_dma);

/*清除命令狀態(tài)寄存器*/

writel(0xFFFFFFFF,host->base+S3C2410_SDICMDSTAT);

writel(0xFFFFFFFF,host->base+S3C2410_SDIDSTA);/*設(shè)置SDI控制器*/

writel(sdi_bsize,host->base+S3C2410_SDIBSIZE);

writel(sdi_timer,host->base+S3C2410_SDITIMER);

writel(sdi_imsk,host->base+S3C2410_SDIIMSK);

/*設(shè)置SDI命令參數(shù)和數(shù)據(jù)寄存器*/

writel(sdi_carg,host->base+S3C2410_SDICMDARG);

writel(sdi_dcon,host->base+S3C2410_SDIDCON);

//Thisinitiatestransfer

writel(sdi_ccon,host->base+S3C2410_SDICMDCON);/*等待傳輸完成*/

wait_for_completion(&host->complete_request);

DBG("[CMD]requestcomplete.\n");

if(mrq->data)

{

wait_for_completion(&host->complete_dma);

}

/*清除SD/MMC控制器和寄存器*/

writel(0,host->base+S3C2410_SDICMDARG);

writel(0,host->base+S3C2410_SDIDCON);

writel(0,host->base+S3C2410_SDICMDCON);

writel(0,host->base+S3C2410_SDIIMSK);/*讀取響應(yīng)*/

mrq->cmd->resp[0]=readl(host->base+S3C2410_SDIRSP0);

mrq->cmd->resp[1]=readl(host->base+S3C2410_SDIRSP1);

mrq->cmd->resp[2]=readl(host->base+S3C2410_SDIRSP2);

mrq->cmd->resp[3]=readl(host->base+S3C2410_SDIRSP3);

host->mrq=NULL;

if(!mrq->data)gotorequest_done;dma_unmap_sg(&pdev->dev,mrq->data->sg,dma_len,\

mrq->data

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論