brintos

brintos / linux-shallow public Read only

0
0
Text · 3.5 KiB · 7f6a235 Raw
142 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * ledtrig-gio.c - LED Trigger Based on GPIO events4 *5 * Copyright 2009 Felipe Balbi <me@felipebalbi.com>6 * Copyright 2023 Linus Walleij <linus.walleij@linaro.org>7 */8 9#include <linux/module.h>10#include <linux/kernel.h>11#include <linux/init.h>12#include <linux/gpio/consumer.h>13#include <linux/interrupt.h>14#include <linux/leds.h>15#include <linux/slab.h>16#include "../leds.h"17 18struct gpio_trig_data {19	struct led_classdev *led;20	unsigned desired_brightness;	/* desired brightness when led is on */21	struct gpio_desc *gpiod;	/* gpio that triggers the led */22};23 24static irqreturn_t gpio_trig_irq(int irq, void *_led)25{26	struct led_classdev *led = _led;27	struct gpio_trig_data *gpio_data = led_get_trigger_data(led);28	int tmp;29 30	tmp = gpiod_get_value_cansleep(gpio_data->gpiod);31	if (tmp) {32		if (gpio_data->desired_brightness)33			led_set_brightness_nosleep(gpio_data->led,34					   gpio_data->desired_brightness);35		else36			led_set_brightness_nosleep(gpio_data->led, LED_FULL);37	} else {38		led_set_brightness_nosleep(gpio_data->led, LED_OFF);39	}40 41	return IRQ_HANDLED;42}43 44static ssize_t desired_brightness_show(struct device *dev,45		struct device_attribute *attr, char *buf)46{47	struct gpio_trig_data *gpio_data = led_trigger_get_drvdata(dev);48 49	return sysfs_emit(buf, "%u\n", gpio_data->desired_brightness);50}51 52static ssize_t desired_brightness_store(struct device *dev,53		struct device_attribute *attr, const char *buf, size_t n)54{55	struct gpio_trig_data *gpio_data = led_trigger_get_drvdata(dev);56	u8 desired_brightness;57	int ret;58 59	ret = kstrtou8(buf, 10, &desired_brightness);60	if (ret)61		return ret;62 63	gpio_data->desired_brightness = desired_brightness;64 65	return n;66}67static DEVICE_ATTR_RW(desired_brightness);68 69static struct attribute *gpio_trig_attrs[] = {70	&dev_attr_desired_brightness.attr,71	NULL72};73ATTRIBUTE_GROUPS(gpio_trig);74 75static int gpio_trig_activate(struct led_classdev *led)76{77	struct gpio_trig_data *gpio_data;78	struct device *dev = led->dev;79	int ret;80 81	gpio_data = kzalloc(sizeof(*gpio_data), GFP_KERNEL);82	if (!gpio_data)83		return -ENOMEM;84 85	/*86	 * The generic property "trigger-sources" is followed,87	 * and we hope that this is a GPIO.88	 */89	gpio_data->gpiod = gpiod_get_optional(dev, "trigger-sources", GPIOD_IN);90	if (IS_ERR(gpio_data->gpiod)) {91		ret = PTR_ERR(gpio_data->gpiod);92		kfree(gpio_data);93		return ret;94	}95	if (!gpio_data->gpiod) {96		dev_err(dev, "no valid GPIO for the trigger\n");97		kfree(gpio_data);98		return -EINVAL;99	}100 101	gpiod_set_consumer_name(gpio_data->gpiod, "led-trigger");102 103	gpio_data->led = led;104	led_set_trigger_data(led, gpio_data);105 106	ret = request_threaded_irq(gpiod_to_irq(gpio_data->gpiod), NULL, gpio_trig_irq,107			IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_RISING108			| IRQF_TRIGGER_FALLING, "ledtrig-gpio", led);109	if (ret) {110		dev_err(dev, "request_irq failed with error %d\n", ret);111		gpiod_put(gpio_data->gpiod);112		kfree(gpio_data);113		return ret;114	}115 116	/* Finally update the LED to initial status */117	gpio_trig_irq(0, led);118 119	return 0;120}121 122static void gpio_trig_deactivate(struct led_classdev *led)123{124	struct gpio_trig_data *gpio_data = led_get_trigger_data(led);125 126	free_irq(gpiod_to_irq(gpio_data->gpiod), led);127	gpiod_put(gpio_data->gpiod);128	kfree(gpio_data);129}130 131static struct led_trigger gpio_led_trigger = {132	.name		= "gpio",133	.activate	= gpio_trig_activate,134	.deactivate	= gpio_trig_deactivate,135	.groups		= gpio_trig_groups,136};137module_led_trigger(gpio_led_trigger);138 139MODULE_AUTHOR("Felipe Balbi <me@felipebalbi.com>");140MODULE_DESCRIPTION("GPIO LED trigger");141MODULE_LICENSE("GPL v2");142