zd_rf_uw2453.c (15104B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* ZD1211 USB-WLAN driver for Linux 3 * 4 * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de> 5 * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org> 6 */ 7 8#include <linux/kernel.h> 9#include <linux/slab.h> 10 11#include "zd_rf.h" 12#include "zd_usb.h" 13#include "zd_chip.h" 14 15/* This RF programming code is based upon the code found in v2.16.0.0 of the 16 * ZyDAS vendor driver. Unlike other RF's, Ubec publish full technical specs 17 * for this RF on their website, so we're able to understand more than 18 * usual as to what is going on. Thumbs up for Ubec for doing that. */ 19 20/* The 3-wire serial interface provides access to 8 write-only registers. 21 * The data format is a 4 bit register address followed by a 20 bit value. */ 22#define UW2453_REGWRITE(reg, val) ((((reg) & 0xf) << 20) | ((val) & 0xfffff)) 23 24/* For channel tuning, we have to configure registers 1 (synthesizer), 2 (synth 25 * fractional divide ratio) and 3 (VCO config). 26 * 27 * We configure the RF to produce an interrupt when the PLL is locked onto 28 * the configured frequency. During initialization, we run through a variety 29 * of different VCO configurations on channel 1 until we detect a PLL lock. 30 * When this happens, we remember which VCO configuration produced the lock 31 * and use it later. Actually, we use the configuration *after* the one that 32 * produced the lock, which seems odd, but it works. 33 * 34 * If we do not see a PLL lock on any standard VCO config, we fall back on an 35 * autocal configuration, which has a fixed (as opposed to per-channel) VCO 36 * config and different synth values from the standard set (divide ratio 37 * is still shared with the standard set). */ 38 39/* The per-channel synth values for all standard VCO configurations. These get 40 * written to register 1. */ 41static const u8 uw2453_std_synth[] = { 42 RF_CHANNEL( 1) = 0x47, 43 RF_CHANNEL( 2) = 0x47, 44 RF_CHANNEL( 3) = 0x67, 45 RF_CHANNEL( 4) = 0x67, 46 RF_CHANNEL( 5) = 0x67, 47 RF_CHANNEL( 6) = 0x67, 48 RF_CHANNEL( 7) = 0x57, 49 RF_CHANNEL( 8) = 0x57, 50 RF_CHANNEL( 9) = 0x57, 51 RF_CHANNEL(10) = 0x57, 52 RF_CHANNEL(11) = 0x77, 53 RF_CHANNEL(12) = 0x77, 54 RF_CHANNEL(13) = 0x77, 55 RF_CHANNEL(14) = 0x4f, 56}; 57 58/* This table stores the synthesizer fractional divide ratio for *all* VCO 59 * configurations (both standard and autocal). These get written to register 2. 60 */ 61static const u16 uw2453_synth_divide[] = { 62 RF_CHANNEL( 1) = 0x999, 63 RF_CHANNEL( 2) = 0x99b, 64 RF_CHANNEL( 3) = 0x998, 65 RF_CHANNEL( 4) = 0x99a, 66 RF_CHANNEL( 5) = 0x999, 67 RF_CHANNEL( 6) = 0x99b, 68 RF_CHANNEL( 7) = 0x998, 69 RF_CHANNEL( 8) = 0x99a, 70 RF_CHANNEL( 9) = 0x999, 71 RF_CHANNEL(10) = 0x99b, 72 RF_CHANNEL(11) = 0x998, 73 RF_CHANNEL(12) = 0x99a, 74 RF_CHANNEL(13) = 0x999, 75 RF_CHANNEL(14) = 0xccc, 76}; 77 78/* Here is the data for all the standard VCO configurations. We shrink our 79 * table a little by observing that both channels in a consecutive pair share 80 * the same value. We also observe that the high 4 bits ([0:3] in the specs) 81 * are all 'Reserved' and are always set to 0x4 - we chop them off in the data 82 * below. */ 83#define CHAN_TO_PAIRIDX(a) ((a - 1) / 2) 84#define RF_CHANPAIR(a,b) [CHAN_TO_PAIRIDX(a)] 85static const u16 uw2453_std_vco_cfg[][7] = { 86 { /* table 1 */ 87 RF_CHANPAIR( 1, 2) = 0x664d, 88 RF_CHANPAIR( 3, 4) = 0x604d, 89 RF_CHANPAIR( 5, 6) = 0x6675, 90 RF_CHANPAIR( 7, 8) = 0x6475, 91 RF_CHANPAIR( 9, 10) = 0x6655, 92 RF_CHANPAIR(11, 12) = 0x6455, 93 RF_CHANPAIR(13, 14) = 0x6665, 94 }, 95 { /* table 2 */ 96 RF_CHANPAIR( 1, 2) = 0x666d, 97 RF_CHANPAIR( 3, 4) = 0x606d, 98 RF_CHANPAIR( 5, 6) = 0x664d, 99 RF_CHANPAIR( 7, 8) = 0x644d, 100 RF_CHANPAIR( 9, 10) = 0x6675, 101 RF_CHANPAIR(11, 12) = 0x6475, 102 RF_CHANPAIR(13, 14) = 0x6655, 103 }, 104 { /* table 3 */ 105 RF_CHANPAIR( 1, 2) = 0x665d, 106 RF_CHANPAIR( 3, 4) = 0x605d, 107 RF_CHANPAIR( 5, 6) = 0x666d, 108 RF_CHANPAIR( 7, 8) = 0x646d, 109 RF_CHANPAIR( 9, 10) = 0x664d, 110 RF_CHANPAIR(11, 12) = 0x644d, 111 RF_CHANPAIR(13, 14) = 0x6675, 112 }, 113 { /* table 4 */ 114 RF_CHANPAIR( 1, 2) = 0x667d, 115 RF_CHANPAIR( 3, 4) = 0x607d, 116 RF_CHANPAIR( 5, 6) = 0x665d, 117 RF_CHANPAIR( 7, 8) = 0x645d, 118 RF_CHANPAIR( 9, 10) = 0x666d, 119 RF_CHANPAIR(11, 12) = 0x646d, 120 RF_CHANPAIR(13, 14) = 0x664d, 121 }, 122 { /* table 5 */ 123 RF_CHANPAIR( 1, 2) = 0x6643, 124 RF_CHANPAIR( 3, 4) = 0x6043, 125 RF_CHANPAIR( 5, 6) = 0x667d, 126 RF_CHANPAIR( 7, 8) = 0x647d, 127 RF_CHANPAIR( 9, 10) = 0x665d, 128 RF_CHANPAIR(11, 12) = 0x645d, 129 RF_CHANPAIR(13, 14) = 0x666d, 130 }, 131 { /* table 6 */ 132 RF_CHANPAIR( 1, 2) = 0x6663, 133 RF_CHANPAIR( 3, 4) = 0x6063, 134 RF_CHANPAIR( 5, 6) = 0x6643, 135 RF_CHANPAIR( 7, 8) = 0x6443, 136 RF_CHANPAIR( 9, 10) = 0x667d, 137 RF_CHANPAIR(11, 12) = 0x647d, 138 RF_CHANPAIR(13, 14) = 0x665d, 139 }, 140 { /* table 7 */ 141 RF_CHANPAIR( 1, 2) = 0x6653, 142 RF_CHANPAIR( 3, 4) = 0x6053, 143 RF_CHANPAIR( 5, 6) = 0x6663, 144 RF_CHANPAIR( 7, 8) = 0x6463, 145 RF_CHANPAIR( 9, 10) = 0x6643, 146 RF_CHANPAIR(11, 12) = 0x6443, 147 RF_CHANPAIR(13, 14) = 0x667d, 148 }, 149 { /* table 8 */ 150 RF_CHANPAIR( 1, 2) = 0x6673, 151 RF_CHANPAIR( 3, 4) = 0x6073, 152 RF_CHANPAIR( 5, 6) = 0x6653, 153 RF_CHANPAIR( 7, 8) = 0x6453, 154 RF_CHANPAIR( 9, 10) = 0x6663, 155 RF_CHANPAIR(11, 12) = 0x6463, 156 RF_CHANPAIR(13, 14) = 0x6643, 157 }, 158 { /* table 9 */ 159 RF_CHANPAIR( 1, 2) = 0x664b, 160 RF_CHANPAIR( 3, 4) = 0x604b, 161 RF_CHANPAIR( 5, 6) = 0x6673, 162 RF_CHANPAIR( 7, 8) = 0x6473, 163 RF_CHANPAIR( 9, 10) = 0x6653, 164 RF_CHANPAIR(11, 12) = 0x6453, 165 RF_CHANPAIR(13, 14) = 0x6663, 166 }, 167 { /* table 10 */ 168 RF_CHANPAIR( 1, 2) = 0x666b, 169 RF_CHANPAIR( 3, 4) = 0x606b, 170 RF_CHANPAIR( 5, 6) = 0x664b, 171 RF_CHANPAIR( 7, 8) = 0x644b, 172 RF_CHANPAIR( 9, 10) = 0x6673, 173 RF_CHANPAIR(11, 12) = 0x6473, 174 RF_CHANPAIR(13, 14) = 0x6653, 175 }, 176 { /* table 11 */ 177 RF_CHANPAIR( 1, 2) = 0x665b, 178 RF_CHANPAIR( 3, 4) = 0x605b, 179 RF_CHANPAIR( 5, 6) = 0x666b, 180 RF_CHANPAIR( 7, 8) = 0x646b, 181 RF_CHANPAIR( 9, 10) = 0x664b, 182 RF_CHANPAIR(11, 12) = 0x644b, 183 RF_CHANPAIR(13, 14) = 0x6673, 184 }, 185 186}; 187 188/* The per-channel synth values for autocal. These get written to register 1. */ 189static const u16 uw2453_autocal_synth[] = { 190 RF_CHANNEL( 1) = 0x6847, 191 RF_CHANNEL( 2) = 0x6847, 192 RF_CHANNEL( 3) = 0x6867, 193 RF_CHANNEL( 4) = 0x6867, 194 RF_CHANNEL( 5) = 0x6867, 195 RF_CHANNEL( 6) = 0x6867, 196 RF_CHANNEL( 7) = 0x6857, 197 RF_CHANNEL( 8) = 0x6857, 198 RF_CHANNEL( 9) = 0x6857, 199 RF_CHANNEL(10) = 0x6857, 200 RF_CHANNEL(11) = 0x6877, 201 RF_CHANNEL(12) = 0x6877, 202 RF_CHANNEL(13) = 0x6877, 203 RF_CHANNEL(14) = 0x684f, 204}; 205 206/* The VCO configuration for autocal (all channels) */ 207static const u16 UW2453_AUTOCAL_VCO_CFG = 0x6662; 208 209/* TX gain settings. The array index corresponds to the TX power integration 210 * values found in the EEPROM. The values get written to register 7. */ 211static u32 uw2453_txgain[] = { 212 [0x00] = 0x0e313, 213 [0x01] = 0x0fb13, 214 [0x02] = 0x0e093, 215 [0x03] = 0x0f893, 216 [0x04] = 0x0ea93, 217 [0x05] = 0x1f093, 218 [0x06] = 0x1f493, 219 [0x07] = 0x1f693, 220 [0x08] = 0x1f393, 221 [0x09] = 0x1f35b, 222 [0x0a] = 0x1e6db, 223 [0x0b] = 0x1ff3f, 224 [0x0c] = 0x1ffff, 225 [0x0d] = 0x361d7, 226 [0x0e] = 0x37fbf, 227 [0x0f] = 0x3ff8b, 228 [0x10] = 0x3ff33, 229 [0x11] = 0x3fb3f, 230 [0x12] = 0x3ffff, 231}; 232 233/* RF-specific structure */ 234struct uw2453_priv { 235 /* index into synth/VCO config tables where PLL lock was found 236 * -1 means autocal */ 237 int config; 238}; 239 240#define UW2453_PRIV(rf) ((struct uw2453_priv *) (rf)->priv) 241 242static int uw2453_synth_set_channel(struct zd_chip *chip, int channel, 243 bool autocal) 244{ 245 int r; 246 int idx = channel - 1; 247 u32 val; 248 249 if (autocal) 250 val = UW2453_REGWRITE(1, uw2453_autocal_synth[idx]); 251 else 252 val = UW2453_REGWRITE(1, uw2453_std_synth[idx]); 253 254 r = zd_rfwrite_locked(chip, val, RF_RV_BITS); 255 if (r) 256 return r; 257 258 return zd_rfwrite_locked(chip, 259 UW2453_REGWRITE(2, uw2453_synth_divide[idx]), RF_RV_BITS); 260} 261 262static int uw2453_write_vco_cfg(struct zd_chip *chip, u16 value) 263{ 264 /* vendor driver always sets these upper bits even though the specs say 265 * they are reserved */ 266 u32 val = 0x40000 | value; 267 return zd_rfwrite_locked(chip, UW2453_REGWRITE(3, val), RF_RV_BITS); 268} 269 270static int uw2453_init_mode(struct zd_chip *chip) 271{ 272 static const u32 rv[] = { 273 UW2453_REGWRITE(0, 0x25f98), /* enter IDLE mode */ 274 UW2453_REGWRITE(0, 0x25f9a), /* enter CAL_VCO mode */ 275 UW2453_REGWRITE(0, 0x25f94), /* enter RX/TX mode */ 276 UW2453_REGWRITE(0, 0x27fd4), /* power down RSSI circuit */ 277 }; 278 279 return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS); 280} 281 282static int uw2453_set_tx_gain_level(struct zd_chip *chip, int channel) 283{ 284 u8 int_value = chip->pwr_int_values[channel - 1]; 285 286 if (int_value >= ARRAY_SIZE(uw2453_txgain)) { 287 dev_dbg_f(zd_chip_dev(chip), "can't configure TX gain for " 288 "int value %x on channel %d\n", int_value, channel); 289 return 0; 290 } 291 292 return zd_rfwrite_locked(chip, 293 UW2453_REGWRITE(7, uw2453_txgain[int_value]), RF_RV_BITS); 294} 295 296static int uw2453_init_hw(struct zd_rf *rf) 297{ 298 int i, r; 299 int found_config = -1; 300 u16 intr_status; 301 struct zd_chip *chip = zd_rf_to_chip(rf); 302 303 static const struct zd_ioreq16 ioreqs[] = { 304 { ZD_CR10, 0x89 }, { ZD_CR15, 0x20 }, 305 { ZD_CR17, 0x28 }, /* 6112 no change */ 306 { ZD_CR23, 0x38 }, { ZD_CR24, 0x20 }, { ZD_CR26, 0x93 }, 307 { ZD_CR27, 0x15 }, { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 }, 308 { ZD_CR33, 0x28 }, { ZD_CR34, 0x30 }, 309 { ZD_CR35, 0x43 }, /* 6112 3e->43 */ 310 { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 }, 311 { ZD_CR46, 0x92 }, /* 6112 96->92 */ 312 { ZD_CR47, 0x1e }, 313 { ZD_CR48, 0x04 }, /* 5602 Roger */ 314 { ZD_CR49, 0xfa }, { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, 315 { ZD_CR81, 0x30 }, { ZD_CR87, 0x0a }, { ZD_CR89, 0x04 }, 316 { ZD_CR91, 0x00 }, { ZD_CR92, 0x0a }, { ZD_CR98, 0x8d }, 317 { ZD_CR99, 0x28 }, { ZD_CR100, 0x02 }, 318 { ZD_CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */ 319 { ZD_CR102, 0x27 }, 320 { ZD_CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f 321 * 6221 1f->1c 322 */ 323 { ZD_CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */ 324 { ZD_CR109, 0x13 }, 325 { ZD_CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */ 326 { ZD_CR111, 0x13 }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 }, 327 { ZD_CR114, 0x23 }, /* 6221 27->23 */ 328 { ZD_CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */ 329 { ZD_CR116, 0x24 }, /* 6220 1c->24 */ 330 { ZD_CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */ 331 { ZD_CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */ 332 { ZD_CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */ 333 { ZD_CR120, 0x4f }, 334 { ZD_CR121, 0x1f }, /* 6220 4f->1f */ 335 { ZD_CR122, 0xf0 }, { ZD_CR123, 0x57 }, { ZD_CR125, 0xad }, 336 { ZD_CR126, 0x6c }, { ZD_CR127, 0x03 }, 337 { ZD_CR128, 0x14 }, /* 6302 12->11 */ 338 { ZD_CR129, 0x12 }, /* 6301 10->0f */ 339 { ZD_CR130, 0x10 }, { ZD_CR137, 0x50 }, { ZD_CR138, 0xa8 }, 340 { ZD_CR144, 0xac }, { ZD_CR146, 0x20 }, { ZD_CR252, 0xff }, 341 { ZD_CR253, 0xff }, 342 }; 343 344 static const u32 rv[] = { 345 UW2453_REGWRITE(4, 0x2b), /* configure receiver gain */ 346 UW2453_REGWRITE(5, 0x19e4f), /* configure transmitter gain */ 347 UW2453_REGWRITE(6, 0xf81ad), /* enable RX/TX filter tuning */ 348 UW2453_REGWRITE(7, 0x3fffe), /* disable TX gain in test mode */ 349 350 /* enter CAL_FIL mode, TX gain set by registers, RX gain set by pins, 351 * RSSI circuit powered down, reduced RSSI range */ 352 UW2453_REGWRITE(0, 0x25f9c), /* 5d01 cal_fil */ 353 354 /* synthesizer configuration for channel 1 */ 355 UW2453_REGWRITE(1, 0x47), 356 UW2453_REGWRITE(2, 0x999), 357 358 /* disable manual VCO band selection */ 359 UW2453_REGWRITE(3, 0x7602), 360 361 /* enable manual VCO band selection, configure current level */ 362 UW2453_REGWRITE(3, 0x46063), 363 }; 364 365 r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); 366 if (r) 367 return r; 368 369 r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS); 370 if (r) 371 return r; 372 373 r = uw2453_init_mode(chip); 374 if (r) 375 return r; 376 377 /* Try all standard VCO configuration settings on channel 1 */ 378 for (i = 0; i < ARRAY_SIZE(uw2453_std_vco_cfg) - 1; i++) { 379 /* Configure synthesizer for channel 1 */ 380 r = uw2453_synth_set_channel(chip, 1, false); 381 if (r) 382 return r; 383 384 /* Write VCO config */ 385 r = uw2453_write_vco_cfg(chip, uw2453_std_vco_cfg[i][0]); 386 if (r) 387 return r; 388 389 /* ack interrupt event */ 390 r = zd_iowrite16_locked(chip, 0x0f, UW2453_INTR_REG); 391 if (r) 392 return r; 393 394 /* check interrupt status */ 395 r = zd_ioread16_locked(chip, &intr_status, UW2453_INTR_REG); 396 if (r) 397 return r; 398 399 if (!(intr_status & 0xf)) { 400 dev_dbg_f(zd_chip_dev(chip), 401 "PLL locked on configuration %d\n", i); 402 found_config = i; 403 break; 404 } 405 } 406 407 if (found_config == -1) { 408 /* autocal */ 409 dev_dbg_f(zd_chip_dev(chip), 410 "PLL did not lock, using autocal\n"); 411 412 r = uw2453_synth_set_channel(chip, 1, true); 413 if (r) 414 return r; 415 416 r = uw2453_write_vco_cfg(chip, UW2453_AUTOCAL_VCO_CFG); 417 if (r) 418 return r; 419 } 420 421 /* To match the vendor driver behaviour, we use the configuration after 422 * the one that produced a lock. */ 423 UW2453_PRIV(rf)->config = found_config + 1; 424 425 return zd_iowrite16_locked(chip, 0x06, ZD_CR203); 426} 427 428static int uw2453_set_channel(struct zd_rf *rf, u8 channel) 429{ 430 int r; 431 u16 vco_cfg; 432 int config = UW2453_PRIV(rf)->config; 433 bool autocal = (config == -1); 434 struct zd_chip *chip = zd_rf_to_chip(rf); 435 436 static const struct zd_ioreq16 ioreqs[] = { 437 { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, { ZD_CR79, 0x58 }, 438 { ZD_CR12, 0xf0 }, { ZD_CR77, 0x1b }, { ZD_CR78, 0x58 }, 439 }; 440 441 r = uw2453_synth_set_channel(chip, channel, autocal); 442 if (r) 443 return r; 444 445 if (autocal) 446 vco_cfg = UW2453_AUTOCAL_VCO_CFG; 447 else 448 vco_cfg = uw2453_std_vco_cfg[config][CHAN_TO_PAIRIDX(channel)]; 449 450 r = uw2453_write_vco_cfg(chip, vco_cfg); 451 if (r) 452 return r; 453 454 r = uw2453_init_mode(chip); 455 if (r) 456 return r; 457 458 r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); 459 if (r) 460 return r; 461 462 r = uw2453_set_tx_gain_level(chip, channel); 463 if (r) 464 return r; 465 466 return zd_iowrite16_locked(chip, 0x06, ZD_CR203); 467} 468 469static int uw2453_switch_radio_on(struct zd_rf *rf) 470{ 471 int r; 472 struct zd_chip *chip = zd_rf_to_chip(rf); 473 struct zd_ioreq16 ioreqs[] = { 474 { ZD_CR11, 0x00 }, { ZD_CR251, 0x3f }, 475 }; 476 477 /* enter RXTX mode */ 478 r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f94), RF_RV_BITS); 479 if (r) 480 return r; 481 482 if (zd_chip_is_zd1211b(chip)) 483 ioreqs[1].value = 0x7f; 484 485 return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); 486} 487 488static int uw2453_switch_radio_off(struct zd_rf *rf) 489{ 490 int r; 491 struct zd_chip *chip = zd_rf_to_chip(rf); 492 static const struct zd_ioreq16 ioreqs[] = { 493 { ZD_CR11, 0x04 }, { ZD_CR251, 0x2f }, 494 }; 495 496 /* enter IDLE mode */ 497 /* FIXME: shouldn't we go to SLEEP? sent email to zydas */ 498 r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f90), RF_RV_BITS); 499 if (r) 500 return r; 501 502 return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); 503} 504 505static void uw2453_clear(struct zd_rf *rf) 506{ 507 kfree(rf->priv); 508} 509 510int zd_rf_init_uw2453(struct zd_rf *rf) 511{ 512 rf->init_hw = uw2453_init_hw; 513 rf->set_channel = uw2453_set_channel; 514 rf->switch_radio_on = uw2453_switch_radio_on; 515 rf->switch_radio_off = uw2453_switch_radio_off; 516 rf->patch_6m_band_edge = zd_rf_generic_patch_6m; 517 rf->clear = uw2453_clear; 518 /* we have our own TX integration code */ 519 rf->update_channel_int = 0; 520 521 rf->priv = kmalloc(sizeof(struct uw2453_priv), GFP_KERNEL); 522 if (rf->priv == NULL) 523 return -ENOMEM; 524 525 return 0; 526} 527