Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux...
[deliverable/linux.git] / drivers / net / wireless / iwlwifi / iwl-io.c
CommitLineData
02a7fa00
JB
1/******************************************************************************
2 *
4e318262 3 * Copyright(c) 2003 - 2012 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
JB
31
32#include "iwl-io.h"
6ac7d115 33#include "iwl-csr.h"
83ed9015 34#include "iwl-debug.h"
02a7fa00
JB
35
36#define IWL_POLL_INTERVAL 10 /* microseconds */
37
1042db2a 38static inline void __iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask)
02a7fa00 39{
1042db2a 40 iwl_write32(trans, reg, iwl_read32(trans, reg) | mask);
02a7fa00
JB
41}
42
1042db2a 43static inline void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
02a7fa00 44{
1042db2a 45 iwl_write32(trans, reg, iwl_read32(trans, reg) & ~mask);
02a7fa00
JB
46}
47
1042db2a 48void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask)
02a7fa00
JB
49{
50 unsigned long flags;
51
1042db2a
EG
52 spin_lock_irqsave(&trans->reg_lock, flags);
53 __iwl_set_bit(trans, reg, mask);
54 spin_unlock_irqrestore(&trans->reg_lock, flags);
02a7fa00 55}
cc5f7e39 56EXPORT_SYMBOL_GPL(iwl_set_bit);
02a7fa00 57
1042db2a 58void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
02a7fa00
JB
59{
60 unsigned long flags;
61
1042db2a
EG
62 spin_lock_irqsave(&trans->reg_lock, flags);
63 __iwl_clear_bit(trans, reg, mask);
64 spin_unlock_irqrestore(&trans->reg_lock, flags);
02a7fa00 65}
cc5f7e39 66EXPORT_SYMBOL_GPL(iwl_clear_bit);
02a7fa00 67
2baa2e57
JB
68void iwl_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value)
69{
70 unsigned long flags;
71 u32 v;
72
73#ifdef CONFIG_IWLWIFI_DEBUG
74 WARN_ON_ONCE(value & ~mask);
75#endif
76
77 spin_lock_irqsave(&trans->reg_lock, flags);
78 v = iwl_read32(trans, reg);
79 v &= ~mask;
80 v |= value;
81 iwl_write32(trans, reg, v);
82 spin_unlock_irqrestore(&trans->reg_lock, flags);
83}
84EXPORT_SYMBOL_GPL(iwl_set_bits_mask);
85
1042db2a 86int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
02a7fa00
JB
87 u32 bits, u32 mask, int timeout)
88{
89 int t = 0;
90
91 do {
1042db2a 92 if ((iwl_read32(trans, addr) & mask) == (bits & mask))
02a7fa00
JB
93 return t;
94 udelay(IWL_POLL_INTERVAL);
95 t += IWL_POLL_INTERVAL;
96 } while (t < timeout);
97
98 return -ETIMEDOUT;
99}
cc5f7e39 100EXPORT_SYMBOL_GPL(iwl_poll_bit);
02a7fa00 101
1042db2a 102int iwl_grab_nic_access_silent(struct iwl_trans *trans)
02a7fa00
JB
103{
104 int ret;
02a7fa00 105
1042db2a 106 lockdep_assert_held(&trans->reg_lock);
02a7fa00
JB
107
108 /* this bit wakes up the NIC */
1042db2a
EG
109 __iwl_set_bit(trans, CSR_GP_CNTRL,
110 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
02a7fa00
JB
111
112 /*
113 * These bits say the device is running, and should keep running for
114 * at least a short while (at least as long as MAC_ACCESS_REQ stays 1),
115 * but they do not indicate that embedded SRAM is restored yet;
116 * 3945 and 4965 have volatile SRAM, and must save/restore contents
117 * to/from host DRAM when sleeping/waking for power-saving.
118 * Each direction takes approximately 1/4 millisecond; with this
119 * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a
120 * series of register accesses are expected (e.g. reading Event Log),
121 * to keep device from sleeping.
122 *
123 * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that
124 * SRAM is okay/restored. We don't check that here because this call
125 * is just for hardware register access; but GP1 MAC_SLEEP check is a
126 * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log).
127 *
128 * 5000 series and later (including 1000 series) have non-volatile SRAM,
129 * and do not save/restore SRAM when power cycling.
130 */
1042db2a 131 ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
02a7fa00
JB
132 CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
133 (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
134 CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000);
135 if (ret < 0) {
1042db2a 136 iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI);
02a7fa00
JB
137 return -EIO;
138 }
139
140 return 0;
141}
cc5f7e39 142EXPORT_SYMBOL_GPL(iwl_grab_nic_access_silent);
02a7fa00 143
bfe4b80e 144bool iwl_grab_nic_access(struct iwl_trans *trans)
4119904f 145{
1042db2a 146 int ret = iwl_grab_nic_access_silent(trans);
aa5affba 147 if (unlikely(ret)) {
1042db2a 148 u32 val = iwl_read32(trans, CSR_GP_CNTRL);
aa5affba
SG
149 WARN_ONCE(1, "Timeout waiting for hardware access "
150 "(CSR_GP_CNTRL 0x%08x)\n", val);
bfe4b80e 151 return false;
4119904f
JB
152 }
153
bfe4b80e 154 return true;
4119904f 155}
cc5f7e39 156EXPORT_SYMBOL_GPL(iwl_grab_nic_access);
4119904f 157
1042db2a 158void iwl_release_nic_access(struct iwl_trans *trans)
02a7fa00 159{
1042db2a
EG
160 lockdep_assert_held(&trans->reg_lock);
161 __iwl_clear_bit(trans, CSR_GP_CNTRL,
02a7fa00 162 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
3a73a300
SG
163 /*
164 * Above we read the CSR_GP_CNTRL register, which will flush
165 * any previous writes, but we need the write that clears the
166 * MAC_ACCESS_REQ bit to be performed before any other writes
167 * scheduled on different CPUs (after we drop reg_lock).
168 */
169 mmiowb();
02a7fa00 170}
cc5f7e39 171EXPORT_SYMBOL_GPL(iwl_release_nic_access);
02a7fa00 172
1042db2a 173u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
02a7fa00
JB
174{
175 u32 value;
176 unsigned long flags;
177
1042db2a
EG
178 spin_lock_irqsave(&trans->reg_lock, flags);
179 iwl_grab_nic_access(trans);
180 value = iwl_read32(trans, reg);
181 iwl_release_nic_access(trans);
182 spin_unlock_irqrestore(&trans->reg_lock, flags);
02a7fa00
JB
183
184 return value;
185}
cc5f7e39 186EXPORT_SYMBOL_GPL(iwl_read_direct32);
02a7fa00 187
1042db2a 188void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
02a7fa00
JB
189{
190 unsigned long flags;
191
1042db2a 192 spin_lock_irqsave(&trans->reg_lock, flags);
bfe4b80e 193 if (likely(iwl_grab_nic_access(trans))) {
1042db2a
EG
194 iwl_write32(trans, reg, value);
195 iwl_release_nic_access(trans);
02a7fa00 196 }
1042db2a 197 spin_unlock_irqrestore(&trans->reg_lock, flags);
02a7fa00 198}
cc5f7e39 199EXPORT_SYMBOL_GPL(iwl_write_direct32);
02a7fa00 200
1042db2a 201int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
02a7fa00
JB
202 int timeout)
203{
204 int t = 0;
205
206 do {
1042db2a 207 if ((iwl_read_direct32(trans, addr) & mask) == mask)
02a7fa00
JB
208 return t;
209 udelay(IWL_POLL_INTERVAL);
210 t += IWL_POLL_INTERVAL;
211 } while (t < timeout);
212
213 return -ETIMEDOUT;
214}
cc5f7e39 215EXPORT_SYMBOL_GPL(iwl_poll_direct_bit);
02a7fa00 216
1042db2a 217static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 reg)
02a7fa00 218{
1042db2a 219 iwl_write32(trans, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
1042db2a 220 return iwl_read32(trans, HBUS_TARG_PRPH_RDAT);
02a7fa00
JB
221}
222
1042db2a 223static inline void __iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val)
02a7fa00 224{
1042db2a 225 iwl_write32(trans, HBUS_TARG_PRPH_WADDR,
02a7fa00 226 ((addr & 0x0000FFFF) | (3 << 24)));
1042db2a 227 iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val);
02a7fa00
JB
228}
229
1042db2a 230u32 iwl_read_prph(struct iwl_trans *trans, u32 reg)
02a7fa00
JB
231{
232 unsigned long flags;
233 u32 val;
234
1042db2a
EG
235 spin_lock_irqsave(&trans->reg_lock, flags);
236 iwl_grab_nic_access(trans);
237 val = __iwl_read_prph(trans, reg);
238 iwl_release_nic_access(trans);
239 spin_unlock_irqrestore(&trans->reg_lock, flags);
02a7fa00
JB
240 return val;
241}
cc5f7e39 242EXPORT_SYMBOL_GPL(iwl_read_prph);
02a7fa00 243
1042db2a 244void iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val)
02a7fa00
JB
245{
246 unsigned long flags;
247
1042db2a 248 spin_lock_irqsave(&trans->reg_lock, flags);
bfe4b80e 249 if (likely(iwl_grab_nic_access(trans))) {
1042db2a
EG
250 __iwl_write_prph(trans, addr, val);
251 iwl_release_nic_access(trans);
02a7fa00 252 }
1042db2a 253 spin_unlock_irqrestore(&trans->reg_lock, flags);
02a7fa00 254}
cc5f7e39 255EXPORT_SYMBOL_GPL(iwl_write_prph);
02a7fa00 256
1042db2a 257void iwl_set_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask)
02a7fa00
JB
258{
259 unsigned long flags;
260
1042db2a 261 spin_lock_irqsave(&trans->reg_lock, flags);
bfe4b80e
SG
262 if (likely(iwl_grab_nic_access(trans))) {
263 __iwl_write_prph(trans, reg,
264 __iwl_read_prph(trans, reg) | mask);
265 iwl_release_nic_access(trans);
266 }
1042db2a 267 spin_unlock_irqrestore(&trans->reg_lock, flags);
02a7fa00 268}
cc5f7e39 269EXPORT_SYMBOL_GPL(iwl_set_bits_prph);
02a7fa00 270
1042db2a 271void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 reg,
02a7fa00
JB
272 u32 bits, u32 mask)
273{
274 unsigned long flags;
275
1042db2a 276 spin_lock_irqsave(&trans->reg_lock, flags);
bfe4b80e
SG
277 if (likely(iwl_grab_nic_access(trans))) {
278 __iwl_write_prph(trans, reg,
279 (__iwl_read_prph(trans, reg) & mask) | bits);
280 iwl_release_nic_access(trans);
281 }
1042db2a 282 spin_unlock_irqrestore(&trans->reg_lock, flags);
02a7fa00 283}
cc5f7e39 284EXPORT_SYMBOL_GPL(iwl_set_bits_mask_prph);
02a7fa00 285
1042db2a 286void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask)
02a7fa00
JB
287{
288 unsigned long flags;
289 u32 val;
290
1042db2a 291 spin_lock_irqsave(&trans->reg_lock, flags);
bfe4b80e
SG
292 if (likely(iwl_grab_nic_access(trans))) {
293 val = __iwl_read_prph(trans, reg);
294 __iwl_write_prph(trans, reg, (val & ~mask));
295 iwl_release_nic_access(trans);
296 }
1042db2a 297 spin_unlock_irqrestore(&trans->reg_lock, flags);
02a7fa00 298}
cc5f7e39 299EXPORT_SYMBOL_GPL(iwl_clear_bits_prph);
02a7fa00 300
e4b1681e
EG
301void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
302 void *buf, int dwords)
02a7fa00
JB
303{
304 unsigned long flags;
e46f6538
JB
305 int offs;
306 u32 *vals = buf;
02a7fa00 307
1042db2a 308 spin_lock_irqsave(&trans->reg_lock, flags);
bfe4b80e
SG
309 if (likely(iwl_grab_nic_access(trans))) {
310 iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr);
e4b1681e 311 for (offs = 0; offs < dwords; offs++)
bfe4b80e
SG
312 vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
313 iwl_release_nic_access(trans);
314 }
1042db2a 315 spin_unlock_irqrestore(&trans->reg_lock, flags);
e46f6538 316}
e4b1681e 317EXPORT_SYMBOL_GPL(_iwl_read_targ_mem_dwords);
e46f6538 318
1042db2a 319u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr)
e46f6538
JB
320{
321 u32 value;
322
e4b1681e 323 _iwl_read_targ_mem_dwords(trans, addr, &value, 1);
e46f6538 324
02a7fa00
JB
325 return value;
326}
cc5f7e39 327EXPORT_SYMBOL_GPL(iwl_read_targ_mem);
02a7fa00 328
e4b1681e
EG
329int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
330 void *buf, int dwords)
02a7fa00
JB
331{
332 unsigned long flags;
ee8ba880
HK
333 int offs, result = 0;
334 u32 *vals = buf;
02a7fa00 335
1042db2a 336 spin_lock_irqsave(&trans->reg_lock, flags);
bfe4b80e 337 if (likely(iwl_grab_nic_access(trans))) {
1042db2a 338 iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr);
e4b1681e 339 for (offs = 0; offs < dwords; offs++)
1042db2a
EG
340 iwl_write32(trans, HBUS_TARG_MEM_WDAT, vals[offs]);
341 iwl_release_nic_access(trans);
ee8ba880
HK
342 } else
343 result = -EBUSY;
1042db2a 344 spin_unlock_irqrestore(&trans->reg_lock, flags);
ee8ba880
HK
345
346 return result;
347}
e4b1681e 348EXPORT_SYMBOL_GPL(_iwl_write_targ_mem_dwords);
ee8ba880 349
1042db2a 350int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val)
ee8ba880 351{
e4b1681e 352 return _iwl_write_targ_mem_dwords(trans, addr, &val, 1);
02a7fa00 353}
cc5f7e39 354EXPORT_SYMBOL_GPL(iwl_write_targ_mem);
This page took 0.193468 seconds and 5 git commands to generate.