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); // 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); // 设备节点 reg 表示 cs
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.) */ // 选择 spi 的模式
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)) // 选择 spi cs 是高有效还是低有效
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 }
Linux kernel 有关 spi 设备树参数解析的更多相关文章
- linux设备驱动程序-i2c(2)-adapter和设备树的解析
linux设备驱动程序-i2c(2)-adapter和设备树的解析 (注: 基于beagle bone green开发板,linux4.14内核版本) 在本系列linux内核i2c框架的前两篇,分别讲 ...
- linux驱动之获取设备树信息
上一篇文章学习了字符设备的注册,操作过的小伙伴都知道上一篇文章中测试驱动时是通过手动创建设备节点的,现在开始学习怎么自动挂载设备节点和设备树信息的获取,这篇文章中的源码将会是我以后编写字符驱动的模板. ...
- ARM Linux 3.x的设备树(Device Tree)
http://blog.csdn.net/21cnbao/article/details/8457546 宋宝华 Barry Song <21cnbao@gmail.com> 1. ...
- 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 ...
- 【转】 ARM Linux 3.x的设备树(Device Tree)
1. ARM Device Tree起源 http://blog.csdn.net/21cnbao/article/details/8457546 Linus Torvalds在2011年3月1 ...
- 【转】ARM Linux 3.x的设备树(Device Tree)
原文网址:http://blog.csdn.net/21cnbao/article/details/8457546 1. ARM Device Tree起源 Linus Torvalds在201 ...
- ARM Linux 3.x的设备树(Device Tree)【转】
转自:http://blog.csdn.net/21cnbao/article/details/8457546 宋宝华 Barry Song <21cnbao@gmail.com> 1. ...
- imx6设备树pinctrl解析【转】
转自:http://blog.csdn.net/michaelcao1980/article/details/50730421 版权声明:本文为博主原创文章,未经博主允许不得转载. 最近在移植linu ...
- LINUX kernel笔记系列 :IO块参数 图
Linux下,I/O处理的层次可分为4层: 系统调用层,应用程序使用系统调用指定读写哪个文件,文件偏移是多少 文件系统层,写文件时将用户态中的buffer拷贝到内核态下,并由cache缓存该部分数 ...
随机推荐
- 机器学习---支持向量机(SVM)
非常久之前就学了SVM,总认为不就是找到中间那条线嘛,但有些地方模棱两可,真正编程的时候又是一团浆糊.參数任意试验,毫无章法.既然又又一次学到了这一章节,那就要把之前没有搞懂的地方都整明确,嗯~ 下面 ...
- javascript的崛起及其生态元素
随着web的流行,人们花在浏览器上的时间吸引了巨头们对浏览器的重视,继而几年前富客户端概念,一批富客户端技术的涌现,如silverlight, flex等,曾经风起云涌,最终都败给了html5 和 j ...
- 【转载】java前后端 动静分离,JavaWeb项目为什么我们要放弃jsp?
原文:http://blog.csdn.net/piantoutongyang/article/details/50878214 今天看到两篇文章,讲解 为什么web开发启用jsp,确实挺有道理,整理 ...
- Android 获取闹钟引发的血案
想做一个锁屏的软件.锁屏后可以显示闹钟信息. 一开始的思路是通过android content provider获取 mActivityObject.getContentResolver().quer ...
- java类中serialversionuid 作用 是什么?举个例子说明(转)
serialVersionUID适用于Java的序列化机制.简单来说,Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的.在进行反序列化时,JVM会把传来的字节流中的 ...
- mysql存储过程基础
存储过程简介 SQL语句需要先编译然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储 ...
- Java实现打印功能
用java实现打印,java.awt中提供了一些打印的API,要实现打印,首先要获得打印对象,然后继承Printable实现接口方法print,以便打印机进行打印,最后用Graphics2D直接输出直 ...
- C# Split() 去除 \r\n 分组
str为读入的文本string[] ReadText = str.Replace("\r\n", "@").Split('@'); 转自 http://zhid ...
- 服务器有无中木马前期诊断 注意:wget最好是从服务器上卸载掉,因为多数情况是wget下载木马到服务器的
# rpm -qf /usr/bin/wget wget-.el6_6..x86_64 rpm -e --nodeps wget 有无下列文件: cat /etc/rc.d/init.d/selinu ...
- 破解AI大脑黑盒迈出新一步!谷歌现在更懂机器,还开源了研究工具
https://zhuanlan.zhihu.com/p/34306323 https://distill.pub/2018/building-blocks/