/*
 * Copyright (c) 2007-2016, Synaptics Incorporated
 * Copyright (C) 2016 Zodiac Inflight Innovations
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 */

#include <linux/kernel.h>
#include <linux/rmi.h>
#include <linux/firmware.h>
#include <asm/unaligned.h>
#include <linux/bitops.h>

#include "rmi_driver.h"
#include "rmi_f34.h"

static int rmi_f34_write_bootloader_id(struct f34_data *f34)
{
	struct rmi_function *fn = f34->fn;
	struct rmi_device *rmi_dev = fn->rmi_dev;
	u8 bootloader_id[F34_BOOTLOADER_ID_LEN];
	int ret;

	ret = rmi_read_block(rmi_dev, fn->fd.query_base_addr,
			     bootloader_id, sizeof(bootloader_id));
	if (ret) {
		dev_err(&fn->dev, "%s: Reading bootloader ID failed: %d\n",
				__func__, ret);
		return ret;
	}

	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: writing bootloader id '%c%c'\n",
			__func__, bootloader_id[0], bootloader_id[1]);

	ret = rmi_write_block(rmi_dev,
			      fn->fd.data_base_addr + F34_BLOCK_DATA_OFFSET,
			      bootloader_id, sizeof(bootloader_id));
	if (ret) {
		dev_err(&fn->dev, "Failed to write bootloader ID: %d\n", ret);
		return ret;
	}

	return 0;
}

static int rmi_f34_command(struct f34_data *f34, u8 command,
			   unsigned int timeout, bool write_bl_id)
{
	struct rmi_function *fn = f34->fn;
	struct rmi_device *rmi_dev = fn->rmi_dev;
	int ret;

	if (write_bl_id) {
		ret = rmi_f34_write_bootloader_id(f34);
		if (ret)
			return ret;
	}

	init_completion(&f34->v5.cmd_done);

	ret = rmi_read(rmi_dev, f34->v5.ctrl_address, &f34->v5.status);
	if (ret) {
		dev_err(&f34->fn->dev,
			"%s: Failed to read cmd register: %d (command %#02x)\n",
			__func__, ret, command);
		return ret;
	}

	f34->v5.status |= command & 0x0f;

	ret = rmi_write(rmi_dev, f34->v5.ctrl_address, f34->v5.status);
	if (ret < 0) {
		dev_err(&f34->fn->dev,
			"Failed to write F34 command %#02x: %d\n",
			command, ret);
		return ret;
	}

	if (!wait_for_completion_timeout(&f34->v5.cmd_done,
				msecs_to_jiffies(timeout))) {

		ret = rmi_read(rmi_dev, f34->v5.ctrl_address, &f34->v5.status);
		if (ret) {
			dev_err(&f34->fn->dev,
				"%s: cmd %#02x timed out: %d\n",
				__func__, command, ret);
			return ret;
		}

		if (f34->v5.status & 0x7f) {
			dev_err(&f34->fn->dev,
				"%s: cmd %#02x timed out, status: %#02x\n",
				__func__, command, f34->v5.status);
			return -ETIMEDOUT;
		}
	}

	return 0;
}

static irqreturn_t rmi_f34_attention(int irq, void *ctx)
{
	struct rmi_function *fn = ctx;
	struct f34_data *f34 = dev_get_drvdata(&fn->dev);
	int ret;
	u8 status;

	if (f34->bl_version == 5) {
		ret = rmi_read(f34->fn->rmi_dev, f34->v5.ctrl_address,
			       &status);
		rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: status: %#02x, ret: %d\n",
			__func__, status, ret);

		if (!ret && !(status & 0x7f))
			complete(&f34->v5.cmd_done);
	} else {
		ret = rmi_read_block(f34->fn->rmi_dev,
				     f34->fn->fd.data_base_addr +
						f34->v7.off.flash_status,
				     &status, sizeof(status));
		rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: status: %#02x, ret: %d\n",
			__func__, status, ret);

		if (!ret && !(status & 0x1f))
			complete(&f34->v7.cmd_done);
	}

	return IRQ_HANDLED;
}

static int rmi_f34_write_blocks(struct f34_data *f34, const void *data,
				int block_count, u8 command)
{
	struct rmi_function *fn = f34->fn;
	struct rmi_device *rmi_dev = fn->rmi_dev;
	u16 address = fn->fd.data_base_addr + F34_BLOCK_DATA_OFFSET;
	u8 start_address[] = { 0, 0 };
	int i;
	int ret;

	ret = rmi_write_block(rmi_dev, fn->fd.data_base_addr,
			      start_address, sizeof(start_address));
	if (ret) {
		dev_err(&fn->dev, "Failed to write initial zeros: %d\n", ret);
		return ret;
	}

	for (i = 0; i < block_count; i++) {
		ret = rmi_write_block(rmi_dev, address,
				      data, f34->v5.block_size);
		if (ret) {
			dev_err(&fn->dev,
				"failed to write block #%d: %d\n", i, ret);
			return ret;
		}

		ret = rmi_f34_command(f34, command, F34_IDLE_WAIT_MS, false);
		if (ret) {
			dev_err(&fn->dev,
				"Failed to write command for block #%d: %d\n",
				i, ret);
			return ret;
		}

		rmi_dbg(RMI_DEBUG_FN, &fn->dev, "wrote block %d of %d\n",
			i + 1, block_count);

		data += f34->v5.block_size;
		f34->update_progress += f34->v5.block_size;
		f34->update_status = (f34->update_progress * 100) /
			f34->update_size;
	}

	return 0;
}

static int rmi_f34_write_firmware(struct f34_data *f34, const void *data)
{
	return rmi_f34_write_blocks(f34, data, f34->v5.fw_blocks,
				    F34_WRITE_FW_BLOCK);
}

static int rmi_f34_write_config(struct f34_data *f34, const void *data)
{
	return rmi_f34_write_blocks(f34, data, f34->v5.config_blocks,
				    F34_WRITE_CONFIG_BLOCK);
}

static int rmi_f34_enable_flash(struct f34_data *f34)
{
	return rmi_f34_command(f34, F34_ENABLE_FLASH_PROG,
			       F34_ENABLE_WAIT_MS, true);
}

static int rmi_f34_flash_firmware(struct f34_data *f34,
				  const struct rmi_f34_firmware *syn_fw)
{
	struct rmi_function *fn = f34->fn;
	u32 image_size = le32_to_cpu(syn_fw->image_size);
	u32 config_size = le32_to_cpu(syn_fw->config_size);
	int ret;

	f34->update_progress = 0;
	f34->update_size = image_size + config_size;

	if (image_size) {
		dev_info(&fn->dev, "Erasing firmware...\n");
		ret = rmi_f34_command(f34, F34_ERASE_ALL,
				      F34_ERASE_WAIT_MS, true);
		if (ret)
			return ret;

		dev_info(&fn->dev, "Writing firmware (%d bytes)...\n",
			 image_size);
		ret = rmi_f34_write_firmware(f34, syn_fw->data);
		if (ret)
			return ret;
	}

	if (config_size) {
		/*
		 * We only need to erase config if we haven't updated
		 * firmware.
		 */
		if (!image_size) {
			dev_info(&fn->dev, "Erasing config...\n");
			ret = rmi_f34_command(f34, F34_ERASE_CONFIG,
					      F34_ERASE_WAIT_MS, true);
			if (ret)
				return ret;
		}

		dev_info(&fn->dev, "Writing config (%d bytes)...\n",
			 config_size);
		ret = rmi_f34_write_config(f34, &syn_fw->data[image_size]);
		if (ret)
			return ret;
	}

	return 0;
}

static int rmi_f34_update_firmware(struct f34_data *f34,
				   const struct firmware *fw)
{
	const struct rmi_f34_firmware *syn_fw =
				(const struct rmi_f34_firmware *)fw->data;
	u32 image_size = le32_to_cpu(syn_fw->image_size);
	u32 config_size = le32_to_cpu(syn_fw->config_size);
	int ret;

	BUILD_BUG_ON(offsetof(struct rmi_f34_firmware, data) !=
			F34_FW_IMAGE_OFFSET);

	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
		"FW size:%zd, checksum:%08x, image_size:%d, config_size:%d\n",
		fw->size,
		le32_to_cpu(syn_fw->checksum),
		image_size, config_size);

	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
		"FW bootloader_id:%02x, product_id:%.*s, info: %02x%02x\n",
		syn_fw->bootloader_version,
		(int)sizeof(syn_fw->product_id), syn_fw->product_id,
		syn_fw->product_info[0], syn_fw->product_info[1]);

	if (image_size && image_size != f34->v5.fw_blocks * f34->v5.block_size) {
		dev_err(&f34->fn->dev,
			"Bad firmware image: fw size %d, expected %d\n",
			image_size, f34->v5.fw_blocks * f34->v5.block_size);
		ret = -EILSEQ;
		goto out;
	}

	if (config_size &&
	    config_size != f34->v5.config_blocks * f34->v5.block_size) {
		dev_err(&f34->fn->dev,
			"Bad firmware image: config size %d, expected %d\n",
			config_size,
			f34->v5.config_blocks * f34->v5.block_size);
		ret = -EILSEQ;
		goto out;
	}

	if (image_size && !config_size) {
		dev_err(&f34->fn->dev, "Bad firmware image: no config data\n");
		ret = -EILSEQ;
		goto out;
	}

	dev_info(&f34->fn->dev, "Firmware image OK\n");
	mutex_lock(&f34->v5.flash_mutex);

	ret = rmi_f34_flash_firmware(f34, syn_fw);

	mutex_unlock(&f34->v5.flash_mutex);

out:
	return ret;
}

static int rmi_f34_status(struct rmi_function *fn)
{
	struct f34_data *f34 = dev_get_drvdata(&fn->dev);

	/*
	 * The status is the percentage complete, or once complete,
	 * zero for success or a negative return code.
	 */
	return f34->update_status;
}

static ssize_t rmi_driver_bootloader_id_show(struct device *dev,
					     struct device_attribute *dattr,
					     char *buf)
{
	struct rmi_driver_data *data = dev_get_drvdata(dev);
	struct rmi_function *fn = data->f34_container;
	struct f34_data *f34;

	if (fn) {
		f34 = dev_get_drvdata(&fn->dev);

		if (f34->bl_version == 5)
			return scnprintf(buf, PAGE_SIZE, "%c%c\n",
					 f34->bootloader_id[0],
					 f34->bootloader_id[1]);
		else
			return scnprintf(buf, PAGE_SIZE, "V%d.%d\n",
					 f34->bootloader_id[1],
					 f34->bootloader_id[0]);
	}

	return 0;
}

static DEVICE_ATTR(bootloader_id, 0444, rmi_driver_bootloader_id_show, NULL);

static ssize_t rmi_driver_configuration_id_show(struct device *dev,
						struct device_attribute *dattr,
						char *buf)
{
	struct rmi_driver_data *data = dev_get_drvdata(dev);
	struct rmi_function *fn = data->f34_container;
	struct f34_data *f34;

	if (fn) {
		f34 = dev_get_drvdata(&fn->dev);

		return scnprintf(buf, PAGE_SIZE, "%s\n", f34->configuration_id);
	}

	return 0;
}

static DEVICE_ATTR(configuration_id, 0444,
		   rmi_driver_configuration_id_show, NULL);

static int rmi_firmware_update(struct rmi_driver_data *data,
			       const struct firmware *fw)
{
	struct rmi_device *rmi_dev = data->rmi_dev;
	struct device *dev = &rmi_dev->dev;
	struct f34_data *f34;
	int ret;

	if (!data->f34_container) {
		dev_warn(dev, "%s: No F34 present!\n", __func__);
		return -EINVAL;
	}

	f34 = dev_get_drvdata(&data->f34_container->dev);

	if (f34->bl_version == 7) {
		if (data->pdt_props & HAS_BSR) {
			dev_err(dev, "%s: LTS not supported\n", __func__);
			return -ENODEV;
		}
	} else if (f34->bl_version != 5) {
		dev_warn(dev, "F34 V%d not supported!\n",
			 data->f34_container->fd.function_version);
		return -ENODEV;
	}

	/* Enter flash mode */
	if (f34->bl_version == 7)
		ret = rmi_f34v7_start_reflash(f34, fw);
	else
		ret = rmi_f34_enable_flash(f34);
	if (ret)
		return ret;

	rmi_disable_irq(rmi_dev, false);

	/* Tear down functions and re-probe */
	rmi_free_function_list(rmi_dev);

	ret = rmi_probe_interrupts(data);
	if (ret)
		return ret;

	ret = rmi_init_functions(data);
	if (ret)
		return ret;

	if (!data->bootloader_mode || !data->f34_container) {
		dev_warn(dev, "%s: No F34 present or not in bootloader!\n",
				__func__);
		return -EINVAL;
	}

	rmi_enable_irq(rmi_dev, false);

	f34 = dev_get_drvdata(&data->f34_container->dev);

	/* Perform firmware update */
	if (f34->bl_version == 7)
		ret = rmi_f34v7_do_reflash(f34, fw);
	else
		ret = rmi_f34_update_firmware(f34, fw);

	if (ret) {
		f34->update_status = ret;
		dev_err(&f34->fn->dev,
			"Firmware update failed, status: %d\n", ret);
	} else {
		dev_info(&f34->fn->dev, "Firmware update complete\n");
	}

	rmi_disable_irq(rmi_dev, false);

	/* Re-probe */
	rmi_dbg(RMI_DEBUG_FN, dev, "Re-probing device\n");
	rmi_free_function_list(rmi_dev);

	ret = rmi_scan_pdt(rmi_dev, NULL, rmi_initial_reset);
	if (ret < 0)
		dev_warn(dev, "RMI reset failed!\n");

	ret = rmi_probe_interrupts(data);
	if (ret)
		return ret;

	ret = rmi_init_functions(data);
	if (ret)
		return ret;

	rmi_enable_irq(rmi_dev, false);

	if (data->f01_container->dev.driver)
		/* Driver already bound, so enable ATTN now. */
		return rmi_enable_sensor(rmi_dev);

	rmi_dbg(RMI_DEBUG_FN, dev, "%s complete\n", __func__);

	return ret;
}

static ssize_t rmi_driver_update_fw_store(struct device *dev,
					  struct device_attribute *dattr,
					  const char *buf, size_t count)
{
	struct rmi_driver_data *data = dev_get_drvdata(dev);
	char fw_name[NAME_MAX];
	const struct firmware *fw;
	size_t copy_count = count;
	int ret;

	if (count == 0 || count >= NAME_MAX)
		return -EINVAL;

	if (buf[count - 1] == '\0' || buf[count - 1] == '\n')
		copy_count -= 1;

	strncpy(fw_name, buf, copy_count);
	fw_name[copy_count] = '\0';

	ret = request_firmware(&fw, fw_name, dev);
	if (ret)
		return ret;

	dev_info(dev, "Flashing %s\n", fw_name);

	ret = rmi_firmware_update(data, fw);

	release_firmware(fw);

	return ret ?: count;
}

static DEVICE_ATTR(update_fw, 0200, NULL, rmi_driver_update_fw_store);

static ssize_t rmi_driver_update_fw_status_show(struct device *dev,
						struct device_attribute *dattr,
						char *buf)
{
	struct rmi_driver_data *data = dev_get_drvdata(dev);
	int update_status = 0;

	if (data->f34_container)
		update_status = rmi_f34_status(data->f34_container);

	return scnprintf(buf, PAGE_SIZE, "%d\n", update_status);
}

static DEVICE_ATTR(update_fw_status, 0444,
		   rmi_driver_update_fw_status_show, NULL);

static struct attribute *rmi_firmware_attrs[] = {
	&dev_attr_bootloader_id.attr,
	&dev_attr_configuration_id.attr,
	&dev_attr_update_fw.attr,
	&dev_attr_update_fw_status.attr,
	NULL
};

static const struct attribute_group rmi_firmware_attr_group = {
	.attrs = rmi_firmware_attrs,
};

static int rmi_f34_probe(struct rmi_function *fn)
{
	struct f34_data *f34;
	unsigned char f34_queries[9];
	bool has_config_id;
	u8 version = fn->fd.function_version;
	int ret;

	f34 = devm_kzalloc(&fn->dev, sizeof(struct f34_data), GFP_KERNEL);
	if (!f34)
		return -ENOMEM;

	f34->fn = fn;
	dev_set_drvdata(&fn->dev, f34);

	/* v5 code only supported version 0, try V7 probe */
	if (version > 0)
		return rmi_f34v7_probe(f34);

	f34->bl_version = 5;

	ret = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr,
			     f34_queries, sizeof(f34_queries));
	if (ret) {
		dev_err(&fn->dev, "%s: Failed to query properties\n",
			__func__);
		return ret;
	}

	snprintf(f34->bootloader_id, sizeof(f34->bootloader_id),
		 "%c%c", f34_queries[0], f34_queries[1]);

	mutex_init(&f34->v5.flash_mutex);
	init_completion(&f34->v5.cmd_done);

	f34->v5.block_size = get_unaligned_le16(&f34_queries[3]);
	f34->v5.fw_blocks = get_unaligned_le16(&f34_queries[5]);
	f34->v5.config_blocks = get_unaligned_le16(&f34_queries[7]);
	f34->v5.ctrl_address = fn->fd.data_base_addr + F34_BLOCK_DATA_OFFSET +
		f34->v5.block_size;
	has_config_id = f34_queries[2] & (1 << 2);

	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Bootloader ID: %s\n",
		f34->bootloader_id);
	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Block size: %d\n",
		f34->v5.block_size);
	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "FW blocks: %d\n",
		f34->v5.fw_blocks);
	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "CFG blocks: %d\n",
		f34->v5.config_blocks);

	if (has_config_id) {
		ret = rmi_read_block(fn->rmi_dev, fn->fd.control_base_addr,
				     f34_queries, sizeof(f34_queries));
		if (ret) {
			dev_err(&fn->dev, "Failed to read F34 config ID\n");
			return ret;
		}

		snprintf(f34->configuration_id, sizeof(f34->configuration_id),
			 "%02x%02x%02x%02x",
			 f34_queries[0], f34_queries[1],
			 f34_queries[2], f34_queries[3]);

		rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Configuration ID: %s\n",
			 f34->configuration_id);
	}

	return 0;
}

int rmi_f34_create_sysfs(struct rmi_device *rmi_dev)
{
	return sysfs_create_group(&rmi_dev->dev.kobj, &rmi_firmware_attr_group);
}

void rmi_f34_remove_sysfs(struct rmi_device *rmi_dev)
{
	sysfs_remove_group(&rmi_dev->dev.kobj, &rmi_firmware_attr_group);
}

struct rmi_function_handler rmi_f34_handler = {
	.driver = {
		.name = "rmi4_f34",
	},
	.func = 0x34,
	.probe = rmi_f34_probe,
	.attention = rmi_f34_attention,
};
