spi控制器和spi设备的加载过程

news2024/10/7 6:51:25

 spi控制器都是挂在platform总线上的,所以要等platform总线上的设备驱动加载spi控制器完成后才能加载spi设备。

1.spi控制器加载

由spi控制器驱动程序调用spi_register_master来完成spi控制器驱动加载

int spi_register_master(struct spi_master *master)
{
...

    status = of_spi_register_master(master);    //片选gpio的解析,片选是在控制器配置的

    ...
    if (master->transfer)
        dev_info(dev, "master is unqueued, this is deprecated\n");
    else {
        status = spi_master_initialize_queue(master);   //消息队列的初始化
        if (status) {
            device_del(&master->dev);
            goto done;
        }
    }
    /* add statistics */
    spin_lock_init(&master->statistics.lock);

    mutex_lock(&board_lock);
    list_add_tail(&master->list, &spi_master_list);
    list_for_each_entry(bi, &board_list, list)
        spi_match_master_to_boardinfo(master, &bi->board_info)

//这里是通过spi_register_board_info调用,产生的spi device需要解析并添加到maste链表上
    mutex_unlock(&board_lock);

    /* Register devices from the device tree and ACPI */
    of_register_spi_devices(master);   //spi device的添加
    acpi_register_spi_devices(master);  //acpi设备的添加,这里不关注
done:
    return status;
}

2.片选的解析 

以上是spi master,基本上芯片提供商都有自己的解决方案一般不需要我们改动。与我们相关的是spi device dtsi的配置

3.spi device的添加

static void of_register_spi_devices(struct spi_master *master)
{
    struct spi_device *spi;
    struct device_node *nc;

    if (!master->dev.of_node)
        return;

    for_each_available_child_of_node(master->dev.of_node, nc) {
        if (of_node_test_and_set_flag(nc, OF_POPULATED))
            continue;
        spi = of_register_spi_device(master, nc);
        if (IS_ERR(spi))
            dev_warn(&master->dev, "Failed to create SPI device for %s\n",
                nc->full_name);
    }
}

of_register_spi_device(struct spi_master *master, struct device_node *nc)
{
    struct spi_device *spi;
    int rc;
    u32 value;

    /* Alloc an spi_device */
    spi = spi_alloc_device(master);
    if (!spi) {
        dev_err(&master->dev, "spi_device alloc error for %s\n",
            nc->full_name);
        rc = -ENOMEM;
        goto err_out;
    }

    /* Select device driver */从node中获取compatible属性,然后填充
    rc = of_modalias_node(nc, spi->modalias,
                sizeof(spi->modalias));
    if (rc < 0) {
        dev_err(&master->dev, "cannot find modalias for %s\n",
            nc->full_name);
        goto err_out;
    }

    /* Device address */
    rc = of_property_read_u32(nc, "reg", &value);
    if (rc) {
        dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n",
            nc->full_name, rc);
        goto err_out;
    }
    spi->chip_select = value;

//这个reg是spi device必需配置项,且不能大于master设置的最大片选值。主要是设置片选的下标,因为片选数组是在master里面配置的

    /* Mode (clock phase/polarity/etc.) */
    if (of_find_property(nc, "spi-cpha", NULL))
        spi->mode |= SPI_CPHA;
    if (of_find_property(nc, "spi-cpol", NULL))
        spi->mode |= SPI_CPOL;
    if (of_find_property(nc, "spi-cs-high", NULL))
        spi->mode |= SPI_CS_HIGH;
    if (of_find_property(nc, "spi-3wire", NULL))
        spi->mode |= SPI_3WIRE;
    if (of_find_property(nc, "spi-lsb-first", NULL))
        spi->mode |= SPI_LSB_FIRST;

    /* Device DUAL/QUAD mode */
    if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) {
        switch (value) {
        case 1:
            break;
        case 2:
            spi->mode |= SPI_TX_DUAL;
            break;
        case 4:
            spi->mode |= SPI_TX_QUAD;
            break;
        default:
            dev_warn(&master->dev,
                "spi-tx-bus-width %d not supported\n",
                value);
            break;
        }
    }

    if (!of_property_read_u32(nc, "spi-rx-bus-width", &value)) {
        switch (value) {
        case 1:
            break;
        case 2:
            spi->mode |= SPI_RX_DUAL;
            break;
        case 4:
            spi->mode |= SPI_RX_QUAD;
            break;
        default:
            dev_warn(&master->dev,
                "spi-rx-bus-width %d not supported\n",
                value);
            break;
        }
    }

     //上面是spi mode配置,可以在dtsi里面直接配置,也可以在spi_driver匹配成功后,调用spi_setup重新设定mode

    /* Device speed */
    rc = of_property_read_u32(nc, "spi-max-frequency", &value);
    if (rc) {
        dev_err(&master->dev, "%s has no valid 'spi-max-frequency' property (%d)\n",
            nc->full_name, rc);
        goto err_out;
    }
    spi->max_speed_hz = value;

     //spi最大速率,必需配置

    /* Store a pointer to the node in the device structure */
    of_node_get(nc);
    spi->dev.of_node = nc;

     //主要是作一些检测,没有问题完成device添加。这里注意的是如果同相的控制器上片选配置已经存在链表上,那么这个spi device将会添加失败
    rc = spi_add_device(spi);
    if (rc) {
        dev_err(&master->dev, "spi_device register error %s\n",
            nc->full_name);
        goto err_out;
    }

    return spi;

err_out:
    spi_dev_put(spi);
    return ERR_PTR(rc);
}

从上面大体可知,一个spi device dtsi有两个配置项必需存在

1.reg

2.spi-max-frequency

4.spi中断的解析

 

在驱动匹配成功后,probe加载时会解析中断。这里只需要按中断配置的方式来正常配置中断就好了. eg:

 #interrupt-cells : Defines the width of cells used to represent interrupts.  Typically this value is <2>,

which includes a 32-bit number that represents the interrupt number,

and a 32-bit number that represents the interrupt sense and level.

一般device我们用到的#interrupt-cells配置是2,表示有2个参数。一个是中断后,另一个是中断触发方式
#define IRQ_TYPE_NONE        0
#define IRQ_TYPE_EDGE_RISING    1
#define IRQ_TYPE_EDGE_FALLING    2
#define IRQ_TYPE_EDGE_BOTH    (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
#define IRQ_TYPE_LEVEL_HIGH    4
#define IRQ_TYPE_LEVEL_LOW    8

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/679759.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【ubuntu20.04上构建qemu启动linux kernel】

参考Ubuntu环境下使用qemu搭建arm64运行环境 - 简书 一、交叉编译工具 sudo apt install gcc-aarch64-linux-gnu aarch64-linux-gnu-gcc -v 二、linux内核编译 git clone https://github.com/torvalds/linux.git cp arch/arm64/configs/virt.config .config make ARCHarm64 m…

并网逆变器杂记1-VO-DCC双环控制

NOTE1&#xff1a; 母线电压恒定的条件是&#xff1a; PV输出功率 &#xff0c;等于逆变侧消耗功率 假设&#xff1a;PV侧给母线输入10A &#xff0c;但是逆变侧消耗1A&#xff0c;此时母线Udc会升高 反之PV输入1A&#xff0c;消耗10A&#xff0c;母线Udc会降低。 NOTE2&#…

【IP地址】使用这个免费工具轻松获取地理位置

文章目录 前言一、Ip-API二、使用示例2.1、语言2.2、数据格式 三、简单示例四、更好的服务五、需要注意的点结尾 前言 今天分享一个免费的在线工具来查询IP地址所在的地理位置。可以通过IP地址所属的网络运营商和其他相关信息来确定设备的位置&#xff0c;包括国家、地区、城市…

CentOs中操作用户命令(添加或删除)

1、不添加任何参数,创建 zhangsan 用户 不加参数时,创建用户默认创建一个用户目录以及用户和组同名,且UID和GID相同 useradd zhangsan 用 id和 ll 命令查看一下,是否成功创建用户目录以及用户和用户组 id ll uid1003( zhangsan) gid1003( zhangsan) 组1003( zhangsan) 2…

Obsidian 与 Typora 图片兼容保存路径一致设置

目录 一、问题二、解决方法 Obsidian官网 &#xff1a; https://obsidian.md/ Your thoughts are yours. 你的想法就是你的。 Obsidian stores notes on your device, so you can access them quickly, even offline. No one else can read them, not even us. 黑曜石将笔记存储…

Java——基础语法

文章目录 1. 变量&#xff1a;变量的声明和初始化变量的作用域变量的命名规则常量 2. 运算符&#xff1a;算术运算符关系运算符逻辑运算符位运算符其他运算符 3. 流程控制&#xff1a;分支结构循环结构跳转控制 4. 类与对象&#xff1a;类的概念对象的概念类的成员构造方法和析…

深入理解深度学习——BERT派生模型:T5(Text to Text Transfer Transformer)

分类目录&#xff1a;《深入理解深度学习》总目录 T5的全称为Text to Text Transfer Transformer&#xff0c;是谷歌提出的预训练语言模型领域的通用模型&#xff0c;该模型将所有自然语言问题都转化成文本到文本的形式&#xff0c;并用一个统一的模型解决。为了得到大一统的高…

Tkinter创建列表使用方法

前言 ttk.Treeview 是 Tkinter 模块中的一个组件&#xff0c;它提供了一个可用于显示层次结构数据的树状列表。它具有以下特点和功能&#xff1a; 显示层次结构&#xff1a;ttk.Treeview支持以树状结构显示数据。每个节点可以有子节点&#xff0c;从而形成层次结构。用户可以展…

GPT-2源码实现及GPT-3、GPT-3.5、GPT-4及GPT-5内幕解析(三)

GPT-2源码实现及GPT-3、GPT-3.5、GPT-4及GPT-5内幕解析(三) 5.3 GPT-3 内幕机制可视化解析 GPT-3是一个基于Transformer的语言模型,通过不同的层次提取语言不同层面的特性,构建整个语言的语义信息,它学习的过程跟人类正常学习的过程是类似的,开始的时候是一个无监督预训练…

材料表面与界面 关键概念介绍

目录 1. Conductivity and two general modes of charge transport in solid-state materials (Fig. 1b) 2. What is Bravais lattice, what is basis and what is crystal lattice (Fig. 2). The differences between five possible Bravais lattices in two dimensions (Fi…

【计算机毕设系统项目说明】VB+ACCESS采购管理系统开发(论文+系统+答辩PPT+封面)

大家好&#xff0c;这里是小伙整理的VB项目系列&#xff0c;大家可以用于自己的课设Q或毕设&#xff0c;需要的可自取。 项目包含内容 项目包含&#xff1a; 项目源码 论文 答辩PPT 其他相关 截图&#xff1a; 库存管理软件说明 一.系统设置 1&#xff09; 锁定&#xff1…

2023考研一战上岸 电子科技大学 860软件工程 经验分享

目录 1. 前言&#xff1a;考研&#xff0c;心态最重要&#xff01; 2. 初试各科复习经验 (1) 数学一 (2) 英语一 (3) 专业课 (4) 政治 (5) 四门课时间划分 3. 复试流程和备考建议 (1) 复试流程 (2) 备考建议 4. 结语 首先&#xff0c;先简要做一个自我介绍&#xff…

记录:Qt Creator 10配置安卓开发环境

Qt Creator 现在的安卓开发环境配置相比老版本方便了不少&#xff0c;本文以目前在线安装版的 Qt Creator 10.0.2 Qt 5.15 / Qt 6.5 为例做演示&#xff08;有些文件可能会因为网络问题需要科学上网才能下载&#xff09;。 1.下载 JDK 11 https://adoptium.net/zh-CN/temuri…

MATLAB 之 对话框设计

这里写目录标题 一、对话框设计1. 控件的种类及作用2. 控件的操作2.1 建立控件对象2.2 控件对象的基本控制属性2.3 建立控件对象举例 一、对话框设计 对话框是用户与计算机进行信息交流的临时窗口&#xff0c;在现代软件中有着广泛的应用。在软件设计时&#xff0c;借助于对话…

分治、贪心专题

分治、贪心专题 分治篇LeetCode 241. 为运算表达式设计优先级解题思路代码实现总结 不要纠结&#xff0c;干就完事了&#xff0c;熟练度很重要&#xff01;&#xff01;&#xff01;多练习&#xff0c;多总结&#xff01;&#xff01;&#xff01; 分治篇 LeetCode 241. 为运算…

夏驰和徐策的大学英语四六级备考

一、今日单词&#xff1a; 1.anxiety 中文意思是"焦虑"或"忧虑"。它通常用来描述一种内心的不安、紧张或担忧感。"anxiety"可以指个人的情绪状态&#xff0c;也可以指一种心理疾病或临床诊断。 以下是一些关于"anxiety"的用法和例…

3DMAX样条线轮廓修改器插件SplineOffset使用方法详解

SplineOffset 是 3dMax 的修改器&#xff0c;可创建样条曲线的多个克隆&#xff0c;并可选择增量增加或减少偏移、平移和旋转。在许多方面&#xff0c;它类似于 3ds Max 的内置阵列工具与样条线偏移功能相结合&#xff0c;但有两个主要优点&#xff1a;首先&#xff0c;SplineO…

Spring Framework 6 中的设计模式

文章目录 1、简介2、单例模式&#xff08;Singleton Pattern&#xff09;2.1 单例 Beans&#xff08;Singleton Beans&#xff09;2.2 自动注入单例&#xff08;Autowired Singletons&#xff09; 3、工厂方法模式&#xff08;Factory Method Pattern&#xff09;3.1 应用上下文…

【课程笔记】分布式计算系统 徐辰

分布式计算系统笔记 课程介绍 课程背景 大数据处理系统——> 分布式计算系统 Hadoop&#xff0c;Spark&#xff0c;Flink大数据涵义过于宽泛 本课程/教材 强调系统设计、原理、编程的集合 课程目的 培养系统思维 应用层&#xff1a;搜索、推荐算法设计层&#xff1a…

work 6.24

1、grep&#xff1a;查找字符串 grep 字符串 文件名 -w:按单词查找 -R:实现递归查找&#xff0c;主要用于路径是目录的情况 -i:不区分大小写 -n:显示行号 grep -w "^ubuntu" /etc/passwd ---->查找以ubuntu单词作为开头位置的所在行 grep -w "ubuntu$"…