xref: /linux/drivers/leds/leds-expresswire.c (revision 69050f8d6d075dc01af7a5f2f550a8067510366f)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Shared library for Kinetic's ExpressWire protocol.
4  * This protocol works by pulsing the ExpressWire IC's control GPIO.
5  * ktd2692 and ktd2801 are known to use this protocol.
6  */
7 
8 #include <linux/bits.h>
9 #include <linux/delay.h>
10 #include <linux/export.h>
11 #include <linux/gpio/consumer.h>
12 #include <linux/irqflags.h>
13 #include <linux/types.h>
14 
15 #include <linux/leds-expresswire.h>
16 
17 void expresswire_power_off(struct expresswire_common_props *props)
18 {
19 	gpiod_set_value_cansleep(props->ctrl_gpio, 0);
20 	fsleep(props->timing.poweroff_us);
21 }
22 EXPORT_SYMBOL_NS_GPL(expresswire_power_off, "EXPRESSWIRE");
23 
24 void expresswire_enable(struct expresswire_common_props *props)
25 {
26 	unsigned long flags;
27 
28 	local_irq_save(flags);
29 
30 	gpiod_set_value(props->ctrl_gpio, 1);
31 	udelay(props->timing.detect_delay_us);
32 	gpiod_set_value(props->ctrl_gpio, 0);
33 	udelay(props->timing.detect_us);
34 	gpiod_set_value(props->ctrl_gpio, 1);
35 
36 	local_irq_restore(flags);
37 }
38 EXPORT_SYMBOL_NS_GPL(expresswire_enable, "EXPRESSWIRE");
39 
40 static void expresswire_start(struct expresswire_common_props *props)
41 {
42 	gpiod_set_value(props->ctrl_gpio, 1);
43 	udelay(props->timing.data_start_us);
44 }
45 
46 static void expresswire_end(struct expresswire_common_props *props)
47 {
48 	gpiod_set_value(props->ctrl_gpio, 0);
49 	udelay(props->timing.end_of_data_low_us);
50 	gpiod_set_value(props->ctrl_gpio, 1);
51 	udelay(props->timing.end_of_data_high_us);
52 }
53 
54 static void expresswire_set_bit(struct expresswire_common_props *props, bool bit)
55 {
56 	if (bit) {
57 		gpiod_set_value(props->ctrl_gpio, 0);
58 		udelay(props->timing.short_bitset_us);
59 		gpiod_set_value(props->ctrl_gpio, 1);
60 		udelay(props->timing.long_bitset_us);
61 	} else {
62 		gpiod_set_value(props->ctrl_gpio, 0);
63 		udelay(props->timing.long_bitset_us);
64 		gpiod_set_value(props->ctrl_gpio, 1);
65 		udelay(props->timing.short_bitset_us);
66 	}
67 }
68 
69 void expresswire_write_u8(struct expresswire_common_props *props, u8 val)
70 {
71 	unsigned long flags;
72 
73 	local_irq_save(flags);
74 
75 	expresswire_start(props);
76 	for (int i = 7; i >= 0; i--)
77 		expresswire_set_bit(props, val & BIT(i));
78 	expresswire_end(props);
79 
80 	local_irq_restore(flags);
81 }
82 EXPORT_SYMBOL_NS_GPL(expresswire_write_u8, "EXPRESSWIRE");
83