二、Linux spi 控制器驱动

时间:2023-01-29 17:56:07

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对象中接口来发送和接收数据。

2.2)device tree描述spi控制器

使用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节点中的reginterrupt 属性也会被转化为对应的描述控制器寄存器和中断信息的struct resource对象,并被该节点转化的struct platform_device对象中的resource成员引用。

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

3、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:

273 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_messagetranfer接口的区别是:如果驱动实现transfer 接口,还要实现工作队列来负责调度和控制spi接口发送数据。而transfer_one_message机制就不需要再实现队列了。spi子系统中已经实现了一个内核线程来负责数据的调度和传输。

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

下面介绍俩个与数据传输有关系的数据结构: struct spi_messagestruct 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的驱动会使用这个成员来获取一些状态信息。

3.1)板级代码描述spi控制器的驱动

描述s3c64xx平台的spi控制器使用的是struct platform_device数据结构,对应的驱动那就是struct platform_driver数据结构。下面来看看描述s3c64xx平台的spi控制器的struct platform_device对应的struct platform_driver是如何实现的。源代码kernel/drivers/spi/spi-s3c64xx.c就是s3c64xx平台spi控制器的驱动代码。
先来看看代码中的struct platform_driver是如何定义和注册的。

1556 static struct platform_driver s3c64xx_spi_driver = {
1557 .driver = {
1558 .name = "s3c64xx-spi",
1559 .owner = THIS_MODULE,
1560 .pm = &s3c64xx_spi_pm,
1561 .of_match_table = of_match_ptr(s3c64xx_spi_dt_match),
1562 },
1563 .remove = s3c64xx_spi_remove,
1564 .id_table = s3c64xx_spi_driver_ids,
1565 };
1566 MODULE_ALIAS("platform:s3c64xx-spi");
1567
1568 static int __init s3c64xx_spi_init(void)
1569 {
1570 return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe);
1571 }
1572 subsys_initcall(s3c64xx_spi_init);
1573
1574 static void __exit s3c64xx_spi_exit(void)
1575 {
1576 platform_driver_unregister(&s3c64xx_spi_driver);
1577 }
1578 module_exit(s3c64xx_spi_exit);
1579
1580 MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
1581 MODULE_DESCRIPTION("S3C64XX SPI Controller Driver");
1582 MODULE_LICENSE("GPL");

其中static int __init s3c64xx_spi_init(void)static void __exit s3c64xx_spi_exit(void)就不多说了,照写就行了,基本上是固定格式。

s3c64xx_spi_init(void)中有一个platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe)调用,这函数就是将s3c64xx_spi_driver注册到内核,如何该驱动匹配到一个设备,就调用s3c64xx_spi_probe去探测设备。
其实上述代码有一种更为简单的写法,仅供参考,如下:

static struct platform_driver s3c64xx_spi_driver = {
.driver = {
.name = "s3c64xx-spi",
.owner = THIS_MODULE,
.pm = &s3c64xx_spi_pm,
.of_match_table = of_match_ptr(s3c64xx_spi_dt_match),
},
.remove = s3c64xx_spi_remove,

.id_table = s3c64xx_spi_driver_ids,
};
module_platform_driver(&s3c64xx_spi_driver);
MODULE_ALIAS("platform:s3c64xx-spi");

这种方法可能开起来更简洁一些。代码使用了module_platform_driver这样一个宏。

我们可以先忽略s3c64xx_spi_driver中的of_match_table项,这个项目是使用device tree时才会用到的,下面小节会讲解。
s3c64xx_spi_driver.driver.name 项,代表的驱动的名字,这个名字可以在/sys/bus/platform/drivers下面看到。如果s3c64xx_spi_driver.driver.of_match_tables3c64xx_spi_driver.id_table都未设置的情况下,s3c64xx_spi_driver.driver.name项会被用来和platform_device.name匹配。
struct platform_driver对象和struct platform_device对像的匹配原则为:最先匹配of_match_table中的项目,其次匹配id_table中的项目,最后是根据platform_driver.driver.nameplatform_device.name去匹配。可能有人会问:为什么不是platform_driver.driver.nameplatform_device.dev.name去匹配?其实platform_device.dev.name是由platform_device.nameplatform_device.id连接而成,具体是如何连接的,可以参考kernel/drivers/base/platform.c的platform_add_device()。所以直接用platform_driver.driver.nameplatform_device.dev.name来匹配驱动和设备是不会成功匹配的。具体platform_driverplatform_device匹配的代码如下:

721 static int platform_match(struct device *dev, struct device_driver *drv)
722 {
723 struct platform_device *pdev = to_platform_device(dev);
724 struct platform_driver *pdrv = to_platform_driver(drv);
725
726 /* Attempt an OF style match first */
727 if (of_driver_match_device(dev, drv))
728 return 1;
729
730 /* Then try ACPI style match */
731 if (acpi_driver_match_device(dev, drv))
732 return 1;
733
734 /* Then try to match against the id table */
735 if (pdrv->id_table)
736 return platform_match_id(pdrv->id_table, pdev) != NULL;
737
738 /* fall-back to driver name match */
739 return (strcmp(pdev->name, drv->name) == 0);
740 }

platform_match()中我们可以看到具体的驱动和设备的匹配规则。

我们回过来看看s3c64xx_spi_probe(struct platform_device *pdev),这个函数是s3c64xx平台spi控制器驱动的关键,代码比较长,这个函数是在platform_driverplatform_device匹配后才执行的,具体到我们这个例子,即s3c64xx_spi_drivers3c64xx_device_spi0匹配后才执行的。具体的匹配规则上面已经讲述过了。其中函数的参数具体到我们的例子就是一个指向s3c64xx_device_spi0的指针。下面以s3c64xx_device_spi0为例分步讲解。

第1步,获取spi0控制器的寄存器、中断的相关信息,这些信息都是和CPU紧密相关的,不同平台是不一样的。

下面代码是获取寄存器的物理地址:

1218         mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

这个mem_res其实就是就是s3c64xx_device_spi0.resource[0],即s3c64xx_spi0_resource[0],这里面记录了s3c64xx的spi0控制器的寄存器组物理地址。把这个地址映射到内核的虚拟地址中就可以访问spi0控制器的寄存器了。

下面一行代码获取中断信息,spi0的中断信息,就是在2.1节提到的s3c64xx_spi0_resource[3]

1052         irq = platform_get_irq(pdev, 0);

第2步,分配描述spi控制器驱动的私有数据和struct spi_master对象,代码如下:

1058         master = spi_alloc_master(&pdev->dev,
1059 sizeof(struct s3c64xx_spi_driver_data));

这个调用分配了一块连续内存,大小为sizeof(struct spi_master) + sizeof(struct s3c64xx_spi_driver_data)。其中sizeof(struct spi_master)大小给spi_master使用,剩下的内存起始地址通过spi_master_set_devdata()调用,设置给了spi_master.dev.driver_data

下面看看struct s3c64xx_spi_driver_data,先贴代码:

180 struct s3c64xx_spi_driver_data {
181 void __iomem *regs;
182 struct clk *clk;
183 struct clk *src_clk;
184 struct platform_device *pdev;
185 struct spi_master *master;
186 struct s3c64xx_spi_info *cntrlr_info;
187 struct spi_device *tgl_spi;
188 spinlock_t lock;
189 unsigned long sfr_start;
190 struct completion xfer_completion;
191 unsigned state;
192 unsigned cur_mode, cur_bpw;
193 unsigned cur_speed;
194 struct s3c64xx_spi_dma_data rx_dma;
195 struct s3c64xx_spi_dma_data tx_dma;
196 struct s3c64xx_spi_port_config *port_conf;
197 unsigned int port_id;
198 };

这个数据结构描述的是s3c64xx平台spi控制器相关的信息,其中包括spi控制器寄存器地址,spi控制器时钟源,dma相关信息,和spi控制器的配置信息,还有一些记录状态的数据以及各种锁。这里面还有一个struct spi_master指针,它会指向与该数据描述的spi控制器对应的spi_master

继续看代码:

1064 
1065 platform_set_drvdata(pdev, master);
1066
1067 sdd = spi_master_get_devdata(master);
1068 sdd->port_conf = s3c64xx_spi_get_port_config(pdev);
1069 sdd->master = master;
1070 sdd->cntrlr_info = sci;
1071 sdd->pdev = pdev;
1072 sdd->sfr_start = mem_res->start;
1073 if (pdev->dev.of_node) {
1074 ret = of_alias_get_id(pdev->dev.of_node, "spi");
1075 if (ret < 0) {
1076 dev_err(&pdev->dev, "failed to get alias id, errno %d\n",
1077 ret);
1078 goto err0;
1079 }
1080 sdd->port_id = ret;
1081 } else {
1082 sdd->port_id = pdev->id;
1083 }
1084
1085 sdd->cur_bpw = 8;

这段代码比较简单,设置一些指针的地址,以及spi控制器相关的数据。

第3步,设置struct spi_master结构体的信息,包括驱动中需要实现的接口:

1268         master->bus_num = sdd->port_id;
1269 master->setup = s3c64xx_spi_setup;
1270 master->cleanup = s3c64xx_spi_cleanup;
1271 master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer;
1272 master->transfer_one_message = s3c64xx_spi_transfer_one_message;
1273 master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer;
1274 master->num_chipselect = sci->num_cs;
1275 master->dma_alignment = 8;
1276 /* the spi->mode bits understood by this driver: */
1277 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;

这里面,s3c64xx_spi_setup()s3c64xx_spi_cleanup()s3c64xx_spi_prepare_transfer()s3c64xx_spi_transfer_one_message()s3c64xx_spi_unprepare_transfer()是必须要实现的接口,这些接口是和spi控制器相关的。s3c64xx_spi_transfer_one_message()就是为了传输一个struct spi_message中的数据。这些接口不详细介绍,有兴趣可以直接阅读代码。

第4步,映射寄存器地址到内核虚拟地址空间,申请中断和配置spi接口:

1279         sdd->regs = devm_request_and_ioremap(&pdev->dev, mem_res);
1280 if (sdd->regs == NULL) {
1281 dev_err(&pdev->dev, "Unable to remap IO\n");
1282 ret = -ENXIO;
1283 goto err1;
1284 }
1285
1286 if (!sci->cfg_gpio && pdev->dev.of_node) {
1287 if (s3c64xx_spi_parse_dt_gpio(sdd))
1288 return -EBUSY;
1289 } else if (sci->cfg_gpio == NULL || sci->cfg_gpio()) {
1290 dev_err(&pdev->dev, "Unable to config gpio\n");
1291 ret = -EBUSY;
1292 goto err2;
1293 }
1294
1295 /* Setup clocks */
1296 sdd->clk = clk_get(&pdev->dev, "spi");
1297 if (IS_ERR(sdd->clk)) {
1298 dev_err(&pdev->dev, "Unable to acquire clock 'spi'\n");
1299 ret = PTR_ERR(sdd->clk);
1300 goto err3;
1301 }
1302
1303 if (clk_prepare_enable(sdd->clk)) {
1304 dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n");
1305 ret = -EBUSY;
1306 goto err4;
1307 }
1308
1309 sprintf(clk_name, "spi_busclk%d", sci->src_clk_nr);
1310 sdd->src_clk = clk_get(&pdev->dev, clk_name);
1311 if (IS_ERR(sdd->src_clk)) {
1312 dev_err(&pdev->dev,
1313 "Unable to acquire clock '%s'\n", clk_name);
1314 ret = PTR_ERR(sdd->src_clk);
1315 goto err5;
1316 }
1317
1318 if (clk_prepare_enable(sdd->src_clk)) {
1319 dev_err(&pdev->dev, "Couldn't enable clock '%s'\n", clk_name);
1320 ret = -EBUSY;
1321 goto err6;
1322 }
1323
1324 /* Setup Deufult Mode */
1325 s3c64xx_spi_hwinit(sdd, sdd->port_id);
1326
1327 spin_lock_init(&sdd->lock);
1328 init_completion(&sdd->xfer_completion);
1329 INIT_LIST_HEAD(&sdd->queue);
1330
1331 ret = request_irq(irq, s3c64xx_spi_irq, 0, "spi-s3c64xx", sdd);
1332 if (ret != 0) {
1333 dev_err(&pdev->dev, "Failed to request IRQ %d: %d\n",
1334 irq, ret);
1335 goto err7;
1336 }
1337
1338 writel(S3C64XX_SPI_INT_RX_OVERRUN_EN | S3C64XX_SPI_INT_RX_UNDERRUN_EN |
1339 S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN,
1340 sdd->regs + S3C64XX_SPI_INT_EN);

第5步,注册spi_master到spi子系统中去:

1342         if (spi_register_master(master)) {
1343 dev_err(&pdev->dev, "cannot register SPI master\n");
1344 ret = -EBUSY;
1345 goto err8;
1346 }

这一步完成后,spi控制器的驱动就完成了。

3.2)device tree描述spi控制器的驱动

和不使用device tree的spi控制器驱动基本类似,不过有一些不同。下面通过简单讲解kernel/drivers/spi/spi-omap2-mcspi.c这个am33xx处理器的spi控制器驱动,来看看使用device tree时,spi控制器驱动如何编写。

同样,该驱动也是struct platform_device驱动,也就是说实现的是一个struct platform_driver。驱动文件中首先需要申明struct of_device_id数组,这个数组就决定了该struct platform_driver适用于那些struct platform_device。当然我们这个驱动是为了驱动spi控制器的。

先看看struct of_device_id的申明:

1123 static struct omap2_mcspi_platform_config omap2_pdata = {
1124 .regs_offset = 0,
1125 };
1126
1127 static struct omap2_mcspi_platform_config omap4_pdata = {
1128 .regs_offset = OMAP4_MCSPI_REG_OFFSET,
1129 };
1130
1131 static const struct of_device_id omap_mcspi_of_match[] = {
1132 {
1133 .compatible = "ti,omap2-mcspi",
1134 .data = &omap2_pdata,
1135 },
1136 {
1137 .compatible = "ti,omap4-mcspi",
1138 .data = &omap4_pdata,
1139 },
1140 { },
1141 };
1142 MODULE_DEVICE_TABLE(of, omap_mcspi_of_match);
1143

上述代码说明了,该驱动适用于device tree中compatible属性值为”ti,omap2-mcspi”或compatible属性值为”ti,omap4-mcspi”的驱动。2.2节中描述spi控制器的device tree节点中,compatible属性值为”ti,omap4-mcspi”,所以该驱动适用于device tree中描述的spi控制器。

下面代码是平台驱动的固定格式了,贴出代码,不再详述:

1342 static struct platform_driver omap2_mcspi_driver = {
1343 .driver = {
1344 .name = "omap2_mcspi",
1345 .owner = THIS_MODULE,
1346 .pm = &omap2_mcspi_pm_ops,
1347 .of_match_table = omap_mcspi_of_match,
1348 },
1349 .probe = omap2_mcspi_probe,
1350 .remove = omap2_mcspi_remove,
1351 };
1352
1353 module_platform_driver(omap2_mcspi_driver);

下面看一下omap2_mcspi_probe()接口,这个和上一小节的s3c64xx_spi_probe()很类似,我们简单看一下。

1144 static int omap2_mcspi_probe(struct platform_device *pdev)
1145 {
1146 struct spi_master *master;
1147 const struct omap2_mcspi_platform_config *pdata;
1148 struct omap2_mcspi *mcspi;
1149 struct resource *r;
1150 int status = 0, i;
1151 u32 regs_offset = 0;
1152 static int bus_num = 1;
1153 struct device_node *node = pdev->dev.of_node;
1154 const struct of_device_id *match;
1155 struct pinctrl *pinctrl;
1156
1157 master = spi_alloc_master(&pdev->dev, sizeof *mcspi);
1158 if (master == NULL) {
1159 dev_dbg(&pdev->dev, "master allocation failed\n");
1160 return -ENOMEM;
1161 }

上面一段代码分配了struct spi_master对象内存和驱动私有数据结构。

接着看:

1163         /* the spi->mode bits understood by this driver: */
1164 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
1165
1166 master->setup = omap2_mcspi_setup;
1167 master->prepare_transfer_hardware = omap2_prepare_transfer;
1168 master->unprepare_transfer_hardware = omap2_unprepare_transfer;
1169 master->transfer_one_message = omap2_mcspi_transfer_one_message;
1170 master->cleanup = omap2_mcspi_cleanup;
1171 master->dev.of_node = node;
1172
1173 dev_set_drvdata(&pdev->dev, master);
1174
1175 mcspi = spi_master_get_devdata(master);
1176 mcspi->master = master;

这段代码设置struct spi_master对象的信息,包括setup()cleanup()prepare_transfer_hardware()transfer_one_message()unprepare_transfer_hardware()等一些列接口。

接下来就是从device tree spi节点中获取片选等信息:

1178         match = of_match_device(omap_mcspi_of_match, &pdev->dev);
1179 if (match) {
1180 u32 num_cs = 1; /* default number of chipselect */
1181 pdata = match->data;
1182
1183 of_property_read_u32(node, "ti,spi-num-cs", &num_cs);
1184 master->num_chipselect = num_cs;
1185 master->bus_num = bus_num++;
1186 if (of_get_property(node, "ti,pindir-d0-out-d1-in", NULL))
1187 mcspi->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN;
1188 } else {
1189 pdata = pdev->dev.platform_data;
1190 master->num_chipselect = pdata->num_cs;
1191 if (pdev->id != -1)
1192 master->bus_num = pdev->id;
1193 mcspi->pin_dir = pdata->pin_dir;
1194 }
1195 regs_offset = pdata->regs_offset;

接下来映射寄存器地址到内核地址:

1197         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1198 if (r == NULL) {
1199 status = -ENODEV;
1200 goto free_master;
1201 }
1202
1203 r->start += regs_offset;
1204 r->end += regs_offset;
1205 mcspi->phys = r->start;
1206
1207 mcspi->base = devm_request_and_ioremap(&pdev->dev, r);
1208 if (!mcspi->base) {
1209 dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");
1210 status = -ENOMEM;
1211 goto free_master;
1212 }

接下来就是硬件相关配置,包括DMA,复用引脚的设置和spi控制器的配置:

1218         mcspi->dma_channels = kcalloc(master->num_chipselect,
1219 sizeof(struct omap2_mcspi_dma),
1220 GFP_KERNEL);
1221
1222 if (mcspi->dma_channels == NULL)
1223 goto free_master;
1224
1225 for (i = 0; i < master->num_chipselect; i++) {
1226 char dma_ch_name[14];
1227 struct resource *dma_res;
1228
1229 sprintf(dma_ch_name, "rx%d", i);
1230 dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
1231 dma_ch_name);
1232 if (!dma_res) {
1233 dev_dbg(&pdev->dev, "cannot get DMA RX channel\n");
1234 status = -ENODEV;
1235 break;
1236 }
1237
1238 mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start;
1239 sprintf(dma_ch_name, "tx%d", i);
1240 dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
1241 dma_ch_name);
1242 if (!dma_res) {
1243 dev_dbg(&pdev->dev, "cannot get DMA TX channel\n");
1244 status = -ENODEV;
1245 break;
1246 }
1247
1248 mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start;
1249 }
1250
1251 if (status < 0)
1252 goto dma_chnl_free;
1253
1254 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
1255 if (IS_ERR(pinctrl))
1256 dev_warn(&pdev->dev,
1257 "pins are not configured from the driver\n");
1258
1259 pm_runtime_use_autosuspend(&pdev->dev);
1260 pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
1261 pm_runtime_enable(&pdev->dev);
1262
1263 if (status || omap2_mcspi_master_setup(mcspi) < 0)
1264 goto disable_pm;
1265

最后一步,注册spi_master到spi子系统中去:

1266         status = spi_register_master(master);

4、总结


下面简单总结一下实现一个spi控制器驱动,即spi master controller驱动,需要做哪些工作。

第一步,向内核申明spi控制器设备,SoC中通常使用struct platform_device或device tree,你可能会在kernel/arch/arm/mach-*/board-*.c看到类似如下代码:

230         #include <mach/spi.h>
231
232 static struct platform_device spi2 = { ... };
233
234 void mysoc_register_spi(unsigned n, struct mysoc_spi_data *pdata)
235 {
236 struct mysoc_spi_data *pdata2;
237
238 pdata2 = kmalloc(sizeof *pdata2, GFP_KERNEL);
239 *pdata2 = pdata;
240 ...
241 if (n == 2) {
242 spi2->dev.platform_data = pdata2;
243 register_platform_device(&spi2);
244
245 /* also: set up pin modes so the spi2 signals are
246 * visible on the relevant pins ... bootloaders on
247 * production boards may already have done this, but
248 * developer boards will often need Linux to do it.
249 */

250 }
251 ...
252 }
253

或在支持device tree的平台上,在kernel/arch/arm/boot/dts/xxx.dts中看到如下代码:

369         spi0: spi@0x0000abcd {
370 compatible = "xxx,xxxx";
371 #address-cells = <1>;
372 #size-cells = <0>;
373 reg = <0x0000abcd 0x400>;
383 };

不同的平台可能有所不同。

第二步,spi控制器相关的platform_device被注册在platform_bus上,需要写一个驱动来绑定这个platform_device,并在platform_driver的probe接口中创建并提供struct spi_master对象。

第三步,实现spi_master对象中的一些接口,比如:setup()cleanup()prepare_transfer_hardware()等。

第四步,具体平台相关的代码,例如配置寄存器,设置中断和DMA等。

第五步,注册spi_master到spi子系统中去。

未完待续………