有些时候,我们需要自己新增一个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
写完啦。