cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fw_common.c (6565B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* 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	else
    189		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		else
    204			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
    218bool rtl8723_cmd_send_packet(struct ieee80211_hw *hw,
    219			     struct sk_buff *skb)
    220{
    221	struct rtl_priv *rtlpriv = rtl_priv(hw);
    222	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
    223	struct rtl8192_tx_ring *ring;
    224	struct rtl_tx_desc *pdesc;
    225	struct sk_buff *pskb = NULL;
    226	unsigned long flags;
    227
    228	ring = &rtlpci->tx_ring[BEACON_QUEUE];
    229
    230	pskb = __skb_dequeue(&ring->queue);
    231	kfree_skb(pskb);
    232	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
    233
    234	pdesc = &ring->desc[0];
    235	rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb);
    236
    237	__skb_queue_tail(&ring->queue, skb);
    238
    239	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
    240
    241	rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
    242
    243	return true;
    244}
    245EXPORT_SYMBOL_GPL(rtl8723_cmd_send_packet);