// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2019-2020 Linaro Limited */

#include <linux/acpi.h>
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <asm/unaligned.h>

#include "xhci.h"
#include "xhci-trace.h"
#include "xhci-pci.h"

#define RENESAS_FW_VERSION				0x6C
#define RENESAS_ROM_CONFIG				0xF0
#define RENESAS_FW_STATUS				0xF4
#define RENESAS_FW_STATUS_MSB				0xF5
#define RENESAS_ROM_STATUS				0xF6
#define RENESAS_ROM_STATUS_MSB				0xF7
#define RENESAS_DATA0					0xF8
#define RENESAS_DATA1					0xFC

#define RENESAS_FW_VERSION_FIELD			GENMASK(23, 7)
#define RENESAS_FW_VERSION_OFFSET			8

#define RENESAS_FW_STATUS_DOWNLOAD_ENABLE		BIT(0)
#define RENESAS_FW_STATUS_LOCK				BIT(1)
#define RENESAS_FW_STATUS_RESULT			GENMASK(6, 4)
  #define RENESAS_FW_STATUS_INVALID			0
  #define RENESAS_FW_STATUS_SUCCESS			BIT(4)
  #define RENESAS_FW_STATUS_ERROR			BIT(5)
#define RENESAS_FW_STATUS_SET_DATA0			BIT(8)
#define RENESAS_FW_STATUS_SET_DATA1			BIT(9)

#define RENESAS_ROM_STATUS_ACCESS			BIT(0)
#define RENESAS_ROM_STATUS_ERASE			BIT(1)
#define RENESAS_ROM_STATUS_RELOAD			BIT(2)
#define RENESAS_ROM_STATUS_RESULT			GENMASK(6, 4)
  #define RENESAS_ROM_STATUS_NO_RESULT			0
  #define RENESAS_ROM_STATUS_SUCCESS			BIT(4)
  #define RENESAS_ROM_STATUS_ERROR			BIT(5)
#define RENESAS_ROM_STATUS_SET_DATA0			BIT(8)
#define RENESAS_ROM_STATUS_SET_DATA1			BIT(9)
#define RENESAS_ROM_STATUS_ROM_EXISTS			BIT(15)

#define RENESAS_ROM_ERASE_MAGIC				0x5A65726F
#define RENESAS_ROM_WRITE_MAGIC				0x53524F4D

#define RENESAS_RETRY	10000
#define RENESAS_DELAY	10

static int renesas_fw_download_image(struct pci_dev *dev,
				     const u32 *fw, size_t step, bool rom)
{
	size_t i;
	int err;
	u8 fw_status;
	bool data0_or_data1;
	u32 status_reg;

	if (rom)
		status_reg = RENESAS_ROM_STATUS_MSB;
	else
		status_reg = RENESAS_FW_STATUS_MSB;

	/*
	 * The hardware does alternate between two 32-bit pages.
	 * (This is because each row of the firmware is 8 bytes).
	 *
	 * for even steps we use DATA0, for odd steps DATA1.
	 */
	data0_or_data1 = (step & 1) == 1;

	/* step+1. Read "Set DATAX" and confirm it is cleared. */
	for (i = 0; i < RENESAS_RETRY; i++) {
		err = pci_read_config_byte(dev, status_reg, &fw_status);
		if (err) {
			dev_err(&dev->dev, "Read Status failed: %d\n",
				pcibios_err_to_errno(err));
			return pcibios_err_to_errno(err);
		}
		if (!(fw_status & BIT(data0_or_data1)))
			break;

		udelay(RENESAS_DELAY);
	}
	if (i == RENESAS_RETRY) {
		dev_err(&dev->dev, "Timeout for Set DATAX step: %zd\n", step);
		return -ETIMEDOUT;
	}

	/*
	 * step+2. Write FW data to "DATAX".
	 * "LSB is left" => force little endian
	 */
	err = pci_write_config_dword(dev, data0_or_data1 ?
				     RENESAS_DATA1 : RENESAS_DATA0,
				     (__force u32)cpu_to_le32(fw[step]));
	if (err) {
		dev_err(&dev->dev, "Write to DATAX failed: %d\n",
			pcibios_err_to_errno(err));
		return pcibios_err_to_errno(err);
	}

	udelay(100);

	/* step+3. Set "Set DATAX". */
	err = pci_write_config_byte(dev, status_reg, BIT(data0_or_data1));
	if (err) {
		dev_err(&dev->dev, "Write config for DATAX failed: %d\n",
			pcibios_err_to_errno(err));
		return pcibios_err_to_errno(err);
	}

	return 0;
}

static int renesas_fw_verify(const void *fw_data,
			     size_t length)
{
	u16 fw_version_pointer;

	/*
	 * The Firmware's Data Format is describe in
	 * "6.3 Data Format" R19UH0078EJ0500 Rev.5.00 page 124
	 */

	/*
	 * The bootrom chips of the big brother have sizes up to 64k, let's
	 * assume that's the biggest the firmware can get.
	 */
	if (length < 0x1000 || length >= 0x10000) {
		pr_err("firmware is size %zd is not (4k - 64k).",
			length);
		return -EINVAL;
	}

	/* The First 2 bytes are fixed value (55aa). "LSB on Left" */
	if (get_unaligned_le16(fw_data) != 0x55aa) {
		pr_err("no valid firmware header found.");
		return -EINVAL;
	}

	/* verify the firmware version position and print it. */
	fw_version_pointer = get_unaligned_le16(fw_data + 4);
	if (fw_version_pointer + 2 >= length) {
		pr_err("fw ver pointer is outside of the firmware image");
		return -EINVAL;
	}

	return 0;
}

static bool renesas_check_rom(struct pci_dev *pdev)
{
	u16 rom_status;
	int retval;

	/* Check if external ROM exists */
	retval = pci_read_config_word(pdev, RENESAS_ROM_STATUS, &rom_status);
	if (retval)
		return false;

	rom_status &= RENESAS_ROM_STATUS_ROM_EXISTS;
	if (rom_status) {
		dev_dbg(&pdev->dev, "External ROM exists\n");
		return true; /* External ROM exists */
	}

	return false;
}

static int renesas_check_rom_state(struct pci_dev *pdev)
{
	u16 rom_state;
	u32 version;
	int err;

	/* check FW version */
	err = pci_read_config_dword(pdev, RENESAS_FW_VERSION, &version);
	if (err)
		return pcibios_err_to_errno(err);

	version &= RENESAS_FW_VERSION_FIELD;
	version = version >> RENESAS_FW_VERSION_OFFSET;
	dev_dbg(&pdev->dev, "Found ROM version: %x\n", version);

	/*
	 * Test if ROM is present and loaded, if so we can skip everything
	 */
	err = pci_read_config_word(pdev, RENESAS_ROM_STATUS, &rom_state);
	if (err)
		return pcibios_err_to_errno(err);

	if (rom_state & RENESAS_ROM_STATUS_ROM_EXISTS) {
		/* ROM exists */
		dev_dbg(&pdev->dev, "ROM exists\n");

		/* Check the "Result Code" Bits (6:4) and act accordingly */
		switch (rom_state & RENESAS_ROM_STATUS_RESULT) {
		case RENESAS_ROM_STATUS_SUCCESS:
			return 0;

		case RENESAS_ROM_STATUS_NO_RESULT: /* No result yet */
			dev_dbg(&pdev->dev, "Unknown ROM status ...\n");
			return -ENOENT;

		case RENESAS_ROM_STATUS_ERROR: /* Error State */
		default: /* All other states are marked as "Reserved states" */
			dev_err(&pdev->dev, "Invalid ROM..");
			break;
		}
	}

	return -EIO;
}

static int renesas_fw_check_running(struct pci_dev *pdev)
{
	u8 fw_state;
	int err;

	/*
	 * Test if the device is actually needing the firmware. As most
	 * BIOSes will initialize the device for us. If the device is
	 * initialized.
	 */
	err = pci_read_config_byte(pdev, RENESAS_FW_STATUS, &fw_state);
	if (err)
		return pcibios_err_to_errno(err);

	/*
	 * Check if "FW Download Lock" is locked. If it is and the FW is
	 * ready we can simply continue. If the FW is not ready, we have
	 * to give up.
	 */
	if (fw_state & RENESAS_FW_STATUS_LOCK) {
		dev_dbg(&pdev->dev, "FW Download Lock is engaged.");

		if (fw_state & RENESAS_FW_STATUS_SUCCESS)
			return 0;

		dev_err(&pdev->dev,
			"FW Download Lock is set and FW is not ready. Giving Up.");
		return -EIO;
	}

	/*
	 * Check if "FW Download Enable" is set. If someone (us?) tampered
	 * with it and it can't be reset, we have to give up too... and
	 * ask for a forgiveness and a reboot.
	 */
	if (fw_state & RENESAS_FW_STATUS_DOWNLOAD_ENABLE) {
		dev_err(&pdev->dev,
			"FW Download Enable is stale. Giving Up (poweroff/reboot needed).");
		return -EIO;
	}

	/* Otherwise, Check the "Result Code" Bits (6:4) and act accordingly */
	switch (fw_state & RENESAS_FW_STATUS_RESULT) {
	case 0: /* No result yet */
		dev_dbg(&pdev->dev, "FW is not ready/loaded yet.");

		/* tell the caller, that this device needs the firmware. */
		return 1;

	case RENESAS_FW_STATUS_SUCCESS: /* Success, device should be working. */
		dev_dbg(&pdev->dev, "FW is ready.");
		return 0;

	case RENESAS_FW_STATUS_ERROR: /* Error State */
		dev_err(&pdev->dev,
			"hardware is in an error state. Giving up (poweroff/reboot needed).");
		return -ENODEV;

	default: /* All other states are marked as "Reserved states" */
		dev_err(&pdev->dev,
			"hardware is in an invalid state %lx. Giving up (poweroff/reboot needed).",
			(fw_state & RENESAS_FW_STATUS_RESULT) >> 4);
		return -EINVAL;
	}
}

static int renesas_fw_download(struct pci_dev *pdev,
			       const struct firmware *fw)
{
	const u32 *fw_data = (const u32 *)fw->data;
	size_t i;
	int err;
	u8 fw_status;

	/*
	 * For more information and the big picture: please look at the
	 * "Firmware Download Sequence" in "7.1 FW Download Interface"
	 * of R19UH0078EJ0500 Rev.5.00 page 131
	 */

	/*
	 * 0. Set "FW Download Enable" bit in the
	 * "FW Download Control & Status Register" at 0xF4
	 */
	err = pci_write_config_byte(pdev, RENESAS_FW_STATUS,
				    RENESAS_FW_STATUS_DOWNLOAD_ENABLE);
	if (err)
		return pcibios_err_to_errno(err);

	/* 1 - 10 follow one step after the other. */
	for (i = 0; i < fw->size / 4; i++) {
		err = renesas_fw_download_image(pdev, fw_data, i, false);
		if (err) {
			dev_err(&pdev->dev,
				"Firmware Download Step %zd failed at position %zd bytes with (%d).",
				i, i * 4, err);
			return err;
		}
	}

	/*
	 * This sequence continues until the last data is written to
	 * "DATA0" or "DATA1". Naturally, we wait until "SET DATA0/1"
	 * is cleared by the hardware beforehand.
	 */
	for (i = 0; i < RENESAS_RETRY; i++) {
		err = pci_read_config_byte(pdev, RENESAS_FW_STATUS_MSB,
					   &fw_status);
		if (err)
			return pcibios_err_to_errno(err);
		if (!(fw_status & (BIT(0) | BIT(1))))
			break;

		udelay(RENESAS_DELAY);
	}
	if (i == RENESAS_RETRY)
		dev_warn(&pdev->dev, "Final Firmware Download step timed out.");

	/*
	 * 11. After finishing writing the last data of FW, the
	 * System Software must clear "FW Download Enable"
	 */
	err = pci_write_config_byte(pdev, RENESAS_FW_STATUS, 0);
	if (err)
		return pcibios_err_to_errno(err);

	/* 12. Read "Result Code" and confirm it is good. */
	for (i = 0; i < RENESAS_RETRY; i++) {
		err = pci_read_config_byte(pdev, RENESAS_FW_STATUS, &fw_status);
		if (err)
			return pcibios_err_to_errno(err);
		if (fw_status & RENESAS_FW_STATUS_SUCCESS)
			break;

		udelay(RENESAS_DELAY);
	}
	if (i == RENESAS_RETRY) {
		/* Timed out / Error - let's see if we can fix this */
		err = renesas_fw_check_running(pdev);
		switch (err) {
		case 0: /*
			 * we shouldn't end up here.
			 * maybe it took a little bit longer.
			 * But all should be well?
			 */
			break;

		case 1: /* (No result yet! */
			dev_err(&pdev->dev, "FW Load timedout");
			return -ETIMEDOUT;

		default:
			return err;
		}
	}

	return 0;
}

static void renesas_rom_erase(struct pci_dev *pdev)
{
	int retval, i;
	u8 status;

	dev_dbg(&pdev->dev, "Performing ROM Erase...\n");
	retval = pci_write_config_dword(pdev, RENESAS_DATA0,
					RENESAS_ROM_ERASE_MAGIC);
	if (retval) {
		dev_err(&pdev->dev, "ROM erase, magic word write failed: %d\n",
			pcibios_err_to_errno(retval));
		return;
	}

	retval = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, &status);
	if (retval) {
		dev_err(&pdev->dev, "ROM status read failed: %d\n",
			pcibios_err_to_errno(retval));
		return;
	}
	status |= RENESAS_ROM_STATUS_ERASE;
	retval = pci_write_config_byte(pdev, RENESAS_ROM_STATUS, status);
	if (retval) {
		dev_err(&pdev->dev, "ROM erase set word write failed\n");
		return;
	}

	/* sleep a bit while ROM is erased */
	msleep(20);

	for (i = 0; i < RENESAS_RETRY; i++) {
		retval = pci_read_config_byte(pdev, RENESAS_ROM_STATUS,
					      &status);
		status &= RENESAS_ROM_STATUS_ERASE;
		if (!status)
			break;

		mdelay(RENESAS_DELAY);
	}

	if (i == RENESAS_RETRY)
		dev_dbg(&pdev->dev, "Chip erase timedout: %x\n", status);

	dev_dbg(&pdev->dev, "ROM Erase... Done success\n");
}

static bool renesas_setup_rom(struct pci_dev *pdev, const struct firmware *fw)
{
	const u32 *fw_data = (const u32 *)fw->data;
	int err, i;
	u8 status;

	/* 2. Write magic word to Data0 */
	err = pci_write_config_dword(pdev, RENESAS_DATA0,
				     RENESAS_ROM_WRITE_MAGIC);
	if (err)
		return false;

	/* 3. Set External ROM access */
	err = pci_write_config_byte(pdev, RENESAS_ROM_STATUS,
				    RENESAS_ROM_STATUS_ACCESS);
	if (err)
		goto remove_bypass;

	/* 4. Check the result */
	err = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, &status);
	if (err)
		goto remove_bypass;
	status &= GENMASK(6, 4);
	if (status) {
		dev_err(&pdev->dev,
			"setting external rom failed: %x\n", status);
		goto remove_bypass;
	}

	/* 5 to 16 Write FW to DATA0/1 while checking SetData0/1 */
	for (i = 0; i < fw->size / 4; i++) {
		err = renesas_fw_download_image(pdev, fw_data, i, true);
		if (err) {
			dev_err(&pdev->dev,
				"ROM Download Step %d failed at position %d bytes with (%d)\n",
				 i, i * 4, err);
			goto remove_bypass;
		}
	}

	/*
	 * wait till DATA0/1 is cleared
	 */
	for (i = 0; i < RENESAS_RETRY; i++) {
		err = pci_read_config_byte(pdev, RENESAS_ROM_STATUS_MSB,
					   &status);
		if (err)
			goto remove_bypass;
		if (!(status & (BIT(0) | BIT(1))))
			break;

		udelay(RENESAS_DELAY);
	}
	if (i == RENESAS_RETRY) {
		dev_err(&pdev->dev, "Final Firmware ROM Download step timed out\n");
		goto remove_bypass;
	}

	/* 17. Remove bypass */
	err = pci_write_config_byte(pdev, RENESAS_ROM_STATUS, 0);
	if (err)
		return false;

	udelay(10);

	/* 18. check result */
	for (i = 0; i < RENESAS_RETRY; i++) {
		err = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, &status);
		if (err) {
			dev_err(&pdev->dev, "Read ROM status failed:%d\n",
				pcibios_err_to_errno(err));
			return false;
		}
		status &= RENESAS_ROM_STATUS_RESULT;
		if (status ==  RENESAS_ROM_STATUS_SUCCESS) {
			dev_dbg(&pdev->dev, "Download ROM success\n");
			break;
		}
		udelay(RENESAS_DELAY);
	}
	if (i == RENESAS_RETRY) { /* Timed out */
		dev_err(&pdev->dev,
			"Download to external ROM TO: %x\n", status);
		return false;
	}

	dev_dbg(&pdev->dev, "Download to external ROM succeeded\n");

	/* Last step set Reload */
	err = pci_write_config_byte(pdev, RENESAS_ROM_STATUS,
				    RENESAS_ROM_STATUS_RELOAD);
	if (err) {
		dev_err(&pdev->dev, "Set ROM execute failed: %d\n",
			pcibios_err_to_errno(err));
		return false;
	}

	/*
	 * wait till Reload is cleared
	 */
	for (i = 0; i < RENESAS_RETRY; i++) {
		err = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, &status);
		if (err)
			return false;
		if (!(status & RENESAS_ROM_STATUS_RELOAD))
			break;

		udelay(RENESAS_DELAY);
	}
	if (i == RENESAS_RETRY) {
		dev_err(&pdev->dev, "ROM Exec timed out: %x\n", status);
		return false;
	}

	return true;

remove_bypass:
	pci_write_config_byte(pdev, RENESAS_ROM_STATUS, 0);
	return false;
}

static int renesas_load_fw(struct pci_dev *pdev, const struct firmware *fw)
{
	int err = 0;
	bool rom;

	/* Check if the device has external ROM */
	rom = renesas_check_rom(pdev);
	if (rom) {
		/* perform chip erase first */
		renesas_rom_erase(pdev);

		/* lets try loading fw on ROM first */
		rom = renesas_setup_rom(pdev, fw);
		if (!rom) {
			dev_dbg(&pdev->dev,
				"ROM load failed, falling back on FW load\n");
		} else {
			dev_dbg(&pdev->dev,
				"ROM load success\n");
			goto exit;
		}
	}

	err = renesas_fw_download(pdev, fw);

exit:
	if (err)
		dev_err(&pdev->dev, "firmware failed to download (%d).", err);
	return err;
}

int renesas_xhci_check_request_fw(struct pci_dev *pdev,
				  const struct pci_device_id *id)
{
	struct xhci_driver_data *driver_data =
			(struct xhci_driver_data *)id->driver_data;
	const char *fw_name = driver_data->firmware;
	const struct firmware *fw;
	bool has_rom;
	int err;

	/* Check if device has ROM and loaded, if so skip everything */
	has_rom = renesas_check_rom(pdev);
	if (has_rom) {
		err = renesas_check_rom_state(pdev);
		if (!err)
			return 0;
		else if (err != -ENOENT)
			has_rom = false;
	}

	err = renesas_fw_check_running(pdev);
	/* Continue ahead, if the firmware is already running. */
	if (!err)
		return 0;

	/* no firmware interface available */
	if (err != 1)
		return has_rom ? 0 : err;

	pci_dev_get(pdev);
	err = firmware_request_nowarn(&fw, fw_name, &pdev->dev);
	pci_dev_put(pdev);
	if (err) {
		if (has_rom) {
			dev_info(&pdev->dev, "failed to load firmware %s, fallback to ROM\n",
				 fw_name);
			return 0;
		}
		dev_err(&pdev->dev, "failed to load firmware %s: %d\n",
			fw_name, err);
		return err;
	}

	err = renesas_fw_verify(fw->data, fw->size);
	if (err)
		goto exit;

	err = renesas_load_fw(pdev, fw);
exit:
	release_firmware(fw);
	return err;
}
EXPORT_SYMBOL_GPL(renesas_xhci_check_request_fw);

MODULE_LICENSE("GPL v2");
