]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/rt2860/common/rtmp_mcu.c
Staging: rt{2860,2870}sta: Use request_firmware() to load firmware
[net-next-2.6.git] / drivers / staging / rt2860 / common / rtmp_mcu.c
CommitLineData
ca97b838
BZ
1/*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
24 * *
25 *************************************************************************
26
27 Module Name:
28 rtmp_mcu.c
29
30 Abstract:
31 Miniport generic portion header file
32
33 Revision History:
34 Who When What
35 -------- ---------- ----------------------------------------------
36*/
37
ca97b838
BZ
38#include "../rt_config.h"
39
c22202fa
BH
40#include <linux/crc-ccitt.h>
41#include <linux/firmware.h>
ca97b838 42
ca97b838 43#ifdef RTMP_MAC_USB
ca97b838 44
c22202fa
BH
45#define FIRMWAREIMAGE_LENGTH 0x1000
46
47#define FIRMWARE_2870_MIN_VERSION 12
48#define FIRMWARE_2870_FILENAME "rt2870.bin"
49MODULE_FIRMWARE(FIRMWARE_2870_FILENAME);
50
51#define FIRMWARE_3070_MIN_VERSION 17
52#define FIRMWARE_3070_FILENAME "rt3070.bin"
53MODULE_FIRMWARE(FIRMWARE_3070_FILENAME);
ca97b838 54
c22202fa
BH
55#define FIRMWARE_3071_MIN_VERSION 17
56#define FIRMWARE_3071_FILENAME "rt3071.bin" /* for RT3071/RT3072 */
57MODULE_FIRMWARE(FIRMWARE_3071_FILENAME);
ca97b838 58
c22202fa
BH
59#else /* RTMP_MAC_PCI */
60
61#define FIRMWAREIMAGE_LENGTH 0x2000
62
63#define FIRMWARE_2860_MIN_VERSION 11
64#define FIRMWARE_2860_FILENAME "rt2860.bin"
65MODULE_FIRMWARE(FIRMWARE_2860_FILENAME);
66
67#define FIRMWARE_3090_MIN_VERSION 19
68#define FIRMWARE_3090_FILENAME "rt3090.bin" /* for RT3090/RT3390 */
69MODULE_FIRMWARE(FIRMWARE_3090_FILENAME);
70
71#endif
ca97b838
BZ
72
73/*
74 ========================================================================
75
76 Routine Description:
77 erase 8051 firmware image in MAC ASIC
78
79 Arguments:
80 Adapter Pointer to our adapter
81
82 IRQL = PASSIVE_LEVEL
83
84 ========================================================================
85*/
62eb734b 86int RtmpAsicEraseFirmware(struct rt_rtmp_adapter *pAd)
ca97b838 87{
51126deb 88 unsigned long i;
ca97b838 89
96b3c83d 90 for (i = 0; i < MAX_FIRMWARE_IMAGE_SIZE; i += 4)
ca97b838
BZ
91 RTMP_IO_WRITE32(pAd, FIRMWARE_IMAGE_BASE + i, 0);
92
93 return 0;
94}
95
c22202fa
BH
96static const struct firmware *rtmp_get_firmware(struct rt_rtmp_adapter *adapter)
97{
98 const char *name;
99 const struct firmware *fw = NULL;
100 u8 min_version;
101 struct device *dev;
102 int err;
103
104 if (adapter->firmware)
105 return adapter->firmware;
106
107#ifdef RTMP_MAC_USB
108 if (IS_RT3071(adapter)) {
109 name = FIRMWARE_3071_FILENAME;
110 min_version = FIRMWARE_3071_MIN_VERSION;
111 } else if (IS_RT3070(adapter)) {
112 name = FIRMWARE_3070_FILENAME;
113 min_version = FIRMWARE_3070_MIN_VERSION;
114 } else {
115 name = FIRMWARE_2870_FILENAME;
116 min_version = FIRMWARE_2870_MIN_VERSION;
117 }
118 dev = &((struct os_cookie *)adapter->OS_Cookie)->pUsb_Dev->dev;
119#else /* RTMP_MAC_PCI */
120 if (IS_RT3090(adapter) || IS_RT3390(adapter)) {
121 name = FIRMWARE_3090_FILENAME;
122 min_version = FIRMWARE_3090_MIN_VERSION;
123 } else {
124 name = FIRMWARE_2860_FILENAME;
125 min_version = FIRMWARE_2860_MIN_VERSION;
126 }
127 dev = &((struct os_cookie *)adapter->OS_Cookie)->pci_dev->dev;
128#endif
129
130 err = request_firmware(&fw, name, dev);
131 if (err) {
132 dev_err(dev, "firmware file %s request failed (%d)\n",
133 name, err);
134 return NULL;
135 }
136
137 if (fw->size < FIRMWAREIMAGE_LENGTH) {
138 dev_err(dev, "firmware file %s size is invalid\n", name);
139 goto invalid;
140 }
141
142 /* is it new enough? */
143 adapter->FirmwareVersion = fw->data[FIRMWAREIMAGE_LENGTH - 3];
144 if (adapter->FirmwareVersion < min_version) {
145 dev_err(dev,
146 "firmware file %s is too old;"
147 " driver requires v%d or later\n",
148 name, min_version);
149 goto invalid;
150 }
151
152 /* is the internal CRC correct? */
153 if (crc_ccitt(0xffff, fw->data, FIRMWAREIMAGE_LENGTH - 2) !=
154 (fw->data[FIRMWAREIMAGE_LENGTH - 2] |
155 (fw->data[FIRMWAREIMAGE_LENGTH - 1] << 8))) {
156 dev_err(dev, "firmware file %s failed internal CRC\n", name);
157 goto invalid;
158 }
159
160 adapter->firmware = fw;
161 return fw;
162
163invalid:
164 release_firmware(fw);
165 return NULL;
166}
167
ca97b838
BZ
168/*
169 ========================================================================
170
171 Routine Description:
172 Load 8051 firmware file into MAC ASIC
173
174 Arguments:
175 Adapter Pointer to our adapter
176
177 Return Value:
178 NDIS_STATUS_SUCCESS firmware image load ok
179 NDIS_STATUS_FAILURE image not found
180
181 IRQL = PASSIVE_LEVEL
182
183 ========================================================================
184*/
62eb734b 185int RtmpAsicLoadFirmware(struct rt_rtmp_adapter *pAd)
ca97b838 186{
c22202fa 187 const struct firmware *fw;
51126deb 188 int Status = NDIS_STATUS_SUCCESS;
c22202fa 189 unsigned long Index;
51126deb 190 u32 MacReg = 0;
ca97b838 191
c22202fa
BH
192 fw = rtmp_get_firmware(pAd);
193 if (!fw)
194 return NDIS_STATUS_FAILURE;
ca97b838 195
c22202fa 196 RTMP_WRITE_FIRMWARE(pAd, fw->data, FIRMWAREIMAGE_LENGTH);
ca97b838 197
ca97b838
BZ
198 /* check if MCU is ready */
199 Index = 0;
96b3c83d 200 do {
ca97b838
BZ
201 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MacReg);
202
203 if (MacReg & 0x80)
204 break;
205
206 RTMPusecDelay(1000);
207 } while (Index++ < 1000);
208
96b3c83d
BZ
209 if (Index > 1000) {
210 DBGPRINT(RT_DEBUG_ERROR,
d6dbc012 211 ("NICLoadFirmware: MCU is not ready\n"));
ca97b838
BZ
212 Status = NDIS_STATUS_FAILURE;
213 }
214
96b3c83d 215 DBGPRINT(RT_DEBUG_TRACE, ("<=== %s (status=%d)\n", __func__, Status));
ca97b838 216
96b3c83d 217 return Status;
ca97b838
BZ
218}
219
62eb734b 220int RtmpAsicSendCommandToMcu(struct rt_rtmp_adapter *pAd,
51126deb
BZ
221 u8 Command,
222 u8 Token, u8 Arg0, u8 Arg1)
ca97b838 223{
96b3c83d
BZ
224 HOST_CMD_CSR_STRUC H2MCmd;
225 H2M_MAILBOX_STRUC H2MMailbox;
51126deb 226 unsigned long i = 0;
ca97b838 227
e44fd1cf 228#ifdef PCIE_PS_SUPPORT
ec278fa2
BZ
229 /* 3090F power solution 3 has hw limitation that needs to ban all mcu command */
230 /* when firmware is in radio state. For other chip doesn't have this limitation. */
96b3c83d
BZ
231 if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))
232 && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd)
233 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
234 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) {
e44fd1cf
BZ
235 RTMP_SEM_LOCK(&pAd->McuCmdLock);
236 if ((pAd->brt30xxBanMcuCmd == TRUE)
96b3c83d 237 && (Command != WAKE_MCU_CMD) && (Command != RFOFF_MCU_CMD)) {
e44fd1cf 238 RTMP_SEM_UNLOCK(&pAd->McuCmdLock);
96b3c83d
BZ
239 DBGPRINT(RT_DEBUG_TRACE,
240 (" Ban Mcu Cmd %x in sleep mode\n", Command));
e44fd1cf 241 return FALSE;
96b3c83d
BZ
242 } else if ((Command == SLEEP_MCU_CMD)
243 || (Command == RFOFF_MCU_CMD)) {
e44fd1cf 244 pAd->brt30xxBanMcuCmd = TRUE;
96b3c83d 245 } else if (Command != WAKE_MCU_CMD) {
e44fd1cf
BZ
246 pAd->brt30xxBanMcuCmd = FALSE;
247 }
248
249 RTMP_SEM_UNLOCK(&pAd->McuCmdLock);
250
251 }
96b3c83d
BZ
252 if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))
253 && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd)
254 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
255 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
256 && (Command == WAKE_MCU_CMD)) {
257
258 do {
259 RTMP_IO_FORCE_READ32(pAd, H2M_MAILBOX_CSR,
260 &H2MMailbox.word);
e44fd1cf
BZ
261 if (H2MMailbox.field.Owner == 0)
262 break;
263
264 RTMPusecDelay(2);
96b3c83d
BZ
265 DBGPRINT(RT_DEBUG_INFO,
266 ("AsicSendCommanToMcu::Mail box is busy\n"));
267 } while (i++ < 100);
e44fd1cf 268
23a51a80 269 if (i > 100) {
e44fd1cf
BZ
270 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
271 return FALSE;
272 }
273
ec278fa2 274 H2MMailbox.field.Owner = 1; /* pass ownership to MCU */
e44fd1cf
BZ
275 H2MMailbox.field.CmdToken = Token;
276 H2MMailbox.field.HighByte = Arg1;
96b3c83d 277 H2MMailbox.field.LowByte = Arg0;
e44fd1cf
BZ
278 RTMP_IO_FORCE_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
279
96b3c83d
BZ
280 H2MCmd.word = 0;
281 H2MCmd.field.HostCommand = Command;
e44fd1cf
BZ
282 RTMP_IO_FORCE_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
283
96b3c83d 284 } else
ec278fa2 285#endif /* PCIE_PS_SUPPORT // */
e44fd1cf 286 {
96b3c83d
BZ
287 do {
288 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
289 if (H2MMailbox.field.Owner == 0)
290 break;
ca97b838 291
96b3c83d
BZ
292 RTMPusecDelay(2);
293 } while (i++ < 100);
ca97b838 294
96b3c83d 295 if (i > 100) {
ca97b838 296#ifdef RTMP_MAC_PCI
ec278fa2 297#endif /* RTMP_MAC_PCI // */
96b3c83d
BZ
298 {
299 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
300 }
301 return FALSE;
ca97b838 302 }
ca97b838 303#ifdef RTMP_MAC_PCI
ec278fa2 304#endif /* RTMP_MAC_PCI // */
ca97b838 305
ec278fa2 306 H2MMailbox.field.Owner = 1; /* pass ownership to MCU */
96b3c83d
BZ
307 H2MMailbox.field.CmdToken = Token;
308 H2MMailbox.field.HighByte = Arg1;
309 H2MMailbox.field.LowByte = Arg0;
310 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
ca97b838 311
96b3c83d
BZ
312 H2MCmd.word = 0;
313 H2MCmd.field.HostCommand = Command;
314 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
ca97b838 315
96b3c83d
BZ
316 if (Command != 0x80) {
317 }
ca97b838 318 }
e44fd1cf 319#ifdef PCIE_PS_SUPPORT
ec278fa2
BZ
320 /* 3090 MCU Wakeup command needs more time to be stable. */
321 /* Before stable, don't issue other MCU command to prevent from firmware error. */
96b3c83d
BZ
322 if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))
323 && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd)
324 && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
325 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
326 && (Command == WAKE_MCU_CMD)) {
e44fd1cf 327 RTMPusecDelay(2000);
ec278fa2
BZ
328 /*Put this is after RF programming. */
329 /*NdisAcquireSpinLock(&pAd->McuCmdLock); */
330 /*pAd->brt30xxBanMcuCmd = FALSE; */
331 /*NdisReleaseSpinLock(&pAd->McuCmdLock); */
e44fd1cf 332 }
ec278fa2 333#endif /* PCIE_PS_SUPPORT // */
ca97b838
BZ
334
335 return TRUE;
336}