0073-BCM270x_DT-Add-pwr_led-and-the-required-input-trigge.patch 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. From 211b0053ad2b173e646e4db1b5dd2f51a2da4ed7 Mon Sep 17 00:00:00 2001
  2. From: Phil Elwell <phil@raspberrypi.org>
  3. Date: Fri, 6 Feb 2015 13:50:57 +0000
  4. Subject: [PATCH 073/381] BCM270x_DT: Add pwr_led, and the required "input"
  5. trigger
  6. The "input" trigger makes the associated GPIO an input. This is to support
  7. the Raspberry Pi PWR LED, which is driven by external hardware in normal use.
  8. N.B. pwr_led is not available on Model A or B boards.
  9. leds-gpio: Implement the brightness_get method
  10. The power LED uses some clever logic that means it is driven
  11. by a voltage measuring circuit when configured as input, otherwise
  12. it is driven by the GPIO output value. This patch wires up the
  13. brightness_get method for leds-gpio so that user-space can monitor
  14. the LED value via /sys/class/gpio/led1/brightness. Using the input
  15. trigger this returns an indication of the system power health,
  16. otherwise it is just whatever value the trigger has written most
  17. recently.
  18. See: https://github.com/raspberrypi/linux/issues/1064
  19. ---
  20. drivers/leds/leds-gpio.c | 18 +++++++++++-
  21. drivers/leds/trigger/Kconfig | 7 +++++
  22. drivers/leds/trigger/Makefile | 1 +
  23. drivers/leds/trigger/ledtrig-input.c | 54 ++++++++++++++++++++++++++++++++++++
  24. include/linux/leds.h | 3 ++
  25. 5 files changed, 82 insertions(+), 1 deletion(-)
  26. create mode 100644 drivers/leds/trigger/ledtrig-input.c
  27. --- a/drivers/leds/leds-gpio.c
  28. +++ b/drivers/leds/leds-gpio.c
  29. @@ -42,6 +42,13 @@ static void gpio_led_work(struct work_st
  30. led_dat->platform_gpio_blink_set(led_dat->gpiod,
  31. led_dat->new_level, NULL, NULL);
  32. led_dat->blinking = 0;
  33. + } else if (led_dat->cdev.flags & SET_GPIO_INPUT) {
  34. + gpiod_direction_input(led_dat->gpiod);
  35. + led_dat->cdev.flags &= ~SET_GPIO_INPUT;
  36. + }
  37. + else if (led_dat->cdev.flags & SET_GPIO_OUTPUT) {
  38. + gpiod_direction_output(led_dat->gpiod, led_dat->new_level);
  39. + led_dat->cdev.flags &= ~SET_GPIO_OUTPUT;
  40. } else
  41. gpiod_set_value_cansleep(led_dat->gpiod, led_dat->new_level);
  42. }
  43. @@ -62,7 +69,8 @@ static void gpio_led_set(struct led_clas
  44. * seem to have a reliable way to know if we're already in one; so
  45. * let's just assume the worst.
  46. */
  47. - if (led_dat->can_sleep) {
  48. + if (led_dat->can_sleep ||
  49. + (led_dat->cdev.flags & (SET_GPIO_INPUT | SET_GPIO_OUTPUT) )) {
  50. led_dat->new_level = level;
  51. schedule_work(&led_dat->work);
  52. } else {
  53. @@ -75,6 +83,13 @@ static void gpio_led_set(struct led_clas
  54. }
  55. }
  56. +static enum led_brightness gpio_led_get(struct led_classdev *led_cdev)
  57. +{
  58. + struct gpio_led_data *led_dat =
  59. + container_of(led_cdev, struct gpio_led_data, cdev);
  60. + return gpiod_get_value_cansleep(led_dat->gpiod) ? LED_FULL : LED_OFF;
  61. +}
  62. +
  63. static int gpio_blink_set(struct led_classdev *led_cdev,
  64. unsigned long *delay_on, unsigned long *delay_off)
  65. {
  66. @@ -131,6 +146,7 @@ static int create_gpio_led(const struct
  67. led_dat->cdev.blink_set = gpio_blink_set;
  68. }
  69. led_dat->cdev.brightness_set = gpio_led_set;
  70. + led_dat->cdev.brightness_get = gpio_led_get;
  71. if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP)
  72. state = !!gpiod_get_value_cansleep(led_dat->gpiod);
  73. else
  74. --- a/drivers/leds/trigger/Kconfig
  75. +++ b/drivers/leds/trigger/Kconfig
  76. @@ -126,4 +126,11 @@ config LEDS_TRIGGER_USBDEV
  77. This allows LEDs to be controlled by the presence/activity of
  78. an USB device. If unsure, say N.
  79. +config LEDS_TRIGGER_INPUT
  80. + tristate "LED Input Trigger"
  81. + depends on LEDS_TRIGGERS
  82. + help
  83. + This allows the GPIOs assigned to be LEDs to be initialised to inputs.
  84. + If unsure, say Y.
  85. +
  86. endif # LEDS_TRIGGERS
  87. --- a/drivers/leds/trigger/Makefile
  88. +++ b/drivers/leds/trigger/Makefile
  89. @@ -8,3 +8,4 @@ obj-$(CONFIG_LEDS_TRIGGER_CPU) += ledtr
  90. obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
  91. obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o
  92. obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o
  93. +obj-$(CONFIG_LEDS_TRIGGER_INPUT) += ledtrig-input.o
  94. --- /dev/null
  95. +++ b/drivers/leds/trigger/ledtrig-input.c
  96. @@ -0,0 +1,54 @@
  97. +/*
  98. + * Set LED GPIO to Input "Trigger"
  99. + *
  100. + * Copyright 2015 Phil Elwell <phil@raspberrypi.org>
  101. + *
  102. + * Based on Nick Forbes's ledtrig-default-on.c.
  103. + *
  104. + * This program is free software; you can redistribute it and/or modify
  105. + * it under the terms of the GNU General Public License version 2 as
  106. + * published by the Free Software Foundation.
  107. + *
  108. + */
  109. +
  110. +#include <linux/module.h>
  111. +#include <linux/kernel.h>
  112. +#include <linux/init.h>
  113. +#include <linux/leds.h>
  114. +#include <linux/gpio.h>
  115. +#include "../leds.h"
  116. +
  117. +static void input_trig_activate(struct led_classdev *led_cdev)
  118. +{
  119. + led_cdev->flags |= SET_GPIO_INPUT;
  120. + led_set_brightness_async(led_cdev, 0);
  121. +}
  122. +
  123. +static void input_trig_deactivate(struct led_classdev *led_cdev)
  124. +{
  125. + led_cdev->flags |= SET_GPIO_OUTPUT;
  126. + led_set_brightness_async(led_cdev, 0);
  127. +}
  128. +
  129. +static struct led_trigger input_led_trigger = {
  130. + .name = "input",
  131. + .activate = input_trig_activate,
  132. + .deactivate = input_trig_deactivate,
  133. +};
  134. +
  135. +static int __init input_trig_init(void)
  136. +{
  137. + return led_trigger_register(&input_led_trigger);
  138. +}
  139. +
  140. +static void __exit input_trig_exit(void)
  141. +{
  142. + led_trigger_unregister(&input_led_trigger);
  143. +}
  144. +
  145. +module_init(input_trig_init);
  146. +module_exit(input_trig_exit);
  147. +
  148. +MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.org>");
  149. +MODULE_DESCRIPTION("Set LED GPIO to Input \"trigger\"");
  150. +MODULE_LICENSE("GPL");
  151. --- a/include/linux/leds.h
  152. +++ b/include/linux/leds.h
  153. @@ -48,6 +48,9 @@ struct led_classdev {
  154. #define SET_BRIGHTNESS_ASYNC (1 << 21)
  155. #define SET_BRIGHTNESS_SYNC (1 << 22)
  156. #define LED_DEV_CAP_FLASH (1 << 23)
  157. + /* Additions for Raspberry Pi PWR LED */
  158. +#define SET_GPIO_INPUT (1 << 30)
  159. +#define SET_GPIO_OUTPUT (1 << 31)
  160. /* Set LED brightness level */
  161. /* Must not sleep, use a workqueue if needed */