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:
parent
d94faebdc7
commit
3e9bdb9662
189
sys/dev/ic/max2820reg.h
Normal file
189
sys/dev/ic/max2820reg.h
Normal 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
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
624
sys/dev/ic/rtwphy.c
Normal 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
10
sys/dev/ic/rtwphy.h
Normal 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
352
sys/dev/ic/rtwphyio.c
Normal 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
40
sys/dev/ic/rtwphyio.h
Normal 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
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
441
sys/dev/ic/rtwvar.h
Normal 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
258
sys/dev/ic/sa2400reg.h
Normal 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_ */
|
Loading…
Reference in New Issue
Block a user