![《基于S3C2440的嵌入式Linux開發(fā)實例》課件第4章_第1頁](http://file4.renrendoc.com/view7/M01/0B/22/wKhkGWbPHVGAEyolAACraOGTLcc365.jpg)
![《基于S3C2440的嵌入式Linux開發(fā)實例》課件第4章_第2頁](http://file4.renrendoc.com/view7/M01/0B/22/wKhkGWbPHVGAEyolAACraOGTLcc3652.jpg)
![《基于S3C2440的嵌入式Linux開發(fā)實例》課件第4章_第3頁](http://file4.renrendoc.com/view7/M01/0B/22/wKhkGWbPHVGAEyolAACraOGTLcc3653.jpg)
![《基于S3C2440的嵌入式Linux開發(fā)實例》課件第4章_第4頁](http://file4.renrendoc.com/view7/M01/0B/22/wKhkGWbPHVGAEyolAACraOGTLcc3654.jpg)
![《基于S3C2440的嵌入式Linux開發(fā)實例》課件第4章_第5頁](http://file4.renrendoc.com/view7/M01/0B/22/wKhkGWbPHVGAEyolAACraOGTLcc3655.jpg)
版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 辦公園林綠化合同范本
- 2025年度辦事處設(shè)計及智能化辦公系統(tǒng)合同
- 兒童玩具商標(biāo)轉(zhuǎn)讓居間合同
- 玻璃制品廠出租居間合同
- 第三人房產(chǎn)抵押擔(dān)保合同
- 網(wǎng)絡(luò)故障排除與維護(hù)手冊
- 工程中介居間合同
- 三農(nóng)產(chǎn)品安全檢測技術(shù)指南
- 大數(shù)據(jù)應(yīng)用與服務(wù)平臺建設(shè)項目合同
- 供應(yīng)商管理與采購合同談判規(guī)定
- 四川省自貢市2024-2025學(xué)年上學(xué)期八年級英語期末試題(含答案無聽力音頻及原文)
- 2025-2030年中國汽車防滑鏈行業(yè)競爭格局展望及投資策略分析報告新版
- 2025年上海用人單位勞動合同(4篇)
- 二年級上冊口算題3000道-打印版讓孩子口算無憂
- 新疆烏魯木齊地區(qū)2025年高三年級第一次質(zhì)量監(jiān)測生物學(xué)試卷(含答案)
- 衛(wèi)生服務(wù)個人基本信息表
- 高中英語北師大版必修第一冊全冊單詞表(按單元編排)
- 新教科版科學(xué)小學(xué)四年級下冊全冊教案
- 苗圃建設(shè)項目施工組織設(shè)計范本
- 2024中考語文試卷及答案長沙
- 廣東省湛江市廉江市2023-2024學(xué)年八年級上學(xué)期期末考試數(shù)學(xué)試卷(含答案)
評論
0/150
提交評論