1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2023 Anshul Dalal <anshulusr@gmail.com>
4 *
5 * Driver for Adafruit Mini I2C Gamepad
6 *
7 * Based on the work of:
8 *	Oleh Kravchenko (Sparkfun Qwiic Joystick driver)
9 *
10 * Datasheet: https://cdn-learn.adafruit.com/downloads/pdf/gamepad-qt.pdf
11 * Product page: https://www.adafruit.com/product/5743
12 * Firmware and hardware sources: https://github.com/adafruit/Adafruit_Seesaw
13 *
14 * TODO:
15 *	- Add interrupt support
16 */
17
18#include <asm/unaligned.h>
19#include <linux/bits.h>
20#include <linux/delay.h>
21#include <linux/i2c.h>
22#include <linux/input.h>
23#include <linux/input/sparse-keymap.h>
24#include <linux/kernel.h>
25#include <linux/module.h>
26
27#define SEESAW_DEVICE_NAME		"seesaw-gamepad"
28
29#define SEESAW_ADC_BASE			0x0900
30
31#define SEESAW_GPIO_DIRCLR_BULK		0x0103
32#define SEESAW_GPIO_BULK		0x0104
33#define SEESAW_GPIO_BULK_SET		0x0105
34#define SEESAW_GPIO_PULLENSET		0x010b
35
36#define SEESAW_STATUS_HW_ID		0x0001
37#define SEESAW_STATUS_SWRST		0x007f
38
39#define SEESAW_ADC_OFFSET		0x07
40
41#define SEESAW_BUTTON_A			0x05
42#define SEESAW_BUTTON_B			0x01
43#define SEESAW_BUTTON_X			0x06
44#define SEESAW_BUTTON_Y			0x02
45#define SEESAW_BUTTON_START		0x10
46#define SEESAW_BUTTON_SELECT		0x00
47
48#define SEESAW_ANALOG_X			0x0e
49#define SEESAW_ANALOG_Y			0x0f
50
51#define SEESAW_JOYSTICK_MAX_AXIS	1023
52#define SEESAW_JOYSTICK_FUZZ		2
53#define SEESAW_JOYSTICK_FLAT		4
54
55#define SEESAW_GAMEPAD_POLL_INTERVAL_MS	16
56#define SEESAW_GAMEPAD_POLL_MIN		8
57#define SEESAW_GAMEPAD_POLL_MAX		32
58
59static const unsigned long SEESAW_BUTTON_MASK =
60	BIT(SEESAW_BUTTON_A) | BIT(SEESAW_BUTTON_B) | BIT(SEESAW_BUTTON_X) |
61	BIT(SEESAW_BUTTON_Y) | BIT(SEESAW_BUTTON_START) |
62	BIT(SEESAW_BUTTON_SELECT);
63
64struct seesaw_gamepad {
65	struct input_dev *input_dev;
66	struct i2c_client *i2c_client;
67};
68
69struct seesaw_data {
70	u16 x;
71	u16 y;
72	u32 button_state;
73};
74
75static const struct key_entry seesaw_buttons_new[] = {
76	{ KE_KEY, SEESAW_BUTTON_A, .keycode = BTN_SOUTH },
77	{ KE_KEY, SEESAW_BUTTON_B, .keycode = BTN_EAST },
78	{ KE_KEY, SEESAW_BUTTON_X, .keycode = BTN_NORTH },
79	{ KE_KEY, SEESAW_BUTTON_Y, .keycode = BTN_WEST },
80	{ KE_KEY, SEESAW_BUTTON_START, .keycode = BTN_START },
81	{ KE_KEY, SEESAW_BUTTON_SELECT, .keycode = BTN_SELECT },
82	{ KE_END, 0 }
83};
84
85static int seesaw_register_read(struct i2c_client *client, u16 reg, void *buf,
86				int count)
87{
88	__be16 register_buf = cpu_to_be16(reg);
89	struct i2c_msg message_buf[2] = {
90		{
91			.addr = client->addr,
92			.flags = client->flags,
93			.len = sizeof(register_buf),
94			.buf = (u8 *)&register_buf,
95		},
96		{
97			.addr = client->addr,
98			.flags = client->flags | I2C_M_RD,
99			.len = count,
100			.buf = (u8 *)buf,
101		},
102	};
103	int ret;
104
105	ret = i2c_transfer(client->adapter, message_buf,
106			   ARRAY_SIZE(message_buf));
107	if (ret < 0)
108		return ret;
109
110	return 0;
111}
112
113static int seesaw_register_write_u8(struct i2c_client *client, u16 reg,
114				    u8 value)
115{
116	u8 write_buf[sizeof(reg) + sizeof(value)];
117	int ret;
118
119	put_unaligned_be16(reg, write_buf);
120	write_buf[sizeof(reg)] = value;
121
122	ret = i2c_master_send(client, write_buf, sizeof(write_buf));
123	if (ret < 0)
124		return ret;
125
126	return 0;
127}
128
129static int seesaw_register_write_u32(struct i2c_client *client, u16 reg,
130				     u32 value)
131{
132	u8 write_buf[sizeof(reg) + sizeof(value)];
133	int ret;
134
135	put_unaligned_be16(reg, write_buf);
136	put_unaligned_be32(value, write_buf + sizeof(reg));
137	ret = i2c_master_send(client, write_buf, sizeof(write_buf));
138	if (ret < 0)
139		return ret;
140
141	return 0;
142}
143
144static int seesaw_read_data(struct i2c_client *client, struct seesaw_data *data)
145{
146	__be16 adc_data;
147	__be32 read_buf;
148	int err;
149
150	err = seesaw_register_read(client, SEESAW_GPIO_BULK,
151				   &read_buf, sizeof(read_buf));
152	if (err)
153		return err;
154
155	data->button_state = ~be32_to_cpu(read_buf);
156
157	err = seesaw_register_read(client,
158				   SEESAW_ADC_BASE |
159					(SEESAW_ADC_OFFSET + SEESAW_ANALOG_X),
160				   &adc_data, sizeof(adc_data));
161	if (err)
162		return err;
163	/*
164	 * ADC reads left as max and right as 0, must be reversed since kernel
165	 * expects reports in opposite order.
166	 */
167	data->x = SEESAW_JOYSTICK_MAX_AXIS - be16_to_cpu(adc_data);
168
169	err = seesaw_register_read(client,
170				   SEESAW_ADC_BASE |
171					(SEESAW_ADC_OFFSET + SEESAW_ANALOG_Y),
172				   &adc_data, sizeof(adc_data));
173	if (err)
174		return err;
175
176	data->y = be16_to_cpu(adc_data);
177
178	return 0;
179}
180
181static void seesaw_poll(struct input_dev *input)
182{
183	struct seesaw_gamepad *private = input_get_drvdata(input);
184	struct seesaw_data data;
185	int err, i;
186
187	err = seesaw_read_data(private->i2c_client, &data);
188	if (err) {
189		dev_err_ratelimited(&input->dev,
190				    "failed to read joystick state: %d\n", err);
191		return;
192	}
193
194	input_report_abs(input, ABS_X, data.x);
195	input_report_abs(input, ABS_Y, data.y);
196
197	for_each_set_bit(i, &SEESAW_BUTTON_MASK,
198			 BITS_PER_TYPE(SEESAW_BUTTON_MASK)) {
199		if (!sparse_keymap_report_event(input, i,
200						data.button_state & BIT(i),
201						false))
202			dev_err_ratelimited(&input->dev,
203					    "failed to report keymap event");
204	}
205
206	input_sync(input);
207}
208
209static int seesaw_probe(struct i2c_client *client)
210{
211	struct seesaw_gamepad *seesaw;
212	u8 hardware_id;
213	int err;
214
215	err = seesaw_register_write_u8(client, SEESAW_STATUS_SWRST, 0xFF);
216	if (err)
217		return err;
218
219	/* Wait for the registers to reset before proceeding */
220	usleep_range(10000, 15000);
221
222	seesaw = devm_kzalloc(&client->dev, sizeof(*seesaw), GFP_KERNEL);
223	if (!seesaw)
224		return -ENOMEM;
225
226	err = seesaw_register_read(client, SEESAW_STATUS_HW_ID,
227				   &hardware_id, sizeof(hardware_id));
228	if (err)
229		return err;
230
231	dev_dbg(&client->dev, "Adafruit Seesaw Gamepad, Hardware ID: %02x\n",
232		hardware_id);
233
234	/* Set Pin Mode to input and enable pull-up resistors */
235	err = seesaw_register_write_u32(client, SEESAW_GPIO_DIRCLR_BULK,
236					SEESAW_BUTTON_MASK);
237	if (err)
238		return err;
239	err = seesaw_register_write_u32(client, SEESAW_GPIO_PULLENSET,
240					SEESAW_BUTTON_MASK);
241	if (err)
242		return err;
243	err = seesaw_register_write_u32(client, SEESAW_GPIO_BULK_SET,
244					SEESAW_BUTTON_MASK);
245	if (err)
246		return err;
247
248	seesaw->i2c_client = client;
249	seesaw->input_dev = devm_input_allocate_device(&client->dev);
250	if (!seesaw->input_dev)
251		return -ENOMEM;
252
253	seesaw->input_dev->id.bustype = BUS_I2C;
254	seesaw->input_dev->name = "Adafruit Seesaw Gamepad";
255	seesaw->input_dev->phys = "i2c/" SEESAW_DEVICE_NAME;
256	input_set_drvdata(seesaw->input_dev, seesaw);
257	input_set_abs_params(seesaw->input_dev, ABS_X,
258			     0, SEESAW_JOYSTICK_MAX_AXIS,
259			     SEESAW_JOYSTICK_FUZZ, SEESAW_JOYSTICK_FLAT);
260	input_set_abs_params(seesaw->input_dev, ABS_Y,
261			     0, SEESAW_JOYSTICK_MAX_AXIS,
262			     SEESAW_JOYSTICK_FUZZ, SEESAW_JOYSTICK_FLAT);
263
264	err = sparse_keymap_setup(seesaw->input_dev, seesaw_buttons_new, NULL);
265	if (err) {
266		dev_err(&client->dev,
267			"failed to set up input device keymap: %d\n", err);
268		return err;
269	}
270
271	err = input_setup_polling(seesaw->input_dev, seesaw_poll);
272	if (err) {
273		dev_err(&client->dev, "failed to set up polling: %d\n", err);
274		return err;
275	}
276
277	input_set_poll_interval(seesaw->input_dev,
278				SEESAW_GAMEPAD_POLL_INTERVAL_MS);
279	input_set_max_poll_interval(seesaw->input_dev, SEESAW_GAMEPAD_POLL_MAX);
280	input_set_min_poll_interval(seesaw->input_dev, SEESAW_GAMEPAD_POLL_MIN);
281
282	err = input_register_device(seesaw->input_dev);
283	if (err) {
284		dev_err(&client->dev, "failed to register joystick: %d\n", err);
285		return err;
286	}
287
288	return 0;
289}
290
291static const struct i2c_device_id seesaw_id_table[] = {
292	{ SEESAW_DEVICE_NAME },
293	{ /* Sentinel */ }
294};
295MODULE_DEVICE_TABLE(i2c, seesaw_id_table);
296
297static const struct of_device_id seesaw_of_table[] = {
298	{ .compatible = "adafruit,seesaw-gamepad"},
299	{ /* Sentinel */ }
300};
301MODULE_DEVICE_TABLE(of, seesaw_of_table);
302
303static struct i2c_driver seesaw_driver = {
304	.driver = {
305		.name = SEESAW_DEVICE_NAME,
306		.of_match_table = seesaw_of_table,
307	},
308	.id_table = seesaw_id_table,
309	.probe = seesaw_probe,
310};
311module_i2c_driver(seesaw_driver);
312
313MODULE_AUTHOR("Anshul Dalal <anshulusr@gmail.com>");
314MODULE_DESCRIPTION("Adafruit Mini I2C Gamepad driver");
315MODULE_LICENSE("GPL");
316