/*
 * Device state switch handlers.
 */
static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
{
	u32 reg;

	/*
	 * Wait until BBP and RF are ready.
	 */
	if (rt2800_wait_csr_ready(rt2x00dev))
		return -EBUSY;

	rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
	rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);

	rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);

	rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);

	rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);

	rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
				    USB_MODE_RESET, REGISTER_TIMEOUT);

	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);

	return 0;
}
Example #2
0
static void rt2800usb_kill_tx_queue(struct data_queue *queue)
{
	if (queue->qid == QID_BEACON)
		rt2x00usb_register_write(queue->rt2x00dev, BCN_TIME_CFG, 0);

	rt2x00usb_kill_tx_queue(queue);
}
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;
}
static void rt2800usb_stop_queue(struct data_queue *queue)
{
	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
	u32 reg;

	switch (queue->qid) {
	case QID_RX:
		rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
		rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
		rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
		break;
	case QID_BEACON:
		rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
		rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
		break;
	default:
		break;
	}
}
/*
 * Watchdog handlers
 */
static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
{
	unsigned int i;
	u32 reg;

	rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
	if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) {
		WARNING(rt2x00dev, "TX HW queue 0 timed out,"
			" invoke forced kick\n");

		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40012);

		for (i = 0; i < 10; i++) {
			udelay(10);
			if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q))
				break;
		}

		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);
	}

	rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
	if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) {
		WARNING(rt2x00dev, "TX HW queue 1 timed out,"
			" invoke forced kick\n");

		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf4000a);

		for (i = 0; i < 10; i++) {
			udelay(10);
			if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q))
				break;
		}

		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);
	}

	rt2x00usb_watchdog(rt2x00dev);
}
static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
{
	u32 reg;

	if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev)))
		return -EIO;

	rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, &reg);
	rt2x00_set_field32(&reg, USB_DMA_CFG_PHY_CLEAR, 0);
	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_EN, 0);
	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128);
	/*
	 * Total room for RX frames in kilobytes, PBF might still exceed
	 * this limit so reduce the number to prevent errors.
	 */
	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_LIMIT,
			   ((rt2x00dev->ops->rx->entry_num * DATA_FRAME_SIZE)
			    / 1024) - 3);
	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_EN, 1);
	rt2x00_set_field32(&reg, USB_DMA_CFG_TX_BULK_EN, 1);
	rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg);

	return rt2800_enable_radio(rt2x00dev);
}
Example #7
0
static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
{
	int retval;
	u32 reg;

	/*
	 * Allocate eeprom data.
	 */
	retval = rt2800usb_validate_eeprom(rt2x00dev);
	if (retval)
		return retval;

	retval = rt2800_init_eeprom(rt2x00dev);
	if (retval)
		return retval;

	/*
	 * Enable rfkill polling by setting GPIO direction of the
	 * rfkill switch GPIO pin correctly.
	 */
	rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
	rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT2, 1);
	rt2x00usb_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);

	/*
	 * 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(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
	__set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);

	/*
	 * This device requires firmware.
	 */
	__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
	__set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags);
	if (!modparam_nohwcrypt)
		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
	__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
	__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
	__set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);

	setup_timer(&rt2x00dev->txstatus_timer,
		    rt2800usb_tx_sta_fifo_timeout,
		    (unsigned long) rt2x00dev);

	/*
	 * Set the rssi offset.
	 */
	rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;

	/*
	 * Overwrite TX done handler
	 */
	PREPARE_WORK(&rt2x00dev->txdone_work, rt2800usb_work_txdone);

	return 0;
}