brintos

brintos / linux-shallow public Read only

0
0
Text · 5.7 KiB · 50b79cf Raw
218 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright(c) 2009-2014  Realtek Corporation.*/3 4#include "../wifi.h"5#include "../pci.h"6#include "../base.h"7#include "../efuse.h"8#include "fw_common.h"9#include <linux/module.h>10 11void rtl8723_enable_fw_download(struct ieee80211_hw *hw, bool enable)12{13	struct rtl_priv *rtlpriv = rtl_priv(hw);14	u8 tmp;15 16	if (enable) {17		tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);18		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1,19			       tmp | 0x04);20 21		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);22		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);23 24		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);25		rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);26	} else {27		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);28		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);29 30		rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);31	}32}33EXPORT_SYMBOL_GPL(rtl8723_enable_fw_download);34 35void rtl8723_write_fw(struct ieee80211_hw *hw,36		      enum version_8723e version,37		      u8 *buffer, u32 size, u8 max_page)38{39	struct rtl_priv *rtlpriv = rtl_priv(hw);40	u8 *bufferptr = buffer;41	u32 page_nums, remain_size;42	u32 page, offset;43 44	rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);45 46	rtl_fill_dummy(bufferptr, &size);47 48	page_nums = size / FW_8192C_PAGE_SIZE;49	remain_size = size % FW_8192C_PAGE_SIZE;50 51	if (page_nums > max_page) {52		pr_err("Page numbers should not greater than %d\n",53		       max_page);54	}55	for (page = 0; page < page_nums; page++) {56		offset = page * FW_8192C_PAGE_SIZE;57		rtl_fw_page_write(hw, page, (bufferptr + offset),58				  FW_8192C_PAGE_SIZE);59	}60 61	if (remain_size) {62		offset = page_nums * FW_8192C_PAGE_SIZE;63		page = page_nums;64		rtl_fw_page_write(hw, page, (bufferptr + offset), remain_size);65	}66	rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE, "FW write done.\n");67}68EXPORT_SYMBOL_GPL(rtl8723_write_fw);69 70void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw)71{72	u8 u1b_tmp;73	u8 delay = 100;74	struct rtl_priv *rtlpriv = rtl_priv(hw);75 76	rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);77	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);78 79	while (u1b_tmp & BIT(2)) {80		delay--;81		if (delay == 0)82			break;83		udelay(50);84		u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);85	}86	if (delay == 0) {87		u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);88		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1,89			       u1b_tmp&(~BIT(2)));90	}91}92EXPORT_SYMBOL_GPL(rtl8723ae_firmware_selfreset);93 94void rtl8723be_firmware_selfreset(struct ieee80211_hw *hw)95{96	u8 u1b_tmp;97	struct rtl_priv *rtlpriv = rtl_priv(hw);98 99	u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);100	rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));101 102	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);103	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));104	udelay(50);105 106	u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);107	rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0)));108 109	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);110	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));111 112	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,113		"_8051Reset8723be(): 8051 reset success .\n");114}115EXPORT_SYMBOL_GPL(rtl8723be_firmware_selfreset);116 117int rtl8723_fw_free_to_go(struct ieee80211_hw *hw, bool is_8723be,118			  int max_count)119{120	struct rtl_priv *rtlpriv = rtl_priv(hw);121	int err = -EIO;122	u32 counter = 0;123	u32 value32;124 125	do {126		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);127	} while ((counter++ < max_count) &&128		 (!(value32 & FWDL_CHKSUM_RPT)));129 130	if (counter >= max_count) {131		pr_err("chksum report fail ! REG_MCUFWDL:0x%08x .\n",132		       value32);133		goto exit;134	}135	value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL) | MCUFWDL_RDY;136	value32 &= ~WINTINI_RDY;137	rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);138 139	if (is_8723be)140		rtl8723be_firmware_selfreset(hw);141	counter = 0;142 143	do {144		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);145		if (value32 & WINTINI_RDY) {146			rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE,147				"Polling FW ready success!! REG_MCUFWDL:0x%08x .\n",148				value32);149			err = 0;150			goto exit;151		}152 153		mdelay(FW_8192C_POLLING_DELAY);154 155	} while (counter++ < max_count);156 157	pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n",158	       value32);159 160exit:161	return err;162}163EXPORT_SYMBOL_GPL(rtl8723_fw_free_to_go);164 165int rtl8723_download_fw(struct ieee80211_hw *hw,166			bool is_8723be, int max_count)167{168	struct rtl_priv *rtlpriv = rtl_priv(hw);169	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));170	struct rtlwifi_firmware_header *pfwheader;171	u8 *pfwdata;172	u32 fwsize;173	int err;174	enum version_8723e version = rtlhal->version;175	int max_page;176 177	if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)178		return 1;179 180	pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;181	rtlhal->fw_version = le16_to_cpu(pfwheader->version);182	rtlhal->fw_subversion = pfwheader->subversion;183	pfwdata = rtlhal->pfirmware;184	fwsize = rtlhal->fwsize;185 186	if (!is_8723be)187		max_page = 6;188	else189		max_page = 8;190	if (rtlpriv->cfg->ops->is_fw_header(pfwheader)) {191		rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD,192			"Firmware Version(%d), Signature(%#x), Size(%d)\n",193			pfwheader->version, pfwheader->signature,194			(int)sizeof(struct rtlwifi_firmware_header));195 196		pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);197		fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);198	}199 200	if (rtl_read_byte(rtlpriv, REG_MCUFWDL)&BIT(7)) {201		if (is_8723be)202			rtl8723be_firmware_selfreset(hw);203		else204			rtl8723ae_firmware_selfreset(hw);205		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);206	}207	rtl8723_enable_fw_download(hw, true);208	rtl8723_write_fw(hw, version, pfwdata, fwsize, max_page);209	rtl8723_enable_fw_download(hw, false);210 211	err = rtl8723_fw_free_to_go(hw, is_8723be, max_count);212	if (err)213		pr_err("Firmware is not ready to run!\n");214	return 0;215}216EXPORT_SYMBOL_GPL(rtl8723_download_fw);217 218