aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-io.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.c168
1 files changed, 22 insertions, 146 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c
index cdaff9572059..bff3ac96c00b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/iwlwifi/iwl-io.c
@@ -35,12 +35,12 @@
35 35
36#define IWL_POLL_INTERVAL 10 /* microseconds */ 36#define IWL_POLL_INTERVAL 10 /* microseconds */
37 37
38static inline void __iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) 38void __iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask)
39{ 39{
40 iwl_write32(trans, reg, iwl_read32(trans, reg) | mask); 40 iwl_write32(trans, reg, iwl_read32(trans, reg) | mask);
41} 41}
42 42
43static inline void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) 43void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
44{ 44{
45 iwl_write32(trans, reg, iwl_read32(trans, reg) & ~mask); 45 iwl_write32(trans, reg, iwl_read32(trans, reg) & ~mask);
46} 46}
@@ -99,86 +99,16 @@ int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
99} 99}
100EXPORT_SYMBOL_GPL(iwl_poll_bit); 100EXPORT_SYMBOL_GPL(iwl_poll_bit);
101 101
102int iwl_grab_nic_access_silent(struct iwl_trans *trans)
103{
104 int ret;
105
106 lockdep_assert_held(&trans->reg_lock);
107
108 /* this bit wakes up the NIC */
109 __iwl_set_bit(trans, CSR_GP_CNTRL,
110 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
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 */
131 ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
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) {
136 iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI);
137 return -EIO;
138 }
139
140 return 0;
141}
142EXPORT_SYMBOL_GPL(iwl_grab_nic_access_silent);
143
144bool iwl_grab_nic_access(struct iwl_trans *trans)
145{
146 int ret = iwl_grab_nic_access_silent(trans);
147 if (unlikely(ret)) {
148 u32 val = iwl_read32(trans, CSR_GP_CNTRL);
149 WARN_ONCE(1, "Timeout waiting for hardware access "
150 "(CSR_GP_CNTRL 0x%08x)\n", val);
151 return false;
152 }
153
154 return true;
155}
156EXPORT_SYMBOL_GPL(iwl_grab_nic_access);
157
158void iwl_release_nic_access(struct iwl_trans *trans)
159{
160 lockdep_assert_held(&trans->reg_lock);
161 __iwl_clear_bit(trans, CSR_GP_CNTRL,
162 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
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();
170}
171EXPORT_SYMBOL_GPL(iwl_release_nic_access);
172
173u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) 102u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
174{ 103{
175 u32 value; 104 u32 value = 0x5a5a5a5a;
176 unsigned long flags; 105 unsigned long flags;
177 106
178 spin_lock_irqsave(&trans->reg_lock, flags); 107 spin_lock_irqsave(&trans->reg_lock, flags);
179 iwl_grab_nic_access(trans); 108 if (iwl_trans_grab_nic_access(trans, false)) {
180 value = iwl_read32(trans, reg); 109 value = iwl_read32(trans, reg);
181 iwl_release_nic_access(trans); 110 iwl_trans_release_nic_access(trans);
111 }
182 spin_unlock_irqrestore(&trans->reg_lock, flags); 112 spin_unlock_irqrestore(&trans->reg_lock, flags);
183 113
184 return value; 114 return value;
@@ -190,9 +120,9 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
190 unsigned long flags; 120 unsigned long flags;
191 121
192 spin_lock_irqsave(&trans->reg_lock, flags); 122 spin_lock_irqsave(&trans->reg_lock, flags);
193 if (likely(iwl_grab_nic_access(trans))) { 123 if (iwl_trans_grab_nic_access(trans, false)) {
194 iwl_write32(trans, reg, value); 124 iwl_write32(trans, reg, value);
195 iwl_release_nic_access(trans); 125 iwl_trans_release_nic_access(trans);
196 } 126 }
197 spin_unlock_irqrestore(&trans->reg_lock, flags); 127 spin_unlock_irqrestore(&trans->reg_lock, flags);
198} 128}
@@ -230,12 +160,13 @@ static inline void __iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
230u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs) 160u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
231{ 161{
232 unsigned long flags; 162 unsigned long flags;
233 u32 val; 163 u32 val = 0x5a5a5a5a;
234 164
235 spin_lock_irqsave(&trans->reg_lock, flags); 165 spin_lock_irqsave(&trans->reg_lock, flags);
236 iwl_grab_nic_access(trans); 166 if (iwl_trans_grab_nic_access(trans, false)) {
237 val = __iwl_read_prph(trans, ofs); 167 val = __iwl_read_prph(trans, ofs);
238 iwl_release_nic_access(trans); 168 iwl_trans_release_nic_access(trans);
169 }
239 spin_unlock_irqrestore(&trans->reg_lock, flags); 170 spin_unlock_irqrestore(&trans->reg_lock, flags);
240 return val; 171 return val;
241} 172}
@@ -246,9 +177,9 @@ void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
246 unsigned long flags; 177 unsigned long flags;
247 178
248 spin_lock_irqsave(&trans->reg_lock, flags); 179 spin_lock_irqsave(&trans->reg_lock, flags);
249 if (likely(iwl_grab_nic_access(trans))) { 180 if (iwl_trans_grab_nic_access(trans, false)) {
250 __iwl_write_prph(trans, ofs, val); 181 __iwl_write_prph(trans, ofs, val);
251 iwl_release_nic_access(trans); 182 iwl_trans_release_nic_access(trans);
252 } 183 }
253 spin_unlock_irqrestore(&trans->reg_lock, flags); 184 spin_unlock_irqrestore(&trans->reg_lock, flags);
254} 185}
@@ -259,10 +190,10 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
259 unsigned long flags; 190 unsigned long flags;
260 191
261 spin_lock_irqsave(&trans->reg_lock, flags); 192 spin_lock_irqsave(&trans->reg_lock, flags);
262 if (likely(iwl_grab_nic_access(trans))) { 193 if (iwl_trans_grab_nic_access(trans, false)) {
263 __iwl_write_prph(trans, ofs, 194 __iwl_write_prph(trans, ofs,
264 __iwl_read_prph(trans, ofs) | mask); 195 __iwl_read_prph(trans, ofs) | mask);
265 iwl_release_nic_access(trans); 196 iwl_trans_release_nic_access(trans);
266 } 197 }
267 spin_unlock_irqrestore(&trans->reg_lock, flags); 198 spin_unlock_irqrestore(&trans->reg_lock, flags);
268} 199}
@@ -274,10 +205,10 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
274 unsigned long flags; 205 unsigned long flags;
275 206
276 spin_lock_irqsave(&trans->reg_lock, flags); 207 spin_lock_irqsave(&trans->reg_lock, flags);
277 if (likely(iwl_grab_nic_access(trans))) { 208 if (iwl_trans_grab_nic_access(trans, false)) {
278 __iwl_write_prph(trans, ofs, 209 __iwl_write_prph(trans, ofs,
279 (__iwl_read_prph(trans, ofs) & mask) | bits); 210 (__iwl_read_prph(trans, ofs) & mask) | bits);
280 iwl_release_nic_access(trans); 211 iwl_trans_release_nic_access(trans);
281 } 212 }
282 spin_unlock_irqrestore(&trans->reg_lock, flags); 213 spin_unlock_irqrestore(&trans->reg_lock, flags);
283} 214}
@@ -289,66 +220,11 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
289 u32 val; 220 u32 val;
290 221
291 spin_lock_irqsave(&trans->reg_lock, flags); 222 spin_lock_irqsave(&trans->reg_lock, flags);
292 if (likely(iwl_grab_nic_access(trans))) { 223 if (iwl_trans_grab_nic_access(trans, false)) {
293 val = __iwl_read_prph(trans, ofs); 224 val = __iwl_read_prph(trans, ofs);
294 __iwl_write_prph(trans, ofs, (val & ~mask)); 225 __iwl_write_prph(trans, ofs, (val & ~mask));
295 iwl_release_nic_access(trans); 226 iwl_trans_release_nic_access(trans);
296 } 227 }
297 spin_unlock_irqrestore(&trans->reg_lock, flags); 228 spin_unlock_irqrestore(&trans->reg_lock, flags);
298} 229}
299EXPORT_SYMBOL_GPL(iwl_clear_bits_prph); 230EXPORT_SYMBOL_GPL(iwl_clear_bits_prph);
300
301void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
302 void *buf, int dwords)
303{
304 unsigned long flags;
305 int offs;
306 u32 *vals = buf;
307
308 spin_lock_irqsave(&trans->reg_lock, flags);
309 if (likely(iwl_grab_nic_access(trans))) {
310 iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr);
311 for (offs = 0; offs < dwords; offs++)
312 vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
313 iwl_release_nic_access(trans);
314 }
315 spin_unlock_irqrestore(&trans->reg_lock, flags);
316}
317EXPORT_SYMBOL_GPL(_iwl_read_targ_mem_dwords);
318
319u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr)
320{
321 u32 value;
322
323 _iwl_read_targ_mem_dwords(trans, addr, &value, 1);
324
325 return value;
326}
327EXPORT_SYMBOL_GPL(iwl_read_targ_mem);
328
329int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
330 const void *buf, int dwords)
331{
332 unsigned long flags;
333 int offs, result = 0;
334 const u32 *vals = buf;
335
336 spin_lock_irqsave(&trans->reg_lock, flags);
337 if (likely(iwl_grab_nic_access(trans))) {
338 iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr);
339 for (offs = 0; offs < dwords; offs++)
340 iwl_write32(trans, HBUS_TARG_MEM_WDAT, vals[offs]);
341 iwl_release_nic_access(trans);
342 } else
343 result = -EBUSY;
344 spin_unlock_irqrestore(&trans->reg_lock, flags);
345
346 return result;
347}
348EXPORT_SYMBOL_GPL(_iwl_write_targ_mem_dwords);
349
350int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val)
351{
352 return _iwl_write_targ_mem_dwords(trans, addr, &val, 1);
353}
354EXPORT_SYMBOL_GPL(iwl_write_targ_mem);