// SPDX-License-Identifier: GPL-2.0-only
/* r8169_firmware.c: RealTek 8169/8168/8101 ethernet driver.
 *
 * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
 * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
 * Copyright (c) a lot of people too. Please respect their work.
 *
 * See MAINTAINERS file for support contact information.
 */

#include <linux/delay.h>
#include <linux/firmware.h>

#include "r8169_firmware.h"

enum rtl_fw_opcode {
	PHY_READ		= 0x0,
	PHY_DATA_OR		= 0x1,
	PHY_DATA_AND		= 0x2,
	PHY_BJMPN		= 0x3,
	PHY_MDIO_CHG		= 0x4,
	PHY_CLEAR_READCOUNT	= 0x7,
	PHY_WRITE		= 0x8,
	PHY_READCOUNT_EQ_SKIP	= 0x9,
	PHY_COMP_EQ_SKIPN	= 0xa,
	PHY_COMP_NEQ_SKIPN	= 0xb,
	PHY_WRITE_PREVIOUS	= 0xc,
	PHY_SKIPN		= 0xd,
	PHY_DELAY_MS		= 0xe,
};

struct fw_info {
	u32	magic;
	char	version[RTL_VER_SIZE];
	__le32	fw_start;
	__le32	fw_len;
	u8	chksum;
} __packed;

#define FW_OPCODE_SIZE sizeof_field(struct rtl_fw_phy_action, code[0])

static bool rtl_fw_format_ok(struct rtl_fw *rtl_fw)
{
	const struct firmware *fw = rtl_fw->fw;
	struct fw_info *fw_info = (struct fw_info *)fw->data;
	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;

	if (fw->size < FW_OPCODE_SIZE)
		return false;

	if (!fw_info->magic) {
		size_t i, size, start;
		u8 checksum = 0;

		if (fw->size < sizeof(*fw_info))
			return false;

		for (i = 0; i < fw->size; i++)
			checksum += fw->data[i];
		if (checksum != 0)
			return false;

		start = le32_to_cpu(fw_info->fw_start);
		if (start > fw->size)
			return false;

		size = le32_to_cpu(fw_info->fw_len);
		if (size > (fw->size - start) / FW_OPCODE_SIZE)
			return false;

		strscpy(rtl_fw->version, fw_info->version, RTL_VER_SIZE);

		pa->code = (__le32 *)(fw->data + start);
		pa->size = size;
	} else {
		if (fw->size % FW_OPCODE_SIZE)
			return false;

		strscpy(rtl_fw->version, rtl_fw->fw_name, RTL_VER_SIZE);

		pa->code = (__le32 *)fw->data;
		pa->size = fw->size / FW_OPCODE_SIZE;
	}

	return true;
}

static bool rtl_fw_data_ok(struct rtl_fw *rtl_fw)
{
	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
	size_t index;

	for (index = 0; index < pa->size; index++) {
		u32 action = le32_to_cpu(pa->code[index]);
		u32 val = action & 0x0000ffff;
		u32 regno = (action & 0x0fff0000) >> 16;

		switch (action >> 28) {
		case PHY_READ:
		case PHY_DATA_OR:
		case PHY_DATA_AND:
		case PHY_CLEAR_READCOUNT:
		case PHY_WRITE:
		case PHY_WRITE_PREVIOUS:
		case PHY_DELAY_MS:
			break;

		case PHY_MDIO_CHG:
			if (val > 1)
				goto out;
			break;

		case PHY_BJMPN:
			if (regno > index)
				goto out;
			break;
		case PHY_READCOUNT_EQ_SKIP:
			if (index + 2 >= pa->size)
				goto out;
			break;
		case PHY_COMP_EQ_SKIPN:
		case PHY_COMP_NEQ_SKIPN:
		case PHY_SKIPN:
			if (index + 1 + regno >= pa->size)
				goto out;
			break;

		default:
			dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action);
			return false;
		}
	}

	return true;
out:
	dev_err(rtl_fw->dev, "Out of range of firmware\n");
	return false;
}

void rtl_fw_write_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
{
	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
	rtl_fw_write_t fw_write = rtl_fw->phy_write;
	rtl_fw_read_t fw_read = rtl_fw->phy_read;
	int predata = 0, count = 0;
	size_t index;

	for (index = 0; index < pa->size; index++) {
		u32 action = le32_to_cpu(pa->code[index]);
		u32 data = action & 0x0000ffff;
		u32 regno = (action & 0x0fff0000) >> 16;
		enum rtl_fw_opcode opcode = action >> 28;

		if (!action)
			break;

		switch (opcode) {
		case PHY_READ:
			predata = fw_read(tp, regno);
			count++;
			break;
		case PHY_DATA_OR:
			predata |= data;
			break;
		case PHY_DATA_AND:
			predata &= data;
			break;
		case PHY_BJMPN:
			index -= (regno + 1);
			break;
		case PHY_MDIO_CHG:
			if (data) {
				fw_write = rtl_fw->mac_mcu_write;
				fw_read = rtl_fw->mac_mcu_read;
			} else {
				fw_write = rtl_fw->phy_write;
				fw_read = rtl_fw->phy_read;
			}

			break;
		case PHY_CLEAR_READCOUNT:
			count = 0;
			break;
		case PHY_WRITE:
			fw_write(tp, regno, data);
			break;
		case PHY_READCOUNT_EQ_SKIP:
			if (count == data)
				index++;
			break;
		case PHY_COMP_EQ_SKIPN:
			if (predata == data)
				index += regno;
			break;
		case PHY_COMP_NEQ_SKIPN:
			if (predata != data)
				index += regno;
			break;
		case PHY_WRITE_PREVIOUS:
			fw_write(tp, regno, predata);
			break;
		case PHY_SKIPN:
			index += regno;
			break;
		case PHY_DELAY_MS:
			msleep(data);
			break;
		}
	}
}

void rtl_fw_release_firmware(struct rtl_fw *rtl_fw)
{
	release_firmware(rtl_fw->fw);
}

int rtl_fw_request_firmware(struct rtl_fw *rtl_fw)
{
	int rc;

	rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev);
	if (rc < 0)
		goto out;

	if (!rtl_fw_format_ok(rtl_fw) || !rtl_fw_data_ok(rtl_fw)) {
		release_firmware(rtl_fw->fw);
		rc = -EINVAL;
		goto out;
	}

	return 0;
out:
	dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n",
		rtl_fw->fw_name, rc);
	return rc;
}
