Home | History | Annotate | Download | only in rtw
      1 /*
      2  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 /*
      6  * Copyright (c) 2004, 2005 David Young.  All rights reserved.
      7  *
      8  * Programmed for NetBSD by David Young.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. The name of David Young may not be used to endorse or promote
     19  *    products derived from this software without specific prior
     20  *    written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY
     23  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     24  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     25  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL David
     26  * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
     28  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     30  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     31  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
     33  * OF SUCH DAMAGE.
     34  */
     35 /*
     36  * Control the Philips SA2400 RF front-end and the baseband processor
     37  * built into the Realtek RTL8180.
     38  */
     39 #include <sys/types.h>
     40 #include <sys/sysmacros.h>
     41 #include "rtwreg.h"
     42 #include "rtwvar.h"
     43 #include "max2820reg.h"
     44 #include "sa2400reg.h"
     45 #include "rtwphyio.h"
     46 #include "rtwphy.h"
     47 
     48 static int rtw_max2820_pwrstate(struct rtw_rf *, enum rtw_pwrstate);
     49 static int rtw_sa2400_pwrstate(struct rtw_rf *, enum rtw_pwrstate);
     50 
     51 static int
     52 rtw_rf_init(struct rtw_rf *rf, uint_t freq, uint8_t opaque_txpower,
     53     enum rtw_pwrstate power)
     54 {
     55 	return (*rf->rf_init)(rf, freq, opaque_txpower, power);
     56 }
     57 
     58 static int
     59 rtw_rf_tune(struct rtw_rf *rf, uint_t freq)
     60 {
     61 	return (*rf->rf_tune)(rf, freq);
     62 }
     63 
     64 static int
     65 rtw_rf_txpower(struct rtw_rf *rf, uint8_t opaque_txpower)
     66 {
     67 	return (*rf->rf_txpower)(rf, opaque_txpower);
     68 }
     69 
     70 static int
     71 rtw_rfbus_write(struct rtw_rfbus *bus, enum rtw_rfchipid rfchipid, uint_t addr,
     72     uint32_t val)
     73 {
     74 	return (*bus->b_write)(bus->b_regs, rfchipid, addr, val);
     75 }
     76 
     77 static int
     78 rtw_bbp_preinit(struct rtw_regs *regs, uint_t antatten0, int dflantb,
     79     uint_t freq)
     80 {
     81 	uint_t antatten = antatten0;
     82 	if (dflantb)
     83 		antatten |= RTW_BBP_ANTATTEN_DFLANTB;
     84 	if (freq == 2484) /* channel 14 */
     85 		antatten |= RTW_BBP_ANTATTEN_CHAN14;
     86 	return (rtw_bbp_write(regs, RTW_BBP_ANTATTEN, antatten));
     87 }
     88 
     89 static int
     90 rtw_bbp_init(struct rtw_regs *regs, struct rtw_bbpset *bb, int antdiv,
     91     int dflantb, uint8_t cs_threshold, uint_t freq)
     92 {
     93 	int rc;
     94 	uint32_t sys2, sys3;
     95 
     96 	sys2 = bb->bb_sys2;
     97 	if (antdiv)
     98 		sys2 |= RTW_BBP_SYS2_ANTDIV;
     99 	sys3 = bb->bb_sys3 |
    100 	    LSHIFT(cs_threshold, RTW_BBP_SYS3_CSTHRESH_MASK);
    101 
    102 #define	RTW_BBP_WRITE_OR_RETURN(reg, val) \
    103 	if ((rc = rtw_bbp_write(regs, reg, val)) != 0) \
    104 		return (rc);
    105 
    106 	RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS1,		bb->bb_sys1);
    107 	RTW_BBP_WRITE_OR_RETURN(RTW_BBP_TXAGC,		bb->bb_txagc);
    108 	RTW_BBP_WRITE_OR_RETURN(RTW_BBP_LNADET,		bb->bb_lnadet);
    109 	RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCINI,	bb->bb_ifagcini);
    110 	RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCLIMIT,	bb->bb_ifagclimit);
    111 	RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCDET,	bb->bb_ifagcdet);
    112 
    113 	if ((rc = rtw_bbp_preinit(regs, bb->bb_antatten, dflantb, freq)) != 0)
    114 		return (rc);
    115 
    116 	RTW_BBP_WRITE_OR_RETURN(RTW_BBP_TRL,		bb->bb_trl);
    117 	RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS2,		sys2);
    118 	RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS3,		sys3);
    119 	RTW_BBP_WRITE_OR_RETURN(RTW_BBP_CHESTLIM,	bb->bb_chestlim);
    120 	RTW_BBP_WRITE_OR_RETURN(RTW_BBP_CHSQLIM,	bb->bb_chsqlim);
    121 	return (0);
    122 }
    123 
    124 static int
    125 rtw_sa2400_txpower(struct rtw_rf *rf, uint8_t opaque_txpower)
    126 {
    127 	struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf;
    128 	struct rtw_rfbus *bus = &sa->sa_bus;
    129 
    130 	return (rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_TX,
    131 	    opaque_txpower));
    132 }
    133 
    134 #ifdef _RTW_FUTURE_DEBUG_
    135 /*
    136  * make sure we're using the same settings as the reference driver
    137  */
    138 static void
    139 verify_syna(uint_t freq, uint32_t val)
    140 {
    141 	uint32_t expected_val = ~val;
    142 
    143 	switch (freq) {
    144 	case 2412:
    145 		expected_val = 0x0000096c; /* ch 1 */
    146 		break;
    147 	case 2417:
    148 		expected_val = 0x00080970; /* ch 2 */
    149 		break;
    150 	case 2422:
    151 		expected_val = 0x00100974; /* ch 3 */
    152 		break;
    153 	case 2427:
    154 		expected_val = 0x00180978; /* ch 4 */
    155 		break;
    156 	case 2432:
    157 		expected_val = 0x00000980; /* ch 5 */
    158 		break;
    159 	case 2437:
    160 		expected_val = 0x00080984; /* ch 6 */
    161 		break;
    162 	case 2442:
    163 		expected_val = 0x00100988; /* ch 7 */
    164 		break;
    165 	case 2447:
    166 		expected_val = 0x0018098c; /* ch 8 */
    167 		break;
    168 	case 2452:
    169 		expected_val = 0x00000994; /* ch 9 */
    170 		break;
    171 	case 2457:
    172 		expected_val = 0x00080998; /* ch 10 */
    173 		break;
    174 	case 2462:
    175 		expected_val = 0x0010099c; /* ch 11 */
    176 		break;
    177 	case 2467:
    178 		expected_val = 0x001809a0; /* ch 12 */
    179 		break;
    180 	case 2472:
    181 		expected_val = 0x000009a8; /* ch 13 */
    182 		break;
    183 	case 2484:
    184 		expected_val = 0x000009b4; /* ch 14 */
    185 		break;
    186 	}
    187 }
    188 #endif /* _RTW_FUTURE_DEBUG_ */
    189 
    190 /* freq is in MHz */
    191 static int
    192 rtw_sa2400_tune(struct rtw_rf *rf, uint_t freq)
    193 {
    194 	struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf;
    195 	struct rtw_rfbus *bus = &sa->sa_bus;
    196 	int rc;
    197 	uint32_t syna, synb, sync;
    198 
    199 	/*
    200 	 * XO = 44MHz, R = 11, hence N is in units of XO / R = 4MHz.
    201 	 *
    202 	 * The channel spacing (5MHz) is not divisible by 4MHz, so
    203 	 * we set the fractional part of N to compensate.
    204 	 */
    205 	int n = freq / 4, nf = (freq % 4) * 2;
    206 
    207 	syna = LSHIFT(nf, SA2400_SYNA_NF_MASK) | LSHIFT(n, SA2400_SYNA_N_MASK);
    208 	/* verify_syna(freq, syna); */
    209 
    210 	/*
    211 	 * Divide the 44MHz crystal down to 4MHz. Set the fractional
    212 	 * compensation charge pump value to agree with the fractional
    213 	 * modulus.
    214 	 */
    215 	synb = LSHIFT(11, SA2400_SYNB_R_MASK) | SA2400_SYNB_L_NORMAL |
    216 	    SA2400_SYNB_ON | SA2400_SYNB_ONE |
    217 	    LSHIFT(80, SA2400_SYNB_FC_MASK); /* agrees w/ SA2400_SYNA_FM = 0 */
    218 
    219 	sync = SA2400_SYNC_CP_NORMAL;
    220 
    221 	if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_SYNA,
    222 	    syna)) != 0)
    223 		return (rc);
    224 	if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_SYNB,
    225 	    synb)) != 0)
    226 		return (rc);
    227 	if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_SYNC,
    228 	    sync)) != 0)
    229 		return (rc);
    230 	return (rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_SYND, 0x0));
    231 }
    232 
    233 static int
    234 rtw_sa2400_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power)
    235 {
    236 	struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf;
    237 	struct rtw_rfbus *bus = &sa->sa_bus;
    238 	uint32_t opmode;
    239 	opmode = SA2400_OPMODE_DEFAULTS;
    240 	switch (power) {
    241 	case RTW_ON:
    242 		opmode |= SA2400_OPMODE_MODE_TXRX;
    243 		break;
    244 	case RTW_SLEEP:
    245 		opmode |= SA2400_OPMODE_MODE_WAIT;
    246 		break;
    247 	case RTW_OFF:
    248 		opmode |= SA2400_OPMODE_MODE_SLEEP;
    249 		break;
    250 	}
    251 
    252 	if (sa->sa_digphy)
    253 		opmode |= SA2400_OPMODE_DIGIN;
    254 
    255 	return (rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE,
    256 	    opmode));
    257 }
    258 
    259 static int
    260 rtw_sa2400_manrx_init(struct rtw_sa2400 *sa)
    261 {
    262 	uint32_t manrx;
    263 
    264 	/*
    265 	 * we are not supposed to be in RXMGC mode when we do
    266 	 * this?
    267 	 */
    268 	manrx = SA2400_MANRX_AHSN;
    269 	manrx |= SA2400_MANRX_TEN;
    270 	manrx |= LSHIFT(1023, SA2400_MANRX_RXGAIN_MASK);
    271 
    272 	return (rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_MANRX,
    273 	    manrx));
    274 }
    275 
    276 static int
    277 rtw_sa2400_vcocal_start(struct rtw_sa2400 *sa, int start)
    278 {
    279 	uint32_t opmode;
    280 
    281 	opmode = SA2400_OPMODE_DEFAULTS;
    282 	if (start)
    283 		opmode |= SA2400_OPMODE_MODE_VCOCALIB;
    284 	else
    285 		opmode |= SA2400_OPMODE_MODE_SLEEP;
    286 
    287 	if (sa->sa_digphy)
    288 		opmode |= SA2400_OPMODE_DIGIN;
    289 
    290 	return (rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS,
    291 	    SA2400_OPMODE, opmode));
    292 }
    293 
    294 static int
    295 rtw_sa2400_vco_calibration(struct rtw_sa2400 *sa)
    296 {
    297 	int rc;
    298 	/*
    299 	 * calibrate VCO
    300 	 */
    301 	if ((rc = rtw_sa2400_vcocal_start(sa, 1)) != 0)
    302 		return (rc);
    303 	DELAY(2200);	/* 2.2 milliseconds */
    304 	/*
    305 	 * XXX superfluous: SA2400 automatically entered SLEEP mode.
    306 	 */
    307 	return (rtw_sa2400_vcocal_start(sa, 0));
    308 }
    309 
    310 static int
    311 rtw_sa2400_filter_calibration(struct rtw_sa2400 *sa)
    312 {
    313 	uint32_t opmode;
    314 
    315 	opmode = SA2400_OPMODE_DEFAULTS | SA2400_OPMODE_MODE_FCALIB;
    316 	if (sa->sa_digphy)
    317 		opmode |= SA2400_OPMODE_DIGIN;
    318 
    319 	return (rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS,
    320 	    SA2400_OPMODE, opmode));
    321 }
    322 
    323 static int
    324 rtw_sa2400_dc_calibration(struct rtw_sa2400 *sa)
    325 {
    326 	struct rtw_rf *rf = &sa->sa_rf;
    327 	int rc;
    328 	uint32_t dccal;
    329 
    330 	(*rf->rf_continuous_tx_cb)(rf->rf_continuous_tx_arg, 1);
    331 
    332 	dccal = SA2400_OPMODE_DEFAULTS | SA2400_OPMODE_MODE_TXRX;
    333 
    334 	rc = rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE,
    335 	    dccal);
    336 	if (rc != 0)
    337 		return (rc);
    338 
    339 	DELAY(5); /* DCALIB after being in Tx mode for 5 microseconds */
    340 
    341 	dccal &= ~SA2400_OPMODE_MODE_MASK;
    342 	dccal |= SA2400_OPMODE_MODE_DCALIB;
    343 
    344 	rc = rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE,
    345 	    dccal);
    346 	if (rc != 0)
    347 		return (rc);
    348 	DELAY(20); /* calibration takes at most 20 microseconds */
    349 
    350 	(*rf->rf_continuous_tx_cb)(rf->rf_continuous_tx_arg, 0);
    351 
    352 	return (0);
    353 }
    354 
    355 static int
    356 rtw_sa2400_agc_init(struct rtw_sa2400 *sa)
    357 {
    358 	uint32_t agc;
    359 
    360 	agc = LSHIFT(25, SA2400_AGC_MAXGAIN_MASK);
    361 	agc |= LSHIFT(7, SA2400_AGC_BBPDELAY_MASK);
    362 	agc |= LSHIFT(15, SA2400_AGC_LNADELAY_MASK);
    363 	agc |= LSHIFT(27, SA2400_AGC_RXONDELAY_MASK);
    364 
    365 	return (rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_AGC,
    366 	    agc));
    367 }
    368 
    369 static void
    370 rtw_sa2400_destroy(struct rtw_rf *rf)
    371 {
    372 	struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf;
    373 	kmem_free(sa, sizeof (*sa));
    374 }
    375 
    376 static int
    377 rtw_sa2400_calibrate(struct rtw_rf *rf, uint_t freq)
    378 {
    379 	struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf;
    380 	int i, rc;
    381 
    382 	/*
    383 	 * XXX reference driver calibrates VCO twice. Is it a bug?
    384 	 */
    385 	for (i = 0; i < 2; i++) {
    386 		if ((rc = rtw_sa2400_vco_calibration(sa)) != 0)
    387 			return (rc);
    388 	}
    389 	/*
    390 	 * VCO calibration erases synthesizer registers, so re-tune
    391 	 */
    392 	if ((rc = rtw_sa2400_tune(rf, freq)) != 0)
    393 		return (rc);
    394 	if ((rc = rtw_sa2400_filter_calibration(sa)) != 0)
    395 		return (rc);
    396 	/*
    397 	 * analog PHY needs DC calibration
    398 	 */
    399 	if (!sa->sa_digphy)
    400 		return (rtw_sa2400_dc_calibration(sa));
    401 	return (0);
    402 }
    403 
    404 static int
    405 rtw_sa2400_init(struct rtw_rf *rf, uint_t freq, uint8_t opaque_txpower,
    406     enum rtw_pwrstate power)
    407 {
    408 	struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf;
    409 	int rc;
    410 
    411 	if ((rc = rtw_sa2400_txpower(rf, opaque_txpower)) != 0)
    412 		return (rc);
    413 
    414 	/*
    415 	 * skip configuration if it's time to sleep or to power-down.
    416 	 */
    417 	if (power == RTW_SLEEP || power == RTW_OFF)
    418 		return (rtw_sa2400_pwrstate(rf, power));
    419 
    420 	/*
    421 	 * go to sleep for configuration
    422 	 */
    423 	if ((rc = rtw_sa2400_pwrstate(rf, RTW_SLEEP)) != 0)
    424 		return (rc);
    425 
    426 	if ((rc = rtw_sa2400_tune(rf, freq)) != 0)
    427 		return (rc);
    428 	if ((rc = rtw_sa2400_agc_init(sa)) != 0)
    429 		return (rc);
    430 	if ((rc = rtw_sa2400_manrx_init(sa)) != 0)
    431 		return (rc);
    432 	if ((rc = rtw_sa2400_calibrate(rf, freq)) != 0)
    433 		return (rc);
    434 
    435 	/*
    436 	 * enter Tx/Rx mode
    437 	 */
    438 	return (rtw_sa2400_pwrstate(rf, power));
    439 }
    440 
    441 struct rtw_rf *
    442 rtw_sa2400_create(struct rtw_regs *regs, rtw_rf_write_t rf_write, int digphy)
    443 {
    444 	struct rtw_sa2400 *sa;
    445 	struct rtw_rfbus *bus;
    446 	struct rtw_rf *rf;
    447 	struct rtw_bbpset *bb;
    448 
    449 	sa = (struct rtw_sa2400 *)kmem_zalloc(sizeof (*sa), KM_SLEEP);
    450 	if (sa == NULL)
    451 		return (NULL);
    452 
    453 	sa->sa_digphy = digphy;
    454 
    455 	rf = &sa->sa_rf;
    456 	bus = &sa->sa_bus;
    457 
    458 	rf->rf_init = rtw_sa2400_init;
    459 	rf->rf_destroy = rtw_sa2400_destroy;
    460 	rf->rf_txpower = rtw_sa2400_txpower;
    461 	rf->rf_tune = rtw_sa2400_tune;
    462 	rf->rf_pwrstate = rtw_sa2400_pwrstate;
    463 	bb = &rf->rf_bbpset;
    464 
    465 	/*
    466 	 * XXX magic
    467 	 */
    468 	bb->bb_antatten = RTW_BBP_ANTATTEN_PHILIPS_MAGIC;
    469 	bb->bb_chestlim =	0x00;
    470 	bb->bb_chsqlim =	0xa0;
    471 	bb->bb_ifagcdet =	0x64;
    472 	bb->bb_ifagcini =	0x90;
    473 	bb->bb_ifagclimit =	0x1a;
    474 	bb->bb_lnadet =		0xe0;
    475 	bb->bb_sys1 =		0x98;
    476 	bb->bb_sys2 =		0x47;
    477 	bb->bb_sys3 =		0x90;
    478 	bb->bb_trl =		0x88;
    479 	bb->bb_txagc =		0x38;
    480 
    481 	bus->b_regs = regs;
    482 	bus->b_write = rf_write;
    483 
    484 	return (&sa->sa_rf);
    485 }
    486 
    487 /*
    488  * freq is in MHz
    489  */
    490 static int
    491 rtw_max2820_tune(struct rtw_rf *rf, uint_t freq)
    492 {
    493 	struct rtw_max2820 *mx = (struct rtw_max2820 *)rf;
    494 	struct rtw_rfbus *bus = &mx->mx_bus;
    495 
    496 	if (freq < 2400 || freq > 2499)
    497 		return (-1);
    498 
    499 	return (rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_CHANNEL,
    500 	    LSHIFT(freq - 2400, MAX2820_CHANNEL_CF_MASK)));
    501 }
    502 
    503 static void
    504 rtw_max2820_destroy(struct rtw_rf *rf)
    505 {
    506 	struct rtw_max2820 *mx = (struct rtw_max2820 *)rf;
    507 	kmem_free(mx, sizeof (*mx));
    508 }
    509 
    510 /*ARGSUSED*/
    511 static int
    512 rtw_max2820_init(struct rtw_rf *rf, uint_t freq, uint8_t opaque_txpower,
    513     enum rtw_pwrstate power)
    514 {
    515 	struct rtw_max2820 *mx = (struct rtw_max2820 *)rf;
    516 	struct rtw_rfbus *bus = &mx->mx_bus;
    517 	int rc;
    518 
    519 	if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_TEST,
    520 	    MAX2820_TEST_DEFAULT)) != 0)
    521 		return (rc);
    522 
    523 	if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_ENABLE,
    524 	    MAX2820_ENABLE_DEFAULT)) != 0)
    525 		return (rc);
    526 
    527 	/*
    528 	 * skip configuration if it's time to sleep or to power-down.
    529 	 */
    530 	if ((rc = rtw_max2820_pwrstate(rf, power)) != 0)
    531 		return (rc);
    532 	else if (power == RTW_OFF || power == RTW_SLEEP)
    533 		return (0);
    534 
    535 	if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_SYNTH,
    536 	    MAX2820_SYNTH_R_44MHZ)) != 0)
    537 		return (rc);
    538 
    539 	if ((rc = rtw_max2820_tune(rf, freq)) != 0)
    540 		return (rc);
    541 
    542 	/*
    543 	 * XXX The MAX2820 datasheet indicates that 1C and 2C should not
    544 	 * be changed from 7, however, the reference driver sets them
    545 	 * to 4 and 1, respectively.
    546 	 */
    547 	if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_RECEIVE,
    548 	    MAX2820_RECEIVE_DL_DEFAULT |
    549 	    LSHIFT(4, MAX2820A_RECEIVE_1C_MASK) |
    550 	    LSHIFT(1, MAX2820A_RECEIVE_2C_MASK))) != 0)
    551 		return (rc);
    552 
    553 	return (rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM, MAX2820_TRANSMIT,
    554 	    MAX2820_TRANSMIT_PA_DEFAULT));
    555 }
    556 
    557 /*ARGSUSED*/
    558 static int
    559 rtw_max2820_txpower(struct rtw_rf *rf, uint8_t opaque_txpower)
    560 {
    561 	/* TBD */
    562 	return (0);
    563 }
    564 
    565 static int
    566 rtw_max2820_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power)
    567 {
    568 	uint32_t enable;
    569 	struct rtw_max2820 *mx;
    570 	struct rtw_rfbus *bus;
    571 
    572 	mx = (struct rtw_max2820 *)rf;
    573 	bus = &mx->mx_bus;
    574 
    575 	switch (power) {
    576 	case RTW_OFF:
    577 	case RTW_SLEEP:
    578 	default:
    579 		enable = 0x0;
    580 		break;
    581 	case RTW_ON:
    582 		enable = MAX2820_ENABLE_DEFAULT;
    583 		break;
    584 	}
    585 	return (rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM,
    586 	    MAX2820_ENABLE, enable));
    587 }
    588 
    589 struct rtw_rf *
    590 rtw_max2820_create(struct rtw_regs *regs, rtw_rf_write_t rf_write, int is_a)
    591 {
    592 	struct rtw_max2820 *mx;
    593 	struct rtw_rfbus *bus;
    594 	struct rtw_rf *rf;
    595 	struct rtw_bbpset *bb;
    596 
    597 	mx = (struct rtw_max2820 *)kmem_zalloc(sizeof (*mx), KM_SLEEP);
    598 	if (mx == NULL)
    599 		return (NULL);
    600 
    601 	mx->mx_is_a = is_a;
    602 
    603 	rf = &mx->mx_rf;
    604 	bus = &mx->mx_bus;
    605 
    606 	rf->rf_init = rtw_max2820_init;
    607 	rf->rf_destroy = rtw_max2820_destroy;
    608 	rf->rf_txpower = rtw_max2820_txpower;
    609 	rf->rf_tune = rtw_max2820_tune;
    610 	rf->rf_pwrstate = rtw_max2820_pwrstate;
    611 	bb = &rf->rf_bbpset;
    612 
    613 	/*
    614 	 * XXX magic
    615 	 */
    616 	bb->bb_antatten = RTW_BBP_ANTATTEN_MAXIM_MAGIC;
    617 	bb->bb_chestlim =	0;
    618 	bb->bb_chsqlim =	159;
    619 	bb->bb_ifagcdet =	100;
    620 	bb->bb_ifagcini =	144;
    621 	bb->bb_ifagclimit =	26;
    622 	bb->bb_lnadet =		248;
    623 	bb->bb_sys1 =		136;
    624 	bb->bb_sys2 =		71;
    625 	bb->bb_sys3 =		155;
    626 	bb->bb_trl =		136;
    627 	bb->bb_txagc =		8;
    628 
    629 	bus->b_regs = regs;
    630 	bus->b_write = rf_write;
    631 
    632 	return (&mx->mx_rf);
    633 }
    634 
    635 /*
    636  * freq is in MHz
    637  */
    638 int
    639 rtw_phy_init(struct rtw_regs *regs, struct rtw_rf *rf, uint8_t opaque_txpower,
    640     uint8_t cs_threshold, uint_t freq, int antdiv, int dflantb,
    641     enum rtw_pwrstate power)
    642 {
    643 	int rc;
    644 
    645 	/*
    646 	 * XXX is this really necessary?
    647 	 */
    648 	if ((rc = rtw_rf_txpower(rf, opaque_txpower)) != 0)
    649 		return (rc);
    650 	if ((rc = rtw_bbp_preinit(regs, rf->rf_bbpset.bb_antatten, dflantb,
    651 	    freq)) != 0)
    652 		return (rc);
    653 	if ((rc = rtw_rf_tune(rf, freq)) != 0)
    654 		return (rc);
    655 	/*
    656 	 * initialize RF
    657 	 */
    658 	if ((rc = rtw_rf_init(rf, freq, opaque_txpower, power)) != 0)
    659 		return (rc);
    660 #ifdef _RTW_FUTURE_DEBUG_
    661 	/* what is this redundant tx power setting here for? */
    662 	if ((rc = rtw_rf_txpower(rf, opaque_txpower)) != 0)
    663 		return (rc);
    664 #endif /* _RTW_FUTURE_DEBUG */
    665 	return (rtw_bbp_init(regs, &rf->rf_bbpset, antdiv, dflantb,
    666 	    cs_threshold, freq));
    667 }
    668