diff options
Diffstat (limited to 'drivers/input/misc/dm355evm_keys.c')
-rw-r--r-- | drivers/input/misc/dm355evm_keys.c | 42 |
1 files changed, 20 insertions, 22 deletions
diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c index a63315ce4a6c..0918acae584a 100644 --- a/drivers/input/misc/dm355evm_keys.c +++ b/drivers/input/misc/dm355evm_keys.c | |||
@@ -23,30 +23,16 @@ | |||
23 | * pressed, or its autorepeat kicks in, an event is sent. This driver | 23 | * pressed, or its autorepeat kicks in, an event is sent. This driver |
24 | * read those events from the small (32 event) queue and reports them. | 24 | * read those events from the small (32 event) queue and reports them. |
25 | * | 25 | * |
26 | * Because we communicate with the MSP430 using I2C, and all I2C calls | ||
27 | * in Linux sleep, we need to cons up a kind of threaded IRQ handler | ||
28 | * using a work_struct. The IRQ is active low, but we use it through | ||
29 | * the GPIO controller so we can trigger on falling edges. | ||
30 | * | ||
31 | * Note that physically there can only be one of these devices. | 26 | * Note that physically there can only be one of these devices. |
32 | * | 27 | * |
33 | * This driver was tested with firmware revision A4. | 28 | * This driver was tested with firmware revision A4. |
34 | */ | 29 | */ |
35 | struct dm355evm_keys { | 30 | struct dm355evm_keys { |
36 | struct work_struct work; | ||
37 | struct input_dev *input; | 31 | struct input_dev *input; |
38 | struct device *dev; | 32 | struct device *dev; |
39 | int irq; | 33 | int irq; |
40 | }; | 34 | }; |
41 | 35 | ||
42 | static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | ||
43 | { | ||
44 | struct dm355evm_keys *keys = _keys; | ||
45 | |||
46 | schedule_work(&keys->work); | ||
47 | return IRQ_HANDLED; | ||
48 | } | ||
49 | |||
50 | /* These initial keycodes can be remapped by dm355evm_setkeycode(). */ | 36 | /* These initial keycodes can be remapped by dm355evm_setkeycode(). */ |
51 | static struct { | 37 | static struct { |
52 | u16 event; | 38 | u16 event; |
@@ -110,13 +96,12 @@ static struct { | |||
110 | { 0x3169, KEY_PAUSE, }, | 96 | { 0x3169, KEY_PAUSE, }, |
111 | }; | 97 | }; |
112 | 98 | ||
113 | static void dm355evm_keys_work(struct work_struct *work) | 99 | /* runs in an IRQ thread -- can (and will!) sleep */ |
100 | static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | ||
114 | { | 101 | { |
115 | struct dm355evm_keys *keys; | 102 | struct dm355evm_keys *keys = _keys; |
116 | int status; | 103 | int status; |
117 | 104 | ||
118 | keys = container_of(work, struct dm355evm_keys, work); | ||
119 | |||
120 | /* For simplicity we ignore INPUT_COUNT and just read | 105 | /* For simplicity we ignore INPUT_COUNT and just read |
121 | * events until we get the "queue empty" indicator. | 106 | * events until we get the "queue empty" indicator. |
122 | * Reading INPUT_LOW decrements the count. | 107 | * Reading INPUT_LOW decrements the count. |
@@ -183,6 +168,19 @@ static void dm355evm_keys_work(struct work_struct *work) | |||
183 | input_report_key(keys->input, keycode, 0); | 168 | input_report_key(keys->input, keycode, 0); |
184 | input_sync(keys->input); | 169 | input_sync(keys->input); |
185 | } | 170 | } |
171 | return IRQ_HANDLED; | ||
172 | } | ||
173 | |||
174 | /* | ||
175 | * Because we communicate with the MSP430 using I2C, and all I2C calls | ||
176 | * in Linux sleep, we use a threaded IRQ handler. The IRQ itself is | ||
177 | * active low, but we go through the GPIO controller so we can trigger | ||
178 | * on falling edges and not worry about enabling/disabling the IRQ in | ||
179 | * the keypress handling path. | ||
180 | */ | ||
181 | static irqreturn_t dm355evm_keys_hardirq(int irq, void *_keys) | ||
182 | { | ||
183 | return IRQ_WAKE_THREAD; | ||
186 | } | 184 | } |
187 | 185 | ||
188 | static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode) | 186 | static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode) |
@@ -233,7 +231,6 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev) | |||
233 | 231 | ||
234 | keys->dev = &pdev->dev; | 232 | keys->dev = &pdev->dev; |
235 | keys->input = input; | 233 | keys->input = input; |
236 | INIT_WORK(&keys->work, dm355evm_keys_work); | ||
237 | 234 | ||
238 | /* set up "threaded IRQ handler" */ | 235 | /* set up "threaded IRQ handler" */ |
239 | status = platform_get_irq(pdev, 0); | 236 | status = platform_get_irq(pdev, 0); |
@@ -260,9 +257,10 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev) | |||
260 | 257 | ||
261 | /* REVISIT: flush the event queue? */ | 258 | /* REVISIT: flush the event queue? */ |
262 | 259 | ||
263 | status = request_irq(keys->irq, dm355evm_keys_irq, | 260 | status = request_threaded_irq(keys->irq, |
264 | IRQF_TRIGGER_FALLING, | 261 | dm355evm_keys_hardirq, dm355evm_keys_irq, |
265 | dev_name(&pdev->dev), keys); | 262 | IRQF_TRIGGER_FALLING, |
263 | dev_name(&pdev->dev), keys); | ||
266 | if (status < 0) | 264 | if (status < 0) |
267 | goto fail1; | 265 | goto fail1; |
268 | 266 | ||