• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/staging/rt2860/common/
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
38#include	"../rt_config.h"
39
40#include <linux/crc-ccitt.h>
41#include <linux/firmware.h>
42
43#ifdef RTMP_MAC_USB
44
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);
54
55#define FIRMWARE_3071_MIN_VERSION	17
56#define FIRMWARE_3071_FILENAME		"rt3071.bin"	/* for RT3071/RT3072 */
57MODULE_FIRMWARE(FIRMWARE_3071_FILENAME);
58
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
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*/
86int RtmpAsicEraseFirmware(struct rt_rtmp_adapter *pAd)
87{
88	unsigned long i;
89
90	for (i = 0; i < MAX_FIRMWARE_IMAGE_SIZE; i += 4)
91		RTMP_IO_WRITE32(pAd, FIRMWARE_IMAGE_BASE + i, 0);
92
93	return 0;
94}
95
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
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*/
185int RtmpAsicLoadFirmware(struct rt_rtmp_adapter *pAd)
186{
187	const struct firmware *fw;
188	int Status = NDIS_STATUS_SUCCESS;
189	unsigned long Index;
190	u32 MacReg = 0;
191
192	fw = rtmp_get_firmware(pAd);
193	if (!fw)
194		return NDIS_STATUS_FAILURE;
195
196	RTMP_WRITE_FIRMWARE(pAd, fw->data, FIRMWAREIMAGE_LENGTH);
197
198	/* check if MCU is ready */
199	Index = 0;
200	do {
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
209	if (Index > 1000) {
210		DBGPRINT(RT_DEBUG_ERROR,
211			 ("NICLoadFirmware: MCU is not ready\n"));
212		Status = NDIS_STATUS_FAILURE;
213	}
214
215	DBGPRINT(RT_DEBUG_TRACE, ("<=== %s (status=%d)\n", __func__, Status));
216
217	return Status;
218}
219
220int RtmpAsicSendCommandToMcu(struct rt_rtmp_adapter *pAd,
221			     u8 Command,
222			     u8 Token, u8 Arg0, u8 Arg1)
223{
224	HOST_CMD_CSR_STRUC H2MCmd;
225	H2M_MAILBOX_STRUC H2MMailbox;
226	unsigned long i = 0;
227
228#ifdef PCIE_PS_SUPPORT
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. */
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)) {
235		RTMP_SEM_LOCK(&pAd->McuCmdLock);
236		if ((pAd->brt30xxBanMcuCmd == TRUE)
237		    && (Command != WAKE_MCU_CMD) && (Command != RFOFF_MCU_CMD)) {
238			RTMP_SEM_UNLOCK(&pAd->McuCmdLock);
239			DBGPRINT(RT_DEBUG_TRACE,
240				 (" Ban Mcu Cmd %x in sleep mode\n", Command));
241			return FALSE;
242		} else if ((Command == SLEEP_MCU_CMD)
243			   || (Command == RFOFF_MCU_CMD)) {
244			pAd->brt30xxBanMcuCmd = TRUE;
245		} else if (Command != WAKE_MCU_CMD) {
246			pAd->brt30xxBanMcuCmd = FALSE;
247		}
248
249		RTMP_SEM_UNLOCK(&pAd->McuCmdLock);
250
251	}
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);
261			if (H2MMailbox.field.Owner == 0)
262				break;
263
264			RTMPusecDelay(2);
265			DBGPRINT(RT_DEBUG_INFO,
266				 ("AsicSendCommanToMcu::Mail box is busy\n"));
267		} while (i++ < 100);
268
269		if (i > 100) {
270			DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
271			return FALSE;
272		}
273
274		H2MMailbox.field.Owner = 1;	/* pass ownership to MCU */
275		H2MMailbox.field.CmdToken = Token;
276		H2MMailbox.field.HighByte = Arg1;
277		H2MMailbox.field.LowByte = Arg0;
278		RTMP_IO_FORCE_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
279
280		H2MCmd.word = 0;
281		H2MCmd.field.HostCommand = Command;
282		RTMP_IO_FORCE_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
283
284	} else
285#endif /* PCIE_PS_SUPPORT // */
286	{
287		do {
288			RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
289			if (H2MMailbox.field.Owner == 0)
290				break;
291
292			RTMPusecDelay(2);
293		} while (i++ < 100);
294
295		if (i > 100) {
296#ifdef RTMP_MAC_PCI
297#endif /* RTMP_MAC_PCI // */
298			{
299				DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
300			}
301			return FALSE;
302		}
303#ifdef RTMP_MAC_PCI
304#endif /* RTMP_MAC_PCI // */
305
306		H2MMailbox.field.Owner = 1;	/* pass ownership to MCU */
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);
311
312		H2MCmd.word = 0;
313		H2MCmd.field.HostCommand = Command;
314		RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
315
316		if (Command != 0x80) {
317		}
318	}
319#ifdef PCIE_PS_SUPPORT
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. */
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)) {
327		RTMPusecDelay(2000);
328		/*Put this is after RF programming. */
329		/*NdisAcquireSpinLock(&pAd->McuCmdLock); */
330		/*pAd->brt30xxBanMcuCmd = FALSE; */
331		/*NdisReleaseSpinLock(&pAd->McuCmdLock); */
332	}
333#endif /* PCIE_PS_SUPPORT // */
334
335	return TRUE;
336}
337