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