]>
Commit | Line | Data |
---|---|---|
b481de9c ZY |
1 | /****************************************************************************** |
2 | * | |
01f8162a | 3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. |
b481de9c ZY |
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: | |
759ef89f | 24 | * Intel Linux Wireless <ilw@linux.intel.com> |
b481de9c ZY |
25 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
26 | * | |
27 | *****************************************************************************/ | |
28 | ||
3395f6e9 TW |
29 | #ifndef __iwl_io_h__ |
30 | #define __iwl_io_h__ | |
b481de9c ZY |
31 | |
32 | #include <linux/io.h> | |
33 | ||
0a6857e7 | 34 | #include "iwl-debug.h" |
be1a71a1 | 35 | #include "iwl-devtrace.h" |
b481de9c ZY |
36 | |
37 | /* | |
38 | * IO, register, and NIC memory access functions | |
39 | * | |
40 | * NOTE on naming convention and macro usage for these | |
41 | * | |
42 | * A single _ prefix before a an access function means that no state | |
43 | * check or debug information is printed when that function is called. | |
44 | * | |
45 | * A double __ prefix before an access function means that state is checked | |
775ea378 TW |
46 | * and the current line number and caller function name are printed in addition |
47 | * to any other debug output. | |
b481de9c ZY |
48 | * |
49 | * The non-prefixed name is the #define that maps the caller into a | |
775ea378 TW |
50 | * #define that provides the caller's name and __LINE__ to the double |
51 | * prefix version. | |
b481de9c ZY |
52 | * |
53 | * If you wish to call the function without any debug or state checking, | |
54 | * you should use the single _ prefix version (as is used by dependent IO | |
3395f6e9 TW |
55 | * routines, for example _iwl_read_direct32 calls the non-check version of |
56 | * _iwl_read32.) | |
b481de9c ZY |
57 | * |
58 | * These declarations are *extremely* useful in quickly isolating code deltas | |
a96a27f9 | 59 | * which result in misconfiguration of the hardware I/O. In combination with |
b481de9c ZY |
60 | * git-bisect and the IO debug level you can quickly determine the specific |
61 | * commit which breaks the IO sequence to the hardware. | |
62 | * | |
63 | */ | |
64 | ||
be1a71a1 JB |
65 | static inline void _iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) |
66 | { | |
67 | trace_iwlwifi_dev_iowrite32(priv, ofs, val); | |
68 | iowrite32(val, priv->hw_base + ofs); | |
69 | } | |
70 | ||
0a6857e7 | 71 | #ifdef CONFIG_IWLWIFI_DEBUG |
3395f6e9 | 72 | static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv, |
b481de9c ZY |
73 | u32 ofs, u32 val) |
74 | { | |
e1623446 | 75 | IWL_DEBUG_IO(priv, "write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l); |
3395f6e9 | 76 | _iwl_write32(priv, ofs, val); |
b481de9c | 77 | } |
3395f6e9 TW |
78 | #define iwl_write32(priv, ofs, val) \ |
79 | __iwl_write32(__FILE__, __LINE__, priv, ofs, val) | |
b481de9c | 80 | #else |
3395f6e9 | 81 | #define iwl_write32(priv, ofs, val) _iwl_write32(priv, ofs, val) |
b481de9c ZY |
82 | #endif |
83 | ||
be1a71a1 JB |
84 | static inline u32 _iwl_read32(struct iwl_priv *priv, u32 ofs) |
85 | { | |
86 | u32 val = ioread32(priv->hw_base + ofs); | |
87 | trace_iwlwifi_dev_ioread32(priv, ofs, val); | |
88 | return val; | |
89 | } | |
90 | ||
0a6857e7 | 91 | #ifdef CONFIG_IWLWIFI_DEBUG |
3395f6e9 | 92 | static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs) |
b481de9c | 93 | { |
e1623446 | 94 | IWL_DEBUG_IO(priv, "read_direct32(0x%08X) - %s %d\n", ofs, f, l); |
3395f6e9 | 95 | return _iwl_read32(priv, ofs); |
b481de9c | 96 | } |
3395f6e9 | 97 | #define iwl_read32(priv, ofs) __iwl_read32(__FILE__, __LINE__, priv, ofs) |
b481de9c | 98 | #else |
3395f6e9 | 99 | #define iwl_read32(p, o) _iwl_read32(p, o) |
b481de9c ZY |
100 | #endif |
101 | ||
4087f6f6 | 102 | #define IWL_POLL_INTERVAL 10 /* microseconds */ |
3395f6e9 | 103 | static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr, |
b481de9c ZY |
104 | u32 bits, u32 mask, int timeout) |
105 | { | |
4087f6f6 | 106 | int t = 0; |
b481de9c ZY |
107 | |
108 | do { | |
3395f6e9 | 109 | if ((_iwl_read32(priv, addr) & mask) == (bits & mask)) |
4087f6f6 WF |
110 | return t; |
111 | udelay(IWL_POLL_INTERVAL); | |
112 | t += IWL_POLL_INTERVAL; | |
113 | } while (t < timeout); | |
b481de9c ZY |
114 | |
115 | return -ETIMEDOUT; | |
116 | } | |
0a6857e7 | 117 | #ifdef CONFIG_IWLWIFI_DEBUG |
3395f6e9 | 118 | static inline int __iwl_poll_bit(const char *f, u32 l, |
c79dd5b5 | 119 | struct iwl_priv *priv, u32 addr, |
b481de9c ZY |
120 | u32 bits, u32 mask, int timeout) |
121 | { | |
3395f6e9 | 122 | int ret = _iwl_poll_bit(priv, addr, bits, mask, timeout); |
e1623446 | 123 | IWL_DEBUG_IO(priv, "poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n", |
5c1b0958 | 124 | addr, bits, mask, |
c3056065 | 125 | unlikely(ret == -ETIMEDOUT) ? "timeout" : "", f, l); |
ac17a947 | 126 | return ret; |
b481de9c | 127 | } |
3395f6e9 TW |
128 | #define iwl_poll_bit(priv, addr, bits, mask, timeout) \ |
129 | __iwl_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout) | |
b481de9c | 130 | #else |
3395f6e9 | 131 | #define iwl_poll_bit(p, a, b, m, t) _iwl_poll_bit(p, a, b, m, t) |
b481de9c ZY |
132 | #endif |
133 | ||
3395f6e9 | 134 | static inline void _iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) |
b481de9c | 135 | { |
3395f6e9 | 136 | _iwl_write32(priv, reg, _iwl_read32(priv, reg) | mask); |
b481de9c | 137 | } |
0a6857e7 | 138 | #ifdef CONFIG_IWLWIFI_DEBUG |
3395f6e9 | 139 | static inline void __iwl_set_bit(const char *f, u32 l, |
c79dd5b5 | 140 | struct iwl_priv *priv, u32 reg, u32 mask) |
b481de9c | 141 | { |
3395f6e9 | 142 | u32 val = _iwl_read32(priv, reg) | mask; |
e1623446 | 143 | IWL_DEBUG_IO(priv, "set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); |
3395f6e9 | 144 | _iwl_write32(priv, reg, val); |
b481de9c | 145 | } |
a8b50a0a MA |
146 | static inline void iwl_set_bit(struct iwl_priv *p, u32 r, u32 m) |
147 | { | |
148 | unsigned long reg_flags; | |
149 | ||
150 | spin_lock_irqsave(&p->reg_lock, reg_flags); | |
151 | __iwl_set_bit(__FILE__, __LINE__, p, r, m); | |
152 | spin_unlock_irqrestore(&p->reg_lock, reg_flags); | |
153 | } | |
b481de9c | 154 | #else |
a8b50a0a MA |
155 | static inline void iwl_set_bit(struct iwl_priv *p, u32 r, u32 m) |
156 | { | |
157 | unsigned long reg_flags; | |
158 | ||
159 | spin_lock_irqsave(&p->reg_lock, reg_flags); | |
160 | _iwl_set_bit(p, r, m); | |
161 | spin_unlock_irqrestore(&p->reg_lock, reg_flags); | |
162 | } | |
b481de9c ZY |
163 | #endif |
164 | ||
3395f6e9 | 165 | static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) |
b481de9c | 166 | { |
3395f6e9 | 167 | _iwl_write32(priv, reg, _iwl_read32(priv, reg) & ~mask); |
b481de9c | 168 | } |
0a6857e7 | 169 | #ifdef CONFIG_IWLWIFI_DEBUG |
3395f6e9 | 170 | static inline void __iwl_clear_bit(const char *f, u32 l, |
c79dd5b5 | 171 | struct iwl_priv *priv, u32 reg, u32 mask) |
b481de9c | 172 | { |
3395f6e9 | 173 | u32 val = _iwl_read32(priv, reg) & ~mask; |
e1623446 | 174 | IWL_DEBUG_IO(priv, "clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); |
3395f6e9 | 175 | _iwl_write32(priv, reg, val); |
b481de9c | 176 | } |
a8b50a0a MA |
177 | static inline void iwl_clear_bit(struct iwl_priv *p, u32 r, u32 m) |
178 | { | |
179 | unsigned long reg_flags; | |
180 | ||
181 | spin_lock_irqsave(&p->reg_lock, reg_flags); | |
182 | __iwl_clear_bit(__FILE__, __LINE__, p, r, m); | |
183 | spin_unlock_irqrestore(&p->reg_lock, reg_flags); | |
184 | } | |
b481de9c | 185 | #else |
a8b50a0a MA |
186 | static inline void iwl_clear_bit(struct iwl_priv *p, u32 r, u32 m) |
187 | { | |
188 | unsigned long reg_flags; | |
189 | ||
190 | spin_lock_irqsave(&p->reg_lock, reg_flags); | |
191 | _iwl_clear_bit(p, r, m); | |
192 | spin_unlock_irqrestore(&p->reg_lock, reg_flags); | |
193 | } | |
b481de9c ZY |
194 | #endif |
195 | ||
3395f6e9 | 196 | static inline int _iwl_grab_nic_access(struct iwl_priv *priv) |
b481de9c | 197 | { |
ac17a947 | 198 | int ret; |
18d426c4 | 199 | u32 val; |
a8b50a0a | 200 | |
b481de9c | 201 | /* this bit wakes up the NIC */ |
3395f6e9 | 202 | _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
a7e66110 BC |
203 | |
204 | /* | |
205 | * These bits say the device is running, and should keep running for | |
206 | * at least a short while (at least as long as MAC_ACCESS_REQ stays 1), | |
207 | * but they do not indicate that embedded SRAM is restored yet; | |
208 | * 3945 and 4965 have volatile SRAM, and must save/restore contents | |
209 | * to/from host DRAM when sleeping/waking for power-saving. | |
210 | * Each direction takes approximately 1/4 millisecond; with this | |
211 | * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a | |
212 | * series of register accesses are expected (e.g. reading Event Log), | |
213 | * to keep device from sleeping. | |
214 | * | |
215 | * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that | |
216 | * SRAM is okay/restored. We don't check that here because this call | |
217 | * is just for hardware register access; but GP1 MAC_SLEEP check is a | |
218 | * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log). | |
219 | * | |
220 | * 5000 series and later (including 1000 series) have non-volatile SRAM, | |
221 | * and do not save/restore SRAM when power cycling. | |
222 | */ | |
3395f6e9 | 223 | ret = _iwl_poll_bit(priv, CSR_GP_CNTRL, |
b481de9c ZY |
224 | CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, |
225 | (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | | |
e9414b6b | 226 | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); |
ac17a947 | 227 | if (ret < 0) { |
18d426c4 RC |
228 | val = _iwl_read32(priv, CSR_GP_CNTRL); |
229 | IWL_ERR(priv, "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); | |
a8b50a0a | 230 | _iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); |
b481de9c ZY |
231 | return -EIO; |
232 | } | |
233 | ||
b481de9c ZY |
234 | return 0; |
235 | } | |
236 | ||
0a6857e7 | 237 | #ifdef CONFIG_IWLWIFI_DEBUG |
3395f6e9 | 238 | static inline int __iwl_grab_nic_access(const char *f, u32 l, |
c79dd5b5 | 239 | struct iwl_priv *priv) |
b481de9c | 240 | { |
e1623446 | 241 | IWL_DEBUG_IO(priv, "grabbing nic access - %s %d\n", f, l); |
3395f6e9 | 242 | return _iwl_grab_nic_access(priv); |
b481de9c | 243 | } |
3395f6e9 TW |
244 | #define iwl_grab_nic_access(priv) \ |
245 | __iwl_grab_nic_access(__FILE__, __LINE__, priv) | |
b481de9c | 246 | #else |
3395f6e9 TW |
247 | #define iwl_grab_nic_access(priv) \ |
248 | _iwl_grab_nic_access(priv) | |
b481de9c ZY |
249 | #endif |
250 | ||
3395f6e9 | 251 | static inline void _iwl_release_nic_access(struct iwl_priv *priv) |
b481de9c | 252 | { |
a8b50a0a MA |
253 | _iwl_clear_bit(priv, CSR_GP_CNTRL, |
254 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | |
b481de9c | 255 | } |
0a6857e7 | 256 | #ifdef CONFIG_IWLWIFI_DEBUG |
3395f6e9 | 257 | static inline void __iwl_release_nic_access(const char *f, u32 l, |
c79dd5b5 | 258 | struct iwl_priv *priv) |
b481de9c | 259 | { |
b481de9c | 260 | |
e1623446 | 261 | IWL_DEBUG_IO(priv, "releasing nic access - %s %d\n", f, l); |
3395f6e9 | 262 | _iwl_release_nic_access(priv); |
b481de9c | 263 | } |
3395f6e9 TW |
264 | #define iwl_release_nic_access(priv) \ |
265 | __iwl_release_nic_access(__FILE__, __LINE__, priv) | |
b481de9c | 266 | #else |
3395f6e9 TW |
267 | #define iwl_release_nic_access(priv) \ |
268 | _iwl_release_nic_access(priv) | |
b481de9c ZY |
269 | #endif |
270 | ||
3395f6e9 | 271 | static inline u32 _iwl_read_direct32(struct iwl_priv *priv, u32 reg) |
b481de9c | 272 | { |
3395f6e9 | 273 | return _iwl_read32(priv, reg); |
b481de9c | 274 | } |
0a6857e7 | 275 | #ifdef CONFIG_IWLWIFI_DEBUG |
3395f6e9 | 276 | static inline u32 __iwl_read_direct32(const char *f, u32 l, |
c79dd5b5 | 277 | struct iwl_priv *priv, u32 reg) |
b481de9c | 278 | { |
3395f6e9 | 279 | u32 value = _iwl_read_direct32(priv, reg); |
e1623446 | 280 | IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value, |
b481de9c ZY |
281 | f, l); |
282 | return value; | |
283 | } | |
a8b50a0a MA |
284 | static inline u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) |
285 | { | |
286 | u32 value; | |
287 | unsigned long reg_flags; | |
288 | ||
289 | spin_lock_irqsave(&priv->reg_lock, reg_flags); | |
290 | iwl_grab_nic_access(priv); | |
291 | value = __iwl_read_direct32(__FILE__, __LINE__, priv, reg); | |
292 | iwl_release_nic_access(priv); | |
293 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | |
294 | return value; | |
295 | } | |
296 | ||
b481de9c | 297 | #else |
a8b50a0a MA |
298 | static inline u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) |
299 | { | |
300 | u32 value; | |
301 | unsigned long reg_flags; | |
302 | ||
303 | spin_lock_irqsave(&priv->reg_lock, reg_flags); | |
304 | iwl_grab_nic_access(priv); | |
305 | value = _iwl_read_direct32(priv, reg); | |
306 | iwl_release_nic_access(priv); | |
307 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | |
308 | return value; | |
309 | ||
310 | } | |
b481de9c ZY |
311 | #endif |
312 | ||
3395f6e9 | 313 | static inline void _iwl_write_direct32(struct iwl_priv *priv, |
b481de9c ZY |
314 | u32 reg, u32 value) |
315 | { | |
3395f6e9 | 316 | _iwl_write32(priv, reg, value); |
b481de9c | 317 | } |
a8b50a0a | 318 | static inline void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value) |
b481de9c | 319 | { |
a8b50a0a MA |
320 | unsigned long reg_flags; |
321 | ||
322 | spin_lock_irqsave(&priv->reg_lock, reg_flags); | |
323 | if (!iwl_grab_nic_access(priv)) { | |
324 | _iwl_write_direct32(priv, reg, value); | |
325 | iwl_release_nic_access(priv); | |
326 | } | |
327 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | |
b481de9c | 328 | } |
b481de9c | 329 | |
3395f6e9 | 330 | static inline void iwl_write_reg_buf(struct iwl_priv *priv, |
b481de9c ZY |
331 | u32 reg, u32 len, u32 *values) |
332 | { | |
333 | u32 count = sizeof(u32); | |
334 | ||
335 | if ((priv != NULL) && (values != NULL)) { | |
336 | for (; 0 < len; len -= count, reg += count, values++) | |
a8b50a0a | 337 | iwl_write_direct32(priv, reg, *values); |
b481de9c ZY |
338 | } |
339 | } | |
340 | ||
73d7b5ac ZY |
341 | static inline int _iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, |
342 | u32 mask, int timeout) | |
b481de9c | 343 | { |
a8b50a0a MA |
344 | int t = 0; |
345 | ||
346 | do { | |
347 | if ((iwl_read_direct32(priv, addr) & mask) == mask) | |
348 | return t; | |
349 | udelay(IWL_POLL_INTERVAL); | |
350 | t += IWL_POLL_INTERVAL; | |
351 | } while (t < timeout); | |
352 | ||
353 | return -ETIMEDOUT; | |
b481de9c ZY |
354 | } |
355 | ||
0a6857e7 | 356 | #ifdef CONFIG_IWLWIFI_DEBUG |
3395f6e9 | 357 | static inline int __iwl_poll_direct_bit(const char *f, u32 l, |
c79dd5b5 | 358 | struct iwl_priv *priv, |
b481de9c ZY |
359 | u32 addr, u32 mask, int timeout) |
360 | { | |
3395f6e9 | 361 | int ret = _iwl_poll_direct_bit(priv, addr, mask, timeout); |
b481de9c | 362 | |
ac17a947 | 363 | if (unlikely(ret == -ETIMEDOUT)) |
e1623446 | 364 | IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) - " |
b481de9c ZY |
365 | "timedout - %s %d\n", addr, mask, f, l); |
366 | else | |
e1623446 | 367 | IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) = 0x%08X " |
ac17a947 TW |
368 | "- %s %d\n", addr, mask, ret, f, l); |
369 | return ret; | |
b481de9c | 370 | } |
3395f6e9 TW |
371 | #define iwl_poll_direct_bit(priv, addr, mask, timeout) \ |
372 | __iwl_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout) | |
b481de9c | 373 | #else |
3395f6e9 | 374 | #define iwl_poll_direct_bit _iwl_poll_direct_bit |
b481de9c ZY |
375 | #endif |
376 | ||
3395f6e9 | 377 | static inline u32 _iwl_read_prph(struct iwl_priv *priv, u32 reg) |
b481de9c | 378 | { |
3395f6e9 | 379 | _iwl_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); |
a8ec42c1 | 380 | rmb(); |
3395f6e9 | 381 | return _iwl_read_direct32(priv, HBUS_TARG_PRPH_RDAT); |
b481de9c | 382 | } |
a8b50a0a | 383 | static inline u32 iwl_read_prph(struct iwl_priv *priv, u32 reg) |
b481de9c | 384 | { |
a8b50a0a MA |
385 | unsigned long reg_flags; |
386 | u32 val; | |
b481de9c | 387 | |
a8b50a0a MA |
388 | spin_lock_irqsave(&priv->reg_lock, reg_flags); |
389 | iwl_grab_nic_access(priv); | |
390 | val = _iwl_read_prph(priv, reg); | |
391 | iwl_release_nic_access(priv); | |
392 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | |
393 | return val; | |
394 | } | |
b481de9c | 395 | |
3395f6e9 | 396 | static inline void _iwl_write_prph(struct iwl_priv *priv, |
b481de9c ZY |
397 | u32 addr, u32 val) |
398 | { | |
3395f6e9 | 399 | _iwl_write_direct32(priv, HBUS_TARG_PRPH_WADDR, |
b481de9c | 400 | ((addr & 0x0000FFFF) | (3 << 24))); |
a8ec42c1 | 401 | wmb(); |
3395f6e9 | 402 | _iwl_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val); |
b481de9c | 403 | } |
a8b50a0a MA |
404 | |
405 | static inline void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) | |
b481de9c | 406 | { |
a8b50a0a | 407 | unsigned long reg_flags; |
b481de9c | 408 | |
a8b50a0a MA |
409 | spin_lock_irqsave(&priv->reg_lock, reg_flags); |
410 | if (!iwl_grab_nic_access(priv)) { | |
411 | _iwl_write_prph(priv, addr, val); | |
412 | iwl_release_nic_access(priv); | |
413 | } | |
414 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | |
415 | } | |
b481de9c | 416 | |
3395f6e9 TW |
417 | #define _iwl_set_bits_prph(priv, reg, mask) \ |
418 | _iwl_write_prph(priv, reg, (_iwl_read_prph(priv, reg) | mask)) | |
a8b50a0a MA |
419 | |
420 | static inline void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) | |
b481de9c | 421 | { |
a8b50a0a | 422 | unsigned long reg_flags; |
ac17a947 | 423 | |
a8b50a0a MA |
424 | spin_lock_irqsave(&priv->reg_lock, reg_flags); |
425 | iwl_grab_nic_access(priv); | |
3395f6e9 | 426 | _iwl_set_bits_prph(priv, reg, mask); |
a8b50a0a MA |
427 | iwl_release_nic_access(priv); |
428 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | |
b481de9c | 429 | } |
b481de9c | 430 | |
3395f6e9 TW |
431 | #define _iwl_set_bits_mask_prph(priv, reg, bits, mask) \ |
432 | _iwl_write_prph(priv, reg, ((_iwl_read_prph(priv, reg) & mask) | bits)) | |
d8609652 | 433 | |
a8b50a0a MA |
434 | static inline void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, |
435 | u32 bits, u32 mask) | |
b481de9c | 436 | { |
a8b50a0a MA |
437 | unsigned long reg_flags; |
438 | ||
439 | spin_lock_irqsave(&priv->reg_lock, reg_flags); | |
440 | iwl_grab_nic_access(priv); | |
3395f6e9 | 441 | _iwl_set_bits_mask_prph(priv, reg, bits, mask); |
a8b50a0a MA |
442 | iwl_release_nic_access(priv); |
443 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | |
b481de9c | 444 | } |
b481de9c | 445 | |
3395f6e9 | 446 | static inline void iwl_clear_bits_prph(struct iwl_priv |
b481de9c ZY |
447 | *priv, u32 reg, u32 mask) |
448 | { | |
a8b50a0a MA |
449 | unsigned long reg_flags; |
450 | u32 val; | |
451 | ||
452 | spin_lock_irqsave(&priv->reg_lock, reg_flags); | |
453 | iwl_grab_nic_access(priv); | |
454 | val = _iwl_read_prph(priv, reg); | |
3395f6e9 | 455 | _iwl_write_prph(priv, reg, (val & ~mask)); |
a8b50a0a MA |
456 | iwl_release_nic_access(priv); |
457 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | |
b481de9c ZY |
458 | } |
459 | ||
3395f6e9 | 460 | static inline u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) |
b481de9c | 461 | { |
a8b50a0a MA |
462 | unsigned long reg_flags; |
463 | u32 value; | |
464 | ||
465 | spin_lock_irqsave(&priv->reg_lock, reg_flags); | |
466 | iwl_grab_nic_access(priv); | |
467 | ||
468 | _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr); | |
a8ec42c1 | 469 | rmb(); |
a8b50a0a MA |
470 | value = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
471 | ||
472 | iwl_release_nic_access(priv); | |
473 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | |
474 | return value; | |
b481de9c ZY |
475 | } |
476 | ||
3395f6e9 | 477 | static inline void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) |
b481de9c | 478 | { |
a8b50a0a MA |
479 | unsigned long reg_flags; |
480 | ||
481 | spin_lock_irqsave(&priv->reg_lock, reg_flags); | |
482 | if (!iwl_grab_nic_access(priv)) { | |
483 | _iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); | |
484 | wmb(); | |
485 | _iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, val); | |
486 | iwl_release_nic_access(priv); | |
487 | } | |
488 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | |
b481de9c ZY |
489 | } |
490 | ||
3395f6e9 | 491 | static inline void iwl_write_targ_mem_buf(struct iwl_priv *priv, u32 addr, |
af7cca2a | 492 | u32 len, u32 *values) |
b481de9c | 493 | { |
a8b50a0a MA |
494 | unsigned long reg_flags; |
495 | ||
496 | spin_lock_irqsave(&priv->reg_lock, reg_flags); | |
497 | if (!iwl_grab_nic_access(priv)) { | |
498 | _iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); | |
499 | wmb(); | |
500 | for (; 0 < len; len -= sizeof(u32), values++) | |
501 | _iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values); | |
502 | ||
503 | iwl_release_nic_access(priv); | |
504 | } | |
505 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | |
b481de9c | 506 | } |
b481de9c | 507 | #endif |