• linux SPI驱动——gpio模拟spi驱动(三)


    一:首先在我的平台注册platform_device,保证能让spi-gpio.c能执行到probe函数。

       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");
     

    三:具体算法分析

       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

  • 相关阅读:
    在Spring Bean的生命周期中各方法的执行顺序
    java面试宝典
    js代码中实现页面跳转的几种方式
    APP测试学习:系统资源分析
    APP测试学习:webview性能分析
    APP测试学习:app启动性能分析
    App测试学习:自动遍历测试
    性能测试学习:jmeter通过代理录制、回放请求
    Docker学习五:如何搭建私有仓库
    Docker学习四:容器基本操作
  • 原文地址:https://www.cnblogs.com/xuyh/p/6025783.html
Copyright © 2020-2023  润新知