1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Touchkey driver for MELFAS MCS5000/5080 controller 4 * 5 * Copyright (C) 2010 Samsung Electronics Co.Ltd 6 * Author: HeungJun Kim <riverful.kim@samsung.com> 7 * Author: Joonyoung Shim <jy0922.shim@samsung.com> 8 */ 9 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> 17 #include <linux/pm.h> 18 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 24 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 30 31 enum mcs_touchkey_type { 32 MCS5000_TOUCHKEY, 33 MCS5080_TOUCHKEY, 34 }; 35 36 struct mcs_touchkey_chip { 37 unsigned int status_reg; 38 unsigned int pressbit; 39 unsigned int press_invert; 40 unsigned int baseval; 41 }; 42 43 struct mcs_touchkey_data { 44 void (*poweron)(bool); 45 46 struct i2c_client *client; 47 struct input_dev *input_dev; 48 struct mcs_touchkey_chip chip; 49 unsigned int key_code; 50 unsigned int key_val; 51 unsigned short keycodes[]; 52 }; 53 54 static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id) 55 { 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; 60 unsigned int key_val; 61 unsigned int pressed; 62 int val; 63 64 val = i2c_smbus_read_byte_data(client, chip->status_reg); 65 if (val < 0) { 66 dev_err(&client->dev, "i2c read error [%d]\n", val); 67 goto out; 68 } 69 70 pressed = (val & (1 << chip->pressbit)) >> chip->pressbit; 71 if (chip->press_invert) 72 pressed ^= chip->press_invert; 73 74 /* key_val is 0 when released, so we should use key_val of press. */ 75 if (pressed) { 76 key_val = val & (0xff >> (8 - chip->pressbit)); 77 if (!key_val) 78 goto out; 79 key_val -= chip->baseval; 80 data->key_code = data->keycodes[key_val]; 81 data->key_val = key_val; 82 } 83 84 input_event(input, EV_MSC, MSC_SCAN, data->key_val); 85 input_report_key(input, data->key_code, pressed); 86 input_sync(input); 87 88 dev_dbg(&client->dev, "key %d %d %s\n", data->key_val, data->key_code, 89 pressed ? "pressed" : "released"); 90 91 out: 92 return IRQ_HANDLED; 93 } 94 95 static int mcs_touchkey_probe(struct i2c_client *client) 96 { 97 const struct i2c_device_id *id = i2c_client_get_device_id(client); 98 const struct mcs_platform_data *pdata; 99 struct mcs_touchkey_data *data; 100 struct input_dev *input_dev; 101 unsigned int fw_reg; 102 int fw_ver; 103 int error; 104 int i; 105 106 pdata = dev_get_platdata(&client->dev); 107 if (!pdata) { 108 dev_err(&client->dev, "no platform data defined\n"); 109 return -EINVAL; 110 } 111 112 data = kzalloc(struct_size(data, keycodes, pdata->key_maxval + 1), 113 GFP_KERNEL); 114 input_dev = input_allocate_device(); 115 if (!data || !input_dev) { 116 dev_err(&client->dev, "Failed to allocate memory\n"); 117 error = -ENOMEM; 118 goto err_free_mem; 119 } 120 121 data->client = client; 122 data->input_dev = input_dev; 123 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; 129 } else { 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; 135 } 136 137 fw_ver = i2c_smbus_read_byte_data(client, fw_reg); 138 if (fw_ver < 0) { 139 error = fw_ver; 140 dev_err(&client->dev, "i2c read error[%d]\n", error); 141 goto err_free_mem; 142 } 143 dev_info(&client->dev, "Firmware version: %d\n", fw_ver); 144 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; 154 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]); 158 159 data->keycodes[val] = code; 160 __set_bit(code, input_dev->keybit); 161 } 162 163 input_set_capability(input_dev, EV_MSC, MSC_SCAN); 164 input_set_drvdata(input_dev, data); 165 166 if (pdata->cfg_pin) 167 pdata->cfg_pin(); 168 169 if (pdata->poweron) { 170 data->poweron = pdata->poweron; 171 data->poweron(true); 172 } 173 174 error = request_threaded_irq(client->irq, NULL, mcs_touchkey_interrupt, 175 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 176 client->dev.driver->name, data); 177 if (error) { 178 dev_err(&client->dev, "Failed to register interrupt\n"); 179 goto err_free_mem; 180 } 181 182 error = input_register_device(input_dev); 183 if (error) 184 goto err_free_irq; 185 186 i2c_set_clientdata(client, data); 187 return 0; 188 189 err_free_irq: 190 free_irq(client->irq, data); 191 err_free_mem: 192 input_free_device(input_dev); 193 kfree(data); 194 return error; 195 } 196 197 static void mcs_touchkey_remove(struct i2c_client *client) 198 { 199 struct mcs_touchkey_data *data = i2c_get_clientdata(client); 200 201 free_irq(client->irq, data); 202 if (data->poweron) 203 data->poweron(false); 204 input_unregister_device(data->input_dev); 205 kfree(data); 206 } 207 208 static void mcs_touchkey_shutdown(struct i2c_client *client) 209 { 210 struct mcs_touchkey_data *data = i2c_get_clientdata(client); 211 212 if (data->poweron) 213 data->poweron(false); 214 } 215 216 static int mcs_touchkey_suspend(struct device *dev) 217 { 218 struct mcs_touchkey_data *data = dev_get_drvdata(dev); 219 struct i2c_client *client = data->client; 220 221 /* Disable the work */ 222 disable_irq(client->irq); 223 224 /* Finally turn off the power */ 225 if (data->poweron) 226 data->poweron(false); 227 228 return 0; 229 } 230 231 static int mcs_touchkey_resume(struct device *dev) 232 { 233 struct mcs_touchkey_data *data = dev_get_drvdata(dev); 234 struct i2c_client *client = data->client; 235 236 /* Enable the device first */ 237 if (data->poweron) 238 data->poweron(true); 239 240 /* Enable irq again */ 241 enable_irq(client->irq); 242 243 return 0; 244 } 245 246 static DEFINE_SIMPLE_DEV_PM_OPS(mcs_touchkey_pm_ops, 247 mcs_touchkey_suspend, mcs_touchkey_resume); 248 249 static const struct i2c_device_id mcs_touchkey_id[] = { 250 { "mcs5000_touchkey", MCS5000_TOUCHKEY }, 251 { "mcs5080_touchkey", MCS5080_TOUCHKEY }, 252 { } 253 }; 254 MODULE_DEVICE_TABLE(i2c, mcs_touchkey_id); 255 256 static struct i2c_driver mcs_touchkey_driver = { 257 .driver = { 258 .name = "mcs_touchkey", 259 .pm = pm_sleep_ptr(&mcs_touchkey_pm_ops), 260 }, 261 .probe = mcs_touchkey_probe, 262 .remove = mcs_touchkey_remove, 263 .shutdown = mcs_touchkey_shutdown, 264 .id_table = mcs_touchkey_id, 265 }; 266 267 module_i2c_driver(mcs_touchkey_driver); 268 269 /* Module information */ 270 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); 271 MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>"); 272 MODULE_DESCRIPTION("Touchkey driver for MELFAS MCS5000/5080 controller"); 273 MODULE_LICENSE("GPL"); 274