// SPDX-License-Identifier: GPL-2.0
/******************************************************************************
 *
 * Copyright(c) 2009-2013  Realtek Corporation.
 *
 * Contact Information:
 * wlanfae <wlanfae@realtek.com>
 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
 * Hsinchu 300, Taiwan.
 *
 * Larry Finger <Larry.Finger@lwfinger.net>
 *
 *****************************************************************************/

#include "fw.h"
#include "drv_types.h"
#include "usb_ops_linux.h"
#include "rtl8188e_spec.h"
#include "rtl8188e_hal.h"

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

static void _rtl88e_enable_fw_download(struct adapter *adapt, bool enable)
{
	u8 tmp;

	if (enable) {
		tmp = usb_read8(adapt, REG_MCUFWDL);
		usb_write8(adapt, REG_MCUFWDL, tmp | 0x01);

		tmp = usb_read8(adapt, REG_MCUFWDL + 2);
		usb_write8(adapt, REG_MCUFWDL + 2, tmp & 0xf7);
	} else {
		tmp = usb_read8(adapt, REG_MCUFWDL);
		usb_write8(adapt, REG_MCUFWDL, tmp & 0xfe);

		usb_write8(adapt, REG_MCUFWDL + 1, 0x00);
	}
}

static void _rtl88e_fw_block_write(struct adapter *adapt,
				   const u8 *buffer, u32 size)
{
	u32 blk_sz = sizeof(u32);
	const u8 *byte_buffer;
	const u32 *dword_buffer = (u32 *)buffer;
	u32 i, write_address, blk_cnt, remain;

	blk_cnt = size / blk_sz;
	remain = size % blk_sz;

	write_address = FW_8192C_START_ADDRESS;

	for (i = 0; i < blk_cnt; i++, write_address += blk_sz)
		usb_write32(adapt, write_address, dword_buffer[i]);

	byte_buffer = buffer + blk_cnt * blk_sz;
	for (i = 0; i < remain; i++, write_address++)
		usb_write8(adapt, write_address, byte_buffer[i]);
}

static void _rtl88e_fw_page_write(struct adapter *adapt,
				  u32 page, const u8 *buffer, u32 size)
{
	u8 value8;
	u8 u8page = (u8)(page & 0x07);

	value8 = (usb_read8(adapt, REG_MCUFWDL + 2) & 0xF8) | u8page;

	usb_write8(adapt, (REG_MCUFWDL + 2), value8);
	_rtl88e_fw_block_write(adapt, buffer, size);
}

static void _rtl88e_write_fw(struct adapter *adapt, u8 *buffer, u32 size)
{
	u8 *buf_ptr = buffer;
	u32 page_no, remain;
	u32 page, offset;

	page_no = size / FW_8192C_PAGE_SIZE;
	remain = size % FW_8192C_PAGE_SIZE;

	for (page = 0; page < page_no; page++) {
		offset = page * FW_8192C_PAGE_SIZE;
		_rtl88e_fw_page_write(adapt, page, (buf_ptr + offset),
				      FW_8192C_PAGE_SIZE);
	}

	if (remain) {
		offset = page_no * FW_8192C_PAGE_SIZE;
		page = page_no;
		_rtl88e_fw_page_write(adapt, page, (buf_ptr + offset), remain);
	}
}

static void rtl88e_firmware_selfreset(struct adapter *adapt)
{
	u8 u1b_tmp;

	u1b_tmp = usb_read8(adapt, REG_SYS_FUNC_EN + 1);
	usb_write8(adapt, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
	usb_write8(adapt, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
}

static int _rtl88e_fw_free_to_go(struct adapter *adapt)
{
	int err = -EIO;
	u32 counter = 0;
	u32 value32;

	do {
		value32 = usb_read32(adapt, REG_MCUFWDL);
		if (value32 & FWDL_CHKSUM_RPT)
			break;
	} while (counter++ < POLLING_READY_TIMEOUT_COUNT);

	if (counter >= POLLING_READY_TIMEOUT_COUNT)
		goto exit;

	value32 = usb_read32(adapt, REG_MCUFWDL);
	value32 |= MCUFWDL_RDY;
	value32 &= ~WINTINI_RDY;
	usb_write32(adapt, REG_MCUFWDL, value32);

	rtl88e_firmware_selfreset(adapt);
	counter = 0;

	do {
		value32 = usb_read32(adapt, REG_MCUFWDL);
		if (value32 & WINTINI_RDY) {
			err = 0;
			goto exit;
		}

		udelay(FW_8192C_POLLING_DELAY);

	} while (counter++ < POLLING_READY_TIMEOUT_COUNT);

exit:
	return err;
}

int rtl88eu_download_fw(struct adapter *adapt)
{
	struct dvobj_priv *dvobj = adapter_to_dvobj(adapt);
	struct device *device = dvobj_to_dev(dvobj);
	const struct firmware *fw;
	static const char fw_name[] = "rtlwifi/rtl8188eufw.bin";
	struct rtl92c_firmware_header *pfwheader = NULL;
	u8 *download_data, *fw_data;
	size_t download_size;
	unsigned int trailing_zeros_length;

	if (request_firmware(&fw, fw_name, device)) {
		dev_err(device, "Firmware %s not available\n", fw_name);
		return -ENOENT;
	}

	if (fw->size > FW_8188E_SIZE) {
		dev_err(device, "Firmware size exceed 0x%X. Check it.\n",
			FW_8188E_SIZE);
		release_firmware(fw);
		return -1;
	}

	trailing_zeros_length = (4 - fw->size % 4) % 4;

	fw_data = kmalloc(fw->size + trailing_zeros_length, GFP_KERNEL);
	if (!fw_data) {
		release_firmware(fw);
		return -ENOMEM;
	}

	memcpy(fw_data, fw->data, fw->size);
	memset(fw_data + fw->size, 0, trailing_zeros_length);

	pfwheader = (struct rtl92c_firmware_header *)fw_data;

	if (IS_FW_HEADER_EXIST(pfwheader)) {
		download_data = fw_data + 32;
		download_size = fw->size + trailing_zeros_length - 32;
	} else {
		download_data = fw_data;
		download_size = fw->size + trailing_zeros_length;
	}

	release_firmware(fw);

	if (usb_read8(adapt, REG_MCUFWDL) & RAM_DL_SEL) {
		usb_write8(adapt, REG_MCUFWDL, 0);
		rtl88e_firmware_selfreset(adapt);
	}
	_rtl88e_enable_fw_download(adapt, true);
	usb_write8(adapt, REG_MCUFWDL,
		   usb_read8(adapt, REG_MCUFWDL) | FWDL_CHKSUM_RPT);
	_rtl88e_write_fw(adapt, download_data, download_size);
	_rtl88e_enable_fw_download(adapt, false);

	kfree(fw_data);
	return _rtl88e_fw_free_to_go(adapt);
}
