国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
davinci平臺的spi驅動框架
davinci平臺的spi驅動框架
http://blog.chinaunix.net/uid-27717694-id-3774328.html

  1. 一、SPI總線概述
  2. SPI是英語Serial Peripheral interface的縮寫,顧名思義就是串行外圍設備接口,是Motorola首先在其MC68HCXX系列處理器上定義的。SPI接口主要應用在 EEPROM,F(xiàn)LASH,實時時鐘,AD轉換器,還有數(shù)字信號處理器和數(shù)字信號解碼器之間。SPI是一種高速的,全雙工,同步的通信總線,并且在芯片的管腳上只占用四根線,節(jié)約了芯片的管腳,同時為PCB的布局上節(jié)省空間,提供方便。
  3. SPI的通信原理很簡單,它以主從方式工作,這種模式通常有一個主設備和一個或多個從設備,需要4根線,事實上3根也可以。也是所有基于SPI的設備共有的,它們是SDI(數(shù)據(jù)輸入),SDO(數(shù)據(jù)輸出),SCLK(時鐘),CS(片選)
  4. MOSI(SDO):主器件數(shù)據(jù)輸出,從器件數(shù)據(jù)輸入。
  5. MISO(SDI):主器件數(shù)據(jù)輸入,從器件數(shù)據(jù)輸出。
  6. SCLK :時鐘信號,由主器件產生。
  7. CS:從器件使能信號,由主器件控制。
  8. 其中CS是控制芯片是否被選中的,也就是說只有片選信號為預先規(guī)定的使能信號時(高電位或低電位),對此芯片的操作才有效,這就允許在同一總線上連接多個SPI設備成為可能。需要注意的是,在具體的應用中,當一條SPI總線上連接有多個設備時,SPI本身的CS有可能被其他的GPIO腳代替,即每個設備的CS腳被連接到處理器端不同的GPIO,通過操作不同的GPIO口來控制具體的需要操作的SPI設備,減少各個SPI設備間的干擾。
  9. SPI是串行通訊協(xié)議,也就是說數(shù)據(jù)是一位一位從MSB或者LSB開始傳輸?shù)?,這就是SCK時鐘線存在的原因,由SCK提供時鐘脈沖,MISO、MOSI則基于此脈沖完成數(shù)據(jù)傳輸。 SPI支持4-32bits的串行數(shù)據(jù)傳輸,支持MSB和LSB,每次數(shù)據(jù)傳輸時當從設備的大小端發(fā)生變化時需要重新設置SPI Master的大小端。

  10. 二、Linux SPI驅動總體架構
  11. 在2.6的linux內核中,SPI的驅動架構可以分為如下三個層次:SPI 核心層、SPI控制器驅動層和SPI設備驅動層。Linux 中SPI驅動代碼位于drivers/spi目錄。
  12. 1.SPI核心層
  13. SPI核心層是Linux的SPI核心部分,提供了核心數(shù)據(jù)結構的定義、SPI控制器驅動和設備驅動的注冊、注銷管理等API。其為硬件平臺無關層,向下屏蔽了物理總線控制器的差異,定義了統(tǒng)一的訪問策略和接口;其向上提供了統(tǒng)一的接口,以便SPI設備驅動通過總線控制器進行數(shù)據(jù)收發(fā)。
  14. Linux中,SPI核心層的代碼位于driver/spi/spi.c。

  15. 2.SPI控制器驅動層
  16. SPI控制器驅動層,每種處理器平臺都有自己的控制器驅動,屬于平臺移植相關層。它的職責是為系統(tǒng)中每條SPI總線實現(xiàn)相應的讀寫方法。在物理上,每個SPI控制器可以連接若干個SPI從設備。
  17. 在系統(tǒng)開機時,SPI控制器驅動被首先裝載。一個控制器驅動用于支持一條特定的SPI總線的讀寫。一個控制器驅動可以用數(shù)據(jù)結構struct spi_master來描述。

  18. 3.SPI設備驅動層
  19. SPI設備驅動層為用戶接口層,其為用戶提供了通過SPI總線訪問具體設備的接口。
  20. SPI設備驅動層可以用兩個模塊來描述,struct spi_driver和struct spi_device。
  21. Driver是為device服務的,spi_driver注冊時會掃描SPI bus上的設備,進行驅動和設備的綁定,probe函數(shù)用于驅動和設備匹配時被調用。從上面的結構體注釋中我們可以知道,SPI的通信是通過消息隊列機制,而不是像I2C那樣通過與從設備進行對話的方式。

  22. 三、spi子系統(tǒng)主要數(shù)據(jù)結構
  23. 1.在Linux中,使用spi_master結構來描述一個SPI主機控制器的驅動。
  24. struct spi_master {
  25.     struct device dev;
  26.     s16 bus_num; //為該控制器對應的SPI總線號
  27.     u16 num_chipselect; //控制器支持的片選數(shù)量,即能支持多少個spi設備,從設備的片選號不能大于這個數(shù)量
  28.     u16 dma_alignment;
  29.     int (*setup)(struct spi_device *spi);//函數(shù)是設置SPI總線的模式,時鐘等的初始化函數(shù), 針對設備設置SPI的工作時鐘及數(shù)據(jù)傳輸模式等。在spi_add_device函數(shù)中調用
  30.     int (*transfer)(struct spi_device *spi,struct spi_message *mesg);//實現(xiàn)SPI總線讀寫方法的函數(shù)。實現(xiàn)數(shù)據(jù)的雙向傳輸,可能會睡眠
  31.     void (*cleanup)(struct spi_device *spi); //注銷時候調用
  32. };
  33. //分配,注冊和注銷的SPI主機的API由SPI核心提供:
  34. struct spi_master *spi_alloc_master(struct device *host, unsigned size);
  35. int spi_register_master(struct spi_master *master);
  36. void spi_unregister_master(struct spi_master *master);
  37.    
  38. 2.在Linux中用spi_driver來描述一個SPI外設驅動。
  39. struct spi_driver {
  40.     const struct spi_device_id *id_table;//匹配的設備表
  41.     int            (*probe)(struct spi_device *spi);
  42.     int            (*remove)(struct spi_device *spi);
  43.     void        (*shutdown)(struct spi_device *spi);
  44.     int            (*suspend)(struct spi_device *spi, pm_message_t mesg);
  45.     int            (*resume)(struct spi_device *spi);
  46.     struct device_driver    driver;
  47. };

  48. 3.Linux用spi_device來描述一個SPI外設設備。
  49. struct spi_device {
  50.     struct device        dev;
  51.     struct spi_master    *master;//對應的控制器指針
  52.     u32            max_speed_hz;//spi通信的時鐘
  53.     u8            chip_select; //片選,用于區(qū)分同一總線上的不同設備
  54.     u8            mode;
  55. #define    SPI_CPHA    0x01            /* clock phase */
  56. #define    SPI_CPOL    0x02            /* clock polarity */
  57. #define    SPI_MODE_0    (0|0)            /* (original MicroWire) */
  58. #define    SPI_MODE_1    (0|SPI_CPHA)
  59. #define    SPI_MODE_2    (SPI_CPOL|0)
  60. #define    SPI_MODE_3    (SPI_CPOL|SPI_CPHA)
  61. #define    SPI_CS_HIGH    0x04            /* chipselect active high? */
  62. #define    SPI_LSB_FIRST    0x08            /* per-word bits-on-wire */
  63. #define    SPI_3WIRE    0x10            /* SI/SO signals shared */
  64. #define    SPI_LOOP    0x20            /* loopback mode */
  65. #define    SPI_NO_CS    0x40            /* 1 dev/bus, no chipselect */
  66. #define    SPI_READY    0x80            /* slave pulls low to pause */
  67.     u8            bits_per_word;//每個字長的比特數(shù)
  68.     int            irq;//使用的中斷號
  69.     void            *controller_state;
  70.     void            *controller_data;
  71.     char            modalias[SPI_NAME_SIZE];//名字
  72. };
  73. 看這三個結構的關系,這里spi_device與spi_master是同一個父設備,這是在spi_new_device函數(shù)中設定的,一般這個設備是一個物理設備。

  74. 4.為了解決多個不同的SPI設備共享SPI控制器而帶來的訪問沖突,spi_bitbang使用內核提供的工作隊列(workqueue)。 workqueue是Linux內核中定義的一種回調處理方式。采用這種方式需要傳輸數(shù)據(jù)時,不直接完成數(shù)據(jù)的傳輸,而是將要傳輸?shù)墓ぷ鞣盅b成相應的消息 (spi_message),發(fā)送給對應的workqueue,由與workqueue關聯(lián)的內核守護線程(daemon)負責具體的執(zhí)行。由于 workqueue會將收到的消息按時間先后順序排列,這樣就是對設備的訪問嚴格串行化,解決了沖突。
  75. struct spi_bitbang {
  76.     struct workqueue_struct *workqueue;//工作隊列頭
  77.     struct work_struct work;//每一次傳輸都傳遞下來一個spi_message,都向工作隊列頭添加一個
  78.     workspinlock_t lock;
  79.     struct list_head queue;//掛接spi_message,如果上一次的spi_message還沒有處理完,接下來的spi_message就掛接在queue上等待處理
  80.     u8 busy;//忙碌標志
  81.     u8 use_dma;
  82.     u8 flags;
  83.     struct spi_master *master;//指向spi控制器
  84.     int (*setup_transfer)(struct spi_device *spi,struct spi_transfer *t);//設置傳輸模式
  85.     void (*chipselect)(struct spi_device *spi, int is_on);//片選
  86. #define BITBANG_CS_ACTIVE 1 /* normally nCS, active low */
  87. #define BITBANG_CS_INACTIVE 0
  88.     int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t);//傳輸函數(shù)
  89.     u32 (*txrx_word[4])(struct spi_device *spi,unsigned nsecs,u32 word, u8 bits);
  90. };

  91. 5.下面來看看spi_message:
  92. struct spi_message {
  93.     struct list_head transfers; //此次消息的傳輸隊列,一個消息可以包含多個傳輸段
  94.     struct spi_device *spi; //傳輸?shù)哪康脑O備
  95.     unsigned is_dma_mapped:1; //如果為真,此次調用提供dma和cpu虛擬地址
  96.     void (*complete)(void *context); //異步調用完成后的回調函數(shù)
  97.     void *context; //回調函數(shù)的參數(shù)
  98.     unsigned actual_length; //此次傳輸?shù)膶嶋H長度
  99.     int status; //執(zhí)行的結果,成功被置0,否則是一個負的錯誤碼
  100.     struct list_head queue;
  101.     void *state;
  102. };
  103. 在有消息需要傳遞的時候,會將spi_transfer通過自己的transfer_list字段掛到spi_message的transfers鏈表頭上。spi_message用來原子的執(zhí)行spi_transfer表示的一串數(shù)組傳輸請求。這個傳輸隊列是原子的,這意味著在這個消息完成之前不會有其 他消息占用總線。消息的執(zhí)行總是按照FIFO的順序。

  104. 6.下面看一看spi_transfer:
  105. struct spi_transfer {
  106.     const void *tx_buf; //要寫入設備的數(shù)據(jù)(必須是dma_safe),或者為NULL
  107.     void *rx_buf; //要讀取的數(shù)據(jù)緩沖(必須是dma_safe),或者為NULL
  108.     unsigned len; //tx和rx的大小(字節(jié)數(shù)),這里不是指它的和,而是各自的長度,他們總是相等的
  109.     dma_addr_t tx_dma; //如果spi_message.is_dma_mapped是真,這個是tx的dma地址
  110.     dma_addr_t rx_dma; //如果spi_message.is_dma_mapped是真,這個是rx的dma地址
  111.     unsigned cs_change:1; //影響此次傳輸之后的片選,指示本次tranfer結束之后是否要重新片選并調用setup改變設置,這個標志可以較少系統(tǒng)開銷u8
  112.     bits_per_word; //每個字長的比特數(shù),如果是0,使用默認值
  113.     u16 delay_usecs; //此次傳輸結束和片選改變之間的延時,之后就會啟動另一個傳輸或者結束整個消息
  114.     u32 speed_hz; //通信時鐘。如果是0,使用默認值
  115.     struct list_head transfer_list; //用來連接的雙向鏈表節(jié)點
  116. };

  117. 7.spi控制器驅動的私有數(shù)據(jù)
  118. struct davinci_spi {
  119.     struct spi_bitbang    bitbang;
  120.     struct clk        *clk;//時鐘
  121.     u8            version;
  122.     resource_size_t        pbase;//spi寄存器物理地址
  123.     void __iomem        *base;//spi寄存器虛擬地址
  124.     u32            irq;//spi中斷號
  125.     struct completion    done;

  126.     const void    *tx;//發(fā)送buffer
  127.     void            *rx;//讀buffer
  128. #define SPI_TMP_BUFSZ    (SMP_CACHE_BYTES + 1)
  129.     u8            rx_tmp_buf[SPI_TMP_BUFSZ];
  130.     int            rcount;//讀數(shù)據(jù)個數(shù)
  131.     int            wcount;//寫數(shù)據(jù)個數(shù)
  132.     struct davinci_spi_dma    dma;
  133.     struct davinci_spi_platform_data *pdata;

  134.     void        (*get_rx)(u32 rx_data, struct davinci_spi *);//讀數(shù)據(jù)函數(shù)
  135.     u32            (*get_tx)(struct davinci_spi *);//發(fā)送數(shù)據(jù)函數(shù)
  136.     u8            bytes_per_word[SPI_MAX_CHIPSELECT];
  137.     u32            speed;
  138.     u32            cs_num;
  139.     bool        in_use;

  140. #ifdef CONFIG_CPU_FREQ
  141.     struct notifier_block freq_transition;
  142. #endif
  143. };


  144. 四、spi驅動初始化
  145. 1.spi總線注冊
  146. //spi總線結構
  147. struct bus_type spi_bus_type = {
  148.     .name        = "spi",
  149.     .dev_attrs    = spi_dev_attrs,
  150.     .match        = spi_match_device,
  151.     .uevent        = spi_uevent,
  152.     .suspend    = spi_suspend,
  153.     .resume        = spi_resume,
  154. };

  155. //spi_master類,會在sysfs文件系統(tǒng)創(chuàng)建該類
  156. static struct class spi_master_class = {
  157.     .name        = "spi_master",
  158.     .owner        = THIS_MODULE,
  159.     .dev_release    = spi_master_release,
  160. };

  161. static int __init spi_init(void)
  162. {
  163.     int    status;

  164.     buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
  165.     if (!buf) {
  166.         status = -ENOMEM;
  167.         goto err0;
  168.     }
  169.     //分別對應sysfs文件系統(tǒng)中的sys/bus/下的spi目錄和sys/class/下的spi_master目錄。
  170.     status = bus_register(&spi_bus_type);//注冊spi總線
  171.     if (status < 0)
  172.         goto err1;

  173.     status = class_register(&spi_master_class);//創(chuàng)建spi_master的類
  174.     if (status < 0)
  175.         goto err2;
  176.     return 0;

  177. err2:
  178.     bus_unregister(&spi_bus_type);
  179. err1:
  180.     kfree(buf);
  181.     buf = NULL;
  182. err0:
  183.     return status;
  184. }

  185. 2.spi控制器管腳的復用配置
  186. const short da850_spi0_pins[] __initdata = {
  187.     DA850_SPI0_CLK,DA850_SPI0_ENA,DA850_SPI0_SOMI,DA850_SPI0_SIMO,
  188.     -1
  189. };

  190. static __init void da850_evm_init(void)
  191. {
  192.     //......
  193.     ret = davinci_cfg_reg_list(da850_spi0_pins);//復用管腳配置
  194.     if (ret)
  195.         pr_warning("da850_evm_init: spi0 mux setup failed: %d\n",    ret);
  196.     //......    
  197. }

  198. 3.注冊spi的platform device設備        
  199. static struct spi_board_info da850evm_spi_info[] = {
  200.     {
  201.         .modalias = "ads7846",//設備名,與spi_driver中定義的名字相同
  202.         .bus_num = 0,
  203.         .chip_select = 0,
  204.         .max_speed_hz = 1500000,
  205.         .mode             = SPI_MODE_0,
  206.         .irq = 128,//GPIO1[11]
  207.         .platform_data = &ads7846_config,
  208.         },
  209. };

  210. static void __init da850evm_init_spi0(struct spi_board_info *info, unsigned len)
  211. {
  212.     int ret;
  213.     
  214.     //注冊spi設備的信息到board_list鏈表中,待spi master注冊好后掃描這些板級設備再進行注冊
  215.     ret = spi_register_board_info(info, len);
  216.     if (ret)
  217.         pr_warning("failed to register board info : %d\n", ret);
  218.     
  219.     //注冊spi0的platform device
  220.     ret = da8xx_register_spi(0, &da850evm_spi0_pdata);
  221.     if (ret)
  222.         pr_warning("failed to register spi 1 device : %d\n", ret);

  223.     if (!(system_rev & 0x100))
  224.         register_mtd_user(&spi_notifier);
  225. }

  226. int __init spi_register_board_info(struct spi_board_info const *info, unsigned n)
  227. {
  228.     struct boardinfo *bi;
  229.     int i;

  230.     bi = kzalloc(n * sizeof(*bi), GFP_KERNEL);//分配一個boardinfo結構
  231.     if (!bi)
  232.         return -ENOMEM;

  233.     for (i = 0; i < n; i++, bi++, info++) {
  234.         struct spi_master *master;
  235.         memcpy(&bi->board_info, info, sizeof(*info));//填充boardinfo結構
  236.         mutex_lock(&board_lock);
  237.         list_add_tail(&bi->list, &board_list);//掛載到全局鏈表board_list中
  238.         
  239.         //遍歷spi_master_list鏈表,查看是否有spi設備在此spi控制器上,現(xiàn)在因為spi master尚未注冊,不會注冊板級設備。
  240.         //待spi控制器注冊后,還會掃描鏈表進行匹配,來注冊板級設備
  241.         list_for_each_entry(master, &spi_master_list, list)
  242.             spi_match_master_to_boardinfo(master, &bi->board_info);
  243.         mutex_unlock(&board_lock);
  244.     }
  245.     return 0;
  246. }

  247. static struct resource da8xx_spi0_resources[] = {
  248.     [0] = {
  249.         .start = 0x01c41000,
  250.         .end = 0x01c41fff,
  251.         .flags = IORESOURCE_MEM,
  252.     },
  253.     [1] = {
  254.         .start = IRQ_DA8XX_SPINT0,
  255.         .end = IRQ_DA8XX_SPINT0,
  256.         .flags = IORESOURCE_IRQ,
  257.     },
  258.     [2] = {
  259.         .start = EDMA_CTLR_CHAN(0, 14),
  260.         .end = EDMA_CTLR_CHAN(0, 14),
  261.         .flags = IORESOURCE_DMA,
  262.     },
  263.     [3] = {
  264.         .start = EDMA_CTLR_CHAN(0, 15),
  265.         .end = EDMA_CTLR_CHAN(0, 15),
  266.         .flags = IORESOURCE_DMA,
  267.     },
  268.     [4] = {
  269.         .start = 0,
  270.         .end = 0,
  271.         .flags = IORESOURCE_DMA,
  272.     },
  273. };

  274. static struct platform_device da8xx_spi_device[] = {
  275.     [0] = {
  276.         .name = "spi_davinci",
  277.         .id = 0,
  278.         .num_resources = ARRAY_SIZE(da8xx_spi0_resources),
  279.         .resource = da8xx_spi0_resources,
  280.     },
  281.     [1] = {
  282.         .name = "spi_davinci",
  283.         .id = 1,
  284.         .num_resources = ARRAY_SIZE(da8xx_spi1_resources),
  285.         .resource = da8xx_spi1_resources,
  286.     },
  287. };

  288. int __init da8xx_register_spi(int instance,struct davinci_spi_platform_data *pdata)
  289. {
  290.     struct platform_device *pdev;

  291.     if (instance == 0)
  292.         pdev = &da8xx_spi_device[0];
  293.     else if (instance == 1)
  294.         pdev = &da8xx_spi_device[1];
  295.     else
  296.         return -EINVAL;

  297.     pdev->dev.platform_data = pdata;

  298.     return platform_device_register(pdev);//注冊platform device設備
  299. }

  300. 4.注冊platform driver,會注冊spi控制器spi_master

  301. static struct platform_driver davinci_spi_driver = {
  302.     .driver = {
  303.         .name = "spi_davinci",
  304.         .owner = THIS_MODULE,
  305.     },
  306.     .remove = __exit_p(davinci_spi_remove),
  307.     .suspend = davinci_spi_suspend,
  308.     .resume = davinci_spi_resume,
  309. };

  310. static int __init davinci_spi_init(void)
  311. {
  312.     return platform_driver_probe(&davinci_spi_driver, davinci_spi_probe);
  313. }

  314. //platform driver與platform device匹配成功后,調用davinci_spi_probe
  315. static int davinci_spi_probe(struct platform_device *pdev)
  316. {
  317.     struct spi_master *master;
  318.     struct davinci_spi *dspi;
  319.     struct davinci_spi_platform_data *pdata;
  320.     struct resource *r, *mem;
  321.     resource_size_t dma_rx_chan = SPI_NO_RESOURCE;
  322.     resource_size_t    dma_tx_chan = SPI_NO_RESOURCE;
  323.     resource_size_t    dma_eventq = SPI_NO_RESOURCE;
  324.     int i = 0, ret = 0;
  325.     u32 spipc0;

  326.     pdata = pdev->dev.platform_data;
  327.     if (pdata == NULL) {
  328.         ret = -ENODEV;
  329.         goto err;
  330.     }
  331.     
  332.     //分配一個spi控制器的spi_master結構,分配struct spi_master + struct davinci_spi大小的數(shù)據(jù),把davinci_spi設為spi_master的私有數(shù)據(jù)
  333.     master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi));
  334.     if (master == NULL) {
  335.         ret = -ENOMEM;
  336.         goto err;
  337.     }
  338.     
  339.     //把spi_master設置為platform_device結構中dev的私有數(shù)據(jù)
  340.     dev_set_drvdata(&pdev->dev, master);
  341.     
  342.     //從master中獲得私有數(shù)據(jù)davinci_spi
  343.     dspi = spi_master_get_devdata(master);
  344.     if (dspi == NULL) {
  345.         ret = -ENOENT;
  346.         goto free_master;
  347.     }
  348.     
  349.     //從platform device的私有數(shù)據(jù)中獲得spi控制器的寄存器物理地址資源
  350.     r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  351.     if (r == NULL) {
  352.         ret = -ENOENT;
  353.         goto free_master;
  354.     }
  355.     dspi->pbase = r->start;//spi寄存器起始物理地址
  356.     dspi->pdata = pdata;
  357.     
  358.     //為spi控制器的物理地址申請內存空間
  359.     mem = request_mem_region(r->start, resource_size(r), pdev->name);
  360.     if (mem == NULL) {
  361.         ret = -EBUSY;
  362.         goto free_master;
  363.     }
  364.     
  365.     //將spi控制器的寄存器物理地址映射到內核空間
  366.     dspi->base = ioremap(r->start, resource_size(r));
  367.     if (dspi->base == NULL) {
  368.         ret = -ENOMEM;
  369.         goto release_region;
  370.     }
  371.     
  372.     //從platform device的私有數(shù)據(jù)中獲得spi控制器的中斷號
  373.     dspi->irq = platform_get_irq(pdev, 0);
  374.     if (dspi->irq <= 0) {
  375.         ret = -EINVAL;
  376.         goto unmap_io;
  377.     }
  378.     
  379.     //申請中斷號
  380.     ret = request_irq(dspi->irq, davinci_spi_irq, 0, dev_name(&pdev->dev),dspi);
  381.     if (ret)
  382.         goto unmap_io;
  383.     
  384.     //spi master計數(shù)加1,且
  385.     dspi->bitbang.master = spi_master_get(master);
  386.     if (dspi->bitbang.master == NULL) {
  387.         ret = -ENODEV;
  388.         goto irq_free;
  389.     }
  390.     
  391.     //獲得spi時鐘
  392.     dspi->clk = clk_get(&pdev->dev, NULL);
  393.     if (IS_ERR(dspi->clk)) {
  394.         ret = -ENODEV;
  395.         goto put_master;
  396.     }
  397.     clk_enable(dspi->clk);//時鐘使能

  398.     master->bus_num = pdev->id;//spi控制器所在的spi總線號
  399.     master->num_chipselect = pdata->num_chipselect;//spi控制器的片選數(shù)量
  400.     master->setup = davinci_spi_setup;//spi控制器的setup函數(shù)
  401.     
  402.     //spi_bitbang專門負責數(shù)據(jù)的傳輸*
  403.     dspi->bitbang.chipselect = davinci_spi_chipselect;//片選選擇函數(shù)
  404.     dspi->bitbang.setup_transfer = davinci_spi_setup_transfer;//建立傳輸?shù)暮瘮?shù)

  405.     dspi->version = pdata->version;//版本號SPI_VERSION_2
  406.     //設置一些標志位
  407.     dspi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP;
  408.     if (dspi->version == SPI_VERSION_2)
  409.         dspi->bitbang.flags |= SPI_READY;
  410.     
  411.     //DMA操作的一些設置
  412.     r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
  413.     if (r)
  414.         dma_rx_chan = r->start;
  415.     r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
  416.     if (r)
  417.         dma_tx_chan = r->start;
  418.     r = platform_get_resource(pdev, IORESOURCE_DMA, 2);
  419.     if (r)
  420.         dma_eventq = r->start;

  421.     //數(shù)據(jù)傳輸函數(shù)
  422.     dspi->bitbang.txrx_bufs = davinci_spi_bufs;
  423.     //沒有使用DMA
  424.     if (dma_rx_chan != SPI_NO_RESOURCE &&dma_tx_chan != SPI_NO_RESOURCE &&dma_eventq != SPI_NO_RESOURCE) {
  425.         dspi->dma.rx_channel = dma_rx_chan;
  426.         dspi->dma.tx_channel = dma_tx_chan;
  427.         dspi->dma.eventq = dma_eventq;

  428.         ret = davinci_spi_request_dma(dspi);
  429.         if (ret)
  430.             goto free_clk;

  431.         dev_info(&pdev->dev, "DMA: supported\n");
  432.         dev_info(&pdev->dev, "DMA: RX channel: %d, TX channel: %d, event queue: %d\n", dma_rx_chan, dma_tx_chan,dma_eventq);
  433.     }
  434.     
  435.     //設置spi的讀寫函數(shù)
  436.     dspi->get_rx = davinci_spi_rx_buf_u8;
  437.     dspi->get_tx = davinci_spi_tx_buf_u8;

  438.     init_completion(&dspi->done);
  439.     ret = davinci_spi_cpufreq_register(dspi);//cpu變頻相關操作
  440.     if (ret) {
  441.         pr_info("davinci SPI contorller driver failed to register cpufreq\n");
  442.         goto free_dma;
  443.     }

  444.     iowrite32(0, dspi->base + SPIGCR0);//reset spi控制器
  445.     udelay(100);
  446.     iowrite32(1, dspi->base + SPIGCR0);//跳出spi控制器reset狀態(tài)

  447.     //初始化設置寄存器,包括對SPIMOSI,SPIMISO,SPICLK引腳的設置
  448.     spipc0 = SPIPC0_DIFUN_MASK | SPIPC0_DOFUN_MASK | SPIPC0_CLKFUN_MASK;
  449.     iowrite32(spipc0, dspi->base + SPIPC0);

  450.     //GPIO作為片選管腳的初始化
  451.     if (pdata->chip_sel) {
  452.         for (i = 0; i < pdata->num_chipselect; i++) {
  453.             if (pdata->chip_sel[i] != SPI_INTERN_CS)
  454.                 gpio_direction_output(pdata->chip_sel[i], 1);
  455.         }
  456.     }

  457.     if (pdata->intr_line)
  458.         iowrite32(SPI_INTLVL_1, dspi->base + SPILVL);//設置spi中斷的等級
  459.     else
  460.         iowrite32(SPI_INTLVL_0, dspi->base + SPILVL);

  461.     iowrite32(CS_DEFAULT, dspi->base + SPIDEF);//設置片選寄存器,寫入默認值0xFF

  462.     /* master mode default */
  463.     set_io_bits(dspi->base + SPIGCR1, SPIGCR1_CLKMOD_MASK);//設置為master模式
  464.     set_io_bits(dspi->base + SPIGCR1, SPIGCR1_MASTER_MASK);//設置為master模式
  465.     set_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);//設置為power-down模式

  466.     //設置bitbang傳輸
  467.     ret = spi_bitbang_start(&dspi->bitbang);
  468.     if (ret)
  469.         goto free_dma;

  470.     dev_info(&pdev->dev, "Controller at 0x%p\n", dspi->base);

  471.     return ret;

  472. free_dma:
  473.     edma_free_channel(dspi->dma.tx_channel);
  474.     edma_free_channel(dspi->dma.rx_channel);
  475.     edma_free_slot(dspi->dma.dummy_param_slot);
  476. free_clk:
  477.     clk_disable(dspi->clk);
  478.     clk_put(dspi->clk);
  479. put_master:
  480.     spi_master_put(master);
  481. irq_free:
  482.     free_irq(dspi->irq, dspi);
  483. unmap_io:
  484.     iounmap(dspi->base);
  485. release_region:
  486.     release_mem_region(dspi->pbase, resource_size(r));
  487. free_master:
  488.     kfree(master);
  489. err:
  490.     return ret;
  491. }

  492. int spi_bitbang_start(struct spi_bitbang *bitbang)
  493. {
  494.     int    status;

  495.     if (!bitbang->master || !bitbang->chipselect)
  496.         return -EINVAL;
  497.     
  498.      /*初始化一個工作隊列,后面再create_singlethread_workqueue,等到有數(shù)據(jù)要傳輸?shù)臅r候,在spi_bitbang_transfer函數(shù)中通過調用queue_work(bitbang->workqueue, &bitbang->work),把work扔進workqueue中調度運行,這是內核的一貫做法*/
  499.     //動態(tài)創(chuàng)建一個work_struct結構,它的處理函數(shù)是bitbang_work
  500.     INIT_WORK(&bitbang->work, bitbang_work);
  501.     spin_lock_init(&bitbang->lock);//初始化自旋鎖和鏈表頭
  502.     INIT_LIST_HEAD(&bitbang->queue);//初始化鏈表頭

  503.     if (!bitbang->master->mode_bits)
  504.         bitbang->master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;

  505.     if (!bitbang->master->transfer)
  506.         bitbang->master->transfer = spi_bitbang_transfer;//spi數(shù)據(jù)的傳輸就是通過調用這個方法來實現(xiàn)的
  507.     
  508.     //數(shù)據(jù)傳輸過程:spi_bitbang_transfer-->......-->davinci_spi_bufs
  509.     if (!bitbang->txrx_bufs) {//前邊已經賦值davinci_spi_bufs
  510.         bitbang->use_dma = 0;
  511.         bitbang->txrx_bufs = spi_bitbang_bufs;
  512.         if (!bitbang->master->setup) {
  513.             if (!bitbang->setup_transfer)
  514.                 bitbang->setup_transfer =
  515.                      spi_bitbang_setup_transfer;
  516.             bitbang->master->setup = spi_bitbang_setup;
  517.             bitbang->master->cleanup = spi_bitbang_cleanup;
  518.         }
  519.     } else if (!bitbang->master->setup)
  520.         return -EINVAL;

  521.     bitbang->busy = 0;
  522.     //調用create_singlethread_workqueue創(chuàng)建單個工作線程
  523.     bitbang->workqueue = create_singlethread_workqueue(dev_name(bitbang->master->dev.parent));
  524.     if (bitbang->workqueue == NULL) {
  525.         status = -EBUSY;
  526.         goto err1;
  527.     }

  528.     //注冊spi主機控制器
  529.     status = spi_register_master(bitbang->master);
  530.     if (status < 0)
  531.         goto err2;

  532.     return status;

  533. err2:
  534.     destroy_workqueue(bitbang->workqueue);
  535. err1:
  536.     return status;
  537. }

  538. int spi_register_master(struct spi_master *master)
  539. {
  540.     static atomic_t        dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
  541.     struct device        *dev = master->dev.parent;
  542.     struct boardinfo    *bi;
  543.     int            status = -ENODEV;
  544.     int            dynamic = 0;

  545.     if (!dev)
  546.         return -ENODEV;

  547.     //spi控制器的片選數(shù)量不能為0
  548.     if (master->num_chipselect == 0)
  549.         return -EINVAL;

  550.     if (master->bus_num < 0) {//spi控制器總線號不能為0
  551.         master->bus_num = atomic_dec_return(&dyn_bus_id);
  552.         dynamic = 1;
  553.     }

  554.     spin_lock_init(&master->bus_lock_spinlock);
  555.     mutex_init(&master->bus_lock_mutex);
  556.     master->bus_lock_flag = 0;

  557.     //設置spi控制器的名稱,即在sysfs文件系統(tǒng)中顯示的名稱
  558.     dev_set_name(&master->dev, "spi%u", master->bus_num);
  559.     
  560.     //設備添加到內核,會在sysfs文件系統(tǒng)下創(chuàng)建屬性文件,這也是sys/class/spi_master下產生spi0,spi1的原因
  561.     status = device_add(&master->dev);
  562.     if (status < 0)
  563.         goto done;
  564.     dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev),dynamic ? " (dynamic)" : "");

  565.     mutex_lock(&board_lock);
  566.     list_add_tail(&master->list, &spi_master_list);//將spi控制器的master掛載到全局鏈表spi_master_list
  567.     
  568.     /*在spi controller的driver注冊的時候不但注冊這個主機控制器的驅動,還要遍歷這個主機控制器的總線上的spi_device,
  569.     將總線上的 spi_device全部注冊進內核。當注冊進內核并且spi_driver已經注冊的時候,如果總線match成功,
  570.     則會調用spi_driver的 probe函數(shù),這個將在后邊進行分析。
  571.     */
  572.     list_for_each_entry(bi, &board_list, list)//遍歷每個boardinfo管理的spi_board_info,如果設備的總線號與控制器的總線好相等,則創(chuàng)建新設備
  573.         spi_match_master_to_boardinfo(master, &bi->board_info);
  574.     mutex_unlock(&board_lock);

  575.     status = 0;
  576.     /* Register devices from the device tree */
  577.     of_register_spi_devices(master);
  578. done:
  579.     return status;
  580. }

  581. static void spi_match_master_to_boardinfo(struct spi_master *master,struct spi_board_info *bi)
  582. {
  583.     struct spi_device *dev;

  584.     if (master->bus_num != bi->bus_num)//要在同一個spi總線上
  585.         return;
  586.     
  587.     //向spi控制器添加spi device
  588.     dev = spi_new_device(master, bi);
  589.     if (!dev)
  590.         dev_err(master->dev.parent, "can't create new device for %s\n",bi->modalias);
  591. }

  592. struct spi_device *spi_new_device(struct spi_master *master,struct spi_board_info *chip)
  593. {
  594.     struct spi_device    *proxy;
  595.     int            status;

  596.     //分配spi_device,并初始化spi->dev的一些字段
  597.     proxy = spi_alloc_device(master);
  598.     if (!proxy)
  599.         return NULL;

  600.     WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));
  601.     //初始化spi_device的各個字段
  602.     proxy->chip_select = chip->chip_select;//片選號
  603.     proxy->max_speed_hz = chip->max_speed_hz;
  604.     proxy->mode = chip->mode;
  605.     proxy->irq = chip->irq;
  606.     strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));//spi設備的名字
  607.     proxy->dev.platform_data = (void *) chip->platform_data;
  608.     proxy->controller_data = chip->controller_data;
  609.     proxy->controller_state = NULL;
  610.     
  611.     //添加spi設備
  612.     status = spi_add_device(proxy);
  613.     if (status < 0) {
  614.         spi_dev_put(proxy);
  615.         return NULL;
  616.     }

  617.     return proxy;
  618. }

  619. int spi_add_device(struct spi_device *spi)
  620. {
  621.     static DEFINE_MUTEX(spi_add_lock);
  622.     struct device *dev = spi->master->dev.parent;
  623.     struct device *d;
  624.     int status;

  625.     //spi設備的片選號不能超過spi控制器的片選數(shù)量
  626.     if (spi->chip_select >= spi->master->num_chipselect) {
  627.         dev_err(dev, "cs%d >= max %d\n",spi->chip_select,spi->master->num_chipselect);
  628.         return -EINVAL;
  629.     }

  630.     //這里設置是spi_device在Linux設備驅動模型中的name,也就是spi0.0
  631.     dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->master->dev),spi->chip_select);
  632.     mutex_lock(&spi_add_lock);

  633.     //如果總線上掛的設備已經有這個名字,則設置狀態(tài)忙碌,并退出
  634.     d = bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev));
  635.     if (d != NULL) {
  636.         dev_err(dev, "chipselect %d already in use\n",spi->chip_select);
  637.         put_device(d);
  638.         status = -EBUSY;
  639.         goto done;
  640.     }

  641.     //對spi_device進行設置
  642.     status = spi_setup(spi);
  643.     if (status < 0) {
  644.         dev_err(dev, "can't setup %s, status %d\n",dev_name(&spi->dev), status);
  645.         goto done;
  646.     }

  647.     //添加到內核,在sysfs文件系統(tǒng)下創(chuàng)建相應的屬性文件(設備文件dev文件不會在這里創(chuàng)建,下邊注冊spi device驅動時會創(chuàng)建dev文件)
  648.     status = device_add(&spi->dev);
  649.     if (status < 0)
  650.         dev_err(dev, "can't add %s, status %d\n",dev_name(&spi->dev), status);
  651.     else
  652.         dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev));

  653. done:
  654.     mutex_unlock(&spi_add_lock);
  655.     return status;
  656. }

  657. int spi_setup(struct spi_device *spi)
  658. {
  659.     unsigned    bad_bits;
  660.     int        status;

  661.     bad_bits = spi->mode & ~spi->master->mode_bits;
  662.     if (bad_bits) {
  663.         dev_err(&spi->dev, "setup: unsupported mode bits %x\n",bad_bits);
  664.         return -EINVAL;
  665.     }
  666.     
  667.     if (!spi->bits_per_word)
  668.         spi->bits_per_word = 8;

  669.     status = spi->master->setup(spi);//調用davinci_spi_setup

  670.     dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s"
  671.                 "%u bits/w, %u Hz max --> %d\n",
  672.             (int) (spi->mode & (SPI_CPOL | SPI_CPHA)),
  673.             (spi->mode & SPI_CS_HIGH) ? "cs_high, " : "",
  674.             (spi->mode & SPI_LSB_FIRST) ? "lsb, " : "",
  675.             (spi->mode & SPI_3WIRE) ? "3wire, " : "",
  676.             (spi->mode & SPI_LOOP) ? "loopback, " : "",
  677.             spi->bits_per_word, spi->max_speed_hz,
  678.             status);

  679.     return status;
  680. }

  681. static int davinci_spi_setup(struct spi_device *spi)
  682. {
  683.     int retval = 0;
  684.     struct davinci_spi *dspi;
  685.     struct davinci_spi_platform_data *pdata;
  686.     
  687.     //從spi master的私有數(shù)據(jù)中取出davinci_spi
  688.     dspi = spi_master_get_devdata(spi->master);
  689.     pdata = dspi->pdata;

  690.     //設置了每字長的位數(shù),發(fā)送速度
  691.     if (!spi->bits_per_word)
  692.         spi->bits_per_word = 8;

  693.     //設置spi片選管腳
  694.     if (!(spi->mode & SPI_NO_CS)) {
  695.         if ((pdata->chip_sel == NULL) ||(pdata->chip_sel[spi->chip_select] == SPI_INTERN_CS))
  696.             set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select);
  697.     }

  698.     //使能spi控制器
  699.     if (spi->mode & SPI_READY)
  700.         set_io_bits(dspi->base + SPIPC0, SPIPC0_SPIENA_MASK);

  701.     //是否使能內部loop-back測試模式
  702.     if (spi->mode & SPI_LOOP)
  703.         set_io_bits(dspi->base + SPIGCR1, SPIGCR1_LOOPBACK_MASK);
  704.     else
  705.         clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_LOOPBACK_MASK);

  706.     return retval;
  707. }

  708. 5.spi device的驅動注冊,并創(chuàng)建設備節(jié)點
  709. static struct spi_driver ads7846_driver = {
  710.     .driver = {
  711.         .name    = "ads7846",
  712.         .bus    = &spi_bus_type,
  713.         .owner    = THIS_MODULE,
  714.     },
  715.     .probe        = ads7846_probe,
  716.     .remove        = __devexit_p(ads7846_remove),
  717.     .suspend    = ads7846_suspend,
  718.     .resume        = ads7846_resume,
  719. };

  720. static int __init ads7846_init(void)
  721. {
  722.     return spi_register_driver(&ads7846_driver);
  723. }

  724. //驅動與設備匹配成功后,會調用ads7846_probe函數(shù),此函數(shù)會創(chuàng)建spi設備的字符設備,設備節(jié)點,這里創(chuàng)建的是/dev/input/event0

本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
linux內核SPI總線驅動分析
spi子系統(tǒng)分析
spi驅動框架分板(上)
通過mtd讀寫flash
linux中probe函數(shù)傳遞參數(shù)的尋找(下)
Linux下spi驅動開發(fā)(1)
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服