Linux設備驅動剖析之SPI(一)


寫在前面

        初次接觸SPI是因為幾年前玩單片機的時候,由於普通的51單片機沒有SPI控制器,所以只好用IO口去模擬。最近一次接觸SPI是大三時參加的校內選拔賽,當時需要用2440去控制nrf24L01,從而實現數據的無線傳輸。nrf24L01是一種典型的SPI接口的2.4GHz無線收發器,當時搞了很久,由於時間比較緊,而且當時根本不熟悉Linux的SPI子系統,最后雖然采用IO口模擬SPI的方式勉強實現了,但是這根本就不符合Linux驅動的編程規范,或者說是在破壞Linux、污染kernel。

     根據我個人所知道的,Linux SPI一直是處於被“忽略”的角色,市場上大部分板子在板級文件里都沒有關於SPI的相關代碼,而大部分講驅動的書籍也沒有專門的一章來講述關於Linux SPI方面的內容,與IIC相比,SPI就是一個不被重視的“家伙”,為什么?我也不知道。為了幫SPI抱打不平,我決定基於Linux-2.6.36,說說Linux中SPI子系統。

     先給出Linux SPI子系統的體系結構圖:

                         SPI子系統體系結構

下面開始分析SPI子系統。

Linux中SPI子系統的初始化是從drivers/spi/spi.c文件中的spi_init函數開始的,看看它的定義:

00001025 static int __init spi_init(void)
00001026 {
00001027     int    status;
00001028 
00001029     buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
00001030     if (!buf) {
00001031         status = -ENOMEM;
00001032         goto err0;
00001033     }
00001034 
00001035     status = bus_register(&spi_bus_type);
00001036     if (status < 0)
00001037         goto err1;
00001038 
00001039     status = class_register(&spi_master_class);
00001040     if (status < 0)
00001041         goto err2;
00001042     return 0;
00001043 
00001044 err2:
00001045     bus_unregister(&spi_bus_type);
00001046 err1:
00001047     kfree(buf);
00001048     buf = NULL;
00001049 err0:
00001050     return status;
00001051 }

1029行,分配spi buf內存,其中buf和SPI_BUFSIZ都在spi.c文件中定義:

00000945 #define    SPI_BUFSIZ    max(32,SMP_CACHE_BYTES)
00000946 
00000947 static u8    *buf;

1035行,注冊spi總線,同樣是在spi.c文件中:

00000145 struct bus_type spi_bus_type = {
00000146     .name        = "spi",
00000147     .dev_attrs    = spi_dev_attrs,
00000148     .match        = spi_match_device,
00000149     .uevent        = spi_uevent,
00000150     .suspend        = spi_suspend,
00000151     .resume        = spi_resume,
00000152 };

146行,總線的名字就叫spi。

148行,比較重要的,spi_match_device是spi總線上匹配設備和設備驅動的函數,同樣是在spi.c文件中:

00000085 static int spi_match_device(struct device *dev, struct device_driver *drv)
00000086 {
00000087     const struct spi_device    *spi = to_spi_device(dev);
00000088     const struct spi_driver    *sdrv = to_spi_driver(drv);
00000089 
00000090     /* Attempt an OF style match */
00000091     if (of_driver_match_device(dev, drv))
00000092         return 1;
00000093 
00000094     if (sdrv->id_table)
00000095         return !!spi_match_id(sdrv->id_table, spi);
00000096 
00000097     return strcmp(spi->modalias, drv->name) == 0;
00000098 }

寫過驅動的都應該知道platform總線有struct platform_device和struct platform_driver,到了SPI總線,當然也有對應的struct spi_device和struct spi_driver,如87、88行所示。87行,關於struct spi_device的定義是在include/linux/spi/spi.h中:

00000069 struct spi_device {
00000070     struct device        dev;
00000071     struct spi_master    *master;
00000072     u32            max_speed_hz;
00000073     u8            chip_select;
00000074     u8            mode;
00000075 #define    SPI_CPHA    0x01            /* clock phase */
00000076 #define    SPI_CPOL    0x02            /* clock polarity */
00000077 #define    SPI_MODE_0    (0|0)            /* (original MicroWire) */
00000078 #define    SPI_MODE_1    (0|SPI_CPHA)
00000079 #define    SPI_MODE_2    (SPI_CPOL|0)
00000080 #define    SPI_MODE_3    (SPI_CPOL|SPI_CPHA)
00000081 #define    SPI_CS_HIGH    0x04            /* chipselect active high? */
00000082 #define    SPI_LSB_FIRST    0x08            /* per-word bits-on-wire */
00000083 #define    SPI_3WIRE    0x10            /* SI/SO signals shared */
00000084 #define    SPI_LOOP    0x20            /* loopback mode */
00000085 #define    SPI_NO_CS    0x40            /* 1 dev/bus, no chipselect */
00000086 #define    SPI_READY    0x80            /* slave pulls low to pause */
00000087     u8            bits_per_word;
00000088     int            irq;
00000089     void            *controller_state;
00000090     void            *controller_data;
00000091     char            modalias[SPI_NAME_SIZE];
00000092 
00000093     /*
00000094      * likely need more hooks for more protocol options affecting how
00000095      * the controller talks to each chip, like:
00000096      *  - memory packing (12 bit samples into low bits, others zeroed)
00000097      *  - priority
00000098      *  - drop chipselect after each word
00000099      *  - chipselect delays
00000100      *  - ...
00000101      */
00000102 };

70行,dev,嵌入到設備模型中用的。

71行,master,spi設備的更高層描述,每一個spi控制器就對應一個master,一個spi設備必須對應一個master,master下可以有多個spi設備。

72,73行沒什么好說的,從變量的名字就可以明白。

74行,mode,針對時鍾相位CPHA(0或1)和時鍾極性CPOL(0或1)的不同組合,將spi分成四種模式,就是77至80行這四種。CPOL表示當空閑時(沒有進行數據傳輸)時鍾信號的電平,CPOL=0表示低電平,CPOL=1表示高電平。每個時鍾周期都有兩次電平的跳變,上升沿和下降沿,CPHA就表示在每個時鍾周期里是第一個邊沿采樣數據還是第二個邊沿采樣數據,具體第一個邊沿或者第二個邊沿是上升沿還是下降沿則由CPOL決定。看下面這張圖就明白了。藍色箭頭表示對數據進行采樣。

87行,如果傳輸是以字節為單位的話就設置為8,相應地,如果是以2個字節為單位則設置為16。

88行,中斷號。89行,沒有使用,在后面會看到這個值會被設置為NULL。90行,后面講到具體的控制器再說。91行,很重要,一般來說設備與驅動能否匹配起來就要看它,注意,這里只是說一般,因為還有另外兩種匹配的方法,不過大部分設備和驅動能否匹配起來都是根據名字是否相等,當然像USB驅動就不是根據名字來匹配的,而是根據與id table。struct spi_driver的定義也是在include/linux/spi/spi.h:

00000175 struct spi_driver {
00000176     const struct spi_device_id *id_table;
00000177     int            (*probe)(struct spi_device *spi);
00000178     int            (*remove)(struct spi_device *spi);
00000179     void            (*shutdown)(struct spi_device *spi);
00000180     int            (*suspend)(struct spi_device *spi, pm_message_t mesg);
00000181     int            (*resume)(struct spi_device *spi);
00000182     struct device_driver    driver;
00000183 };

182行,driver就是在設備模型中使用的那個device_driver,其他都是一些函數指針的定義,挺熟悉的了,就不多說了。

      回到spi_match_device函數,91行和95行就是設備和驅動匹配的另外兩種方法,因為后文要講的spi驅動使用的是第三種方法,因此這里就不討論這兩種方法了。97行,根據設備名和驅動名是否相等進行匹配,相等則返回1,表示匹配成功,此時驅動里的probe函數將會被調用,這也是我們最希望看到的,返回0則表示匹配失敗。

      我們知道,對於具體的平台,nand、iic、frame buffer等這些都是平台設備,spi當然也一樣是平台設備,對於平台設備,大部分情況下是先注冊設備再注冊驅動。因此下面就以tiny6410為具體平台,按照這種先后順序來講述。

S3c6410有兩個SPI控制器,以SPI0為例就可以了。首先看s3c6410中關於SPI0控制器的描述,在arch/arm/mach-s3c64xx/dev-spi.c文件中:

00000101 struct platform_device s3c64xx_device_spi0 = {
00000102     .name          = "s3c64xx-spi",
00000103     .id          = 0,
00000104     .num_resources      = ARRAY_SIZE(s3c64xx_spi0_resource),
00000105     .resource      = s3c64xx_spi0_resource,
00000106     .dev = {
00000107         .dma_mask        = &spi_dmamask,
00000108         .coherent_dma_mask    = DMA_BIT_MASK(32),
00000109         .platform_data = &s3c64xx_spi0_pdata,
00000110     },
00000111 };

102行,驅動能否與這個設備匹配,就看這個名字了,因此對應的驅動名字必須與之一樣。103行,SPI控制器的ID,SPI0控制器就為0,SPI1控制器就為1。

104和105行是關於IO口資源、DMA資源和中斷資源的。107、108行是關於DMA的,不說了。109行,給驅動用的,在驅動那里再說。在板初始化函數mini6410_machine_init里調用platform_add_devices函數就可以將SPI0設備注冊到platform總線上。

S3c6410的SPI控制器驅動在drivers/spi/spi_s3c64xx.c文件里。初始化函數:

00001183 static int __init s3c64xx_spi_init(void)
00001184 {
00001185     return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe);
00001186 }

1185行,s3c64xx_spi_driver是struct platform_driver的實例,也在spi_s3c64xx.c文件中定義:

00001172 static struct platform_driver s3c64xx_spi_driver = {
00001173     .driver = {
00001174         .name    = "s3c64xx-spi",
00001175         .owner = THIS_MODULE,
00001176     },
00001177     .remove = s3c64xx_spi_remove,
00001178     .suspend = s3c64xx_spi_suspend,
00001179     .resume = s3c64xx_spi_resume,
00001180 };

1174行,看到了沒?和之前在s3c64xx_device_spi0里定義的名字是一樣的,這樣它們就可以匹配起來,1185行的s3c64xx_spi_probe驅動探測函數就會被調用,看下它的定義:

00000911 static int __init s3c64xx_spi_probe(struct platform_device *pdev)
00000912 {
00000913     struct resource    *mem_res, *dmatx_res, *dmarx_res;
00000914     struct s3c64xx_spi_driver_data *sdd;
00000915     struct s3c64xx_spi_info *sci;
00000916     struct spi_master *master;
00000917     int ret;
00000918 
00000919     if (pdev->id < 0) {
00000920         dev_err(&pdev->dev,
00000921                 "Invalid platform device id-%d\n", pdev->id);
00000922         return -ENODEV;
00000923     }
00000924 
00000925     if (pdev->dev.platform_data == NULL) {
00000926         dev_err(&pdev->dev, "platform_data missing!\n");
00000927         return -ENODEV;
00000928     }
00000929 
00000930     sci = pdev->dev.platform_data;
00000931     if (!sci->src_clk_name) {
00000932         dev_err(&pdev->dev,
00000933             "Board init must call s3c64xx_spi_set_info()\n");
00000934         return -EINVAL;
00000935     }
00000936 
00000937     /* Check for availability of necessary resource */
00000938 
00000939     dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
00000940     if (dmatx_res == NULL) {
00000941         dev_err(&pdev->dev, "Unable to get SPI-Tx dma resource\n");
00000942         return -ENXIO;
00000943     }
00000944 
00000945     dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
00000946     if (dmarx_res == NULL) {
00000947         dev_err(&pdev->dev, "Unable to get SPI-Rx dma resource\n");
00000948         return -ENXIO;
00000949     }
00000950 
00000951     mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
00000952     if (mem_res == NULL) {
00000953         dev_err(&pdev->dev, "Unable to get SPI MEM resource\n");
00000954         return -ENXIO;
00000955     }
00000956 
00000957     master = spi_alloc_master(&pdev->dev,
00000958                 sizeof(struct s3c64xx_spi_driver_data));
00000959     if (master == NULL) {
00000960         dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
00000961         return -ENOMEM;
00000962     }
00000963 
00000964     platform_set_drvdata(pdev, master);
00000965 
00000966     sdd = spi_master_get_devdata(master);
00000967     sdd->master = master;
00000968     sdd->cntrlr_info = sci;
00000969     sdd->pdev = pdev;
00000970     sdd->sfr_start = mem_res->start;
00000971     sdd->tx_dmach = dmatx_res->start;
00000972     sdd->rx_dmach = dmarx_res->start;
00000973 
00000974     sdd->cur_bpw = 8;
00000975 
00000976     master->bus_num = pdev->id;
00000977     master->setup = s3c64xx_spi_setup;
00000978     master->transfer = s3c64xx_spi_transfer;
00000979     master->num_chipselect = sci->num_cs;
00000980     master->dma_alignment = 8;
00000981     /* the spi->mode bits understood by this driver: */
00000982     
00000983     master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
00000984 
00000985     if (request_mem_region(mem_res->start,
00000986             resource_size(mem_res), pdev->name) == NULL) {
00000987         dev_err(&pdev->dev, "Req mem region failed\n");
00000988         ret = -ENXIO;
00000989         goto err0;
00000990     }
00000991 
00000992     sdd->regs = ioremap(mem_res->start, resource_size(mem_res));
00000993     if (sdd->regs == NULL) {
00000994         dev_err(&pdev->dev, "Unable to remap IO\n");
00000995         ret = -ENXIO;
00000996         goto err1;
00000997     }
00000998 
00000999     if (sci->cfg_gpio == NULL || sci->cfg_gpio(pdev)) {
00001000         dev_err(&pdev->dev, "Unable to config gpio\n");
00001001         ret = -EBUSY;
00001002         goto err2;
00001003     }
00001004 
00001005     /* Setup clocks */
00001006     sdd->clk = clk_get(&pdev->dev, "spi");
00001007     if (IS_ERR(sdd->clk)) {
00001008         dev_err(&pdev->dev, "Unable to acquire clock 'spi'\n");
00001009         ret = PTR_ERR(sdd->clk);
00001010         goto err3;
00001011     }
00001012 
00001013     if (clk_enable(sdd->clk)) {
00001014         dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n");
00001015         ret = -EBUSY;
00001016         goto err4;
00001017     }
00001018 
00001019     sdd->src_clk = clk_get(&pdev->dev, sci->src_clk_name);
00001020     if (IS_ERR(sdd->src_clk)) {
00001021         dev_err(&pdev->dev,
00001022             "Unable to acquire clock '%s'\n", sci->src_clk_name);
00001023         ret = PTR_ERR(sdd->src_clk);
00001024         goto err5;
00001025     }
00001026 
00001027     if (clk_enable(sdd->src_clk)) {
00001028         dev_err(&pdev->dev, "Couldn't enable clock '%s'\n",
00001029                             sci->src_clk_name);
00001030         ret = -EBUSY;
00001031         goto err6;
00001032     }
00001033 
00001034     sdd->workqueue = create_singlethread_workqueue(
00001035                         dev_name(master->dev.parent));
00001036     if (sdd->workqueue == NULL) {
00001037         dev_err(&pdev->dev, "Unable to create workqueue\n");
00001038         ret = -ENOMEM;
00001039         goto err7;
00001040     }
00001041 
00001042     /* Setup Deufult Mode */
00001043     s3c64xx_spi_hwinit(sdd, pdev->id);
00001044 
00001045     spin_lock_init(&sdd->lock);
00001046     init_completion(&sdd->xfer_completion);
00001047     INIT_WORK(&sdd->work, s3c64xx_spi_work);
00001048     INIT_LIST_HEAD(&sdd->queue);
00001049 
00001050     if (spi_register_master(master)) {
00001051         dev_err(&pdev->dev, "cannot register SPI master\n");
00001052         ret = -EBUSY;
00001053         goto err8;
00001054     }
00001055 
00001056     dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d "
00001057                     "with %d Slaves attached\n",
00001058                     pdev->id, master->num_chipselect);
00001059     dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
00001060                     mem_res->end, mem_res->start,
00001061                     sdd->rx_dmach, sdd->tx_dmach);
00001062 
00001063     return 0;
00001064 
00001065 err8:
00001066     destroy_workqueue(sdd->workqueue);
00001067 err7:
00001068     clk_disable(sdd->src_clk);
00001069 err6:
00001070     clk_put(sdd->src_clk);
00001071 err5:
00001072     clk_disable(sdd->clk);
00001073 err4:
00001074     clk_put(sdd->clk);
00001075 err3:
00001076 err2:
00001077     iounmap((void *) sdd->regs);
00001078 err1:
00001079     release_mem_region(mem_res->start, resource_size(mem_res));
00001080 err0:
00001081     platform_set_drvdata(pdev, NULL);
00001082     spi_master_put(master);
00001083 
00001084     return ret;
00001085 }

函數很長,但做的東西卻很簡單。919至923行,SPI控制器的ID是從0開始的,小於0的話,沒門,出錯。

925至928行,必須要有platform_data,否則出錯。930行,如果platform_data存在的話就把它取出來。

931至935行,如果src_clk_name為0,則表示在板初始化函數里沒有調用s3c64xx_spi_set_info函數。

939至955行,獲取在設備里定義的IO口和DMA資源。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM