iwlwifi: mvm: remove SCD_QUEUE_CONFIG TLV flag
[linux-block.git] / drivers / net / wireless / iwlwifi / iwl-io.c
CommitLineData
02a7fa00
JB
1/******************************************************************************
2 *
51368bf7 3 * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
02a7fa00
JB
4 *
5 * Portions of this file are derived from the ipw3945 project.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 *
20 * The full GNU General Public License is included in this distribution in the
21 * file called LICENSE.
22 *
23 * Contact Information:
24 * Intel Linux Wireless <ilw@linux.intel.com>
25 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
26 *
27 *****************************************************************************/
83ed9015
EG
28#include <linux/delay.h>
29#include <linux/device.h>
cc5f7e39 30#include <linux/export.h>
02a7fa00 31
48e29340 32#include "iwl-drv.h"
02a7fa00 33#include "iwl-io.h"
6ac7d115 34#include "iwl-csr.h"
83ed9015 35#include "iwl-debug.h"
4c9706dc 36#include "iwl-prph.h"
313b0a29 37#include "iwl-fh.h"
02a7fa00 38
a73a2cea
EG
39void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val)
40{
41 trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val);
42 iwl_trans_write8(trans, ofs, val);
43}
44IWL_EXPORT_SYMBOL(iwl_write8);
45
46void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val)
47{
48 trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val);
49 iwl_trans_write32(trans, ofs, val);
50}
51IWL_EXPORT_SYMBOL(iwl_write32);
52
53u32 iwl_read32(struct iwl_trans *trans, u32 ofs)
54{
55 u32 val = iwl_trans_read32(trans, ofs);
56 trace_iwlwifi_dev_ioread32(trans->dev, ofs, val);
57 return val;
58}
59IWL_EXPORT_SYMBOL(iwl_read32);
60
02a7fa00
JB
61#define IWL_POLL_INTERVAL 10 /* microseconds */
62
1042db2a 63int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
02a7fa00
JB
64 u32 bits, u32 mask, int timeout)
65{
66 int t = 0;
67
68 do {
1042db2a 69 if ((iwl_read32(trans, addr) & mask) == (bits & mask))
02a7fa00
JB
70 return t;
71 udelay(IWL_POLL_INTERVAL);
72 t += IWL_POLL_INTERVAL;
73 } while (t < timeout);
74
75 return -ETIMEDOUT;
76}
48e29340 77IWL_EXPORT_SYMBOL(iwl_poll_bit);
02a7fa00 78
1042db2a 79u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
02a7fa00 80{
abae2386 81 u32 value = 0x5a5a5a5a;
02a7fa00 82 unsigned long flags;
e56b04ef 83 if (iwl_trans_grab_nic_access(trans, false, &flags)) {
abae2386 84 value = iwl_read32(trans, reg);
e56b04ef 85 iwl_trans_release_nic_access(trans, &flags);
abae2386 86 }
02a7fa00
JB
87
88 return value;
89}
48e29340 90IWL_EXPORT_SYMBOL(iwl_read_direct32);
02a7fa00 91
1042db2a 92void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
02a7fa00
JB
93{
94 unsigned long flags;
95
e56b04ef 96 if (iwl_trans_grab_nic_access(trans, false, &flags)) {
1042db2a 97 iwl_write32(trans, reg, value);
e56b04ef 98 iwl_trans_release_nic_access(trans, &flags);
02a7fa00 99 }
02a7fa00 100}
48e29340 101IWL_EXPORT_SYMBOL(iwl_write_direct32);
02a7fa00 102
1042db2a 103int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
02a7fa00
JB
104 int timeout)
105{
106 int t = 0;
107
108 do {
1042db2a 109 if ((iwl_read_direct32(trans, addr) & mask) == mask)
02a7fa00
JB
110 return t;
111 udelay(IWL_POLL_INTERVAL);
112 t += IWL_POLL_INTERVAL;
113 } while (t < timeout);
114
115 return -ETIMEDOUT;
116}
48e29340 117IWL_EXPORT_SYMBOL(iwl_poll_direct_bit);
02a7fa00 118
a812cba9 119u32 __iwl_read_prph(struct iwl_trans *trans, u32 ofs)
02a7fa00 120{
6a06b6c1
EG
121 u32 val = iwl_trans_read_prph(trans, ofs);
122 trace_iwlwifi_dev_ioread_prph32(trans->dev, ofs, val);
123 return val;
02a7fa00
JB
124}
125
a812cba9 126void __iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
02a7fa00 127{
6a06b6c1
EG
128 trace_iwlwifi_dev_iowrite_prph32(trans->dev, ofs, val);
129 iwl_trans_write_prph(trans, ofs, val);
02a7fa00
JB
130}
131
6a06b6c1 132u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
02a7fa00
JB
133{
134 unsigned long flags;
abae2386 135 u32 val = 0x5a5a5a5a;
02a7fa00 136
e56b04ef 137 if (iwl_trans_grab_nic_access(trans, false, &flags)) {
abae2386 138 val = __iwl_read_prph(trans, ofs);
e56b04ef 139 iwl_trans_release_nic_access(trans, &flags);
abae2386 140 }
02a7fa00
JB
141 return val;
142}
48e29340 143IWL_EXPORT_SYMBOL(iwl_read_prph);
02a7fa00 144
6a06b6c1 145void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
02a7fa00
JB
146{
147 unsigned long flags;
148
e56b04ef 149 if (iwl_trans_grab_nic_access(trans, false, &flags)) {
6a06b6c1 150 __iwl_write_prph(trans, ofs, val);
e56b04ef 151 iwl_trans_release_nic_access(trans, &flags);
02a7fa00 152 }
02a7fa00 153}
48e29340 154IWL_EXPORT_SYMBOL(iwl_write_prph);
02a7fa00 155
189fa2fa
EH
156int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr,
157 u32 bits, u32 mask, int timeout)
158{
159 int t = 0;
160
161 do {
162 if ((iwl_read_prph(trans, addr) & mask) == (bits & mask))
163 return t;
164 udelay(IWL_POLL_INTERVAL);
165 t += IWL_POLL_INTERVAL;
166 } while (t < timeout);
167
168 return -ETIMEDOUT;
169}
170
6a06b6c1 171void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
02a7fa00
JB
172{
173 unsigned long flags;
174
e56b04ef 175 if (iwl_trans_grab_nic_access(trans, false, &flags)) {
6a06b6c1
EG
176 __iwl_write_prph(trans, ofs,
177 __iwl_read_prph(trans, ofs) | mask);
e56b04ef 178 iwl_trans_release_nic_access(trans, &flags);
bfe4b80e 179 }
02a7fa00 180}
48e29340 181IWL_EXPORT_SYMBOL(iwl_set_bits_prph);
02a7fa00 182
6a06b6c1 183void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
02a7fa00
JB
184 u32 bits, u32 mask)
185{
186 unsigned long flags;
187
e56b04ef 188 if (iwl_trans_grab_nic_access(trans, false, &flags)) {
6a06b6c1
EG
189 __iwl_write_prph(trans, ofs,
190 (__iwl_read_prph(trans, ofs) & mask) | bits);
e56b04ef 191 iwl_trans_release_nic_access(trans, &flags);
bfe4b80e 192 }
02a7fa00 193}
48e29340 194IWL_EXPORT_SYMBOL(iwl_set_bits_mask_prph);
02a7fa00 195
6a06b6c1 196void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
02a7fa00
JB
197{
198 unsigned long flags;
199 u32 val;
200
e56b04ef 201 if (iwl_trans_grab_nic_access(trans, false, &flags)) {
6a06b6c1
EG
202 val = __iwl_read_prph(trans, ofs);
203 __iwl_write_prph(trans, ofs, (val & ~mask));
e56b04ef 204 iwl_trans_release_nic_access(trans, &flags);
bfe4b80e 205 }
02a7fa00 206}
48e29340 207IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);
313b0a29 208
4c9706dc
LK
209void iwl_force_nmi(struct iwl_trans *trans)
210{
5dd9c68a 211 if (trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
66396583
EG
212 iwl_write_prph(trans, DEVICE_SET_NMI_REG,
213 DEVICE_SET_NMI_VAL_DRV);
214 iwl_write_prph(trans, DEVICE_SET_NMI_REG,
215 DEVICE_SET_NMI_VAL_HW);
216 } else {
5dd9c68a
EG
217 iwl_write_prph(trans, DEVICE_SET_NMI_8000_REG,
218 DEVICE_SET_NMI_8000_VAL);
9b666db4
EG
219 iwl_write_prph(trans, DEVICE_SET_NMI_REG,
220 DEVICE_SET_NMI_VAL_DRV);
66396583 221 }
4c9706dc
LK
222}
223IWL_EXPORT_SYMBOL(iwl_force_nmi);
224
313b0a29
IH
225static const char *get_fh_string(int cmd)
226{
227#define IWL_CMD(x) case x: return #x
228 switch (cmd) {
229 IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
230 IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
231 IWL_CMD(FH_RSCSR_CHNL0_WPTR);
232 IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
233 IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
234 IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
235 IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
236 IWL_CMD(FH_TSSR_TX_STATUS_REG);
237 IWL_CMD(FH_TSSR_TX_ERROR_REG);
238 default:
239 return "UNKNOWN";
240 }
241#undef IWL_CMD
242}
243
244int iwl_dump_fh(struct iwl_trans *trans, char **buf)
245{
246 int i;
247 static const u32 fh_tbl[] = {
248 FH_RSCSR_CHNL0_STTS_WPTR_REG,
249 FH_RSCSR_CHNL0_RBDCB_BASE_REG,
250 FH_RSCSR_CHNL0_WPTR,
251 FH_MEM_RCSR_CHNL0_CONFIG_REG,
252 FH_MEM_RSSR_SHARED_CTRL_REG,
253 FH_MEM_RSSR_RX_STATUS_REG,
254 FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
255 FH_TSSR_TX_STATUS_REG,
256 FH_TSSR_TX_ERROR_REG
257 };
258
259#ifdef CONFIG_IWLWIFI_DEBUGFS
260 if (buf) {
261 int pos = 0;
262 size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
263
264 *buf = kmalloc(bufsz, GFP_KERNEL);
265 if (!*buf)
266 return -ENOMEM;
267
268 pos += scnprintf(*buf + pos, bufsz - pos,
269 "FH register values:\n");
270
271 for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
272 pos += scnprintf(*buf + pos, bufsz - pos,
273 " %34s: 0X%08x\n",
274 get_fh_string(fh_tbl[i]),
275 iwl_read_direct32(trans, fh_tbl[i]));
276
277 return pos;
278 }
279#endif
280
281 IWL_ERR(trans, "FH register values:\n");
282 for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
283 IWL_ERR(trans, " %34s: 0X%08x\n",
284 get_fh_string(fh_tbl[i]),
285 iwl_read_direct32(trans, fh_tbl[i]));
286
287 return 0;
288}