1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Touchkey driver for MELFAS MCS5000/5080 controller
5 * Copyright (C) 2010 Samsung Electronics Co.Ltd
6 * Author: HeungJun Kim <riverful.kim@samsung.com>
7 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
10 #include <linux/module.h>
11 #include <linux/i2c.h>
12 #include <linux/interrupt.h>
13 #include <linux/input.h>
14 #include <linux/irq.h>
15 #include <linux/slab.h>
16 #include <linux/platform_data/mcs.h>
19 /* MCS5000 Touchkey */
20 #define MCS5000_TOUCHKEY_STATUS 0x04
21 #define MCS5000_TOUCHKEY_STATUS_PRESS 7
22 #define MCS5000_TOUCHKEY_FW 0x0a
23 #define MCS5000_TOUCHKEY_BASE_VAL 0x61
25 /* MCS5080 Touchkey */
26 #define MCS5080_TOUCHKEY_STATUS 0x00
27 #define MCS5080_TOUCHKEY_STATUS_PRESS 3
28 #define MCS5080_TOUCHKEY_FW 0x01
29 #define MCS5080_TOUCHKEY_BASE_VAL 0x1
31 enum mcs_touchkey_type
{
36 struct mcs_touchkey_chip
{
37 unsigned int status_reg
;
38 unsigned int pressbit
;
39 unsigned int press_invert
;
43 struct mcs_touchkey_data
{
44 void (*poweron
)(bool);
46 struct i2c_client
*client
;
47 struct input_dev
*input_dev
;
48 struct mcs_touchkey_chip chip
;
49 unsigned int key_code
;
51 unsigned short keycodes
[];
54 static irqreturn_t
mcs_touchkey_interrupt(int irq
, void *dev_id
)
56 struct mcs_touchkey_data
*data
= dev_id
;
57 struct mcs_touchkey_chip
*chip
= &data
->chip
;
58 struct i2c_client
*client
= data
->client
;
59 struct input_dev
*input
= data
->input_dev
;
64 val
= i2c_smbus_read_byte_data(client
, chip
->status_reg
);
66 dev_err(&client
->dev
, "i2c read error [%d]\n", val
);
70 pressed
= (val
& (1 << chip
->pressbit
)) >> chip
->pressbit
;
71 if (chip
->press_invert
)
72 pressed
^= chip
->press_invert
;
74 /* key_val is 0 when released, so we should use key_val of press. */
76 key_val
= val
& (0xff >> (8 - chip
->pressbit
));
79 key_val
-= chip
->baseval
;
80 data
->key_code
= data
->keycodes
[key_val
];
81 data
->key_val
= key_val
;
84 input_event(input
, EV_MSC
, MSC_SCAN
, data
->key_val
);
85 input_report_key(input
, data
->key_code
, pressed
);
88 dev_dbg(&client
->dev
, "key %d %d %s\n", data
->key_val
, data
->key_code
,
89 pressed
? "pressed" : "released");
95 static int mcs_touchkey_probe(struct i2c_client
*client
,
96 const struct i2c_device_id
*id
)
98 const struct mcs_platform_data
*pdata
;
99 struct mcs_touchkey_data
*data
;
100 struct input_dev
*input_dev
;
106 pdata
= dev_get_platdata(&client
->dev
);
108 dev_err(&client
->dev
, "no platform data defined\n");
112 data
= kzalloc(struct_size(data
, keycodes
, pdata
->key_maxval
+ 1),
114 input_dev
= input_allocate_device();
115 if (!data
|| !input_dev
) {
116 dev_err(&client
->dev
, "Failed to allocate memory\n");
121 data
->client
= client
;
122 data
->input_dev
= input_dev
;
124 if (id
->driver_data
== MCS5000_TOUCHKEY
) {
125 data
->chip
.status_reg
= MCS5000_TOUCHKEY_STATUS
;
126 data
->chip
.pressbit
= MCS5000_TOUCHKEY_STATUS_PRESS
;
127 data
->chip
.baseval
= MCS5000_TOUCHKEY_BASE_VAL
;
128 fw_reg
= MCS5000_TOUCHKEY_FW
;
130 data
->chip
.status_reg
= MCS5080_TOUCHKEY_STATUS
;
131 data
->chip
.pressbit
= MCS5080_TOUCHKEY_STATUS_PRESS
;
132 data
->chip
.press_invert
= 1;
133 data
->chip
.baseval
= MCS5080_TOUCHKEY_BASE_VAL
;
134 fw_reg
= MCS5080_TOUCHKEY_FW
;
137 fw_ver
= i2c_smbus_read_byte_data(client
, fw_reg
);
140 dev_err(&client
->dev
, "i2c read error[%d]\n", error
);
143 dev_info(&client
->dev
, "Firmware version: %d\n", fw_ver
);
145 input_dev
->name
= "MELFAS MCS Touchkey";
146 input_dev
->id
.bustype
= BUS_I2C
;
147 input_dev
->dev
.parent
= &client
->dev
;
148 input_dev
->evbit
[0] = BIT_MASK(EV_KEY
);
149 if (!pdata
->no_autorepeat
)
150 input_dev
->evbit
[0] |= BIT_MASK(EV_REP
);
151 input_dev
->keycode
= data
->keycodes
;
152 input_dev
->keycodesize
= sizeof(data
->keycodes
[0]);
153 input_dev
->keycodemax
= pdata
->key_maxval
+ 1;
155 for (i
= 0; i
< pdata
->keymap_size
; i
++) {
156 unsigned int val
= MCS_KEY_VAL(pdata
->keymap
[i
]);
157 unsigned int code
= MCS_KEY_CODE(pdata
->keymap
[i
]);
159 data
->keycodes
[val
] = code
;
160 __set_bit(code
, input_dev
->keybit
);
163 input_set_capability(input_dev
, EV_MSC
, MSC_SCAN
);
164 input_set_drvdata(input_dev
, data
);
169 if (pdata
->poweron
) {
170 data
->poweron
= pdata
->poweron
;
174 error
= request_threaded_irq(client
->irq
, NULL
, mcs_touchkey_interrupt
,
175 IRQF_TRIGGER_FALLING
| IRQF_ONESHOT
,
176 client
->dev
.driver
->name
, data
);
178 dev_err(&client
->dev
, "Failed to register interrupt\n");
182 error
= input_register_device(input_dev
);
186 i2c_set_clientdata(client
, data
);
190 free_irq(client
->irq
, data
);
192 input_free_device(input_dev
);
197 static int mcs_touchkey_remove(struct i2c_client
*client
)
199 struct mcs_touchkey_data
*data
= i2c_get_clientdata(client
);
201 free_irq(client
->irq
, data
);
203 data
->poweron(false);
204 input_unregister_device(data
->input_dev
);
210 static void mcs_touchkey_shutdown(struct i2c_client
*client
)
212 struct mcs_touchkey_data
*data
= i2c_get_clientdata(client
);
215 data
->poweron(false);
218 #ifdef CONFIG_PM_SLEEP
219 static int mcs_touchkey_suspend(struct device
*dev
)
221 struct mcs_touchkey_data
*data
= dev_get_drvdata(dev
);
222 struct i2c_client
*client
= data
->client
;
224 /* Disable the work */
225 disable_irq(client
->irq
);
227 /* Finally turn off the power */
229 data
->poweron(false);
234 static int mcs_touchkey_resume(struct device
*dev
)
236 struct mcs_touchkey_data
*data
= dev_get_drvdata(dev
);
237 struct i2c_client
*client
= data
->client
;
239 /* Enable the device first */
243 /* Enable irq again */
244 enable_irq(client
->irq
);
250 static SIMPLE_DEV_PM_OPS(mcs_touchkey_pm_ops
,
251 mcs_touchkey_suspend
, mcs_touchkey_resume
);
253 static const struct i2c_device_id mcs_touchkey_id
[] = {
254 { "mcs5000_touchkey", MCS5000_TOUCHKEY
},
255 { "mcs5080_touchkey", MCS5080_TOUCHKEY
},
258 MODULE_DEVICE_TABLE(i2c
, mcs_touchkey_id
);
260 static struct i2c_driver mcs_touchkey_driver
= {
262 .name
= "mcs_touchkey",
263 .pm
= &mcs_touchkey_pm_ops
,
265 .probe
= mcs_touchkey_probe
,
266 .remove
= mcs_touchkey_remove
,
267 .shutdown
= mcs_touchkey_shutdown
,
268 .id_table
= mcs_touchkey_id
,
271 module_i2c_driver(mcs_touchkey_driver
);
273 /* Module information */
274 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
275 MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>");
276 MODULE_DESCRIPTION("Touchkey driver for MELFAS MCS5000/5080 controller");
277 MODULE_LICENSE("GPL");