xref: /wlan-dirver/qca-wifi-host-cmn/hif/src/mp_dev.c (revision 97f44cd39e4ff816eaa1710279d28cf6b9e65ad9)
1 /*
2  * Copyright (c) 2013-2014, 2016-2018, 2020 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(struct hif_softc *scn,
73 				       void __iomem *mem, uint32_t reg,
74 				       uint32_t bitmask, uint32_t val)
75 {
76 	uint32_t value = hif_read32_mb(scn, mem + (reg));
77 	uint32_t shift = 0;
78 
79 	value &= ~(bitmask);
80 	while (!((bitmask >> shift) & 0x01))
81 		shift++;
82 
83 	value |= (((val) << shift) & (bitmask));
84 	hif_write32_mb(scn, mem + (reg), value);
85 }
86 
87 static inline uint32_t get_target_reg_bits(struct hif_softc *scn,
88 					   void __iomem *mem,
89 					   uint32_t reg, uint32_t bitmask)
90 {
91 	uint32_t value = hif_read32_mb(scn, mem + (reg));
92 	uint32_t shift = 0;
93 
94 	while (!((bitmask >> shift) & 0x01))
95 		shift++;
96 
97 	return (value >> shift) & bitmask;
98 }
99 
100 void priv_start_cap_chaninfo(struct hif_softc *scn)
101 {
102 	set_target_reg_bits(scn, scn->mem, BB_chaninfo_ctrl,
103 			    CHANINFO_CTRL_CAPTURE_CHAN_INFO_MASK, 1);
104 }
105 
106 void priv_start_agc(struct hif_softc *scn)
107 {
108 	g_priv_dump_ctx.gain_min_offsets_orig =
109 		hif_read32_mb(scn, scn->mem + BB_gains_min_offsets);
110 	set_target_reg_bits(scn, scn->mem, BB_gains_min_offsets,
111 			    AGC_HISTORY_DUMP_MASK,
112 			    0x0f);
113 }
114 
115 static void priv_stop_agc(struct hif_softc *scn)
116 {
117 	set_target_reg_bits(scn, scn->mem, BB_gains_min_offsets,
118 			    AGC_HISTORY_DUMP_MASK,
119 			    0);
120 }
121 
122 void priv_dump_chaninfo(struct hif_softc *scn)
123 {
124 	uint32_t bw, val;
125 	uint32_t len, i, tmp;
126 	uint32_t chain_mask;
127 	uint32_t chain0, chain1;
128 
129 	chain_mask =
130 		get_target_reg_bits(scn, scn->mem, BB_multichain_enable,
131 				    MULTICHAIN_ENABLE_RX_CHAIN_MASK_MASK);
132 	chain0 = chain_mask & 1;
133 	chain1 = chain_mask & 2;
134 
135 	hif_info("E");
136 	bw = get_target_reg_bits(scn, scn->mem, BB_chaninfo_ctrl,
137 				 CHANINFO_CTRL_CHANINFOMEM_BW_MASK);
138 
139 	if (bw == 0)
140 		len = 53;
141 	else if (bw == 1)
142 		len = 57;
143 	else if (bw == 2)
144 		len = 59 * 2 - 1;
145 	else
146 		len = 60 * 2 + 61 * 2;
147 
148 	/*
149 	 * each tone is 16 bit valid, write to 32bit buffer each.
150 	 * bw==0(legacy20): 53 tones.
151 	 * bw==1(ht/vht20): 57 tones.
152 	 * bw==2(ht/vht40): 59+58 tones.
153 	 * bw==3(vht80): 60*2+61*2 tones.
154 	 */
155 
156 	if (chain0) {
157 		hif_write32_mb(scn, scn->mem + BB_chn_tables_intf_addr,
158 			       0x80003200);
159 	}
160 	if (chain1) {
161 		hif_write32_mb(scn, scn->mem + BB_chn1_tables_intf_addr,
162 			       0x80003200);
163 	}
164 
165 	set_target_reg_bits(scn, scn->mem, BB_chaninfo_ctrl,
166 			    CHANINFOMEM_S2_READ_MASK, 0);
167 
168 	if (chain0) {
169 		if (bw < 2) {
170 			len = (bw == 0) ? 53 : 57;
171 			for (i = 0; i < len; i++) {
172 				val = hif_read32_mb(scn, scn->mem +
173 						    BB_chn_tables_intf_data) &
174 					0x0000ffff;
175 				qdf_debug("0x%x\t", val);
176 				if (i % 4 == 0)
177 					qdf_debug("\n");
178 			}
179 		} else {
180 			len = (bw == 2) ? 59 : 60;
181 			for (i = 0; i < len; i++) {
182 				tmp = hif_read32_mb(scn, 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, scn->mem +
192 					      BB_chn_tables_intf_addr,
193 					      0x80003300);
194 				len = 61;
195 				for (i = 0; i < len; i++) {
196 					tmp = hif_read32_mb(scn, scn->mem +
197 						BB_chn_tables_intf_data);
198 					qdf_debug("0x%x\t",
199 					       ((tmp >> 16) & 0x0000ffff));
200 					qdf_debug("0x%x\t", (tmp & 0x0000ffff));
201 					if (i % 2 == 0)
202 						qdf_debug("\n");
203 				}
204 			}
205 		}
206 	}
207 	if (chain1) {
208 		if (bw < 2) {
209 			len = (bw == 0) ? 53 : 57;
210 			for (i = 0; i < len; i++) {
211 				val =
212 					hif_read32_mb(scn, scn->mem +
213 						BB_chn1_tables_intf_data) &
214 					0x0000ffff;
215 				qdf_debug("0x%x\t", val);
216 				if (i % 4 == 0)
217 					qdf_debug("\n");
218 			}
219 		} else {
220 			len = (bw == 2) ? 59 : 60;
221 			for (i = 0; i < len; i++) {
222 				tmp =
223 					hif_read32_mb(scn, scn->mem +
224 						     BB_chn1_tables_intf_data);
225 				qdf_debug("0x%x", (tmp >> 16) & 0x0000ffff);
226 				qdf_debug("0x%x", tmp & 0x0000ffff);
227 				if (i % 2 == 0)
228 					qdf_debug("\n");
229 			}
230 			if (bw > 2) {
231 				/* bw == 3 for vht80 */
232 				hif_write32_mb(scn, scn->mem +
233 					      BB_chn1_tables_intf_addr,
234 					      0x80003300);
235 				len = 61;
236 				for (i = 0; i < len; i++) {
237 					tmp =
238 						hif_read32_mb(scn, scn->mem +
239 						     BB_chn1_tables_intf_data);
240 					qdf_debug("0x%x\t",
241 					       ((tmp >> 16) & 0x0000ffff));
242 					qdf_debug("0x%x\t", (tmp & 0x0000ffff));
243 					if (i % 2 == 0)
244 						qdf_debug("\n");
245 				}
246 			}
247 		}
248 	}
249 	hif_info("X");
250 }
251 
252 void priv_dump_agc(struct hif_softc *scn)
253 {
254 	int i, len = 30;        /* check this value for Rome and Peregrine */
255 	uint32_t chain0, chain1, chain_mask, val;
256 
257 	if (Q_TARGET_ACCESS_BEGIN(scn) < 0)
258 		return;
259 
260 	chain_mask =
261 		get_target_reg_bits(scn, scn->mem, BB_multichain_enable,
262 				    MULTICHAIN_ENABLE_RX_CHAIN_MASK_MASK);
263 	chain0 = chain_mask & 1;
264 	chain1 = chain_mask & 2;
265 
266 	len = len << 1;         /* each agc item is 64bit, total*2 */
267 	priv_stop_agc(scn);
268 
269 	set_target_reg_bits(scn, scn->mem, BB_chaninfo_ctrl,
270 			    CHANINFOMEM_S2_READ_MASK, 0);
271 
272 	hif_info("AGC history buffer dump: E");
273 	if (chain0) {
274 		for (i = 0; i < len; i++) {
275 			hif_write32_mb(scn, scn->mem +
276 				PHY_BB_CHN_TABLES_INTF_ADDR,
277 				BB_chaninfo_tab_b0 + i * 4);
278 			val = hif_read32_mb(scn, scn->mem +
279 				PHY_BB_CHN_TABLES_INTF_DATA);
280 			qdf_debug("0x%x\t", val);
281 			if (i % 4 == 0)
282 				qdf_debug("\n");
283 		}
284 	}
285 	if (chain1) {
286 		for (i = 0; i < len; i++) {
287 			hif_write32_mb(scn, scn->mem +
288 				PHY_BB_CHN1_TABLES_INTF_ADDR,
289 				BB_chaninfo_tab_b0 + i * 4);
290 			val = hif_read32_mb(scn, scn->mem +
291 				PHY_BB_CHN1_TABLES_INTF_DATA);
292 			qdf_debug("0x%x\t", val);
293 			if (i % 4 == 0)
294 				qdf_debug("\n");
295 		}
296 	}
297 	hif_info("AGC history buffer dump X");
298 	/* restore original value */
299 	hif_write32_mb(scn, scn->mem + BB_gains_min_offsets,
300 		       g_priv_dump_ctx.gain_min_offsets_orig);
301 
302 	Q_TARGET_ACCESS_END(scn);
303 
304 }
305 
306 void priv_dump_bbwatchdog(struct hif_softc *scn)
307 {
308 	uint32_t val;
309 
310 	hif_info("BB watchdog dump E");
311 	val = hif_read32_mb(scn, scn->mem + BB_watchdog_status);
312 	qdf_debug("0x%x\t", val);
313 	val = hif_read32_mb(scn, scn->mem + BB_watchdog_ctrl_1);
314 	qdf_debug("0x%x\t", val);
315 	val = hif_read32_mb(scn, scn->mem + BB_watchdog_ctrl_2);
316 	qdf_debug("0x%x\t", val);
317 	val = hif_read32_mb(scn, scn->mem + BB_watchdog_status_B);
318 	qdf_debug("0x%x", val);
319 	hif_info("BB watchdog dump X");
320 }
321