// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) IBM Corporation 2020
 */

#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/limits.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/spinlock.h>

#define DEVICE_NAME		"ibm-panel"
#define PANEL_KEYCODES_COUNT	3

struct ibm_panel {
	u8 idx;
	u8 command[11];
	u32 keycodes[PANEL_KEYCODES_COUNT];
	spinlock_t lock;	/* protects writes to idx and command */
	struct input_dev *input;
};

static u8 ibm_panel_calculate_checksum(struct ibm_panel *panel)
{
	u8 chksum;
	u16 sum = 0;
	unsigned int i;

	for (i = 0; i < sizeof(panel->command) - 1; ++i) {
		sum += panel->command[i];
		if (sum & 0xff00) {
			sum &= 0xff;
			sum++;
		}
	}

	chksum = sum & 0xff;
	chksum = ~chksum;
	chksum++;

	return chksum;
}

static void ibm_panel_process_command(struct ibm_panel *panel)
{
	u8 button;
	u8 chksum;

	if (panel->command[0] != 0xff && panel->command[1] != 0xf0) {
		dev_dbg(&panel->input->dev, "command invalid: %02x %02x\n",
			panel->command[0], panel->command[1]);
		return;
	}

	chksum = ibm_panel_calculate_checksum(panel);
	if (chksum != panel->command[sizeof(panel->command) - 1]) {
		dev_dbg(&panel->input->dev,
			"command failed checksum: %u != %u\n", chksum,
			panel->command[sizeof(panel->command) - 1]);
		return;
	}

	button = panel->command[2] & 0xf;
	if (button < PANEL_KEYCODES_COUNT) {
		input_report_key(panel->input, panel->keycodes[button],
				 !(panel->command[2] & 0x80));
		input_sync(panel->input);
	} else {
		dev_dbg(&panel->input->dev, "unknown button %u\n",
			button);
	}
}

static int ibm_panel_i2c_slave_cb(struct i2c_client *client,
				  enum i2c_slave_event event, u8 *val)
{
	unsigned long flags;
	struct ibm_panel *panel = i2c_get_clientdata(client);

	dev_dbg(&panel->input->dev, "event: %u data: %02x\n", event, *val);

	spin_lock_irqsave(&panel->lock, flags);

	switch (event) {
	case I2C_SLAVE_STOP:
		if (panel->idx == sizeof(panel->command))
			ibm_panel_process_command(panel);
		else
			dev_dbg(&panel->input->dev,
				"command incorrect size %u\n", panel->idx);
		fallthrough;
	case I2C_SLAVE_WRITE_REQUESTED:
		panel->idx = 0;
		break;
	case I2C_SLAVE_WRITE_RECEIVED:
		if (panel->idx < sizeof(panel->command))
			panel->command[panel->idx++] = *val;
		else
			/*
			 * The command is too long and therefore invalid, so set the index
			 * to it's largest possible value. When a STOP is finally received,
			 * the command will be rejected upon processing.
			 */
			panel->idx = U8_MAX;
		break;
	case I2C_SLAVE_READ_REQUESTED:
	case I2C_SLAVE_READ_PROCESSED:
		*val = 0xff;
		break;
	default:
		break;
	}

	spin_unlock_irqrestore(&panel->lock, flags);

	return 0;
}

static int ibm_panel_probe(struct i2c_client *client)
{
	struct ibm_panel *panel;
	int i;
	int error;

	panel = devm_kzalloc(&client->dev, sizeof(*panel), GFP_KERNEL);
	if (!panel)
		return -ENOMEM;

	spin_lock_init(&panel->lock);

	panel->input = devm_input_allocate_device(&client->dev);
	if (!panel->input)
		return -ENOMEM;

	panel->input->name = client->name;
	panel->input->id.bustype = BUS_I2C;

	error = device_property_read_u32_array(&client->dev,
					       "linux,keycodes",
					       panel->keycodes,
					       PANEL_KEYCODES_COUNT);
	if (error) {
		/*
		 * Use gamepad buttons as defaults for compatibility with
		 * existing applications.
		 */
		panel->keycodes[0] = BTN_NORTH;
		panel->keycodes[1] = BTN_SOUTH;
		panel->keycodes[2] = BTN_SELECT;
	}

	for (i = 0; i < PANEL_KEYCODES_COUNT; ++i)
		input_set_capability(panel->input, EV_KEY, panel->keycodes[i]);

	error = input_register_device(panel->input);
	if (error) {
		dev_err(&client->dev,
			"Failed to register input device: %d\n", error);
		return error;
	}

	i2c_set_clientdata(client, panel);
	error = i2c_slave_register(client, ibm_panel_i2c_slave_cb);
	if (error) {
		dev_err(&client->dev,
			"Failed to register as i2c slave: %d\n", error);
		return error;
	}

	return 0;
}

static void ibm_panel_remove(struct i2c_client *client)
{
	i2c_slave_unregister(client);
}

static const struct of_device_id ibm_panel_match[] = {
	{ .compatible = "ibm,op-panel" },
	{ }
};
MODULE_DEVICE_TABLE(of, ibm_panel_match);

static struct i2c_driver ibm_panel_driver = {
	.driver = {
		.name = DEVICE_NAME,
		.of_match_table = ibm_panel_match,
	},
	.probe_new = ibm_panel_probe,
	.remove = ibm_panel_remove,
};
module_i2c_driver(ibm_panel_driver);

MODULE_AUTHOR("Eddie James <eajames@linux.ibm.com>");
MODULE_DESCRIPTION("IBM Operation Panel Driver");
MODULE_LICENSE("GPL");
