2  * LEDs driver for GPIOs
 
   4  * Copyright (C) 2007 8D Technologies inc.
 
   5  * Raphael Assenat <raph@8d.com>
 
   7  * This program is free software; you can redistribute it and/or modify
 
   8  * it under the terms of the GNU General Public License version 2 as
 
   9  * published by the Free Software Foundation.
 
  12 #include <linux/kernel.h>
 
  13 #include <linux/init.h>
 
  14 #include <linux/platform_device.h>
 
  15 #include <linux/leds.h>
 
  16 #include <linux/workqueue.h>
 
  20 struct gpio_led_data {
 
  21         struct led_classdev cdev;
 
  23         struct work_struct work;
 
  27         int (*platform_gpio_blink_set)(unsigned gpio,
 
  28                         unsigned long *delay_on, unsigned long *delay_off);
 
  31 static void gpio_led_work(struct work_struct *work)
 
  33         struct gpio_led_data    *led_dat =
 
  34                 container_of(work, struct gpio_led_data, work);
 
  36         gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level);
 
  39 static void gpio_led_set(struct led_classdev *led_cdev,
 
  40         enum led_brightness value)
 
  42         struct gpio_led_data *led_dat =
 
  43                 container_of(led_cdev, struct gpio_led_data, cdev);
 
  51         if (led_dat->active_low)
 
  54         /* Setting GPIOs with I2C/etc requires a task context, and we don't
 
  55          * seem to have a reliable way to know if we're already in one; so
 
  56          * let's just assume the worst.
 
  58         if (led_dat->can_sleep) {
 
  59                 led_dat->new_level = level;
 
  60                 schedule_work(&led_dat->work);
 
  62                 gpio_set_value(led_dat->gpio, level);
 
  65 static int gpio_blink_set(struct led_classdev *led_cdev,
 
  66         unsigned long *delay_on, unsigned long *delay_off)
 
  68         struct gpio_led_data *led_dat =
 
  69                 container_of(led_cdev, struct gpio_led_data, cdev);
 
  71         return led_dat->platform_gpio_blink_set(led_dat->gpio, delay_on, delay_off);
 
  74 static int gpio_led_probe(struct platform_device *pdev)
 
  76         struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
 
  77         struct gpio_led *cur_led;
 
  78         struct gpio_led_data *leds_data, *led_dat;
 
  84         leds_data = kzalloc(sizeof(struct gpio_led_data) * pdata->num_leds,
 
  89         for (i = 0; i < pdata->num_leds; i++) {
 
  90                 cur_led = &pdata->leds[i];
 
  91                 led_dat = &leds_data[i];
 
  93                 ret = gpio_request(cur_led->gpio, cur_led->name);
 
  97                 led_dat->cdev.name = cur_led->name;
 
  98                 led_dat->cdev.default_trigger = cur_led->default_trigger;
 
  99                 led_dat->gpio = cur_led->gpio;
 
 100                 led_dat->can_sleep = gpio_cansleep(cur_led->gpio);
 
 101                 led_dat->active_low = cur_led->active_low;
 
 102                 if (pdata->gpio_blink_set) {
 
 103                         led_dat->platform_gpio_blink_set = pdata->gpio_blink_set;
 
 104                         led_dat->cdev.blink_set = gpio_blink_set;
 
 106                 led_dat->cdev.brightness_set = gpio_led_set;
 
 107                 led_dat->cdev.brightness = LED_OFF;
 
 109                 gpio_direction_output(led_dat->gpio, led_dat->active_low);
 
 111                 INIT_WORK(&led_dat->work, gpio_led_work);
 
 113                 ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
 
 115                         gpio_free(led_dat->gpio);
 
 120         platform_set_drvdata(pdev, leds_data);
 
 126                 for (i = i - 1; i >= 0; i--) {
 
 127                         led_classdev_unregister(&leds_data[i].cdev);
 
 128                         cancel_work_sync(&leds_data[i].work);
 
 129                         gpio_free(leds_data[i].gpio);
 
 138 static int __devexit gpio_led_remove(struct platform_device *pdev)
 
 141         struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
 
 142         struct gpio_led_data *leds_data;
 
 144         leds_data = platform_get_drvdata(pdev);
 
 146         for (i = 0; i < pdata->num_leds; i++) {
 
 147                 led_classdev_unregister(&leds_data[i].cdev);
 
 148                 cancel_work_sync(&leds_data[i].work);
 
 149                 gpio_free(leds_data[i].gpio);
 
 158 static int gpio_led_suspend(struct platform_device *pdev, pm_message_t state)
 
 160         struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
 
 161         struct gpio_led_data *leds_data;
 
 164         leds_data = platform_get_drvdata(pdev);
 
 166         for (i = 0; i < pdata->num_leds; i++)
 
 167                 led_classdev_suspend(&leds_data[i].cdev);
 
 172 static int gpio_led_resume(struct platform_device *pdev)
 
 174         struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
 
 175         struct gpio_led_data *leds_data;
 
 178         leds_data = platform_get_drvdata(pdev);
 
 180         for (i = 0; i < pdata->num_leds; i++)
 
 181                 led_classdev_resume(&leds_data[i].cdev);
 
 186 #define gpio_led_suspend NULL
 
 187 #define gpio_led_resume NULL
 
 190 static struct platform_driver gpio_led_driver = {
 
 191         .probe          = gpio_led_probe,
 
 192         .remove         = __devexit_p(gpio_led_remove),
 
 193         .suspend        = gpio_led_suspend,
 
 194         .resume         = gpio_led_resume,
 
 197                 .owner  = THIS_MODULE,
 
 201 static int __init gpio_led_init(void)
 
 203         return platform_driver_register(&gpio_led_driver);
 
 206 static void __exit gpio_led_exit(void)
 
 208         platform_driver_unregister(&gpio_led_driver);
 
 211 module_init(gpio_led_init);
 
 212 module_exit(gpio_led_exit);
 
 214 MODULE_AUTHOR("Raphael Assenat <raph@8d.com>");
 
 215 MODULE_DESCRIPTION("GPIO LED driver");
 
 216 MODULE_LICENSE("GPL");
 
 217 MODULE_ALIAS("platform:leds-gpio");