1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2003-2014, 2018-2020 Intel Corporation 4 * Copyright (C) 2015-2016 Intel Deutschland GmbH 5 */ 6 #include <linux/delay.h> 7 #include <linux/device.h> 8 #include <linux/export.h> 9 10 #include "iwl-drv.h" 11 #include "iwl-io.h" 12 #include "iwl-csr.h" 13 #include "iwl-debug.h" 14 #include "iwl-prph.h" 15 #include "iwl-fh.h" 16 17 void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) 18 { 19 trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val); 20 iwl_trans_write8(trans, ofs, val); 21 } 22 IWL_EXPORT_SYMBOL(iwl_write8); 23 24 void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val) 25 { 26 trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val); 27 iwl_trans_write32(trans, ofs, val); 28 } 29 IWL_EXPORT_SYMBOL(iwl_write32); 30 31 void iwl_write64(struct iwl_trans *trans, u64 ofs, u64 val) 32 { 33 trace_iwlwifi_dev_iowrite64(trans->dev, ofs, val); 34 iwl_trans_write32(trans, ofs, lower_32_bits(val)); 35 iwl_trans_write32(trans, ofs + 4, upper_32_bits(val)); 36 } 37 IWL_EXPORT_SYMBOL(iwl_write64); 38 39 u32 iwl_read32(struct iwl_trans *trans, u32 ofs) 40 { 41 u32 val = iwl_trans_read32(trans, ofs); 42 43 trace_iwlwifi_dev_ioread32(trans->dev, ofs, val); 44 return val; 45 } 46 IWL_EXPORT_SYMBOL(iwl_read32); 47 48 #define IWL_POLL_INTERVAL 10 /* microseconds */ 49 50 int iwl_poll_bit(struct iwl_trans *trans, u32 addr, 51 u32 bits, u32 mask, int timeout) 52 { 53 int t = 0; 54 55 do { 56 if ((iwl_read32(trans, addr) & mask) == (bits & mask)) 57 return t; 58 udelay(IWL_POLL_INTERVAL); 59 t += IWL_POLL_INTERVAL; 60 } while (t < timeout); 61 62 return -ETIMEDOUT; 63 } 64 IWL_EXPORT_SYMBOL(iwl_poll_bit); 65 66 u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) 67 { 68 u32 value = 0x5a5a5a5a; 69 unsigned long flags; 70 if (iwl_trans_grab_nic_access(trans, &flags)) { 71 value = iwl_read32(trans, reg); 72 iwl_trans_release_nic_access(trans, &flags); 73 } 74 75 return value; 76 } 77 IWL_EXPORT_SYMBOL(iwl_read_direct32); 78 79 void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) 80 { 81 unsigned long flags; 82 83 if (iwl_trans_grab_nic_access(trans, &flags)) { 84 iwl_write32(trans, reg, value); 85 iwl_trans_release_nic_access(trans, &flags); 86 } 87 } 88 IWL_EXPORT_SYMBOL(iwl_write_direct32); 89 90 void iwl_write_direct64(struct iwl_trans *trans, u64 reg, u64 value) 91 { 92 unsigned long flags; 93 94 if (iwl_trans_grab_nic_access(trans, &flags)) { 95 iwl_write64(trans, reg, value); 96 iwl_trans_release_nic_access(trans, &flags); 97 } 98 } 99 IWL_EXPORT_SYMBOL(iwl_write_direct64); 100 101 int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, 102 int timeout) 103 { 104 int t = 0; 105 106 do { 107 if ((iwl_read_direct32(trans, addr) & mask) == mask) 108 return t; 109 udelay(IWL_POLL_INTERVAL); 110 t += IWL_POLL_INTERVAL; 111 } while (t < timeout); 112 113 return -ETIMEDOUT; 114 } 115 IWL_EXPORT_SYMBOL(iwl_poll_direct_bit); 116 117 u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs) 118 { 119 u32 val = iwl_trans_read_prph(trans, ofs); 120 trace_iwlwifi_dev_ioread_prph32(trans->dev, ofs, val); 121 return val; 122 } 123 IWL_EXPORT_SYMBOL(iwl_read_prph_no_grab); 124 125 void iwl_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val) 126 { 127 trace_iwlwifi_dev_iowrite_prph32(trans->dev, ofs, val); 128 iwl_trans_write_prph(trans, ofs, val); 129 } 130 IWL_EXPORT_SYMBOL(iwl_write_prph_no_grab); 131 132 void iwl_write_prph64_no_grab(struct iwl_trans *trans, u64 ofs, u64 val) 133 { 134 trace_iwlwifi_dev_iowrite_prph64(trans->dev, ofs, val); 135 iwl_write_prph_no_grab(trans, ofs, val & 0xffffffff); 136 iwl_write_prph_no_grab(trans, ofs + 4, val >> 32); 137 } 138 IWL_EXPORT_SYMBOL(iwl_write_prph64_no_grab); 139 140 u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs) 141 { 142 unsigned long flags; 143 u32 val = 0x5a5a5a5a; 144 145 if (iwl_trans_grab_nic_access(trans, &flags)) { 146 val = iwl_read_prph_no_grab(trans, ofs); 147 iwl_trans_release_nic_access(trans, &flags); 148 } 149 return val; 150 } 151 IWL_EXPORT_SYMBOL(iwl_read_prph); 152 153 void iwl_write_prph_delay(struct iwl_trans *trans, u32 ofs, u32 val, u32 delay_ms) 154 { 155 unsigned long flags; 156 157 if (iwl_trans_grab_nic_access(trans, &flags)) { 158 mdelay(delay_ms); 159 iwl_write_prph_no_grab(trans, ofs, val); 160 iwl_trans_release_nic_access(trans, &flags); 161 } 162 } 163 IWL_EXPORT_SYMBOL(iwl_write_prph_delay); 164 165 int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr, 166 u32 bits, u32 mask, int timeout) 167 { 168 int t = 0; 169 170 do { 171 if ((iwl_read_prph(trans, addr) & mask) == (bits & mask)) 172 return t; 173 udelay(IWL_POLL_INTERVAL); 174 t += IWL_POLL_INTERVAL; 175 } while (t < timeout); 176 177 return -ETIMEDOUT; 178 } 179 180 void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) 181 { 182 unsigned long flags; 183 184 if (iwl_trans_grab_nic_access(trans, &flags)) { 185 iwl_write_prph_no_grab(trans, ofs, 186 iwl_read_prph_no_grab(trans, ofs) | 187 mask); 188 iwl_trans_release_nic_access(trans, &flags); 189 } 190 } 191 IWL_EXPORT_SYMBOL(iwl_set_bits_prph); 192 193 void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, 194 u32 bits, u32 mask) 195 { 196 unsigned long flags; 197 198 if (iwl_trans_grab_nic_access(trans, &flags)) { 199 iwl_write_prph_no_grab(trans, ofs, 200 (iwl_read_prph_no_grab(trans, ofs) & 201 mask) | bits); 202 iwl_trans_release_nic_access(trans, &flags); 203 } 204 } 205 IWL_EXPORT_SYMBOL(iwl_set_bits_mask_prph); 206 207 void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) 208 { 209 unsigned long flags; 210 u32 val; 211 212 if (iwl_trans_grab_nic_access(trans, &flags)) { 213 val = iwl_read_prph_no_grab(trans, ofs); 214 iwl_write_prph_no_grab(trans, ofs, (val & ~mask)); 215 iwl_trans_release_nic_access(trans, &flags); 216 } 217 } 218 IWL_EXPORT_SYMBOL(iwl_clear_bits_prph); 219 220 void iwl_force_nmi(struct iwl_trans *trans) 221 { 222 if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000) 223 iwl_write_prph_delay(trans, DEVICE_SET_NMI_REG, 224 DEVICE_SET_NMI_VAL_DRV, 1); 225 else if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) 226 iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER, 227 UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER); 228 else 229 iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6, 230 UREG_DOORBELL_TO_ISR6_NMI_BIT); 231 } 232 IWL_EXPORT_SYMBOL(iwl_force_nmi); 233 234 static const char *get_rfh_string(int cmd) 235 { 236 #define IWL_CMD(x) case x: return #x 237 #define IWL_CMD_MQ(arg, reg, q) { if (arg == reg(q)) return #reg; } 238 239 int i; 240 241 for (i = 0; i < IWL_MAX_RX_HW_QUEUES; i++) { 242 IWL_CMD_MQ(cmd, RFH_Q_FRBDCB_BA_LSB, i); 243 IWL_CMD_MQ(cmd, RFH_Q_FRBDCB_WIDX, i); 244 IWL_CMD_MQ(cmd, RFH_Q_FRBDCB_RIDX, i); 245 IWL_CMD_MQ(cmd, RFH_Q_URBD_STTS_WPTR_LSB, i); 246 } 247 248 switch (cmd) { 249 IWL_CMD(RFH_RXF_DMA_CFG); 250 IWL_CMD(RFH_GEN_CFG); 251 IWL_CMD(RFH_GEN_STATUS); 252 IWL_CMD(FH_TSSR_TX_STATUS_REG); 253 IWL_CMD(FH_TSSR_TX_ERROR_REG); 254 default: 255 return "UNKNOWN"; 256 } 257 #undef IWL_CMD_MQ 258 } 259 260 struct reg { 261 u32 addr; 262 bool is64; 263 }; 264 265 static int iwl_dump_rfh(struct iwl_trans *trans, char **buf) 266 { 267 int i, q; 268 int num_q = trans->num_rx_queues; 269 static const u32 rfh_tbl[] = { 270 RFH_RXF_DMA_CFG, 271 RFH_GEN_CFG, 272 RFH_GEN_STATUS, 273 FH_TSSR_TX_STATUS_REG, 274 FH_TSSR_TX_ERROR_REG, 275 }; 276 static const struct reg rfh_mq_tbl[] = { 277 { RFH_Q0_FRBDCB_BA_LSB, true }, 278 { RFH_Q0_FRBDCB_WIDX, false }, 279 { RFH_Q0_FRBDCB_RIDX, false }, 280 { RFH_Q0_URBD_STTS_WPTR_LSB, true }, 281 }; 282 283 #ifdef CONFIG_IWLWIFI_DEBUGFS 284 if (buf) { 285 int pos = 0; 286 /* 287 * Register (up to 34 for name + 8 blank/q for MQ): 40 chars 288 * Colon + space: 2 characters 289 * 0X%08x: 10 characters 290 * New line: 1 character 291 * Total of 53 characters 292 */ 293 size_t bufsz = ARRAY_SIZE(rfh_tbl) * 53 + 294 ARRAY_SIZE(rfh_mq_tbl) * 53 * num_q + 40; 295 296 *buf = kmalloc(bufsz, GFP_KERNEL); 297 if (!*buf) 298 return -ENOMEM; 299 300 pos += scnprintf(*buf + pos, bufsz - pos, 301 "RFH register values:\n"); 302 303 for (i = 0; i < ARRAY_SIZE(rfh_tbl); i++) 304 pos += scnprintf(*buf + pos, bufsz - pos, 305 "%40s: 0X%08x\n", 306 get_rfh_string(rfh_tbl[i]), 307 iwl_read_prph(trans, rfh_tbl[i])); 308 309 for (i = 0; i < ARRAY_SIZE(rfh_mq_tbl); i++) 310 for (q = 0; q < num_q; q++) { 311 u32 addr = rfh_mq_tbl[i].addr; 312 313 addr += q * (rfh_mq_tbl[i].is64 ? 8 : 4); 314 pos += scnprintf(*buf + pos, bufsz - pos, 315 "%34s(q %2d): 0X%08x\n", 316 get_rfh_string(addr), q, 317 iwl_read_prph(trans, addr)); 318 } 319 320 return pos; 321 } 322 #endif 323 324 IWL_ERR(trans, "RFH register values:\n"); 325 for (i = 0; i < ARRAY_SIZE(rfh_tbl); i++) 326 IWL_ERR(trans, " %34s: 0X%08x\n", 327 get_rfh_string(rfh_tbl[i]), 328 iwl_read_prph(trans, rfh_tbl[i])); 329 330 for (i = 0; i < ARRAY_SIZE(rfh_mq_tbl); i++) 331 for (q = 0; q < num_q; q++) { 332 u32 addr = rfh_mq_tbl[i].addr; 333 334 addr += q * (rfh_mq_tbl[i].is64 ? 8 : 4); 335 IWL_ERR(trans, " %34s(q %d): 0X%08x\n", 336 get_rfh_string(addr), q, 337 iwl_read_prph(trans, addr)); 338 } 339 340 return 0; 341 } 342 343 static const char *get_fh_string(int cmd) 344 { 345 switch (cmd) { 346 IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); 347 IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); 348 IWL_CMD(FH_RSCSR_CHNL0_WPTR); 349 IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); 350 IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); 351 IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); 352 IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); 353 IWL_CMD(FH_TSSR_TX_STATUS_REG); 354 IWL_CMD(FH_TSSR_TX_ERROR_REG); 355 default: 356 return "UNKNOWN"; 357 } 358 #undef IWL_CMD 359 } 360 361 int iwl_dump_fh(struct iwl_trans *trans, char **buf) 362 { 363 int i; 364 static const u32 fh_tbl[] = { 365 FH_RSCSR_CHNL0_STTS_WPTR_REG, 366 FH_RSCSR_CHNL0_RBDCB_BASE_REG, 367 FH_RSCSR_CHNL0_WPTR, 368 FH_MEM_RCSR_CHNL0_CONFIG_REG, 369 FH_MEM_RSSR_SHARED_CTRL_REG, 370 FH_MEM_RSSR_RX_STATUS_REG, 371 FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, 372 FH_TSSR_TX_STATUS_REG, 373 FH_TSSR_TX_ERROR_REG 374 }; 375 376 if (trans->trans_cfg->mq_rx_supported) 377 return iwl_dump_rfh(trans, buf); 378 379 #ifdef CONFIG_IWLWIFI_DEBUGFS 380 if (buf) { 381 int pos = 0; 382 size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; 383 384 *buf = kmalloc(bufsz, GFP_KERNEL); 385 if (!*buf) 386 return -ENOMEM; 387 388 pos += scnprintf(*buf + pos, bufsz - pos, 389 "FH register values:\n"); 390 391 for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) 392 pos += scnprintf(*buf + pos, bufsz - pos, 393 " %34s: 0X%08x\n", 394 get_fh_string(fh_tbl[i]), 395 iwl_read_direct32(trans, fh_tbl[i])); 396 397 return pos; 398 } 399 #endif 400 401 IWL_ERR(trans, "FH register values:\n"); 402 for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) 403 IWL_ERR(trans, " %34s: 0X%08x\n", 404 get_fh_string(fh_tbl[i]), 405 iwl_read_direct32(trans, fh_tbl[i])); 406 407 return 0; 408 } 409 410 int iwl_finish_nic_init(struct iwl_trans *trans, 411 const struct iwl_cfg_trans_params *cfg_trans) 412 { 413 int err; 414 415 if (cfg_trans->bisr_workaround) { 416 /* ensure the TOP FSM isn't still in previous reset */ 417 mdelay(2); 418 } 419 420 /* 421 * Set "initialization complete" bit to move adapter from 422 * D0U* --> D0A* (powered-up active) state. 423 */ 424 iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); 425 426 if (cfg_trans->device_family == IWL_DEVICE_FAMILY_8000) 427 udelay(2); 428 429 /* 430 * Wait for clock stabilization; once stabilized, access to 431 * device-internal resources is supported, e.g. iwl_write_prph() 432 * and accesses to uCode SRAM. 433 */ 434 err = iwl_poll_bit(trans, CSR_GP_CNTRL, 435 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 436 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 437 25000); 438 if (err < 0) 439 IWL_DEBUG_INFO(trans, "Failed to wake NIC\n"); 440 441 if (cfg_trans->bisr_workaround) { 442 /* ensure BISR shift has finished */ 443 udelay(200); 444 } 445 446 return err < 0 ? err : 0; 447 } 448 IWL_EXPORT_SYMBOL(iwl_finish_nic_init); 449