diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-io.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-io.c | 168 |
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 | ||
38 | static inline void __iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) | 38 | void __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 | ||
43 | static inline void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) | 43 | void __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 | } |
100 | EXPORT_SYMBOL_GPL(iwl_poll_bit); | 100 | EXPORT_SYMBOL_GPL(iwl_poll_bit); |
101 | 101 | ||
102 | int 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 | } | ||
142 | EXPORT_SYMBOL_GPL(iwl_grab_nic_access_silent); | ||
143 | |||
144 | bool 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 | } | ||
156 | EXPORT_SYMBOL_GPL(iwl_grab_nic_access); | ||
157 | |||
158 | void 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 | } | ||
171 | EXPORT_SYMBOL_GPL(iwl_release_nic_access); | ||
172 | |||
173 | u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) | 102 | u32 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) | |||
230 | u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs) | 160 | u32 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 | } |
299 | EXPORT_SYMBOL_GPL(iwl_clear_bits_prph); | 230 | EXPORT_SYMBOL_GPL(iwl_clear_bits_prph); |
300 | |||
301 | void _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 | } | ||
317 | EXPORT_SYMBOL_GPL(_iwl_read_targ_mem_dwords); | ||
318 | |||
319 | u32 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 | } | ||
327 | EXPORT_SYMBOL_GPL(iwl_read_targ_mem); | ||
328 | |||
329 | int _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 | } | ||
348 | EXPORT_SYMBOL_GPL(_iwl_write_targ_mem_dwords); | ||
349 | |||
350 | int 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 | } | ||
354 | EXPORT_SYMBOL_GPL(iwl_write_targ_mem); | ||