[英]Reading Device Hardware Register
我正在嘗試創建一個設備驅動程序,盡管是一個天真簡單的驅動程序,它只是讀取代表撥碼開關的硬件寄存器的狀態。 這方面很新,我不確定在哪里可以找到有關該主題的足夠資源。 最好在 sysfs 中公開數據。
數據傳輸系統:
switches@c1000000 {
compatible = "test, test-switches";
label = "security_switch";
reg = c1000000;
mask = 0x1000;
status = "okay";
};
司機:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mod_devicetable.h>
#include <linux/property.h>
#include <linux/platform_device.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
/* Declare the probe and remove functions */
static int dt_probe(struct platform_device *pdev);
static int dt_remove(struct platform_device *pdev);
/* Declare the read switch function */
int read_switch(struct platform_device *pdev);
int read_switch(struct platform_device *pdev)
{
static void *reg_data;
int ret;
unsigned int adr_reg, bit_mask;
struct device *dev = &pdev->dev;
ret = device_property_read_u32(dev, "reg", &adr_reg);
if(ret) {
printk("Error! Could not read 'reg'\n");
return -1;
}
printk("Reg read as - %d\n", adr_reg);
ret = device_property_read_u32(dev, "mask", &bit_mask);
if(ret) {
printk("Error! Could not read 'mask'\n");
return -1;
}
printk("Mask read as - %d\n", bit_mask);
reg_data = ioremap(adr_reg, bit_mask);
printk("Value @%d", adr_reg);
printk("-%d ", bit_mask);
printk(": %d\n", ioread32(reg_data));
iounmap(reg_data);
return 0;
}
/**
* @brief This structure is used to match the DTS entry
*/
static const struct of_device_id switch_driver_ids[] = {
{
.compatible = "test,test-switches",
}, {}
};
MODULE_DEVICE_TABLE(of, switch_driver_ids);
/**
* @brief Platform Driver definition including functions used for adding, removing and probing
* the device
*/
static struct platform_driver switch_driver = {
.probe = dt_probe,
.remove = dt_remove,
.driver = {
.name = "switch_device_driver",
.of_match_table = switch_driver_ids,
},
};
/**
* @brief This function is called loading the driver
*/
static int dt_probe(struct platform_device *pdev) {
struct device *dev = &pdev->dev;
int ret;
const char *label;
const char *status;
unsigned int reg;
printk("dt_probe - Probing function!\n");
/* Check for device properties */
if(!device_property_present(dev, "label")) {
printk("dt_probe - Error! Device property 'label' not found!\n");
return -1;
}
printk("dt_probe - Error! Device property 'label' found!\n");
if(!device_property_present(dev, "status")) {
printk("dt_probe - Error! Device property 'status' not found!\n");
return -1;
}
printk("dt_probe - Error! Device property 'status' found!\n");
if(!device_property_present(dev, "reg")) {
printk("dt_probe - Error! Device property 'reg' not found!\n");
return -1;
}
printk("dt_probe - Error! Device property 'reg' found!\n");
/* Read device properties */
ret = device_property_read_string(dev, "label", &label);
if(ret) {
printk("dt_probe - Error! Could not read 'label'\n");
return -1;
}
printk("dt_probe - label: %s\n", label);
ret = device_property_read_string(dev, "status", &status);
if(ret) {
printk("dt_probe - Error! Could not read 'status'\n");
return -1;
}
printk("dt_probe - status: %s\n", status);
ret = device_property_read_u32(dev, "reg", ®);
if(ret) {
printk("dt_probe - Error! Could not read 'reg'\n");
return -1;
}
printk("dt_probe - reg: %d\n", reg);
read_switch(pdev);
return 0;
}
/**
* @brief This function is called unloading the driver
*/
static int dt_remove(struct platform_device *pdev) {
printk("dt_probe - Removing driver\n");
return 0;
}
/**
* @brief This function is called when the module is loaded into the kernel
*/
static int __init init_drv(void) {
printk("dt_probe - Loading the driver...\n");
if(platform_driver_register(&switch_driver)) {
printk("dt_probe - Error! Could not load driver\n");
return -1;
}
return 0;
}
/**
* @brief This function is called when the module is removed from the kernel
*/
static void __exit exit_drv(void) {
printk("dt_probe - Unload driver");
platform_driver_unregister(&switch_driver);
}
module_init(init_drv);
module_exit(exit_drv);
這里有關於 sysfs 的基本文檔:
https://docs.kernel.org/filesystems/sysfs.html
在 include/linux/sysfs.h 和 include/linux/device.h 中有更多信息。
不過一般來說:學習這些東西的最佳方法是閱讀 kernel 文檔(kernel 源代碼樹下的文檔文件夾)、Kernel 源代碼本身、郵件列表和其他完善/編寫的主線驅動程序。
這曾經是設備驅動程序的一本不錯的入門書,現在已經過時了,但一些概念可能仍然適用: https://lwn.net/Kernel/LDD3/
不確定我是否遵循 DIP 開關如何“映射”到特定寄存器。 如果這是您的 SOC 上的 GPIO 引腳,那么獲得 sysfs 訪問權限的簡單方法是通過 sysfs 使用 GPIO,盡管根據您的平台整理引腳號可能很棘手。
也就是說,如果這確實需要它自己的驅動程序——那么通常您會希望使用DEVICE_ATTR
宏系列來定義您的屬性,然后使用sysfs_create_group
/ sysfs_remove_group
或sysfs_add_file
/ sysfs_remove_file
來注冊/注銷您的probe
/ remove
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.