Linux Audio

Check our new training course

Yocto / OpenEmbedded training

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