950-0079-leds-Add-the-input-trigger-for-pwr_led.patch 5.6 KB

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