一、硬件功能
假设这个虚拟的GPIO Controller有4个引脚:
二、编写设备树文件
gpio_virt: virtual_gpiocontroller {
compatible = "100ask,virtual_gpio";
gpio-controller;
#gpio-cells = <2>;
ngpios = <4>;
};
三、编写驱动程序
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/gpio/driver.h>
#include <linux/gpio.h>
static struct gpio_chip *g_virt_gpio;
static int g_gpio_val = 0;
static const struct of_device_id virtual_gpio_of_match[] = {
{ .compatible = "100ask,virtual_gpio", },
{ /* sentinel */ }
};
static int virt_gpio_direction_output(struct gpio_chip *gc,
unsigned offset, int val)
{
printk("%s %d\n", __FUNCTION__, __LINE__);
printk("set pin %d as output %s\n", offset, val ? "high" : "low");
return 0;
}
static int virt_gpio_direction_input(struct gpio_chip *gc,
unsigned offset)
{
printk("%s %d\n", __FUNCTION__, __LINE__);
printk("set pin %d as input\n", offset);
return 0;
}
static int virt_gpio_get_value(struct gpio_chip *gc, unsigned offset)
{
printk("%s %d\n", __FUNCTION__, __LINE__);
return (g_gpio_val & (1<<offset)) ? 1: 0;
}
static void virt_gpio_set_value(struct gpio_chip *gc,
unsigned offset, int val)
{
printk("%s %d val:%d\n", __FUNCTION__, __LINE__, val);
if(val) {
g_gpio_val |= (1<<offset);
} else {
g_gpio_val &= ~(1<<offset);
}
}
static int virtual_gpio_probe(struct platform_device *pdev)
{
int ret = 0;
unsigned int val;
printk("%s %d\n", __FUNCTION__, __LINE__);
g_virt_gpio = devm_kzalloc(&pdev->dev, sizeof(*g_virt_gpio), GFP_KERNEL);
g_virt_gpio->label = pdev->name;
g_virt_gpio->direction_output = virt_gpio_direction_output;
g_virt_gpio->direction_input = virt_gpio_direction_input;
g_virt_gpio->get = virt_gpio_get_value;
g_virt_gpio->set = virt_gpio_set_value;
g_virt_gpio->parent = &pdev->dev;
g_virt_gpio->owner = THIS_MODULE;
g_virt_gpio->base = -1;
ret = of_property_read_u32(pdev->dev.of_node, "ngpios", &val);
g_virt_gpio->ngpio = val;
ret = devm_gpiochip_add_data(&pdev->dev, g_virt_gpio, NULL);
return 0;
}
static int virtual_gpio_remove(struct platform_device *pdev)
{
printk("%s %d\n", __FUNCTION__, __LINE__);
return 0;
}
static struct platform_driver virtual_gpio_driver = {
.driver = {
.name = "vitual-gpio",
.of_match_table = of_match_ptr(virtual_gpio_of_match),
},
.probe = virtual_gpio_probe,
.remove = virtual_gpio_remove,
};
static int virtual_gpio_init(void)
{
printk("%s %d\n", __FUNCTION__, __LINE__);
return platform_driver_register(&virtual_gpio_driver);
}
static void virtual_gpio_exit(void)
{
printk("%s %d\n", __FUNCTION__, __LINE__);
platform_driver_unregister(&virtual_gpio_driver);
}
module_init(virtual_gpio_init);
module_exit(virtual_gpio_exit);
MODULE_LICENSE("GPL");