Linux kernel 有关 spi 设备树参数解析

  • 最近做了一个 spi 设备驱动从板级设备驱动升级到设备树设备驱动,这其中要了解 spi 设备树代码的解析。

  • 设备树配置如下:

    503 &spi0 {
    504     status = "okay";
    505     pinctrl-name = "default";
    506     pinctrl-0 = <&spi0_pins>;
    507     ti,pindir-d0-out-d1-in;
    508
    509     wk2124A {
    510         compatible = "wk2124A";    //  匹配字符串
    511         reg = <0>;                    // cs
    512         # spi-cpha = <1>;              // 配置 spi  的模式
    513         # spi-tx-bus-width = <1>;   // 这是是 spi-tx 的总线宽度
    514         # spi-rx-bus-width = <1>;
    515         spi-max-frequency = <10000000>;        // spi 最大速率配置
    516     };
    517 };
  • 代码跟踪

    // drivers/spi/spi.c
    2772 postcore_initcall(spi_init);
    
    2733 static int __init spi_init(void)
    2734 {
    2735     int status;
    2736
    2737     buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
    2738     if (!buf) {
    2739         status = -ENOMEM;
    2740         goto err0;
    2741     }
    2742
    2743     status = bus_register(&spi_bus_type);
    2744     if (status < 0)
    2745         goto err1;
    2746
    2747     status = class_register(&spi_master_class);
    2748     if (status < 0)
    2749         goto err2;
    2750
    2751     if (IS_ENABLED(CONFIG_OF_DYNAMIC))
    2752         WARN_ON(of_reconfig_notifier_register(&spi_of_notifier));
    2753
    2754     return 0;
    2755
    2756 err2:
    2757     bus_unregister(&spi_bus_type);
    2758 err1:
    2759     kfree(buf);
    2760     buf = NULL;
    2761 err0:
    2762     return status;
    2763 }
    
    2726 static struct notifier_block spi_of_notifier = {
    2727     .notifier_call = of_spi_notify,
    2728 };
    
    2686 static int of_spi_notify(struct notifier_block *nb, unsigned long action,
    2687              void *arg)
    2688 {
    2689     struct of_reconfig_data *rd = arg;
    2690     struct spi_master *master;
    2691     struct spi_device *spi;
    2692
    2693     switch (of_reconfig_get_state_change(action, arg)) {
    2694     case OF_RECONFIG_CHANGE_ADD:
    2695         master = of_find_spi_master_by_node(rd->dn->parent);
    2696         if (master == NULL)
    2697             return NOTIFY_OK;   /* not for us */
    2698
    2699         spi = of_register_spi_device(master, rd->dn);   // ---> 注册设备
    2700         put_device(&master->dev);
                    // ... ...
    2722
    2723     return NOTIFY_OK;
    2724 }
    
    1428 #if defined(CONFIG_OF)
    1429 static struct spi_device *
    1430 of_register_spi_device(struct spi_master *master, struct device_node *nc)
    1431 {
    1432     struct spi_device *spi;
    1433     int rc;
    1434     u32 value;
    1435
    1436     /* Alloc an spi_device */
    1437     spi = spi_alloc_device(master);
    1438     if (!spi) {
    1439         dev_err(&master->dev, "spi_device alloc error for %s\n",
    1440             nc->full_name);
    1441         rc = -ENOMEM;
    1442         goto err_out;
    1443     }
    1444
    1445     /* Select device driver */
    1446     rc = of_modalias_node(nc, spi->modalias,
    1447                 sizeof(spi->modalias));
    1448     if (rc < 0) {
    1449         dev_err(&master->dev, "cannot find modalias for %s\n",
    1450             nc->full_name);
    1451         goto err_out;
    1452     }
    1453
    1454     /* Device address */
    1455     rc = of_property_read_u32(nc, "reg", &value);
    1456     if (rc) {
    1457         dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n",
    1458             nc->full_name, rc);
    1459         goto err_out;
    1460     }
    1461     spi->chip_select = value;
    1462
    1463     /* Mode (clock phase/polarity/etc.) */
    1464     if (of_find_property(nc, "spi-cpha", NULL))
    1465         spi->mode |= SPI_CPHA;
    1466     if (of_find_property(nc, "spi-cpol", NULL))
    1467         spi->mode |= SPI_CPOL;
    1468     if (of_find_property(nc, "spi-cs-high", NULL))
    1469         spi->mode |= SPI_CS_HIGH;
    1470     if (of_find_property(nc, "spi-3wire", NULL))
    1471         spi->mode |= SPI_3WIRE;
    1472     if (of_find_property(nc, "spi-lsb-first", NULL))
    1473         spi->mode |= SPI_LSB_FIRST;
    1474
    1475     /* Device DUAL/QUAD mode */
    1476     if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) {
    1477         switch (value) {
    1478         case 1:
    1479             break;
    1480         case 2:
    1481             spi->mode |= SPI_TX_DUAL;
    1482             break;
    1483         case 4:
    1484             spi->mode |= SPI_TX_QUAD;
    1485             break;
    1486         default:
    1487             dev_warn(&master->dev,
    1488                 "spi-tx-bus-width %d not supported\n",
    1489                 value);
    1490             break;
    1491         }
    1492     }
    1493
    1494     if (!of_property_read_u32(nc, "spi-rx-bus-width", &value)) {
    1495         switch (value) {
    1496         case 1:
    1497             break;
    1498         case 2:
    1499             spi->mode |= SPI_RX_DUAL;
    1500             break;
    1501         case 4:
    1502             spi->mode |= SPI_RX_QUAD;
    1503             break;
    1504         default:
    1505             dev_warn(&master->dev,
    1506                 "spi-rx-bus-width %d not supported\n",
    1507                 value);
    1508             break;
    1509         }
    1510     }
    1511
    1512     /* Device speed */
    1513     rc = of_property_read_u32(nc, "spi-max-frequency", &value);
    1514     if (rc) {
    1515         dev_err(&master->dev, "%s has no valid 'spi-max-frequency' property      (%d)\n",
    1516             nc->full_name, rc);
    1517         goto err_out;
    1518     }
    1519     spi->max_speed_hz = value;
    1520
    1521     /* Store a pointer to the node in the device structure */
    1522     of_node_get(nc);
    1523     spi->dev.of_node = nc;
    1524
    1525     /* Register the new device */
    1526     rc = spi_add_device(spi);
    1527     if (rc) {
    1528         dev_err(&master->dev, "spi_device register error %s\n",
    1529             nc->full_name);
    1530         goto err_out;
    1531     }
    1532
    1533     return spi;
    1534
    1535 err_out:
    1536     spi_dev_put(spi);
    1537     return ERR_PTR(rc);
    1538 }    

原文地址:https://www.cnblogs.com/chenfulin5/p/8472426.html

时间: 2024-10-10 09:15:16

Linux kernel 有关 spi 设备树参数解析的相关文章

关于linux ARM device tree设备树

关于linux ARM device tree设备树 关于linux device tree .dtb文件是如何加载到内核并解析的.见下图: 关于arm device tree的phandle的处理原理,见下图: 详细情况,见下面我的ARM device tree原理视频课程:https://edu.51cto.com/course/17175.html 具体请参考我的免费的linux各种驱动开发课程如下:https://edu.51cto.com/course/17138.html 另外我的相

ARM Linux 3.x的设备树(Device Tree)【转】

转自:http://blog.csdn.net/21cnbao/article/details/8457546 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] ARM Device Tree起源 Device Tree组成和结构 DTS device tree source DTC device tree compiler Device Tree Blob dtb Binding Bootloader Device Tree引发的BSP和驱动变更 常用OF API 总结

ARM Linux 3.x的设备树(Device Tree)

1.    ARM Device Tree起源 在过去的ARM Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的垃圾代码,相当多数的代码只是在描述板级细节,而这些板级细节对于内核来讲,不过是垃圾,如板上的platform设备.resource.i2c_board_info.spi_board_info以及各种硬件的platform_data.读者有兴趣可以统计下常见的s3c2410.s3c6410等板级目录,代码量在数万行.社区必须改变这种局面,

【转】ARM Linux 3.x的设备树(Device Tree)

原文网址:http://blog.csdn.net/21cnbao/article/details/8457546 1.    ARM Device Tree起源 Linus Torvalds在2011年3月17日的ARM Linux邮件列表宣称“this whole ARM thing is a f*cking pain in the ass”,引发ARM Linux社区的地震,随后ARM社区进行了一系列的重大修正.在过去的ARM Linux中,arch/arm/plat-xxx和arch/a

imx6设备树pinctrl解析【转】

转自:http://blog.csdn.net/michaelcao1980/article/details/50730421 版权声明:本文为博主原创文章,未经博主允许不得转载. 最近在移植linux,用到kernel版本为3.14.28,在高版本的内核源码中用到了设备树(device-tree),设备树中用到pinctrl的配置,记录一下. 1.普通设置 在配置串口时,pinctrl的配置信息如下所示: &uart2 { pinctrl-names = ; ; //........ }; 这

LINUX kernel笔记系列 :IO块参数 图

Linux下,I/O处理的层次可分为4层: 系统调用层,应用程序使用系统调用指定读写哪个文件,文件偏移是多少 文件系统层,写文件时将用户态中的buffer拷贝到内核态下,并由cache缓存该部分数据 块层,管理块设备I/O队列,对I/O请求进行合并.排序 设备层,通过DMA与内存直接交互,将数据写到磁盘 下图清晰地说明了Linux I/O层次结构: 写文件过程 写文件的过程包含了读的过程,文件先从磁盘载入内存,存到cache中,磁盘内容与物理内存页间建立起映射关系.用于写文件的write函数的声

linux kernel (proc文件系统)参数

http://blog.csdn.net/guowake/article/details/3279796 Linux Proc文件系统,通过对Proc文件系统进行调整,达到性能优化的目的. 二./proc/sys/kernel/优化1)     /proc/sys/kernel/ctrl-alt-del该文件有一个二进制值,该值控制系统在接收到ctrl+alt+delete按键组合时如何反应.这两个值分别是:零(0)值,表示捕获ctrl+alt+delete,并将其送至 init 程序:这将允许

设备树DTS使用

参考:<设备树DTS使用总结 - 基于MT76X8> .<linux内核设备树及编译> 一.Linux设备树的起源 在Linux 2.6中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的垃圾代码,相当多数的代码只是在描述板级细节,而这些板级细节对于内核来讲,不过是垃圾,如板上的platform设备.resource.i2c_board_info.spi_board_info以及各种硬件platform_data. 在Linux3.x版本后,ar

分析内核源码,设备树【转】

转自:http://blog.csdn.net/fight_onlyfor_you/article/details/78092204 U-Boot需要将设备树在内存中的存储地址传给内核.该树主要由三大部分组成:头(Header).结构块(Structure block).字符串块(Strings block). 设备树在内存中的存储布局图如下 1.1 头(header) 1.2 结构块(struct block)  扁平设备树结构块是线性化的树形结构,和字符串块一起组成了设备树的主体,以节点形式