static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; rt2x00dev->priv = (void *)&rt2800pci_rt2800_ops; /* * Allocate eeprom data. */ retval = rt2800pci_validate_eeprom(rt2x00dev); if (retval) return retval; retval = rt2800_init_eeprom(rt2x00dev); if (retval) return retval; /* * Initialize hw specifications. */ retval = rt2800_probe_hw_mode(rt2x00dev); if (retval) return retval; /* * This device has multiple filters for control frames * and has a separate filter for PS Poll frames. */ __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags); /* * This device requires firmware. */ if (!rt2x00_rt(&rt2x00dev->chip, RT2880) && !rt2x00_rt(&rt2x00dev->chip, RT3052)) __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); if (!modparam_nohwcrypt) __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); /* * Set the rssi offset. */ rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; return 0; }
static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev, const u8 *data, const size_t len) { int status; u32 offset; u32 length; /* * Check which section of the firmware we need. */ if (rt2x00_rt(rt2x00dev, RT2860) || rt2x00_rt(rt2x00dev, RT2872) || rt2x00_rt(rt2x00dev, RT3070)) { offset = 0; length = 4096; } else { offset = 4096; length = 4096; } /* * Write firmware to device. */ rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, data + offset, length); rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); /* * Send firmware request to device to load firmware, * we need to specify a long timeout time. */ status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, USB_MODE_FIRMWARE, REGISTER_TIMEOUT_FIRMWARE); if (status < 0) { ERROR(rt2x00dev, "Failed to write Firmware to device.\n"); return status; } msleep(10); rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); return 0; }
/* * Firmware functions */ static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) { /* * Chip rt3290 use specific 4KB firmware named rt3290.bin. */ if (rt2x00_rt(rt2x00dev, RT3290)) return FIRMWARE_RT3290; else return FIRMWARE_RT2860; }
static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) { u32 reg; /* * Reset DMA indexes */ rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, ®); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg); rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); if (rt2x00_is_pcie(rt2x00dev) && (rt2x00_rt(rt2x00dev, RT3572) || rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392))) { rt2x00pci_register_read(rt2x00dev, AUX_CTRL, ®); rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); rt2x00pci_register_write(rt2x00dev, AUX_CTRL, reg); } rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); reg = 0; rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); return 0; }
static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, const u8 *data, const size_t len) { size_t offset = 0; /* * Firmware files: * There are 2 variations of the rt2870 firmware. * a) size: 4kb * b) size: 8kb * Note that (b) contains 2 separate firmware blobs of 4k * within the file. The first blob is the same firmware as (a), * but the second blob is for the additional chipsets. */ if (len != 4096 && len != 8192) return FW_BAD_LENGTH; /* * Check if we need the upper 4kb firmware data or not. */ if ((len == 4096) && !rt2x00_rt(rt2x00dev, RT2860) && !rt2x00_rt(rt2x00dev, RT2872) && !rt2x00_rt(rt2x00dev, RT3070)) return FW_BAD_VERSION; /* * 8kb firmware files must be checked as if it were * 2 separate firmware files. */ while (offset < len) { if (!rt2800usb_check_crc(data + offset, 4096)) return FW_BAD_CRC; offset += 4096; } return FW_OK; }
static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, const u8 *data, const size_t len) { unsigned int i; int status; u32 reg; u32 offset; u32 length; /* * Check which section of the firmware we need. */ if (rt2x00_rt(rt2x00dev, RT2860) || rt2x00_rt(rt2x00dev, RT2872) || rt2x00_rt(rt2x00dev, RT3070)) { offset = 0; length = 4096; } else { offset = 4096; length = 4096; } /* * Wait for stable hardware. */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2800_register_read(rt2x00dev, MAC_CSR0, ®); if (reg && reg != ~0) break; msleep(1); } if (i == REGISTER_BUSY_COUNT) { ERROR(rt2x00dev, "Unstable hardware.\n"); return -EBUSY; } /* * Write firmware to device. */ rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, FIRMWARE_IMAGE_BASE, data + offset, length, REGISTER_TIMEOUT32(length)); rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); /* * Send firmware request to device to load firmware, * we need to specify a long timeout time. */ status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, USB_MODE_FIRMWARE, REGISTER_TIMEOUT_FIRMWARE); if (status < 0) { ERROR(rt2x00dev, "Failed to write Firmware to device.\n"); return status; } msleep(10); rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); /* * Send signal to firmware during boot time. */ rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3071) || rt2x00_rt(rt2x00dev, RT3572)) { udelay(200); rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0); udelay(10); } /* * Wait for device to stabilize. */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) break; msleep(1); } if (i == REGISTER_BUSY_COUNT) { ERROR(rt2x00dev, "PBF system register not ready.\n"); return -EBUSY; } /* * Initialize firmware. */ rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); msleep(1); return 0; }
int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops) { struct ieee80211_hw *hw; struct rt2x00_dev *rt2x00dev; int retval; u16 chip; retval = pci_enable_device(pci_dev); if (retval) { rt2x00_probe_err("Enable device failed\n"); return retval; } retval = pci_request_regions(pci_dev, pci_name(pci_dev)); if (retval) { rt2x00_probe_err("PCI request regions failed\n"); goto exit_disable_device; } pci_set_master(pci_dev); if (pci_set_mwi(pci_dev)) rt2x00_probe_err("MWI not available\n"); if (dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32))) { rt2x00_probe_err("PCI DMA not supported\n"); retval = -EIO; goto exit_release_regions; } hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw); if (!hw) { rt2x00_probe_err("Failed to allocate hardware\n"); retval = -ENOMEM; goto exit_release_regions; } pci_set_drvdata(pci_dev, hw); rt2x00dev = hw->priv; rt2x00dev->dev = &pci_dev->dev; rt2x00dev->ops = ops; rt2x00dev->hw = hw; rt2x00dev->irq = pci_dev->irq; rt2x00dev->name = pci_name(pci_dev); if (pci_is_pcie(pci_dev)) rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE); else rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); retval = rt2x00pci_alloc_reg(rt2x00dev); if (retval) goto exit_free_device; /* * Because rt3290 chip use different efuse offset to read efuse data. * So before read efuse it need to indicate it is the * rt3290 or not. */ pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip); rt2x00dev->chip.rt = chip; if (rt2x00_rt(rt2x00dev, MT7630)) MT76x0_WLAN_ChipOnOff(rt2x00dev, 1, 1); retval = rt2x00lib_probe_dev(rt2x00dev); if (retval) goto exit_free_reg; if (rt2x00_rt(rt2x00dev, MT7630)) { rt2x00dev->TXWISize=20; rt2x00dev->bscan=0; NdisAllocateSpinLock(rt2x00dev, &rt2x00dev->CtrlRingLock); NdisAllocateSpinLock(rt2x00dev, &rt2x00dev->CalLock); retval = RTMPAllocTxRxRingMemory(rt2x00dev); if (retval != NDIS_STATUS_SUCCESS) goto exit_free_reg; } return 0; exit_free_reg: rt2x00pci_free_reg(rt2x00dev); exit_free_device: ieee80211_free_hw(hw); exit_release_regions: pci_release_regions(pci_dev); exit_disable_device: pci_disable_device(pci_dev); pci_set_drvdata(pci_dev, NULL); return retval; }