xref: /illumos-gate/usr/src/uts/common/io/rtw/rtwphy.c (revision 46b592853d0f4f11781b6b0a7533f267c6aee132)
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