Linux spi驱动(二)

1、概览

对于ARM平台来说,大多数CPU都是SoC。spi控制器被集成在CPU内部。spi总线上的数据传输过程通常就是这个spi控制器来控制的。为了使spi控制器能工作在linux spi子系统中,我们就需要针对CPU内部的spi控制器编写一个驱动。前面的博文提到过,在linux spi系统中struct spi_master对象就对应了一个spi控制器。编写spi控制器驱动其实就是实现struct spi_master中的各种接口,并将该struct spi_master结构注册到spi子系统中去。下面将结合代码,具体介绍如何实现一个spi控制器驱动。

2、spi控制器驱动设备侧

对ARM平台中各种控制器,主要有两种方法在内核中申明一个spi控制器设备。一种是在板级代码中向内核中注册一个struct platform_device对象。另一种方法是使用device tree来描述spi控制器的各种信息,然后由device tree相关代码解析并向内核申明一个spi控制器相关的设备。对于第一种方法主要在2.6.xx的内核中普遍使用的。而第二种方法在3.xx的内核中使用的。虽然说新版的内核对于第一种方法仍然支持,但是已经很少使用了。对于描述spi控制器上述两种方法同样适用,下面具体介绍两种方法。

2.1)板级代码中向内核注册spi控制器

为了更好理解,我们可以通过代码来具体讲解如何注册一个描述spi控制器的struct platform_device。鉴于新的平台已经使用Device Tree来描述SoC中的各种控制器,我们选用比较老的CPU来讲解这种方式描述spi控制器,我们用s3c64xx的板级代码作为示例。目前在3.xx内核中arch/arm/mach-s3c64xx/mach-crag6410.c中有如何注册描述spi控制器的struct platform_device的。此文件371行左右有如下代码:

371 static struct platform_device *crag6410_devices[] __initdata = {
    /*[......] */ /* 省略与spi无关代码 */
385         &s3c64xx_device_spi0,
    /*[......]*/
397 };

代码中定义了一个struct platform_device指针数组nexcoder_devices[],这个数组中的struct platform_device指针对应的struct platform_device用来表示CPU上个各种总线的控制器。这个数组中的各个struct platform_device最终都会被注册到内核中。由上面的代码可以看出与spi控制器相关的struct platform_device结构:s3c64xx_device_spi0,表示s3c64xx上的spi0。注册crag6410_devices[]中的struct platform_device对象到内核中的的代码如下:

825 static void __init crag6410_machine_init(void)
826 {
    /* [......] */ /* 省略与spi无关代码 */
855         s3c64xx_spi0_set_platdata(NULL, 0, 2);
856 
857         platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices));
858 
    /* [......] */
864 }

s3c64xx_spi0_set_platdata() 设置一些spi控制器相关信息到s3c64xx_device_spi0中去,包括片选信息,该spi控制器的时钟等等,这些信息会在后面的spi控制器驱动中用到,代码如下:

1541 void __init s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
1542                                                 int num_cs)
1543 {
1544         struct s3c64xx_spi_info pd;
1545 
1546         /* Reject invalid configuration */
1547         if (!num_cs || src_clk_nr < 0) {
1548                 pr_err("%s: Invalid SPI configuration\n", __func__);
1549                 return;
1550         }
1551 
1552         pd.num_cs = num_cs;
1553         pd.src_clk_nr = src_clk_nr;
1554         pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi0_cfg_gpio;
1555 
1556         s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi0);
1557 }

我们回过头来看看s3c64xx_device_spi0是什么样的,它们在文件arch/arm/plat-samsung/devs.c中的1522行左右:

1522 #ifdef CONFIG_S3C64XX_DEV_SPI0
1523 static struct resource s3c64xx_spi0_resource[] = {
1524         [0] = DEFINE_RES_MEM(S3C_PA_SPI0, SZ_256), //spi寄存器地址信息
1525         [1] = DEFINE_RES_DMA(DMACH_SPI0_TX),
1526         [2] = DEFINE_RES_DMA(DMACH_SPI0_RX),
1527         [3] = DEFINE_RES_IRQ(IRQ_SPI0),//中断信息
1528 };
1529 
1530 struct platform_device s3c64xx_device_spi0 = {
1531         .name           = "s3c6410-spi",
1532         .id             = 0,
1533         .num_resources  = ARRAY_SIZE(s3c64xx_spi0_resource),
1534         .resource       = s3c64xx_spi0_resource,
1535         .dev = {
1536                 .dma_mask               = &samsung_device_dma_mask,
1537                 .coherent_dma_mask      = DMA_BIT_MASK(32),
1538         },
1539 };

代码中struct resource对象描述的是与spi控制器硬件相关信息,包括寄存器起始地址和地址大小,DMA相关信息,以及中断号等信息,这些信息在spi控制器驱动中会用到。若希望一个spi控制器可以正常的工作在linux spi子系统中,构建并注册一个描述spi控制器的struct platform_device对象是必须的。只有注册了这个设备,才能在spi控制器的平台设备驱动注册时匹配这个设备,并使用这个struct platform_device中的信息来够建和注册struct spi_master对象到linux spi子系统中去。所有的spi设备驱动必须要调用struct spi_master对象中接口来发送和接收数据。
使用device tree来描述spi控制器相关信息就会简单很多,它的格式也比较固定,下面以基于TI的AM33xx的CPU来讲解如何使用device tree来描述spi控制器信息。在arch/arm/boot/dts/am33xxx.dtsi中有关于spi控制器的描述:

369         spi0: spi@48030000 {
370             compatible = "ti,omap4-mcspi";  //用来和驱动的of_device_id项目匹配
371             #address-cells = <1>;
372             #size-cells = <0>;
373             reg = <0x48030000 0x400>;    //spi控制器寄存器地址信息
374             interrupt = <65>;            //spi相关中断信息
375             ti,spi-num-cs = <2>;         //片选脚个数
376             ti,hwmods = "spi0";
377             dmas = <&edma 16
378                 &edma 17
379                 &edma 18
380                 &edma 19>;
381             dma-names = "tx0", "rx0", "tx1", "rx1";
382             status = "disabled";       //控制是否解析该节点
383         };
384 
385         spi1: spi@481a0000 {
386             compatible = "ti,omap4-mcspi";
387             #address-cells = <1>;
388             #size-cells = <0>;
389             reg = <0x481a0000 0x400>;
390             interrupt = <125>;
391             ti,spi-num-cs = <2>;
392             ti,hwmods = "spi1";
393             dmas = <&edma 42
394                 &edma 43
395                 &edma 44
396                 &edma 45>;                           
397             dma-names = "tx0", "rx0", "tx1", "rx1";
398             status = "disabled";
399 
400         };

其实device tree中描述的spi控制器信息在device tree解析时也会转化成一个struct platform_device对象,并注册的到内核。它和第一种方法本质上是一样的,不过这种方法不需要在板级代码中构建各种struct platform_device对象来描述CPU上各种控制器的信息,可以提高代码复用度。

每个描述spi控制器的device tree节点会被转化为一个struct platform_device对象。device tree节点中的reg 和interrupt 属性也会被转化为对应的描述控制器寄存器和中断信息的struct resource对象,并被该节点转化的struct platform_device对象中的resource成员引用。

关于如何Device Tree来描述spi控制器的详细介绍,请参考内核源码中Documentation/devicetree/bindings/spi/目录下的文档。
关于Device Tree的用法请参考内核源码中Documentation/devicetree/下的文档。

spi控制器驱动驱动侧

和上一节一样,本节中也会用两个驱动,分别对应上一节中每个小节。用s3c64xx CPU的spi控制器驱动来讲解在板级代码中用struct platform_device 对象来描述spi控制器时,驱动的写法。用am33xx CPU的spi控制器驱动来讲解用device tree描述spi控制器时驱动的写法。

在开始讲解这两个驱动之前,先来详细讲解spi控制器驱动中会用到的各种数据结构。首先我们来了解一下spi_bus_type:

230 struct bus_type spi_bus_type = {
231         .name           = "spi",
232         .dev_attrs      = spi_dev_attrs,
233         .match          = spi_match_device,
234         .uevent         = spi_uevent,
235         .pm             = &spi_pm,
236 };
237 EXPORT_SYMBOL_GPL(spi_bus_type);

这个数据结构非常重要,逻辑上它代表的是spi总线。所有的struct spi_master对象和struct spi_device对象注册到spi子系统后都会链接到这个数据结构中去。并且struct spi_driver注册到spi子系统后也会链接到这个数据结构中。其中的match 回调函数,即spi_match_device 函数中实现了spi设备和spi设备驱动匹配的策略。这个函数会在下一篇博文 《三、Linux spi设备驱动》中具体讲解。

下面这个数据结构可以说是spi控制器驱动中的核心,它就是struct spi_master:

struct spi_master {
274         struct device   dev;
275 
276         struct list_head list;
277 
278         /* other than negative (== assign one dynamically), bus_num is fully
279          * board-specific.  usually that simplifies to being SOC-specific.
280          * example:  one SOC has three SPI controllers, numbered 0..2,
281          * and one board's schematics might show it using SPI-2.  software
282          * would normally use bus_num=2 for that controller.
283          */
284         s16                     bus_num;
285 
286         /* chipselects will be integral to many controllers; some others
287          * might use board-specific GPIOs.
288          */
289         u16                     num_chipselect;
290 
291         /* some SPI controllers pose alignment requirements on DMAable
292          * buffers; let protocol drivers know about these requirements.
293          */
294         u16                     dma_alignment;
295 
296         /* spi_device.mode flags understood by this controller driver */
297         u16                     mode_bits;
298 
299         /* other constraints relevant to this driver */
300         u16                     flags;
301 #define SPI_MASTER_HALF_DUPLEX  BIT(0)          /* can't do full duplex */
302 #define SPI_MASTER_NO_RX        BIT(1)          /* can't do buffer read */
303 #define SPI_MASTER_NO_TX        BIT(2)          /* can't do buffer write */
304 
305         /* lock and mutex for SPI bus locking */
306         spinlock_t              bus_lock_spinlock;
307         struct mutex            bus_lock_mutex;
308 
309         /* flag indicating that the SPI bus is locked for exclusive use */
310         bool                    bus_lock_flag;
311 
312         /* Setup mode and clock, etc (spi driver may call many times).
313          *
314          * IMPORTANT:  this may be called when transfers to another
315          * device are active.  DO NOT UPDATE SHARED REGISTERS in ways
316          * which could break those transfers.
317          */
318         int                     (*setup)(struct spi_device *spi);
319 
320         /* bidirectional bulk transfers
321          *
322          * + The transfer() method may not sleep; its main role is
323          *   just to add the message to the queue.
324          * + For now there's no remove-from-queue operation, or
325          *   any other request management
326          * + To a given spi_device, message queueing is pure fifo
327          *
328          * + The master's main job is to process its message queue,
329          *   selecting a chip then transferring data
330          * + If there are multiple spi_device children, the i/o queue
331          *   arbitration algorithm is unspecified (round robin, fifo,
332          *   priority, reservations, preemption, etc)
333          *
334          * + Chipselect stays active during the entire message
335          *   (unless modified by spi_transfer.cs_change != 0).
336          * + The message transfers use clock and SPI mode parameters
337          *   previously established by setup() for this device
338          */
339         int                     (*transfer)(struct spi_device *spi,
340                                                 struct spi_message *mesg);
341 
342         /* called on release() to free memory provided by spi_master */
343         void                    (*cleanup)(struct spi_device *spi);
344 
345         /*
346          * These hooks are for drivers that want to use the generic
347          * master transfer queueing mechanism. If these are used, the
348          * transfer() function above must NOT be specified by the driver.
349          * Over time we expect SPI drivers to be phased over to this API.
350          */
351         bool                            queued;
352         struct kthread_worker           kworker;
353         struct task_struct              *kworker_task;
354         struct kthread_work             pump_messages;
355         spinlock_t                      queue_lock;
356         struct list_head                queue;
357         struct spi_message              *cur_msg;
358         bool                            busy;
359         bool                            running;
360         bool                            rt;
361 
362         int (*prepare_transfer_hardware)(struct spi_master *master);
363         int (*transfer_one_message)(struct spi_master *master,
364                                     struct spi_message *mesg);
365         int (*unprepare_transfer_hardware)(struct spi_master *master);
366         /* gpio chip select */
367         int                     *cs_gpios;
368 };

这个数据结构的定义比较长,里面有很多元素我们是不需要关心的,spi子系统会实现其中一些。我们选择需要我们实现的项目来讲解。

s16 bus_num
需要在驱动中设置。代表该总线的编号,这个与硬件相关。

u16 num_chipselect
片选的个数,与spi总线上连接的设备有关。

u16 mode_bits
spi控制器所支持模式的标志位。包括相位、极性、片选模式(高电平或低电平)。

int (*setup) (struct spi_device *spi)
这个回调函数可以选择实现。这个函数的作用就是在发送数据给一个spi设备之前, 根据spi设备中记录的spi总线的电气信息重新配置spi控制器,使spi控制器的速率、工作模式等满足spi设备的要求。

int (*transfer)(struct spi_device *spi, struct spi_message *mesg)
在比较老的内核中,这个回调函数是必须要实现的。在使用spi总线进行分段数据传输时,需要调用这个函数来传输数据。这个接口已经不建议使用了,将来可能会从内核中移除,后面介绍替代接口。

void (*cleanup) (struct spi_device *spi)
选择实现该接口。主要用来释放一些资源。

int (*prepare_transfer_hardware)(struct spi_master *master)
选择实现该接口。发送数据之前使spi控制器做好准备,可能是从低功耗模式转化到正常工作模式等。

int (*unprepare_transfer_hardware)(struct spi_master *master)
选择实现该接口。发送数据后可以使用该接口切换spi控制状态。

int (*transfer_one_message)(struct spi_master *master, struct spi_message *mesg)
如果未实现int (*transfer)(struct spi_device *spi, struct spi_message *mesg)接口,这个接口是必须实现的。transfer_one_message 和 tranfer接口的区别是:如果驱动实现transfer 接口,还要实现工作队列来负责调度和控制spi接口发送数据。而transfer_one_message机制就不需要再实现队列了。spi子系统中已经实现了一个内核线程来负责数据的调度和传输。

int *cs_gpios
选择实现。与片选信号有关系。

下面介绍俩个与数据传输有关系的数据结构: struct spi_message 和 struct spi_transfer。一个struct spi_message代表针对一个设备进行一次分段数据传输。而一个struct spi_transfer表示一段数据传输。所以一个struct spi_message对象中包含多个struct spi_transfer对象。

首先介绍struct spi_transfer, 一个struct spi_transfer代表一次spi数据传输,其中包含了读和写数据的缓冲区对,struct spi_transfer结构体定义如下:

495 struct spi_transfer {
496         /* it's ok if tx_buf == rx_buf (right?)
497          * for MicroWire, one buffer must be null
498          * buffers must work with dma_*map_single() calls, unless
499          *   spi_message.is_dma_mapped reports a pre-existing mapping
500          */
501         const void      *tx_buf;
502         void            *rx_buf;
503         unsigned        len;
504 
505         dma_addr_t      tx_dma;
506         dma_addr_t      rx_dma;
507 
508         unsigned        cs_change:1;
509         u8              bits_per_word;
510         u16             delay_usecs;
511         u32             speed_hz;
512 
513         struct list_head transfer_list;
514 };

const void *tx_buf
发送数据缓冲区,发送至spi设备的数据存放在这个缓冲区中。

void *rx_buf
接收数据缓冲区,从spi设备接收的数据保存在这个缓冲区中。

unsigned len
缓冲区长度。

dma_addr_t tx_dma
如果使用dma,发送缓冲区的dma地址。

dma_addr_t rx_dma
如果使用dma,接搜缓冲区的dma地址。

unsigned cs_change:1
本次数据传输后,是否改变片选信号状态。

u8 bits_per_word
字长信息,每次写入spi控制器的数据大小,这与硬件的实现有关系有关系。bits_per_word = 0时,会使用spi_device中的默认值。

u16 delay_usecs
本次数据传输结束后,需要延时时间,才能改变片选信号状态,或进行下一次数据传输,或进行下一个spi_message数据传输。

u32 speed_hz
传输速率,不一定使用这个值,选择spi控制器支持的最大速度,spi设备支持的最大速度和这个值之间的最小值。

struct list_head transfer_list
通过这个链表头,将这个transfer链接到一个spi_message.transfers中。
下面介绍struct spi_message数据结构:

544 struct spi_message {
545         struct list_head        transfers;
546 
547         struct spi_device       *spi;
548 
549         unsigned                is_dma_mapped:1;
550 
551         /* REVISIT:  we might want a flag affecting the behavior of the
552          * last transfer ... allowing things like "read 16 bit length L"
553          * immediately followed by "read L bytes".  Basically imposing
554          * a specific message scheduling algorithm.
555          *
556          * Some controller drivers (message-at-a-time queue processing)
557          * could provide that as their default scheduling algorithm.  But
558          * others (with multi-message pipelines) could need a flag to
559          * tell them about such special cases.
560          */
561 
562         /* completion is reported through a callback */
563         void                    (*complete)(void *context);
564         void                    *context;
565         unsigned                actual_length;
566         int                     status;
567 
568         /* for optional use by whatever driver currently owns the
569          * spi_message ...  between calls to spi_async and then later
570          * complete(), that's the spi_master controller driver.
571          */
572         struct list_head        queue;
573         void                    *state;
574 };

struct list_head transfers
这个不用说了,所有需要传输的struct spi_transfer对象都会链接到这个链表上。

struct spi_device *spi
数据传输至这个spi设备。

unsigned is_dma_mapped:1
是否是dma传输?如果是,调用者需要在struct spi_transfer中提供发送和接收数据的dma地址和虚拟地址。

void (*complete)(void *context)
这个回调函数用来通知唤醒调用进程。

void *context
complete()回调的参数,通常为一个struct completion对象。

unsigned actual_length
本次message传输实际传输数据的长度。

int status
本次传输的结果,成功status == 0。

struct list_head queue
通过这个链表头将该message链接到等待spi控制器传输的message链表中。

void *state
拥有这个message的驱动会使用这个成员来获取一些状态信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值