1 // SPDX-License-Identifier: GPL-2.0-only
4 * h3600 atmel micro companion support, key subdevice
5 * based on previous kernel 2.4 version
6 * Author : Alessandro Gardich <gremlin@gremlin.it>
7 * Author : Linus Walleij <linus.walleij@linaro.org>
9 #include <linux/module.h>
10 #include <linux/init.h>
12 #include <linux/interrupt.h>
13 #include <linux/sched.h>
15 #include <linux/sysctl.h>
16 #include <linux/proc_fs.h>
17 #include <linux/delay.h>
18 #include <linux/device.h>
19 #include <linux/input.h>
20 #include <linux/platform_device.h>
21 #include <linux/mfd/ipaq-micro.h>
23 struct ipaq_micro_keys
{
24 struct ipaq_micro
*micro
;
25 struct input_dev
*input
;
29 static const u16 micro_keycodes
[] = {
30 KEY_RECORD
, /* 1: Record button */
31 KEY_CALENDAR
, /* 2: Calendar */
32 KEY_ADDRESSBOOK
, /* 3: Contacts (looks like Outlook) */
33 KEY_MAIL
, /* 4: Envelope (Q on older iPAQs) */
34 KEY_HOMEPAGE
, /* 5: Start (looks like swoopy arrow) */
36 KEY_RIGHT
, /* 7: Right */
37 KEY_LEFT
, /* 8: Left */
38 KEY_DOWN
, /* 9: Down */
41 static void micro_key_receive(void *data
, int len
, unsigned char *msg
)
43 struct ipaq_micro_keys
*keys
= data
;
49 if (key
< ARRAY_SIZE(micro_keycodes
)) {
50 input_report_key(keys
->input
, keys
->codes
[key
], down
);
51 input_sync(keys
->input
);
55 static void micro_key_start(struct ipaq_micro_keys
*keys
)
57 spin_lock(&keys
->micro
->lock
);
58 keys
->micro
->key
= micro_key_receive
;
59 keys
->micro
->key_data
= keys
;
60 spin_unlock(&keys
->micro
->lock
);
63 static void micro_key_stop(struct ipaq_micro_keys
*keys
)
65 spin_lock(&keys
->micro
->lock
);
66 keys
->micro
->key
= NULL
;
67 keys
->micro
->key_data
= NULL
;
68 spin_unlock(&keys
->micro
->lock
);
71 static int micro_key_open(struct input_dev
*input
)
73 struct ipaq_micro_keys
*keys
= input_get_drvdata(input
);
75 micro_key_start(keys
);
80 static void micro_key_close(struct input_dev
*input
)
82 struct ipaq_micro_keys
*keys
= input_get_drvdata(input
);
87 static int micro_key_probe(struct platform_device
*pdev
)
89 struct ipaq_micro_keys
*keys
;
93 keys
= devm_kzalloc(&pdev
->dev
, sizeof(*keys
), GFP_KERNEL
);
97 keys
->micro
= dev_get_drvdata(pdev
->dev
.parent
);
99 keys
->input
= devm_input_allocate_device(&pdev
->dev
);
103 keys
->input
->keycodesize
= sizeof(micro_keycodes
[0]);
104 keys
->input
->keycodemax
= ARRAY_SIZE(micro_keycodes
);
105 keys
->codes
= devm_kmemdup(&pdev
->dev
, micro_keycodes
,
106 keys
->input
->keycodesize
* keys
->input
->keycodemax
,
108 keys
->input
->keycode
= keys
->codes
;
110 __set_bit(EV_KEY
, keys
->input
->evbit
);
111 for (i
= 0; i
< ARRAY_SIZE(micro_keycodes
); i
++)
112 __set_bit(micro_keycodes
[i
], keys
->input
->keybit
);
114 keys
->input
->name
= "h3600 micro keys";
115 keys
->input
->open
= micro_key_open
;
116 keys
->input
->close
= micro_key_close
;
117 input_set_drvdata(keys
->input
, keys
);
119 error
= input_register_device(keys
->input
);
123 platform_set_drvdata(pdev
, keys
);
127 static int __maybe_unused
micro_key_suspend(struct device
*dev
)
129 struct ipaq_micro_keys
*keys
= dev_get_drvdata(dev
);
131 micro_key_stop(keys
);
136 static int __maybe_unused
micro_key_resume(struct device
*dev
)
138 struct ipaq_micro_keys
*keys
= dev_get_drvdata(dev
);
139 struct input_dev
*input
= keys
->input
;
141 mutex_lock(&input
->mutex
);
143 if (input_device_enabled(input
))
144 micro_key_start(keys
);
146 mutex_unlock(&input
->mutex
);
151 static SIMPLE_DEV_PM_OPS(micro_key_dev_pm_ops
,
152 micro_key_suspend
, micro_key_resume
);
154 static struct platform_driver micro_key_device_driver
= {
156 .name
= "ipaq-micro-keys",
157 .pm
= µ_key_dev_pm_ops
,
159 .probe
= micro_key_probe
,
161 module_platform_driver(micro_key_device_driver
);
163 MODULE_LICENSE("GPL");
164 MODULE_DESCRIPTION("driver for iPAQ Atmel micro keys");
165 MODULE_ALIAS("platform:ipaq-micro-keys");