基于高通MSM8953平台android9.0的GPIO驱动开发
2.1、注册设备:
2.1.1、添加编译选项:
1)、修改kernel/msm-4.9/drivers/leds下Makefile文件:
obj-$(CONFIG_LED_GPIO) += led_gpio.o
2)、修改kernel/msm-4.9/drivers/leds下Kconfig文件:
config LED_GPIO
tristate "led_gpio"
2.1.2、修改驱动配置文件,驱动编译进系统:
修改kernel/msm-4.9/arch/arm64/configs下的msm8953_defconfig文件:
CONFIG_LED_GPIO=y
2.2、注册驱动:
2.2.1、修改dts设备树文件:
1)、文件名:msm8953-mtp-dtsi。
2)、文件路径:kernel/msm-4.9/arch/arm64/boot/dts/qcom/msm8953-mtp-dtsi
3)、在&soc下添加:
&soc {
led_gpio {
compatible = "led_gpio";
led_gpio,gpio97 = <&tlmm 97 0x1>;
};
};
2.2.2、添加驱动:
在kernel/msm-4.9/drivers/leds下添加led_gpio.c文件:
#include <linux/types.h>
#include <linux/pm.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/fsl_devices.h>
#include <asm/setup.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/stat.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/spinlock.h>
#include <linux/err.h>
#include <linux/regulator/consumer.h>
int led_gpio97 = -1;
static struct class * led_gpios_class = NULL;
static struct device * led_gpio97_dev = NULL;
#define CTL_LED_ON "1"
#define CTL_LED_OFF "0"
//使用 cat命令时候调用此函数
static ssize_t led_gpio97_show(struct device *dev,struct device_attribute *attr, char *buf)
{
int gpio_state = gpio_get_value(led_gpio97);
sprintf(buf, "%d\n", gpio_state);
return strlen(buf);
}
//使用 echo 命令时候调用此函数
static ssize_t led_gpio97_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
if(!strncmp(buf, CTL_LED_ON, strlen(CTL_LED_ON))) {
gpio_set_value(led_gpio97, 1);
} else if(!strncmp(buf, CTL_LED_OFF, strlen(CTL_LED_OFF))) {
gpio_set_value(led_gpio97, 0);
}
return count;
}
static struct device_attribute led_gpio97_dev_attr = {
.attr = {
.name = "state",
.mode = S_IRWXU|S_IRWXG|S_IRWXO,
},
.show = led_gpio97_show,
.store = led_gpio97_store,
};
static int led_gpio_probe(struct platform_device *pdev)
{
int ret = 0;
printk("enter led_gpio_probe \n");
//寻找设备树dts下的 "led_gpio,gpio97" 名称对应的GPIO口
led_gpio97 = of_get_named_gpio(pdev->dev.of_node, "led_gpio,gpio97", 0);
if (led_gpio97 < 0)
printk("led_gpio97 is not available \n");
//对应修改的dts的 label
ret = gpio_request(led_gpio97, "led_gpio");
if(0 != ret) {
printk("gpio request %d failed.", led_gpio97);
goto fail1;
}
gpio_direction_output(led_gpio97, 0); //设置gpio为输出
//创建led_gpios节点
led_gpios_class = class_create(THIS_MODULE, "led_gpios");
if(IS_ERR(led_gpios_class))
{
ret = PTR_ERR(led_gpios_class);
printk("Failed to create class.\n");
return ret;
}
//创建led_gpio97 的驱动设备
led_gpio0_dev=device_create(led_gpios_class, NULL, 0, NULL, "led_gpio7");
if (IS_ERR(led_gpio97_dev))
{
ret = PTR_ERR(test_gpios_class);
printk("Failed to create device(led_gpio97_dev)!\n");
return ret;
}
//根据 led_gpio0_dev_attr 配置,生成相应的文件
ret = device_create_file(led_gpio97_dev, & led_gpio97_dev_attr);
if(ret)
{
pr_err("%s: led_gpio97 creat sysfs failed\n",__func__);
return ret;
}
printk("enter led_gpio_probe, ok \n");
fail1:
return ret;
}
static int led_gpio_remove(struct platform_device *pdev)
{
device_destroy(led_gpios_class, 0);
class_destroy(led_gpios_class);
device_remove_file(led_gpio97_dev, & led_gpio97_dev_attr);
return 0;
}
static int led_gpio_suspend(struct platform_device *pdev,pm_message_t state)
{
return 0;
}
static int led_gpio_resume(struct platform_device *pdev)
{
return 0;
}
static struct of_device_id led_gpio_dt_match[] = {
{ .compatible = "led_gpio",},
{ },
};
MODULE_DEVICE_TABLE(of, led_gpio_dt_match);
//驱动的方法与函数对应
static struct platform_driver gpio_led_driver = {
.driver = {
.name = "led_gpio",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(led_gpio_dt_match),
},
.probe = led_gpio_probe,
.remove = led_gpio_remove,
.suspend = led_gpio_suspend,
.resume = led_gpio_resume,
};
static __init int gpio_led_init(void)
{
return platform_driver_register(&gpio_led_driver);
}
static void __exit gpio_led_exit(void)
{
platform_driver_unregister(&gpio_led_driver);
}
module_init(gpio_led_init);
module_exit(gpio_led_exit);
MODULE_LICENSE("GPL");
2.3、编译系统:
source build/envsetup.sh
lunch msm8953_64-userdebug
make -j8