1a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn/*
296481b20f4d6df7021867ae9a9deaa989ec32e40Ivo van Doorn	Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
39c9a0d145fee73b5e821bb460732ac2a66c680b3Gertjan van Wingerde	Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
49c9a0d145fee73b5e821bb460732ac2a66c680b3Gertjan van Wingerde	Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
59c9a0d145fee73b5e821bb460732ac2a66c680b3Gertjan van Wingerde	Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
69c9a0d145fee73b5e821bb460732ac2a66c680b3Gertjan van Wingerde	Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
79c9a0d145fee73b5e821bb460732ac2a66c680b3Gertjan van Wingerde	Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
89c9a0d145fee73b5e821bb460732ac2a66c680b3Gertjan van Wingerde	Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
99c9a0d145fee73b5e821bb460732ac2a66c680b3Gertjan van Wingerde	Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
10a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	<http://rt2x00.serialmonkey.com>
11a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
12a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	This program is free software; you can redistribute it and/or modify
13a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	it under the terms of the GNU General Public License as published by
14a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	the Free Software Foundation; either version 2 of the License, or
15a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	(at your option) any later version.
16a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
17a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	This program is distributed in the hope that it will be useful,
18a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	but WITHOUT ANY WARRANTY; without even the implied warranty of
19a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	GNU General Public License for more details.
21a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
22a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	You should have received a copy of the GNU General Public License
23a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	along with this program; if not, write to the
24a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	Free Software Foundation, Inc.,
25a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn */
27a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
28a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn/*
29a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	Module: rt2800pci
30a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	Abstract: rt2800pci device specific routines.
31a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	Supported chipsets: RT2800E & RT2800ED.
32a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn */
33a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
34a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#include <linux/delay.h>
35a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#include <linux/etherdevice.h>
36a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#include <linux/init.h>
37a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#include <linux/kernel.h>
38a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#include <linux/module.h>
39a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#include <linux/pci.h>
40a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#include <linux/platform_device.h>
41a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#include <linux/eeprom_93cx6.h>
42a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
43a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#include "rt2x00.h"
44a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#include "rt2x00pci.h"
45a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#include "rt2x00soc.h"
467ef5cc92bac940419f022e11115a28daea53814fBartlomiej Zolnierkiewicz#include "rt2800lib.h"
47b54f78a8b7a108a4abc81d88d641769726be23c1Bartlomiej Zolnierkiewicz#include "rt2800.h"
48a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#include "rt2800pci.h"
49a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
50a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn/*
51a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn * Allow hardware encryption to be disabled.
52a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn */
53eb93992207dadb946a3b5cf4544957dc924a6f58Rusty Russellstatic bool modparam_nohwcrypt = false;
54a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornmodule_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
55a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van DoornMODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
56a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
57a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
58a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
59a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	unsigned int i;
60a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	u32 reg;
61a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
62f18d4463d092162f34a8bd226505627ceeac3e8aLuis Correia	/*
63f18d4463d092162f34a8bd226505627ceeac3e8aLuis Correia	 * SOC devices don't support MCU requests.
64f18d4463d092162f34a8bd226505627ceeac3e8aLuis Correia	 */
65f18d4463d092162f34a8bd226505627ceeac3e8aLuis Correia	if (rt2x00_is_soc(rt2x00dev))
66f18d4463d092162f34a8bd226505627ceeac3e8aLuis Correia		return;
67f18d4463d092162f34a8bd226505627ceeac3e8aLuis Correia
68a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	for (i = 0; i < 200; i++) {
699a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
70a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
71a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
72a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		    (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
73a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		    (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD2) == token) ||
74a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		    (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD3) == token))
75a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn			break;
76a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
77a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		udelay(REGISTER_BUSY_DELAY);
78a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	}
79a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
80a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	if (i == 200)
81a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		ERROR(rt2x00dev, "MCU request failed, no response from hardware\n");
82a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
839a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
849a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
85a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
86a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
8772c7296e03e381b49958809915105b18b09fa7a3Gertjan van Wingerde#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X)
88a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
89a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
90ef8397cfb3a385bc57a32213d0e4a5b7903a9dc6Gertjan van Wingerde	void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE);
91a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
92a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE);
93ef8397cfb3a385bc57a32213d0e4a5b7903a9dc6Gertjan van Wingerde
94ef8397cfb3a385bc57a32213d0e4a5b7903a9dc6Gertjan van Wingerde	iounmap(base_addr);
95a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
96a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#else
97a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
98a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
99a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
10072c7296e03e381b49958809915105b18b09fa7a3Gertjan van Wingerde#endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */
101a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
10272c7296e03e381b49958809915105b18b09fa7a3Gertjan van Wingerde#ifdef CONFIG_PCI
103a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
104a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
105a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	struct rt2x00_dev *rt2x00dev = eeprom->data;
106a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	u32 reg;
107a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1089a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
109a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
110a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
111a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
112a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	eeprom->reg_data_clock =
113a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	    !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_CLOCK);
114a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	eeprom->reg_chip_select =
115a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	    !!rt2x00_get_field32(reg, E2PROM_CSR_CHIP_SELECT);
116a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
117a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
118a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
119a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
120a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	struct rt2x00_dev *rt2x00dev = eeprom->data;
121a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	u32 reg = 0;
122a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
123a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_set_field32(&reg, E2PROM_CSR_DATA_IN, !!eeprom->reg_data_in);
124a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_set_field32(&reg, E2PROM_CSR_DATA_OUT, !!eeprom->reg_data_out);
125a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_set_field32(&reg, E2PROM_CSR_DATA_CLOCK,
126a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn			   !!eeprom->reg_data_clock);
127a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_set_field32(&reg, E2PROM_CSR_CHIP_SELECT,
128a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn			   !!eeprom->reg_chip_select);
129a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1309a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg);
131a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
132a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
133a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
134a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
135a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	struct eeprom_93cx6 eeprom;
136a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	u32 reg;
137a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1389a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
139a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
140a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	eeprom.data = rt2x00dev;
141a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	eeprom.register_read = rt2800pci_eepromregister_read;
142a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	eeprom.register_write = rt2800pci_eepromregister_write;
14320f8b139a3834db1545454b4392aa73dcf595c9fGertjan van Wingerde	switch (rt2x00_get_field32(reg, E2PROM_CSR_TYPE))
14420f8b139a3834db1545454b4392aa73dcf595c9fGertjan van Wingerde	{
14520f8b139a3834db1545454b4392aa73dcf595c9fGertjan van Wingerde	case 0:
14620f8b139a3834db1545454b4392aa73dcf595c9fGertjan van Wingerde		eeprom.width = PCI_EEPROM_WIDTH_93C46;
14720f8b139a3834db1545454b4392aa73dcf595c9fGertjan van Wingerde		break;
14820f8b139a3834db1545454b4392aa73dcf595c9fGertjan van Wingerde	case 1:
14920f8b139a3834db1545454b4392aa73dcf595c9fGertjan van Wingerde		eeprom.width = PCI_EEPROM_WIDTH_93C66;
15020f8b139a3834db1545454b4392aa73dcf595c9fGertjan van Wingerde		break;
15120f8b139a3834db1545454b4392aa73dcf595c9fGertjan van Wingerde	default:
15220f8b139a3834db1545454b4392aa73dcf595c9fGertjan van Wingerde		eeprom.width = PCI_EEPROM_WIDTH_93C86;
15320f8b139a3834db1545454b4392aa73dcf595c9fGertjan van Wingerde		break;
15420f8b139a3834db1545454b4392aa73dcf595c9fGertjan van Wingerde	}
155a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	eeprom.reg_data_in = 0;
156a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	eeprom.reg_data_out = 0;
157a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	eeprom.reg_data_clock = 0;
158a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	eeprom.reg_chip_select = 0;
159a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
160a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom,
161a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn			       EEPROM_SIZE / sizeof(u16));
162a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
163a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
164a65986824d2552dd76786d5a0012989a64c45ab7Gertjan van Wingerdestatic int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev)
165a65986824d2552dd76786d5a0012989a64c45ab7Gertjan van Wingerde{
16630e840346c516ad4e36f710fa485933ccc7afa66Bartlomiej Zolnierkiewicz	return rt2800_efuse_detect(rt2x00dev);
167a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
168a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
16930e840346c516ad4e36f710fa485933ccc7afa66Bartlomiej Zolnierkiewiczstatic inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
170a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
17130e840346c516ad4e36f710fa485933ccc7afa66Bartlomiej Zolnierkiewicz	rt2800_read_eeprom_efuse(rt2x00dev);
172a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
173a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#else
174a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic inline void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
175a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
176a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
177a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
178a65986824d2552dd76786d5a0012989a64c45ab7Gertjan van Wingerdestatic inline int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev)
179a65986824d2552dd76786d5a0012989a64c45ab7Gertjan van Wingerde{
180a65986824d2552dd76786d5a0012989a64c45ab7Gertjan van Wingerde	return 0;
181a65986824d2552dd76786d5a0012989a64c45ab7Gertjan van Wingerde}
182a65986824d2552dd76786d5a0012989a64c45ab7Gertjan van Wingerde
183a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
184a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
185a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
18672c7296e03e381b49958809915105b18b09fa7a3Gertjan van Wingerde#endif /* CONFIG_PCI */
187a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
188a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn/*
1895450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn * Queue handlers.
1905450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn */
1915450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doornstatic void rt2800pci_start_queue(struct data_queue *queue)
1925450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn{
1935450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
1945450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	u32 reg;
1955450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn
1965450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	switch (queue->qid) {
1975450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	case QID_RX:
1989a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
1995450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
2009a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
2015450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
2025450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	case QID_BEACON:
2039a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
2045450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
2055450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
2065450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
2079a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
20869cf36a4523be026bc16743c5c989c5e82edb7d9Helmut Schaa
2099a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, &reg);
21069cf36a4523be026bc16743c5c989c5e82edb7d9Helmut Schaa		rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 1);
2119a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);
2125450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
2135450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	default:
2145450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
2156403eab143205a45a5493166ff8bf7e3646f4a77Joe Perches	}
2165450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn}
2175450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn
2185450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doornstatic void rt2800pci_kick_queue(struct data_queue *queue)
2195450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn{
2205450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
2215450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	struct queue_entry *entry;
2225450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn
2235450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	switch (queue->qid) {
224f615e9a38a8e6239d35891a05f2ac1159088780aIvo van Doorn	case QID_AC_VO:
225f615e9a38a8e6239d35891a05f2ac1159088780aIvo van Doorn	case QID_AC_VI:
2265450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	case QID_AC_BE:
2275450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	case QID_AC_BK:
2285450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		entry = rt2x00queue_get_entry(queue, Q_INDEX);
2299a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(queue->qid),
2309a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa					 entry->entry_idx);
2315450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
2325450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	case QID_MGMT:
2335450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		entry = rt2x00queue_get_entry(queue, Q_INDEX);
2349a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(5),
2359a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa					 entry->entry_idx);
2365450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
2375450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	default:
2385450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
2395450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	}
2405450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn}
2415450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn
2425450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doornstatic void rt2800pci_stop_queue(struct data_queue *queue)
2435450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn{
2445450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
2455450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	u32 reg;
2465450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn
2475450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	switch (queue->qid) {
2485450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	case QID_RX:
2499a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
2505450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
2519a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
2525450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
2535450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	case QID_BEACON:
2549a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
2555450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
2565450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
2575450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
2589a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
25969cf36a4523be026bc16743c5c989c5e82edb7d9Helmut Schaa
2609a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, &reg);
26169cf36a4523be026bc16743c5c989c5e82edb7d9Helmut Schaa		rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 0);
2629a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);
263a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa
264a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa		/*
265abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		 * Wait for current invocation to finish. The tasklet
266abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		 * won't be scheduled anymore afterwards since we disabled
267abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		 * the TBTT and PRE TBTT timer.
268a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa		 */
269abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		tasklet_kill(&rt2x00dev->tbtt_tasklet);
270abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		tasklet_kill(&rt2x00dev->pretbtt_tasklet);
271abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa
2725450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
2735450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	default:
2745450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn		break;
2755450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn	}
2765450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn}
2775450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn
2785450b7e2f0b47e52175b31399d8186a74ef3c46dIvo van Doorn/*
279a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn * Firmware functions
280a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn */
281a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
282a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
283a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	return FIRMWARE_RT2860;
284a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
285a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
286f31c9a8c1380e20e95d06925f2e42baf61af4db7Ivo van Doornstatic int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
287a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn				    const u8 *data, const size_t len)
288a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
289a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	u32 reg;
290a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
291a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	/*
292a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * enable Host program ram write selection
293a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 */
294a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	reg = 0;
295a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_set_field32(&reg, PBF_SYS_CTRL_HOST_RAM_WRITE, 1);
2969a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
297a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
298a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	/*
299a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * Write firmware to device.
300a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 */
301d4c838ef5e5c2c7e205adf9e011d2e8bd6eae738Ivo van Doorn	rt2x00pci_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
302d4c838ef5e5c2c7e205adf9e011d2e8bd6eae738Ivo van Doorn				      data, len);
303a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
3049a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
3059a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
306a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
3079a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
3089a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
309a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
310a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	return 0;
311a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
312a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
313a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn/*
314a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn * Initialization functions.
315a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn */
316a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic bool rt2800pci_get_entry_state(struct queue_entry *entry)
317a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
318a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
319a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	u32 word;
320a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
321a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	if (entry->queue->qid == QID_RX) {
322a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rt2x00_desc_read(entry_priv->desc, 1, &word);
323a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
324a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		return (!rt2x00_get_field32(word, RXD_W1_DMA_DONE));
325a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	} else {
326a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rt2x00_desc_read(entry_priv->desc, 1, &word);
327a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
328a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		return (!rt2x00_get_field32(word, TXD_W1_DMA_DONE));
329a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	}
330a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
331a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
332a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic void rt2800pci_clear_entry(struct queue_entry *entry)
333a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
334a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
335a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
33695192339c2de1e1a61baf289af3e3332403371c9Helmut Schaa	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
337a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	u32 word;
338a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
339a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	if (entry->queue->qid == QID_RX) {
340a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rt2x00_desc_read(entry_priv->desc, 0, &word);
341a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rt2x00_set_field32(&word, RXD_W0_SDP0, skbdesc->skb_dma);
342a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rt2x00_desc_write(entry_priv->desc, 0, word);
343a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
344a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rt2x00_desc_read(entry_priv->desc, 1, &word);
345a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rt2x00_set_field32(&word, RXD_W1_DMA_DONE, 0);
346a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rt2x00_desc_write(entry_priv->desc, 1, word);
34795192339c2de1e1a61baf289af3e3332403371c9Helmut Schaa
34895192339c2de1e1a61baf289af3e3332403371c9Helmut Schaa		/*
34995192339c2de1e1a61baf289af3e3332403371c9Helmut Schaa		 * Set RX IDX in register to inform hardware that we have
35095192339c2de1e1a61baf289af3e3332403371c9Helmut Schaa		 * handled this entry and it is available for reuse again.
35195192339c2de1e1a61baf289af3e3332403371c9Helmut Schaa		 */
3529a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX,
35395192339c2de1e1a61baf289af3e3332403371c9Helmut Schaa				      entry->entry_idx);
354a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	} else {
355a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rt2x00_desc_read(entry_priv->desc, 1, &word);
356a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1);
357a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rt2x00_desc_write(entry_priv->desc, 1, word);
358a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	}
359a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
360a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
361a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
362a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
363a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	struct queue_entry_priv_pci *entry_priv;
364a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	u32 reg;
365a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
366a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	/*
367a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * Initialize registers.
368a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 */
369a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
3709a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma);
3719a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT0,
3729a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa				 rt2x00dev->tx[0].limit);
3739a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX0, 0);
3749a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX0, 0);
375a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
376a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
3779a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma);
3789a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT1,
3799a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa				 rt2x00dev->tx[1].limit);
3809a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX1, 0);
3819a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX1, 0);
382a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
383a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
3849a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma);
3859a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT2,
3869a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa				 rt2x00dev->tx[2].limit);
3879a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX2, 0);
3889a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX2, 0);
389a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
390a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
3919a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma);
3929a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT3,
3939a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa				 rt2x00dev->tx[3].limit);
3949a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX3, 0);
3959a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX3, 0);
396a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
397a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	entry_priv = rt2x00dev->rx->entries[0].priv_data;
3989a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma);
3999a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, RX_MAX_CNT,
4009a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa				 rt2x00dev->rx[0].limit);
4019a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX,
4029a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa				 rt2x00dev->rx[0].limit - 1);
4039a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, RX_DRX_IDX, 0);
404a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
405a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	/*
406a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * Enable global DMA configuration
407a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 */
4089a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
409a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
410a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
411a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
4129a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
413a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
4149a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, DELAY_INT_CFG, 0);
415a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
416a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	return 0;
417a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
418a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
419a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn/*
420a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn * Device state switch handlers.
421a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn */
422a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
423a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn				 enum dev_state state)
424a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
425a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	u32 reg;
426a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	unsigned long flags;
427a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
428a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	/*
429a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * When interrupts are being enabled, the interrupt registers
430a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * should clear the register to assure a clean state.
431a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 */
432a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	if (state == STATE_RADIO_IRQ_ON) {
4339a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
4349a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
435a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	}
436a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
437a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
438dfd00c4c8f3dfa1fd7cec45f83d98b2a49743dcdStanislaw Gruszka	reg = 0;
439dfd00c4c8f3dfa1fd7cec45f83d98b2a49743dcdStanislaw Gruszka	if (state == STATE_RADIO_IRQ_ON) {
440dfd00c4c8f3dfa1fd7cec45f83d98b2a49743dcdStanislaw Gruszka		rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, 1);
441dfd00c4c8f3dfa1fd7cec45f83d98b2a49743dcdStanislaw Gruszka		rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, 1);
442dfd00c4c8f3dfa1fd7cec45f83d98b2a49743dcdStanislaw Gruszka		rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, 1);
443dfd00c4c8f3dfa1fd7cec45f83d98b2a49743dcdStanislaw Gruszka		rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, 1);
444dfd00c4c8f3dfa1fd7cec45f83d98b2a49743dcdStanislaw Gruszka		rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, 1);
445dfd00c4c8f3dfa1fd7cec45f83d98b2a49743dcdStanislaw Gruszka	}
4469a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
447a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
448a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa
449a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	if (state == STATE_RADIO_IRQ_OFF) {
450a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa		/*
451abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		 * Wait for possibly running tasklets to finish.
452a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa		 */
453abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		tasklet_kill(&rt2x00dev->txstatus_tasklet);
454abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		tasklet_kill(&rt2x00dev->rxdone_tasklet);
455abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		tasklet_kill(&rt2x00dev->autowake_tasklet);
456abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		tasklet_kill(&rt2x00dev->tbtt_tasklet);
457abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		tasklet_kill(&rt2x00dev->pretbtt_tasklet);
458a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	}
459a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
460a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
461e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerdestatic int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
462e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde{
463e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde	u32 reg;
464e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde
465e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde	/*
466e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde	 * Reset DMA indexes
467e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde	 */
4689a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
469e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, 1);
470e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, 1);
471e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, 1);
472e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX3, 1);
473e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX4, 1);
474e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX5, 1);
475e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
4769a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
477e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde
4789a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
4799a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
480e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde
481872834dfb38edc6f72cfc783a5ce78f2a9f36ec5Gertjan van Wingerde	if (rt2x00_is_pcie(rt2x00dev) &&
482872834dfb38edc6f72cfc783a5ce78f2a9f36ec5Gertjan van Wingerde	    (rt2x00_rt(rt2x00dev, RT3572) ||
4832ed7188447fd48336f296ce2dfbd35785768d28cJohn Li	     rt2x00_rt(rt2x00dev, RT5390) ||
4842ed7188447fd48336f296ce2dfbd35785768d28cJohn Li	     rt2x00_rt(rt2x00dev, RT5392))) {
4859a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_read(rt2x00dev, AUX_CTRL, &reg);
486adde5882bc6c21de7ee80ee15dfd58c7e9a472acGabor Juhos		rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
487adde5882bc6c21de7ee80ee15dfd58c7e9a472acGabor Juhos		rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
4889a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_write(rt2x00dev, AUX_CTRL, reg);
489adde5882bc6c21de7ee80ee15dfd58c7e9a472acGabor Juhos	}
49060687ba710359f32343b7630dc05d3811ef5bf4cRA-Shiang Tu
4919a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
492e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde
4932a48e8ae113be506a7169d50c0b8fcb3ab0c462aStanislaw Gruszka	reg = 0;
494e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
495e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
4969a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
497e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde
4989a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
499e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde
500e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde	return 0;
501e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde}
502e3a896b9924d6dcd88ad16186d7ec77f32d12ef8Gertjan van Wingerde
503a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)
504a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
505e8b461c37717d6b5c071c4924845884a86c20752Jakub Kicinski	int retval;
506e8b461c37717d6b5c071c4924845884a86c20752Jakub Kicinski
50767a4c1e24d58e0d88ed88539641631f6fc8a0cfdGertjan van Wingerde	if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) ||
508b9a07ae9d9e09662013992088fd58ffbcb2f9a30Ivo van Doorn		     rt2800pci_init_queues(rt2x00dev)))
509a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		return -EIO;
510a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
511e8b461c37717d6b5c071c4924845884a86c20752Jakub Kicinski	retval = rt2800_enable_radio(rt2x00dev);
512e8b461c37717d6b5c071c4924845884a86c20752Jakub Kicinski	if (retval)
513e8b461c37717d6b5c071c4924845884a86c20752Jakub Kicinski		return retval;
514e8b461c37717d6b5c071c4924845884a86c20752Jakub Kicinski
515e8b461c37717d6b5c071c4924845884a86c20752Jakub Kicinski	/* After resume MCU_BOOT_SIGNAL will trash these. */
516e8b461c37717d6b5c071c4924845884a86c20752Jakub Kicinski	rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
517e8b461c37717d6b5c071c4924845884a86c20752Jakub Kicinski	rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
518e8b461c37717d6b5c071c4924845884a86c20752Jakub Kicinski
519e8b461c37717d6b5c071c4924845884a86c20752Jakub Kicinski	rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, 0xff, 0x02);
520e8b461c37717d6b5c071c4924845884a86c20752Jakub Kicinski	rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF);
521e8b461c37717d6b5c071c4924845884a86c20752Jakub Kicinski
522e8b461c37717d6b5c071c4924845884a86c20752Jakub Kicinski	rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKEUP, 0, 0);
523e8b461c37717d6b5c071c4924845884a86c20752Jakub Kicinski	rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP);
524e8b461c37717d6b5c071c4924845884a86c20752Jakub Kicinski
525e8b461c37717d6b5c071c4924845884a86c20752Jakub Kicinski	return retval;
526a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
527a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
528a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
529a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
5307f6e144fb99a4a70d3c5ad5f074204c5b89a6f65RA-Jay Hung	if (rt2x00_is_soc(rt2x00dev)) {
5317f6e144fb99a4a70d3c5ad5f074204c5b89a6f65RA-Jay Hung		rt2800_disable_radio(rt2x00dev);
5329a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0);
5339a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0);
5347f6e144fb99a4a70d3c5ad5f074204c5b89a6f65RA-Jay Hung	}
535a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
536a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
537a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
538a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn			       enum dev_state state)
539a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
540a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	if (state == STATE_AWAKE) {
54109a3311c1a061bda809ff78c512855f3b71dcd6bJakub Kicinski		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKEUP,
54209a3311c1a061bda809ff78c512855f3b71dcd6bJakub Kicinski				   0, 0x02);
54309a3311c1a061bda809ff78c512855f3b71dcd6bJakub Kicinski		rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP);
5447f6e144fb99a4a70d3c5ad5f074204c5b89a6f65RA-Jay Hung	} else if (state == STATE_SLEEP) {
5459a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS,
5469a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa					 0xffffffff);
5479a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID,
5489a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa					 0xffffffff);
54909a3311c1a061bda809ff78c512855f3b71dcd6bJakub Kicinski		rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP,
55009a3311c1a061bda809ff78c512855f3b71dcd6bJakub Kicinski				   0xff, 0x01);
551a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	}
552a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
553a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	return 0;
554a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
555a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
556a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
557a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn				      enum dev_state state)
558a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
559a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	int retval = 0;
560a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
561a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	switch (state) {
562a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	case STATE_RADIO_ON:
563a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		retval = rt2800pci_enable_radio(rt2x00dev);
564a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		break;
565a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	case STATE_RADIO_OFF:
566a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		/*
567a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		 * After the radio has been disabled, the device should
568a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		 * be put to sleep for powersaving.
569a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		 */
570a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rt2800pci_disable_radio(rt2x00dev);
571a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rt2800pci_set_state(rt2x00dev, STATE_SLEEP);
572a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		break;
573a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	case STATE_RADIO_IRQ_ON:
574a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	case STATE_RADIO_IRQ_OFF:
575a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rt2800pci_toggle_irq(rt2x00dev, state);
576a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		break;
577a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	case STATE_DEEP_SLEEP:
578a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	case STATE_SLEEP:
579a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	case STATE_STANDBY:
580a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	case STATE_AWAKE:
581a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		retval = rt2800pci_set_state(rt2x00dev, state);
582a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		break;
583a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	default:
584a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		retval = -ENOTSUPP;
585a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		break;
586a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	}
587a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
588a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	if (unlikely(retval))
589a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
590a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		      state, retval);
591a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
592a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	return retval;
593a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
594a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
595a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn/*
596a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn * TX descriptor initialization
597a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn */
5980c5879bc62f9b8eb31520a86213466f3a68ec794Ivo van Doornstatic __le32 *rt2800pci_get_txwi(struct queue_entry *entry)
599a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
6000c5879bc62f9b8eb31520a86213466f3a68ec794Ivo van Doorn	return (__le32 *) entry->skb->data;
601745b1ae31ba6644a943ec2b6da2d03f00d8b2dd2Helmut Schaa}
602745b1ae31ba6644a943ec2b6da2d03f00d8b2dd2Helmut Schaa
603933314582ee5db00123683cf4c4d713ec9add306Ivo van Doornstatic void rt2800pci_write_tx_desc(struct queue_entry *entry,
604745b1ae31ba6644a943ec2b6da2d03f00d8b2dd2Helmut Schaa				    struct txentry_desc *txdesc)
605745b1ae31ba6644a943ec2b6da2d03f00d8b2dd2Helmut Schaa{
606933314582ee5db00123683cf4c4d713ec9add306Ivo van Doorn	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
607933314582ee5db00123683cf4c4d713ec9add306Ivo van Doorn	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
60885b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde	__le32 *txd = entry_priv->desc;
609745b1ae31ba6644a943ec2b6da2d03f00d8b2dd2Helmut Schaa	u32 word;
610745b1ae31ba6644a943ec2b6da2d03f00d8b2dd2Helmut Schaa
611a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	/*
612a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * The buffers pointed by SD_PTR0/SD_LEN0 and SD_PTR1/SD_LEN1
613a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * must contains a TXWI structure + 802.11 header + padding + 802.11
614a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * data. We choose to have SD_PTR0/SD_LEN0 only contains TXWI and
615a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * SD_PTR1/SD_LEN1 contains 802.11 header + padding + 802.11
616a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * data. It means that LAST_SEC0 is always 0.
617a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 */
618a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
619a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	/*
620a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * Initialize TX descriptor
621a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 */
6223de3d966007592693e68a973f62a1e3828565af0Helmut Schaa	word = 0;
623a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma);
624a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_desc_write(txd, 0, word);
625a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
6263de3d966007592693e68a973f62a1e3828565af0Helmut Schaa	word = 0;
627933314582ee5db00123683cf4c4d713ec9add306Ivo van Doorn	rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len);
628a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_set_field32(&word, TXD_W1_LAST_SEC1,
629a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn			   !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
630a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_set_field32(&word, TXD_W1_BURST,
631a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn			   test_bit(ENTRY_TXD_BURST, &txdesc->flags));
63285b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde	rt2x00_set_field32(&word, TXD_W1_SD_LEN0, TXWI_DESC_SIZE);
633a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0);
634a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0);
635a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_desc_write(txd, 1, word);
636a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
6373de3d966007592693e68a973f62a1e3828565af0Helmut Schaa	word = 0;
638a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_set_field32(&word, TXD_W2_SD_PTR1,
63985b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde			   skbdesc->skb_dma + TXWI_DESC_SIZE);
640a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_desc_write(txd, 2, word);
641a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
6423de3d966007592693e68a973f62a1e3828565af0Helmut Schaa	word = 0;
643a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_set_field32(&word, TXD_W3_WIV,
644a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn			   !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
645a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_set_field32(&word, TXD_W3_QSEL, 2);
646a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00_desc_write(txd, 3, word);
64785b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde
64885b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde	/*
64985b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde	 * Register descriptor details in skb frame descriptor.
65085b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde	 */
65185b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde	skbdesc->desc = txd;
65285b7a8b3871bde7885516fed2a1c8da699913318Gertjan van Wingerde	skbdesc->desc_len = TXD_DESC_SIZE;
653a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
654a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
655a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn/*
656a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn * RX control handlers
657a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn */
658a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic void rt2800pci_fill_rxdone(struct queue_entry *entry,
659a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn				  struct rxdone_entry_desc *rxdesc)
660a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
661a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
662a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	__le32 *rxd = entry_priv->desc;
6632de64dd22d0390688b853788dcadee3c0ad9e518Gertjan van Wingerde	u32 word;
6642de64dd22d0390688b853788dcadee3c0ad9e518Gertjan van Wingerde
6652de64dd22d0390688b853788dcadee3c0ad9e518Gertjan van Wingerde	rt2x00_desc_read(rxd, 3, &word);
6662de64dd22d0390688b853788dcadee3c0ad9e518Gertjan van Wingerde
6672de64dd22d0390688b853788dcadee3c0ad9e518Gertjan van Wingerde	if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR))
668a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
669a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
67078b8f3b0ddb061af1e3907f9c4bca76eae39f79fGertjan van Wingerde	/*
67178b8f3b0ddb061af1e3907f9c4bca76eae39f79fGertjan van Wingerde	 * Unfortunately we don't know the cipher type used during
67278b8f3b0ddb061af1e3907f9c4bca76eae39f79fGertjan van Wingerde	 * decryption. This prevents us from correct providing
67378b8f3b0ddb061af1e3907f9c4bca76eae39f79fGertjan van Wingerde	 * correct statistics through debugfs.
67478b8f3b0ddb061af1e3907f9c4bca76eae39f79fGertjan van Wingerde	 */
6752de64dd22d0390688b853788dcadee3c0ad9e518Gertjan van Wingerde	rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W3_CIPHER_ERROR);
676a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
6772de64dd22d0390688b853788dcadee3c0ad9e518Gertjan van Wingerde	if (rt2x00_get_field32(word, RXD_W3_DECRYPTED)) {
678a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		/*
679a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		 * Hardware has stripped IV/EIV data from 802.11 frame during
680a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		 * decryption. Unfortunately the descriptor doesn't contain
681a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		 * any fields with the EIV/IV data either, so they can't
682a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		 * be restored by rt2x00lib.
683a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		 */
684a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rxdesc->flags |= RX_FLAG_IV_STRIPPED;
685a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
686a45f369d477c0e1b15b77c7b09ccfa043097e9abGertjan van Wingerde		/*
687a45f369d477c0e1b15b77c7b09ccfa043097e9abGertjan van Wingerde		 * The hardware has already checked the Michael Mic and has
688a45f369d477c0e1b15b77c7b09ccfa043097e9abGertjan van Wingerde		 * stripped it from the frame. Signal this to mac80211.
689a45f369d477c0e1b15b77c7b09ccfa043097e9abGertjan van Wingerde		 */
690a45f369d477c0e1b15b77c7b09ccfa043097e9abGertjan van Wingerde		rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
691a45f369d477c0e1b15b77c7b09ccfa043097e9abGertjan van Wingerde
692a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
693a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn			rxdesc->flags |= RX_FLAG_DECRYPTED;
694a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
695a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn			rxdesc->flags |= RX_FLAG_MMIC_ERROR;
696a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	}
697a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
6982de64dd22d0390688b853788dcadee3c0ad9e518Gertjan van Wingerde	if (rt2x00_get_field32(word, RXD_W3_MY_BSS))
699a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rxdesc->dev_flags |= RXDONE_MY_BSS;
700a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
7012de64dd22d0390688b853788dcadee3c0ad9e518Gertjan van Wingerde	if (rt2x00_get_field32(word, RXD_W3_L2PAD))
702a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		rxdesc->dev_flags |= RXDONE_L2PAD;
703a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
704a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	/*
7052de64dd22d0390688b853788dcadee3c0ad9e518Gertjan van Wingerde	 * Process the RXWI structure that is at the start of the buffer.
706a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 */
707748619220651a33c260ed6c0a7648e69324edd74Ivo van Doorn	rt2800_process_rxwi(entry, rxdesc);
708a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
709a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
710a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn/*
711a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn * Interrupt functions.
712a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn */
7134d66edc8b6c0622ed6df74709de65f70d1ca222fGertjan van Wingerdestatic void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev)
7144d66edc8b6c0622ed6df74709de65f70d1ca222fGertjan van Wingerde{
7154d66edc8b6c0622ed6df74709de65f70d1ca222fGertjan van Wingerde	struct ieee80211_conf conf = { .flags = 0 };
7164d66edc8b6c0622ed6df74709de65f70d1ca222fGertjan van Wingerde	struct rt2x00lib_conf libconf = { .conf = &conf };
7174d66edc8b6c0622ed6df74709de65f70d1ca222fGertjan van Wingerde
7184d66edc8b6c0622ed6df74709de65f70d1ca222fGertjan van Wingerde	rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
7194d66edc8b6c0622ed6df74709de65f70d1ca222fGertjan van Wingerde}
7204d66edc8b6c0622ed6df74709de65f70d1ca222fGertjan van Wingerde
7212e7798b7c12bdaab4a4aee76d6d1ab7c986234acHelmut Schaastatic bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
72296c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa{
72396c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	struct data_queue *queue;
72496c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	struct queue_entry *entry;
72596c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	u32 status;
72696c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	u8 qid;
7272e7798b7c12bdaab4a4aee76d6d1ab7c986234acHelmut Schaa	int max_tx_done = 16;
72896c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa
729c4d63244218bf93d1f0cdf4389e0906df8f506c1Johannes Stezenbach	while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) {
73012eec2cc0d5eacd8287646585dc88ab558d4866dHelmut Schaa		qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE);
73187443e875c8ad1f0c25b1255bdeb88de934e151eHelmut Schaa		if (unlikely(qid >= QID_RX)) {
73296c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			/*
73396c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			 * Unknown queue, this shouldn't happen. Just drop
73496c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			 * this tx status.
73596c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			 */
73696c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			WARNING(rt2x00dev, "Got TX status report with "
737094a1d92fdb18c4455758b1c33e99d647c837ee9Johannes Stezenbach					   "unexpected pid %u, dropping\n", qid);
73896c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			break;
73996c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa		}
74096c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa
74111f818e0eb50864c7e6f8af38d8f8822f992906aHelmut Schaa		queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
74296c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa		if (unlikely(queue == NULL)) {
74396c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			/*
74496c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			 * The queue is NULL, this shouldn't happen. Stop
74596c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			 * processing here and drop the tx status
74696c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			 */
74796c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			WARNING(rt2x00dev, "Got TX status for an unavailable "
748094a1d92fdb18c4455758b1c33e99d647c837ee9Johannes Stezenbach					   "queue %u, dropping\n", qid);
74996c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			break;
75096c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa		}
75196c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa
75287443e875c8ad1f0c25b1255bdeb88de934e151eHelmut Schaa		if (unlikely(rt2x00queue_empty(queue))) {
75396c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			/*
75496c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			 * The queue is empty. Stop processing here
75596c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			 * and drop the tx status.
75696c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			 */
75796c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			WARNING(rt2x00dev, "Got TX status for an empty "
758094a1d92fdb18c4455758b1c33e99d647c837ee9Johannes Stezenbach					   "queue %u, dropping\n", qid);
75996c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			break;
76096c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa		}
76196c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa
76296c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa		entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
76331937c423ed3a13613b3aa7459e7405dd428f2d8Helmut Schaa		rt2800_txdone_entry(entry, status, rt2800pci_get_txwi(entry));
7642e7798b7c12bdaab4a4aee76d6d1ab7c986234acHelmut Schaa
7652e7798b7c12bdaab4a4aee76d6d1ab7c986234acHelmut Schaa		if (--max_tx_done == 0)
7662e7798b7c12bdaab4a4aee76d6d1ab7c986234acHelmut Schaa			break;
76796c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	}
7682e7798b7c12bdaab4a4aee76d6d1ab7c986234acHelmut Schaa
7692e7798b7c12bdaab4a4aee76d6d1ab7c986234acHelmut Schaa	return !max_tx_done;
77096c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa}
77196c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa
7727a5a681a7df7d844b52f82a4388e078071eb883eHelmut Schaastatic inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
7737a5a681a7df7d844b52f82a4388e078071eb883eHelmut Schaa					      struct rt2x00_field32 irq_field)
774a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
775a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	u32 reg;
776a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
777a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	/*
778a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	 * Enable a single interrupt. The interrupt mask register
779a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	 * access needs locking.
7809f926fb57a2eb14d58ea6d6699544f9ccd0df8c7Helmut Schaa	 */
7810aa13b2e06fbb8327c7acb4ccf684b2b65c302ceHelmut Schaa	spin_lock_irq(&rt2x00dev->irqmask_lock);
7829a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
783a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	rt2x00_set_field32(&reg, irq_field, 1);
7849a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
7850aa13b2e06fbb8327c7acb4ccf684b2b65c302ceHelmut Schaa	spin_unlock_irq(&rt2x00dev->irqmask_lock);
786a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa}
7879f926fb57a2eb14d58ea6d6699544f9ccd0df8c7Helmut Schaa
788a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaastatic void rt2800pci_txstatus_tasklet(unsigned long data)
789a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa{
7902e7798b7c12bdaab4a4aee76d6d1ab7c986234acHelmut Schaa	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
7912e7798b7c12bdaab4a4aee76d6d1ab7c986234acHelmut Schaa	if (rt2800pci_txdone(rt2x00dev))
7922e7798b7c12bdaab4a4aee76d6d1ab7c986234acHelmut Schaa		tasklet_schedule(&rt2x00dev->txstatus_tasklet);
7939f926fb57a2eb14d58ea6d6699544f9ccd0df8c7Helmut Schaa
7949f926fb57a2eb14d58ea6d6699544f9ccd0df8c7Helmut Schaa	/*
795a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	 * No need to enable the tx status interrupt here as we always
796a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	 * leave it enabled to minimize the possibility of a tx status
797a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	 * register overflow. See comment in interrupt handler.
798a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 */
799a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa}
800a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
801a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaastatic void rt2800pci_pretbtt_tasklet(unsigned long data)
802a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa{
803a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
804a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	rt2x00lib_pretbtt(rt2x00dev);
805abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
806abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT);
807a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa}
8084d66edc8b6c0622ed6df74709de65f70d1ca222fGertjan van Wingerde
809a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaastatic void rt2800pci_tbtt_tasklet(unsigned long data)
810a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa{
811a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
812290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
813290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa	u32 reg;
814290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa
815a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	rt2x00lib_beacondone(rt2x00dev);
816290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa
817290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa	if (rt2x00dev->intf_ap_count) {
818290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa		/*
819290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa		 * The rt2800pci hardware tbtt timer is off by 1us per tbtt
820290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa		 * causing beacon skew and as a result causing problems with
821290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa		 * some powersaving clients over time. Shorten the beacon
822290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa		 * interval every 64 beacons by 64us to mitigate this effect.
823290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa		 */
824290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa		if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) {
825290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa			rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
826290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa			rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
827290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa					   (rt2x00dev->beacon_int * 16) - 1);
828290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa			rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
829290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa		} else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) {
830290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa			rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
831290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa			rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
832290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa					   (rt2x00dev->beacon_int * 16));
833290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa			rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
834290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa		}
835290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa		drv_data->tbtt_tick++;
836290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa		drv_data->tbtt_tick %= BCN_TBTT_OFFSET;
837290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa	}
838290d60891eb659e52204ec209e08cc0cabc5b99fHelmut Schaa
839abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
840abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT);
841a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa}
84278e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa
843a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaastatic void rt2800pci_rxdone_tasklet(unsigned long data)
844a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa{
845a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
846166389375d5a3894aa00a9c2e490ac4b9af2a891Helmut Schaa	if (rt2x00pci_rxdone(rt2x00dev))
847166389375d5a3894aa00a9c2e490ac4b9af2a891Helmut Schaa		tasklet_schedule(&rt2x00dev->rxdone_tasklet);
848abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa	else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
849166389375d5a3894aa00a9c2e490ac4b9af2a891Helmut Schaa		rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE);
850a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa}
851a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa
852a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaastatic void rt2800pci_autowake_tasklet(unsigned long data)
853a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa{
854a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
855a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	rt2800pci_wakeup(rt2x00dev);
856abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
857abc11994112bf7441519e35f51c29ff5de5b0d4dHelmut Schaa		rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_AUTO_WAKEUP);
858a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
859a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
86096c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaastatic void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
86196c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa{
86296c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	u32 status;
86396c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	int i;
86496c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa
86596c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	/*
86696c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	 * The TX_FIFO_STATUS interrupt needs special care. We should
86796c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	 * read TX_STA_FIFO but we should do it immediately as otherwise
86896c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	 * the register can overflow and we would lose status reports.
86996c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	 *
87096c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	 * Hence, read the TX_STA_FIFO register and copy all tx status
87196c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	 * reports into a kernel FIFO which is handled in the txstatus
87296c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	 * tasklet. We use a tasklet to process the tx status reports
87396c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	 * because we can schedule the tasklet multiple times (when the
87496c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	 * interrupt fires again during tx status processing).
87596c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	 *
87696c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	 * Furthermore we don't disable the TX_FIFO_STATUS
87796c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	 * interrupt here but leave it enabled so that the TX_STA_FIFO
8783736fe5808577f9d3a31a565ef4e78ceae250c98Helmut Schaa	 * can also be read while the tx status tasklet gets executed.
87996c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	 *
88096c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	 * Since we have only one producer and one consumer we don't
88196c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	 * need to lock the kfifo.
88296c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	 */
883efd2f271e44c7ea011cdb0363d38f40338ab80d2Helmut Schaa	for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
8849a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa		rt2x00pci_register_read(rt2x00dev, TX_STA_FIFO, &status);
88596c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa
88696c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa		if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
88796c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			break;
88896c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa
889c4d63244218bf93d1f0cdf4389e0906df8f506c1Johannes Stezenbach		if (!kfifo_put(&rt2x00dev->txstatus_fifo, &status)) {
89096c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			WARNING(rt2x00dev, "TX status FIFO overrun,"
89196c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa				"drop tx status report.\n");
89296c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa			break;
89396c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa		}
89496c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	}
89596c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa
89696c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	/* Schedule the tasklet for processing the tx status. */
89796c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa	tasklet_schedule(&rt2x00dev->txstatus_tasklet);
89896c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa}
89996c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa
90078e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaastatic irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
90178e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa{
90278e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa	struct rt2x00_dev *rt2x00dev = dev_instance;
903a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	u32 reg, mask;
90478e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa
90578e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa	/* Read status and ACK all interrupts */
9069a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
9079a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
90878e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa
90978e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa	if (!reg)
91078e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa		return IRQ_NONE;
91178e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa
91278e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
91378e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa		return IRQ_HANDLED;
91478e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa
915a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	/*
916a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	 * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits
917a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	 * for interrupts and interrupt masks we can just use the value of
918a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	 * INT_SOURCE_CSR to create the interrupt mask.
919a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	 */
920a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	mask = ~reg;
92178e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa
922a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
923a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa		rt2800pci_txstatus_interrupt(rt2x00dev);
92496c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa		/*
925a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa		 * Never disable the TX_FIFO_STATUS interrupt.
92696c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa		 */
927a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa		rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1);
928a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	}
92996c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa
930a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
931a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa		tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet);
93278e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa
933a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
934a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa		tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
93596c3da7d7d7c37ee308ad6813947f48a71cca573Helmut Schaa
936a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE))
937a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa		tasklet_schedule(&rt2x00dev->rxdone_tasklet);
93878e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa
939a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
940a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa		tasklet_schedule(&rt2x00dev->autowake_tasklet);
941a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa
942a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	/*
943a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	 * Disable all interrupts for which a tasklet was scheduled right now,
944a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	 * the tasklet will reenable the appropriate interrupts.
945a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	 */
9460aa13b2e06fbb8327c7acb4ccf684b2b65c302ceHelmut Schaa	spin_lock(&rt2x00dev->irqmask_lock);
9479a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
948a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	reg &= mask;
9499a8199961b22e61221a6114b8bbbc26ddcc243f7Helmut Schaa	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
9500aa13b2e06fbb8327c7acb4ccf684b2b65c302ceHelmut Schaa	spin_unlock(&rt2x00dev->irqmask_lock);
951a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa
952a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	return IRQ_HANDLED;
95378e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa}
95478e256c9a3717bcae2e9ed05c9ec7bed7bf2c55dHelmut Schaa
955a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn/*
956a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn * Device probe functions.
957a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn */
9587ab71325cf0940099c376799aca6de7bc86ad2d0Bartlomiej Zolnierkiewiczstatic int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
9597ab71325cf0940099c376799aca6de7bc86ad2d0Bartlomiej Zolnierkiewicz{
9607ab71325cf0940099c376799aca6de7bc86ad2d0Bartlomiej Zolnierkiewicz	/*
9617ab71325cf0940099c376799aca6de7bc86ad2d0Bartlomiej Zolnierkiewicz	 * Read EEPROM into buffer
9627ab71325cf0940099c376799aca6de7bc86ad2d0Bartlomiej Zolnierkiewicz	 */
963cea90e55969ff70b970d64d564076a5469331527Gertjan van Wingerde	if (rt2x00_is_soc(rt2x00dev))
9647ab71325cf0940099c376799aca6de7bc86ad2d0Bartlomiej Zolnierkiewicz		rt2800pci_read_eeprom_soc(rt2x00dev);
965cea90e55969ff70b970d64d564076a5469331527Gertjan van Wingerde	else if (rt2800pci_efuse_detect(rt2x00dev))
966cea90e55969ff70b970d64d564076a5469331527Gertjan van Wingerde		rt2800pci_read_eeprom_efuse(rt2x00dev);
967cea90e55969ff70b970d64d564076a5469331527Gertjan van Wingerde	else
968cea90e55969ff70b970d64d564076a5469331527Gertjan van Wingerde		rt2800pci_read_eeprom_pci(rt2x00dev);
9697ab71325cf0940099c376799aca6de7bc86ad2d0Bartlomiej Zolnierkiewicz
9707ab71325cf0940099c376799aca6de7bc86ad2d0Bartlomiej Zolnierkiewicz	return rt2800_validate_eeprom(rt2x00dev);
9717ab71325cf0940099c376799aca6de7bc86ad2d0Bartlomiej Zolnierkiewicz}
9727ab71325cf0940099c376799aca6de7bc86ad2d0Bartlomiej Zolnierkiewicz
973a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
974a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
975a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	int retval;
976a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
977a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	/*
978a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * Allocate eeprom data.
979a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 */
980a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	retval = rt2800pci_validate_eeprom(rt2x00dev);
981a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	if (retval)
982a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		return retval;
983a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
98438bd7b8a0f485ba5ad514fcd621a1842ebadf9e6Bartlomiej Zolnierkiewicz	retval = rt2800_init_eeprom(rt2x00dev);
985a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	if (retval)
986a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		return retval;
987a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
988a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	/*
989a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * Initialize hw specifications.
990a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 */
9914da2933fe1f2d3d9ed548660f5c02a9b0608a8c7Bartlomiej Zolnierkiewicz	retval = rt2800_probe_hw_mode(rt2x00dev);
992a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	if (retval)
993a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		return retval;
994a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
995a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	/*
996a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * This device has multiple filters for control frames
997a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * and has a separate filter for PS Poll frames.
998a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 */
9997dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
10007dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn	__set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);
1001a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1002a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	/*
10039f926fb57a2eb14d58ea6d6699544f9ccd0df8c7Helmut Schaa	 * This device has a pre tbtt interrupt and thus fetches
10049f926fb57a2eb14d58ea6d6699544f9ccd0df8c7Helmut Schaa	 * a new beacon directly prior to transmission.
10059f926fb57a2eb14d58ea6d6699544f9ccd0df8c7Helmut Schaa	 */
10067dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn	__set_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags);
10079f926fb57a2eb14d58ea6d6699544f9ccd0df8c7Helmut Schaa
10089f926fb57a2eb14d58ea6d6699544f9ccd0df8c7Helmut Schaa	/*
1009a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * This device requires firmware.
1010a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 */
1011cea90e55969ff70b970d64d564076a5469331527Gertjan van Wingerde	if (!rt2x00_is_soc(rt2x00dev))
10127dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn		__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
10137dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn	__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
10147dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn	__set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags);
10157dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn	__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
10167dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn	__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
1017a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	if (!modparam_nohwcrypt)
10187dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
10197dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
10207dab73b37f5e8885cb73efd25e73861f9b4f0246Ivo van Doorn	__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
1021a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1022a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	/*
1023a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 * Set the rssi offset.
1024a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	 */
1025a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
1026a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1027a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	return 0;
1028a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
1029a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1030e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaastatic const struct ieee80211_ops rt2800pci_mac80211_ops = {
1031e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.tx			= rt2x00mac_tx,
1032e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.start			= rt2x00mac_start,
1033e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.stop			= rt2x00mac_stop,
1034e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.add_interface		= rt2x00mac_add_interface,
1035e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.remove_interface	= rt2x00mac_remove_interface,
1036e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.config			= rt2x00mac_config,
1037e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.configure_filter	= rt2x00mac_configure_filter,
1038e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.set_key		= rt2x00mac_set_key,
1039e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.sw_scan_start		= rt2x00mac_sw_scan_start,
1040e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.sw_scan_complete	= rt2x00mac_sw_scan_complete,
1041e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.get_stats		= rt2x00mac_get_stats,
1042e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.get_tkip_seq		= rt2800_get_tkip_seq,
1043e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.set_rts_threshold	= rt2800_set_rts_threshold,
1044a2b1328a23c57fbb9c51e6660a11049c35d151f9Helmut Schaa	.sta_add		= rt2x00mac_sta_add,
1045a2b1328a23c57fbb9c51e6660a11049c35d151f9Helmut Schaa	.sta_remove		= rt2x00mac_sta_remove,
1046e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.bss_info_changed	= rt2x00mac_bss_info_changed,
1047e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.conf_tx		= rt2800_conf_tx,
1048e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.get_tsf		= rt2800_get_tsf,
1049e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.rfkill_poll		= rt2x00mac_rfkill_poll,
1050e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.ampdu_action		= rt2800_ampdu_action,
1051f44df18c58d4debe3ec0bb76a490aa2f3929fd8bIvo van Doorn	.flush			= rt2x00mac_flush,
1052977206d79fdc9fc1b153e0b52c56e0be59586f37Helmut Schaa	.get_survey		= rt2800_get_survey,
1053e7dee444263a103a9a2ac5fd5d0b5e9dc177d57cIvo van Doorn	.get_ringparam		= rt2x00mac_get_ringparam,
10545f0dd296a01c8173fcc05a8b262a1168ae90bc74Gertjan van Wingerde	.tx_frames_pending	= rt2x00mac_tx_frames_pending,
1055e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa};
1056e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa
1057e796643eaf0889c346e6b69c5afe777c327b1919Ivo van Doornstatic const struct rt2800_ops rt2800pci_rt2800_ops = {
1058e796643eaf0889c346e6b69c5afe777c327b1919Ivo van Doorn	.register_read		= rt2x00pci_register_read,
1059e796643eaf0889c346e6b69c5afe777c327b1919Ivo van Doorn	.register_read_lock	= rt2x00pci_register_read, /* same for PCI */
1060e796643eaf0889c346e6b69c5afe777c327b1919Ivo van Doorn	.register_write		= rt2x00pci_register_write,
1061e796643eaf0889c346e6b69c5afe777c327b1919Ivo van Doorn	.register_write_lock	= rt2x00pci_register_write, /* same for PCI */
1062e796643eaf0889c346e6b69c5afe777c327b1919Ivo van Doorn	.register_multiread	= rt2x00pci_register_multiread,
1063e796643eaf0889c346e6b69c5afe777c327b1919Ivo van Doorn	.register_multiwrite	= rt2x00pci_register_multiwrite,
1064e796643eaf0889c346e6b69c5afe777c327b1919Ivo van Doorn	.regbusy_read		= rt2x00pci_regbusy_read,
1065e796643eaf0889c346e6b69c5afe777c327b1919Ivo van Doorn	.drv_write_firmware	= rt2800pci_write_firmware,
1066e796643eaf0889c346e6b69c5afe777c327b1919Ivo van Doorn	.drv_init_registers	= rt2800pci_init_registers,
10670c5879bc62f9b8eb31520a86213466f3a68ec794Ivo van Doorn	.drv_get_txwi		= rt2800pci_get_txwi,
1068e796643eaf0889c346e6b69c5afe777c327b1919Ivo van Doorn};
1069e796643eaf0889c346e6b69c5afe777c327b1919Ivo van Doorn
1070a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
1071a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.irq_handler		= rt2800pci_interrupt,
1072a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	.txstatus_tasklet	= rt2800pci_txstatus_tasklet,
1073a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	.pretbtt_tasklet	= rt2800pci_pretbtt_tasklet,
1074a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	.tbtt_tasklet		= rt2800pci_tbtt_tasklet,
1075a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	.rxdone_tasklet		= rt2800pci_rxdone_tasklet,
1076a9d61e9e779579c66c0d4c8af203d51dbca1473cHelmut Schaa	.autowake_tasklet	= rt2800pci_autowake_tasklet,
1077a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.probe_hw		= rt2800pci_probe_hw,
1078a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.get_firmware_name	= rt2800pci_get_firmware_name,
1079f31c9a8c1380e20e95d06925f2e42baf61af4db7Ivo van Doorn	.check_firmware		= rt2800_check_firmware,
1080f31c9a8c1380e20e95d06925f2e42baf61af4db7Ivo van Doorn	.load_firmware		= rt2800_load_firmware,
1081a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.initialize		= rt2x00pci_initialize,
1082a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.uninitialize		= rt2x00pci_uninitialize,
1083a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.get_entry_state	= rt2800pci_get_entry_state,
1084a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.clear_entry		= rt2800pci_clear_entry,
1085a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.set_device_state	= rt2800pci_set_device_state,
1086f445061630c7a4a85193fdef006234f94f71c366Bartlomiej Zolnierkiewicz	.rfkill_poll		= rt2800_rfkill_poll,
1087f445061630c7a4a85193fdef006234f94f71c366Bartlomiej Zolnierkiewicz	.link_stats		= rt2800_link_stats,
1088f445061630c7a4a85193fdef006234f94f71c366Bartlomiej Zolnierkiewicz	.reset_tuner		= rt2800_reset_tuner,
1089f445061630c7a4a85193fdef006234f94f71c366Bartlomiej Zolnierkiewicz	.link_tuner		= rt2800_link_tuner,
10909e33a3553821418b2c4f53d09311476c55176b13Helmut Schaa	.gain_calibration	= rt2800_gain_calibration,
10912e9c43dd45ced5bd77c94d4216f96b4a49448d73John Li	.vco_calibration	= rt2800_vco_calibration,
1092dbba306f2ae574450a7a5133d6637fe6f5fafc72Ivo van Doorn	.start_queue		= rt2800pci_start_queue,
1093dbba306f2ae574450a7a5133d6637fe6f5fafc72Ivo van Doorn	.kick_queue		= rt2800pci_kick_queue,
1094dbba306f2ae574450a7a5133d6637fe6f5fafc72Ivo van Doorn	.stop_queue		= rt2800pci_stop_queue,
1095152a599274b15028604e24ae2d9c9d7f49853977Ivo van Doorn	.flush_queue		= rt2x00pci_flush_queue,
1096a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.write_tx_desc		= rt2800pci_write_tx_desc,
10970c5879bc62f9b8eb31520a86213466f3a68ec794Ivo van Doorn	.write_tx_data		= rt2800_write_tx_data,
1098f0194b2d5d01b99555fd8a6e42281809086f1ab1Gertjan van Wingerde	.write_beacon		= rt2800_write_beacon,
109969cf36a4523be026bc16743c5c989c5e82edb7d9Helmut Schaa	.clear_beacon		= rt2800_clear_beacon,
1100a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.fill_rxdone		= rt2800pci_fill_rxdone,
1101f445061630c7a4a85193fdef006234f94f71c366Bartlomiej Zolnierkiewicz	.config_shared_key	= rt2800_config_shared_key,
1102f445061630c7a4a85193fdef006234f94f71c366Bartlomiej Zolnierkiewicz	.config_pairwise_key	= rt2800_config_pairwise_key,
1103f445061630c7a4a85193fdef006234f94f71c366Bartlomiej Zolnierkiewicz	.config_filter		= rt2800_config_filter,
1104f445061630c7a4a85193fdef006234f94f71c366Bartlomiej Zolnierkiewicz	.config_intf		= rt2800_config_intf,
1105f445061630c7a4a85193fdef006234f94f71c366Bartlomiej Zolnierkiewicz	.config_erp		= rt2800_config_erp,
1106f445061630c7a4a85193fdef006234f94f71c366Bartlomiej Zolnierkiewicz	.config_ant		= rt2800_config_ant,
1107f445061630c7a4a85193fdef006234f94f71c366Bartlomiej Zolnierkiewicz	.config			= rt2800_config,
1108a2b1328a23c57fbb9c51e6660a11049c35d151f9Helmut Schaa	.sta_add		= rt2800_sta_add,
1109a2b1328a23c57fbb9c51e6660a11049c35d151f9Helmut Schaa	.sta_remove		= rt2800_sta_remove,
1110a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn};
1111a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1112a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic const struct data_queue_desc rt2800pci_queue_rx = {
1113efd2f271e44c7ea011cdb0363d38f40338ab80d2Helmut Schaa	.entry_num		= 128,
1114a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.data_size		= AGGREGATION_SIZE,
1115a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.desc_size		= RXD_DESC_SIZE,
1116a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.priv_size		= sizeof(struct queue_entry_priv_pci),
1117a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn};
1118a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1119a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic const struct data_queue_desc rt2800pci_queue_tx = {
1120efd2f271e44c7ea011cdb0363d38f40338ab80d2Helmut Schaa	.entry_num		= 64,
1121a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.data_size		= AGGREGATION_SIZE,
1122a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.desc_size		= TXD_DESC_SIZE,
1123a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.priv_size		= sizeof(struct queue_entry_priv_pci),
1124a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn};
1125a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1126a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic const struct data_queue_desc rt2800pci_queue_bcn = {
1127efd2f271e44c7ea011cdb0363d38f40338ab80d2Helmut Schaa	.entry_num		= 8,
1128a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.data_size		= 0, /* No DMA required for beacons */
1129a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.desc_size		= TXWI_DESC_SIZE,
1130a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.priv_size		= sizeof(struct queue_entry_priv_pci),
1131a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn};
1132a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1133a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic const struct rt2x00_ops rt2800pci_ops = {
113404d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.name			= KBUILD_MODNAME,
11353a1c01288e5596fb70ca48ec9d9d8b561121c544Gertjan van Wingerde	.drv_data_size		= sizeof(struct rt2800_drv_data),
113604d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.max_sta_intf		= 1,
113704d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.max_ap_intf		= 8,
113804d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.eeprom_size		= EEPROM_SIZE,
113904d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.rf_size		= RF_SIZE,
114004d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.tx_queues		= NUM_TX_QUEUES,
1141e6218cc47bd54710dc523e8c983ceddba625e3aeGertjan van Wingerde	.extra_tx_headroom	= TXWI_DESC_SIZE,
114204d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.rx			= &rt2800pci_queue_rx,
114304d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.tx			= &rt2800pci_queue_tx,
114404d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.bcn			= &rt2800pci_queue_bcn,
114504d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.lib			= &rt2800pci_rt2x00_ops,
1146e796643eaf0889c346e6b69c5afe777c327b1919Ivo van Doorn	.drv			= &rt2800pci_rt2800_ops,
1147e783619ea8f1fb9fccec4931b0cf956de0ed1019Helmut Schaa	.hw			= &rt2800pci_mac80211_ops,
1148a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#ifdef CONFIG_RT2X00_LIB_DEBUGFS
114904d0362e2fa9d5f1ab560d0d59d04a535b4f3973Gertjan van Wingerde	.debugfs		= &rt2800_rt2x00debug,
1150a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
1151a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn};
1152a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1153a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn/*
1154a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn * RT2800pci module information.
1155a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn */
115672c7296e03e381b49958809915105b18b09fa7a3Gertjan van Wingerde#ifdef CONFIG_PCI
1157a3aa18842a5303fc28fcc4d57dbd16618bd830a0Alexey Dobriyanstatic DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
1158e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1814, 0x0601) },
1159e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1814, 0x0681) },
1160e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1814, 0x0701) },
1161e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1814, 0x0781) },
1162e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1814, 0x3090) },
1163e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1814, 0x3091) },
1164e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1814, 0x3092) },
1165e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1432, 0x7708) },
1166e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1432, 0x7727) },
1167e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1432, 0x7728) },
1168e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1432, 0x7738) },
1169e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1432, 0x7748) },
1170e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1432, 0x7758) },
1171e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1432, 0x7768) },
1172e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1462, 0x891a) },
1173e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1a3b, 0x1059) },
1174f93bc9b3ce379800b30b3c2f4fc945ae35a80039Gertjan van Wingerde#ifdef CONFIG_RT2800PCI_RT33XX
1175e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1814, 0x3390) },
1176f93bc9b3ce379800b30b3c2f4fc945ae35a80039Gertjan van Wingerde#endif
1177de1ebdceb6a4fe1b7073b81d273285b7c8bed312Gertjan van Wingerde#ifdef CONFIG_RT2800PCI_RT35XX
1178e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1432, 0x7711) },
1179e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1432, 0x7722) },
1180e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1814, 0x3060) },
1181e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1814, 0x3062) },
1182e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1814, 0x3562) },
1183e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1814, 0x3592) },
1184e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1814, 0x3593) },
1185de1ebdceb6a4fe1b7073b81d273285b7c8bed312Gertjan van Wingerde#endif
118660687ba710359f32343b7630dc05d3811ef5bf4cRA-Shiang Tu#ifdef CONFIG_RT2800PCI_RT53XX
1187e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	{ PCI_DEVICE(0x1814, 0x5390) },
11885126d97ef5a38df8b24abb7611dcba7e5b729021zero.lin	{ PCI_DEVICE(0x1814, 0x539a) },
118971e0b38c2914018b01f3f08b43ee9e3328197699Gertjan van Wingerde	{ PCI_DEVICE(0x1814, 0x539f) },
119060687ba710359f32343b7630dc05d3811ef5bf4cRA-Shiang Tu#endif
1191a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	{ 0, }
1192a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn};
119372c7296e03e381b49958809915105b18b09fa7a3Gertjan van Wingerde#endif /* CONFIG_PCI */
1194a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1195a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van DoornMODULE_AUTHOR(DRV_PROJECT);
1196a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van DoornMODULE_VERSION(DRV_VERSION);
1197a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van DoornMODULE_DESCRIPTION("Ralink RT2800 PCI & PCMCIA Wireless LAN driver.");
1198a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van DoornMODULE_SUPPORTED_DEVICE("Ralink RT2860 PCI & PCMCIA chipset based cards");
119972c7296e03e381b49958809915105b18b09fa7a3Gertjan van Wingerde#ifdef CONFIG_PCI
1200a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van DoornMODULE_FIRMWARE(FIRMWARE_RT2860);
1201a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van DoornMODULE_DEVICE_TABLE(pci, rt2800pci_device_table);
120272c7296e03e381b49958809915105b18b09fa7a3Gertjan van Wingerde#endif /* CONFIG_PCI */
1203a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van DoornMODULE_LICENSE("GPL");
1204a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
120572c7296e03e381b49958809915105b18b09fa7a3Gertjan van Wingerde#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X)
1206714fa6636331d33c6045efe394f36c964a6c14eeGertjan van Wingerdestatic int rt2800soc_probe(struct platform_device *pdev)
1207714fa6636331d33c6045efe394f36c964a6c14eeGertjan van Wingerde{
12086e93d7195e75741e9ebe23ca5591977d0b39ecc0Helmut Schaa	return rt2x00soc_probe(pdev, &rt2800pci_ops);
1209714fa6636331d33c6045efe394f36c964a6c14eeGertjan van Wingerde}
1210a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1211a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic struct platform_driver rt2800soc_driver = {
1212a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.driver		= {
1213a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		.name		= "rt2800_wmac",
1214a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		.owner		= THIS_MODULE,
1215a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		.mod_name	= KBUILD_MODNAME,
1216a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	},
1217714fa6636331d33c6045efe394f36c964a6c14eeGertjan van Wingerde	.probe		= rt2800soc_probe,
1218a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.remove		= __devexit_p(rt2x00soc_remove),
1219a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.suspend	= rt2x00soc_suspend,
1220a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.resume		= rt2x00soc_resume,
1221a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn};
122272c7296e03e381b49958809915105b18b09fa7a3Gertjan van Wingerde#endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */
1223a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
122472c7296e03e381b49958809915105b18b09fa7a3Gertjan van Wingerde#ifdef CONFIG_PCI
1225e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerdestatic int rt2800pci_probe(struct pci_dev *pci_dev,
1226e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde			   const struct pci_device_id *id)
1227e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde{
1228e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	return rt2x00pci_probe(pci_dev, &rt2800pci_ops);
1229e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde}
1230e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde
1231a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic struct pci_driver rt2800pci_driver = {
1232a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.name		= KBUILD_MODNAME,
1233a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.id_table	= rt2800pci_device_table,
1234e01ae27f8ce6bd3ee26ef33c704f62449ce8233bGertjan van Wingerde	.probe		= rt2800pci_probe,
1235a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.remove		= __devexit_p(rt2x00pci_remove),
1236a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.suspend	= rt2x00pci_suspend,
1237a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	.resume		= rt2x00pci_resume,
1238a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn};
123972c7296e03e381b49958809915105b18b09fa7a3Gertjan van Wingerde#endif /* CONFIG_PCI */
1240a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1241a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic int __init rt2800pci_init(void)
1242a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
1243a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	int ret = 0;
1244a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
124572c7296e03e381b49958809915105b18b09fa7a3Gertjan van Wingerde#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X)
1246a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	ret = platform_driver_register(&rt2800soc_driver);
1247a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	if (ret)
1248a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		return ret;
1249a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#endif
125072c7296e03e381b49958809915105b18b09fa7a3Gertjan van Wingerde#ifdef CONFIG_PCI
1251a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	ret = pci_register_driver(&rt2800pci_driver);
1252a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	if (ret) {
125372c7296e03e381b49958809915105b18b09fa7a3Gertjan van Wingerde#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X)
1254a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		platform_driver_unregister(&rt2800soc_driver);
1255a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#endif
1256a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn		return ret;
1257a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	}
1258a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#endif
1259a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1260a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	return ret;
1261a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
1262a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1263a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornstatic void __exit rt2800pci_exit(void)
1264a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn{
126572c7296e03e381b49958809915105b18b09fa7a3Gertjan van Wingerde#ifdef CONFIG_PCI
1266a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	pci_unregister_driver(&rt2800pci_driver);
1267a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#endif
126872c7296e03e381b49958809915105b18b09fa7a3Gertjan van Wingerde#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X)
1269a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn	platform_driver_unregister(&rt2800soc_driver);
1270a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn#endif
1271a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn}
1272a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doorn
1273a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornmodule_init(rt2800pci_init);
1274a9b3a9f7214b3acc56330c2257aeaa5fa85bf520Ivo van Doornmodule_exit(rt2800pci_exit);
1275