一、旧版的gpio子系统
1、函数接口
static inline int of_get_gpio(struct device_node *np, int index) //从设备树获取 gpio
static inline int gpio_request(unsigned gpio, const char *label) //拿到gpio引脚使用权
static inline void gpio_free(unsigned gpio) //释放gpio引脚使用权
static inline int gpio_direction_input(unsigned gpio) //将gpio设置为输入
static inline int gpio_direction_output(unsigned gpio, int value) //将gpio设置为输出,同时输出高低电平
static inline int gpio_get_value(unsigned gpio) //获取gpio引脚的数据
static inline void gpio_set_value(unsigned gpio, int value) //设置gpio引脚的数据
2、设备树节点
led_test2:stm32mp157_led_test2 {
compatible = "stm32mp157_led_test,old_gpios";
led_name = "led_dev";
//gpio = <&gpioz 5 GPIO_ACTIVE_HIGH>, <&gpioz 6 GPIO_ACTIVE_HIGH>, <&gpioz 7 GPIO_ACTIVE_HIGH>; //不可以这样写
gpios = <&gpioz 5 GPIO_ACTIVE_HIGH>, <&gpioz 6 GPIO_ACTIVE_HIGH>, <&gpioz 7 GPIO_ACTIVE_HIGH>;
};
使用 gpios,不能使用 gpio
3、使用方法
int gpioz_5;
int gpioz_6;
int gpioz_7;
int led_pdrv_probe(struct platform_device *pdev)
{
/...其他代码.../
gpioz_5 = of_get_gpio(np, 0);
gpioz_6 = of_get_gpio(np, 1);
gpioz_7 = of_get_gpio(np, 2);
gpio_request(gpioz_5, "gpioz_5");
gpio_request(gpioz_6, "gpioz_6");
gpio_request(gpioz_7, "gpioz_7");
gpio_direction_output(gpioz_5, 0);
gpio_direction_output(gpioz_6, 0);
gpio_direction_output(gpioz_7, 0);
/...其他代码.../
}
int led_pdrv_remove(struct platform_device *pdev)
{
/...其他代码.../
gpio_free(gpioz_5);
gpio_free(gpioz_6);
gpio_free(gpioz_7);
/...其他代码.../
}
//使用 platform_device 时用于匹配 pdev.name
const struct platform_device_id led_id_table[] = {
{"led_pdev", 0x12},
{"led_pdev1", 0x34},
};
//设备树 compatible 匹配
const struct of_device_id led_of_match_table[] = {
{.compatible = "stm32mp157_led_test,old_gpios",},
};
struct platform_driver led_pdrv = {
.probe = led_pdrv_probe,
.remove = led_pdrv_remove,
.driver = {
.name = "led_driver_override",
.of_match_table = led_of_match_table,
},
.id_table = led_id_table,
};
static int __init led_pdrv_init(void)
{
printk("---------[%s]--------------\n", __FUNCTION__);
return platform_driver_register(&led_pdrv);
}
static void __exit led_pdrv_exit(void)
{
printk("---------[%s]--------------\n", __FUNCTION__);
platform_driver_unregister(&led_pdrv);
}
module_init(led_pdrv_init);
module_exit(led_pdrv_exit);
MODULE_LICENSE("GPL");
使用 gpio_request 的意义在于,用于申请一个GPIO资源,确保在后续的操作中该资源不会被其他设备或驱动占用,起到引用计数+1的效果。
二、新版的gpio子系统
1、函数接口
struct gpio_desc *gpiod_get(struct device *dev,const char *con_id, enum gpiod_flags flags);//获取gpio引脚对象指针
struct gpio_desc *gpiod_get_index(struct device *dev,const char *con_id, int index, enum gpiod_flags flags);
static inline void gpiod_put(struct gpio_desc *desc) //释放gpio引脚对象
int gpiod_direction_input(struct gpio_desc *desc); //将gpio设置为输入
int gpiod_direction_output(struct gpio_desc *desc, int value); //将gpio设置为输出,同时输出高低电平
int gpiod_get_value(const struct gpio_desc *desc); //获取gpio引脚的数据
void gpiod_set_value(struct gpio_desc *desc, int value); //设置gpio引脚的数据
struct gpio_desc *devm_gpiod_get(struct device *dev, const char *con_id,enum gpiod_flags flags);//获取gpio引脚对象指针
struct gpio_desc *devm_gpiod_get_index(struct device *dev, const char *con_id, int index, enum gpiod_flags flags);
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc); //释放gpio引脚对象
devm_gpiod_get和 devm_gpiod_get_index 调用后,当设备被销毁或卸载时,内核会自动遍历并释放该设备所持有的所有资源。
如果想在设备被销毁或卸载时前释放资源,应调用 devm_gpiod_put
2、设备树节点
led_test3:stm32mp157_led_test3_name {
compatible = "stm32mp157_led_test,new_gpios";
led_name = "led_dev";
//gpios = <&gpioz 5 GPIO_ACTIVE_HIGH>, <&gpioz 6 GPIO_ACTIVE_HIGH>, <&gpioz 7 GPIO_ACTIVE_HIGH>;
//gpio = <&gpioz 5 GPIO_ACTIVE_HIGH>, <&gpioz 6 GPIO_ACTIVE_HIGH>, <&gpioz 7 GPIO_ACTIVE_HIGH>;
//led-gpio = <&gpioz 5 GPIO_ACTIVE_HIGH>, <&gpioz 6 GPIO_ACTIVE_HIGH>, <&gpioz 7 GPIO_ACTIVE_HIGH>;
led-gpios = <&gpioz 5 GPIO_ACTIVE_HIGH>, <&gpioz 6 GPIO_ACTIVE_HIGH>, <&gpioz 7 GPIO_ACTIVE_HIGH>;
};
可以使用 gpios,gpio,led-gpio,led-gpios
3、使用方法
struct gpio_desc gpioz[3];
int led_pdrv_probe(struct platform_device *pdev)
{
int i = 0;
/...其他代码.../
for (i = 0; i < ARRAY_SIZE(gpioz); ++i)
{
//gpioz[i] = devm_gpiod_get_index(&pdev->dev, NULL, i, GPIOD_OUT_LOW);
gpioz[i] = devm_gpiod_get_index(&pdev->dev, "led", i, GPIOD_OUT_LOW);
//gpioz[i] = gpiod_get_index(&pdev->dev, "led", i, GPIOD_OUT_LOW);
gpiod_direction_output(gpioz[i], 0);
}
/...其他代码.../
}
int led_pdrv_remove(struct platform_device *pdev)
{
/...其他代码.../
//devm_gpiod_put(&pdev->dev, led->gpioz[i]);//调用 devm_gpiod_get_index 会自动释放内存资源
//gpiod_put(led->gpioz[i]);
/...其他代码.../
}
//使用 platform_device 时用于匹配 pdev.name
const struct platform_device_id led_id_table[] = {
{"led_pdev", 0x12},
{"led_pdev1", 0x34},
};
//设备树 compatible 匹配
const struct of_device_id led_of_match_table[] = {
{.compatible = "stm32mp157_led_test,old_gpios",},
};
struct platform_driver led_pdrv = {
.probe = led_pdrv_probe,
.remove = led_pdrv_remove,
.driver = {
.name = "led_driver_override",
.of_match_table = led_of_match_table,
},
.id_table = led_id_table,
};
static int __init led_pdrv_init(void)
{
printk("---------[%s]--------------\n", __FUNCTION__);
return platform_driver_register(&led_pdrv);
}
static void __exit led_pdrv_exit(void)
{
printk("---------[%s]--------------\n", __FUNCTION__);
platform_driver_unregister(&led_pdrv);
}
module_init(led_pdrv_init);
module_exit(led_pdrv_exit);
MODULE_LICENSE("GPL");
当设备树描述为gpio/gpios时,使用 gpioz[i] = devm_gpiod_get_index(&pdev->dev, NULL, i, GPIOD_OUT_LOW);
调用 gpiod_get_index 后,需要使用 gpiod_put 释放资源。

5416

被折叠的 条评论
为什么被折叠?



