linux SPI驅動——gpio模擬spi驅動(三)

一:首先在個人平臺註冊platform_device,保證能讓spi-gpio.c能執行到probe函數。css

 1: struct spi_gpio_platform_data {
 2:     unsigned    sck;
 3:     unsigned    mosi;
 4:     unsigned    miso;
 5:  
 6:     u16        num_chipselect;
 7: };
 1: //#define NCS GPIO_PB(2) //定義SS所對應的GPIO接口編號 
 2: //#define SCLK GPIO_PB(0) //定義SCLK所對應的GPIO接口編號 
 3: //#define MOSI GPIO_PB(4) //定義SCLK所對應的GPIO接口編號 
 4: //#define MISO GPIO_PB(1)
 5: static struct spi_gpio_platform_data jz_spi_gpio_data = {
 6:     .sck    = GPIO_PB(0),    //GPIO_SPI_SCK,
 7:     .mosi    = GPIO_PB(4),     //GPIO_SPI_MOSI,
 8:     .miso    = GPIO_PB(1),    //GPIO_SPI_MISO,
 9:     .num_chipselect = 1,
 10: };
 11:  
 12: struct platform_device jz_spi_gpio_device = {
 13:     .name   = "spi_gpio",
 14:     .id     = 0, 
 15:     .dev    = {
 16:         .platform_data = &jz_spi_gpio_data,
 17:     },
 18: };
註冊platform device
1: platform_device_register(&jz_spi_gpio_device);
 
二:註冊platform_driver在spi_gpio.c裏面註冊platform driver
 1: MODULE_ALIAS("platform:" DRIVER_NAME);
 2:  
 3: static struct platform_driver spi_gpio_driver = {
 4:     .driver.name    = DRIVER_NAME,
 5:     .driver.owner    = THIS_MODULE,
 6:     .remove        = __exit_p(spi_gpio_remove),
 7: };
 8:  
 9: static int __init spi_gpio_init(void)
 10: {
 11:     return platform_driver_probe(&spi_gpio_driver, spi_gpio_probe);
 12: }
 13: module_init(spi_gpio_init);
 14:  
 15: static void __exit spi_gpio_exit(void)
 16: {
 17:     platform_driver_unregister(&spi_gpio_driver);
 18: }
 19: module_exit(spi_gpio_exit);
 20:  
 21:  
 22: MODULE_DESCRIPTION("SPI master driver using generic bitbanged GPIO ");
 23: MODULE_AUTHOR("David Brownell");
 24: MODULE_LICENSE("GPL");
 

三:具體算法分析html

 1: struct spi_gpio {
 2:     struct spi_bitbang          bitbang;        /* gpio 模擬spi算法相關的結構 */
 3:     struct spi_gpio_platform_data  pdata;        /* spi platform data 對應模擬spi的四個gpio編號 */
 4:     struct platform_device    *pdev;        /* 對應註冊的 platform device */
 5: };
 1:  
 2: static int __init spi_gpio_probe(struct platform_device *pdev)
 3: {
 4:     int                status;
 5:     struct spi_master        *master;
 6:     struct spi_gpio            *spi_gpio;
 7:     struct spi_gpio_platform_data    *pdata;
 8:     u16 master_flags = 0;
 9:  
 10:     pdata = pdev->dev.platform_data; /* 存放spi的四根gpio */
 11: #ifdef GENERIC_BITBANG
 12:     if (!pdata || !pdata->num_chipselect)
 13:         return -ENODEV;
 14: #endif
 15:  
 16:     /* 申請註冊四個gpio */
 17:     status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags);
 18:     if (status < 0) {
 19:         return status;
 20:     }
 21:  
 22:     /* alloc a spi master ,master->dev->p->driver_data = &master[1]*/
 23:     master = spi_alloc_master(&pdev->dev, sizeof *spi_gpio);
 24:     if (!master) {
 25:         status = -ENOMEM;
 26:         goto gpio_free;
 27:     }
 28:     /* spi_gpio指向一塊空間, 即指向mstaer[1] 
 29:  pdev->dev->p->driver_data = spi_gpio;
 30:  初始化spi_gpio
 31:  */
 32:     spi_gpio = spi_master_get_devdata(master);
 33:     platform_set_drvdata(pdev, spi_gpio); 
 34:  
 35:     spi_gpio->pdev = pdev;
 36:     if (pdata)
 37:         spi_gpio->pdata = *pdata;
 38:  
 39:     master->flags = master_flags;
 40:     master->bus_num = pdev->id;
 41:     master->num_chipselect = SPI_N_CHIPSEL;
 42:     master->setup = spi_gpio_setup; /* setup 好比cs引腳申請 */
 43:     master->cleanup = spi_gpio_cleanup;
 44:     /* spi_gpio->bitbang.master = master */
 45:     spi_gpio->bitbang.master = spi_master_get(master);
 46:     spi_gpio->bitbang.chipselect = spi_gpio_chipselect;
 47:     /* spi_gpio->bitbang.txrx_word 數組函數四個元素指針,分別指向spi四種mode算法函數 */
 48:     if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) {
 49:         spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;
 50:         spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1;
 51:         spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;
 52:         spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3;
 53:     } else {
 54:         spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0;
 55:         spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1;
 56:         spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2;
 57:         spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3;
 58:     }
 59:     /* spi_gpio->bitbang.setup_transfer初始化傳輸的bits_per_word和speed */
 60:     spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;
 61:     spi_gpio->bitbang.flags = SPI_CS_HIGH;
 62:     /* spi_gpio->bitbang相關算法接口初始化 */
 63:     status = spi_bitbang_start(&spi_gpio->bitbang);
 64:     if (status < 0) {
 65:         spi_master_put(spi_gpio->bitbang.master);
 66: gpio_free:
 67:         if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
 68:             gpio_free(SPI_MISO_GPIO);
 69:         if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
 70:             gpio_free(SPI_MOSI_GPIO);
 71:         gpio_free(SPI_SCK_GPIO);
 72:         spi_master_put(master);
 73:     }
 74:  
 75:     return status;
 76: }
 
四:總之最終讓spi_gpi0整個對象存放了整個gpio模擬spi的算法結構;而pdev->dev->p->driver_data = spi_gpio;
platform device和 platform driver二者match結果是:

root@CarRadio:/# ls /sys/bus/platform/devices/spi_gpio.0/
driver      modalias    power       spi0.0      spi_master  subsystem   uevent
root@CarRadio:/# ls /sys/bus/platform/devices/spi_gpio.0/driver/
spi_gpio.0  uevent
算法

相關文章
相關標籤/搜索