驱动模块使用SPI总线范例
来源:互联网 发布:比较骚的网络女主播 编辑:程序博客网 时间:2024/05/21 00:49
前两天写了一个<驱动模块使用I2C总线范例>。由于SPI和I2C类似,加上有空闲时间,故参考之前写的I2C实现了这个SPI模块。代码如下,这个代码未经调试,我目前的板子没有用到SPI接口,但是总体架构应该没错的。
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/errno.h>
- #include <linux/init.h>
- #include <linux/list.h>
- #include <linux/smp_lock.h>
- #include <linux/spi/spi.h>
- struct spi_api {
- struct list_head list;
- struct spi_device *spi;
- };
- #define SPI_MINORS 32
- #define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH /
- | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP /
- | SPI_NO_CS | SPI_READY)
- static LIST_HEAD(spi_api_list);
- static DEFINE_SPINLOCK(spi_api_list_lock);
- static struct spi_api *get_spi_api(int bus_id)
- {
- struct spi_api *spi_api;
- spin_lock(&spi_api_list_lock);
- list_for_each_entry(spi_api, &spi_api_list, list) {
- if (spi_api->spi->master->bus_num == bus_id)
- goto found;
- }
- spi_api = NULL;
- found:
- spin_unlock(&spi_api_list_lock);
- return spi_api;
- }
- static struct spi_api *add_spi_api(struct spi_device *spi)
- {
- struct spi_api *spi_api;
- if (spi->master->bus_num >= SPI_MINORS) {
- printk(KERN_ERR "spi_api: Out of device minors (%d)/n",
- spi->master->bus_num);
- return NULL;
- }
- spi_api = kzalloc(sizeof(*spi_api), GFP_KERNEL);
- if (!spi_api)
- return NULL;
- spi_api->spi = spi;
- spin_lock(&spi_api_list_lock);
- list_add_tail(&spi_api->list, &spi_api_list);
- spin_unlock(&spi_api_list_lock);
- return spi_api;
- }
- static void del_spi_api(struct spi_api *spi_api)
- {
- spin_lock(&spi_api_list_lock);
- list_del(&spi_api->list);
- spin_unlock(&spi_api_list_lock);
- kfree(spi_api);
- }
- static int spi_api_do_set(int bus_id,
- u8 mode,
- u8 bits_per_word,
- u8 max_speed_hz)
- {
- struct spi_device *spi;
- struct spi_api *spi_api = get_spi_api(bus_id);
- if (!spi_api)
- return -ENODEV;
- spi = spi_api->spi;
- spi->mode &= ~SPI_MODE_MASK;
- spi->mode |= mode;
- spi->bits_per_word = bits_per_word;
- spi->max_speed_hz = max_speed_hz;
- return spi_setup(spi);
- }
- static int spi_api_do_write(int bus_id, const u8 *buf, size_t len)
- {
- struct spi_api *spi_api = get_spi_api(bus_id);
- if (!spi_api)
- return -ENODEV;
- return spi_write(spi_api->spi, buf, len);
- }
- static int spi_api_do_read(int bus_id, u8 *buf, size_t len)
- {
- struct spi_api *spi_api = get_spi_api(bus_id);
- if (!spi_api)
- return -ENODEV;
- return spi_read(spi_api->spi, buf, len);
- }
- static int spi_api_do_write_then_read(int bus_id,
- const u8 *txbuf, unsigned n_tx,
- u8 *rxbuf, unsigned n_rx)
- {
- struct spi_api *spi_api = get_spi_api(bus_id);
- if (!spi_api)
- return -ENODEV;
- return spi_write_then_read(spi_api->spi, txbuf, n_tx, rxbuf, n_rx);
- }
- static int spi_api_probe(struct spi_device *spi)
- {
- add_spi_api(spi);
- printk(KERN_INFO "spi_api_probe device[%d]/n", spi->master->bus_num);
- return 0;
- }
- static int spi_api_remove(struct spi_device *spi)
- {
- struct spi_api * spi_api = get_spi_api(spi->master->bus_num);
- if (spi_api)
- del_spi_api(spi_api);
- return 0;
- }
- static struct spi_driver spi_api_driver = {
- .driver = {
- .name = "SPI-API",
- .owner = THIS_MODULE,
- },
- .probe = spi_api_probe,
- .remove = spi_api_remove,
- };
- static int __init spi_api_init(void)
- {
- int ret = spi_register_driver(&spi_api_driver);
- if (ret) {
- printk(KERN_ERR "[%s] Driver registration failed, module not inserted./n", __func__);
- return ret;
- }
- printk("spi_api_init/n");
- return 0 ;
- }
- static void __exit spi_api_exit(void)
- {
- spi_unregister_driver(&spi_api_driver);
- }
- MODULE_AUTHOR("Loon, <sepnic@gmail.com>");
- MODULE_DESCRIPTION("SPI spi_api Driver");
- MODULE_LICENSE("GPL");
- module_init(spi_api_init);
- module_exit(spi_api_exit);
- EXPORT_SYMBOL_GPL(spi_api_do_set);
- EXPORT_SYMBOL_GPL(spi_api_do_write);
- EXPORT_SYMBOL_GPL(spi_api_do_read);
- EXPORT_SYMBOL_GPL(spi_api_do_write_then_read);
0 0
- 驱动模块使用SPI总线范例
- 驱动模块使用SPI总线范例
- 驱动模块使用I2C总线范例
- 驱动模块使用I2C总线范例
- SPI总线驱动12864
- linux SPI总线驱动
- SPI总线驱动分析
- SPI总线驱动分析
- SPI总线驱动
- linux下的SPI模块驱动使用
- spi总线设备驱动分析
- linux SPI总线驱动(一)
- Linux Platform总线+SPI总线分析-SPI驱动
- Linux spi驱动分析(一)----总线驱动
- Linux spi驱动分析(一)----总线驱动
- Linux spi驱动分析(一)----总线驱动
- Linux spi驱动分析(一)----总线驱动
- Linux spi驱动分析(一)----总线驱动
- va_start、va_arg、va_end、va_copy 可变参函数
- 程序猿如何从失恋中走出来
- Java NIO使用及原理分析(三)
- Gradient Boosting and GBDT
- C#提取文件名
- 驱动模块使用SPI总线范例
- Shell的基本语法
- hadoop安全模式
- 初学ssh之Spring 01
- HTTP Status 403 - Access to the requested resource has been denied
- Log4J基础详解及示例
- Socket ( Udp) 通信服务端
- 海思3515添加串口
- linux内核之list_head