xref: /wlan-dirver/qca-wifi-host-cmn/hif/src/mp_dev.c (revision 0a341a5e929822071094f40c50086862947cca6b)
1 /*
2  * Copyright (c) 2013-2014, 2016-2017 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include "hif_io32.h"
20 #include "hif_debug.h"
21 #include "mp_dev.h"
22 
23 /*chaninfo*/
24 #define  CHANINFOMEM_S2_READ_MASK               0x00000008
25 #define  CHANINFO_CTRL_CAPTURE_CHAN_INFO_MASK   0x00000001
26 #define  CHANINFO_CTRL_CHANINFOMEM_BW_MASK      0x00000030
27 #define  MULTICHAIN_ENABLE_RX_CHAIN_MASK_MASK   0x00000007
28 
29 /*agc*/
30 #define GAINS_MIN_OFFSETS_CF_AGC_HIST_ENABLE_MASK              0x00040000
31 #define GAINS_MIN_OFFSETS_CF_AGC_HIST_GC_MASK                  0x00080000
32 #define GAINS_MIN_OFFSETS_CF_AGC_HIST_VOTING_MASK              0x00100000
33 #define GAINS_MIN_OFFSETS_CF_AGC_HIST_PHY_ERR_MASK             0x00200000
34 #define  AGC_HISTORY_DUMP_MASK (\
35 	GAINS_MIN_OFFSETS_CF_AGC_HIST_ENABLE_MASK| \
36 	GAINS_MIN_OFFSETS_CF_AGC_HIST_GC_MASK| \
37 	GAINS_MIN_OFFSETS_CF_AGC_HIST_VOTING_MASK| \
38 	GAINS_MIN_OFFSETS_CF_AGC_HIST_PHY_ERR_MASK \
39 	)
40 
41 #define BB_chaninfo_ctrl         0x1a370
42 #define BB_multichain_enable     0x1a2a0
43 #define BB_chn_tables_intf_addr  0x19894
44 #define BB_chn1_tables_intf_addr 0x1a894
45 #define BB_chn_tables_intf_data  0x19898
46 #define BB_chn1_tables_intf_data 0x1a898
47 #define BB_gains_min_offsets     0x19e08
48 #define BB_chaninfo_tab_b0       0x03200
49 #define BB_chaninfo_tab_b1       0x03300
50 #define BB_watchdog_status       0x1a7c0
51 #define BB_watchdog_ctrl_1       0x1a7c4
52 #define BB_watchdog_ctrl_2       0x1a7c8
53 #define BB_watchdog_status_B     0x1a7e0
54 
55 
56 #define PHY_BB_CHN_TABLES_INTF_ADDR 0x19894
57 #define PHY_BB_CHN_TABLES_INTF_DATA 0x19898
58 
59 #define PHY_BB_CHN1_TABLES_INTF_ADDR 0x1a894
60 #define PHY_BB_CHN1_TABLES_INTF_DATA 0x1a898
61 
62 
63 struct priv_ctrl_ctx {
64 	uint32_t chaninfo_ctrl_orig;
65 	uint32_t gain_min_offsets_orig;
66 	uint32_t anyreg_start;
67 	uint32_t anyreg_len;
68 };
69 
70 static struct priv_ctrl_ctx g_priv_dump_ctx;
71 
72 static inline void set_target_reg_bits(void __iomem *mem, uint32_t reg,
73 				       uint32_t bitmask, uint32_t val)
74 {
75 	uint32_t value = hif_read32_mb(mem + (reg));
76 	uint32_t shift = 0;
77 
78 	value &= ~(bitmask);
79 	while (!((bitmask >> shift) & 0x01))
80 		shift++;
81 
82 	value |= (((val) << shift) & (bitmask));
83 	hif_write32_mb(mem + (reg), value);
84 }
85 
86 static inline uint32_t get_target_reg_bits(void __iomem *mem,
87 					   uint32_t reg, uint32_t bitmask)
88 {
89 	uint32_t value = hif_read32_mb(mem + (reg));
90 	uint32_t shift = 0;
91 
92 	while (!((bitmask >> shift) & 0x01))
93 		shift++;
94 
95 	return (value >> shift) & bitmask;
96 }
97 
98 void priv_start_cap_chaninfo(struct hif_softc *scn)
99 {
100 	set_target_reg_bits(scn->mem, BB_chaninfo_ctrl,
101 			    CHANINFO_CTRL_CAPTURE_CHAN_INFO_MASK, 1);
102 }
103 
104 void priv_start_agc(struct hif_softc *scn)
105 {
106 	g_priv_dump_ctx.gain_min_offsets_orig =
107 		hif_read32_mb(scn->mem + BB_gains_min_offsets);
108 	set_target_reg_bits(scn->mem, BB_gains_min_offsets,
109 			    AGC_HISTORY_DUMP_MASK,
110 			    0x0f);
111 }
112 
113 static void priv_stop_agc(struct hif_softc *scn)
114 {
115 	set_target_reg_bits(scn->mem, BB_gains_min_offsets,
116 			    AGC_HISTORY_DUMP_MASK,
117 			    0);
118 }
119 
120 void priv_dump_chaninfo(struct hif_softc *scn)
121 {
122 	uint32_t bw, val;
123 	uint32_t len, i, tmp;
124 	uint32_t chain_mask;
125 	uint32_t chain0, chain1;
126 
127 	chain_mask =
128 		get_target_reg_bits(scn->mem, BB_multichain_enable,
129 				    MULTICHAIN_ENABLE_RX_CHAIN_MASK_MASK);
130 	chain0 = chain_mask & 1;
131 	chain1 = chain_mask & 2;
132 
133 	HIF_TRACE("%s: E", __func__);
134 	bw = get_target_reg_bits(scn->mem, BB_chaninfo_ctrl,
135 				 CHANINFO_CTRL_CHANINFOMEM_BW_MASK);
136 
137 	if (bw == 0)
138 		len = 53;
139 	else if (bw == 1)
140 		len = 57;
141 	else if (bw == 2)
142 		len = 59 * 2 - 1;
143 	else
144 		len = 60 * 2 + 61 * 2;
145 
146 	/*
147 	 * each tone is 16 bit valid, write to 32bit buffer each.
148 	 * bw==0(legacy20): 53 tones.
149 	 * bw==1(ht/vht20): 57 tones.
150 	 * bw==2(ht/vht40): 59+58 tones.
151 	 * bw==3(vht80): 60*2+61*2 tones.
152 	 */
153 
154 	if (chain0) {
155 		hif_write32_mb(scn->mem + BB_chn_tables_intf_addr,
156 			      0x80003200);
157 	}
158 	if (chain1) {
159 		hif_write32_mb(scn->mem + BB_chn1_tables_intf_addr,
160 			      0x80003200);
161 	}
162 
163 	set_target_reg_bits(scn->mem, BB_chaninfo_ctrl,
164 			CHANINFOMEM_S2_READ_MASK, 0);
165 
166 	if (chain0) {
167 		if (bw < 2) {
168 			len = (bw == 0) ? 53 : 57;
169 			for (i = 0; i < len; i++) {
170 				val =
171 					hif_read32_mb(scn->mem +
172 						     BB_chn_tables_intf_data) &
173 					0x0000ffff;
174 				qdf_debug("0x%x\t", val);
175 				if (i % 4 == 0)
176 					qdf_debug("\n");
177 			}
178 		} else {
179 			len = (bw == 2) ? 59 : 60;
180 			for (i = 0; i < len; i++) {
181 				tmp =
182 					hif_read32_mb(scn->mem +
183 						     BB_chn_tables_intf_data);
184 				qdf_debug("0x%x\t", ((tmp >> 16) & 0x0000ffff));
185 				qdf_debug("0x%x\t", (tmp & 0x0000ffff));
186 				if (i % 2 == 0)
187 					qdf_debug("\n");
188 			}
189 			if (bw > 2) {
190 				/* bw == 3 for vht80 */
191 				hif_write32_mb(scn->mem +
192 					      BB_chn_tables_intf_addr,
193 					      0x80003300);
194 				len = 61;
195 				for (i = 0; i < len; i++) {
196 					tmp =
197 						hif_read32_mb(scn->mem +
198 						     BB_chn_tables_intf_data);
199 					qdf_debug("0x%x\t",
200 					       ((tmp >> 16) & 0x0000ffff));
201 					qdf_debug("0x%x\t", (tmp & 0x0000ffff));
202 					if (i % 2 == 0)
203 						qdf_debug("\n");
204 				}
205 			}
206 		}
207 	}
208 	if (chain1) {
209 		if (bw < 2) {
210 			len = (bw == 0) ? 53 : 57;
211 			for (i = 0; i < len; i++) {
212 				val =
213 					hif_read32_mb(scn->mem +
214 						BB_chn1_tables_intf_data) &
215 					0x0000ffff;
216 				qdf_debug("0x%x\t", val);
217 				if (i % 4 == 0)
218 					qdf_debug("\n");
219 			}
220 		} else {
221 			len = (bw == 2) ? 59 : 60;
222 			for (i = 0; i < len; i++) {
223 				tmp =
224 					hif_read32_mb(scn->mem +
225 						     BB_chn1_tables_intf_data);
226 				qdf_debug("0x%x\n", (tmp >> 16) & 0x0000ffff);
227 				qdf_debug("0x%x\n", tmp & 0x0000ffff);
228 				if (i % 2 == 0)
229 					qdf_debug("\n");
230 			}
231 			if (bw > 2) {
232 				/* bw == 3 for vht80 */
233 				hif_write32_mb(scn->mem +
234 					      BB_chn1_tables_intf_addr,
235 					      0x80003300);
236 				len = 61;
237 				for (i = 0; i < len; i++) {
238 					tmp =
239 						hif_read32_mb(scn->mem +
240 						     BB_chn1_tables_intf_data);
241 					qdf_debug("0x%x\t",
242 					       ((tmp >> 16) & 0x0000ffff));
243 					qdf_debug("0x%x\t", (tmp & 0x0000ffff));
244 					if (i % 2 == 0)
245 						qdf_debug("\n");
246 				}
247 			}
248 		}
249 	}
250 	HIF_TRACE("%s: X", __func__);
251 }
252 
253 void priv_dump_agc(struct hif_softc *scn)
254 {
255 	int i, len = 30;        /* check this value for Rome and Peregrine */
256 	uint32_t chain0, chain1, chain_mask, val;
257 
258 	if (Q_TARGET_ACCESS_BEGIN(scn) < 0)
259 		return;
260 
261 	chain_mask =
262 		get_target_reg_bits(scn->mem, BB_multichain_enable,
263 				    MULTICHAIN_ENABLE_RX_CHAIN_MASK_MASK);
264 	chain0 = chain_mask & 1;
265 	chain1 = chain_mask & 2;
266 
267 	len = len << 1;         /* each agc item is 64bit, total*2 */
268 	priv_stop_agc(scn);
269 
270 	set_target_reg_bits(scn->mem, BB_chaninfo_ctrl,
271 			CHANINFOMEM_S2_READ_MASK, 0);
272 
273 	HIF_TRACE("%s: AGC history buffer dump: E", __func__);
274 	if (chain0) {
275 		for (i = 0; i < len; i++) {
276 			hif_write32_mb(scn->mem +
277 				PHY_BB_CHN_TABLES_INTF_ADDR,
278 				BB_chaninfo_tab_b0 + i * 4);
279 			val = hif_read32_mb(scn->mem +
280 				PHY_BB_CHN_TABLES_INTF_DATA);
281 			qdf_debug("0x%x\t", val);
282 			if (i % 4 == 0)
283 				qdf_debug("\n");
284 		}
285 	}
286 	if (chain1) {
287 		for (i = 0; i < len; i++) {
288 			hif_write32_mb(scn->mem +
289 				PHY_BB_CHN1_TABLES_INTF_ADDR,
290 				BB_chaninfo_tab_b0 + i * 4);
291 			val = hif_read32_mb(scn->mem +
292 				PHY_BB_CHN1_TABLES_INTF_DATA);
293 			qdf_debug("0x%x\t", val);
294 			if (i % 4 == 0)
295 				qdf_debug("\n");
296 		}
297 	}
298 	HIF_TRACE("%s: AGC history buffer dump X", __func__);
299 	/* restore original value */
300 	hif_write32_mb(scn->mem + BB_gains_min_offsets,
301 		      g_priv_dump_ctx.gain_min_offsets_orig);
302 
303 	Q_TARGET_ACCESS_END(scn);
304 
305 }
306 
307 void priv_dump_bbwatchdog(struct hif_softc *scn)
308 {
309 	uint32_t val;
310 
311 	HIF_TRACE("%s: BB watchdog dump E", __func__);
312 	val = hif_read32_mb(scn->mem + BB_watchdog_status);
313 	qdf_debug("0x%x\t", val);
314 	val = hif_read32_mb(scn->mem + BB_watchdog_ctrl_1);
315 	qdf_debug("0x%x\t", val);
316 	val = hif_read32_mb(scn->mem + BB_watchdog_ctrl_2);
317 	qdf_debug("0x%x\t", val);
318 	val = hif_read32_mb(scn->mem + BB_watchdog_status_B);
319 	qdf_debug("0x%x", val);
320 	HIF_TRACE("%s: BB watchdog dump X", __func__);
321 }
322