Android 驱动-点灯
通过设备树属性
1. 设备树
&leds_test_node
{
compatible = "leds_test";
status = "disable";
// 添加属性 of_get_name_gpio(node, "gpios1", 0)
gpios1 = <&gpl2 0 GPIO_ACTIVE_HIGH>;
gpios2 = <&gpk1 1 GPIO_ACTIVE_HIGH>;
}
2. 解析设备树
int gpio_pin[2] = {-1, -1};
static int leds_probe(struct platform_device *pdev)
{
int ret;
struct pinctl *pinctl;
struct device *dev = &pdev->dev;
pinctl = devm_pinctl_get_select_default(dev);
// gpio编号
gpio_pin[0] = of_get_name_gpio(node, "gpios1", 0);
gpio_pin[1] = of_get_name_gpio(node, "gpios2", 0);
// 申请
ret = gpio_request(gpio_pin[0], "led1");
if (ret != 0)
{
printk("gpio request failed\n");
return ret;
}
ret = gpio_request(gpio_pin[1], "led2");
if (ret != 0)
{
printk("gpio request failed\n");
return ret;
}
gpio_free(gpio_pin[0]);
gpio_free(gpio_pin[1]);
gpio_direction_output(gpio_pin[0], 0);
gpio_set_value(gpio_pin[0], 1);
gpio_direction_output(gpio_pin[1], 0);
gpio_set_value(gpio_pin[1], 1);
return 0;
}
通过设备树引脚
1. 设备树
&leds_test_node
{
status = "okay";
pinctrl - names = "itop-leds1-on", "itop-leds1-off";
pinctrl - 0 = <&leds_gpios1_on>;
pinctrl - 1 = <&leds_gpios1_off>;
};
2. 解析设备树
static int leds_probe(struct platform_device *pdev)
{
int ret;
struct pinctl *pinctl;
struct pinctl_state *state;
struct device *dev = &pdev->dev;
pinctl = devm_pinctl_get();
if (IS_ERR(pinctl))
{
printk("%d\n", PTR_ERR(pinctl));
}
state = pinctl_lookup_state(pinctl, "itop-leds1-on");
if (IS_ERR(state))
{
printk("%d\n", PTR_ERR(state));
}
ret = pinctl_select_state(pinctl, state);
if (ret < 0)
{
}
// 释放句柄
devm_pinctl_put(pinctl);
// pinctl = devm_pinctl_get_select_default(&pdev->dev);
return 0;
}
完整代码
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/pinctl/consumer.h>
#define DEVICE_NAME "leds_test"
int gpio_pin[2] = {-1, -1};
int leds_open(struct inode *inode, struct file *filp)
{
printk("open\n");
return nonseekable_open(inode, filp);
}
int leds_release(struct inode *inode, struct file *silp)
{
printk("close\n");
return 0;
}
long leds_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
printk("ioctl\n");
switch (cmd)
{
case 0:
case 1:
gpio_set_value(gpio_pin[arg], cmd);
break;
default:
return -1;
}
return 0;
}
static struct file_operations leds_ops = {
.owner = THIS_MODULE,
.open = leds_open,
.release = leds_release,
.unlocked_ioctl = leds_ioctl,
};
// static struct miscdevice leds_dev = {
// .minor = MISC_DYNAMIC_MINOR,
// .fops = &leds_ops,
// .name = DRIVER_NAME,
// };
static int leds_probe(struct platform_device *pdev)
{
// struct device_node *node = pdev->dev.of_node;
int ret;
struct pinctl *pinctl;
struct pinctl_state *state;
printk("probe\n");
struct device *dev = &pdev->dev;
pinctl = devm_pinctl_get();
if (IS_ERR(pinctl))
{
printk("%d\n", PTR_ERR(pinctl));
}
state = pinctl_lookup_state(pinctl, "itop-leds1-on");
if (IS_ERR(state))
{
printk("%d\n", PTR_ERR(state));
}
ret = pinctl_select_state(pinctl, state);
if (ret < 0)
{
}
// 释放句柄
devm_pinctl_put(pinctl);
// pinctl = devm_pinctl_get_select_default(&pdev->dev);
// // gpio编号
// gpio_pin[0] = of_get_name_gpio(node, "gpios1", 0);
// gpio_pin[1] = of_get_name_gpio(node, "gpios2", 0);
// // 申请
// ret = gpio_request(gpio_pin[0], "led1");
// if (ret != 0)
// {
// printk("gpio request failed\n");
// return ret;
// }
// ret = gpio_request(gpio_pin[1], "led2");
// if (ret != 0)
// {
// printk("gpio request failed\n");
// return ret;
// }
// gpio_free(gpio_pin[0]);
// gpio_free(gpio_pin[1]);
// gpio_direction_output(gpio_pin[0], 0);
// gpio_set_value(gpio_pin[0], 1);
// gpio_direction_output(gpio_pin[1], 0);
// gpio_set_value(gpio_pin[1], 1);
// 杂项设备注冊
// ret = misc_register(&leds_dev);
// if (ret < 0)
// {
// printk("register error\n");
// goto exit;
// }
printk("probe ok\n");
return 0;
// exit:
// misc_deregister(&leds_dev);
// return ret;
}
static int leds_remove(struct platform_device *pdev)
{
// misc_deregister(&leds_dev);
return 0;
}
// 平台设备驱动
static struct of_device_id of_my_match[] = {
{.compatible = "myled"},
{}};
static struct platform_device my_platform_device = {
.remove = leds_release,
.probe = leds_probe,
.driver = {
.name = "myled",
.owner = THIS_MODULE,
.of_match_table = of_my_match,
},
};
static int __init led_module_init(void)
{
printk("%s\n", __FUNCTION__)
platform_device_register(&my_platform_device);
return 0;
}
static void __exit led_module_cleanup(void)
{
platform_device_unregister(&my_platform_device);
}
subys_initcall(led_module_init);
module_init(led_module_init);
module_exit(led_module_cleanup);
MODULE_LICENSE("GPL");
备注
作者 [@lhgcs]
2020 年 07月 28日