Linux SPI通过设备树文件添加设备

一、设备树文件编写

 1 spi_master: spi_master
 2 {
 3     #address-cells = <1>;
 4     #size-cells = <0>;
 5     compatible = "spi_master";
 6     io_phy_addr = <0x1f000000>;
 7     banks = <0x1110>,<0x1111>,<0x1038>,<0x101E>;
 8     interrupts = <GIC_SPI INT_IRQ_MSPI_0 IRQ_TYPE_LEVEL_HIGH>,<GIC_SPI INT_IRQ_MSPI_1 IRQ_TYPE_LEVEL_HIGH>;
 9     spi0_mode = <1>;
10     spi1_mode = <3>;
11     status = "okay";
12 
13     spi_device: spi_device
14     {
15          compatible = "spi_device";
16          reg = <0x0>;
17          spi-max-frequency = <10000000>;
18          status = "okay";
19     };
20 };

       如上DTS文件片段,SPI Device 节点必须定义在 SPI Master 节点下,其中 compatible 属性和 reg 属性,以上 compatible 属性用于匹配对应的 Driver 程序,reg 属性用于指定使用的 SPI Master 的编号,SPI 相关设备树文件识别见下文讲解。

二、代码流程

       匹配设备树文件在SPI子系统中有两个地方:在 spi_register_master() 中匹配和在 device register 时通过内核的通知链(notifier_block)来调用设备树匹配相关程序。

       在 spi_register_master() 中匹配:

 1 //driver/spi/spi.c
 2 int spi_register_master(struct spi_master *master)
 3 {
 4     static atomic_t      dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
 5     struct device        *dev = master->dev.parent;
 6     struct boardinfo     *bi;
 7     int            status = -ENODEV;
 8     int            dynamic = 0;
 9 
10     if (!dev)
11         return -ENODEV;
12 
13     status = of_spi_register_master(master);
14     if (status)
15         return status;
16 
17     /* even if it's just one always-selected device, there must
18      * be at least one chipselect
19      */
20     if (master->num_chipselect == 0)
21         return -EINVAL;
22 
23     if ((master->bus_num < 0) && master->dev.of_node)
24         master->bus_num = of_alias_get_id(master->dev.of_node, "spi");
25 
26     /* convention:  dynamically assigned bus IDs count down from the max */
27     if (master->bus_num < 0) {
28         /* FIXME switch to an IDR based scheme, something like
29          * I2C now uses, so we can't run out of "dynamic" IDs
30          */
31         master->bus_num = atomic_dec_return(&dyn_bus_id);
32         dynamic = 1;
33     }
34 
35     INIT_LIST_HEAD(&master->queue);
36     spin_lock_init(&master->queue_lock);
37     spin_lock_init(&master->bus_lock_spinlock);
38     mutex_init(&master->bus_lock_mutex);
39     mutex_init(&master->io_mutex);
40     master->bus_lock_flag = 0;
41     init_completion(&master->xfer_completion);
42     if (!master->max_dma_len)
43         master->max_dma_len = INT_MAX;
44 
45     /* register the device, then userspace will see it.
46      * registration fails if the bus ID is in use.
47      */
48     dev_set_name(&master->dev, "spi%u", master->bus_num);
49     status = device_add(&master->dev);
50     if (status < 0)
51         goto done;
52     dev_dbg(dev, "registered master %s%s
", dev_name(&master->dev),
53             dynamic ? " (dynamic)" : "");
54 
55     /* If we're using a queued driver, start the queue */
56     if (master->transfer)
57         dev_info(dev, "master is unqueued, this is deprecated
");
58     else {
59         status = spi_master_initialize_queue(master);
60         if (status) {
61             device_del(&master->dev);
62             goto done;
63         }
64     }
65     /* add statistics */
66     spin_lock_init(&master->statistics.lock);
67 
68     mutex_lock(&board_lock);
69     list_add_tail(&master->list, &spi_master_list);
70     list_for_each_entry(bi, &board_list, list)
71         spi_match_master_to_boardinfo(master, &bi->board_info);
72     mutex_unlock(&board_lock);
73 
74     /* Register devices from the device tree and ACPI */
75     of_register_spi_devices(master);  // 设备树匹配操作
76     acpi_register_spi_devices(master);
77 done:
78     return status;
79 }
 1 //driver/spi/spi.c
 2 static void of_register_spi_devices(struct spi_master *master)
 3 {
 4     struct spi_device *spi;
 5     struct device_node *nc;
 6 
 7     if (!master->dev.of_node)
 8         return;
 9 
10     for_each_available_child_of_node(master->dev.of_node, nc) {
11         if (of_node_test_and_set_flag(nc, OF_POPULATED))
12             continue;
13         spi = of_register_spi_device(master, nc);  // 设备树匹配操作
14         if (IS_ERR(spi)) {
15             dev_warn(&master->dev, "Failed to create SPI device for %s
",
16                 nc->full_name);
17             of_node_clear_flag(nc, OF_POPULATED);
18         }
19     }
20 }

        在 device register 时匹配:

 1 //driver/spi/spi.c
 2 static int __init spi_init(void)
 3 {
 4     int    status;
 5 
 6     buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
 7     if (!buf) {
 8         status = -ENOMEM;
 9         goto err0;
10     }
11 
12     status = bus_register(&spi_bus_type);
13     if (status < 0)
14         goto err1;
15 
16     status = class_register(&spi_master_class);
17     if (status < 0)
18         goto err2;
19 
20     if (IS_ENABLED(CONFIG_OF_DYNAMIC))
21         WARN_ON(of_reconfig_notifier_register(&spi_of_notifier));
22     if (IS_ENABLED(CONFIG_ACPI))
23         WARN_ON(acpi_reconfig_notifier_register(&spi_acpi_notifier));
24 
25     return 0;
26 
27 err2:
28     bus_unregister(&spi_bus_type);
29 err1:
30     kfree(buf);
31     buf = NULL;
32 err0:
33     return status;
34 }
35 
36 postcore_initcall(spi_init);

         在 device register 时,需配置 CONFIG_OF_DYNAMIC 宏以开启动态匹配才能够使用设备树添加设备,该宏在 menuconfig/Device Drivers/Device Tree and Open Firmware support 中开启,如下图:

 1 //driver/spi/spi.c
 2 static struct notifier_block spi_of_notifier = {
 3     .notifier_call = of_spi_notify,
 4 };
 5 
 6 static int of_spi_notify(struct notifier_block *nb, unsigned long action,
 7              void *arg)
 8 {
 9     struct of_reconfig_data *rd = arg;
10     struct spi_master *master;
11     struct spi_device *spi;
12 
13     switch (of_reconfig_get_state_change(action, arg)) {
14     case OF_RECONFIG_CHANGE_ADD:
15         master = of_find_spi_master_by_node(rd->dn->parent);
16         if (master == NULL)
17             return NOTIFY_OK;    /* not for us */
18 
19         if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) {
20             put_device(&master->dev);
21             return NOTIFY_OK;
22         }
23 
24         spi = of_register_spi_device(master, rd->dn);  // 设备树匹配操作
25         put_device(&master->dev);
26 
27         if (IS_ERR(spi)) {
28             pr_err("%s: failed to create for '%s'
",
29                     __func__, rd->dn->full_name);
30             of_node_clear_flag(rd->dn, OF_POPULATED);
31             return notifier_from_errno(PTR_ERR(spi));
32         }
33         break;
34 
35     case OF_RECONFIG_CHANGE_REMOVE:
36         /* already depopulated? */
37         if (!of_node_check_flag(rd->dn, OF_POPULATED))
38             return NOTIFY_OK;
39 
40         /* find our device by node */
41         spi = of_find_spi_device_by_node(rd->dn);
42         if (spi == NULL)
43             return NOTIFY_OK;    /* no? not meant for us */
44 
45         /* unregister takes one ref away */
46         spi_unregister_device(spi);
47 
48         /* and put the reference of the find */
49         put_device(&spi->dev);
50         break;
51     }
52 
53     return NOTIFY_OK;
54 }
  1 //driver/spi/spi.c
  2 static struct spi_device *
  3 of_register_spi_device(struct spi_master *master, struct device_node *nc)
  4 {
  5     struct spi_device *spi;
  6     int rc;
  7     u32 value;
  8 
  9     /* Alloc an spi_device */
 10     spi = spi_alloc_device(master);
 11     if (!spi) {
 12         dev_err(&master->dev, "spi_device alloc error for %s
",
 13             nc->full_name);
 14         rc = -ENOMEM;
 15         goto err_out;
 16     }
 17 
 18     /* Select device driver */
 19     rc = of_modalias_node(nc, spi->modalias,
 20                 sizeof(spi->modalias));
 21     if (rc < 0) {
 22         dev_err(&master->dev, "cannot find modalias for %s
",
 23             nc->full_name);
 24         goto err_out;
 25     }
 26 
 27     /* Device address */
 28     rc = of_property_read_u32(nc, "reg", &value);
 29     if (rc) {
 30         dev_err(&master->dev, "%s has no valid 'reg' property (%d)
",
 31             nc->full_name, rc);
 32         goto err_out;
 33     }
 34     spi->chip_select = value;
 35 
 36     /* Mode (clock phase/polarity/etc.) */
 37     if (of_find_property(nc, "spi-cpha", NULL))
 38         spi->mode |= SPI_CPHA;
 39     if (of_find_property(nc, "spi-cpol", NULL))
 40         spi->mode |= SPI_CPOL;
 41     if (of_find_property(nc, "spi-cs-high", NULL))
 42         spi->mode |= SPI_CS_HIGH;
 43     if (of_find_property(nc, "spi-3wire", NULL))
 44         spi->mode |= SPI_3WIRE;
 45     if (of_find_property(nc, "spi-lsb-first", NULL))
 46         spi->mode |= SPI_LSB_FIRST;
 47 
 48     /* Device DUAL/QUAD mode */
 49     if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) {
 50         switch (value) {
 51         case 1:
 52             break;
 53         case 2:
 54             spi->mode |= SPI_TX_DUAL;
 55             break;
 56         case 4:
 57             spi->mode |= SPI_TX_QUAD;
 58             break;
 59         default:
 60             dev_warn(&master->dev,
 61                 "spi-tx-bus-width %d not supported
",
 62                 value);
 63             break;
 64         }
 65     }
 66 
 67     if (!of_property_read_u32(nc, "spi-rx-bus-width", &value)) {
 68         switch (value) {
 69         case 1:
 70             break;
 71         case 2:
 72             spi->mode |= SPI_RX_DUAL;
 73             break;
 74         case 4:
 75             spi->mode |= SPI_RX_QUAD;
 76             break;
 77         default:
 78             dev_warn(&master->dev,
 79                 "spi-rx-bus-width %d not supported
",
 80                 value);
 81             break;
 82         }
 83     }
 84 
 85     /* Device speed */
 86     rc = of_property_read_u32(nc, "spi-max-frequency", &value);
 87     if (rc) {
 88         dev_err(&master->dev, "%s has no valid 'spi-max-frequency' property (%d)
",
 89             nc->full_name, rc);
 90         goto err_out;
 91     }
 92     spi->max_speed_hz = value;
 93 
 94     /* Store a pointer to the node in the device structure */
 95     of_node_get(nc);
 96     spi->dev.of_node = nc;
 97 
 98     /* Register the new device */
 99     rc = spi_add_device(spi);
100     if (rc) {
101         dev_err(&master->dev, "spi_device register error %s
",
102             nc->full_name);
103         goto err_of_node_put;
104     }
105 
106     return spi;
107 
108 err_of_node_put:
109     of_node_put(nc);
110 err_out:
111     spi_dev_put(spi);
112     return ERR_PTR(rc);
113 }

end

原文地址:https://www.cnblogs.com/xujiawei29/p/12157566.html