阅读:6318回复:3

Linux新增一个简单的驱动

楼主#
更多 发布于:2020-08-31 14:30
有些时候,我们需要自己新增一个linux驱动来实现对一些新增模块的上电初始化。这里记录下我自己写的一个最简单的linux驱动。

平台:全志A133 android10

1.在相应的目录,编写源代码
我自己使用的目录是:
kernel/linux-4.9/drivers/sim/
在该目录下,新增了pax_sim.c和pax_sim.h
.
├── Kconfig
├── Makefile
├── pax_sim.c
└── pax_sim.h
Kconfig:
config PAX_SIM
 tristate "support SIM 4G"
 default y
 help
 support SIM 4G
Makefile:
obj-$(CONFIG_PAX_SIM) += pax_sim.o
pax_sim.c:
#include <linux/module.h>
#include <linux/types.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#include "pax_sim.h"


static SIM_INFO sim_info;


static int  sim_probe(struct platform_device *pdev){
 struct device_node *np = pdev->dev.of_node;
 
 const char  *status;
 int ret = 0;
 
 ret = of_property_read_string(np, "status", &status);
 
 if(ret || strcmp(status, "okay")){
 printk("%s:pax sim driver disable.\n", __func__);
 return 0;
 }
 
 printk("%s:pax sim driver probe.\n", __func__);

 sim_info.en_vcc_gpio = of_get_named_gpio_flags(np, "en_vcc_gpio",0,0);
 //printk("%s:en_vcc_gpio=%d.\n", __func__, sim_info.en_vcc_gpio);
 if (gpio_is_valid(sim_info.en_vcc_gpio)) {
 if(gpio_request(sim_info.en_vcc_gpio,"en_vcc_gpio") < 0){
 pr_err("%s:en_vcc_gpio request failed.\n", __func__);
 }else{
 gpio_direction_output(sim_info.en_vcc_gpio, 1);
 }
 }
 
 sim_info.pwr_key_gpio = of_get_named_gpio_flags(np, "pwr_key_gpio",0,0);
 //printk("%s:pwr_key_gpio=%d.\n", __func__, sim_info.pwr_key_gpio);
 if (gpio_is_valid(sim_info.pwr_key_gpio)) {
 if(gpio_request(sim_info.pwr_key_gpio,"pwr_key_gpio") < 0){
 pr_err("%s:pwr_key_gpio request failed.\n", __func__);
 }else{
 gpio_direction_output(sim_info.pwr_key_gpio, 1);
 gpio_set_value(sim_info.pwr_key_gpio, 1);
 msleep(2000);
 gpio_set_value(sim_info.pwr_key_gpio, 0);
 }
 }
 
 sim_info.sim_sel_gpio = of_get_named_gpio_flags(np, "sim_sel_gpio",0,0);
 //printk("%s:sim_sel_gpio=%d.\n", __func__, sim_info.sim_sel_gpio);
 if (gpio_is_valid(sim_info.sim_sel_gpio)) {
 if(gpio_request(sim_info.sim_sel_gpio,"sim_sel_gpio") < 0){
 pr_err("%s:sim_sel_gpio request failed.\n", __func__);
 }else{
 gpio_direction_output(sim_info.sim_sel_gpio, 0);
 }
 }
 return 0;
}

static int  sim_remove(struct platform_device *pdev){
 gpio_free(sim_info.en_vcc_gpio);
 gpio_free(sim_info.pwr_key_gpio);
 gpio_free(sim_info.sim_sel_gpio);
 return 0;
}


static struct of_device_id sim_match_table[] = {
 { .compatible = "pax,sim", },
};


static struct platform_driver sim_driver = {
 .driver = {
 .name = "sim",
 .owner = THIS_MODULE,
 .of_match_table = sim_match_table,
 },
 .probe = sim_probe,
 .remove = sim_remove,
};


static int __init sim_init(void){
 return platform_driver_register(&sim_driver);
}


static void __exit sim_exit(void){
 platform_driver_unregister(&sim_driver);
}

module_init(sim_init);
module_exit(sim_exit);


MODULE_AUTHOR("vaststargames@vaststargames.com");
MODULE_DESCRIPTION("SIM 4G Driver");
MODULE_LICENSE("GPL");

pax_sim.h:

#ifndef __PAX_SIM_H__
#define __PAX_SIM_H__


typedef struct _SIM_INFO{
 int en_vcc_gpio;
 int pwr_key_gpio;
 int sim_sel_gpio;
}SIM_INFO;


#endif
----------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------

然后修改上一级目录的Kconfig和Makefile,将新增的代码包含进去编译:
kernel/linux-4.9/drivers/Kconfig:
source "drivers/gator/Kconfig"
+source "drivers/sim/Kconfig"
endmenu
kernel/linux-4.9/drivers/Makefile:
obj-$(CONFIG_GATOR) += gator/
+obj-$(CONFIG_PAX_SIM) += sim/
----------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------

再然后在内核的config文件中增加PAX_SIM变量来控制模块的编译。
lichee/kernel/linux-4.9/arch/arm64/configs/sun50iw10p1smp_a133_android_defconfig
CONFIG_SUNXI_GMAC=m
CONFIG_OF=y
+CONFIG_PAX_SIM=m
这里我是将他设置为‘m’,也就是编译成ko模块,手动insmod的方式,这样做是为了不影响其他项目。因为我们一个代码多个项目同时用。也可以将它设置为‘y’,直接编译成pax_sim.o链接进内核自动加载。


再然后设置在dts中定义相关的节点,配置gpio口:
lichee/device/config/chips/a100/configs/xxxxxx.dts:
};

+ sim {
+        compatible = "pax,sim";
+ en_vcc_gpio = <&pio PD 16 1 0 1 1>;
+ pwr_key_gpio = <&pio PD 17 1 0 1 1>;
+ sim_sel_gpio = <&pio PH 16 1 0 1 1>;
+ status = "okay";
+ };
};

OK,到这里基本编写完成,我们只需要在init.rc脚本中,insmod这个ko就好啦:
init.sun50iw10p10.rc:
+on fs
+ insmod /vendor/modules/pax_sim.ko

写完啦。
If you have nothing to lose, then you can do anything.
沙发#
发布于:2021-04-12 11:03
板凳#
发布于:2020-09-17 14:00
zhaoyf13:不错,可以出一个linux驱动开发的教程了,《从精通到懵逼》《从入门到放弃》系列回到原帖
嗯,有此意
If you have nothing to lose, then you can do anything.
地板#
发布于:2020-09-17 11:03
不错,可以出一个linux驱动开发的教程了,《从精通到懵逼》《从入门到放弃》系列
[url]http://190.lsal.cn/195/1329.gif?0728100424873[/url]
游客

返回顶部