leds-gpio.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*
  2. * LEDs driver for GPIOs
  3. *
  4. * Copyright (C) 2007 8D Technologies inc.
  5. * Raphael Assenat <raph@8d.com>
  6. *
  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.
  10. *
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/init.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/leds.h>
  16. #include <asm/gpio.h>
  17. struct gpio_led_data {
  18. struct led_classdev cdev;
  19. unsigned gpio;
  20. u8 active_low;
  21. };
  22. static void gpio_led_set(struct led_classdev *led_cdev,
  23. enum led_brightness value)
  24. {
  25. struct gpio_led_data *led_dat =
  26. container_of(led_cdev, struct gpio_led_data, cdev);
  27. int level;
  28. if (value == LED_OFF)
  29. level = 0;
  30. else
  31. level = 1;
  32. if (led_dat->active_low)
  33. level = !level;
  34. gpio_set_value(led_dat->gpio, level);
  35. }
  36. static int __init gpio_led_probe(struct platform_device *pdev)
  37. {
  38. struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
  39. struct gpio_led *cur_led;
  40. struct gpio_led_data *leds_data, *led_dat;
  41. int i, ret = 0;
  42. if (!pdata)
  43. return -EBUSY;
  44. leds_data = kzalloc(sizeof(struct gpio_led_data) * pdata->num_leds,
  45. GFP_KERNEL);
  46. if (!leds_data)
  47. return -ENOMEM;
  48. for (i = 0; i < pdata->num_leds; i++) {
  49. cur_led = &pdata->leds[i];
  50. led_dat = &leds_data[i];
  51. led_dat->cdev.name = cur_led->name;
  52. led_dat->cdev.default_trigger = cur_led->default_trigger;
  53. led_dat->gpio = cur_led->gpio;
  54. led_dat->active_low = cur_led->active_low;
  55. led_dat->cdev.brightness_set = gpio_led_set;
  56. led_dat->cdev.brightness = cur_led->active_low ? LED_FULL : LED_OFF;
  57. ret = gpio_request(led_dat->gpio, led_dat->cdev.name);
  58. if (ret < 0)
  59. goto err;
  60. gpio_direction_output(led_dat->gpio, led_dat->active_low);
  61. ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
  62. if (ret < 0) {
  63. gpio_free(led_dat->gpio);
  64. goto err;
  65. }
  66. }
  67. platform_set_drvdata(pdev, leds_data);
  68. return 0;
  69. err:
  70. if (i > 0) {
  71. for (i = i - 1; i >= 0; i--) {
  72. led_classdev_unregister(&leds_data[i].cdev);
  73. gpio_free(leds_data[i].gpio);
  74. }
  75. }
  76. kfree(leds_data);
  77. return ret;
  78. }
  79. static int __exit gpio_led_remove(struct platform_device *pdev)
  80. {
  81. int i;
  82. struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
  83. struct gpio_led_data *leds_data;
  84. leds_data = platform_get_drvdata(pdev);
  85. for (i = 0; i < pdata->num_leds; i++) {
  86. led_classdev_unregister(&leds_data[i].cdev);
  87. gpio_free(leds_data[i].gpio);
  88. }
  89. kfree(leds_data);
  90. return 0;
  91. }
  92. #ifdef CONFIG_PM
  93. static int gpio_led_suspend(struct platform_device *pdev, pm_message_t state)
  94. {
  95. struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
  96. struct gpio_led_data *leds_data;
  97. int i;
  98. leds_data = platform_get_drvdata(pdev);
  99. for (i = 0; i < pdata->num_leds; i++)
  100. led_classdev_suspend(&leds_data[i].cdev);
  101. return 0;
  102. }
  103. static int gpio_led_resume(struct platform_device *pdev)
  104. {
  105. struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
  106. struct gpio_led_data *leds_data;
  107. int i;
  108. leds_data = platform_get_drvdata(pdev);
  109. for (i = 0; i < pdata->num_leds; i++)
  110. led_classdev_resume(&leds_data[i].cdev);
  111. return 0;
  112. }
  113. #else
  114. #define gpio_led_suspend NULL
  115. #define gpio_led_resume NULL
  116. #endif
  117. static struct platform_driver gpio_led_driver = {
  118. .remove = __exit_p(gpio_led_remove),
  119. .suspend = gpio_led_suspend,
  120. .resume = gpio_led_resume,
  121. .driver = {
  122. .name = "leds-gpio",
  123. .owner = THIS_MODULE,
  124. },
  125. };
  126. static int __init gpio_led_init(void)
  127. {
  128. return platform_driver_probe(&gpio_led_driver, gpio_led_probe);
  129. }
  130. static void __exit gpio_led_exit(void)
  131. {
  132. platform_driver_unregister(&gpio_led_driver);
  133. }
  134. module_init(gpio_led_init);
  135. module_exit(gpio_led_exit);
  136. MODULE_AUTHOR("Raphael Assenat <raph@8d.com>");
  137. MODULE_DESCRIPTION("GPIO LED driver");
  138. MODULE_LICENSE("GPL");