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