// SPDX-License-Identifier: GPL-2.0-only
/*
 * I2C Link Layer for ST21NFCA HCI based Driver
 * Copyright (C) 2014  STMicroelectronics SAS. All rights reserved.
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/crc-ccitt.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/gpio/consumer.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/acpi.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/nfc.h>
#include <linux/firmware.h>

#include <net/nfc/hci.h>
#include <net/nfc/llc.h>
#include <net/nfc/nfc.h>

#include "st21nfca.h"

/*
 * Every frame starts with ST21NFCA_SOF_EOF and ends with ST21NFCA_SOF_EOF.
 * Because ST21NFCA_SOF_EOF is a possible data value, there is a mecanism
 * called byte stuffing has been introduced.
 *
 * if byte == ST21NFCA_SOF_EOF or ST21NFCA_ESCAPE_BYTE_STUFFING
 * - insert ST21NFCA_ESCAPE_BYTE_STUFFING (escape byte)
 * - xor byte with ST21NFCA_BYTE_STUFFING_MASK
 */
#define ST21NFCA_SOF_EOF		0x7e
#define ST21NFCA_BYTE_STUFFING_MASK	0x20
#define ST21NFCA_ESCAPE_BYTE_STUFFING	0x7d

/* SOF + 00 */
#define ST21NFCA_FRAME_HEADROOM			2

/* 2 bytes crc + EOF */
#define ST21NFCA_FRAME_TAILROOM 3
#define IS_START_OF_FRAME(buf) (buf[0] == ST21NFCA_SOF_EOF && \
				buf[1] == 0)

#define ST21NFCA_HCI_DRIVER_NAME "st21nfca_hci"
#define ST21NFCA_HCI_I2C_DRIVER_NAME "st21nfca_hci_i2c"

struct st21nfca_i2c_phy {
	struct i2c_client *i2c_dev;
	struct nfc_hci_dev *hdev;

	struct gpio_desc *gpiod_ena;
	struct st21nfca_se_status se_status;

	struct sk_buff *pending_skb;
	int current_read_len;
	/*
	 * crc might have fail because i2c macro
	 * is disable due to other interface activity
	 */
	int crc_trials;

	int powered;
	int run_mode;

	/*
	 * < 0 if hardware error occured (e.g. i2c err)
	 * and prevents normal operation.
	 */
	int hard_fault;
	struct mutex phy_lock;
};

static const u8 len_seq[] = { 16, 24, 12, 29 };
static const u16 wait_tab[] = { 2, 3, 5, 15, 20, 40};

#define I2C_DUMP_SKB(info, skb)					\
do {								\
	pr_debug("%s:\n", info);				\
	print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET,	\
		       16, 1, (skb)->data, (skb)->len, 0);	\
} while (0)

/*
 * In order to get the CLF in a known state we generate an internal reboot
 * using a proprietary command.
 * Once the reboot is completed, we expect to receive a ST21NFCA_SOF_EOF
 * fill buffer.
 */
static int st21nfca_hci_platform_init(struct st21nfca_i2c_phy *phy)
{
	u16 wait_reboot[] = { 50, 300, 1000 };
	char reboot_cmd[] = { 0x7E, 0x66, 0x48, 0xF6, 0x7E };
	u8 tmp[ST21NFCA_HCI_LLC_MAX_SIZE];
	int i, r = -1;

	for (i = 0; i < ARRAY_SIZE(wait_reboot) && r < 0; i++) {
		r = i2c_master_send(phy->i2c_dev, reboot_cmd,
				    sizeof(reboot_cmd));
		if (r < 0)
			msleep(wait_reboot[i]);
	}
	if (r < 0)
		return r;

	/* CLF is spending about 20ms to do an internal reboot */
	msleep(20);
	r = -1;
	for (i = 0; i < ARRAY_SIZE(wait_reboot) && r < 0; i++) {
		r = i2c_master_recv(phy->i2c_dev, tmp,
				    ST21NFCA_HCI_LLC_MAX_SIZE);
		if (r < 0)
			msleep(wait_reboot[i]);
	}
	if (r < 0)
		return r;

	for (i = 0; i < ST21NFCA_HCI_LLC_MAX_SIZE &&
		tmp[i] == ST21NFCA_SOF_EOF; i++)
		;

	if (r != ST21NFCA_HCI_LLC_MAX_SIZE)
		return -ENODEV;

	usleep_range(1000, 1500);
	return 0;
}

static int st21nfca_hci_i2c_enable(void *phy_id)
{
	struct st21nfca_i2c_phy *phy = phy_id;

	gpiod_set_value(phy->gpiod_ena, 1);
	phy->powered = 1;
	phy->run_mode = ST21NFCA_HCI_MODE;

	usleep_range(10000, 15000);

	return 0;
}

static void st21nfca_hci_i2c_disable(void *phy_id)
{
	struct st21nfca_i2c_phy *phy = phy_id;

	gpiod_set_value(phy->gpiod_ena, 0);

	phy->powered = 0;
}

static void st21nfca_hci_add_len_crc(struct sk_buff *skb)
{
	u16 crc;
	u8 tmp;

	*(u8 *)skb_push(skb, 1) = 0;

	crc = crc_ccitt(0xffff, skb->data, skb->len);
	crc = ~crc;

	tmp = crc & 0x00ff;
	skb_put_u8(skb, tmp);

	tmp = (crc >> 8) & 0x00ff;
	skb_put_u8(skb, tmp);
}

static void st21nfca_hci_remove_len_crc(struct sk_buff *skb)
{
	skb_pull(skb, ST21NFCA_FRAME_HEADROOM);
	skb_trim(skb, skb->len - ST21NFCA_FRAME_TAILROOM);
}

/*
 * Writing a frame must not return the number of written bytes.
 * It must return either zero for success, or <0 for error.
 * In addition, it must not alter the skb
 */
static int st21nfca_hci_i2c_write(void *phy_id, struct sk_buff *skb)
{
	int r = -1, i, j;
	struct st21nfca_i2c_phy *phy = phy_id;
	struct i2c_client *client = phy->i2c_dev;
	u8 tmp[ST21NFCA_HCI_LLC_MAX_SIZE * 2];

	I2C_DUMP_SKB("st21nfca_hci_i2c_write", skb);

	if (phy->hard_fault != 0)
		return phy->hard_fault;

	/*
	 * Compute CRC before byte stuffing computation on frame
	 * Note st21nfca_hci_add_len_crc is doing a byte stuffing
	 * on its own value
	 */
	st21nfca_hci_add_len_crc(skb);

	/* add ST21NFCA_SOF_EOF on tail */
	skb_put_u8(skb, ST21NFCA_SOF_EOF);
	/* add ST21NFCA_SOF_EOF on head */
	*(u8 *)skb_push(skb, 1) = ST21NFCA_SOF_EOF;

	/*
	 * Compute byte stuffing
	 * if byte == ST21NFCA_SOF_EOF or ST21NFCA_ESCAPE_BYTE_STUFFING
	 * insert ST21NFCA_ESCAPE_BYTE_STUFFING (escape byte)
	 * xor byte with ST21NFCA_BYTE_STUFFING_MASK
	 */
	tmp[0] = skb->data[0];
	for (i = 1, j = 1; i < skb->len - 1; i++, j++) {
		if (skb->data[i] == ST21NFCA_SOF_EOF
		    || skb->data[i] == ST21NFCA_ESCAPE_BYTE_STUFFING) {
			tmp[j] = ST21NFCA_ESCAPE_BYTE_STUFFING;
			j++;
			tmp[j] = skb->data[i] ^ ST21NFCA_BYTE_STUFFING_MASK;
		} else {
			tmp[j] = skb->data[i];
		}
	}
	tmp[j] = skb->data[i];
	j++;

	/*
	 * Manage sleep mode
	 * Try 3 times to send data with delay between each
	 */
	mutex_lock(&phy->phy_lock);
	for (i = 0; i < ARRAY_SIZE(wait_tab) && r < 0; i++) {
		r = i2c_master_send(client, tmp, j);
		if (r < 0)
			msleep(wait_tab[i]);
	}
	mutex_unlock(&phy->phy_lock);

	if (r >= 0) {
		if (r != j)
			r = -EREMOTEIO;
		else
			r = 0;
	}

	st21nfca_hci_remove_len_crc(skb);

	return r;
}

static int get_frame_size(u8 *buf, int buflen)
{
	int len = 0;

	if (buf[len + 1] == ST21NFCA_SOF_EOF)
		return 0;

	for (len = 1; len < buflen && buf[len] != ST21NFCA_SOF_EOF; len++)
		;

	return len;
}

static int check_crc(u8 *buf, int buflen)
{
	u16 crc;

	crc = crc_ccitt(0xffff, buf, buflen - 2);
	crc = ~crc;

	if (buf[buflen - 2] != (crc & 0xff) || buf[buflen - 1] != (crc >> 8)) {
		pr_err(ST21NFCA_HCI_DRIVER_NAME
		       ": CRC error 0x%x != 0x%x 0x%x\n", crc, buf[buflen - 1],
		       buf[buflen - 2]);

		pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__);
		print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE,
			       16, 2, buf, buflen, false);
		return -EPERM;
	}
	return 0;
}

/*
 * Prepare received data for upper layer.
 * Received data include byte stuffing, crc and sof/eof
 * which is not usable by hci part.
 * returns:
 * frame size without sof/eof, header and byte stuffing
 * -EBADMSG : frame was incorrect and discarded
 */
static int st21nfca_hci_i2c_repack(struct sk_buff *skb)
{
	int i, j, r, size;

	if (skb->len < 1 || (skb->len > 1 && skb->data[1] != 0))
		return -EBADMSG;

	size = get_frame_size(skb->data, skb->len);
	if (size > 0) {
		skb_trim(skb, size);
		/* remove ST21NFCA byte stuffing for upper layer */
		for (i = 1, j = 0; i < skb->len; i++) {
			if (skb->data[i + j] ==
					(u8) ST21NFCA_ESCAPE_BYTE_STUFFING) {
				skb->data[i] = skb->data[i + j + 1]
						| ST21NFCA_BYTE_STUFFING_MASK;
				i++;
				j++;
			}
			skb->data[i] = skb->data[i + j];
		}
		/* remove byte stuffing useless byte */
		skb_trim(skb, i - j);
		/* remove ST21NFCA_SOF_EOF from head */
		skb_pull(skb, 1);

		r = check_crc(skb->data, skb->len);
		if (r != 0) {
			i = 0;
			return -EBADMSG;
		}

		/* remove headbyte */
		skb_pull(skb, 1);
		/* remove crc. Byte Stuffing is already removed here */
		skb_trim(skb, skb->len - 2);
		return skb->len;
	}
	return 0;
}

/*
 * Reads an shdlc frame and returns it in a newly allocated sk_buff. Guarantees
 * that i2c bus will be flushed and that next read will start on a new frame.
 * returned skb contains only LLC header and payload.
 * returns:
 * frame size : if received frame is complete (find ST21NFCA_SOF_EOF at
 * end of read)
 * -EAGAIN : if received frame is incomplete (not find ST21NFCA_SOF_EOF
 * at end of read)
 * -EREMOTEIO : i2c read error (fatal)
 * -EBADMSG : frame was incorrect and discarded
 * (value returned from st21nfca_hci_i2c_repack)
 * -EIO : if no ST21NFCA_SOF_EOF is found after reaching
 * the read length end sequence
 */
static int st21nfca_hci_i2c_read(struct st21nfca_i2c_phy *phy,
				 struct sk_buff *skb)
{
	int r, i;
	u8 len;
	u8 buf[ST21NFCA_HCI_LLC_MAX_PAYLOAD];
	struct i2c_client *client = phy->i2c_dev;

	if (phy->current_read_len < ARRAY_SIZE(len_seq)) {
		len = len_seq[phy->current_read_len];

		/*
		 * Add retry mecanism
		 * Operation on I2C interface may fail in case of operation on
		 * RF or SWP interface
		 */
		r = 0;
		mutex_lock(&phy->phy_lock);
		for (i = 0; i < ARRAY_SIZE(wait_tab) && r <= 0; i++) {
			r = i2c_master_recv(client, buf, len);
			if (r < 0)
				msleep(wait_tab[i]);
		}
		mutex_unlock(&phy->phy_lock);

		if (r != len) {
			phy->current_read_len = 0;
			return -EREMOTEIO;
		}

		/*
		 * The first read sequence does not start with SOF.
		 * Data is corrupeted so we drop it.
		 */
		if (!phy->current_read_len && !IS_START_OF_FRAME(buf)) {
			skb_trim(skb, 0);
			phy->current_read_len = 0;
			return -EIO;
		} else if (phy->current_read_len && IS_START_OF_FRAME(buf)) {
			/*
			 * Previous frame transmission was interrupted and
			 * the frame got repeated.
			 * Received frame start with ST21NFCA_SOF_EOF + 00.
			 */
			skb_trim(skb, 0);
			phy->current_read_len = 0;
		}

		skb_put_data(skb, buf, len);

		if (skb->data[skb->len - 1] == ST21NFCA_SOF_EOF) {
			phy->current_read_len = 0;
			return st21nfca_hci_i2c_repack(skb);
		}
		phy->current_read_len++;
		return -EAGAIN;
	}
	return -EIO;
}

/*
 * Reads an shdlc frame from the chip. This is not as straightforward as it
 * seems. The frame format is data-crc, and corruption can occur anywhere
 * while transiting on i2c bus, such that we could read an invalid data.
 * The tricky case is when we read a corrupted data or crc. We must detect
 * this here in order to determine that data can be transmitted to the hci
 * core. This is the reason why we check the crc here.
 * The CLF will repeat a frame until we send a RR on that frame.
 *
 * On ST21NFCA, IRQ goes in idle when read starts. As no size information are
 * available in the incoming data, other IRQ might come. Every IRQ will trigger
 * a read sequence with different length and will fill the current frame.
 * The reception is complete once we reach a ST21NFCA_SOF_EOF.
 */
static irqreturn_t st21nfca_hci_irq_thread_fn(int irq, void *phy_id)
{
	struct st21nfca_i2c_phy *phy = phy_id;

	int r;

	if (!phy || irq != phy->i2c_dev->irq) {
		WARN_ON_ONCE(1);
		return IRQ_NONE;
	}

	if (phy->hard_fault != 0)
		return IRQ_HANDLED;

	r = st21nfca_hci_i2c_read(phy, phy->pending_skb);
	if (r == -EREMOTEIO) {
		phy->hard_fault = r;

		nfc_hci_recv_frame(phy->hdev, NULL);

		return IRQ_HANDLED;
	} else if (r == -EAGAIN || r == -EIO) {
		return IRQ_HANDLED;
	} else if (r == -EBADMSG && phy->crc_trials < ARRAY_SIZE(wait_tab)) {
		/*
		 * With ST21NFCA, only one interface (I2C, RF or SWP)
		 * may be active at a time.
		 * Having incorrect crc is usually due to i2c macrocell
		 * deactivation in the middle of a transmission.
		 * It may generate corrupted data on i2c.
		 * We give sometime to get i2c back.
		 * The complete frame will be repeated.
		 */
		msleep(wait_tab[phy->crc_trials]);
		phy->crc_trials++;
		phy->current_read_len = 0;
		kfree_skb(phy->pending_skb);
	} else if (r > 0) {
		/*
		 * We succeeded to read data from the CLF and
		 * data is valid.
		 * Reset counter.
		 */
		nfc_hci_recv_frame(phy->hdev, phy->pending_skb);
		phy->crc_trials = 0;
	} else {
		kfree_skb(phy->pending_skb);
	}

	phy->pending_skb = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE * 2, GFP_KERNEL);
	if (phy->pending_skb == NULL) {
		phy->hard_fault = -ENOMEM;
		nfc_hci_recv_frame(phy->hdev, NULL);
	}

	return IRQ_HANDLED;
}

static const struct nfc_phy_ops i2c_phy_ops = {
	.write = st21nfca_hci_i2c_write,
	.enable = st21nfca_hci_i2c_enable,
	.disable = st21nfca_hci_i2c_disable,
};

static const struct acpi_gpio_params enable_gpios = { 1, 0, false };

static const struct acpi_gpio_mapping acpi_st21nfca_gpios[] = {
	{ "enable-gpios", &enable_gpios, 1 },
	{},
};

static int st21nfca_hci_i2c_probe(struct i2c_client *client,
				  const struct i2c_device_id *id)
{
	struct device *dev = &client->dev;
	struct st21nfca_i2c_phy *phy;
	int r;

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		nfc_err(&client->dev, "Need I2C_FUNC_I2C\n");
		return -ENODEV;
	}

	phy = devm_kzalloc(&client->dev, sizeof(struct st21nfca_i2c_phy),
			   GFP_KERNEL);
	if (!phy)
		return -ENOMEM;

	phy->i2c_dev = client;
	phy->pending_skb = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE * 2, GFP_KERNEL);
	if (phy->pending_skb == NULL)
		return -ENOMEM;

	phy->current_read_len = 0;
	phy->crc_trials = 0;
	mutex_init(&phy->phy_lock);
	i2c_set_clientdata(client, phy);

	r = devm_acpi_dev_add_driver_gpios(dev, acpi_st21nfca_gpios);
	if (r)
		dev_dbg(dev, "Unable to add GPIO mapping table\n");

	/* Get EN GPIO from resource provider */
	phy->gpiod_ena = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
	if (IS_ERR(phy->gpiod_ena)) {
		nfc_err(dev, "Unable to get ENABLE GPIO\n");
		return PTR_ERR(phy->gpiod_ena);
	}

	phy->se_status.is_ese_present =
			device_property_read_bool(&client->dev, "ese-present");
	phy->se_status.is_uicc_present =
			device_property_read_bool(&client->dev, "uicc-present");

	r = st21nfca_hci_platform_init(phy);
	if (r < 0) {
		nfc_err(&client->dev, "Unable to reboot st21nfca\n");
		return r;
	}

	r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
				st21nfca_hci_irq_thread_fn,
				IRQF_ONESHOT,
				ST21NFCA_HCI_DRIVER_NAME, phy);
	if (r < 0) {
		nfc_err(&client->dev, "Unable to register IRQ handler\n");
		return r;
	}

	return st21nfca_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME,
					ST21NFCA_FRAME_HEADROOM,
					ST21NFCA_FRAME_TAILROOM,
					ST21NFCA_HCI_LLC_MAX_PAYLOAD,
					&phy->hdev,
					&phy->se_status);
}

static int st21nfca_hci_i2c_remove(struct i2c_client *client)
{
	struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client);

	st21nfca_hci_remove(phy->hdev);

	if (phy->powered)
		st21nfca_hci_i2c_disable(phy);

	return 0;
}

static const struct i2c_device_id st21nfca_hci_i2c_id_table[] = {
	{ST21NFCA_HCI_DRIVER_NAME, 0},
	{}
};
MODULE_DEVICE_TABLE(i2c, st21nfca_hci_i2c_id_table);

static const struct acpi_device_id st21nfca_hci_i2c_acpi_match[] __maybe_unused = {
	{"SMO2100", 0},
	{}
};
MODULE_DEVICE_TABLE(acpi, st21nfca_hci_i2c_acpi_match);

static const struct of_device_id of_st21nfca_i2c_match[] __maybe_unused = {
	{ .compatible = "st,st21nfca-i2c", },
	{ .compatible = "st,st21nfca_i2c", },
	{}
};
MODULE_DEVICE_TABLE(of, of_st21nfca_i2c_match);

static struct i2c_driver st21nfca_hci_i2c_driver = {
	.driver = {
		.name = ST21NFCA_HCI_I2C_DRIVER_NAME,
		.of_match_table = of_match_ptr(of_st21nfca_i2c_match),
		.acpi_match_table = ACPI_PTR(st21nfca_hci_i2c_acpi_match),
	},
	.probe = st21nfca_hci_i2c_probe,
	.id_table = st21nfca_hci_i2c_id_table,
	.remove = st21nfca_hci_i2c_remove,
};
module_i2c_driver(st21nfca_hci_i2c_driver);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION(DRIVER_DESC);
