下面是两个LED灯的驱动程序 一个用platform_driver 另一个用file_operations
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/platform_device.h>
- #include <linux/leds.h>
- #include <mach/hardware.h>
- #include <mach/regs-gpio.h>
- #include <mach/leds-gpio.h>
- /* our context */
- struct s3c24xx_gpio_led {
- struct led_classdev cdev;
- struct s3c24xx_led_platdata *pdata;
- };
- static inline struct s3c24xx_gpio_led *pdev_to_gpio(struct platform_device *dev)
- {
- return platform_get_drvdata(dev);
- }
- static inline struct s3c24xx_gpio_led *to_gpio(struct led_classdev *led_cdev)
- {
- return container_of(led_cdev, struct s3c24xx_gpio_led, cdev);
- }
- static void s3c24xx_led_set(struct led_classdev *led_cdev,
- enum led_brightness value)
- {
- struct s3c24xx_gpio_led *led = to_gpio(led_cdev);
- struct s3c24xx_led_platdata *pd = led->pdata;
- /* there will be a short delay between setting the output and
- * going from output to input when using tristate. */
- s3c2410_gpio_setpin(pd->gpio, (value ? 1 : 0) ^
- (pd->flags & S3C24XX_LEDF_ACTLOW));
- if (pd->flags & S3C24XX_LEDF_TRISTATE)
- s3c2410_gpio_cfgpin(pd->gpio,
- value ? S3C2410_GPIO_OUTPUT : S3C2410_GPIO_INPUT);
- }
- static int s3c24xx_led_remove(struct platform_device *dev)
- {
- struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
- led_classdev_unregister(&led->cdev);
- kfree(led);
- return 0;
- }
- static int s3c24xx_led_probe(struct platform_device *dev)
- {
- struct s3c24xx_led_platdata *pdata = dev->dev.platform_data;
- struct s3c24xx_gpio_led *led;
- int ret;
- led = kzalloc(sizeof(struct s3c24xx_gpio_led), GFP_KERNEL);
- if (led == NULL) {
- dev_err(&dev->dev, "No memory for device\n");
- return -ENOMEM;
- }
- platform_set_drvdata(dev, led);
- led->cdev.brightness_set = s3c24xx_led_set;
- led->cdev.default_trigger = pdata->def_trigger;
- led->cdev.name = pdata->name;
- led->pdata = pdata;
- /* no point in having a pull-up if we are always driving */
- if (pdata->flags & S3C24XX_LEDF_TRISTATE) {
- s3c2410_gpio_setpin(pdata->gpio, 0);
- s3c2410_gpio_cfgpin(pdata->gpio, S3C2410_GPIO_INPUT);
- } else {
- s3c2410_gpio_pullup(pdata->gpio, 0);
- s3c2410_gpio_setpin(pdata->gpio, 0);
- s3c2410_gpio_cfgpin(pdata->gpio, S3C2410_GPIO_OUTPUT);
- }
- /* register our new led device */
- ret = led_classdev_register(&dev->dev, &led->cdev);
- if (ret < 0) {
- dev_err(&dev->dev, "led_classdev_register failed\n");
- goto exit_err1;
- }
- return 0;
- exit_err1:
- kfree(led);
- return ret;
- }
- #ifdef CONFIG_PM
- static int s3c24xx_led_suspend(struct platform_device *dev, pm_message_t state)
- {
- struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
- led_classdev_suspend(&led->cdev);
- return 0;
- }
- static int s3c24xx_led_resume(struct platform_device *dev)
- {
- struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
- led_classdev_resume(&led->cdev);
- return 0;
- }
- #else
- #define s3c24xx_led_suspend NULL
- #define s3c24xx_led_resume NULL
- #endif
- static struct platform_driver s3c24xx_led_driver = {
- .probe = s3c24xx_led_probe,
- .remove = s3c24xx_led_remove,
- .suspend = s3c24xx_led_suspend,
- .resume = s3c24xx_led_resume,
- .driver = {
- .name = "s3c24xx_led",
- .owner = THIS_MODULE,
- },
- };
- static int __init s3c24xx_led_init(void)
- {
- return platform_driver_register(&s3c24xx_led_driver);
- }
- static void __exit s3c24xx_led_exit(void)
- {
- platform_driver_unregister(&s3c24xx_led_driver);
- }
- module_init(s3c24xx_led_init);
- module_exit(s3c24xx_led_exit);
- MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
- MODULE_DESCRIPTION("S3C24XX LED driver");
- MODULE_LICENSE("GPL");
- MODULE_ALIAS("platform:s3c24xx_led");
- 另一个如下:
- #include <asm/uaccess.h>
- #include <asm/atomic.h>
- #include <asm/unistd.h>
- #define DEVICE_NAME "leds"
- static unsigned long led_table [] = {
- S3C2410_GPB5,
- S3C2410_GPB6,
- S3C2410_GPB7,
- S3C2410_GPB8,
- };
- static unsigned int led_cfg_table [] = {
- S3C2410_GPB5_OUTP,
- S3C2410_GPB6_OUTP,
- S3C2410_GPB7_OUTP,
- S3C2410_GPB8_OUTP,
- };
- static int sbc2440_leds_ioctl(
- struct inode *inode,
- struct file *file,
- unsigned int cmd,
- unsigned long arg)
- {
- switch(cmd) {
- case 0:
- case 1:
- if (arg > 4) {
- return -EINVAL;
- }
- s3c2410_gpio_setpin(led_table[arg], !cmd);
- return 0;
- default:
- return -EINVAL;
- }
- }
- static struct file_operations dev_fops = {
- .owner = THIS_MODULE,
- .ioctl = sbc2440_leds_ioctl,
- };
- static struct miscdevice misc = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = DEVICE_NAME,
- .fops = &dev_fops,
- };
- static int __init dev_init(void)
- {
- int ret;
- int i;
- for (i = 0; i < 4; i++) {
- s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
- s3c2410_gpio_setpin(led_table[i], 0);
- }
- ret = misc_register(&misc);
- printk (DEVICE_NAME"\tinitialized\n");
- return ret;
- }
- static void __exit dev_exit(void)
- {
- misc_deregister(&misc);
- }
- module_init(dev_init);
- module_exit(dev_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("FriendlyARM Inc.");
原文地址 http://blog.csdn.net/sdustliyang/article/details/6668929
后记:仔细看两种驱动结构的区别,这里有一个问题我想问s3c24xx_led_set 在platform driver驱动中是如何被上层调用的?file 形式的驱动很明显,但是platform的驱动太蛋疼了。