Add work-in-progress driver rtw(4) for Realtek RTL8180 MAC/baseband.

Add register definitions for Maxim MAX2820 and Philips SA2400 radio
front-ends.
This commit is contained in:
dyoung 2004-09-26 02:29:15 +00:00
parent d94faebdc7
commit 3e9bdb9662
9 changed files with 5616 additions and 0 deletions

189
sys/dev/ic/max2820reg.h Normal file
View File

@ -0,0 +1,189 @@
/* $NetBSD: max2820reg.h,v 1.1 2004/09/26 02:29:15 dyoung Exp $ */
/*
* Copyright (c) 2004 David Young. All rights reserved.
*
* This code was written by David Young.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David
* Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#ifndef _DEV_IC_MAX2820REG_H_
#define _DEV_IC_MAX2820REG_H_
/*
* Serial bus format for Maxim MAX2820/MAX2820A/MAX2821/MAX2821A
* 2.4GHz 802.11b Zero-IF Transceivers
*/
#define MAX2820_TWI_ADDR_MASK BITS(15,12)
#define MAX2820_TWI_DATA_MASK BITS(11,0)
/*
* Registers for Maxim MAX2820/MAX2820A/MAX2821/MAX2821A 2.4GHz
* 802.11b Zero-IF Transceivers
*/
#define MAX2820_TEST 0 /* Test Register */
#define MAX2820_TEST_DEFAULT BITS(2,0) /* Always set to this value. */
#define MAX2820_ENABLE 1 /* Block-Enable Register */
#define MAX2820_ENABLE_RSVD1 BIT(11) /* reserved */
#define MAX2820_ENABLE_PAB BIT(10) /* Transmit Baseband Filters
* Enable
* PAB_EN = SHDNB &&
* (MAX2820_ENABLE_PAB ||
* TX_ON)
*/
#define MAX2820_ENABLE_TXFLT BIT(9) /* Transmit Baseband Filters
* Enable
* TXFLT_EN = SHDNB &&
* (MAX2820_ENABLE_TXFLT ||
* TX_ON)
*/
#define MAX2820_ENABLE_TXUVD BIT(8) /* Tx Upconverter, VGA, and
* Driver Amp Enable
* TXUVD_EN = SHDNB &&
* (MAX2820_ENABLE_TXUVD ||
* TX_ON)
*/
#define MAX2820_ENABLE_DET BIT(7) /* Receive Detector Enable
* DET_EN = SHDNB &&
* (MAX2820_ENABLE_DET ||
* RX_ON)
*/
#define MAX2820_ENABLE_RXDFA BIT(6) /* Rx Downconverter, Filters,
* and AGC Amps Enable
* RXDFA_EN = SHDNB &&
* (MAX2820_ENABLE_RXDFA ||
* RX_ON)
*/
#define MAX2820_ENABLE_RXLNA BIT(5) /* Receive LNA Enable
* AT_EN = SHDNB &&
* (MAX2820_ENABLE_RXLNA ||
* RX_ON)
*/
#define MAX2820_ENABLE_AT BIT(4) /* Auto-tuner Enable
* AT_EN = SHDNB &&
* (MAX2820_ENABLE_AT ||
* RX_ON || TX_ON)
*/
#define MAX2820_ENABLE_CP BIT(3) /* PLL Charge-Pump Enable
* CP_EN = SHDNB
* && MAX2820_ENABLE_CP
*/
#define MAX2820_ENABLE_PLL BIT(2) /* PLL Enable
* PLL_EN = SHDNB
* && MAX2820_ENABLE_PLL
*/
#define MAX2820_ENABLE_VCO BIT(1) /* VCO Enable
* VCO_EN = SHDNB
* && MAX2820_ENABLE_VCO
*/
#define MAX2820_ENABLE_RSVD0 BIT(0) /* reserved */
#define MAX2820_ENABLE_DEFAULT (MAX2820_ENABLE_AT|MAX2820_ENABLE_CP|\
MAX2820_ENABLE_PLL|MAX2820_ENABLE_VCO)
#define MAX2820_SYNTH 2 /* Synthesizer Register */
#define MAX2820_SYNTH_RSVD0 BITS(11,7) /* reserved */
#define MAX2820_SYNTH_ICP BIT(6) /* Charge-Pump Current Select
* 0 = +/-1mA
* 1 = +/-2mA
*/
#define MAX2820_SYNTH_R_MASK BITS(5,0) /* Reference Frequency Divider
* 0 = 22MHz
* 1 = 44MHz
*/
#define MAX2820_SYNTH_R_22MHZ LSHIFT(0, MAX2820_SYNTH_R_MASK)
#define MAX2820_SYNTH_R_44MHZ LSHIFT(1, MAX2820_SYNTH_R_MASK)
#define MAX2820_SYNTH_ICP_DEFAULT MAX2820_SYNTH_ICP
#define MAX2820_SYNTH_R_DEFAULT LSHIFT(0, MAX2820_SYNTH_R_MASK)
#define MAX2820_CHANNEL 3 /* Channel Frequency Register */
#define MAX2820_CHANNEL_RSVD BITS(11,7) /* reserved */
#define MAX2820_CHANNEL_CF_MASK BITS(6,0) /* Channel Frequency Select
* fLO = 2400MHz + CF * 1MHz
*/
#define MAX2820_CHANNEL_RSVD_DEFAULT LSHIFT(0, MAX2820_CHANNEL_RSVD)
#define MAX2820_CHANNEL_CF_DEFAULT LSHIFT(37, MAX2820_CHANNEL_CF_MASK)
#define MAX2820_RECEIVE 4 /* Receiver Settings Register
* MAX2820/MAX2821
*/
#define MAX2820_RECEIVE_2C_MASK BITS(11,9) /* VGA DC Offset Nulling
* Parameter 2
*/
#define MAX2820_RECEIVE_1C_MASK BITS(8,6) /* VGA DC Offset Nulling
* Parameter 1
*/
#define MAX2820_RECEIVE_DL_MASK BITS(5,4) /* Rx Level Detector Midpoint
* Select
* 11, 01 = 50.2mVp
* 10 = 70.9mVp
* 00 = 35.5mVp
*/
#define MAX2820_RECEIVE_SF BIT(3) /* Special Function Select
* 0 = OFF
* 1 = ON
*/
#define MAX2820_RECEIVE_BW_MASK BITS(2,0) /* Receive Filter -3dB Frequency
* Select (all frequencies are
* approximate)
*/
/* 8.5MHz */
#define MAX2820_RECEIVE_BW_8_5MHZ LSHIFT(0, MAX2820_RECEIVE_BW_MASK)
#define MAX2820_RECEIVE_BW_8MHZ LSHIFT(1, MAX2820_RECEIVE_BW_MASK)
#define MAX2820_RECEIVE_BW_7_5MHZ LSHIFT(2, MAX2820_RECEIVE_BW_MASK)
#define MAX2820_RECEIVE_BW_7MHZ LSHIFT(3, MAX2820_RECEIVE_BW_MASK)
#define MAX2820_RECEIVE_BW_6_5MHZ LSHIFT(4, MAX2820_RECEIVE_BW_MASK)
#define MAX2820_RECEIVE_BW_6MHZ LSHIFT(5, MAX2820_RECEIVE_BW_MASK)
#define MAX2820_RECEIVE_2C_DEFAULT LSHIFT(7, MAX2820_RECEIVE_2C_MASK)
#define MAX2820_RECEIVE_1C_DEFAULT LSHIFT(7, MAX2820_RECEIVE_1C_MASK)
#define MAX2820_RECEIVE_DL_DEFAULT LSHIFT(1, MAX2820_RECEIVE_DL_MASK)
#define MAX2820_RECEIVE_SF_DEFAULT LSHIFT(0, MAX2820_RECEIVE_SF)
#define MAX2820_RECEIVE_BW_DEFAULT MAX2820_RECEIVE_BW_7_5MHZ
#define MAX2820A_RECEIVE 4 /* Receiver Settings Register,
* MAX2820A/MAX2821A
*/
/* VGA DC Offset Nulling Parameter 2 */
#define MAX2820A_RECEIVE_2C_MASK BITS(11,9)
#define MAX2820A_RECEIVE_2C_DEFAULT LSHIFT(7, MAX2820A_RECEIVE_2C_MASK)
/* VGA DC Offset Nulling Parameter 1 */
#define MAX2820A_RECEIVE_1C_MASK BITS(8,6)
#define MAX2820A_RECEIVE_1C_DEFAULT LSHIFT(7, MAX2820A_RECEIVE_1C_MASK)
#define MAX2820A_RECEIVE_RSVD0_MASK BITS(5,3)
#define MAX2820A_RECEIVE_RSVD0_DEFAULT LSHIFT(2, MAX2820A_RECEIVE_RSVD0_MASK)
#define MAX2820A_RECEIVE_RSVD1_MASK BITS(2,0)
#define MAX2820A_RECEIVE_RSVD1_DEFAULT LSHIFT(2,MAX2820_RECEIVE_RSVD1_MASK)
#define MAX2820_TRANSMIT 5 /* Transmitter Settings Reg. */
#define MAX2820_TRANSMIT_RSVD_MASK BITS(11,4) /* reserved */
#define MAX2820_TRANSMIT_PA_MASK BITS(3,0) /* PA Bias Select
* 15 = Highest
* 0 = Lowest
*/
#define MAX2820_TRANSMIT_PA_DEFAULT LSHIFT(0, MAX2820_TRANSMIT_PA_MASK)
#endif /* _DEV_IC_MAX2820REG_H_ */

2630
sys/dev/ic/rtw.c Normal file

File diff suppressed because it is too large Load Diff

624
sys/dev/ic/rtwphy.c Normal file
View File

@ -0,0 +1,624 @@
/* $NetBSD: rtwphy.c,v 1.1 2004/09/26 02:29:15 dyoung Exp $ */
/*-
* Copyright (c) 2004, 2005 David Young. All rights reserved.
*
* Programmed for NetBSD by David Young.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of David Young may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David
* Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
/*
* Control the Philips SA2400 RF front-end and the baseband processor
* built into the Realtek RTL8180.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rtwphy.c,v 1.1 2004/09/26 02:29:15 dyoung Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/types.h>
#include <machine/bus.h>
#include <net/if.h>
#include <net/if_media.h>
#include <net/if_ether.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_compat.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/ic/rtwreg.h>
#include <dev/ic/max2820reg.h>
#include <dev/ic/sa2400reg.h>
#include <dev/ic/rtwvar.h>
#include <dev/ic/rtwphyio.h>
#include <dev/ic/rtwphy.h>
static int rtw_max2820_pwrstate(struct rtw_rf *, enum rtw_pwrstate);
static int rtw_sa2400_pwrstate(struct rtw_rf *, enum rtw_pwrstate);
static int
rtw_bbp_preinit(struct rtw_regs *regs, u_int antatten0, int dflantb,
u_int freq)
{
u_int antatten = antatten0;
if (dflantb)
antatten |= RTW_BBP_ANTATTEN_DFLANTB;
if (freq == 2484) /* channel 14 */
antatten |= RTW_BBP_ANTATTEN_CHAN14;
return rtw_bbp_write(regs, RTW_BBP_ANTATTEN, antatten);
}
static int
rtw_bbp_init(struct rtw_regs *regs, struct rtw_bbpset *bb, int antdiv,
int dflantb, u_int8_t cs_threshold, u_int freq)
{
int rc;
u_int32_t sys2, sys3;
sys2 = bb->bb_sys2;
if (antdiv)
sys2 |= RTW_BBP_SYS2_ANTDIV;
sys3 = bb->bb_sys3 |
LSHIFT(cs_threshold, RTW_BBP_SYS3_CSTHRESH_MASK);
#define RTW_BBP_WRITE_OR_RETURN(reg, val) \
if ((rc = rtw_bbp_write(regs, reg, val)) != 0) \
return rc;
RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS1, bb->bb_sys1);
RTW_BBP_WRITE_OR_RETURN(RTW_BBP_TXAGC, bb->bb_txagc);
RTW_BBP_WRITE_OR_RETURN(RTW_BBP_LNADET, bb->bb_lnadet);
RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCINI, bb->bb_ifagcini);
RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCLIMIT, bb->bb_ifagclimit);
RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCDET, bb->bb_ifagcdet);
if ((rc = rtw_bbp_preinit(regs, bb->bb_antatten, dflantb, freq)) != 0)
return rc;
RTW_BBP_WRITE_OR_RETURN(RTW_BBP_TRL, bb->bb_trl);
RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS2, sys2);
RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS3, sys3);
RTW_BBP_WRITE_OR_RETURN(RTW_BBP_CHESTLIM, bb->bb_chestlim);
RTW_BBP_WRITE_OR_RETURN(RTW_BBP_CHSQLIM, bb->bb_chsqlim);
return 0;
}
static int
rtw_sa2400_txpower(struct rtw_rf *rf, u_int8_t opaque_txpower)
{
struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf;
struct rtw_rfbus *bus = &sa->sa_bus;
return rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_TX,
opaque_txpower);
}
/* make sure we're using the same settings as the reference driver */
static void
verify_syna(u_int freq, u_int32_t val)
{
u_int32_t expected_val = ~val;
switch (freq) {
case 2412:
expected_val = 0x0000096c; /* ch 1 */
break;
case 2417:
expected_val = 0x00080970; /* ch 2 */
break;
case 2422:
expected_val = 0x00100974; /* ch 3 */
break;
case 2427:
expected_val = 0x00180978; /* ch 4 */
break;
case 2432:
expected_val = 0x00000980; /* ch 5 */
break;
case 2437:
expected_val = 0x00080984; /* ch 6 */
break;
case 2442:
expected_val = 0x00100988; /* ch 7 */
break;
case 2447:
expected_val = 0x0018098c; /* ch 8 */
break;
case 2452:
expected_val = 0x00000994; /* ch 9 */
break;
case 2457:
expected_val = 0x00080998; /* ch 10 */
break;
case 2462:
expected_val = 0x0010099c; /* ch 11 */
break;
case 2467:
expected_val = 0x001809a0; /* ch 12 */
break;
case 2472:
expected_val = 0x000009a8; /* ch 13 */
break;
case 2484:
expected_val = 0x000009b4; /* ch 14 */
break;
}
KASSERT(val == expected_val);
}
/* freq is in MHz */
static int
rtw_sa2400_tune(struct rtw_rf *rf, u_int freq)
{
struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf;
struct rtw_rfbus *bus = &sa->sa_bus;
int rc;
u_int32_t syna, synb, sync;
/* XO = 44MHz, R = 11, hence N is in units of XO / R = 4MHz.
*
* The channel spacing (5MHz) is not divisible by 4MHz, so
* we set the fractional part of N to compensate.
*/
int n = freq / 4, nf = (freq % 4) * 2;
syna = LSHIFT(nf, SA2400_SYNA_NF_MASK) | LSHIFT(n, SA2400_SYNA_N_MASK);
verify_syna(freq, syna);
/* Divide the 44MHz crystal down to 4MHz. Set the fractional
* compensation charge pump value to agree with the fractional
* modulus.
*/
synb = LSHIFT(11, SA2400_SYNB_R_MASK) | SA2400_SYNB_L_NORMAL |
SA2400_SYNB_ON | SA2400_SYNB_ONE |
LSHIFT(80, SA2400_SYNB_FC_MASK); /* agrees w/ SA2400_SYNA_FM = 0 */
sync = SA2400_SYNC_CP_NORMAL;
if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_SYNA,
syna)) != 0)
return rc;
if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_SYNB,
synb)) != 0)
return rc;
if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_SYNC,
sync)) != 0)
return rc;
return rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_SYND, 0x0);
}
static int
rtw_sa2400_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power)
{
struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf;
struct rtw_rfbus *bus = &sa->sa_bus;
u_int32_t opmode;
opmode = SA2400_OPMODE_XO;
opmode |= SA2400_OPMODE_RXLV;
opmode |= SA2400_OPMODE_CLK;
opmode |= SA2400_OPMODE_I0P3;
opmode |= LSHIFT(3, SA2400_OPMODE_FILTTUNE_MASK);
switch (power) {
case RTW_ON:
opmode |= SA2400_OPMODE_MODE_TXRX;
break;
case RTW_SLEEP:
opmode |= SA2400_OPMODE_MODE_WAIT;
break;
case RTW_OFF:
opmode |= SA2400_OPMODE_MODE_SLEEP;
break;
}
if (sa->sa_digphy)
opmode |= SA2400_OPMODE_DIGIN;
return rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE,
opmode);
}
static int
rtw_sa2400_manrx_init(struct rtw_sa2400 *sa)
{
u_int32_t manrx;
/* XXX we are not supposed to be in RXMGC mode when we do
* this?
*/
manrx = SA2400_MANRX_AHSN;
manrx |= SA2400_MANRX_TEN;
manrx |= LSHIFT(1023, SA2400_MANRX_RXGAIN_MASK);
return rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_MANRX,
manrx);
}
static int
rtw_sa2400_vcocal_start(struct rtw_sa2400 *sa, int start)
{
u_int32_t opmode;
opmode = SA2400_OPMODE_XO;
opmode |= SA2400_OPMODE_RXLV;
opmode |= SA2400_OPMODE_CLK;
opmode |= SA2400_OPMODE_I0P3;
opmode |= LSHIFT(3, SA2400_OPMODE_FILTTUNE_MASK);
if (start)
opmode |= SA2400_OPMODE_MODE_VCOCALIB;
else
opmode |= SA2400_OPMODE_MODE_SLEEP;
if (sa->sa_digphy)
opmode |= SA2400_OPMODE_DIGIN;
return rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE,
opmode);
}
static int
rtw_sa2400_vco_calibration(struct rtw_sa2400 *sa)
{
int rc;
/* calibrate VCO */
if ((rc = rtw_sa2400_vcocal_start(sa, 1)) != 0)
return rc;
DELAY(2200); /* 2.2 milliseconds */
/* XXX superfluous: SA2400 automatically entered SLEEP mode. */
return rtw_sa2400_vcocal_start(sa, 0);
}
static int
rtw_sa2400_filter_calibration(struct rtw_sa2400 *sa)
{
u_int32_t opmode;
opmode = SA2400_OPMODE_XO;
opmode |= SA2400_OPMODE_RXLV;
opmode |= SA2400_OPMODE_CLK;
opmode |= SA2400_OPMODE_I0P3;
opmode |= LSHIFT(3, SA2400_OPMODE_FILTTUNE_MASK);
opmode |= SA2400_OPMODE_MODE_FCALIB;
if (sa->sa_digphy)
opmode |= SA2400_OPMODE_DIGIN;
return rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE,
opmode);
}
static int
rtw_sa2400_dc_calibration(struct rtw_sa2400 *sa)
{
struct rtw_rf *rf = &sa->sa_rf;
int rc;
u_int32_t dccal;
(*rf->rf_continuous_tx_cb)(rf->rf_continuous_tx_arg, 1);
dccal = SA2400_OPMODE_XO;
dccal |= SA2400_OPMODE_RXLV;
dccal |= SA2400_OPMODE_CLK;
dccal |= SA2400_OPMODE_I0P3;
dccal |= LSHIFT(3, SA2400_OPMODE_FILTTUNE_MASK);
dccal |= SA2400_OPMODE_MODE_TXRX;
rc = rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE,
dccal);
if (rc != 0)
return rc;
DELAY(5); /* DCALIB after being in Tx mode for 5
* microseconds
*/
dccal &= ~SA2400_OPMODE_MODE_MASK;
dccal |= SA2400_OPMODE_MODE_DCALIB;
rc = rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE,
dccal);
if (rc != 0)
return rc;
DELAY(20); /* calibration takes at most 20 microseconds */
(*rf->rf_continuous_tx_cb)(rf->rf_continuous_tx_arg, 0);
return 0;
}
static int
rtw_sa2400_agc_init(struct rtw_sa2400 *sa)
{
u_int32_t agc;
agc = LSHIFT(25, SA2400_AGC_MAXGAIN_MASK);
agc |= LSHIFT(7, SA2400_AGC_BBPDELAY_MASK);
agc |= LSHIFT(15, SA2400_AGC_LNADELAY_MASK);
agc |= LSHIFT(27, SA2400_AGC_RXONDELAY_MASK);
return rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_AGC,
agc);
}
static void
rtw_sa2400_destroy(struct rtw_rf *rf)
{
struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf;
memset(sa, 0, sizeof(*sa));
free(sa, M_DEVBUF);
}
static int
rtw_sa2400_init(struct rtw_rf *rf, u_int freq, u_int8_t opaque_txpower,
enum rtw_pwrstate power)
{
struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf;
int rc;
if ((rc = rtw_sa2400_txpower(rf, opaque_txpower)) != 0)
return rc;
/* skip configuration if it's time to sleep or to power-down. */
if (power == RTW_SLEEP || power == RTW_OFF)
return rtw_sa2400_pwrstate(rf, power);
/* go to sleep for configuration */
if ((rc = rtw_sa2400_pwrstate(rf, RTW_SLEEP)) != 0)
return rc;
if ((rc = rtw_sa2400_agc_init(sa)) != 0)
return rc;
if ((rc = rtw_sa2400_manrx_init(sa)) != 0)
return rc;
/* XXX reference driver calibrates VCO twice. Is it a bug? */
if ((rc = rtw_sa2400_vco_calibration(sa)) != 0)
return rc;
/* VCO calibration erases synthesizer registers */
if ((rc = rtw_sa2400_tune(rf, freq)) != 0)
return rc;
if ((rc = rtw_sa2400_filter_calibration(sa)) != 0)
return rc;
/* analog PHY needs DC calibration */
if (!sa->sa_digphy && (rc = rtw_sa2400_dc_calibration(sa)) != 0)
return rc;
/* enter Tx/Rx mode */
return rtw_sa2400_pwrstate(rf, power);
}
struct rtw_rf *
rtw_sa2400_create(struct rtw_regs *regs, rtw_rf_write_t rf_write, int digphy)
{
struct rtw_sa2400 *sa;
struct rtw_rfbus *bus;
struct rtw_rf *rf;
struct rtw_bbpset *bb;
sa = malloc(sizeof(*sa), M_DEVBUF, M_NOWAIT | M_ZERO);
if (sa == NULL)
return NULL;
sa->sa_digphy = digphy;
rf = &sa->sa_rf;
bus = &sa->sa_bus;
rf->rf_init = rtw_sa2400_init;
rf->rf_destroy = rtw_sa2400_destroy;
rf->rf_txpower = rtw_sa2400_txpower;
rf->rf_tune = rtw_sa2400_tune;
rf->rf_pwrstate = rtw_sa2400_pwrstate;
bb = &rf->rf_bbpset;
/* XXX magic */
bb->bb_antatten = RTW_BBP_ANTATTEN_PHILIPS_MAGIC;
bb->bb_chestlim = 0x00;
bb->bb_chsqlim = 0xa0;
bb->bb_ifagcdet = 0x64;
bb->bb_ifagcini = 0x90;
bb->bb_ifagclimit = 0x1a;
bb->bb_lnadet = 0xe0;
bb->bb_sys1 = 0x98;
bb->bb_sys2 = 0x47;
bb->bb_sys3 = 0x90;
bb->bb_trl = 0x88;
bb->bb_txagc = 0x38;
bus->b_regs = regs;
bus->b_write = rf_write;
return &sa->sa_rf;
}
/* freq is in MHz */
static int
rtw_max2820_tune(struct rtw_rf *rf, u_int freq)
{
struct rtw_max2820 *mx = (struct rtw_max2820 *)rf;
struct rtw_rfbus *bus = &mx->mx_bus;
if (freq < 2400 || freq > 2499)
return -1;
return rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_CHANNEL,
LSHIFT(freq - 2400, MAX2820_CHANNEL_CF_MASK));
}
static void
rtw_max2820_destroy(struct rtw_rf *rf)
{
struct rtw_max2820 *mx = (struct rtw_max2820 *)rf;
memset(mx, 0, sizeof(*mx));
free(mx, M_DEVBUF);
}
static int
rtw_max2820_init(struct rtw_rf *rf, u_int freq, u_int8_t opaque_txpower,
enum rtw_pwrstate power)
{
struct rtw_max2820 *mx = (struct rtw_max2820 *)rf;
struct rtw_rfbus *bus = &mx->mx_bus;
int rc;
if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_TEST,
MAX2820_TEST_DEFAULT)) != 0)
return rc;
if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_ENABLE,
MAX2820_ENABLE_DEFAULT)) != 0)
return rc;
/* skip configuration if it's time to sleep or to power-down. */
if ((rc = rtw_max2820_pwrstate(rf, power)) != 0)
return rc;
else if (power == RTW_OFF || power == RTW_SLEEP)
return 0;
if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_SYNTH,
MAX2820_SYNTH_R_44MHZ)) != 0)
return rc;
if ((rc = rtw_max2820_tune(rf, freq)) != 0)
return rc;
/* XXX The MAX2820 datasheet indicates that 1C and 2C should not
* be changed from 7, however, the reference driver sets them
* to 4 and 1, respectively.
*/
if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_RECEIVE,
MAX2820_RECEIVE_DL_DEFAULT |
LSHIFT(4, MAX2820A_RECEIVE_1C_MASK) |
LSHIFT(1, MAX2820A_RECEIVE_2C_MASK))) != 0)
return rc;
return rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_TRANSMIT,
MAX2820_TRANSMIT_PA_DEFAULT);
}
static int
rtw_max2820_txpower(struct rtw_rf *rf, u_int8_t opaque_txpower)
{
/* TBD */
return 0;
}
static int
rtw_max2820_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power)
{
uint32_t enable;
struct rtw_max2820 *mx;
struct rtw_rfbus *bus;
mx = (struct rtw_max2820 *)rf;
bus = &mx->mx_bus;
switch (power) {
case RTW_OFF:
case RTW_SLEEP:
default:
enable = 0x0;
break;
case RTW_ON:
enable = MAX2820_ENABLE_DEFAULT;
break;
}
return rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_ENABLE, enable);
}
struct rtw_rf *
rtw_max2820_create(struct rtw_regs *regs, rtw_rf_write_t rf_write, int is_a)
{
struct rtw_max2820 *mx;
struct rtw_rfbus *bus;
struct rtw_rf *rf;
struct rtw_bbpset *bb;
mx = malloc(sizeof(*mx), M_DEVBUF, M_NOWAIT | M_ZERO);
if (mx == NULL)
return NULL;
mx->mx_is_a = is_a;
rf = &mx->mx_rf;
bus = &mx->mx_bus;
rf->rf_init = rtw_max2820_init;
rf->rf_destroy = rtw_max2820_destroy;
rf->rf_txpower = rtw_max2820_txpower;
rf->rf_tune = rtw_max2820_tune;
rf->rf_pwrstate = rtw_max2820_pwrstate;
bb = &rf->rf_bbpset;
/* XXX magic */
bb->bb_antatten = RTW_BBP_ANTATTEN_MAXIM_MAGIC;
bb->bb_chestlim = 0;
bb->bb_chsqlim = 159;
bb->bb_ifagcdet = 100;
bb->bb_ifagcini = 144;
bb->bb_ifagclimit = 26;
bb->bb_lnadet = 248;
bb->bb_sys1 = 136;
bb->bb_sys2 = 71;
bb->bb_sys3 = 155;
bb->bb_trl = 136;
bb->bb_txagc = 8;
bus->b_regs = regs;
bus->b_write = rf_write;
return &mx->mx_rf;
}
/* freq is in MHz */
int
rtw_phy_init(struct rtw_regs *regs, struct rtw_rf *rf, u_int8_t opaque_txpower,
u_int8_t cs_threshold, u_int freq, int antdiv, int dflantb,
enum rtw_pwrstate power)
{
int rc;
RTW_DPRINTF(("%s: txpower %u csthresh %u freq %u antdiv %u dflantb %u "
"pwrstate %s\n", __func__, opaque_txpower, cs_threshold,
freq, antdiv, dflantb, rtw_pwrstate_string(power)));
/* XXX is this really necessary? */
if ((rc = rtw_rf_txpower(rf, opaque_txpower)) != 0)
return rc;
if ((rc = rtw_bbp_preinit(regs, rf->rf_bbpset.bb_antatten, dflantb,
freq)) != 0)
return rc;
if ((rc = rtw_rf_tune(rf, freq)) != 0)
return rc;
/* initialize RF */
if ((rc = rtw_rf_init(rf, freq, opaque_txpower, power)) != 0)
return rc;
#if 0 /* what is this redundant tx power setting here for? */
if ((rc = rtw_rf_txpower(rf, opaque_txpower)) != 0)
return rc;
#endif
return rtw_bbp_init(regs, &rf->rf_bbpset, antdiv, dflantb,
cs_threshold, freq);
}

10
sys/dev/ic/rtwphy.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef _DEV_IC_RTWPHY_H
#define _DEV_IC_RTWPHY_H
struct rtw_rf *rtw_sa2400_create(struct rtw_regs *, rtw_rf_write_t, int);
struct rtw_rf *rtw_max2820_create(struct rtw_regs *, rtw_rf_write_t, int);
int rtw_phy_init(struct rtw_regs *, struct rtw_rf *, u_int8_t, u_int8_t, u_int,
int, int, enum rtw_pwrstate);
#endif /* _DEV_IC_RTWPHY_H */

352
sys/dev/ic/rtwphyio.c Normal file
View File

@ -0,0 +1,352 @@
/* $NetBSD: rtwphyio.c,v 1.1 2004/09/26 02:29:15 dyoung Exp $ */
/*-
* Copyright (c) 2004, 2005 David Young. All rights reserved.
*
* Programmed for NetBSD by David Young.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of David Young may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David
* Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
/*
* Control input/output with the Philips SA2400 RF front-end and
* the baseband processor built into the Realtek RTL8180.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rtwphyio.c,v 1.1 2004/09/26 02:29:15 dyoung Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/types.h>
#include <machine/bus.h>
#include <net/if.h>
#include <net/if_media.h>
#include <net/if_ether.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_compat.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/ic/rtwreg.h>
#include <dev/ic/max2820reg.h>
#include <dev/ic/sa2400reg.h>
#include <dev/ic/si4136reg.h>
#include <dev/ic/rtwvar.h>
#include <dev/ic/rtwphyio.h>
#include <dev/ic/rtwphy.h>
static int rtw_macbangbits_timeout = 100;
u_int8_t
rtw_bbp_read(struct rtw_regs *regs, u_int addr)
{
KASSERT((addr & ~PRESHIFT(RTW_BB_ADDR_MASK)) == 0);
RTW_WRITE(regs, RTW_BB,
LSHIFT(addr, RTW_BB_ADDR_MASK) | RTW_BB_RD_MASK | RTW_BB_WR_MASK);
delay(10); /* XXX */
RTW_WBR(regs, RTW_BB, RTW_BB);
return MASK_AND_RSHIFT(RTW_READ(regs, RTW_BB), RTW_BB_RD_MASK);
}
int
rtw_bbp_write(struct rtw_regs *regs, u_int addr, u_int val)
{
#define BBP_WRITE_ITERS 50
#define BBP_WRITE_DELAY 1
int i;
uint32_t wrbbp, rdbbp;
RTW_DPRINTF(("%s: bbp[%u] <- %u\n", __func__, addr, val));
KASSERT((addr & ~PRESHIFT(RTW_BB_ADDR_MASK)) == 0);
KASSERT((val & ~PRESHIFT(RTW_BB_WR_MASK)) == 0);
wrbbp = LSHIFT(addr, RTW_BB_ADDR_MASK) | RTW_BB_WREN |
LSHIFT(val, RTW_BB_WR_MASK) | RTW_BB_RD_MASK,
rdbbp = LSHIFT(addr, RTW_BB_ADDR_MASK) |
RTW_BB_WR_MASK | RTW_BB_RD_MASK;
RTW_DPRINTF2(("%s: rdbbp = %#08x, wrbbp = %#08x\n", __func__,
rdbbp, wrbbp));
for (i = BBP_WRITE_ITERS; --i >= 0; ) {
RTW_RBW(regs, RTW_BB, RTW_BB);
RTW_WRITE(regs, RTW_BB, wrbbp);
RTW_SYNC(regs, RTW_BB, RTW_BB);
RTW_WRITE(regs, RTW_BB, rdbbp);
RTW_SYNC(regs, RTW_BB, RTW_BB);
delay(BBP_WRITE_DELAY); /* 1 microsecond */
if (MASK_AND_RSHIFT(RTW_READ(regs, RTW_BB),
RTW_BB_RD_MASK) == val) {
RTW_DPRINTF2(("%s: finished in %dus\n", __func__,
BBP_WRITE_DELAY * (BBP_WRITE_ITERS - i)));
return 0;
}
delay(BBP_WRITE_DELAY); /* again */
}
printf("%s: timeout\n", __func__);
return -1;
}
/* Help rtw_rf_hostwrite bang bits to RF over 3-wire interface. */
static __inline void
rtw_rf_hostbangbits(struct rtw_regs *regs, u_int32_t bits, int lo_to_hi,
u_int nbits)
{
int i;
u_int32_t mask, reg;
KASSERT(nbits <= 32);
RTW_DPRINTF(("%s: %u bits, %#08x, %s\n", __func__, nbits, bits,
(lo_to_hi) ? "lo to hi" : "hi to lo"));
reg = RTW_PHYCFG_HST;
RTW_WRITE(regs, RTW_PHYCFG, reg);
RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG);
if (lo_to_hi)
mask = 0x1;
else
mask = 1 << (nbits - 1);
for (i = 0; i < nbits; i++) {
RTW_DPRINTF2(("%s: bits %#08x mask %#08x -> bit %#08x\n",
__func__, bits, mask, bits & mask));
if ((bits & mask) != 0)
reg |= RTW_PHYCFG_HST_DATA;
else
reg &= ~RTW_PHYCFG_HST_DATA;
reg |= RTW_PHYCFG_HST_CLK;
RTW_WRITE(regs, RTW_PHYCFG, reg);
RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG);
DELAY(2); /* arbitrary delay */
reg &= ~RTW_PHYCFG_HST_CLK;
RTW_WRITE(regs, RTW_PHYCFG, reg);
RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG);
if (lo_to_hi)
mask <<= 1;
else
mask >>= 1;
}
reg |= RTW_PHYCFG_HST_EN;
KASSERT((reg & RTW_PHYCFG_HST_CLK) == 0);
RTW_WRITE(regs, RTW_PHYCFG, reg);
RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG);
}
/* Help rtw_rf_macwrite: tell MAC to bang bits to RF over the 3-wire
* interface.
*/
static __inline int
rtw_rf_macbangbits(struct rtw_regs *regs, u_int32_t reg)
{
int i;
RTW_DPRINTF(("%s: %#08x\n", __func__, reg));
RTW_WRITE(regs, RTW_PHYCFG, RTW_PHYCFG_MAC_POLL | reg);
RTW_WBR(regs, RTW_PHYCFG, RTW_PHYCFG);
for (i = rtw_macbangbits_timeout; --i >= 0; delay(1)) {
if ((RTW_READ(regs, RTW_PHYCFG) & RTW_PHYCFG_MAC_POLL) == 0) {
RTW_DPRINTF2(("%s: finished in %dus\n", __func__,
rtw_macbangbits_timeout - i));
return 0;
}
RTW_RBR(regs, RTW_PHYCFG, RTW_PHYCFG); /* XXX paranoia? */
}
printf("%s: RTW_PHYCFG_MAC_POLL still set.\n", __func__);
return -1;
}
static u_int32_t
rtw_grf5101_host_crypt(u_int addr, u_int32_t val)
{
/* TBD */
return 0;
}
static u_int32_t
rtw_grf5101_mac_crypt(u_int addr, u_int32_t val)
{
u_int32_t data_and_addr;
#define EXTRACT_NIBBLE(d, which) (((d) >> (4 * (which))) & 0xf)
static u_int8_t caesar[16] = {0x0, 0x8, 0x4, 0xc,
0x2, 0xa, 0x6, 0xe,
0x1, 0x9, 0x5, 0xd,
0x3, 0xb, 0x7, 0xf};
data_and_addr = caesar[EXTRACT_NIBBLE(val, 2)] |
(caesar[EXTRACT_NIBBLE(val, 1)] << 4) |
(caesar[EXTRACT_NIBBLE(val, 0)] << 8) |
(caesar[(addr >> 1) & 0xf] << 12) |
((addr & 0x1) << 16) |
(caesar[EXTRACT_NIBBLE(val, 3)] << 24);
return LSHIFT(data_and_addr,
RTW_PHYCFG_MAC_PHILIPS_ADDR_MASK|RTW_PHYCFG_MAC_PHILIPS_DATA_MASK);
#undef EXTRACT_NIBBLE
}
static __inline const char *
rtw_rfchipid_string(enum rtw_rfchipid rfchipid)
{
switch (rfchipid) {
case RTW_RFCHIPID_MAXIM:
return "Maxim";
case RTW_RFCHIPID_PHILIPS:
return "Philips";
case RTW_RFCHIPID_GCT:
return "GCT";
case RTW_RFCHIPID_RFMD:
return "RFMD";
case RTW_RFCHIPID_INTERSIL:
return "Intersil";
default:
return "unknown";
}
}
/* Bang bits over the 3-wire interface. */
int
rtw_rf_hostwrite(struct rtw_regs *regs, enum rtw_rfchipid rfchipid,
u_int addr, u_int32_t val)
{
u_int nbits;
int lo_to_hi;
u_int32_t bits;
RTW_DPRINTF(("%s: %s[%u] <- %#08x\n", __func__,
rtw_rfchipid_string(rfchipid), addr, val));
switch (rfchipid) {
case RTW_RFCHIPID_MAXIM:
nbits = 16;
lo_to_hi = 0;
bits = LSHIFT(val, MAX2820_TWI_DATA_MASK) |
LSHIFT(addr, MAX2820_TWI_ADDR_MASK);
break;
case RTW_RFCHIPID_PHILIPS:
KASSERT((addr & ~PRESHIFT(SA2400_TWI_ADDR_MASK)) == 0);
KASSERT((val & ~PRESHIFT(SA2400_TWI_DATA_MASK)) == 0);
bits = LSHIFT(val, SA2400_TWI_DATA_MASK) |
LSHIFT(addr, SA2400_TWI_ADDR_MASK) | SA2400_TWI_WREN;
nbits = 32;
lo_to_hi = 1;
break;
case RTW_RFCHIPID_GCT:
case RTW_RFCHIPID_RFMD:
KASSERT((addr & ~PRESHIFT(SI4126_TWI_ADDR_MASK)) == 0);
KASSERT((val & ~PRESHIFT(SI4126_TWI_DATA_MASK)) == 0);
if (rfchipid == RTW_RFCHIPID_GCT)
bits = rtw_grf5101_host_crypt(addr, val);
else {
bits = LSHIFT(val, SI4126_TWI_DATA_MASK) |
LSHIFT(addr, SI4126_TWI_ADDR_MASK);
}
nbits = 22;
lo_to_hi = 0;
break;
case RTW_RFCHIPID_INTERSIL:
default:
printf("%s: unknown rfchipid %d\n", __func__, rfchipid);
return -1;
}
rtw_rf_hostbangbits(regs, bits, lo_to_hi, nbits);
return 0;
}
static uint32_t
rtw_maxim_swizzle(u_int addr, uint32_t val)
{
uint32_t hidata, lodata;
KASSERT((val & ~(RTW_MAXIM_LODATA_MASK|RTW_MAXIM_HIDATA_MASK)) == 0);
lodata = MASK_AND_RSHIFT(val, RTW_MAXIM_LODATA_MASK);
hidata = MASK_AND_RSHIFT(val, RTW_MAXIM_HIDATA_MASK);
return LSHIFT(lodata, RTW_PHYCFG_MAC_MAXIM_LODATA_MASK) |
LSHIFT(hidata, RTW_PHYCFG_MAC_MAXIM_HIDATA_MASK) |
LSHIFT(addr, RTW_PHYCFG_MAC_MAXIM_ADDR_MASK);
}
/* Tell the MAC what to bang over the 3-wire interface. */
int
rtw_rf_macwrite(struct rtw_regs *regs, enum rtw_rfchipid rfchipid,
u_int addr, u_int32_t val)
{
uint32_t reg;
RTW_DPRINTF(("%s: %s[%u] <- %#08x\n", __func__,
rtw_rfchipid_string(rfchipid), addr, val));
switch (rfchipid) {
case RTW_RFCHIPID_GCT:
reg = rtw_grf5101_mac_crypt(addr, val);
break;
case RTW_RFCHIPID_MAXIM:
reg = rtw_maxim_swizzle(addr, val);
break;
default: /* XXX */
case RTW_RFCHIPID_PHILIPS:
KASSERT(
(addr & ~PRESHIFT(RTW_PHYCFG_MAC_PHILIPS_ADDR_MASK)) == 0);
KASSERT(
(val & ~PRESHIFT(RTW_PHYCFG_MAC_PHILIPS_DATA_MASK)) == 0);
reg = LSHIFT(addr, RTW_PHYCFG_MAC_PHILIPS_ADDR_MASK) |
LSHIFT(val, RTW_PHYCFG_MAC_PHILIPS_DATA_MASK);
}
switch (rfchipid) {
case RTW_RFCHIPID_GCT:
case RTW_RFCHIPID_MAXIM:
case RTW_RFCHIPID_RFMD:
reg |= RTW_PHYCFG_MAC_RFTYPE_RFMD;
break;
case RTW_RFCHIPID_INTERSIL:
reg |= RTW_PHYCFG_MAC_RFTYPE_INTERSIL;
break;
case RTW_RFCHIPID_PHILIPS:
reg |= RTW_PHYCFG_MAC_RFTYPE_PHILIPS;
break;
default:
printf("%s: unknown rfchipid %d\n", __func__, rfchipid);
return -1;
}
return rtw_rf_macbangbits(regs, reg);
}

40
sys/dev/ic/rtwphyio.h Normal file
View File

@ -0,0 +1,40 @@
/* $NetBSD: rtwphyio.h,v 1.1 2004/09/26 02:29:15 dyoung Exp $ */
/*-
* Copyright (c) 2004, 2005 David Young. All rights reserved.
*
* Programmed for NetBSD by David Young.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of David Young may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David
* Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#ifndef _DEV_IC_RTWPHYIO_H
#define _DEV_IC_RTWPHYIO_H
int rtw_rf_hostwrite(struct rtw_regs *, enum rtw_rfchipid, u_int, u_int32_t);
int rtw_rf_macwrite(struct rtw_regs *, enum rtw_rfchipid, u_int, u_int32_t);
u_int8_t rtw_bbp_read(struct rtw_regs *, u_int);
int rtw_bbp_write(struct rtw_regs *, u_int, u_int);
#endif /* _DEV_IC_RTWPHYIO_H */

1072
sys/dev/ic/rtwreg.h Normal file

File diff suppressed because it is too large Load Diff

441
sys/dev/ic/rtwvar.h Normal file
View File

@ -0,0 +1,441 @@
/* $NetBSD: rtwvar.h,v 1.1 2004/09/26 02:29:15 dyoung Exp $ */
/*-
* Copyright (c) 2004, 2005 David Young. All rights reserved.
*
* Driver for the Realtek RTL8180 802.11 MAC/BBP by David Young.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of David Young may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David
* Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#ifndef _DEV_IC_RTWVAR_H_
#define _DEV_IC_RTWVAR_H_
#include <sys/queue.h>
#include <sys/callout.h>
#ifdef RTW_DEBUG
extern int rtw_debug;
#define RTW_DPRINTF(x) if (rtw_debug > 0) printf x
#define RTW_DPRINTF2(x) if (rtw_debug > 1) printf x
#define RTW_DPRINTF3(x) if (rtw_debug > 2) printf x
#define DPRINTF(sc, x) if ((sc)->sc_ic.ic_if.if_flags & IFF_DEBUG) printf x
#define DPRINTF2(sc, x) if ((sc)->sc_ic.ic_if.if_flags & IFF_DEBUG) RTW_DPRINTF2(x)
#define DPRINTF3(sc, x) if ((sc)->sc_ic.ic_if.if_flags & IFF_DEBUG) RTW_DPRINTF3(x)
#else /* RTW_DEBUG */
#define RTW_DPRINTF(x)
#define RTW_DPRINTF2(x)
#define RTW_DPRINTF3(x)
#define DPRINTF(sc, x)
#define DPRINTF2(sc, x)
#define DPRINTF3(sc, x)
#endif /* RTW_DEBUG */
#if 0
enum rtw_rftype {
RTW_RFTYPE_INTERSIL = 0,
RTW_RFTYPE_RFMD,
RTW_RFTYPE_PHILIPS,
RTW_RFTYPE_MAXIM
};
#endif
enum rtw_locale {
RTW_LOCALE_USA = 0,
RTW_LOCALE_EUROPE,
RTW_LOCALE_JAPAN,
RTW_LOCALE_UNKNOWN
};
enum rtw_rfchipid {
RTW_RFCHIPID_RESERVED = 0,
RTW_RFCHIPID_INTERSIL = 1,
RTW_RFCHIPID_RFMD = 2,
RTW_RFCHIPID_PHILIPS = 3,
RTW_RFCHIPID_MAXIM = 4,
RTW_RFCHIPID_GCT = 5
};
/* sc_flags */
#define RTW_F_ENABLED 0x00000001 /* chip is enabled */
#define RTW_F_DIGPHY 0x00000002 /* digital PHY */
#define RTW_F_DFLANTB 0x00000004 /* B antenna is default */
#define RTW_F_ANTDIV 0x00000010 /* h/w antenna diversity */
#define RTW_F_9356SROM 0x00000020 /* 93c56 SROM */
#define RTW_F_SLEEP 0x00000040 /* chip is enabled */
/* all PHY flags */
#define RTW_F_ALLPHY (RTW_F_DIGPHY|RTW_F_DFLANTB|RTW_F_ANTDIV)
struct rtw_regs {
bus_space_tag_t r_bt;
bus_space_handle_t r_bh;
};
#define RTW_SR_GET(sr, ofs) \
(((sr)->sr_content[(ofs)/2] >> (((ofs) % 2 == 0) ? 0 : 8)) & 0xff)
#define RTW_SR_GET16(sr, ofs) \
(RTW_SR_GET((sr), (ofs)) | (RTW_SR_GET((sr), (ofs) + 1) << 8))
struct rtw_srom {
u_int16_t *sr_content;
u_int16_t sr_size;
};
struct rtw_rxctl {
struct mbuf *srx_mbuf;
bus_dmamap_t srx_dmamap;
};
struct rtw_txctl {
SIMPLEQ_ENTRY(rtw_txctl) stx_q;
struct mbuf *stx_mbuf;
bus_dmamap_t stx_dmamap;
struct ieee80211_node *stx_ni; /* destination node */
u_int stx_first; /* 1st hw descriptor */
u_int stx_last; /* last hw descriptor */
};
#define RTW_NTXPRI 4 /* number of Tx priorities */
#define RTW_TXPRILO 0
#define RTW_TXPRIMD 1
#define RTW_TXPRIHI 2
#define RTW_TXPRIBCN 3 /* beacon priority */
#define RTW_MAXPKTSEGS 32 /* max 32 segments per Tx packet */
#define CASSERT(cond, complaint) complaint[(cond) ? 0 : -1] = complaint[(cond) ? 0 : -1]
#define RTW_NTXDESC_ROUNDUP(n) \
roundup(n, RTW_DESC_ALIGNMENT / sizeof(struct rtw_txdesc))
#define RTW_TXQLEN_ROUNDUP(n) \
(RTW_NTXDESC_ROUNDUP(n * RTW_MAXPKTSEGS) / RTW_MAXPKTSEGS)
#define RTW_RXQLEN_ROUNDUP(n) \
roundup(n, RTW_DESC_ALIGNMENT / sizeof(struct rtw_rxctl))
/* The descriptor rings must begin on RTW_DESC_ALIGNMENT boundaries.
* I allocate them consecutively from one buffer, so just round up.
*/
#define RTW_TXQLENLO RTW_TXQLEN_ROUNDUP(64) /* high-priority queue length */
#define RTW_TXQLENMD RTW_TXQLEN_ROUNDUP(32) /* medium-priority */
#define RTW_TXQLENHI RTW_TXQLEN_ROUNDUP(16) /* high-priority */
#define RTW_TXQLENBCN 1 /* beacon */
#define RTW_NTXDESCLO (RTW_TXQLENLO * RTW_MAXPKTSEGS)
#define RTW_NTXDESCMD (RTW_TXQLENMD * RTW_MAXPKTSEGS)
#define RTW_NTXDESCHI (RTW_TXQLENHI * RTW_MAXPKTSEGS)
#define RTW_NTXDESCBCN (RTW_TXQLENBCN * RTW_MAXPKTSEGS)
#define RTW_NTXDESCTOTAL (RTW_NTXDESCLO + RTW_NTXDESCMD + \
RTW_NTXDESCHI + RTW_NTXDESCBCN)
#define RTW_RXQLEN RTW_RXQLEN_ROUNDUP(32)
#define RTW_NRXDESC RTW_RXQLEN
struct rtw_txdesc_blk {
u_int htc_ndesc;
u_int htc_next;
u_int htc_nfree;
bus_addr_t htc_physbase;
bus_addr_t htc_ofs;
struct rtw_txdesc *htc_desc;
};
#define RTW_NEXT_DESC(htc, idx) \
(htc->htc_physbase + \
sizeof(struct rtw_txdesc) * ((idx + 1) % htc->htc_ndesc))
SIMPLEQ_HEAD(rtw_txq, rtw_txctl);
struct rtw_txctl_blk {
/* dirty/free s/w descriptors */
struct rtw_txq stc_dirtyq;
struct rtw_txq stc_freeq;
u_int stc_ndesc;
struct rtw_txctl *stc_desc;
};
struct rtw_descs {
struct rtw_txdesc hd_txlo[RTW_NTXDESCLO];
struct rtw_txdesc hd_txmd[RTW_NTXDESCMD];
struct rtw_txdesc hd_txhi[RTW_NTXDESCMD];
struct rtw_rxdesc hd_rx[RTW_NRXDESC];
struct rtw_txdesc hd_bcn[RTW_NTXDESCBCN];
};
#define RTW_DESC_OFFSET(ring, i) offsetof(struct rtw_descs, ring[i])
#define RTW_RING_OFFSET(ring) RTW_DESC_OFFSET(ring, 0)
#define RTW_RING_BASE(sc, ring) ((sc)->sc_desc_physaddr + \
RTW_RING_OFFSET(ring))
/* Radio capture format for RTL8180. */
#define RTW_RX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | (1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL))
struct rtw_rx_radiotap_header {
struct ieee80211_radiotap_header rr_ihdr;
u_int8_t rr_flags;
u_int8_t rr_rate;
u_int16_t rr_chan_freq;
u_int16_t rr_chan_flags;
u_int8_t rr_antsignal;
} __attribute__((__packed__));
#define RTW_TX_RADIOTAP_PRESENT ((1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL))
struct rtw_tx_radiotap_header {
struct ieee80211_radiotap_header rt_ihdr;
u_int8_t rt_flags;
u_int8_t rt_rate;
u_int16_t rt_chan_freq;
u_int16_t rt_chan_flags;
} __attribute__((__packed__));
enum rtw_attach_state {FINISHED, FINISH_DESCMAP_LOAD, FINISH_DESCMAP_CREATE,
FINISH_DESC_MAP, FINISH_DESC_ALLOC, FINISH_RXMAPS_CREATE,
FINISH_TXMAPS_CREATE, FINISH_RESET, FINISH_READ_SROM, FINISH_PARSE_SROM,
FINISH_RF_ATTACH, FINISH_ID_STA, FINISH_TXDESCBLK_SETUP,
FINISH_TXCTLBLK_SETUP, DETACHED};
struct rtw_hooks {
void *rh_shutdown; /* shutdown hook */
void *rh_power; /* power management hook */
};
struct rtw_mtbl {
int (*mt_newstate)(struct ieee80211com *,
enum ieee80211_state, int);
void (*mt_recv_mgmt)(struct ieee80211com *,
struct mbuf *, struct ieee80211_node *,
int, int, u_int32_t);
struct ieee80211_node *(*mt_node_alloc)(struct ieee80211com *);
void (*mt_node_free)(struct ieee80211com *,
struct ieee80211_node *);
};
enum rtw_pwrstate { RTW_OFF = 0, RTW_SLEEP, RTW_ON };
typedef void (*rtw_continuous_tx_cb_t)(void *arg, int);
struct rtw_phy {
struct rtw_rf *p_rf;
struct rtw_regs *p_regs;
};
struct rtw_bbpset {
u_int bb_antatten;
u_int bb_chestlim;
u_int bb_chsqlim;
u_int bb_ifagcdet;
u_int bb_ifagcini;
u_int bb_ifagclimit;
u_int bb_lnadet;
u_int bb_sys1;
u_int bb_sys2;
u_int bb_sys3;
u_int bb_trl;
u_int bb_txagc;
};
struct rtw_rf {
void (*rf_destroy)(struct rtw_rf *);
/* args: frequency, txpower, power state */
int (*rf_init)(struct rtw_rf *, u_int, u_int8_t,
enum rtw_pwrstate);
/* arg: power state */
int (*rf_pwrstate)(struct rtw_rf *, enum rtw_pwrstate);
/* arg: frequency */
int (*rf_tune)(struct rtw_rf *, u_int);
/* arg: txpower */
int (*rf_txpower)(struct rtw_rf *, u_int8_t);
rtw_continuous_tx_cb_t rf_continuous_tx_cb;
void *rf_continuous_tx_arg;
struct rtw_bbpset rf_bbpset;
};
static __inline void
rtw_rf_destroy(struct rtw_rf *rf)
{
(*rf->rf_destroy)(rf);
}
static __inline int
rtw_rf_init(struct rtw_rf *rf, u_int freq, u_int8_t opaque_txpower,
enum rtw_pwrstate power)
{
return (*rf->rf_init)(rf, freq, opaque_txpower, power);
}
static __inline int
rtw_rf_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power)
{
return (*rf->rf_pwrstate)(rf, power);
}
static __inline int
rtw_rf_tune(struct rtw_rf *rf, u_int freq)
{
return (*rf->rf_tune)(rf, freq);
}
static __inline int
rtw_rf_txpower(struct rtw_rf *rf, u_int8_t opaque_txpower)
{
return (*rf->rf_txpower)(rf, opaque_txpower);
}
typedef int (*rtw_rf_write_t)(struct rtw_regs *, enum rtw_rfchipid, u_int,
u_int32_t);
struct rtw_rfbus {
struct rtw_regs *b_regs;
rtw_rf_write_t b_write;
};
static __inline int
rtw_rfbus_write(struct rtw_rfbus *bus, enum rtw_rfchipid rfchipid, u_int addr,
u_int32_t val)
{
return (*bus->b_write)(bus->b_regs, rfchipid, addr, val);
}
struct rtw_max2820 {
struct rtw_rf mx_rf;
struct rtw_rfbus mx_bus;
int mx_is_a; /* 1: MAX2820A/MAX2821A */
};
struct rtw_sa2400 {
struct rtw_rf sa_rf;
struct rtw_rfbus sa_bus;
int sa_digphy; /* 1: digital PHY */
};
typedef void (*rtw_pwrstate_t)(struct rtw_regs *, enum rtw_pwrstate, int);
struct rtw_softc {
struct device sc_dev;
struct ieee80211com sc_ic;
struct rtw_regs sc_regs;
bus_dma_tag_t sc_dmat;
u_int32_t sc_flags;
#if 0
enum rtw_rftype sc_rftype;
#endif
enum rtw_attach_state sc_attach_state;
enum rtw_rfchipid sc_rfchipid;
enum rtw_locale sc_locale;
u_int8_t sc_phydelay;
/* s/w Tx/Rx descriptors */
struct rtw_txctl_blk sc_txctl_blk[RTW_NTXPRI];
struct rtw_rxctl sc_rxctl[RTW_RXQLEN];
u_int sc_txq;
u_int sc_txnext;
struct rtw_txdesc_blk sc_txdesc_blk[RTW_NTXPRI];
struct rtw_rxdesc *sc_rxdesc;
u_int sc_rxnext;
struct rtw_descs *sc_descs;
bus_dma_segment_t sc_desc_segs;
int sc_desc_nsegs;
bus_dmamap_t sc_desc_dmamap;
#define sc_desc_physaddr sc_desc_dmamap->dm_segs[0].ds_addr
struct rtw_srom sc_srom;
enum rtw_pwrstate sc_pwrstate;
rtw_pwrstate_t sc_pwrstate_cb;
struct rtw_rf *sc_rf;
u_int16_t sc_inten;
/* interrupt acknowledge hook */
void (*sc_intr_ack) __P((struct rtw_regs *));
int (*sc_enable)(struct rtw_softc *);
void (*sc_disable)(struct rtw_softc *);
void (*sc_power)(struct rtw_softc *, int);
struct rtw_mtbl sc_mtbl;
struct rtw_hooks sc_hooks;
caddr_t sc_radiobpf;
struct callout sc_scan_ch;
u_int sc_cur_chan;
u_int32_t sc_tsfth; /* most significant TSFT bits */
u_int32_t sc_rcr; /* RTW_RCR */
u_int8_t sc_csthr; /* carrier-sense threshold */
int sc_do_tick; /* indicate 1s ticks */
struct timeval sc_tick0; /* first tick */
uint8_t sc_rev; /* PCI/Cardbus revision */
union {
struct rtw_rx_radiotap_header tap;
u_int8_t pad[64];
} sc_rxtapu;
union {
struct rtw_tx_radiotap_header tap;
u_int8_t pad[64];
} sc_txtapu;
};
#define sc_if sc_ic.ic_if
#define sc_rxtap sc_rxtapu.tap
#define sc_txtap sc_txtapu.tap
void rtw_txdac_enable(struct rtw_regs *, int);
void rtw_anaparm_enable(struct rtw_regs *, int);
void rtw_config0123_enable(struct rtw_regs *, int);
void rtw_continuous_tx_enable(struct rtw_regs *, int);
void rtw_attach(struct rtw_softc *);
int rtw_detach(struct rtw_softc *);
int rtw_intr(void *);
void rtw_disable(struct rtw_softc *);
int rtw_enable(struct rtw_softc *);
int rtw_activate(struct device *, enum devact);
void rtw_power(int, void *);
void rtw_shutdown(void *);
const char *rtw_pwrstate_string(enum rtw_pwrstate);
#endif /* _DEV_IC_RTWVAR_H_ */

258
sys/dev/ic/sa2400reg.h Normal file
View File

@ -0,0 +1,258 @@
/* $NetBSD: sa2400reg.h,v 1.1 2004/09/26 02:29:15 dyoung Exp $ */
/*
* Copyright (c) 2005 David Young. All rights reserved.
*
* This code was written by David Young.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David
* Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#ifndef _DEV_IC_SA2400REG_H_
#define _DEV_IC_SA2400REG_H_
/*
* Serial bus format for Philips SA2400 Single-chip Transceiver.
*/
#define SA2400_TWI_DATA_MASK BITS(31,8)
#define SA2400_TWI_WREN BIT(7) /* enable write */
#define SA2400_TWI_ADDR_MASK BITS(6,0)
/*
* Registers for Philips SA2400 Single-chip Transceiver.
*/
#define SA2400_SYNA 0 /* Synthesizer Register A */
#define SA2400_SYNA_FM BIT(21) /* fractional modulus select,
* 0: /8 (default)
* 1: /5
*/
#define SA2400_SYNA_NF_MASK BITS(20,18) /* fractional increment value,
* 0 to 7, default 4
*/
#define SA2400_SYNA_N_MASK BITS(17,2) /* main divider division ratio,
* 512 to 65535, default 615
*/
#define SA2400_SYNB 1 /* Synthesizer Register B */
#define SA2400_SYNB_R_MASK BITS(21,12) /* reference divider ratio,
* 4 to 1023, default 11
*/
#define SA2400_SYNB_L_MASK BITS(11,10) /* lock detect mode */
#define SA2400_SYNB_L_INACTIVE0 LSHIFT(0, SA2400_SYNB_L_MASK)
#define SA2400_SYNB_L_INACTIVE1 LSHIFT(1, SA2400_SYNB_L_MASK)
#define SA2400_SYNB_L_NORMAL LSHIFT(2, SA2400_SYNB_L_MASK)
#define SA2400_SYNB_L_INACTIVE2 LSHIFT(3, SA2400_SYNB_L_MASK)
#define SA2400_SYNB_ON BIT(9) /* power on/off,
* 0: inverted chip mode control
* 1: as defined by chip mode
* (see SA2400_OPMODE)
*/
#define SA2400_SYNB_ONE BIT(8) /* always 1 */
#define SA2400_SYNB_FC_MASK BITS(7,0) /* fractional compensation
* charge pump current DAC,
* 0 to 255, default 80.
*/
#define SA2400_SYNC 2 /* Synthesizer Register C */
#define SA2400_SYNC_CP_MASK BITS(7,6) /* charge pump current
* setting
*/
#define SA2400_SYNC_CP_NORMAL_ LSHIFT(0, SA2400_SYNC_CP_MASK)
#define SA2400_SYNC_CP_THIRD_ LSHIFT(1, SA2400_SYNC_CP_MASK)
#define SA2400_SYNC_CP_NORMAL LSHIFT(2, SA2400_SYNC_CP_MASK) /* recommended */
#define SA2400_SYNC_CP_THIRD LSHIFT(3, SA2400_SYNC_CP_MASK)
#define SA2400_SYNC_SM_MASK BITS(5,3) /* comparison divider select,
* 0 to 4, extra division
* ratio is 2**SM.
*/
#define SA2400_SYNC_ZERO BIT(2) /* always 0 */
#define SA2400_SYND 3 /* Synthesizer Register D */
#define SA2400_SYND_ZERO1_MASK BITS(21,17) /* always 0 */
#define SA2400_SYND_TPHPSU BIT(16) /* T[phpsu], 1: disable
* PHP speedup pump,
* overrides SA2400_SYND_TSPU
*/
#define SA2400_SYND_TPSU BIT(15) /* T[spu], 1: speedup on,
* 0: speedup off
*/
#define SA2400_SYND_ZERO2_MASK BITS(14,3) /* always 0 */
#define SA2400_OPMODE 4 /* Operating mode, filter tuner,
* other controls
*/
#define SA2400_OPMODE_ADC BIT(19) /* 1: in Rx mode, RSSI-ADC always on
* 0: RSSI-ADC only on during AGC
*/
#define SA2400_OPMODE_FTERR BIT(18) /* read-only filter tuner error:
* 1 if tuner out of range
*/
/* Rx & Tx filter tuning, write tuning value (test mode only) or
* read tuner setting (in normal mode).
*/
#define SA2400_OPMODE_FILTTUNE_MASK BITS(17,15)
#define SA2400_OPMODE_V2P5 BIT(14) /* external reference voltage
* (pad v2p5) on
*/
#define SA2400_OPMODE_I1M BIT(13) /* external reference current ... */
#define SA2400_OPMODE_I0P3 BIT(12) /* external reference current ... */
#define SA2400_OPMODE_IN22 BIT(10) /* xtal input frequency,
* 0: 44 MHz
* 1: 22 MHz
*/
#define SA2400_OPMODE_CLK BIT(9) /* reference clock output on */
#define SA2400_OPMODE_XO BIT(8) /* xtal oscillator on */
#define SA2400_OPMODE_DIGIN BIT(7) /* use digital Tx inputs (FIRDAC) */
#define SA2400_OPMODE_RXLV BIT(6) /* Rx output common mode voltage,
* 0: V[DD]/2
* 1: 1.25V
*/
#define SA2400_OPMODE_VEO BIT(5) /* make internal vco
* available at vco pads (vcoextout)
*/
#define SA2400_OPMODE_VEI BIT(4) /* use external vco input (vcoextin) */
/* main operating mode */
#define SA2400_OPMODE_MODE_MASK BITS(3,0)
#define SA2400_OPMODE_MODE_SLEEP LSHIFT(0, SA2400_OPMODE_MODE_MASK)
#define SA2400_OPMODE_MODE_TXRX LSHIFT(1, SA2400_OPMODE_MODE_MASK)
#define SA2400_OPMODE_MODE_WAIT LSHIFT(2, SA2400_OPMODE_MODE_MASK)
#define SA2400_OPMODE_MODE_RXMGC LSHIFT(3, SA2400_OPMODE_MODE_MASK)
#define SA2400_OPMODE_MODE_FCALIB LSHIFT(4, SA2400_OPMODE_MODE_MASK)
#define SA2400_OPMODE_MODE_DCALIB LSHIFT(5, SA2400_OPMODE_MODE_MASK)
#define SA2400_OPMODE_MODE_FASTTXRXMGC LSHIFT(6, SA2400_OPMODE_MODE_MASK)
#define SA2400_OPMODE_MODE_RESET LSHIFT(7, SA2400_OPMODE_MODE_MASK)
#define SA2400_OPMODE_MODE_VCOCALIB LSHIFT(8, SA2400_OPMODE_MODE_MASK)
#define SA2400_AGC 5 /* AGC adjustment */
#define SA2400_AGC_TARGETSIGN BIT(23) /* fine-tune AGC target:
* -7dB to 7dB, sign bit ... */
#define SA2400_AGC_TARGET_MASK BITS(22,20) /* ... plus 0dB - 7dB */
#define SA2400_AGC_MAXGAIN_MASK BITS(19,15) /* maximum AGC gain, 0 to 31,
* (yields 54dB to 85dB)
*/
/* write: settling time after baseband gain switching, units of
* 182 nanoseconds.
* read: output of RSSI/Tx-peak detector's ADC in 5-bit Gray code.
*/
#define SA2400_AGC_BBPDELAY_MASK BITS(14,10)
#define SA2400_AGC_ADCVAL_MASK SA2400_AGC_BBPDELAY_MASK
/* write: settling time after LNA gain switching, units of
* 182 nanoseconds
* read: 2nd sample of RSSI in AGC cycle
*/
#define SA2400_AGC_LNADELAY_MASK BITS(9,5)
#define SA2400_AGC_SAMPLE2_MASK SA2400_AGC_LNADELAY_MASK
/* write: time between turning on Rx and AGCSET, units of
* 182 nanoseconds
* read: 1st sample of RSSI in AGC cycle
*/
#define SA2400_AGC_RXONDELAY_MASK BITS(4,0)
#define SA2400_AGC_SAMPLE1_MASK SA2400_AGC_RXONDELAY_MASK
#define SA2400_MANRX 6 /* Manual receiver control settings */
#define SA2400_MANRX_AHSN BIT(23) /* 1: AGC w/ high S/N---switch LNA at
* step 52 (recommended)
* 0: switch LNA at step 60
*/
/* If _RXOSQON, Q offset is
* (_RXOSQSIGN ? -1 : 1) * (1 + _RXOSQ_MASK) * 8 millivolts,
* otherwise, Q offset is 0.
*
* Ditto I offset.
*/
#define SA2400_MANRX_RXOSQON BIT(22) /* Rx Q-channel correction. */
#define SA2400_MANRX_RXOSQSIGN BIT(21)
#define SA2400_MANRX_RXOSQ_MASK BITS(20,18)
#define SA2400_MANRX_RXOSION BIT(17) /* Rx I-channel correction. */
#define SA2400_MANRX_RXOSISIGN BIT(16)
#define SA2400_MANRX_RXOSI_MASK BITS(15,13)
#define SA2400_MANRX_TEN BIT(12) /* use 10MHz offset cancellation
* cornerpoint for brief period
* after each gain change
*/
/* DC offset cancellation cornerpoint select
* write: in RXMGC, set the cornerpoint
* read: in other modes, read AGC-controlled cornerpoint
*/
#define SA2400_MANRX_CORNERFREQ_MASK BITS(11,10)
/* write: in RXMGC mode, sets receiver gain
* read: in other modes, read AGC-controlled gain
*/
#define SA2400_MANRX_RXGAIN_MASK BITS(9,0)
#define SA2400_TX 7 /* Transmitter settings */
/* Tx offsets
*
* write: in test mode, sets the offsets
* read: in normal mode, returns automatic settings
*/
#define SA2400_TX_TXOSQON BIT(19)
#define SA2400_TX_TXOSQSIGN BIT(18)
#define SA2400_TX_TXOSQ_MASK BITS(17,15)
#define SA2400_TX_TXOSION BIT(14)
#define SA2400_TX_TXOSISIGN BIT(13)
#define SA2400_TX_TXOSI_MASK BITS(12,10)
#define SA2400_TX_RAMP_MASK BITS(9,8) /* Ramp-up delay,
* 0: 1us
* 1: 2us
* 2: 3us
* 3: 4us
* datasheet says, "ramp-up
* time always 1us". huh?
*/
#define SA2400_TX_HIGAIN_MASK BITS(7,4) /* Transmitter gain settings
* for TXHI output
*/
#define SA2400_TX_LOGAIN_MASK BITS(3,0) /* Transmitter gain settings
* for TXLO output
*/
#define SA2400_VCO 8 /* VCO settings */
#define SA2400_VCO_ZERO BITS(6,5) /* always zero */
#define SA2400_VCO_VCERR BIT(4) /* VCO calibration error flag---no
* band with low enough frequency
* could be found
*/
#define SA2400_VCO_VCOBAND_MASK BITS(3,0) /* VCO band,
* write: in test mode, sets
* VCO band
* read: in normal mode,
* the result of
* calibration (VCOCAL).
* 0 = highest
* frequencies
*/
#endif /* _DEV_IC_SA2400REG_H_ */