驱动模块使用SPI总线范例

来源:互联网 发布:比较骚的网络女主播 编辑:程序博客网 时间:2024/05/21 00:49

前两天写了一个<驱动模块使用I2C总线范例>。由于SPI和I2C类似,加上有空闲时间,故参考之前写的I2C实现了这个SPI模块。代码如下,这个代码未经调试,我目前的板子没有用到SPI接口,但是总体架构应该没错的。

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #include <linux/init.h>  
  2. #include <linux/kernel.h>  
  3. #include <linux/module.h>  
  4. #include <linux/init.h>  
  5. #include <linux/errno.h>  
  6. #include <linux/init.h>  
  7. #include <linux/list.h>  
  8. #include <linux/smp_lock.h>  
  9. #include <linux/spi/spi.h>  
  10.   
  11. struct spi_api {  
  12.     struct list_head list;  
  13.     struct spi_device *spi;  
  14. };  
  15.   
  16. #define SPI_MINORS    32  
  17. #define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH /  
  18.         | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP /  
  19.         | SPI_NO_CS | SPI_READY)  
  20.   
  21. static LIST_HEAD(spi_api_list);  
  22. static DEFINE_SPINLOCK(spi_api_list_lock);  
  23.   
  24. static struct spi_api *get_spi_api(int bus_id)  
  25. {  
  26.     struct spi_api *spi_api;  
  27.   
  28.     spin_lock(&spi_api_list_lock);  
  29.     list_for_each_entry(spi_api, &spi_api_list, list) {  
  30.         if (spi_api->spi->master->bus_num == bus_id)  
  31.             goto found;  
  32.     }  
  33.     spi_api = NULL;  
  34.       
  35. found:  
  36.     spin_unlock(&spi_api_list_lock);  
  37.     return spi_api;  
  38. }  
  39.   
  40. static struct spi_api *add_spi_api(struct spi_device *spi)  
  41. {  
  42.     struct spi_api *spi_api;  
  43.   
  44.     if (spi->master->bus_num >= SPI_MINORS) {  
  45.         printk(KERN_ERR "spi_api: Out of device minors (%d)/n",  
  46.             spi->master->bus_num);  
  47.         return NULL;  
  48.     }  
  49.   
  50.     spi_api = kzalloc(sizeof(*spi_api), GFP_KERNEL);  
  51.     if (!spi_api)  
  52.         return NULL;  
  53.     spi_api->spi = spi;  
  54.   
  55.     spin_lock(&spi_api_list_lock);  
  56.     list_add_tail(&spi_api->list, &spi_api_list);  
  57.     spin_unlock(&spi_api_list_lock);  
  58.     return spi_api;  
  59. }  
  60.   
  61. static void del_spi_api(struct spi_api *spi_api)  
  62. {  
  63.     spin_lock(&spi_api_list_lock);  
  64.     list_del(&spi_api->list);  
  65.     spin_unlock(&spi_api_list_lock);  
  66.     kfree(spi_api);  
  67. }  
  68.   
  69. static int spi_api_do_set(int bus_id,  
  70.                           u8 mode,   
  71.                           u8 bits_per_word,   
  72.                           u8 max_speed_hz)  
  73. {  
  74.     struct spi_device *spi;  
  75.     struct spi_api *spi_api = get_spi_api(bus_id);  
  76.     if (!spi_api)  
  77.         return -ENODEV;  
  78.   
  79.     spi = spi_api->spi;  
  80.     spi->mode &= ~SPI_MODE_MASK;  
  81.     spi->mode |= mode;  
  82.     spi->bits_per_word = bits_per_word;  
  83.     spi->max_speed_hz = max_speed_hz;  
  84.     return spi_setup(spi);  
  85. }  
  86.   
  87. static int spi_api_do_write(int bus_id, const u8 *buf, size_t len)  
  88. {  
  89.     struct spi_api *spi_api = get_spi_api(bus_id);  
  90.     if (!spi_api)  
  91.         return -ENODEV;  
  92.     return spi_write(spi_api->spi, buf, len);  
  93. }  
  94.   
  95. static int spi_api_do_read(int bus_id, u8 *buf, size_t len)  
  96. {  
  97.     struct spi_api *spi_api = get_spi_api(bus_id);  
  98.     if (!spi_api)  
  99.         return -ENODEV;  
  100.     return spi_read(spi_api->spi, buf, len);  
  101. }  
  102.   
  103. static int spi_api_do_write_then_read(int bus_id,  
  104.                                       const u8 *txbuf, unsigned n_tx,  
  105.                                       u8 *rxbuf, unsigned n_rx)  
  106. {  
  107.     struct spi_api *spi_api = get_spi_api(bus_id);  
  108.     if (!spi_api)  
  109.         return -ENODEV;  
  110.     return spi_write_then_read(spi_api->spi, txbuf, n_tx, rxbuf, n_rx);  
  111. }  
  112.   
  113. static int spi_api_probe(struct spi_device *spi)  
  114. {   
  115.     add_spi_api(spi);  
  116.     printk(KERN_INFO "spi_api_probe device[%d]/n", spi->master->bus_num);  
  117.     return 0;   
  118. }  
  119.   
  120. static int spi_api_remove(struct spi_device *spi)  
  121. {  
  122.     struct spi_api * spi_api = get_spi_api(spi->master->bus_num);  
  123.     if (spi_api)  
  124.         del_spi_api(spi_api);  
  125.     return 0;  
  126. }  
  127.   
  128. static struct spi_driver spi_api_driver = {  
  129.     .driver = {  
  130.         .name = "SPI-API",  
  131.         .owner = THIS_MODULE,  
  132.     },  
  133.     .probe = spi_api_probe,  
  134.     .remove = spi_api_remove,  
  135. };  
  136.   
  137. static int __init spi_api_init(void)  
  138. {     
  139.     int ret = spi_register_driver(&spi_api_driver);  
  140.       
  141.     if (ret) {  
  142.         printk(KERN_ERR "[%s] Driver registration failed, module not inserted./n", __func__);  
  143.         return ret;  
  144.     }  
  145.     printk("spi_api_init/n");  
  146.     return 0 ;    
  147. }  
  148.   
  149. static void __exit spi_api_exit(void)  
  150. {     
  151.     spi_unregister_driver(&spi_api_driver);  
  152. }  
  153.   
  154. MODULE_AUTHOR("Loon, <sepnic@gmail.com>");  
  155. MODULE_DESCRIPTION("SPI spi_api Driver");  
  156. MODULE_LICENSE("GPL");  
  157.   
  158. module_init(spi_api_init);  
  159. module_exit(spi_api_exit);  
  160.   
  161. EXPORT_SYMBOL_GPL(spi_api_do_set);  
  162. EXPORT_SYMBOL_GPL(spi_api_do_write);  
  163. EXPORT_SYMBOL_GPL(spi_api_do_read);  
  164. EXPORT_SYMBOL_GPL(spi_api_do_write_then_read);  
0 0
原创粉丝点击