- patches.suse/slab-handle-memoryless-nodes-v2a.patch: Refresh.
[linux-flexiantxendom0-3.2.10.git] / drivers / staging / rt2860 / common / rtmp_mcu.c
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 #if defined(RT2860) || defined(RT3090)
41 #include "firmware.h"
42 #include "../../rt3090/firmware.h"
43 #endif
44 #ifdef RT2870
45 #include "../../rt3070/firmware.h"
46 #include "firmware_3070.h"
47 #endif
48
49 #include <linux/bitrev.h>
50
51 #ifdef RTMP_MAC_USB
52 /* */
53 /* RT2870 Firmware Spec only used 1 oct for version expression */
54 /* */
55 #define FIRMWARE_MINOR_VERSION  7
56 #endif /* RTMP_MAC_USB // */
57
58 /* New 8k byte firmware size for RT3071/RT3072 */
59 #define FIRMWAREIMAGE_MAX_LENGTH        0x2000
60 #define FIRMWAREIMAGE_LENGTH                    (sizeof (FirmwareImage) / sizeof(u8))
61 #define FIRMWARE_MAJOR_VERSION          0
62
63 #define FIRMWAREIMAGEV1_LENGTH          0x1000
64 #define FIRMWAREIMAGEV2_LENGTH          0x1000
65
66 #ifdef RTMP_MAC_PCI
67 #define FIRMWARE_MINOR_VERSION          2
68 #endif /* RTMP_MAC_PCI // */
69
70 /*
71         ========================================================================
72
73         Routine Description:
74                 erase 8051 firmware image in MAC ASIC
75
76         Arguments:
77                 Adapter                                         Pointer to our adapter
78
79         IRQL = PASSIVE_LEVEL
80
81         ========================================================================
82 */
83 int RtmpAsicEraseFirmware(struct rt_rtmp_adapter *pAd)
84 {
85         unsigned long i;
86
87         for (i = 0; i < MAX_FIRMWARE_IMAGE_SIZE; i += 4)
88                 RTMP_IO_WRITE32(pAd, FIRMWARE_IMAGE_BASE + i, 0);
89
90         return 0;
91 }
92
93 /*
94         ========================================================================
95
96         Routine Description:
97                 Load 8051 firmware file into MAC ASIC
98
99         Arguments:
100                 Adapter                                         Pointer to our adapter
101
102         Return Value:
103                 NDIS_STATUS_SUCCESS         firmware image load ok
104                 NDIS_STATUS_FAILURE         image not found
105
106         IRQL = PASSIVE_LEVEL
107
108         ========================================================================
109 */
110 int RtmpAsicLoadFirmware(struct rt_rtmp_adapter *pAd)
111 {
112
113         int Status = NDIS_STATUS_SUCCESS;
114         u8 *pFirmwareImage = NULL;
115         unsigned long FileLength, Index;
116         u32 MacReg = 0;
117 #ifdef RTMP_MAC_USB
118         u32 Version = (pAd->MACVersion >> 16);
119 #endif
120
121         /* New 8k byte firmware size for RT3071/RT3072 */
122         {
123 #ifdef RTMP_MAC_PCI
124                 if (IS_RT3090(pAd) || IS_RT3390(pAd)) {
125                         pFirmwareImage = FirmwareImage_3090;
126                         FileLength = FIRMWAREIMAGE_MAX_LENGTH;
127                 } else {
128                         pFirmwareImage = FirmwareImage_2860;
129                         FileLength = FIRMWAREIMAGE_MAX_LENGTH;
130                 }
131 #endif /* RTMP_MAC_PCI // */
132 #ifdef RTMP_MAC_USB
133                 /* the firmware image consists of two parts */
134                 if ((Version != 0x2860) && (Version != 0x2872) && (Version != 0x3070)) {        /* use the second part */
135                         /*printk("KH:Use New Version,part2\n"); */
136                         pFirmwareImage =
137                             (u8 *)&
138                             FirmwareImage_3070[FIRMWAREIMAGEV1_LENGTH];
139                         FileLength = FIRMWAREIMAGEV2_LENGTH;
140                 } else {
141                         /*printk("KH:Use New Version,part1\n"); */
142                         if (Version == 0x3070)
143                                 pFirmwareImage = FirmwareImage_3070;
144                         else
145                                 pFirmwareImage = FirmwareImage_2870;
146                         FileLength = FIRMWAREIMAGEV1_LENGTH;
147                 }
148 #endif /* RTMP_MAC_USB // */
149         }
150
151         RTMP_WRITE_FIRMWARE(pAd, pFirmwareImage, FileLength);
152
153         /* check if MCU is ready */
154         Index = 0;
155         do {
156                 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MacReg);
157
158                 if (MacReg & 0x80)
159                         break;
160
161                 RTMPusecDelay(1000);
162         } while (Index++ < 1000);
163
164         if (Index > 1000) {
165                 DBGPRINT(RT_DEBUG_ERROR,
166                          ("NICLoadFirmware: MCU is not ready\n"));
167                 Status = NDIS_STATUS_FAILURE;
168         }
169
170         DBGPRINT(RT_DEBUG_TRACE, ("<=== %s (status=%d)\n", __func__, Status));
171
172         return Status;
173 }
174
175 int RtmpAsicSendCommandToMcu(struct rt_rtmp_adapter *pAd,
176                              u8 Command,
177                              u8 Token, u8 Arg0, u8 Arg1)
178 {
179         HOST_CMD_CSR_STRUC H2MCmd;
180         H2M_MAILBOX_STRUC H2MMailbox;
181         unsigned long i = 0;
182
183 #ifdef PCIE_PS_SUPPORT
184         /* 3090F power solution 3 has hw limitation that needs to ban all mcu command */
185         /* when firmware is in radio state.  For other chip doesn't have this limitation. */
186         if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))
187              && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd)
188             && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
189             && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) {
190                 RTMP_SEM_LOCK(&pAd->McuCmdLock);
191                 if ((pAd->brt30xxBanMcuCmd == TRUE)
192                     && (Command != WAKE_MCU_CMD) && (Command != RFOFF_MCU_CMD)) {
193                         RTMP_SEM_UNLOCK(&pAd->McuCmdLock);
194                         DBGPRINT(RT_DEBUG_TRACE,
195                                  (" Ban Mcu Cmd %x in sleep mode\n", Command));
196                         return FALSE;
197                 } else if ((Command == SLEEP_MCU_CMD)
198                            || (Command == RFOFF_MCU_CMD)) {
199                         pAd->brt30xxBanMcuCmd = TRUE;
200                 } else if (Command != WAKE_MCU_CMD) {
201                         pAd->brt30xxBanMcuCmd = FALSE;
202                 }
203
204                 RTMP_SEM_UNLOCK(&pAd->McuCmdLock);
205
206         }
207         if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))
208              && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd)
209             && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
210             && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
211             && (Command == WAKE_MCU_CMD)) {
212
213                 do {
214                         RTMP_IO_FORCE_READ32(pAd, H2M_MAILBOX_CSR,
215                                              &H2MMailbox.word);
216                         if (H2MMailbox.field.Owner == 0)
217                                 break;
218
219                         RTMPusecDelay(2);
220                         DBGPRINT(RT_DEBUG_INFO,
221                                  ("AsicSendCommanToMcu::Mail box is busy\n"));
222                 } while (i++ < 100);
223
224                 if (i >= 100) {
225                         DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
226                         return FALSE;
227                 }
228
229                 H2MMailbox.field.Owner = 1;     /* pass ownership to MCU */
230                 H2MMailbox.field.CmdToken = Token;
231                 H2MMailbox.field.HighByte = Arg1;
232                 H2MMailbox.field.LowByte = Arg0;
233                 RTMP_IO_FORCE_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
234
235                 H2MCmd.word = 0;
236                 H2MCmd.field.HostCommand = Command;
237                 RTMP_IO_FORCE_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
238
239         } else
240 #endif /* PCIE_PS_SUPPORT // */
241         {
242                 do {
243                         RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
244                         if (H2MMailbox.field.Owner == 0)
245                                 break;
246
247                         RTMPusecDelay(2);
248                 } while (i++ < 100);
249
250                 if (i > 100) {
251 #ifdef RTMP_MAC_PCI
252 #endif /* RTMP_MAC_PCI // */
253                         {
254                                 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
255                         }
256                         return FALSE;
257                 }
258 #ifdef RTMP_MAC_PCI
259 #endif /* RTMP_MAC_PCI // */
260
261                 H2MMailbox.field.Owner = 1;     /* pass ownership to MCU */
262                 H2MMailbox.field.CmdToken = Token;
263                 H2MMailbox.field.HighByte = Arg1;
264                 H2MMailbox.field.LowByte = Arg0;
265                 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
266
267                 H2MCmd.word = 0;
268                 H2MCmd.field.HostCommand = Command;
269                 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
270
271                 if (Command != 0x80) {
272                 }
273         }
274 #ifdef PCIE_PS_SUPPORT
275         /* 3090 MCU Wakeup command needs more time to be stable. */
276         /* Before stable, don't issue other MCU command to prevent from firmware error. */
277         if (((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))
278              && IS_VERSION_AFTER_F(pAd)) && IS_VERSION_AFTER_F(pAd)
279             && (pAd->StaCfg.PSControl.field.rt30xxPowerMode == 3)
280             && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)
281             && (Command == WAKE_MCU_CMD)) {
282                 RTMPusecDelay(2000);
283                 /*Put this is after RF programming. */
284                 /*NdisAcquireSpinLock(&pAd->McuCmdLock); */
285                 /*pAd->brt30xxBanMcuCmd = FALSE; */
286                 /*NdisReleaseSpinLock(&pAd->McuCmdLock); */
287         }
288 #endif /* PCIE_PS_SUPPORT // */
289
290         return TRUE;
291 }