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