aboutsummaryrefslogtreecommitdiff
path: root/drivers/leds
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/leds')
-rw-r--r--drivers/leds/Kconfig4
-rw-r--r--drivers/leds/Makefile3
-rw-r--r--drivers/leds/leds-expresswire.c68
3 files changed, 75 insertions, 0 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index d721b254e1e4..64bb2de237e9 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -186,6 +186,10 @@ config LEDS_EL15203000
To compile this driver as a module, choose M here: the module
will be called leds-el15203000.
+config LEDS_EXPRESSWIRE
+ bool
+ depends on GPIOLIB
+
config LEDS_TURRIS_OMNIA
tristate "LED support for CZ.NIC's Turris Omnia"
depends on LEDS_CLASS_MULTICOLOR
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index ce07dc295ff0..effdfc6f1e95 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -91,6 +91,9 @@ obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o
obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o
obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
+# Kinetic ExpressWire Protocol
+obj-$(CONFIG_LEDS_EXPRESSWIRE) += leds-expresswire.o
+
# LED SPI Drivers
obj-$(CONFIG_LEDS_CR0014114) += leds-cr0014114.o
obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
diff --git a/drivers/leds/leds-expresswire.c b/drivers/leds/leds-expresswire.c
new file mode 100644
index 000000000000..89e147b0e019
--- /dev/null
+++ b/drivers/leds/leds-expresswire.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Shared library for Kinetic's ExpressWire protocol.
+ * This protocol works by pulsing the ExpressWire IC's control GPIO.
+ * ktd2692 and ktd2801 are known to use this protocol.
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/leds-expresswire.h>
+
+void expresswire_power_off(struct expresswire_common_props *props)
+{
+ gpiod_set_value_cansleep(props->ctrl_gpio, 0);
+ usleep_range(props->timing.poweroff_us, props->timing.poweroff_us * 2);
+}
+EXPORT_SYMBOL_NS_GPL(expresswire_power_off, EXPRESSWIRE);
+
+void expresswire_enable(struct expresswire_common_props *props)
+{
+ gpiod_set_value(props->ctrl_gpio, 1);
+ udelay(props->timing.detect_delay_us);
+ gpiod_set_value(props->ctrl_gpio, 0);
+ udelay(props->timing.detect_us);
+ gpiod_set_value(props->ctrl_gpio, 1);
+}
+EXPORT_SYMBOL_NS_GPL(expresswire_enable, EXPRESSWIRE);
+
+void expresswire_start(struct expresswire_common_props *props)
+{
+ gpiod_set_value(props->ctrl_gpio, 1);
+ udelay(props->timing.data_start_us);
+}
+EXPORT_SYMBOL_NS_GPL(expresswire_start, EXPRESSWIRE);
+
+void expresswire_end(struct expresswire_common_props *props)
+{
+ gpiod_set_value(props->ctrl_gpio, 0);
+ udelay(props->timing.end_of_data_low_us);
+ gpiod_set_value(props->ctrl_gpio, 1);
+ udelay(props->timing.end_of_data_high_us);
+}
+EXPORT_SYMBOL_NS_GPL(expresswire_end, EXPRESSWIRE);
+
+void expresswire_set_bit(struct expresswire_common_props *props, bool bit)
+{
+ if (bit) {
+ gpiod_set_value(props->ctrl_gpio, 0);
+ udelay(props->timing.short_bitset_us);
+ gpiod_set_value(props->ctrl_gpio, 1);
+ udelay(props->timing.long_bitset_us);
+ } else {
+ gpiod_set_value(props->ctrl_gpio, 0);
+ udelay(props->timing.long_bitset_us);
+ gpiod_set_value(props->ctrl_gpio, 1);
+ udelay(props->timing.short_bitset_us);
+ }
+}
+EXPORT_SYMBOL_NS_GPL(expresswire_set_bit, EXPRESSWIRE);
+
+void expresswire_write_u8(struct expresswire_common_props *props, u8 val)
+{
+ expresswire_start(props);
+ for (int i = 7; i >= 0; i--)
+ expresswire_set_bit(props, val & BIT(i));
+ expresswire_end(props);
+}
+EXPORT_SYMBOL_NS_GPL(expresswire_write_u8, EXPRESSWIRE);