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