Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Touchkey driver for MELFAS MCS5000/5080 controller
0004  *
0005  * Copyright (C) 2010 Samsung Electronics Co.Ltd
0006  * Author: HeungJun Kim <riverful.kim@samsung.com>
0007  * Author: Joonyoung Shim <jy0922.shim@samsung.com>
0008  */
0009 
0010 #include <linux/module.h>
0011 #include <linux/i2c.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/input.h>
0014 #include <linux/irq.h>
0015 #include <linux/slab.h>
0016 #include <linux/platform_data/mcs.h>
0017 #include <linux/pm.h>
0018 
0019 /* MCS5000 Touchkey */
0020 #define MCS5000_TOUCHKEY_STATUS     0x04
0021 #define MCS5000_TOUCHKEY_STATUS_PRESS   7
0022 #define MCS5000_TOUCHKEY_FW     0x0a
0023 #define MCS5000_TOUCHKEY_BASE_VAL   0x61
0024 
0025 /* MCS5080 Touchkey */
0026 #define MCS5080_TOUCHKEY_STATUS     0x00
0027 #define MCS5080_TOUCHKEY_STATUS_PRESS   3
0028 #define MCS5080_TOUCHKEY_FW     0x01
0029 #define MCS5080_TOUCHKEY_BASE_VAL   0x1
0030 
0031 enum mcs_touchkey_type {
0032     MCS5000_TOUCHKEY,
0033     MCS5080_TOUCHKEY,
0034 };
0035 
0036 struct mcs_touchkey_chip {
0037     unsigned int status_reg;
0038     unsigned int pressbit;
0039     unsigned int press_invert;
0040     unsigned int baseval;
0041 };
0042 
0043 struct mcs_touchkey_data {
0044     void (*poweron)(bool);
0045 
0046     struct i2c_client *client;
0047     struct input_dev *input_dev;
0048     struct mcs_touchkey_chip chip;
0049     unsigned int key_code;
0050     unsigned int key_val;
0051     unsigned short keycodes[];
0052 };
0053 
0054 static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id)
0055 {
0056     struct mcs_touchkey_data *data = dev_id;
0057     struct mcs_touchkey_chip *chip = &data->chip;
0058     struct i2c_client *client = data->client;
0059     struct input_dev *input = data->input_dev;
0060     unsigned int key_val;
0061     unsigned int pressed;
0062     int val;
0063 
0064     val = i2c_smbus_read_byte_data(client, chip->status_reg);
0065     if (val < 0) {
0066         dev_err(&client->dev, "i2c read error [%d]\n", val);
0067         goto out;
0068     }
0069 
0070     pressed = (val & (1 << chip->pressbit)) >> chip->pressbit;
0071     if (chip->press_invert)
0072         pressed ^= chip->press_invert;
0073 
0074     /* key_val is 0 when released, so we should use key_val of press. */
0075     if (pressed) {
0076         key_val = val & (0xff >> (8 - chip->pressbit));
0077         if (!key_val)
0078             goto out;
0079         key_val -= chip->baseval;
0080         data->key_code = data->keycodes[key_val];
0081         data->key_val = key_val;
0082     }
0083 
0084     input_event(input, EV_MSC, MSC_SCAN, data->key_val);
0085     input_report_key(input, data->key_code, pressed);
0086     input_sync(input);
0087 
0088     dev_dbg(&client->dev, "key %d %d %s\n", data->key_val, data->key_code,
0089         pressed ? "pressed" : "released");
0090 
0091  out:
0092     return IRQ_HANDLED;
0093 }
0094 
0095 static int mcs_touchkey_probe(struct i2c_client *client,
0096         const struct i2c_device_id *id)
0097 {
0098     const struct mcs_platform_data *pdata;
0099     struct mcs_touchkey_data *data;
0100     struct input_dev *input_dev;
0101     unsigned int fw_reg;
0102     int fw_ver;
0103     int error;
0104     int i;
0105 
0106     pdata = dev_get_platdata(&client->dev);
0107     if (!pdata) {
0108         dev_err(&client->dev, "no platform data defined\n");
0109         return -EINVAL;
0110     }
0111 
0112     data = kzalloc(struct_size(data, keycodes, pdata->key_maxval + 1),
0113                GFP_KERNEL);
0114     input_dev = input_allocate_device();
0115     if (!data || !input_dev) {
0116         dev_err(&client->dev, "Failed to allocate memory\n");
0117         error = -ENOMEM;
0118         goto err_free_mem;
0119     }
0120 
0121     data->client = client;
0122     data->input_dev = input_dev;
0123 
0124     if (id->driver_data == MCS5000_TOUCHKEY) {
0125         data->chip.status_reg = MCS5000_TOUCHKEY_STATUS;
0126         data->chip.pressbit = MCS5000_TOUCHKEY_STATUS_PRESS;
0127         data->chip.baseval = MCS5000_TOUCHKEY_BASE_VAL;
0128         fw_reg = MCS5000_TOUCHKEY_FW;
0129     } else {
0130         data->chip.status_reg = MCS5080_TOUCHKEY_STATUS;
0131         data->chip.pressbit = MCS5080_TOUCHKEY_STATUS_PRESS;
0132         data->chip.press_invert = 1;
0133         data->chip.baseval = MCS5080_TOUCHKEY_BASE_VAL;
0134         fw_reg = MCS5080_TOUCHKEY_FW;
0135     }
0136 
0137     fw_ver = i2c_smbus_read_byte_data(client, fw_reg);
0138     if (fw_ver < 0) {
0139         error = fw_ver;
0140         dev_err(&client->dev, "i2c read error[%d]\n", error);
0141         goto err_free_mem;
0142     }
0143     dev_info(&client->dev, "Firmware version: %d\n", fw_ver);
0144 
0145     input_dev->name = "MELFAS MCS Touchkey";
0146     input_dev->id.bustype = BUS_I2C;
0147     input_dev->dev.parent = &client->dev;
0148     input_dev->evbit[0] = BIT_MASK(EV_KEY);
0149     if (!pdata->no_autorepeat)
0150         input_dev->evbit[0] |= BIT_MASK(EV_REP);
0151     input_dev->keycode = data->keycodes;
0152     input_dev->keycodesize = sizeof(data->keycodes[0]);
0153     input_dev->keycodemax = pdata->key_maxval + 1;
0154 
0155     for (i = 0; i < pdata->keymap_size; i++) {
0156         unsigned int val = MCS_KEY_VAL(pdata->keymap[i]);
0157         unsigned int code = MCS_KEY_CODE(pdata->keymap[i]);
0158 
0159         data->keycodes[val] = code;
0160         __set_bit(code, input_dev->keybit);
0161     }
0162 
0163     input_set_capability(input_dev, EV_MSC, MSC_SCAN);
0164     input_set_drvdata(input_dev, data);
0165 
0166     if (pdata->cfg_pin)
0167         pdata->cfg_pin();
0168 
0169     if (pdata->poweron) {
0170         data->poweron = pdata->poweron;
0171         data->poweron(true);
0172     }
0173 
0174     error = request_threaded_irq(client->irq, NULL, mcs_touchkey_interrupt,
0175                      IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
0176                      client->dev.driver->name, data);
0177     if (error) {
0178         dev_err(&client->dev, "Failed to register interrupt\n");
0179         goto err_free_mem;
0180     }
0181 
0182     error = input_register_device(input_dev);
0183     if (error)
0184         goto err_free_irq;
0185 
0186     i2c_set_clientdata(client, data);
0187     return 0;
0188 
0189 err_free_irq:
0190     free_irq(client->irq, data);
0191 err_free_mem:
0192     input_free_device(input_dev);
0193     kfree(data);
0194     return error;
0195 }
0196 
0197 static int mcs_touchkey_remove(struct i2c_client *client)
0198 {
0199     struct mcs_touchkey_data *data = i2c_get_clientdata(client);
0200 
0201     free_irq(client->irq, data);
0202     if (data->poweron)
0203         data->poweron(false);
0204     input_unregister_device(data->input_dev);
0205     kfree(data);
0206 
0207     return 0;
0208 }
0209 
0210 static void mcs_touchkey_shutdown(struct i2c_client *client)
0211 {
0212     struct mcs_touchkey_data *data = i2c_get_clientdata(client);
0213 
0214     if (data->poweron)
0215         data->poweron(false);
0216 }
0217 
0218 #ifdef CONFIG_PM_SLEEP
0219 static int mcs_touchkey_suspend(struct device *dev)
0220 {
0221     struct mcs_touchkey_data *data = dev_get_drvdata(dev);
0222     struct i2c_client *client = data->client;
0223 
0224     /* Disable the work */
0225     disable_irq(client->irq);
0226 
0227     /* Finally turn off the power */
0228     if (data->poweron)
0229         data->poweron(false);
0230 
0231     return 0;
0232 }
0233 
0234 static int mcs_touchkey_resume(struct device *dev)
0235 {
0236     struct mcs_touchkey_data *data = dev_get_drvdata(dev);
0237     struct i2c_client *client = data->client;
0238 
0239     /* Enable the device first */
0240     if (data->poweron)
0241         data->poweron(true);
0242 
0243     /* Enable irq again */
0244     enable_irq(client->irq);
0245 
0246     return 0;
0247 }
0248 #endif
0249 
0250 static SIMPLE_DEV_PM_OPS(mcs_touchkey_pm_ops,
0251              mcs_touchkey_suspend, mcs_touchkey_resume);
0252 
0253 static const struct i2c_device_id mcs_touchkey_id[] = {
0254     { "mcs5000_touchkey", MCS5000_TOUCHKEY },
0255     { "mcs5080_touchkey", MCS5080_TOUCHKEY },
0256     { }
0257 };
0258 MODULE_DEVICE_TABLE(i2c, mcs_touchkey_id);
0259 
0260 static struct i2c_driver mcs_touchkey_driver = {
0261     .driver = {
0262         .name   = "mcs_touchkey",
0263         .pm = &mcs_touchkey_pm_ops,
0264     },
0265     .probe      = mcs_touchkey_probe,
0266     .remove     = mcs_touchkey_remove,
0267     .shutdown       = mcs_touchkey_shutdown,
0268     .id_table   = mcs_touchkey_id,
0269 };
0270 
0271 module_i2c_driver(mcs_touchkey_driver);
0272 
0273 /* Module information */
0274 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
0275 MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>");
0276 MODULE_DESCRIPTION("Touchkey driver for MELFAS MCS5000/5080 controller");
0277 MODULE_LICENSE("GPL");