zoukankan      html  css  js  c++  java
  • 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
    ",
        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
    ",
        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)
    ",
        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
    ",
        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
    ",
        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)
    ",
        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
    ",
        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 }    
    
  • 相关阅读:
    AQS共享锁应用之Semaphore原理
    AQS与重入锁ReetrantLock原理
    2018第23周总结
    阅读思考——被误用的敏捷和阻碍程序员成长的坏习惯
    百度云盘下载工具
    线程中断总结
    JUC包中的锁框架
    Java并发实现线程阻塞原语LockSupport
    react的类型检查PropTypes自React v15.5起已弃用,请使用prop-types
    python性能优化、内存优化、内存泄露;与其他语音比较效率如何?
  • 原文地址:https://www.cnblogs.com/chenfulin5/p/8472426.html
Copyright © 2011-2022 走看看