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