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