18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Atmel AT42QT1070 QTouch Sensor Controller 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2011 Atmel 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Authors: Bo Shen <voice.shen@atmel.com> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Base on AT42QT2160 driver by: 108c2ecf20Sopenharmony_ci * Raphael Derosso Pereira <raphaelpereira@gmail.com> 118c2ecf20Sopenharmony_ci * Copyright (C) 2009 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci#include <linux/kernel.h> 148c2ecf20Sopenharmony_ci#include <linux/module.h> 158c2ecf20Sopenharmony_ci#include <linux/i2c.h> 168c2ecf20Sopenharmony_ci#include <linux/input.h> 178c2ecf20Sopenharmony_ci#include <linux/slab.h> 188c2ecf20Sopenharmony_ci#include <linux/irq.h> 198c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 208c2ecf20Sopenharmony_ci#include <linux/jiffies.h> 218c2ecf20Sopenharmony_ci#include <linux/delay.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/* Address for each register */ 248c2ecf20Sopenharmony_ci#define CHIP_ID 0x00 258c2ecf20Sopenharmony_ci#define QT1070_CHIP_ID 0x2E 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define FW_VERSION 0x01 288c2ecf20Sopenharmony_ci#define QT1070_FW_VERSION 0x15 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define DET_STATUS 0x02 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define KEY_STATUS 0x03 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/* Calibrate */ 358c2ecf20Sopenharmony_ci#define CALIBRATE_CMD 0x38 368c2ecf20Sopenharmony_ci#define QT1070_CAL_TIME 200 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* Reset */ 398c2ecf20Sopenharmony_ci#define RESET 0x39 408c2ecf20Sopenharmony_ci#define QT1070_RESET_TIME 255 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* AT42QT1070 support up to 7 keys */ 438c2ecf20Sopenharmony_cistatic const unsigned short qt1070_key2code[] = { 448c2ecf20Sopenharmony_ci KEY_0, KEY_1, KEY_2, KEY_3, 458c2ecf20Sopenharmony_ci KEY_4, KEY_5, KEY_6, 468c2ecf20Sopenharmony_ci}; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistruct qt1070_data { 498c2ecf20Sopenharmony_ci struct i2c_client *client; 508c2ecf20Sopenharmony_ci struct input_dev *input; 518c2ecf20Sopenharmony_ci unsigned int irq; 528c2ecf20Sopenharmony_ci unsigned short keycodes[ARRAY_SIZE(qt1070_key2code)]; 538c2ecf20Sopenharmony_ci u8 last_keys; 548c2ecf20Sopenharmony_ci}; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic int qt1070_read(struct i2c_client *client, u8 reg) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci int ret; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci ret = i2c_smbus_read_byte_data(client, reg); 618c2ecf20Sopenharmony_ci if (ret < 0) 628c2ecf20Sopenharmony_ci dev_err(&client->dev, 638c2ecf20Sopenharmony_ci "can not read register, returned %d\n", ret); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci return ret; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic int qt1070_write(struct i2c_client *client, u8 reg, u8 data) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci int ret; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci ret = i2c_smbus_write_byte_data(client, reg, data); 738c2ecf20Sopenharmony_ci if (ret < 0) 748c2ecf20Sopenharmony_ci dev_err(&client->dev, 758c2ecf20Sopenharmony_ci "can not write register, returned %d\n", ret); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci return ret; 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic bool qt1070_identify(struct i2c_client *client) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci int id, ver; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci /* Read Chip ID */ 858c2ecf20Sopenharmony_ci id = qt1070_read(client, CHIP_ID); 868c2ecf20Sopenharmony_ci if (id != QT1070_CHIP_ID) { 878c2ecf20Sopenharmony_ci dev_err(&client->dev, "ID %d not supported\n", id); 888c2ecf20Sopenharmony_ci return false; 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci /* Read firmware version */ 928c2ecf20Sopenharmony_ci ver = qt1070_read(client, FW_VERSION); 938c2ecf20Sopenharmony_ci if (ver < 0) { 948c2ecf20Sopenharmony_ci dev_err(&client->dev, "could not read the firmware version\n"); 958c2ecf20Sopenharmony_ci return false; 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci dev_info(&client->dev, "AT42QT1070 firmware version %x\n", ver); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci return true; 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic irqreturn_t qt1070_interrupt(int irq, void *dev_id) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci struct qt1070_data *data = dev_id; 1068c2ecf20Sopenharmony_ci struct i2c_client *client = data->client; 1078c2ecf20Sopenharmony_ci struct input_dev *input = data->input; 1088c2ecf20Sopenharmony_ci int i; 1098c2ecf20Sopenharmony_ci u8 new_keys, keyval, mask = 0x01; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci /* Read the detected status register, thus clearing interrupt */ 1128c2ecf20Sopenharmony_ci qt1070_read(client, DET_STATUS); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci /* Read which key changed */ 1158c2ecf20Sopenharmony_ci new_keys = qt1070_read(client, KEY_STATUS); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(qt1070_key2code); i++) { 1188c2ecf20Sopenharmony_ci keyval = new_keys & mask; 1198c2ecf20Sopenharmony_ci if ((data->last_keys & mask) != keyval) 1208c2ecf20Sopenharmony_ci input_report_key(input, data->keycodes[i], keyval); 1218c2ecf20Sopenharmony_ci mask <<= 1; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci input_sync(input); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci data->last_keys = new_keys; 1268c2ecf20Sopenharmony_ci return IRQ_HANDLED; 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistatic int qt1070_probe(struct i2c_client *client, 1308c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci struct qt1070_data *data; 1338c2ecf20Sopenharmony_ci struct input_dev *input; 1348c2ecf20Sopenharmony_ci int i; 1358c2ecf20Sopenharmony_ci int err; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci err = i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE); 1388c2ecf20Sopenharmony_ci if (!err) { 1398c2ecf20Sopenharmony_ci dev_err(&client->dev, "%s adapter not supported\n", 1408c2ecf20Sopenharmony_ci dev_driver_string(&client->adapter->dev)); 1418c2ecf20Sopenharmony_ci return -ENODEV; 1428c2ecf20Sopenharmony_ci } 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci if (!client->irq) { 1458c2ecf20Sopenharmony_ci dev_err(&client->dev, "please assign the irq to this device\n"); 1468c2ecf20Sopenharmony_ci return -EINVAL; 1478c2ecf20Sopenharmony_ci } 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci /* Identify the qt1070 chip */ 1508c2ecf20Sopenharmony_ci if (!qt1070_identify(client)) 1518c2ecf20Sopenharmony_ci return -ENODEV; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci data = kzalloc(sizeof(struct qt1070_data), GFP_KERNEL); 1548c2ecf20Sopenharmony_ci input = input_allocate_device(); 1558c2ecf20Sopenharmony_ci if (!data || !input) { 1568c2ecf20Sopenharmony_ci dev_err(&client->dev, "insufficient memory\n"); 1578c2ecf20Sopenharmony_ci err = -ENOMEM; 1588c2ecf20Sopenharmony_ci goto err_free_mem; 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci data->client = client; 1628c2ecf20Sopenharmony_ci data->input = input; 1638c2ecf20Sopenharmony_ci data->irq = client->irq; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci input->name = "AT42QT1070 QTouch Sensor"; 1668c2ecf20Sopenharmony_ci input->dev.parent = &client->dev; 1678c2ecf20Sopenharmony_ci input->id.bustype = BUS_I2C; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci /* Add the keycode */ 1708c2ecf20Sopenharmony_ci input->keycode = data->keycodes; 1718c2ecf20Sopenharmony_ci input->keycodesize = sizeof(data->keycodes[0]); 1728c2ecf20Sopenharmony_ci input->keycodemax = ARRAY_SIZE(qt1070_key2code); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci __set_bit(EV_KEY, input->evbit); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(qt1070_key2code); i++) { 1778c2ecf20Sopenharmony_ci data->keycodes[i] = qt1070_key2code[i]; 1788c2ecf20Sopenharmony_ci __set_bit(qt1070_key2code[i], input->keybit); 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci /* Calibrate device */ 1828c2ecf20Sopenharmony_ci qt1070_write(client, CALIBRATE_CMD, 1); 1838c2ecf20Sopenharmony_ci msleep(QT1070_CAL_TIME); 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci /* Soft reset */ 1868c2ecf20Sopenharmony_ci qt1070_write(client, RESET, 1); 1878c2ecf20Sopenharmony_ci msleep(QT1070_RESET_TIME); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci err = request_threaded_irq(client->irq, NULL, qt1070_interrupt, 1908c2ecf20Sopenharmony_ci IRQF_TRIGGER_NONE | IRQF_ONESHOT, 1918c2ecf20Sopenharmony_ci client->dev.driver->name, data); 1928c2ecf20Sopenharmony_ci if (err) { 1938c2ecf20Sopenharmony_ci dev_err(&client->dev, "fail to request irq\n"); 1948c2ecf20Sopenharmony_ci goto err_free_mem; 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci /* Register the input device */ 1988c2ecf20Sopenharmony_ci err = input_register_device(data->input); 1998c2ecf20Sopenharmony_ci if (err) { 2008c2ecf20Sopenharmony_ci dev_err(&client->dev, "Failed to register input device\n"); 2018c2ecf20Sopenharmony_ci goto err_free_irq; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci i2c_set_clientdata(client, data); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci /* Read to clear the chang line */ 2078c2ecf20Sopenharmony_ci qt1070_read(client, DET_STATUS); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci return 0; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_cierr_free_irq: 2128c2ecf20Sopenharmony_ci free_irq(client->irq, data); 2138c2ecf20Sopenharmony_cierr_free_mem: 2148c2ecf20Sopenharmony_ci input_free_device(input); 2158c2ecf20Sopenharmony_ci kfree(data); 2168c2ecf20Sopenharmony_ci return err; 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic int qt1070_remove(struct i2c_client *client) 2208c2ecf20Sopenharmony_ci{ 2218c2ecf20Sopenharmony_ci struct qt1070_data *data = i2c_get_clientdata(client); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci /* Release IRQ */ 2248c2ecf20Sopenharmony_ci free_irq(client->irq, data); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci input_unregister_device(data->input); 2278c2ecf20Sopenharmony_ci kfree(data); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci return 0; 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 2338c2ecf20Sopenharmony_cistatic int qt1070_suspend(struct device *dev) 2348c2ecf20Sopenharmony_ci{ 2358c2ecf20Sopenharmony_ci struct i2c_client *client = to_i2c_client(dev); 2368c2ecf20Sopenharmony_ci struct qt1070_data *data = i2c_get_clientdata(client); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci if (device_may_wakeup(dev)) 2398c2ecf20Sopenharmony_ci enable_irq_wake(data->irq); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci return 0; 2428c2ecf20Sopenharmony_ci} 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_cistatic int qt1070_resume(struct device *dev) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci struct i2c_client *client = to_i2c_client(dev); 2478c2ecf20Sopenharmony_ci struct qt1070_data *data = i2c_get_clientdata(client); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci if (device_may_wakeup(dev)) 2508c2ecf20Sopenharmony_ci disable_irq_wake(data->irq); 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci return 0; 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci#endif 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(qt1070_pm_ops, qt1070_suspend, qt1070_resume); 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_cistatic const struct i2c_device_id qt1070_id[] = { 2598c2ecf20Sopenharmony_ci { "qt1070", 0 }, 2608c2ecf20Sopenharmony_ci { }, 2618c2ecf20Sopenharmony_ci}; 2628c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, qt1070_id); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 2658c2ecf20Sopenharmony_cistatic const struct of_device_id qt1070_of_match[] = { 2668c2ecf20Sopenharmony_ci { .compatible = "qt1070", }, 2678c2ecf20Sopenharmony_ci { }, 2688c2ecf20Sopenharmony_ci}; 2698c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, qt1070_of_match); 2708c2ecf20Sopenharmony_ci#endif 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_cistatic struct i2c_driver qt1070_driver = { 2738c2ecf20Sopenharmony_ci .driver = { 2748c2ecf20Sopenharmony_ci .name = "qt1070", 2758c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(qt1070_of_match), 2768c2ecf20Sopenharmony_ci .pm = &qt1070_pm_ops, 2778c2ecf20Sopenharmony_ci }, 2788c2ecf20Sopenharmony_ci .id_table = qt1070_id, 2798c2ecf20Sopenharmony_ci .probe = qt1070_probe, 2808c2ecf20Sopenharmony_ci .remove = qt1070_remove, 2818c2ecf20Sopenharmony_ci}; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cimodule_i2c_driver(qt1070_driver); 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ciMODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>"); 2868c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Driver for AT42QT1070 QTouch sensor"); 2878c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 288