1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. 4 * All rights reserved. 5 * 6 * Purpose: Provide functions to setup NIC operation mode 7 * Functions: 8 * vnt_set_rspinf - Set RSPINF 9 * vnt_update_ifs - Update slotTime,SIFS,DIFS, and EIFS 10 * vnt_update_top_rates - Update BasicTopRate 11 * vnt_add_basic_rate - Add to BasicRateSet 12 * vnt_ofdm_min_rate - Check if any OFDM rate is in BasicRateSet 13 * vnt_get_tsf_offset - Calculate TSFOffset 14 * vnt_get_next_tbtt - Calculate Next Beacon TSF counter 15 * vnt_reset_next_tbtt - Set NIC Beacon time 16 * vnt_update_next_tbtt - Sync. NIC Beacon time 17 * vnt_radio_power_off - Turn Off NIC Radio Power 18 * vnt_radio_power_on - Turn On NIC Radio Power 19 * 20 * Revision History: 21 * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. 22 * 08-26-2003 Kyle Hsu: Modify the definition type of dwIoBase. 23 * 09-01-2003 Bryan YC Fan: Add vnt_update_ifs(). 24 * 25 */ 26 27 #include <linux/bitops.h> 28 #include <linux/errno.h> 29 #include "device.h" 30 #include "card.h" 31 #include "baseband.h" 32 #include "mac.h" 33 #include "desc.h" 34 #include "rf.h" 35 #include "power.h" 36 #include "key.h" 37 #include "usbpipe.h" 38 39 /* const u16 cw_rxbcntsf_off[MAX_RATE] = 40 * {17, 34, 96, 192, 34, 23, 17, 11, 8, 5, 4, 3}; 41 */ 42 43 static const u16 cw_rxbcntsf_off[MAX_RATE] = { 44 192, 96, 34, 17, 34, 23, 17, 11, 8, 5, 4, 3 45 }; 46 47 int vnt_set_channel(struct vnt_private *priv, u32 connection_channel) 48 { 49 int ret; 50 51 if (connection_channel > CB_MAX_CHANNEL || !connection_channel) 52 return -EINVAL; 53 54 /* clear NAV */ 55 vnt_mac_reg_bits_on(priv, MAC_REG_MACCR, MACCR_CLRNAV); 56 57 /* Set Channel[7] = 0 to tell H/W channel is changing now. */ 58 vnt_mac_reg_bits_off(priv, MAC_REG_CHANNEL, 59 (BIT(7) | BIT(5) | BIT(4))); 60 61 ret = vnt_control_out(priv, MESSAGE_TYPE_SELECT_CHANNEL, 62 connection_channel, 0, 0, NULL); 63 if (ret) 64 return ret; 65 66 return vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG, MAC_REG_CHANNEL, 67 (u8)(connection_channel | 0x80)); 68 } 69 70 static const u8 vnt_rspinf_b_short_table[] = { 71 0x70, 0x00, 0x00, 0x00, 0x38, 0x00, 0x09, 0x00, 72 0x15, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0b, 0x80 73 }; 74 75 static const u8 vnt_rspinf_b_long_table[] = { 76 0x70, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 77 0x15, 0x00, 0x02, 0x00, 0x0b, 0x00, 0x03, 0x80 78 }; 79 80 static const u8 vnt_rspinf_a_table[] = { 81 0x9b, 0x18, 0x9f, 0x10, 0x9a, 0x0a, 0x9e, 0x08, 0x99, 82 0x08, 0x9d, 0x04, 0x98, 0x04, 0x9c, 0x04, 0x9c, 0x04 83 }; 84 85 static const u8 vnt_rspinf_gb_table[] = { 86 0x8b, 0x1e, 0x8f, 0x16, 0x8a, 0x12, 0x8e, 0x0e, 0x89, 87 0x0e, 0x8d, 0x0a, 0x88, 0x0a, 0x8c, 0x0a, 0x8c, 0x0a 88 }; 89 90 int vnt_set_rspinf(struct vnt_private *priv, u8 bb_type) 91 { 92 const u8 *data; 93 u16 len; 94 int ret; 95 96 if (priv->preamble_type) { 97 data = vnt_rspinf_b_short_table; 98 len = ARRAY_SIZE(vnt_rspinf_b_short_table); 99 } else { 100 data = vnt_rspinf_b_long_table; 101 len = ARRAY_SIZE(vnt_rspinf_b_long_table); 102 } 103 104 /* RSPINF_b_1 to RSPINF_b_11 */ 105 ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_RSPINF_B_1, 106 MESSAGE_REQUEST_MACREG, len, data); 107 if (ret) 108 return ret; 109 110 if (bb_type == BB_TYPE_11A) { 111 data = vnt_rspinf_a_table; 112 len = ARRAY_SIZE(vnt_rspinf_a_table); 113 } else { 114 data = vnt_rspinf_gb_table; 115 len = ARRAY_SIZE(vnt_rspinf_gb_table); 116 } 117 118 /* RSPINF_a_6 to RSPINF_a_72 */ 119 return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_RSPINF_A_6, 120 MESSAGE_REQUEST_MACREG, len, data); 121 } 122 123 int vnt_update_ifs(struct vnt_private *priv) 124 { 125 u8 max_min = 0; 126 u8 data[4]; 127 int ret; 128 129 if (priv->packet_type == PK_TYPE_11A) { 130 priv->slot = C_SLOT_SHORT; 131 priv->sifs = C_SIFS_A; 132 priv->difs = C_SIFS_A + 2 * C_SLOT_SHORT; 133 max_min = 4; 134 } else { 135 priv->sifs = C_SIFS_BG; 136 137 if (priv->short_slot_time) { 138 priv->slot = C_SLOT_SHORT; 139 max_min = 4; 140 } else { 141 priv->slot = C_SLOT_LONG; 142 max_min = 5; 143 } 144 145 priv->difs = C_SIFS_BG + 2 * priv->slot; 146 } 147 148 priv->eifs = C_EIFS; 149 150 data[0] = (u8)priv->sifs; 151 data[1] = (u8)priv->difs; 152 data[2] = (u8)priv->eifs; 153 data[3] = (u8)priv->slot; 154 155 ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_SIFS, 156 MESSAGE_REQUEST_MACREG, 4, &data[0]); 157 if (ret) 158 return ret; 159 160 max_min |= 0xa0; 161 162 return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_CWMAXMIN0, 163 MESSAGE_REQUEST_MACREG, 1, &max_min); 164 } 165 166 void vnt_update_top_rates(struct vnt_private *priv) 167 { 168 int pos; 169 170 pos = fls(priv->basic_rates & GENMASK(RATE_54M, RATE_6M)); 171 priv->top_ofdm_basic_rate = pos ? (pos - 1) : RATE_24M; 172 173 pos = fls(priv->basic_rates & GENMASK(RATE_11M, RATE_1M)); 174 priv->top_cck_basic_rate = pos ? (pos - 1) : RATE_1M; 175 } 176 177 bool vnt_ofdm_min_rate(struct vnt_private *priv) 178 { 179 return priv->basic_rates & GENMASK(RATE_54M, RATE_6M) ? true : false; 180 } 181 182 u8 vnt_get_pkt_type(struct vnt_private *priv) 183 { 184 if (priv->bb_type == BB_TYPE_11A || priv->bb_type == BB_TYPE_11B) 185 return (u8)priv->bb_type; 186 else if (vnt_ofdm_min_rate(priv)) 187 return PK_TYPE_11GA; 188 return PK_TYPE_11GB; 189 } 190 191 /* 192 * Description: Calculate TSF offset of two TSF input 193 * Get TSF Offset from RxBCN's TSF and local TSF 194 * 195 * Parameters: 196 * In: 197 * rx_rate - rx rate. 198 * tsf1 - Rx BCN's TSF 199 * tsf2 - Local TSF 200 * Out: 201 * none 202 * 203 * Return Value: TSF Offset value 204 * 205 */ 206 u64 vnt_get_tsf_offset(u8 rx_rate, u64 tsf1, u64 tsf2) 207 { 208 return tsf1 - tsf2 - (u64)cw_rxbcntsf_off[rx_rate % MAX_RATE]; 209 } 210 211 int vnt_adjust_tsf(struct vnt_private *priv, u8 rx_rate, 212 u64 time_stamp, u64 local_tsf) 213 { 214 u64 tsf_offset = 0; 215 u8 data[8]; 216 217 tsf_offset = vnt_get_tsf_offset(rx_rate, time_stamp, local_tsf); 218 219 data[0] = (u8)tsf_offset; 220 data[1] = (u8)(tsf_offset >> 8); 221 data[2] = (u8)(tsf_offset >> 16); 222 data[3] = (u8)(tsf_offset >> 24); 223 data[4] = (u8)(tsf_offset >> 32); 224 data[5] = (u8)(tsf_offset >> 40); 225 data[6] = (u8)(tsf_offset >> 48); 226 data[7] = (u8)(tsf_offset >> 56); 227 228 return vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT, 229 MESSAGE_REQUEST_TSF, 0, 8, data); 230 } 231 232 /* 233 * Description: Clear NIC TSF counter 234 * Clear local TSF counter 235 * 236 * Parameters: 237 * In: 238 * priv - The adapter to be read 239 * 240 * Return Value: true if success; otherwise false 241 * 242 */ 243 bool vnt_clear_current_tsf(struct vnt_private *priv) 244 { 245 vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); 246 247 priv->current_tsf = 0; 248 249 return true; 250 } 251 252 /* 253 * Description: Read NIC TSF counter 254 * Get NEXTTBTT from adjusted TSF and Beacon Interval 255 * 256 * Parameters: 257 * In: 258 * tsf - Current TSF counter 259 * beacon_interval - Beacon Interval 260 * Out: 261 * tsf - Current TSF counter 262 * 263 * Return Value: TSF value of next Beacon 264 * 265 */ 266 u64 vnt_get_next_tbtt(u64 tsf, u16 beacon_interval) 267 { 268 u32 beacon_int; 269 270 beacon_int = beacon_interval * 1024; 271 272 /* Next TBTT = 273 * ((local_current_TSF / beacon_interval) + 1) * beacon_interval 274 */ 275 if (beacon_int) { 276 do_div(tsf, beacon_int); 277 tsf += 1; 278 tsf *= beacon_int; 279 } 280 281 return tsf; 282 } 283 284 int vnt_reset_next_tbtt(struct vnt_private *priv, u16 beacon_interval) 285 { 286 u64 next_tbtt = 0; 287 u8 data[8]; 288 289 vnt_clear_current_tsf(priv); 290 291 next_tbtt = vnt_get_next_tbtt(next_tbtt, beacon_interval); 292 293 data[0] = (u8)next_tbtt; 294 data[1] = (u8)(next_tbtt >> 8); 295 data[2] = (u8)(next_tbtt >> 16); 296 data[3] = (u8)(next_tbtt >> 24); 297 data[4] = (u8)(next_tbtt >> 32); 298 data[5] = (u8)(next_tbtt >> 40); 299 data[6] = (u8)(next_tbtt >> 48); 300 data[7] = (u8)(next_tbtt >> 56); 301 302 return vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT, 303 MESSAGE_REQUEST_TBTT, 0, 8, data); 304 } 305 306 int vnt_update_next_tbtt(struct vnt_private *priv, u64 tsf, 307 u16 beacon_interval) 308 { 309 u8 data[8]; 310 int ret; 311 312 tsf = vnt_get_next_tbtt(tsf, beacon_interval); 313 314 data[0] = (u8)tsf; 315 data[1] = (u8)(tsf >> 8); 316 data[2] = (u8)(tsf >> 16); 317 data[3] = (u8)(tsf >> 24); 318 data[4] = (u8)(tsf >> 32); 319 data[5] = (u8)(tsf >> 40); 320 data[6] = (u8)(tsf >> 48); 321 data[7] = (u8)(tsf >> 56); 322 323 ret = vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT, 324 MESSAGE_REQUEST_TBTT, 0, 8, data); 325 if (ret) 326 return ret; 327 328 dev_dbg(&priv->usb->dev, "%s TBTT: %8llx\n", __func__, tsf); 329 return 0; 330 } 331 332 /* 333 * Description: Turn off Radio power 334 * 335 * Parameters: 336 * In: 337 * priv - The adapter to be turned off 338 * Out: 339 * none 340 * 341 * Return Value: true if success; otherwise false 342 * 343 */ 344 int vnt_radio_power_off(struct vnt_private *priv) 345 { 346 int ret = 0; 347 348 switch (priv->rf_type) { 349 case RF_AL2230: 350 case RF_AL2230S: 351 case RF_VT3226: 352 case RF_VT3226D0: 353 ret = vnt_mac_reg_bits_off(priv, MAC_REG_SOFTPWRCTL, 354 (SOFTPWRCTL_SWPE2 | 355 SOFTPWRCTL_SWPE3)); 356 break; 357 } 358 359 if (ret) 360 goto end; 361 362 ret = vnt_mac_reg_bits_off(priv, MAC_REG_HOSTCR, HOSTCR_RXON); 363 if (ret) 364 goto end; 365 366 ret = vnt_set_deep_sleep(priv); 367 if (ret) 368 goto end; 369 370 ret = vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL1, GPIO3_INTMD); 371 372 end: 373 return ret; 374 } 375 376 /* 377 * Description: Turn on Radio power 378 * 379 * Parameters: 380 * In: 381 * priv - The adapter to be turned on 382 * Out: 383 * none 384 * 385 * Return Value: true if success; otherwise false 386 * 387 */ 388 int vnt_radio_power_on(struct vnt_private *priv) 389 { 390 int ret = 0; 391 392 ret = vnt_exit_deep_sleep(priv); 393 if (ret) 394 return ret; 395 396 ret = vnt_mac_reg_bits_on(priv, MAC_REG_HOSTCR, HOSTCR_RXON); 397 if (ret) 398 return ret; 399 400 switch (priv->rf_type) { 401 case RF_AL2230: 402 case RF_AL2230S: 403 case RF_VT3226: 404 case RF_VT3226D0: 405 ret = vnt_mac_reg_bits_on(priv, MAC_REG_SOFTPWRCTL, 406 (SOFTPWRCTL_SWPE2 | 407 SOFTPWRCTL_SWPE3)); 408 if (ret) 409 return ret; 410 } 411 412 return vnt_mac_reg_bits_off(priv, MAC_REG_GPIOCTL1, GPIO3_INTMD); 413 } 414 415 int vnt_set_bss_mode(struct vnt_private *priv) 416 { 417 int ret; 418 unsigned char type = priv->bb_type; 419 unsigned char data = 0; 420 unsigned char bb_vga_2_3 = 0x00; 421 422 ret = vnt_mac_set_bb_type(priv, type); 423 if (ret) 424 return ret; 425 426 priv->packet_type = vnt_get_pkt_type(priv); 427 428 if (priv->bb_type == BB_TYPE_11A) { 429 data = 0x03; 430 bb_vga_2_3 = 0x10; 431 } else if (priv->bb_type == BB_TYPE_11B) { 432 data = 0x02; 433 } else if (priv->bb_type == BB_TYPE_11G) { 434 data = 0x08; 435 } 436 437 if (data) { 438 ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 439 0x88, data); 440 if (ret) 441 return ret; 442 } 443 444 ret = vnt_update_ifs(priv); 445 if (ret) 446 return ret; 447 448 ret = vnt_set_rspinf(priv, priv->bb_type); 449 if (ret) 450 return ret; 451 452 priv->bb_vga[2] = bb_vga_2_3; 453 priv->bb_vga[3] = bb_vga_2_3; 454 455 return vnt_set_vga_gain_offset(priv, priv->bb_vga[0]); 456 } 457