1 | /* |
---|
2 | * Radio tuning for Maxim max2820 on RTL8180 |
---|
3 | * |
---|
4 | * Copyright 2007 Andrea Merello <andreamrl@tiscali.it> |
---|
5 | * |
---|
6 | * Modified slightly for gPXE, June 2009 by Joshua Oreman. |
---|
7 | * |
---|
8 | * Code from the BSD driver and the rtl8181 project have been |
---|
9 | * very useful to understand certain things |
---|
10 | * |
---|
11 | * I want to thanks the Authors of such projects and the Ndiswrapper |
---|
12 | * project Authors. |
---|
13 | * |
---|
14 | * A special Big Thanks also is for all people who donated me cards, |
---|
15 | * making possible the creation of the original rtl8180 driver |
---|
16 | * from which this code is derived! |
---|
17 | * |
---|
18 | * This program is free software; you can redistribute it and/or modify |
---|
19 | * it under the terms of the GNU General Public License version 2 as |
---|
20 | * published by the Free Software Foundation. |
---|
21 | */ |
---|
22 | |
---|
23 | #include <unistd.h> |
---|
24 | #include <gpxe/pci.h> |
---|
25 | #include <gpxe/net80211.h> |
---|
26 | |
---|
27 | #include "rtl818x.h" |
---|
28 | |
---|
29 | FILE_LICENCE(GPL2_ONLY); |
---|
30 | |
---|
31 | #define MAXIM_ANTENNA 0xb3 |
---|
32 | |
---|
33 | static const u32 max2820_chan[] = { |
---|
34 | 12, /* CH 1 */ |
---|
35 | 17, |
---|
36 | 22, |
---|
37 | 27, |
---|
38 | 32, |
---|
39 | 37, |
---|
40 | 42, |
---|
41 | 47, |
---|
42 | 52, |
---|
43 | 57, |
---|
44 | 62, |
---|
45 | 67, |
---|
46 | 72, |
---|
47 | 84, /* CH 14 */ |
---|
48 | }; |
---|
49 | |
---|
50 | static void write_max2820(struct net80211_device *dev, u8 addr, u32 data) |
---|
51 | { |
---|
52 | struct rtl818x_priv *priv = dev->priv; |
---|
53 | u32 phy_config; |
---|
54 | |
---|
55 | phy_config = 0x90 + (data & 0xf); |
---|
56 | phy_config <<= 16; |
---|
57 | phy_config += addr; |
---|
58 | phy_config <<= 8; |
---|
59 | phy_config += (data >> 4) & 0xff; |
---|
60 | |
---|
61 | /* This was originally a 32-bit write to a typecast |
---|
62 | RFPinsOutput, but gcc complained about aliasing rules. -JBO */ |
---|
63 | rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, phy_config & 0xffff); |
---|
64 | rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, phy_config >> 16); |
---|
65 | |
---|
66 | mdelay(1); |
---|
67 | } |
---|
68 | |
---|
69 | static void max2820_write_phy_antenna(struct net80211_device *dev, short chan) |
---|
70 | { |
---|
71 | struct rtl818x_priv *priv = dev->priv; |
---|
72 | u8 ant; |
---|
73 | |
---|
74 | ant = MAXIM_ANTENNA; |
---|
75 | if (priv->rfparam & RF_PARAM_ANTBDEFAULT) |
---|
76 | ant |= BB_ANTENNA_B; |
---|
77 | if (chan == 14) |
---|
78 | ant |= BB_ANTATTEN_CHAN14; |
---|
79 | |
---|
80 | rtl818x_write_phy(dev, 0x10, ant); |
---|
81 | } |
---|
82 | |
---|
83 | static void max2820_rf_set_channel(struct net80211_device *dev, |
---|
84 | struct net80211_channel *channelp) |
---|
85 | { |
---|
86 | struct rtl818x_priv *priv = dev->priv; |
---|
87 | int channel = channelp->channel_nr; |
---|
88 | unsigned int chan_idx = channel - 1; |
---|
89 | u32 txpw = priv->txpower[chan_idx] & 0xFF; |
---|
90 | u32 chan = max2820_chan[chan_idx]; |
---|
91 | |
---|
92 | /* While philips SA2400 drive the PA bias from |
---|
93 | * sa2400, for MAXIM we do this directly from BB */ |
---|
94 | rtl818x_write_phy(dev, 3, txpw); |
---|
95 | |
---|
96 | max2820_write_phy_antenna(dev, channel); |
---|
97 | write_max2820(dev, 3, chan); |
---|
98 | } |
---|
99 | |
---|
100 | static void max2820_rf_stop(struct net80211_device *dev) |
---|
101 | { |
---|
102 | rtl818x_write_phy(dev, 3, 0x8); |
---|
103 | write_max2820(dev, 1, 0); |
---|
104 | } |
---|
105 | |
---|
106 | |
---|
107 | static void max2820_rf_init(struct net80211_device *dev) |
---|
108 | { |
---|
109 | struct rtl818x_priv *priv = dev->priv; |
---|
110 | |
---|
111 | /* MAXIM from netbsd driver */ |
---|
112 | write_max2820(dev, 0, 0x007); /* test mode as indicated in datasheet */ |
---|
113 | write_max2820(dev, 1, 0x01e); /* enable register */ |
---|
114 | write_max2820(dev, 2, 0x001); /* synt register */ |
---|
115 | |
---|
116 | max2820_rf_set_channel(dev, NULL); |
---|
117 | |
---|
118 | write_max2820(dev, 4, 0x313); /* rx register */ |
---|
119 | |
---|
120 | /* PA is driven directly by the BB, we keep the MAXIM bias |
---|
121 | * at the highest value in case that setting it to lower |
---|
122 | * values may introduce some further attenuation somewhere.. |
---|
123 | */ |
---|
124 | write_max2820(dev, 5, 0x00f); |
---|
125 | |
---|
126 | /* baseband configuration */ |
---|
127 | rtl818x_write_phy(dev, 0, 0x88); /* sys1 */ |
---|
128 | rtl818x_write_phy(dev, 3, 0x08); /* txagc */ |
---|
129 | rtl818x_write_phy(dev, 4, 0xf8); /* lnadet */ |
---|
130 | rtl818x_write_phy(dev, 5, 0x90); /* ifagcinit */ |
---|
131 | rtl818x_write_phy(dev, 6, 0x1a); /* ifagclimit */ |
---|
132 | rtl818x_write_phy(dev, 7, 0x64); /* ifagcdet */ |
---|
133 | |
---|
134 | max2820_write_phy_antenna(dev, 1); |
---|
135 | |
---|
136 | rtl818x_write_phy(dev, 0x11, 0x88); /* trl */ |
---|
137 | |
---|
138 | if (rtl818x_ioread8(priv, &priv->map->CONFIG2) & |
---|
139 | RTL818X_CONFIG2_ANTENNA_DIV) |
---|
140 | rtl818x_write_phy(dev, 0x12, 0xc7); |
---|
141 | else |
---|
142 | rtl818x_write_phy(dev, 0x12, 0x47); |
---|
143 | |
---|
144 | rtl818x_write_phy(dev, 0x13, 0x9b); |
---|
145 | |
---|
146 | rtl818x_write_phy(dev, 0x19, 0x0); /* CHESTLIM */ |
---|
147 | rtl818x_write_phy(dev, 0x1a, 0x9f); /* CHSQLIM */ |
---|
148 | |
---|
149 | max2820_rf_set_channel(dev, NULL); |
---|
150 | } |
---|
151 | |
---|
152 | struct rtl818x_rf_ops max2820_rf_ops __rtl818x_rf_driver = { |
---|
153 | .name = "Maxim max2820", |
---|
154 | .id = 4, |
---|
155 | .init = max2820_rf_init, |
---|
156 | .stop = max2820_rf_stop, |
---|
157 | .set_chan = max2820_rf_set_channel |
---|
158 | }; |
---|