aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c
diff options
context:
space:
mode:
authorLarry Finger <Larry.Finger@lwfinger.net>2014-02-28 16:16:48 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-03-04 13:19:37 -0500
commitcbd0c8512f3b06c86849c554eb092862c46885d5 (patch)
treed48a9d4dd30e74418e7c841c74aba7f43eeb619b /drivers/net/wireless/rtlwifi/rtl8723ae/fw.c
parent0a168b48cdf7c22cf0250f62df4dde20adebf74b (diff)
rtlwifi: rtl8723ae: rtl8723-common: Copy common firmware code
The drivers for RTL8723AE and RTL8723BE have some code in common. This commit copies the common firmware routines into the shared code. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rtlwifi/rtl8723ae/fw.c')
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/fw.c260
1 files changed, 22 insertions, 238 deletions
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c
index ba1502b172a6..728b7563ad36 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c
@@ -34,199 +34,7 @@
34#include "reg.h" 34#include "reg.h"
35#include "def.h" 35#include "def.h"
36#include "fw.h" 36#include "fw.h"
37 37#include "../rtl8723com/fw_common.h"
38static void _rtl8723ae_enable_fw_download(struct ieee80211_hw *hw, bool enable)
39{
40 struct rtl_priv *rtlpriv = rtl_priv(hw);
41 u8 tmp;
42 if (enable) {
43 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
44 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
45
46 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
47 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
48
49 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
50 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
51 } else {
52 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
53 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
54
55 rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
56 }
57}
58
59static void _rtl8723ae_fw_block_write(struct ieee80211_hw *hw,
60 const u8 *buffer, u32 size)
61{
62 struct rtl_priv *rtlpriv = rtl_priv(hw);
63 u32 blockSize = sizeof(u32);
64 u8 *bufferPtr = (u8 *) buffer;
65 u32 *pu4BytePtr = (u32 *) buffer;
66 u32 i, offset, blockCount, remainSize;
67
68 blockCount = size / blockSize;
69 remainSize = size % blockSize;
70
71 for (i = 0; i < blockCount; i++) {
72 offset = i * blockSize;
73 rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
74 *(pu4BytePtr + i));
75 }
76
77 if (remainSize) {
78 offset = blockCount * blockSize;
79 bufferPtr += offset;
80 for (i = 0; i < remainSize; i++) {
81 rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
82 offset + i), *(bufferPtr + i));
83 }
84 }
85}
86
87static void _rtl8723ae_fw_page_write(struct ieee80211_hw *hw,
88 u32 page, const u8 *buffer, u32 size)
89{
90 struct rtl_priv *rtlpriv = rtl_priv(hw);
91 u8 value8;
92 u8 u8page = (u8) (page & 0x07);
93
94 value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
95
96 rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
97 _rtl8723ae_fw_block_write(hw, buffer, size);
98}
99
100static void _rtl8723ae_write_fw(struct ieee80211_hw *hw,
101 enum version_8723e version, u8 *buffer,
102 u32 size)
103{
104 struct rtl_priv *rtlpriv = rtl_priv(hw);
105 u8 *bufferPtr = (u8 *) buffer;
106 u32 page_nums, remain_size;
107 u32 page, offset;
108
109 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);
110
111 page_nums = size / FW_8192C_PAGE_SIZE;
112 remain_size = size % FW_8192C_PAGE_SIZE;
113
114 if (page_nums > 6) {
115 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
116 "Page numbers should not be greater then 6\n");
117 }
118
119 for (page = 0; page < page_nums; page++) {
120 offset = page * FW_8192C_PAGE_SIZE;
121 _rtl8723ae_fw_page_write(hw, page, (bufferPtr + offset),
122 FW_8192C_PAGE_SIZE);
123 }
124
125 if (remain_size) {
126 offset = page_nums * FW_8192C_PAGE_SIZE;
127 page = page_nums;
128 _rtl8723ae_fw_page_write(hw, page, (bufferPtr + offset),
129 remain_size);
130 }
131
132 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW write done.\n");
133}
134
135static int _rtl8723ae_fw_free_to_go(struct ieee80211_hw *hw)
136{
137 struct rtl_priv *rtlpriv = rtl_priv(hw);
138 int err = -EIO;
139 u32 counter = 0;
140 u32 value32;
141
142 do {
143 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
144 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
145 (!(value32 & FWDL_ChkSum_rpt)));
146
147 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
148 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
149 "chksum report faill ! REG_MCUFWDL:0x%08x .\n",
150 value32);
151 goto exit;
152 }
153
154 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
155 "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32);
156
157 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
158 value32 |= MCUFWDL_RDY;
159 value32 &= ~WINTINI_RDY;
160 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
161
162 counter = 0;
163
164 do {
165 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
166 if (value32 & WINTINI_RDY) {
167 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
168 "Polling FW ready success!! REG_MCUFWDL:0x%08x .\n",
169 value32);
170 err = 0;
171 goto exit;
172 }
173
174 mdelay(FW_8192C_POLLING_DELAY);
175
176 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
177
178 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
179 "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32);
180
181exit:
182 return err;
183}
184
185int rtl8723ae_download_fw(struct ieee80211_hw *hw)
186{
187 struct rtl_priv *rtlpriv = rtl_priv(hw);
188 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
189 struct rtl8723ae_firmware_header *pfwheader;
190 u8 *pfwdata;
191 u32 fwsize;
192 int err;
193 enum version_8723e version = rtlhal->version;
194
195 if (!rtlhal->pfirmware)
196 return 1;
197
198 pfwheader = (struct rtl8723ae_firmware_header *)rtlhal->pfirmware;
199 pfwdata = (u8 *) rtlhal->pfirmware;
200 fwsize = rtlhal->fwsize;
201
202 if (IS_FW_HEADER_EXIST(pfwheader)) {
203 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
204 "Firmware Version(%d), Signature(%#x),Size(%d)\n",
205 pfwheader->version, pfwheader->signature,
206 (int)sizeof(struct rtl8723ae_firmware_header));
207
208 pfwdata = pfwdata + sizeof(struct rtl8723ae_firmware_header);
209 fwsize = fwsize - sizeof(struct rtl8723ae_firmware_header);
210 }
211
212 if (rtl_read_byte(rtlpriv, REG_MCUFWDL)&BIT(7)) {
213 rtl8723ae_firmware_selfreset(hw);
214 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
215 }
216 _rtl8723ae_enable_fw_download(hw, true);
217 _rtl8723ae_write_fw(hw, version, pfwdata, fwsize);
218 _rtl8723ae_enable_fw_download(hw, false);
219
220 err = _rtl8723ae_fw_free_to_go(hw);
221 if (err) {
222 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
223 "Firmware is not ready to run!\n");
224 } else {
225 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
226 "Firmware is ready to run!\n");
227 }
228 return 0;
229}
230 38
231static bool rtl8723ae_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum) 39static bool rtl8723ae_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
232{ 40{
@@ -463,50 +271,6 @@ void rtl8723ae_fill_h2c_cmd(struct ieee80211_hw *hw,
463 return; 271 return;
464} 272}
465 273
466void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw)
467{
468 u8 u1tmp;
469 u8 delay = 100;
470 struct rtl_priv *rtlpriv = rtl_priv(hw);
471
472 rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
473 u1tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
474
475 while (u1tmp & BIT(2)) {
476 delay--;
477 if (delay == 0)
478 break;
479 udelay(50);
480 u1tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
481 }
482 if (delay == 0) {
483 u1tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
484 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, u1tmp&(~BIT(2)));
485 }
486}
487
488void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
489{
490 struct rtl_priv *rtlpriv = rtl_priv(hw);
491 u8 u1_h2c_set_pwrmode[3] = { 0 };
492 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
493
494 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
495
496 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
497 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
498 (rtlpriv->mac80211.p2p) ?
499 ppsc->smart_ps : 1);
500 SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
501 ppsc->reg_max_lps_awakeintvl);
502
503 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
504 "rtl8723ae_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
505 u1_h2c_set_pwrmode, 3);
506 rtl8723ae_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
507
508}
509
510static bool _rtl8723ae_cmd_send_packet(struct ieee80211_hw *hw, 274static bool _rtl8723ae_cmd_send_packet(struct ieee80211_hw *hw,
511 struct sk_buff *skb) 275 struct sk_buff *skb)
512{ 276{
@@ -812,7 +576,6 @@ void rtl8723ae_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
812 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); 576 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
813 577
814 p2p_ps_offload->offload_en = 1; 578 p2p_ps_offload->offload_en = 1;
815
816 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { 579 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
817 p2p_ps_offload->role = 1; 580 p2p_ps_offload->role = 1;
818 p2p_ps_offload->allstasleep = 0; 581 p2p_ps_offload->allstasleep = 0;
@@ -836,3 +599,24 @@ void rtl8723ae_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
836 } 599 }
837 rtl8723ae_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload); 600 rtl8723ae_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload);
838} 601}
602
603void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
604{
605 struct rtl_priv *rtlpriv = rtl_priv(hw);
606 u8 u1_h2c_set_pwrmode[3] = { 0 };
607 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
608
609 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
610
611 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
612 SET_H2CCMD_PWRMODE_PARM_SMART_PS_23A(u1_h2c_set_pwrmode,
613 (rtlpriv->mac80211.p2p) ?
614 ppsc->smart_ps : 1);
615 SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
616 ppsc->reg_max_lps_awakeintvl);
617
618 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
619 "rtl8723ae_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
620 u1_h2c_set_pwrmode, 3);
621 rtl8723ae_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
622}