rf.c (9427B)
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. 4 * All rights reserved. 5 * 6 * Purpose: rf function code 7 * 8 * Author: Jerry Chen 9 * 10 * Date: Feb. 19, 2004 11 * 12 * Functions: 13 * vnt_rf_write_embedded - Embedded write RF register via MAC 14 * 15 * Revision History: 16 * RF_VT3226: RobertYu:20051111, VT3226C0 and before 17 * RF_VT3226D0: RobertYu:20051228 18 * RF_VT3342A0: RobertYu:20060609 19 * 20 */ 21 22#include <linux/errno.h> 23#include "mac.h" 24#include "rf.h" 25#include "baseband.h" 26#include "usbpipe.h" 27 28#define CB_AL2230_INIT_SEQ 15 29#define CB_AL7230_INIT_SEQ 16 30#define CB_VT3226_INIT_SEQ 11 31#define CB_VT3342_INIT_SEQ 13 32 33static u8 al2230_init_table[CB_AL2230_INIT_SEQ][3] = { 34 {0x03, 0xf7, 0x90}, 35 {0x03, 0x33, 0x31}, 36 {0x01, 0xb8, 0x02}, 37 {0x00, 0xff, 0xf3}, 38 {0x00, 0x05, 0xa4}, 39 {0x0f, 0x4d, 0xc5}, 40 {0x08, 0x05, 0xb6}, 41 {0x01, 0x47, 0xc7}, 42 {0x00, 0x06, 0x88}, 43 {0x04, 0x03, 0xb9}, 44 {0x00, 0xdb, 0xba}, 45 {0x00, 0x09, 0x9b}, 46 {0x0b, 0xdf, 0xfc}, 47 {0x00, 0x00, 0x0d}, 48 {0x00, 0x58, 0x0f} 49}; 50 51static u8 al2230_channel_table0[CB_MAX_CHANNEL_24G][3] = { 52 {0x03, 0xf7, 0x90}, 53 {0x03, 0xf7, 0x90}, 54 {0x03, 0xe7, 0x90}, 55 {0x03, 0xe7, 0x90}, 56 {0x03, 0xf7, 0xa0}, 57 {0x03, 0xf7, 0xa0}, 58 {0x03, 0xe7, 0xa0}, 59 {0x03, 0xe7, 0xa0}, 60 {0x03, 0xf7, 0xb0}, 61 {0x03, 0xf7, 0xb0}, 62 {0x03, 0xe7, 0xb0}, 63 {0x03, 0xe7, 0xb0}, 64 {0x03, 0xf7, 0xc0}, 65 {0x03, 0xe7, 0xc0} 66}; 67 68static u8 al2230_channel_table1[CB_MAX_CHANNEL_24G][3] = { 69 {0x03, 0x33, 0x31}, 70 {0x0b, 0x33, 0x31}, 71 {0x03, 0x33, 0x31}, 72 {0x0b, 0x33, 0x31}, 73 {0x03, 0x33, 0x31}, 74 {0x0b, 0x33, 0x31}, 75 {0x03, 0x33, 0x31}, 76 {0x0b, 0x33, 0x31}, 77 {0x03, 0x33, 0x31}, 78 {0x0b, 0x33, 0x31}, 79 {0x03, 0x33, 0x31}, 80 {0x0b, 0x33, 0x31}, 81 {0x03, 0x33, 0x31}, 82 {0x06, 0x66, 0x61} 83}; 84 85static u8 vt3226_init_table[CB_VT3226_INIT_SEQ][3] = { 86 {0x03, 0xff, 0x80}, 87 {0x02, 0x82, 0xa1}, 88 {0x03, 0xc6, 0xa2}, 89 {0x01, 0x97, 0x93}, 90 {0x03, 0x66, 0x64}, 91 {0x00, 0x61, 0xa5}, 92 {0x01, 0x7b, 0xd6}, 93 {0x00, 0x80, 0x17}, 94 {0x03, 0xf8, 0x08}, 95 {0x00, 0x02, 0x39}, 96 {0x02, 0x00, 0x2a} 97}; 98 99static u8 vt3226d0_init_table[CB_VT3226_INIT_SEQ][3] = { 100 {0x03, 0xff, 0x80}, 101 {0x03, 0x02, 0x21}, 102 {0x03, 0xc6, 0xa2}, 103 {0x01, 0x97, 0x93}, 104 {0x03, 0x66, 0x64}, 105 {0x00, 0x71, 0xa5}, 106 {0x01, 0x15, 0xc6}, 107 {0x01, 0x2e, 0x07}, 108 {0x00, 0x58, 0x08}, 109 {0x00, 0x02, 0x79}, 110 {0x02, 0x01, 0xaa} 111}; 112 113static u8 vt3226_channel_table0[CB_MAX_CHANNEL_24G][3] = { 114 {0x01, 0x97, 0x83}, 115 {0x01, 0x97, 0x83}, 116 {0x01, 0x97, 0x93}, 117 {0x01, 0x97, 0x93}, 118 {0x01, 0x97, 0x93}, 119 {0x01, 0x97, 0x93}, 120 {0x01, 0x97, 0xa3}, 121 {0x01, 0x97, 0xa3}, 122 {0x01, 0x97, 0xa3}, 123 {0x01, 0x97, 0xa3}, 124 {0x01, 0x97, 0xb3}, 125 {0x01, 0x97, 0xb3}, 126 {0x01, 0x97, 0xb3}, 127 {0x03, 0x37, 0xc3} 128}; 129 130static u8 vt3226_channel_table1[CB_MAX_CHANNEL_24G][3] = { 131 {0x02, 0x66, 0x64}, 132 {0x03, 0x66, 0x64}, 133 {0x00, 0x66, 0x64}, 134 {0x01, 0x66, 0x64}, 135 {0x02, 0x66, 0x64}, 136 {0x03, 0x66, 0x64}, 137 {0x00, 0x66, 0x64}, 138 {0x01, 0x66, 0x64}, 139 {0x02, 0x66, 0x64}, 140 {0x03, 0x66, 0x64}, 141 {0x00, 0x66, 0x64}, 142 {0x01, 0x66, 0x64}, 143 {0x02, 0x66, 0x64}, 144 {0x00, 0xcc, 0xc4} 145}; 146 147static const u32 vt3226d0_lo_current_table[CB_MAX_CHANNEL_24G] = { 148 0x0135c600, 149 0x0135c600, 150 0x0235c600, 151 0x0235c600, 152 0x0235c600, 153 0x0335c600, 154 0x0335c600, 155 0x0335c600, 156 0x0335c600, 157 0x0335c600, 158 0x0335c600, 159 0x0335c600, 160 0x0335c600, 161 0x0135c600 162}; 163 164enum { 165 VNT_TABLE_INIT = 0, 166 VNT_TABLE_INIT_2 = 0, 167 VNT_TABLE_0 = 1, 168 VNT_TABLE_1 = 2, 169 VNT_TABLE_2 = 1 170}; 171 172struct vnt_table_info { 173 u8 *addr; 174 int length; 175}; 176 177static const struct vnt_table_info vnt_table_seq[][3] = { 178 { /* RF_AL2230, RF_AL2230S init table, channel table 0 and 1 */ 179 {&al2230_init_table[0][0], CB_AL2230_INIT_SEQ * 3}, 180 {&al2230_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3}, 181 {&al2230_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3} 182 }, { /* RF_VT3226 init table, channel table 0 and 1 */ 183 {&vt3226_init_table[0][0], CB_VT3226_INIT_SEQ * 3}, 184 {&vt3226_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3}, 185 {&vt3226_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3} 186 }, { /* RF_VT3226D0 init table, channel table 0 and 1 */ 187 {&vt3226d0_init_table[0][0], CB_VT3226_INIT_SEQ * 3}, 188 {&vt3226_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3}, 189 {&vt3226_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3} 190 } 191}; 192 193/* 194 * Description: Write to IF/RF, by embedded programming 195 */ 196int vnt_rf_write_embedded(struct vnt_private *priv, u32 data) 197{ 198 u8 reg_data[4]; 199 200 data |= (VNT_RF_REG_LEN << 3) | IFREGCTL_REGW; 201 202 reg_data[0] = (u8)data; 203 reg_data[1] = (u8)(data >> 8); 204 reg_data[2] = (u8)(data >> 16); 205 reg_data[3] = (u8)(data >> 24); 206 207 return vnt_control_out(priv, MESSAGE_TYPE_WRITE_IFRF, 0, 0, 208 ARRAY_SIZE(reg_data), reg_data); 209} 210 211static u8 vnt_rf_addpower(struct vnt_private *priv) 212{ 213 int base; 214 s32 rssi = -priv->current_rssi; 215 216 if (!rssi) 217 return 7; 218 219 if (priv->rf_type == RF_VT3226D0) 220 base = -60; 221 else 222 base = -70; 223 224 if (rssi < base) 225 return ((rssi - base + 1) / -5) * 2 + 5; 226 227 return 0; 228} 229 230/* Set Tx power by power level and rate */ 231static int vnt_rf_set_txpower(struct vnt_private *priv, u8 power, 232 struct ieee80211_channel *ch) 233{ 234 u32 power_setting = 0; 235 int ret = 0; 236 237 power += vnt_rf_addpower(priv); 238 if (power > VNT_RF_MAX_POWER) 239 power = VNT_RF_MAX_POWER; 240 241 if (priv->power == power) 242 return 0; 243 244 priv->power = power; 245 246 switch (priv->rf_type) { 247 case RF_AL2230: 248 power_setting = 0x0404090 | (power << 12); 249 250 ret = vnt_rf_write_embedded(priv, power_setting); 251 if (ret) 252 return ret; 253 254 if (ch->flags & IEEE80211_CHAN_NO_OFDM) 255 ret = vnt_rf_write_embedded(priv, 0x0001b400); 256 else 257 ret = vnt_rf_write_embedded(priv, 0x0005a400); 258 259 break; 260 case RF_AL2230S: 261 power_setting = 0x0404090 | (power << 12); 262 263 ret = vnt_rf_write_embedded(priv, power_setting); 264 if (ret) 265 return ret; 266 267 if (ch->flags & IEEE80211_CHAN_NO_OFDM) { 268 ret = vnt_rf_write_embedded(priv, 0x040c1400); 269 if (ret) 270 return ret; 271 272 ret = vnt_rf_write_embedded(priv, 0x00299b00); 273 } else { 274 ret = vnt_rf_write_embedded(priv, 0x0005a400); 275 if (ret) 276 return ret; 277 278 ret = vnt_rf_write_embedded(priv, 0x00099b00); 279 } 280 281 break; 282 283 case RF_VT3226: 284 power_setting = ((0x3f - power) << 20) | (0x17 << 8); 285 286 ret = vnt_rf_write_embedded(priv, power_setting); 287 break; 288 case RF_VT3226D0: 289 if (ch->flags & IEEE80211_CHAN_NO_OFDM) { 290 u16 hw_value = ch->hw_value; 291 292 power_setting = ((0x3f - power) << 20) | (0xe07 << 8); 293 294 ret = vnt_rf_write_embedded(priv, power_setting); 295 if (ret) 296 return ret; 297 298 ret = vnt_rf_write_embedded(priv, 0x03c6a200); 299 if (ret) 300 return ret; 301 302 dev_dbg(&priv->usb->dev, 303 "%s 11b channel [%d]\n", __func__, hw_value); 304 305 hw_value--; 306 307 if (hw_value < ARRAY_SIZE(vt3226d0_lo_current_table)) { 308 ret = vnt_rf_write_embedded(priv, 309 vt3226d0_lo_current_table[hw_value]); 310 if (ret) 311 return ret; 312 } 313 314 ret = vnt_rf_write_embedded(priv, 0x015C0800); 315 } else { 316 dev_dbg(&priv->usb->dev, 317 "@@@@ %s> 11G mode\n", __func__); 318 319 power_setting = ((0x3f - power) << 20) | (0x7 << 8); 320 321 ret = vnt_rf_write_embedded(priv, power_setting); 322 if (ret) 323 return ret; 324 325 ret = vnt_rf_write_embedded(priv, 0x00C6A200); 326 if (ret) 327 return ret; 328 329 ret = vnt_rf_write_embedded(priv, 0x016BC600); 330 if (ret) 331 return ret; 332 333 ret = vnt_rf_write_embedded(priv, 0x00900800); 334 } 335 336 break; 337 338 default: 339 break; 340 } 341 return ret; 342} 343 344/* Set Tx power by channel number type */ 345int vnt_rf_setpower(struct vnt_private *priv, 346 struct ieee80211_channel *ch) 347{ 348 u16 channel; 349 u8 power = priv->cck_pwr; 350 351 if (!ch) 352 return -EINVAL; 353 354 /* set channel number to array number */ 355 channel = ch->hw_value - 1; 356 357 if (ch->flags & IEEE80211_CHAN_NO_OFDM) { 358 if (channel < ARRAY_SIZE(priv->cck_pwr_tbl)) 359 power = priv->cck_pwr_tbl[channel]; 360 } else if (ch->band == NL80211_BAND_5GHZ) { 361 /* remove 14 channels to array size */ 362 channel -= 14; 363 364 if (channel < ARRAY_SIZE(priv->ofdm_a_pwr_tbl)) 365 power = priv->ofdm_a_pwr_tbl[channel]; 366 } else { 367 if (channel < ARRAY_SIZE(priv->ofdm_pwr_tbl)) 368 power = priv->ofdm_pwr_tbl[channel]; 369 } 370 371 return vnt_rf_set_txpower(priv, power, ch); 372} 373 374/* Convert rssi to dbm */ 375void vnt_rf_rssi_to_dbm(struct vnt_private *priv, u8 rssi, long *dbm) 376{ 377 u8 idx = ((rssi & 0xc0) >> 6) & 0x03; 378 long b = rssi & 0x3f; 379 long a = 0; 380 u8 airoharf[4] = {0, 18, 0, 40}; 381 382 switch (priv->rf_type) { 383 case RF_AL2230: 384 case RF_AL2230S: 385 case RF_VT3226: 386 case RF_VT3226D0: 387 a = airoharf[idx]; 388 break; 389 default: 390 break; 391 } 392 393 *dbm = -1 * (a + b * 2); 394} 395 396int vnt_rf_table_download(struct vnt_private *priv) 397{ 398 int ret; 399 int idx = -1; 400 const struct vnt_table_info *table_seq; 401 402 switch (priv->rf_type) { 403 case RF_AL2230: 404 case RF_AL2230S: 405 idx = 0; 406 break; 407 case RF_VT3226: 408 idx = 1; 409 break; 410 case RF_VT3226D0: 411 idx = 2; 412 break; 413 } 414 415 if (idx < 0) 416 return 0; 417 418 table_seq = &vnt_table_seq[idx][0]; 419 420 /* Init Table */ 421 ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0, 422 MESSAGE_REQUEST_RF_INIT, 423 table_seq[VNT_TABLE_INIT].length, 424 table_seq[VNT_TABLE_INIT].addr); 425 if (ret) 426 return ret; 427 428 /* Channel Table 0 */ 429 ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE, 430 MESSAGE_REQUEST_RF_CH0, 431 table_seq[VNT_TABLE_0].length, 432 table_seq[VNT_TABLE_0].addr); 433 if (ret) 434 return ret; 435 436 /* Channel Table 1 */ 437 ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE, 438 MESSAGE_REQUEST_RF_CH1, 439 table_seq[VNT_TABLE_1].length, 440 table_seq[VNT_TABLE_1].addr); 441 442 return ret; 443}