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

  • 二、 设备树配置如下:

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

  1. // drivers/spi/spi.c
  2. 2772 postcore_initcall(spi_init); // spi_init
  3. 2733 static int __init spi_init(void)
  4. 2734 {
  5. 2735 int status;
  6. 2736
  7. 2737 buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
  8. 2738 if (!buf) {
  9. 2739 status = -ENOMEM;
  10. 2740 goto err0;
  11. 2741 }
  12. 2742
  13. 2743 status = bus_register(&spi_bus_type);
  14. 2744 if (status < 0)
  15. 2745 goto err1;
  16. 2746
  17. 2747 status = class_register(&spi_master_class);
  18. 2748 if (status < 0)
  19. 2749 goto err2;
  20. 2750
  21. 2751 if (IS_ENABLED(CONFIG_OF_DYNAMIC))
  22. 2752 WARN_ON(of_reconfig_notifier_register(&spi_of_notifier)); // 这里要注册 主机和从机
  23. 2753
  24. 2754 return 0;
  25. 2755
  26. 2756 err2:
  27. 2757 bus_unregister(&spi_bus_type);
  28. 2758 err1:
  29. 2759 kfree(buf);
  30. 2760 buf = NULL;
  31. 2761 err0:
  32. 2762 return status;
  33. 2763 }
  34. 2726 static struct notifier_block spi_of_notifier = {
  35. 2727 .notifier_call = of_spi_notify,
  36. 2728 };
  37. 2686 static int of_spi_notify(struct notifier_block *nb, unsigned long action,
  38. 2687 void *arg)
  39. 2688 {
  40. 2689 struct of_reconfig_data *rd = arg;
  41. 2690 struct spi_master *master;
  42. 2691 struct spi_device *spi;
  43. 2692
  44. 2693 switch (of_reconfig_get_state_change(action, arg)) {
  45. 2694 case OF_RECONFIG_CHANGE_ADD:
  46. 2695 master = of_find_spi_master_by_node(rd->dn->parent); // 找到主机节点
  47. 2696 if (master == NULL)
  48. 2697 return NOTIFY_OK; /* not for us */
  49. 2698
  50. 2699 spi = of_register_spi_device(master, rd->dn); // ---> 注册设备
  51. 2700 put_device(&master->dev);
  52. // ... ...
  53. 2722
  54. 2723 return NOTIFY_OK;
  55. 2724 }
  56. 1428 #if defined(CONFIG_OF)
  57. 1429 static struct spi_device *
  58. 1430 of_register_spi_device(struct spi_master *master, struct device_node *nc)
  59. 1431 {
  60. 1432 struct spi_device *spi;
  61. 1433 int rc;
  62. 1434 u32 value;
  63. 1435
  64. 1436 /* Alloc an spi_device */
  65. 1437 spi = spi_alloc_device(master);
  66. 1438 if (!spi) {
  67. 1439 dev_err(&master->dev, "spi_device alloc error for %s\n",
  68. 1440 nc->full_name);
  69. 1441 rc = -ENOMEM;
  70. 1442 goto err_out;
  71. 1443 }
  72. 1444
  73. 1445 /* Select device driver */
  74. 1446 rc = of_modalias_node(nc, spi->modalias, // 匹配到从机
  75. 1447 sizeof(spi->modalias));
  76. 1448 if (rc < 0) {
  77. 1449 dev_err(&master->dev, "cannot find modalias for %s\n",
  78. 1450 nc->full_name);
  79. 1451 goto err_out;
  80. 1452 }
  81. 1453
  82. 1454 /* Device address */
  83. 1455 rc = of_property_read_u32(nc, "reg", &value); // 设备节点 reg 表示 cs
  84. 1456 if (rc) {
  85. 1457 dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n",
  86. 1458 nc->full_name, rc);
  87. 1459 goto err_out;
  88. 1460 }
  89. 1461 spi->chip_select = value;
  90. 1462
  91. 1463 /* Mode (clock phase/polarity/etc.) */ // 选择 spi 的模式
  92. 1464 if (of_find_property(nc, "spi-cpha", NULL))
  93. 1465 spi->mode |= SPI_CPHA;
  94. 1466 if (of_find_property(nc, "spi-cpol", NULL))
  95. 1467 spi->mode |= SPI_CPOL;
  96. 1468 if (of_find_property(nc, "spi-cs-high", NULL)) // 选择 spi cs 是高有效还是低有效
  97. 1469 spi->mode |= SPI_CS_HIGH;
  98. 1470 if (of_find_property(nc, "spi-3wire", NULL))
  99. 1471 spi->mode |= SPI_3WIRE;
  100. 1472 if (of_find_property(nc, "spi-lsb-first", NULL))
  101. 1473 spi->mode |= SPI_LSB_FIRST;
  102. 1474
  103. 1475 /* Device DUAL/QUAD mode */ // 选择 单线还是双线通道
  104. 1476 if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) {
  105. 1477 switch (value) {
  106. 1478 case 1:
  107. 1479 break;
  108. 1480 case 2:
  109. 1481 spi->mode |= SPI_TX_DUAL;
  110. 1482 break;
  111. 1483 case 4:
  112. 1484 spi->mode |= SPI_TX_QUAD;
  113. 1485 break;
  114. 1486 default:
  115. 1487 dev_warn(&master->dev,
  116. 1488 "spi-tx-bus-width %d not supported\n",
  117. 1489 value);
  118. 1490 break;
  119. 1491 }
  120. 1492 }
  121. 1493
  122. 1494 if (!of_property_read_u32(nc, "spi-rx-bus-width", &value)) {
  123. 1495 switch (value) {
  124. 1496 case 1:
  125. 1497 break;
  126. 1498 case 2:
  127. 1499 spi->mode |= SPI_RX_DUAL;
  128. 1500 break;
  129. 1501 case 4:
  130. 1502 spi->mode |= SPI_RX_QUAD;
  131. 1503 break;
  132. 1504 default:
  133. 1505 dev_warn(&master->dev,
  134. 1506 "spi-rx-bus-width %d not supported\n",
  135. 1507 value);
  136. 1508 break;
  137. 1509 }
  138. 1510 }
  139. 1511
  140. 1512 /* Device speed */ // 设备速度 配置
  141. 1513 rc = of_property_read_u32(nc, "spi-max-frequency", &value);
  142. 1514 if (rc) {
  143. 1515 dev_err(&master->dev, "%s has no valid 'spi-max-frequency' property (%d)\n",
  144. 1516 nc->full_name, rc);
  145. 1517 goto err_out;
  146. 1518 }
  147. 1519 spi->max_speed_hz = value;
  148. 1520
  149. 1521 /* Store a pointer to the node in the device structure */
  150. 1522 of_node_get(nc);
  151. 1523 spi->dev.of_node = nc; // 保存设备结构体
  152. 1524
  153. 1525 /* Register the new device */
  154. 1526 rc = spi_add_device(spi);
  155. 1527 if (rc) {
  156. 1528 dev_err(&master->dev, "spi_device register error %s\n",
  157. 1529 nc->full_name);
  158. 1530 goto err_out;
  159. 1531 }
  160. 1532
  161. 1533 return spi;
  162. 1534
  163. 1535 err_out:
  164. 1536 spi_dev_put(spi);
  165. 1537 return ERR_PTR(rc);
  166. 1538 }

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

  1. linux设备驱动程序-i2c(2)-adapter和设备树的解析

    linux设备驱动程序-i2c(2)-adapter和设备树的解析 (注: 基于beagle bone green开发板,linux4.14内核版本) 在本系列linux内核i2c框架的前两篇,分别讲 ...

  2. linux驱动之获取设备树信息

    上一篇文章学习了字符设备的注册,操作过的小伙伴都知道上一篇文章中测试驱动时是通过手动创建设备节点的,现在开始学习怎么自动挂载设备节点和设备树信息的获取,这篇文章中的源码将会是我以后编写字符驱动的模板. ...

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

    http://blog.csdn.net/21cnbao/article/details/8457546 宋宝华 Barry Song <21cnbao@gmail.com> 1.     ...

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

    1. ARM Device Tree起源 Linus Torvalds在2011年3月17日的ARM Linux邮件列表宣称“this whole ARM thing is a f*cking pai ...

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

    1.    ARM Device Tree起源 http://blog.csdn.net/21cnbao/article/details/8457546 Linus Torvalds在2011年3月1 ...

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

    原文网址:http://blog.csdn.net/21cnbao/article/details/8457546 1.    ARM Device Tree起源 Linus Torvalds在201 ...

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

    转自:http://blog.csdn.net/21cnbao/article/details/8457546 宋宝华 Barry Song <21cnbao@gmail.com> 1.  ...

  8. imx6设备树pinctrl解析【转】

    转自:http://blog.csdn.net/michaelcao1980/article/details/50730421 版权声明:本文为博主原创文章,未经博主允许不得转载. 最近在移植linu ...

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

      Linux下,I/O处理的层次可分为4层: 系统调用层,应用程序使用系统调用指定读写哪个文件,文件偏移是多少 文件系统层,写文件时将用户态中的buffer拷贝到内核态下,并由cache缓存该部分数 ...

随机推荐

  1. PowerShell 获取Site Collection下被签出的文件

    由于权限的设置,当文件被签出时导致别人不可见了,这对校验文件个数的人来说着实是件烦恼的事.幸好利用PowerShell,可以获取Site Collection下被签出的文件. Resolution A ...

  2. c#asp.net url 传递中文参数要使用 System.Web.HttpUtility.UrlEncode 而不能使用Server.UrlEncode

    最近网站里的参数包括中文的例如: http://www.taiba/Tag%b0%ae%c7%e9.html 已开始使用 Server.UrlEncode来做的,但发现,有一些中文在url重写的是说找 ...

  3. 温故而知新 监听 XMLHttpRequest 发起请求

    window.XMLHttpRequest.prototype.open 可以监听 XMLHttpRequest .但不能监听fetch请求. <!DOCTYPE html> <ht ...

  4. spring-cloud/spring-cloud-sleuth github 项目 mark

    97  Star639 Fork335 spring-cloud/spring-cloud-sleuth CodeIssues 5Pull requests 1Projects 0WikiInsigh ...

  5. Vue的计算属性和侦听器

    1 计算属性:他是根据对象已有的属性计算出新的属性值.具有缓存的功能,如果原始属性不变,则用缓存.否则,重新计算. 前端 <form> <label>姓</label&g ...

  6. ARM:移动GPU往PC GPU效能迈进

    行动装置的热潮持续不退,各大手机制造商除了想尽办法推出外型酷炫的行动装置设备来吸引消费者的目光之外,更在行动应用处理器玩起多核心的「核」战争,无非是希望能够带给消费者更优异的效能新体验.然而,随着消费 ...

  7. django form 对象is_bound属性

    问题: 如果判断一个form实例中有没有数据? bug方法: 通过form实例的is_valid()方法来验证 1.Form类的定义 class YourName(Form): your_name = ...

  8. Jenkins管理静态资源

    这里我们的前端是使用webpack来管理静态资源的,把静态资源上传到svn上面来管理 这里我们把项目和静态资源剥离开来,然后静态资源接入CDN 我们的svn的结构是这样的 我们需要把这些目录都进行打包 ...

  9. Atitit 找人软福利建设 技术团队建设大概流程

    Atitit 找人软福利建设 技术团队建设大概流程 火车公司有免费车座,餐馆有免费饭吃.. 软件公司嘛,就是软件资源,知识了...技术... 培训体系 大概的知识库体系..让他知道来到我们团队有着很高 ...

  10. Atitit it行业图像处理行业软件行业感到到迷茫的三大原因和解决方案

    Atitit it行业图像处理行业软件行业感到到迷茫的三大原因和解决方案 1. 迷茫的原因最大原因是未知1 1.1. 我在哪里??自己的定位,1 1.2. 正确方向是什么??1 1.3. 虽然找到方向 ...