我正在try 创建一个平台驱动程序,我有以下代码

模块

// SPDX-License-Identifier: GPL-2.0

#include <linux/module.h>
#include <linux/init.h>
#include <linux/pm.h>
#include <linux/of_device.h>
#include <linux/fb.h>

static int simple_probe(struct platform_device *pdev)
{
    printk(KERN_ERR "SIMPLE: %s\n", "Probing");
    return 0;
}

const struct of_device_id simple_of_match[] = {
    {
        .compatible = "example,simple",
    },
    { /*End of List*/ },
};

struct platform_driver simple_driver = { 
    .probe = simple_probe,
    .driver = { 
        .name = "simple",
        .owner = THIS_MODULE,
        .of_match_table = simple_of_match 
    }
};

static int __init init(void)
{
    if (platform_driver_register(&simple_driver)) {
        printk(KERN_ERR "SIMPLE: %s\n", "Registerered");
    } else {
        printk(KERN_ERR "SIMPLE: %s\n", "Failed");
    }
    return 0;
}

static void __exit deinit(void)
{
    platform_driver_unregister(&simple_driver);
}

module_init(init);
module_exit(deinit);

MODULE_DESCRIPTION("Simple Platform driver");
MODULE_AUTHOR("Bret Joseph Antonio <bret@binclab.com>");
MODULE_LICENSE("GPL");

我的设备树似乎没有运行覆盖,因此设备状态为OK.它仍然没有运行探测回调.

设备树

/dts-v1/;

/ {
    simple@0 {
        compatible = "example,simple";
        pinctrl-names = "lcm_rst_out1_gpio", "lcm_rst_out0_gpio";
        pinctrl-0 = <&PHANDLE1>;
        pinctrl-1 = <&PHANDLE2>;
        status = "okay";
    };
};

我希望内核注册我的驱动程序,然后运行探测函数,但代码

    if (platform_driver_register(&simple_driver) == 0) {
        printk(KERN_ERR "SIMPLE: %s\n", "Registered");
    } else {
        printk(KERN_ERR "SIMPLE: %s\n", "Failed");
    }

返回[ 0.178889] SIMPLE: Registered,但探测函数保持静默.探测功能依赖于什么? 它是否应该在发现设备树中的 node 后立即运行探测?

推荐答案

您需要使用MODULE_DEVICE_TABLE(of, simple_of_match);语句将您的struct of_device_id simple_of_match[]转换为of(开放固件)子系统.这将在构建时为模块创建所需的alias条目.

Consolation is that other kernel drivers in mainline have been patched for this very same omission, e.g. [PATCH] mtd: nand: tango: Export OF device ID table as module aliases and [PATCH] pwm: samsung: Use MODULE_DEVICE_TABLE() to include OF modalias.
That latter patch mentions:

如果...驱动程序被构建为一个模块,modalias信息是 未填充,因此模块不会自动加载.使用MODULE_DEVICE_TABLE() 宏导出设备ID,以便模块包含该信息.

这意味着,如果您的驱动程序始终是内置模块而不是可加载模块,则不需要使用MODULE_DEVICE_TABLE(of, simple_of_match);语句.


内核代码的约定是尽可能将所有符号声明为static.您的代码在这方面不一致,即struct of_device_id simple_of_match[]struct platform_driver simple_driver是全局的.

补丁形式的建议编辑:

- const struct of_device_id simple_of_match[] = {
+ static struct of_device_id simple_of_match[] = {
    {
        .compatible = "example,simple",
    },
    { /*End of List*/ },
  };

+ MODULE_DEVICE_TABLE(of, simple_of_match);


- struct platform_driver simple_driver = { 
+ static struct platform_driver simple_driver = { 
     .probe = simple_probe,
     .driver = { 
         .name = "simple",
         .owner = THIS_MODULE,
         .of_match_table = simple_of_match 
     }
  };

C++相关问答推荐

如何在C中只使用一个带双方括号([i][j])访问语法的malloc来分配动态大小的2d数组?

在C中使用动态内存分配找到最小的负数

为什么GCC在每次循环迭代时都会生成一个数组的mov&S使用[]访问数组?(-03,x86)

向上强制转换C中的数值类型总是可逆的吗?

具有交换链获取和命令缓冲区提交的同步-危险-读后写错误

使用AVX2的英特尔2022编译器的NaN问题&;/fp:FAST

轮询libusb_pollfd struct 列表的正确方式是什么?

如何使用[BTStack]BLE发送大型(>;2kb)信息包

为什么memcpy进入缓冲区和指向缓冲区的指针工作相同?

获取前2个连续1比特的索引的有效方法

当内存来自Malloc时,将char*转换为另一个指针类型是否违反了严格的别名规则?

';\n&39;和';\r&39;中的';\n&39;之间有什么关系?

试图创建一个基本的Word克隆,但遇到了障碍

Ubuntu编译:C中的文件格式无法识别错误

C 程序不显示任何输出,但它接受 CS50 Lab1 的输入问题

使用共享变量同步多线程 C 中的函数

如何向 execl 创建的后台程序提供输入?

全局变量 y0 与 mathlib 冲突,无法编译最小的 C 代码

`void foo(int a[static 0]);` 有效吗?

当 a 是代码块时使用逗号运算符 (a, b)