// SPDX-License-Identifier: GPL-2.0-or-later /* ZD1211 USB-WLAN driver for Linux * * Copyright (C) 2005-2007 Ulrich Kunitz <[email protected]> * Copyright (C) 2006-2007 Daniel Drake <[email protected]> */ #include <linux/kernel.h> #include <linux/slab.h> #include "zd_rf.h" #include "zd_usb.h" #include "zd_chip.h" /* This RF programming code is based upon the code found in v2.16.0.0 of the * ZyDAS vendor driver. Unlike other RF's, Ubec publish full technical specs * for this RF on their website, so we're able to understand more than * usual as to what is going on. Thumbs up for Ubec for doing that. */ /* The 3-wire serial interface provides access to 8 write-only registers. * The data format is a 4 bit register address followed by a 20 bit value. */ #define UW2453_REGWRITE(reg, val) … /* For channel tuning, we have to configure registers 1 (synthesizer), 2 (synth * fractional divide ratio) and 3 (VCO config). * * We configure the RF to produce an interrupt when the PLL is locked onto * the configured frequency. During initialization, we run through a variety * of different VCO configurations on channel 1 until we detect a PLL lock. * When this happens, we remember which VCO configuration produced the lock * and use it later. Actually, we use the configuration *after* the one that * produced the lock, which seems odd, but it works. * * If we do not see a PLL lock on any standard VCO config, we fall back on an * autocal configuration, which has a fixed (as opposed to per-channel) VCO * config and different synth values from the standard set (divide ratio * is still shared with the standard set). */ /* The per-channel synth values for all standard VCO configurations. These get * written to register 1. */ static const u8 uw2453_std_synth[] = …; /* This table stores the synthesizer fractional divide ratio for *all* VCO * configurations (both standard and autocal). These get written to register 2. */ static const u16 uw2453_synth_divide[] = …; /* Here is the data for all the standard VCO configurations. We shrink our * table a little by observing that both channels in a consecutive pair share * the same value. We also observe that the high 4 bits ([0:3] in the specs) * are all 'Reserved' and are always set to 0x4 - we chop them off in the data * below. */ #define CHAN_TO_PAIRIDX(a) … #define RF_CHANPAIR(a,b) … static const u16 uw2453_std_vco_cfg[][7] = …; /* The per-channel synth values for autocal. These get written to register 1. */ static const u16 uw2453_autocal_synth[] = …; /* The VCO configuration for autocal (all channels) */ static const u16 UW2453_AUTOCAL_VCO_CFG = …; /* TX gain settings. The array index corresponds to the TX power integration * values found in the EEPROM. The values get written to register 7. */ static u32 uw2453_txgain[] = …; /* RF-specific structure */ struct uw2453_priv { … }; #define UW2453_PRIV(rf) … static int uw2453_synth_set_channel(struct zd_chip *chip, int channel, bool autocal) { … } static int uw2453_write_vco_cfg(struct zd_chip *chip, u16 value) { … } static int uw2453_init_mode(struct zd_chip *chip) { … } static int uw2453_set_tx_gain_level(struct zd_chip *chip, int channel) { … } static int uw2453_init_hw(struct zd_rf *rf) { … } static int uw2453_set_channel(struct zd_rf *rf, u8 channel) { … } static int uw2453_switch_radio_on(struct zd_rf *rf) { … } static int uw2453_switch_radio_off(struct zd_rf *rf) { … } static void uw2453_clear(struct zd_rf *rf) { … } int zd_rf_init_uw2453(struct zd_rf *rf) { … }