Skip to content

Commit f4b830a

Browse files
LegoLivesMatterlag-linaro
authored andcommitted
leds: expresswire: Fix chip state breakage
It is possible to put the KTD2801 chip in an unknown/undefined state by changing the brightness very rapidly (for example, with a brightness slider). When this happens, the brightness is stuck on max and cannot be changed until the chip is power cycled. Fix this by disabling interrupts while talking to the chip. While at it, make expresswire_power_off() use fsleep() and also unexport some functions meant to be internal. Fixes: 1368d06 ("leds: Introduce ExpressWire library") Tested-by: Karel Balej <balejk@matfyz.cz> Signed-off-by: Duje Mihanović <duje@dujemihanovic.xyz> Link: https://patch.msgid.link/20251217-expresswire-fix-v2-1-4a02b10acd96@dujemihanovic.xyz Signed-off-by: Lee Jones <lee@kernel.org>
1 parent 393d56d commit f4b830a

2 files changed

Lines changed: 17 additions & 10 deletions

File tree

drivers/leds/leds-expresswire.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,44 +9,49 @@
99
#include <linux/delay.h>
1010
#include <linux/export.h>
1111
#include <linux/gpio/consumer.h>
12+
#include <linux/irqflags.h>
1213
#include <linux/types.h>
1314

1415
#include <linux/leds-expresswire.h>
1516

1617
void expresswire_power_off(struct expresswire_common_props *props)
1718
{
1819
gpiod_set_value_cansleep(props->ctrl_gpio, 0);
19-
usleep_range(props->timing.poweroff_us, props->timing.poweroff_us * 2);
20+
fsleep(props->timing.poweroff_us);
2021
}
2122
EXPORT_SYMBOL_NS_GPL(expresswire_power_off, "EXPRESSWIRE");
2223

2324
void expresswire_enable(struct expresswire_common_props *props)
2425
{
26+
unsigned long flags;
27+
28+
local_irq_save(flags);
29+
2530
gpiod_set_value(props->ctrl_gpio, 1);
2631
udelay(props->timing.detect_delay_us);
2732
gpiod_set_value(props->ctrl_gpio, 0);
2833
udelay(props->timing.detect_us);
2934
gpiod_set_value(props->ctrl_gpio, 1);
35+
36+
local_irq_restore(flags);
3037
}
3138
EXPORT_SYMBOL_NS_GPL(expresswire_enable, "EXPRESSWIRE");
3239

33-
void expresswire_start(struct expresswire_common_props *props)
40+
static void expresswire_start(struct expresswire_common_props *props)
3441
{
3542
gpiod_set_value(props->ctrl_gpio, 1);
3643
udelay(props->timing.data_start_us);
3744
}
38-
EXPORT_SYMBOL_NS_GPL(expresswire_start, "EXPRESSWIRE");
3945

40-
void expresswire_end(struct expresswire_common_props *props)
46+
static void expresswire_end(struct expresswire_common_props *props)
4147
{
4248
gpiod_set_value(props->ctrl_gpio, 0);
4349
udelay(props->timing.end_of_data_low_us);
4450
gpiod_set_value(props->ctrl_gpio, 1);
4551
udelay(props->timing.end_of_data_high_us);
4652
}
47-
EXPORT_SYMBOL_NS_GPL(expresswire_end, "EXPRESSWIRE");
4853

49-
void expresswire_set_bit(struct expresswire_common_props *props, bool bit)
54+
static void expresswire_set_bit(struct expresswire_common_props *props, bool bit)
5055
{
5156
if (bit) {
5257
gpiod_set_value(props->ctrl_gpio, 0);
@@ -60,13 +65,18 @@ void expresswire_set_bit(struct expresswire_common_props *props, bool bit)
6065
udelay(props->timing.short_bitset_us);
6166
}
6267
}
63-
EXPORT_SYMBOL_NS_GPL(expresswire_set_bit, "EXPRESSWIRE");
6468

6569
void expresswire_write_u8(struct expresswire_common_props *props, u8 val)
6670
{
71+
unsigned long flags;
72+
73+
local_irq_save(flags);
74+
6775
expresswire_start(props);
6876
for (int i = 7; i >= 0; i--)
6977
expresswire_set_bit(props, val & BIT(i));
7078
expresswire_end(props);
79+
80+
local_irq_restore(flags);
7181
}
7282
EXPORT_SYMBOL_NS_GPL(expresswire_write_u8, "EXPRESSWIRE");

include/linux/leds-expresswire.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@ struct expresswire_common_props {
3030

3131
void expresswire_power_off(struct expresswire_common_props *props);
3232
void expresswire_enable(struct expresswire_common_props *props);
33-
void expresswire_start(struct expresswire_common_props *props);
34-
void expresswire_end(struct expresswire_common_props *props);
35-
void expresswire_set_bit(struct expresswire_common_props *props, bool bit);
3633
void expresswire_write_u8(struct expresswire_common_props *props, u8 val);
3734

3835
#endif /* _LEDS_EXPRESSWIRE_H */

0 commit comments

Comments
 (0)