Linux Audio

Check our new training course

Linux kernel drivers training

May 6-19, 2025
Register
Loading...
Note: File does not exist in v6.8.
  1/******************************************************************************
  2 *
  3 * Copyright(c) 2003 - 2014 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#include <linux/delay.h>
 29#include <linux/device.h>
 30#include <linux/export.h>
 31
 32#include "iwl-drv.h"
 33#include "iwl-io.h"
 34#include "iwl-csr.h"
 35#include "iwl-debug.h"
 36#include "iwl-fh.h"
 37
 38#define IWL_POLL_INTERVAL 10	/* microseconds */
 39
 40int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
 41		 u32 bits, u32 mask, int timeout)
 42{
 43	int t = 0;
 44
 45	do {
 46		if ((iwl_read32(trans, addr) & mask) == (bits & mask))
 47			return t;
 48		udelay(IWL_POLL_INTERVAL);
 49		t += IWL_POLL_INTERVAL;
 50	} while (t < timeout);
 51
 52	return -ETIMEDOUT;
 53}
 54IWL_EXPORT_SYMBOL(iwl_poll_bit);
 55
 56u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
 57{
 58	u32 value = 0x5a5a5a5a;
 59	unsigned long flags;
 60	if (iwl_trans_grab_nic_access(trans, false, &flags)) {
 61		value = iwl_read32(trans, reg);
 62		iwl_trans_release_nic_access(trans, &flags);
 63	}
 64
 65	return value;
 66}
 67IWL_EXPORT_SYMBOL(iwl_read_direct32);
 68
 69void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
 70{
 71	unsigned long flags;
 72
 73	if (iwl_trans_grab_nic_access(trans, false, &flags)) {
 74		iwl_write32(trans, reg, value);
 75		iwl_trans_release_nic_access(trans, &flags);
 76	}
 77}
 78IWL_EXPORT_SYMBOL(iwl_write_direct32);
 79
 80int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
 81			int timeout)
 82{
 83	int t = 0;
 84
 85	do {
 86		if ((iwl_read_direct32(trans, addr) & mask) == mask)
 87			return t;
 88		udelay(IWL_POLL_INTERVAL);
 89		t += IWL_POLL_INTERVAL;
 90	} while (t < timeout);
 91
 92	return -ETIMEDOUT;
 93}
 94IWL_EXPORT_SYMBOL(iwl_poll_direct_bit);
 95
 96u32 __iwl_read_prph(struct iwl_trans *trans, u32 ofs)
 97{
 98	u32 val = iwl_trans_read_prph(trans, ofs);
 99	trace_iwlwifi_dev_ioread_prph32(trans->dev, ofs, val);
100	return val;
101}
102
103void __iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
104{
105	trace_iwlwifi_dev_iowrite_prph32(trans->dev, ofs, val);
106	iwl_trans_write_prph(trans, ofs, val);
107}
108
109u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
110{
111	unsigned long flags;
112	u32 val = 0x5a5a5a5a;
113
114	if (iwl_trans_grab_nic_access(trans, false, &flags)) {
115		val = __iwl_read_prph(trans, ofs);
116		iwl_trans_release_nic_access(trans, &flags);
117	}
118	return val;
119}
120IWL_EXPORT_SYMBOL(iwl_read_prph);
121
122void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
123{
124	unsigned long flags;
125
126	if (iwl_trans_grab_nic_access(trans, false, &flags)) {
127		__iwl_write_prph(trans, ofs, val);
128		iwl_trans_release_nic_access(trans, &flags);
129	}
130}
131IWL_EXPORT_SYMBOL(iwl_write_prph);
132
133int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr,
134		      u32 bits, u32 mask, int timeout)
135{
136	int t = 0;
137
138	do {
139		if ((iwl_read_prph(trans, addr) & mask) == (bits & mask))
140			return t;
141		udelay(IWL_POLL_INTERVAL);
142		t += IWL_POLL_INTERVAL;
143	} while (t < timeout);
144
145	return -ETIMEDOUT;
146}
147
148void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
149{
150	unsigned long flags;
151
152	if (iwl_trans_grab_nic_access(trans, false, &flags)) {
153		__iwl_write_prph(trans, ofs,
154				 __iwl_read_prph(trans, ofs) | mask);
155		iwl_trans_release_nic_access(trans, &flags);
156	}
157}
158IWL_EXPORT_SYMBOL(iwl_set_bits_prph);
159
160void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
161			    u32 bits, u32 mask)
162{
163	unsigned long flags;
164
165	if (iwl_trans_grab_nic_access(trans, false, &flags)) {
166		__iwl_write_prph(trans, ofs,
167				 (__iwl_read_prph(trans, ofs) & mask) | bits);
168		iwl_trans_release_nic_access(trans, &flags);
169	}
170}
171IWL_EXPORT_SYMBOL(iwl_set_bits_mask_prph);
172
173void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
174{
175	unsigned long flags;
176	u32 val;
177
178	if (iwl_trans_grab_nic_access(trans, false, &flags)) {
179		val = __iwl_read_prph(trans, ofs);
180		__iwl_write_prph(trans, ofs, (val & ~mask));
181		iwl_trans_release_nic_access(trans, &flags);
182	}
183}
184IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);
185
186static const char *get_fh_string(int cmd)
187{
188#define IWL_CMD(x) case x: return #x
189	switch (cmd) {
190	IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
191	IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
192	IWL_CMD(FH_RSCSR_CHNL0_WPTR);
193	IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
194	IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
195	IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
196	IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
197	IWL_CMD(FH_TSSR_TX_STATUS_REG);
198	IWL_CMD(FH_TSSR_TX_ERROR_REG);
199	default:
200		return "UNKNOWN";
201	}
202#undef IWL_CMD
203}
204
205int iwl_dump_fh(struct iwl_trans *trans, char **buf)
206{
207	int i;
208	static const u32 fh_tbl[] = {
209		FH_RSCSR_CHNL0_STTS_WPTR_REG,
210		FH_RSCSR_CHNL0_RBDCB_BASE_REG,
211		FH_RSCSR_CHNL0_WPTR,
212		FH_MEM_RCSR_CHNL0_CONFIG_REG,
213		FH_MEM_RSSR_SHARED_CTRL_REG,
214		FH_MEM_RSSR_RX_STATUS_REG,
215		FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
216		FH_TSSR_TX_STATUS_REG,
217		FH_TSSR_TX_ERROR_REG
218	};
219
220#ifdef CONFIG_IWLWIFI_DEBUGFS
221	if (buf) {
222		int pos = 0;
223		size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
224
225		*buf = kmalloc(bufsz, GFP_KERNEL);
226		if (!*buf)
227			return -ENOMEM;
228
229		pos += scnprintf(*buf + pos, bufsz - pos,
230				"FH register values:\n");
231
232		for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
233			pos += scnprintf(*buf + pos, bufsz - pos,
234				"  %34s: 0X%08x\n",
235				get_fh_string(fh_tbl[i]),
236				iwl_read_direct32(trans, fh_tbl[i]));
237
238		return pos;
239	}
240#endif
241
242	IWL_ERR(trans, "FH register values:\n");
243	for (i = 0; i <  ARRAY_SIZE(fh_tbl); i++)
244		IWL_ERR(trans, "  %34s: 0X%08x\n",
245			get_fh_string(fh_tbl[i]),
246			iwl_read_direct32(trans, fh_tbl[i]));
247
248	return 0;
249}