GNU Linux-libre 4.14.266-gnu1
[releases.git] / drivers / net / wireless / realtek / rtlwifi / rtl8723com / fw_common.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2009-2014  Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * The full GNU General Public License is included in this distribution in the
15  * file called LICENSE.
16  *
17  * Contact Information:
18  * wlanfae <wlanfae@realtek.com>
19  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20  * Hsinchu 300, Taiwan.
21  *
22  * Larry Finger <Larry.Finger@lwfinger.net>
23  *
24  *****************************************************************************/
25
26 #include "../wifi.h"
27 #include "../pci.h"
28 #include "../base.h"
29 #include "../efuse.h"
30 #include "fw_common.h"
31 #include <linux/module.h>
32
33 void rtl8723_enable_fw_download(struct ieee80211_hw *hw, bool enable)
34 {
35         struct rtl_priv *rtlpriv = rtl_priv(hw);
36         u8 tmp;
37
38         if (enable) {
39                 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
40                 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1,
41                                tmp | 0x04);
42
43                 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
44                 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
45
46                 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
47                 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
48         } else {
49                 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
50                 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
51
52                 rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
53         }
54 }
55 EXPORT_SYMBOL_GPL(rtl8723_enable_fw_download);
56
57 void rtl8723_write_fw(struct ieee80211_hw *hw,
58                       enum version_8723e version,
59                       u8 *buffer, u32 size, u8 max_page)
60 {
61         struct rtl_priv *rtlpriv = rtl_priv(hw);
62         u8 *bufferptr = buffer;
63         u32 page_nums, remain_size;
64         u32 page, offset;
65
66         RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);
67
68         rtl_fill_dummy(bufferptr, &size);
69
70         page_nums = size / FW_8192C_PAGE_SIZE;
71         remain_size = size % FW_8192C_PAGE_SIZE;
72
73         if (page_nums > max_page) {
74                 pr_err("Page numbers should not greater than %d\n",
75                        max_page);
76         }
77         for (page = 0; page < page_nums; page++) {
78                 offset = page * FW_8192C_PAGE_SIZE;
79                 rtl_fw_page_write(hw, page, (bufferptr + offset),
80                                   FW_8192C_PAGE_SIZE);
81         }
82
83         if (remain_size) {
84                 offset = page_nums * FW_8192C_PAGE_SIZE;
85                 page = page_nums;
86                 rtl_fw_page_write(hw, page, (bufferptr + offset), remain_size);
87         }
88         RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW write done.\n");
89 }
90 EXPORT_SYMBOL_GPL(rtl8723_write_fw);
91
92 void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw)
93 {
94         u8 u1b_tmp;
95         u8 delay = 100;
96         struct rtl_priv *rtlpriv = rtl_priv(hw);
97
98         rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
99         u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
100
101         while (u1b_tmp & BIT(2)) {
102                 delay--;
103                 if (delay == 0)
104                         break;
105                 udelay(50);
106                 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
107         }
108         if (delay == 0) {
109                 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
110                 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1,
111                                u1b_tmp&(~BIT(2)));
112         }
113 }
114 EXPORT_SYMBOL_GPL(rtl8723ae_firmware_selfreset);
115
116 void rtl8723be_firmware_selfreset(struct ieee80211_hw *hw)
117 {
118         u8 u1b_tmp;
119         struct rtl_priv *rtlpriv = rtl_priv(hw);
120
121         u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
122         rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));
123
124         u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
125         rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
126         udelay(50);
127
128         u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
129         rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0)));
130
131         u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
132         rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
133
134         RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
135                  "  _8051Reset8723be(): 8051 reset success .\n");
136 }
137 EXPORT_SYMBOL_GPL(rtl8723be_firmware_selfreset);
138
139 int rtl8723_fw_free_to_go(struct ieee80211_hw *hw, bool is_8723be,
140                           int max_count)
141 {
142         struct rtl_priv *rtlpriv = rtl_priv(hw);
143         int err = -EIO;
144         u32 counter = 0;
145         u32 value32;
146
147         do {
148                 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
149         } while ((counter++ < max_count) &&
150                  (!(value32 & FWDL_CHKSUM_RPT)));
151
152         if (counter >= max_count) {
153                 pr_err("chksum report fail ! REG_MCUFWDL:0x%08x .\n",
154                        value32);
155                 goto exit;
156         }
157         value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL) | MCUFWDL_RDY;
158         value32 &= ~WINTINI_RDY;
159         rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
160
161         if (is_8723be)
162                 rtl8723be_firmware_selfreset(hw);
163         counter = 0;
164
165         do {
166                 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
167                 if (value32 & WINTINI_RDY) {
168                         RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
169                                  "Polling FW ready success!! REG_MCUFWDL:0x%08x .\n",
170                                  value32);
171                         err = 0;
172                         goto exit;
173                 }
174
175                 mdelay(FW_8192C_POLLING_DELAY);
176
177         } while (counter++ < max_count);
178
179         pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n",
180                value32);
181
182 exit:
183         return err;
184 }
185 EXPORT_SYMBOL_GPL(rtl8723_fw_free_to_go);
186
187 int rtl8723_download_fw(struct ieee80211_hw *hw,
188                         bool is_8723be, int max_count)
189 {
190         struct rtl_priv *rtlpriv = rtl_priv(hw);
191         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
192         struct rtlwifi_firmware_header *pfwheader;
193         u8 *pfwdata;
194         u32 fwsize;
195         int err;
196         enum version_8723e version = rtlhal->version;
197         int max_page;
198
199         if (!rtlhal->pfirmware)
200                 return 1;
201
202         pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
203         pfwdata = rtlhal->pfirmware;
204         fwsize = rtlhal->fwsize;
205
206         if (!is_8723be)
207                 max_page = 6;
208         else
209                 max_page = 8;
210         if (rtlpriv->cfg->ops->is_fw_header(pfwheader)) {
211                 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
212                          "Firmware Version(%d), Signature(%#x), Size(%d)\n",
213                          pfwheader->version, pfwheader->signature,
214                          (int)sizeof(struct rtlwifi_firmware_header));
215
216                 pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
217                 fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
218         }
219
220         if (rtl_read_byte(rtlpriv, REG_MCUFWDL)&BIT(7)) {
221                 if (is_8723be)
222                         rtl8723be_firmware_selfreset(hw);
223                 else
224                         rtl8723ae_firmware_selfreset(hw);
225                 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
226         }
227         rtl8723_enable_fw_download(hw, true);
228         rtl8723_write_fw(hw, version, pfwdata, fwsize, max_page);
229         rtl8723_enable_fw_download(hw, false);
230
231         err = rtl8723_fw_free_to_go(hw, is_8723be, max_count);
232         if (err)
233                 pr_err("Firmware is not ready to run!\n");
234         return 0;
235 }
236 EXPORT_SYMBOL_GPL(rtl8723_download_fw);
237
238 bool rtl8723_cmd_send_packet(struct ieee80211_hw *hw,
239                              struct sk_buff *skb)
240 {
241         struct rtl_priv *rtlpriv = rtl_priv(hw);
242         struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
243         struct rtl8192_tx_ring *ring;
244         struct rtl_tx_desc *pdesc;
245         struct sk_buff *pskb = NULL;
246         u8 own;
247         unsigned long flags;
248
249         ring = &rtlpci->tx_ring[BEACON_QUEUE];
250
251         pskb = __skb_dequeue(&ring->queue);
252         kfree_skb(pskb);
253         spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
254
255         pdesc = &ring->desc[0];
256         own = (u8) rtlpriv->cfg->ops->get_desc((u8 *)pdesc, true, HW_DESC_OWN);
257
258         rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb);
259
260         __skb_queue_tail(&ring->queue, skb);
261
262         spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
263
264         rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
265
266         return true;
267 }
268 EXPORT_SYMBOL_GPL(rtl8723_cmd_send_packet);