diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 93f5b1b60fdec835eec36fd1d7364450e1b0d42b..d0d05d663eea4d3f0ca6b062c0406caa85062281 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -46,8 +46,15 @@ static void gpio_led_set(struct led_classdev *led_cdev, led_dat->platform_gpio_blink_set(led_dat->gpiod, level, NULL, NULL); led_dat->blinking = 0; + } else if (led_dat->cdev.flags & SET_GPIO_INPUT) { + gpiod_direction_input(led_dat->gpiod); + led_dat->cdev.flags &= ~SET_GPIO_INPUT; + } else if (led_dat->cdev.flags & SET_GPIO_OUTPUT) { + gpiod_direction_output(led_dat->gpiod, level); + led_dat->cdev.flags &= ~SET_GPIO_OUTPUT; } else { - if (led_dat->can_sleep) + if (led_dat->can_sleep || + (led_dat->cdev.flags & (SET_GPIO_INPUT | SET_GPIO_OUTPUT) )) gpiod_set_value_cansleep(led_dat->gpiod, level); else gpiod_set_value(led_dat->gpiod, level); @@ -61,6 +68,13 @@ static int gpio_led_set_blocking(struct led_classdev *led_cdev, return 0; } +static enum led_brightness gpio_led_get(struct led_classdev *led_cdev) +{ + struct gpio_led_data *led_dat = + container_of(led_cdev, struct gpio_led_data, cdev); + return gpiod_get_value_cansleep(led_dat->gpiod) ? LED_FULL : LED_OFF; +} + static int gpio_blink_set(struct led_classdev *led_cdev, unsigned long *delay_on, unsigned long *delay_off) { @@ -89,6 +103,7 @@ static int create_gpio_led(const struct gpio_led *template, led_dat->platform_gpio_blink_set = blink_set; led_dat->cdev.blink_set = gpio_blink_set; } + led_dat->cdev.brightness_get = gpio_led_get; if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) { state = gpiod_get_value_cansleep(led_dat->gpiod); if (state < 0) diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index ce9429ca6ddea792f6195f6e6f7510eba13129db..03e3f1c267dd73c37fe7fad9028a3d5940e3aad3 100644 --- a/drivers/leds/trigger/Kconfig +++ b/drivers/leds/trigger/Kconfig @@ -114,6 +114,13 @@ config LEDS_TRIGGER_CAMERA This enables direct flash/torch on/off by the driver, kernel space. If unsure, say Y. +config LEDS_TRIGGER_INPUT + tristate "LED Input Trigger" + depends on LEDS_TRIGGERS + help + This allows the GPIOs assigned to be LEDs to be initialised to inputs. + If unsure, say Y. + config LEDS_TRIGGER_PANIC bool "LED Panic Trigger" help diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile index 733a83e2a7183e8e1ef6af04fcea1ed3a1bd2526..f2d085c6723334f7f1e07df618976355788a87c1 100644 --- a/drivers/leds/trigger/Makefile +++ b/drivers/leds/trigger/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_LEDS_TRIGGER_ACTIVITY) += ledtrig-activity.o obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o +obj-$(CONFIG_LEDS_TRIGGER_INPUT) += ledtrig-input.o obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o obj-$(CONFIG_LEDS_TRIGGER_PATTERN) += ledtrig-pattern.o diff --git a/drivers/leds/trigger/ledtrig-input.c b/drivers/leds/trigger/ledtrig-input.c new file mode 100644 index 0000000000000000000000000000000000000000..8a974a3556564959d26aa12035a7beabb83ea4b7 --- /dev/null +++ b/drivers/leds/trigger/ledtrig-input.c @@ -0,0 +1,55 @@ +/* + * Set LED GPIO to Input "Trigger" + * + * Copyright 2015 Phil Elwell + * + * Based on Nick Forbes's ledtrig-default-on.c. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include "../leds.h" + +static int input_trig_activate(struct led_classdev *led_cdev) +{ + led_cdev->flags |= SET_GPIO_INPUT; + led_set_brightness(led_cdev, 0); + return 0; +} + +static void input_trig_deactivate(struct led_classdev *led_cdev) +{ + led_cdev->flags |= SET_GPIO_OUTPUT; + led_set_brightness(led_cdev, 0); +} + +static struct led_trigger input_led_trigger = { + .name = "input", + .activate = input_trig_activate, + .deactivate = input_trig_deactivate, +}; + +static int __init input_trig_init(void) +{ + return led_trigger_register(&input_led_trigger); +} + +static void __exit input_trig_exit(void) +{ + led_trigger_unregister(&input_led_trigger); +} + +module_init(input_trig_init); +module_exit(input_trig_exit); + +MODULE_AUTHOR("Phil Elwell "); +MODULE_DESCRIPTION("Set LED GPIO to Input \"trigger\""); +MODULE_LICENSE("GPL"); diff --git a/include/linux/leds.h b/include/linux/leds.h index 6a8d6409c993edd13ebd2e15e109187973f3d005..aefab0783075cf4e4493d6f6a7bf12a15d4e3a40 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -79,6 +79,9 @@ struct led_classdev { #define LED_BRIGHT_HW_CHANGED BIT(21) #define LED_RETAIN_AT_SHUTDOWN BIT(22) #define LED_INIT_DEFAULT_TRIGGER BIT(23) + /* Additions for Raspberry Pi PWR LED */ +#define SET_GPIO_INPUT BIT(30) +#define SET_GPIO_OUTPUT BIT(31) /* set_brightness_work / blink_timer flags, atomic, private. */ unsigned long work_flags;