Skip to content

Commit 69d5ff3

Browse files
Vogtinatordtor
authored andcommitted
Input: nspire-keypad - enable interrupts only when opened
The driver registers an interrupt handler in _probe, but didn't configure them until later when the _open function is called. In between, the keypad can fire an IRQ due to touchpad activity, which the handler ignores. This causes the kernel to disable the interrupt, blocking the keypad from working. Fix this by disabling interrupts before registering the handler. Additionally, disable them in _close, so that they're only enabled while open. Fixes: fc4f314 ("Input: add TI-Nspire keypad support") Signed-off-by: Fabian Vogt <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent daa58c8 commit 69d5ff3

File tree

1 file changed

+31
-25
lines changed

1 file changed

+31
-25
lines changed

drivers/input/keyboard/nspire-keypad.c

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,15 @@ static irqreturn_t nspire_keypad_irq(int irq, void *dev_id)
9393
return IRQ_HANDLED;
9494
}
9595

96-
static int nspire_keypad_chip_init(struct nspire_keypad *keypad)
96+
static int nspire_keypad_open(struct input_dev *input)
9797
{
98+
struct nspire_keypad *keypad = input_get_drvdata(input);
9899
unsigned long val = 0, cycles_per_us, delay_cycles, row_delay_cycles;
100+
int error;
101+
102+
error = clk_prepare_enable(keypad->clk);
103+
if (error)
104+
return error;
99105

100106
cycles_per_us = (clk_get_rate(keypad->clk) / 1000000);
101107
if (cycles_per_us == 0)
@@ -121,37 +127,18 @@ static int nspire_keypad_chip_init(struct nspire_keypad *keypad)
121127
keypad->int_mask = 1 << 1;
122128
writel(keypad->int_mask, keypad->reg_base + KEYPAD_INTMSK);
123129

124-
/* Disable GPIO interrupts to prevent hanging on touchpad */
125-
/* Possibly used to detect touchpad events */
126-
writel(0, keypad->reg_base + KEYPAD_UNKNOWN_INT);
127-
/* Acknowledge existing interrupts */
128-
writel(~0, keypad->reg_base + KEYPAD_UNKNOWN_INT_STS);
129-
130-
return 0;
131-
}
132-
133-
static int nspire_keypad_open(struct input_dev *input)
134-
{
135-
struct nspire_keypad *keypad = input_get_drvdata(input);
136-
int error;
137-
138-
error = clk_prepare_enable(keypad->clk);
139-
if (error)
140-
return error;
141-
142-
error = nspire_keypad_chip_init(keypad);
143-
if (error) {
144-
clk_disable_unprepare(keypad->clk);
145-
return error;
146-
}
147-
148130
return 0;
149131
}
150132

151133
static void nspire_keypad_close(struct input_dev *input)
152134
{
153135
struct nspire_keypad *keypad = input_get_drvdata(input);
154136

137+
/* Disable interrupts */
138+
writel(0, keypad->reg_base + KEYPAD_INTMSK);
139+
/* Acknowledge existing interrupts */
140+
writel(~0, keypad->reg_base + KEYPAD_INT);
141+
155142
clk_disable_unprepare(keypad->clk);
156143
}
157144

@@ -210,6 +197,25 @@ static int nspire_keypad_probe(struct platform_device *pdev)
210197
return -ENOMEM;
211198
}
212199

200+
error = clk_prepare_enable(keypad->clk);
201+
if (error) {
202+
dev_err(&pdev->dev, "failed to enable clock\n");
203+
return error;
204+
}
205+
206+
/* Disable interrupts */
207+
writel(0, keypad->reg_base + KEYPAD_INTMSK);
208+
/* Acknowledge existing interrupts */
209+
writel(~0, keypad->reg_base + KEYPAD_INT);
210+
211+
/* Disable GPIO interrupts to prevent hanging on touchpad */
212+
/* Possibly used to detect touchpad events */
213+
writel(0, keypad->reg_base + KEYPAD_UNKNOWN_INT);
214+
/* Acknowledge existing GPIO interrupts */
215+
writel(~0, keypad->reg_base + KEYPAD_UNKNOWN_INT_STS);
216+
217+
clk_disable_unprepare(keypad->clk);
218+
213219
input_set_drvdata(input, keypad);
214220

215221
input->id.bustype = BUS_HOST;

0 commit comments

Comments
 (0)