linux内核的gpiolib详解
#include <linux/init.h> // __init __exit #include <linux/module.h> // module_init module_exit #include <mach/regs-gpio.h> #include <mach/gpio-bank.h> #include <asm/io.h> //writel #include <mach/gpio.h> #include <linux/leds.h> #include <asm/string.h> #define X210_LED_OFF 1U #define X210_LED_ON 0U struct led_classdev cdev1; struct led_classdev cdev2; struct led_classdev cdev3; void s5pv210_led1_set(struct led_classdev *led_cdev,enum led_brightness brightness); void s5pv210_led2_set(struct led_classdev *led_cdev,enum led_brightness brightness); void s5pv210_led3_set(struct led_classdev *led_cdev,enum led_brightness brightness); static struct gpio x210_led_gpio[] = { { S5PV210_GPJ0(3), GPIOF_OUT_INIT_HIGH, "LED1" }, /* default to OFF */ { S5PV210_GPJ0(4), GPIOF_OUT_INIT_HIGH, "LED2" }, /* default to OFF */ { S5PV210_GPJ0(5), GPIOF_OUT_INIT_HIGH, "LED3" } /* default to OFF */ }; void s5pv210_led1_set(struct led_classdev *led_cdev,enum led_brightness brightness) { printk(KERN_INFO "s5pv210_led1_set successful %d\n",brightness); if(brightness == LED_OFF) { gpio_set_value(x210_led_gpio[0].gpio,X210_LED_OFF); } else { gpio_set_value(x210_led_gpio[0].gpio,X210_LED_ON); } } void s5pv210_led2_set(struct led_classdev *led_cdev,enum led_brightness brightness) { printk(KERN_INFO "s5pv210_led2_set successful %d\n",brightness); if(brightness == LED_OFF) { gpio_set_value(x210_led_gpio[1].gpio,X210_LED_OFF); } else { gpio_set_value(x210_led_gpio[1].gpio,X210_LED_ON); } } void s5pv210_led3_set(struct led_classdev *led_cdev,enum led_brightness brightness) { printk(KERN_INFO "s5pv210_led3_set successful %d\n",brightness); if(brightness == LED_OFF) { gpio_set_value(x210_led_gpio[2].gpio,X210_LED_OFF); } else { gpio_set_value(x210_led_gpio[2].gpio,X210_LED_ON); } } static int __init s5pv210_led_init(void) { int ret = -1; printk(KERN_INFO "s5pv210_led_init successful \n"); cdev1.brightness_set = s5pv210_led1_set; cdev1.name = "led1"; ret = led_classdev_register(NULL, &cdev1); if (ret < 0) { printk(KERN_WARNING "led_classdev_register fail \n"); goto reg_err1; } cdev2.brightness_set = s5pv210_led2_set; cdev2.name = "led2"; ret = led_classdev_register(NULL, &cdev2); if (ret < 0) { printk(KERN_WARNING "led_classdev_register fail \n"); goto reg_err2; } cdev3.brightness_set = s5pv210_led3_set; cdev3.name = "led3"; ret = led_classdev_register(NULL, &cdev3); if (ret < 0) { printk(KERN_WARNING "led_classdev_register fail \n"); goto reg_err3; } ret = gpio_request_array(x210_led_gpio, ARRAY_SIZE(x210_led_gpio)); if (ret) { goto gpio_err; } return 0; gpio_err: led_classdev_unregister(&cdev3); reg_err3: led_classdev_unregister(&cdev2); reg_err2: led_classdev_unregister(&cdev1); reg_err1: return ret; } static void __exit s5pv210_led_exit(void) { printk(KERN_INFO "s5pv210_led_exit successful \n"); gpio_free_array(x210_led_gpio, ARRAY_SIZE(x210_led_gpio)); led_classdev_unregister(&cdev1); led_classdev_unregister(&cdev2); led_classdev_unregister(&cdev3); } module_init(s5pv210_led_init); module_exit(s5pv210_led_exit); // MODULE_xxx这种宏作用是用来添加模块描述信息 MODULE_LICENSE("GPL"); // 描述模块的许可证 MODULE_AUTHOR("musk"); // 描述模块的作者 MODULE_DESCRIPTION("x210 LED driver"); // 描述模块的介绍信息 MODULE_ALIAS("led_driver"); // 描述模块的别名信息
一. 什么是gpiolib
1.1. linux中从2.6.35以后就开始有gpiolib库了,gpiolib的作用是对所有的gpio实行统一管理,因为驱动在工作的时候,会出现好几个驱动共同使用同一个gpio的情况;这会造成混乱。所以内核提供了一些方法来管理gpio资源;
二. gpiolib在内核中实现流程
2.1. gpiolib初始化哪