基于S3C2440的嵌入式Linux驅(qū)動(dòng)——SPI子系統(tǒng)解讀(二)
掃描二維碼
隨時(shí)隨地手機(jī)看文章
本文屬于第二部分。
4. 主控制器驅(qū)動(dòng)程序
4.1 定義 platform device
下列數(shù)據(jù)結(jié)構(gòu)位于arch/arm/plat-s3c24XX/devs.c
/*SPI(0)*/
staticstructresources3c_spi0_resource[]={
[0]={
.start=S3C24XX_PA_SPI,
.end=S3C24XX_PA_SPI+0x1f,
.flags=IORESOURCE_MEM,
},
[1]={
.start=IRQ_SPI0,
.end=IRQ_SPI0,
.flags=IORESOURCE_IRQ,
}
};
staticu64s3c_device_spi0_dmamask=0xffffffffUL;
structplatform_devices3c_device_spi0={
.name="s3c2410-spi",
.id=0,
.num_resources=ARRAY_SIZE(s3c_spi0_resource),
.resource=s3c_spi0_resource,
.dev={
.dma_mask=&s3c_device_spi0_dmamask,
.coherent_dma_mask=0xffffffffUL
}
};
platform設(shè)備給出了spi0接口的寄存器地址資源以及IRQ資源。注意其設(shè)備名為s3c2410-spi。
4.2 定義platform driver
下列函數(shù)位于deivers/spi/s3c24xx.c。
MODULE_ALIAS("platform:s3c2410-spi");
staticstructplatform_drivers3c24xx_spi_driver={
.remove=__exit_p(s3c24xx_spi_remove),
.suspend=s3c24xx_spi_suspend,
.resume=s3c24xx_spi_resume,
.driver={
.name="s3c2410-spi",
.owner=THIS_MODULE,
},
};
staticint__inits3c24xx_spi_init(void)
{
returnplatform_driver_probe(&s3c24xx_spi_driver,s3c24xx_spi_probe);//設(shè)備不可熱插拔,所以使用該函數(shù),而不是platform_driver_register
}
staticvoid__exits3c24xx_spi_exit(void)
{
platform_driver_unregister(&s3c24xx_spi_driver);
}
module_init(s3c24xx_spi_init);
module_exit(s3c24xx_spi_exit);
調(diào)用了platform_driver_probe注冊(cè)platform驅(qū)動(dòng),注冊(cè)完成以后將會(huì)調(diào)用platform的s3c24xx_spi_probe函數(shù)。
NOTE:platform驅(qū)動(dòng)的name和platform device的name是相同的。
4.2.1s3c24xx_spi_probe函數(shù)
下列函數(shù)位于deivers/spi/s3c24xx.c。
staticint__inits3c24xx_spi_probe(structplatform_device*pdev)
{
structs3c2410_spi_info*pdata;
structs3c24xx_spi*hw;
structspi_master*master;
structresource*res;
interr=0;
/*分配master結(jié)構(gòu)體,其中包括s3c24xx_spi結(jié)構(gòu)的內(nèi)存空間,使用master.dev.driver_data指向它*/
master=spi_alloc_master(&pdev->dev,sizeof(structs3c24xx_spi));
if(master==NULL){
dev_err(&pdev->dev,"Nomemoryforspi_mastern");
err=-ENOMEM;
gotoerr_nomem;
}
/*獲得s3c24xx_spi結(jié)構(gòu),并清0該結(jié)構(gòu)*/
hw=spi_master_get_devdata(master);
memset(hw,0,sizeof(structs3c24xx_spi));
hw->master=spi_master_get(master);/*保存master結(jié)構(gòu)體,同時(shí)增加引用計(jì)數(shù)*/
hw->pdata=pdata=pdev->dev.platform_data;/*獲取s3c2410_spi_info結(jié)構(gòu)體指針*/
hw->dev=&pdev->dev;/*保存platform設(shè)備的dev*/
if(pdata==NULL){
dev_err(&pdev->dev,"Noplatformdatasuppliedn");
err=-ENOENT;
gotoerr_no_pdata;
}
platform_set_drvdata(pdev,hw);/*讓platform_devuce.dev.driver_data指向s3c24xx_spi*/
init_completion(&hw->done);/*初始化completion*/
/*setupthemasterstate.*//*填充master結(jié)構(gòu)體的兩個(gè)字段*/
master->num_chipselect=hw->pdata->num_cs;
master->bus_num=pdata->bus_num;
/*setupthestateforthebitbangdriver*//*填充bitbang字段*/
hw->bitbang.master=hw->master;
hw->bitbang.setup_transfer=s3c24xx_spi_setupxfer;
hw->bitbang.chipselect=s3c24xx_spi_chipsel;
hw->bitbang.txrx_bufs=s3c24xx_spi_txrx;
hw->bitbang.master->setup=s3c24xx_spi_setup;
dev_dbg(hw->dev,"bitbangat%pn",&hw->bitbang);
/*findandmapourresources*/
res=platform_get_resource(pdev,IORESOURCE_MEM,0);/*獲取IO資源*/
if(res==NULL){
dev_err(&pdev->dev,"CannotgetIORESOURCE_MEMn");
err=-ENOENT;
gotoerr_no_iores;
}
hw->ioarea=request_mem_region(res->start,(res->end-res->start)+1,/*申請(qǐng)IO內(nèi)存*/
pdev->name);
if(hw->ioarea==NULL){
dev_err(&pdev->dev,"Cannotreserveregionn");
err=-ENXIO;
gotoerr_no_iores;
}
hw->regs=ioremap(res->start,(res->end-res->start)+1);/*建立映射*/
if(hw->regs==NULL){