linux SPI驱动——spi core(四)

一:

SPI核心,就是指/drivers/spi/目录下spi.c文件中提供给其他文件的函数,首先看下spi核心的初始化函数spi_init(void)。

1: static int __init spi_init(void)  
2: {  
3: int status;  
4:    
5: buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL); /* 初始化缓存 */  
6: if (!buf) {  
7: status = -ENOMEM;  
8: goto err0;  
9: }  
10:    
11:status = bus_register(&spi_bus_type); /* 注册spi总线,此步骤之后就会在/sys/bus目录下生成spi子目录 */  
12: if (status < 0)  
13: goto err1;  
14:    
15: status = class_register(&spi_master_class);;/* 注册spi类,此步骤之后就会在/sys/class目录下生成spi_master子目录 */  
16: if (status < 0)  
17: gotoerr2;  
18: return 0;  
19:    
20: err2:  
21: bus_unregister(&spi_bus_type);  
22: err1:  
23:kfree(buf);  
24: buf = NULL;  
25: err0:  
26: return status;  
27: }

1: struct bus_type spi_bus_type = {  
2: .name = "spi",  
3: .dev_attrs = spi_dev_attrs,  
4: .match = spi_match_device,  
5: .uevent = spi_uevent,  
6: .pm = &spi_pm,  
7: };

1: static struct class spi_master_class = {  
2: .name = "spi_master",  
3: .owner = THIS_MODULE,
4: .dev_release = spi_master_release,  
5: };
 
 
1: postcore_initcall(spi_init); /* 注册 */
 

说明:
        1) 由postcore_initcall(spi_init);可以看出,此宏在系统初始化时是先于module_init()执行的。

        2) 申请的buf空间用于在spi数据传输中。

        3) 接下来是总线注册和类注册。

 

二:

此函数是半双工的形式写then读

1: int spi_write_then_read(struct spi_device *spi,
2: const void *txbuf, unsigned n_tx,
3: void *rxbuf, unsigned n_rx)
4: {
5: static DEFINE_MUTEX(lock);
6:  
7: int status;
8: struct spi_message message;
9: struct spi_transfer x[2];
10: u8 *local_buf;
11:  
12: /* Use preallocated DMA-safe buffer. We can't avoid copying here,
13: * (as a pure convenience thing), but we can keep heap costs
14: * out of the hot path ...
15: */
16: if ((n_tx + n_rx) > SPI_BUFSIZ)
17: return -EINVAL;
18:  
19: spi_message_init(&message);
20: memset(x, 0, sizeof x);
21: if (n_tx) {
22: x[0].len = n_tx;
23: spi_message_add_tail(&x[0], &message);
24: }
25: if (n_rx) {
26: x[1].len = n_rx;
27: spi_message_add_tail(&x[1], &message);
28: }
29:  
30: /* ... unless someone else is using the pre-allocated buffer */
31: if (!mutex_trylock(&lock)) {
32: local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
33: if (!local_buf)
34: return -ENOMEM;
35: else
36: local_buf = buf;
37:  
38: memcpy(local_buf, txbuf, n_tx);
39: x[0].tx_buf = local_buf;
40: x[1].rx_buf = local_buf + n_tx;
41:  
42: /* do the i/o */
43: status = spi_sync(spi, &message);
44: if (status == 0)
45: memcpy(rxbuf, x[1].rx_buf, n_rx);
46:  
47: if (x[0].tx_buf == buf)
48: mutex_unlock(&lock);
49: else
50: kfree(local_buf);
51:  
52: return status;
53: }
 
1: 对master操作的加锁与解锁
2: int spi_bus_lock(struct spi_master *master)
3: {
4: unsigned long flags;
5:  
6: mutex_lock(&master->bus_lock_mutex);
7:  
8: spin_lock_irqsave(&master->bus_lock_spinlock, flags);
9: master->bus_lock_flag = 1;
10: spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);
11:  
12: /* mutex remains locked until spi_bus_unlock is called */
13:  
14: return 0;
15: }
16: int spi_bus_unlock(struct spi_master *master)
17: {
18: master->bus_lock_flag = 0;
19:  
20: mutex_unlock(&master->bus_lock_mutex);
21:  
22: return 0;
23: }
 
同步数据交互
1: int spi_sync(struct spi_device *spi, struct spi_message *message)  
2: {  
3: return__spi_sync(spi, message, 0);  
4: }  
5: int spi_sync_locked(struct spi_device *spi, structspi_message *message)  
6: {  
7: return __spi_sync(spi, message, 1);  
8: }
 
 
异步数据交互
1: int spi_async(struct spi_device *spi, struct spi_message *message)  
2: {  
3: structspi_master *master = spi->master;  
4: int ret;  
5: unsigned long flags;  
6:    
7:spin_lock_irqsave(&master->bus_lock_spinlock, flags);  
8:    
9: if (master->bus_lock_flag)  
10:ret = -EBUSY;  
11: else  
12: ret = __spi_async(spi, message);  
13:    
14:spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);  
15:    
16: return ret;  
17: }  
18:  
19: int spi_async_locked(struct spi_device *spi, struct spi_message *message)  
20: {  
21: structspi_master *master = spi->master;  
22: int ret;  
23: unsigned long flags;  
24:    
25:spin_lock_irqsave(&master->bus_lock_spinlock, flags);  
26:    
27: ret = __spi_async(spi, message);  
28:    
29: spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);  
30:    
31:return ret;  
32:    
33: }

 

 
//创建master
1: struct spi_master *spi_alloc_master(struct device *dev, unsigned size)  
2: {  
3: structspi_master *master;  
4:    
5: if (!dev)  
6: return NULL;  
7:    
8: master = kzalloc(size + sizeof*master, GFP_KERNEL);  
9: if (!master)  
10: return NULL;  
11:    
12: device_initialize(&master->dev);  
13: master->dev.class = &spi_master_class;  
14: master->dev.parent = get_device(dev);
15: spi_master_set_devdata(master, &master[1]);  
16:    
17: return master;  
18: }

//spi_register_master
1: int spi_register_master(struct spi_master *master)  
2: {  
3: static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1);  
4: struct device *dev = master->dev.parent;  
5: struct boardinfo *bi;
6: int status = -ENODEV;  
7: int dynamic = 0;  
8:    
9: if (!dev)  
10: return -ENODEV;  
11:    
12:/* even if it's just one always-selected device, there must  
13: * be at least one chipselect
14: */  
15: if (master->num_chipselect == 0)  
16: return -EINVAL;  
17:    
18: /* convention: dynamically assigned bus IDs count down from the max */  
19: if (master->bus_num < 0) {  
20: /* FIXME switch to an IDR based scheme, something like  
21: * I2C now uses, so we can't run out of "dynamic" IDs  
22: */  
23: master->bus_num = atomic_dec_return(&dyn_bus_id);  
24: dynamic = 1;
25: }  
26:    
27: spin_lock_init(&master->bus_lock_spinlock);  
28: mutex_init(&master->bus_lock_mutex);  
29: master->bus_lock_flag = 0;  
30:    
31: /* register the device, then userspace will see it.  
32: * registration fails if the bus ID is in use.  
33: */  
34:dev_set_name(&master->dev, "spi%u", master->bus_num);  
35: status = device_add(&master->dev);
36: if (status < 0)  
37: goto done;  
38: dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev),  
39: dynamic ? " (dynamic)" : "");  
40:    
41: mutex_lock(&board_lock);
42: list_add_tail(&master->list, &spi_master_list);  
43: list_for_each_entry(bi, &board_list, list)  
44: spi_match_master_to_boardinfo(master, &bi->board_info);  45:mutex_unlock(&board_lock);  
46:    
47: status = 0;  
48:    
49: /* Register devices from the device tree */  
50: of_register_spi_devices(master);  
51: done:  
52: return status;  
53: }

 

分析以上spi_register_master代码:

    1.  spi_match_master_to_boardinfo会将master和每个注册进来的device board联系起来

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值