]>
Commit | Line | Data |
---|---|---|
b481de9c ZY |
1 | /****************************************************************************** |
2 | * | |
3 | * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved. | |
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 | * James P. Ketrenos <ipw2100-admin@linux.intel.com> | |
25 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | |
26 | * | |
27 | *****************************************************************************/ | |
28 | ||
29 | #ifndef __iwl_io_h__ | |
30 | #define __iwl_io_h__ | |
31 | ||
32 | #include <linux/io.h> | |
33 | ||
34 | #include "iwl-debug.h" | |
35 | ||
36 | /* | |
37 | * IO, register, and NIC memory access functions | |
38 | * | |
39 | * NOTE on naming convention and macro usage for these | |
40 | * | |
41 | * A single _ prefix before a an access function means that no state | |
42 | * check or debug information is printed when that function is called. | |
43 | * | |
44 | * A double __ prefix before an access function means that state is checked | |
45 | * (in the case of *restricted calls) and the current line number is printed | |
46 | * in addition to any other debug output. | |
47 | * | |
48 | * The non-prefixed name is the #define that maps the caller into a | |
49 | * #define that provides the caller's __LINE__ to the double prefix version. | |
50 | * | |
51 | * If you wish to call the function without any debug or state checking, | |
52 | * you should use the single _ prefix version (as is used by dependent IO | |
53 | * routines, for example _iwl_read_restricted calls the non-check version of | |
54 | * _iwl_read32.) | |
55 | * | |
56 | * These declarations are *extremely* useful in quickly isolating code deltas | |
57 | * which result in misconfiguring of the hardware I/O. In combination with | |
58 | * git-bisect and the IO debug level you can quickly determine the specific | |
59 | * commit which breaks the IO sequence to the hardware. | |
60 | * | |
61 | */ | |
62 | ||
63 | #define _iwl_write32(iwl, ofs, val) writel((val), (iwl)->hw_base + (ofs)) | |
64 | #ifdef CONFIG_IWLWIFI_DEBUG | |
65 | static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *iwl, | |
66 | u32 ofs, u32 val) | |
67 | { | |
68 | IWL_DEBUG_IO("write_direct32(0x%08X, 0x%08X) - %s %d\n", | |
69 | (u32) (ofs), (u32) (val), f, l); | |
70 | _iwl_write32(iwl, ofs, val); | |
71 | } | |
72 | #define iwl_write32(iwl, ofs, val) \ | |
73 | __iwl_write32(__FILE__, __LINE__, iwl, ofs, val) | |
74 | #else | |
75 | #define iwl_write32(iwl, ofs, val) _iwl_write32(iwl, ofs, val) | |
76 | #endif | |
77 | ||
78 | #define _iwl_read32(iwl, ofs) readl((iwl)->hw_base + (ofs)) | |
79 | #ifdef CONFIG_IWLWIFI_DEBUG | |
80 | static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *iwl, u32 ofs) | |
81 | { | |
82 | IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l); | |
83 | return _iwl_read32(iwl, ofs); | |
84 | } | |
85 | #define iwl_read32(iwl, ofs) __iwl_read32(__FILE__, __LINE__, iwl, ofs) | |
86 | #else | |
87 | #define iwl_read32(p, o) _iwl_read32(p, o) | |
88 | #endif | |
89 | ||
90 | static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr, | |
91 | u32 bits, u32 mask, int timeout) | |
92 | { | |
93 | int i = 0; | |
94 | ||
95 | do { | |
96 | if ((_iwl_read32(priv, addr) & mask) == (bits & mask)) | |
97 | return i; | |
98 | mdelay(10); | |
99 | i += 10; | |
100 | } while (i < timeout); | |
101 | ||
102 | return -ETIMEDOUT; | |
103 | } | |
104 | #ifdef CONFIG_IWLWIFI_DEBUG | |
105 | static inline int __iwl_poll_bit(const char *f, u32 l, | |
106 | struct iwl_priv *priv, u32 addr, | |
107 | u32 bits, u32 mask, int timeout) | |
108 | { | |
109 | int rc = _iwl_poll_bit(priv, addr, bits, mask, timeout); | |
110 | if (unlikely(rc == -ETIMEDOUT)) | |
111 | IWL_DEBUG_IO | |
112 | ("poll_bit(0x%08X, 0x%08X, 0x%08X) - timedout - %s %d\n", | |
113 | addr, bits, mask, f, l); | |
114 | else | |
115 | IWL_DEBUG_IO | |
116 | ("poll_bit(0x%08X, 0x%08X, 0x%08X) = 0x%08X - %s %d\n", | |
117 | addr, bits, mask, rc, f, l); | |
118 | return rc; | |
119 | } | |
120 | #define iwl_poll_bit(iwl, addr, bits, mask, timeout) \ | |
121 | __iwl_poll_bit(__FILE__, __LINE__, iwl, addr, bits, mask, timeout) | |
122 | #else | |
123 | #define iwl_poll_bit(p, a, b, m, t) _iwl_poll_bit(p, a, b, m, t) | |
124 | #endif | |
125 | ||
126 | static inline void _iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) | |
127 | { | |
128 | _iwl_write32(priv, reg, _iwl_read32(priv, reg) | mask); | |
129 | } | |
130 | #ifdef CONFIG_IWLWIFI_DEBUG | |
131 | static inline void __iwl_set_bit(const char *f, u32 l, | |
132 | struct iwl_priv *priv, u32 reg, u32 mask) | |
133 | { | |
134 | u32 val = _iwl_read32(priv, reg) | mask; | |
135 | IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); | |
136 | _iwl_write32(priv, reg, val); | |
137 | } | |
138 | #define iwl_set_bit(p, r, m) __iwl_set_bit(__FILE__, __LINE__, p, r, m) | |
139 | #else | |
140 | #define iwl_set_bit(p, r, m) _iwl_set_bit(p, r, m) | |
141 | #endif | |
142 | ||
143 | static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) | |
144 | { | |
145 | _iwl_write32(priv, reg, _iwl_read32(priv, reg) & ~mask); | |
146 | } | |
147 | #ifdef CONFIG_IWLWIFI_DEBUG | |
148 | static inline void __iwl_clear_bit(const char *f, u32 l, | |
149 | struct iwl_priv *priv, u32 reg, u32 mask) | |
150 | { | |
151 | u32 val = _iwl_read32(priv, reg) & ~mask; | |
152 | IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); | |
153 | _iwl_write32(priv, reg, val); | |
154 | } | |
155 | #define iwl_clear_bit(p, r, m) __iwl_clear_bit(__FILE__, __LINE__, p, r, m) | |
156 | #else | |
157 | #define iwl_clear_bit(p, r, m) _iwl_clear_bit(p, r, m) | |
158 | #endif | |
159 | ||
160 | static inline int _iwl_grab_restricted_access(struct iwl_priv *priv) | |
161 | { | |
162 | int rc; | |
163 | u32 gp_ctl; | |
164 | ||
165 | #ifdef CONFIG_IWLWIFI_DEBUG | |
166 | if (atomic_read(&priv->restrict_refcnt)) | |
167 | return 0; | |
168 | #endif | |
169 | if (test_bit(STATUS_RF_KILL_HW, &priv->status) || | |
170 | test_bit(STATUS_RF_KILL_SW, &priv->status)) { | |
171 | IWL_WARNING("WARNING: Requesting MAC access during RFKILL " | |
172 | "wakes up NIC\n"); | |
173 | ||
174 | /* 10 msec allows time for NIC to complete its data save */ | |
175 | gp_ctl = _iwl_read32(priv, CSR_GP_CNTRL); | |
176 | if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) { | |
177 | IWL_DEBUG_RF_KILL("Wait for complete power-down, " | |
178 | "gpctl = 0x%08x\n", gp_ctl); | |
179 | mdelay(10); | |
180 | } else | |
181 | IWL_DEBUG_RF_KILL("power-down complete, " | |
182 | "gpctl = 0x%08x\n", gp_ctl); | |
183 | } | |
184 | ||
185 | /* this bit wakes up the NIC */ | |
186 | _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | |
187 | rc = _iwl_poll_bit(priv, CSR_GP_CNTRL, | |
188 | CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, | |
189 | (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | | |
190 | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50); | |
191 | if (rc < 0) { | |
192 | IWL_ERROR("MAC is in deep sleep!\n"); | |
193 | return -EIO; | |
194 | } | |
195 | ||
196 | #ifdef CONFIG_IWLWIFI_DEBUG | |
197 | atomic_inc(&priv->restrict_refcnt); | |
198 | #endif | |
199 | return 0; | |
200 | } | |
201 | ||
202 | #ifdef CONFIG_IWLWIFI_DEBUG | |
203 | static inline int __iwl_grab_restricted_access(const char *f, u32 l, | |
204 | struct iwl_priv *priv) | |
205 | { | |
206 | if (atomic_read(&priv->restrict_refcnt)) | |
207 | IWL_DEBUG_INFO("Grabbing access while already held at " | |
208 | "line %d.\n", l); | |
209 | ||
210 | IWL_DEBUG_IO("grabbing restricted access - %s %d\n", f, l); | |
211 | ||
212 | return _iwl_grab_restricted_access(priv); | |
213 | } | |
214 | #define iwl_grab_restricted_access(priv) \ | |
215 | __iwl_grab_restricted_access(__FILE__, __LINE__, priv) | |
216 | #else | |
217 | #define iwl_grab_restricted_access(priv) \ | |
218 | _iwl_grab_restricted_access(priv) | |
219 | #endif | |
220 | ||
221 | static inline void _iwl_release_restricted_access(struct iwl_priv *priv) | |
222 | { | |
223 | #ifdef CONFIG_IWLWIFI_DEBUG | |
224 | if (atomic_dec_and_test(&priv->restrict_refcnt)) | |
225 | #endif | |
226 | _iwl_clear_bit(priv, CSR_GP_CNTRL, | |
227 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | |
228 | } | |
229 | #ifdef CONFIG_IWLWIFI_DEBUG | |
230 | static inline void __iwl_release_restricted_access(const char *f, u32 l, | |
231 | struct iwl_priv *priv) | |
232 | { | |
233 | if (atomic_read(&priv->restrict_refcnt) <= 0) | |
234 | IWL_ERROR("Release unheld restricted access at line %d.\n", l); | |
235 | ||
236 | IWL_DEBUG_IO("releasing restricted access - %s %d\n", f, l); | |
237 | _iwl_release_restricted_access(priv); | |
238 | } | |
239 | #define iwl_release_restricted_access(priv) \ | |
240 | __iwl_release_restricted_access(__FILE__, __LINE__, priv) | |
241 | #else | |
242 | #define iwl_release_restricted_access(priv) \ | |
243 | _iwl_release_restricted_access(priv) | |
244 | #endif | |
245 | ||
246 | static inline u32 _iwl_read_restricted(struct iwl_priv *priv, u32 reg) | |
247 | { | |
248 | return _iwl_read32(priv, reg); | |
249 | } | |
250 | #ifdef CONFIG_IWLWIFI_DEBUG | |
251 | static inline u32 __iwl_read_restricted(const char *f, u32 l, | |
252 | struct iwl_priv *priv, u32 reg) | |
253 | { | |
254 | u32 value = _iwl_read_restricted(priv, reg); | |
255 | if (!atomic_read(&priv->restrict_refcnt)) | |
256 | IWL_ERROR("Unrestricted access from %s %d\n", f, l); | |
257 | IWL_DEBUG_IO("read_restricted(0x%4X) = 0x%08x - %s %d \n", reg, value, | |
258 | f, l); | |
259 | return value; | |
260 | } | |
261 | #define iwl_read_restricted(priv, reg) \ | |
262 | __iwl_read_restricted(__FILE__, __LINE__, priv, reg) | |
263 | #else | |
264 | #define iwl_read_restricted _iwl_read_restricted | |
265 | #endif | |
266 | ||
267 | static inline void _iwl_write_restricted(struct iwl_priv *priv, | |
268 | u32 reg, u32 value) | |
269 | { | |
270 | _iwl_write32(priv, reg, value); | |
271 | } | |
272 | #ifdef CONFIG_IWLWIFI_DEBUG | |
273 | static void __iwl_write_restricted(u32 line, | |
274 | struct iwl_priv *priv, u32 reg, u32 value) | |
275 | { | |
276 | if (!atomic_read(&priv->restrict_refcnt)) | |
277 | IWL_ERROR("Unrestricted access from line %d\n", line); | |
278 | _iwl_write_restricted(priv, reg, value); | |
279 | } | |
280 | #define iwl_write_restricted(priv, reg, value) \ | |
281 | __iwl_write_restricted(__LINE__, priv, reg, value) | |
282 | #else | |
283 | #define iwl_write_restricted _iwl_write_restricted | |
284 | #endif | |
285 | ||
286 | static inline void iwl_write_buffer_restricted(struct iwl_priv *priv, | |
287 | u32 reg, u32 len, u32 *values) | |
288 | { | |
289 | u32 count = sizeof(u32); | |
290 | ||
291 | if ((priv != NULL) && (values != NULL)) { | |
292 | for (; 0 < len; len -= count, reg += count, values++) | |
293 | _iwl_write_restricted(priv, reg, *values); | |
294 | } | |
295 | } | |
296 | ||
297 | static inline int _iwl_poll_restricted_bit(struct iwl_priv *priv, | |
298 | u32 addr, u32 mask, int timeout) | |
299 | { | |
300 | int i = 0; | |
301 | ||
302 | do { | |
303 | if ((_iwl_read_restricted(priv, addr) & mask) == mask) | |
304 | return i; | |
305 | mdelay(10); | |
306 | i += 10; | |
307 | } while (i < timeout); | |
308 | ||
309 | return -ETIMEDOUT; | |
310 | } | |
311 | ||
312 | #ifdef CONFIG_IWLWIFI_DEBUG | |
313 | static inline int __iwl_poll_restricted_bit(const char *f, u32 l, | |
314 | struct iwl_priv *priv, | |
315 | u32 addr, u32 mask, int timeout) | |
316 | { | |
317 | int rc = _iwl_poll_restricted_bit(priv, addr, mask, timeout); | |
318 | ||
319 | if (unlikely(rc == -ETIMEDOUT)) | |
320 | IWL_DEBUG_IO("poll_restricted_bit(0x%08X, 0x%08X) - " | |
321 | "timedout - %s %d\n", addr, mask, f, l); | |
322 | else | |
323 | IWL_DEBUG_IO("poll_restricted_bit(0x%08X, 0x%08X) = 0x%08X " | |
324 | "- %s %d\n", addr, mask, rc, f, l); | |
325 | return rc; | |
326 | } | |
327 | #define iwl_poll_restricted_bit(iwl, addr, mask, timeout) \ | |
328 | __iwl_poll_restricted_bit(__FILE__, __LINE__, iwl, addr, mask, timeout) | |
329 | #else | |
330 | #define iwl_poll_restricted_bit _iwl_poll_restricted_bit | |
331 | #endif | |
332 | ||
333 | static inline u32 _iwl_read_restricted_reg(struct iwl_priv *priv, u32 reg) | |
334 | { | |
335 | _iwl_write_restricted(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); | |
336 | return _iwl_read_restricted(priv, HBUS_TARG_PRPH_RDAT); | |
337 | } | |
338 | #ifdef CONFIG_IWLWIFI_DEBUG | |
339 | static inline u32 __iwl_read_restricted_reg(u32 line, | |
340 | struct iwl_priv *priv, u32 reg) | |
341 | { | |
342 | if (!atomic_read(&priv->restrict_refcnt)) | |
343 | IWL_ERROR("Unrestricted access from line %d\n", line); | |
344 | return _iwl_read_restricted_reg(priv, reg); | |
345 | } | |
346 | ||
347 | #define iwl_read_restricted_reg(priv, reg) \ | |
348 | __iwl_read_restricted_reg(__LINE__, priv, reg) | |
349 | #else | |
350 | #define iwl_read_restricted_reg _iwl_read_restricted_reg | |
351 | #endif | |
352 | ||
353 | static inline void _iwl_write_restricted_reg(struct iwl_priv *priv, | |
354 | u32 addr, u32 val) | |
355 | { | |
356 | _iwl_write_restricted(priv, HBUS_TARG_PRPH_WADDR, | |
357 | ((addr & 0x0000FFFF) | (3 << 24))); | |
358 | _iwl_write_restricted(priv, HBUS_TARG_PRPH_WDAT, val); | |
359 | } | |
360 | #ifdef CONFIG_IWLWIFI_DEBUG | |
361 | static inline void __iwl_write_restricted_reg(u32 line, | |
362 | struct iwl_priv *priv, | |
363 | u32 addr, u32 val) | |
364 | { | |
365 | if (!atomic_read(&priv->restrict_refcnt)) | |
366 | IWL_ERROR("Unrestricted access from line %d\n", line); | |
367 | _iwl_write_restricted_reg(priv, addr, val); | |
368 | } | |
369 | ||
370 | #define iwl_write_restricted_reg(priv, addr, val) \ | |
371 | __iwl_write_restricted_reg(__LINE__, priv, addr, val); | |
372 | #else | |
373 | #define iwl_write_restricted_reg _iwl_write_restricted_reg | |
374 | #endif | |
375 | ||
376 | #define _iwl_set_bits_restricted_reg(priv, reg, mask) \ | |
377 | _iwl_write_restricted_reg(priv, reg, \ | |
378 | (_iwl_read_restricted_reg(priv, reg) | mask)) | |
379 | #ifdef CONFIG_IWLWIFI_DEBUG | |
380 | static inline void __iwl_set_bits_restricted_reg(u32 line, struct iwl_priv | |
381 | *priv, u32 reg, u32 mask) | |
382 | { | |
383 | if (!atomic_read(&priv->restrict_refcnt)) | |
384 | IWL_ERROR("Unrestricted access from line %d\n", line); | |
385 | _iwl_set_bits_restricted_reg(priv, reg, mask); | |
386 | } | |
387 | #define iwl_set_bits_restricted_reg(priv, reg, mask) \ | |
388 | __iwl_set_bits_restricted_reg(__LINE__, priv, reg, mask) | |
389 | #else | |
390 | #define iwl_set_bits_restricted_reg _iwl_set_bits_restricted_reg | |
391 | #endif | |
392 | ||
393 | #define _iwl_set_bits_mask_restricted_reg(priv, reg, bits, mask) \ | |
394 | _iwl_write_restricted_reg( \ | |
395 | priv, reg, ((_iwl_read_restricted_reg(priv, reg) & mask) | bits)) | |
396 | #ifdef CONFIG_IWLWIFI_DEBUG | |
397 | static inline void __iwl_set_bits_mask_restricted_reg(u32 line, | |
398 | struct iwl_priv *priv, u32 reg, u32 bits, u32 mask) | |
399 | { | |
400 | if (!atomic_read(&priv->restrict_refcnt)) | |
401 | IWL_ERROR("Unrestricted access from line %d\n", line); | |
402 | _iwl_set_bits_mask_restricted_reg(priv, reg, bits, mask); | |
403 | } | |
404 | ||
405 | #define iwl_set_bits_mask_restricted_reg(priv, reg, bits, mask) \ | |
406 | __iwl_set_bits_mask_restricted_reg(__LINE__, priv, reg, bits, mask) | |
407 | #else | |
408 | #define iwl_set_bits_mask_restricted_reg _iwl_set_bits_mask_restricted_reg | |
409 | #endif | |
410 | ||
411 | static inline void iwl_clear_bits_restricted_reg(struct iwl_priv | |
412 | *priv, u32 reg, u32 mask) | |
413 | { | |
414 | u32 val = _iwl_read_restricted_reg(priv, reg); | |
415 | _iwl_write_restricted_reg(priv, reg, (val & ~mask)); | |
416 | } | |
417 | ||
418 | static inline u32 iwl_read_restricted_mem(struct iwl_priv *priv, u32 addr) | |
419 | { | |
420 | iwl_write_restricted(priv, HBUS_TARG_MEM_RADDR, addr); | |
421 | return iwl_read_restricted(priv, HBUS_TARG_MEM_RDAT); | |
422 | } | |
423 | ||
424 | static inline void iwl_write_restricted_mem(struct iwl_priv *priv, u32 addr, | |
425 | u32 val) | |
426 | { | |
427 | iwl_write_restricted(priv, HBUS_TARG_MEM_WADDR, addr); | |
428 | iwl_write_restricted(priv, HBUS_TARG_MEM_WDAT, val); | |
429 | } | |
430 | ||
431 | static inline void iwl_write_restricted_mems(struct iwl_priv *priv, u32 addr, | |
432 | u32 len, u32 *values) | |
433 | { | |
434 | iwl_write_restricted(priv, HBUS_TARG_MEM_WADDR, addr); | |
435 | for (; 0 < len; len -= sizeof(u32), values++) | |
436 | iwl_write_restricted(priv, HBUS_TARG_MEM_WDAT, *values); | |
437 | } | |
438 | ||
439 | static inline void iwl_write_restricted_regs(struct iwl_priv *priv, u32 reg, | |
440 | u32 len, u8 *values) | |
441 | { | |
442 | u32 reg_offset = reg; | |
443 | u32 aligment = reg & 0x3; | |
444 | ||
445 | /* write any non-dword-aligned stuff at the beginning */ | |
446 | if (len < sizeof(u32)) { | |
447 | if ((aligment + len) <= sizeof(u32)) { | |
448 | u8 size; | |
449 | u32 value = 0; | |
450 | size = len - 1; | |
451 | memcpy(&value, values, len); | |
452 | reg_offset = (reg_offset & 0x0000FFFF); | |
453 | ||
454 | _iwl_write_restricted(priv, | |
455 | HBUS_TARG_PRPH_WADDR, | |
456 | (reg_offset | (size << 24))); | |
457 | _iwl_write_restricted(priv, HBUS_TARG_PRPH_WDAT, | |
458 | value); | |
459 | } | |
460 | ||
461 | return; | |
462 | } | |
463 | ||
464 | /* now write all the dword-aligned stuff */ | |
465 | for (; reg_offset < (reg + len); | |
466 | reg_offset += sizeof(u32), values += sizeof(u32)) | |
467 | _iwl_write_restricted_reg(priv, reg_offset, *((u32 *) values)); | |
468 | } | |
469 | ||
470 | #endif |