1 | /* $NetBSD: rtwphyio.c,v 1.19 2016/10/09 14:42:30 christos 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 | * |
16 | * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY |
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
18 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David |
20 | * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED |
22 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
25 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
27 | * OF SUCH DAMAGE. |
28 | */ |
29 | /* |
30 | * Control input/output with the Philips SA2400 RF front-end and |
31 | * the baseband processor built into the Realtek RTL8180. |
32 | */ |
33 | |
34 | #include <sys/cdefs.h> |
35 | __KERNEL_RCSID(0, "$NetBSD: rtwphyio.c,v 1.19 2016/10/09 14:42:30 christos Exp $" ); |
36 | |
37 | #include <sys/param.h> |
38 | #include <sys/systm.h> |
39 | #include <sys/types.h> |
40 | #include <sys/device.h> |
41 | |
42 | #include <sys/bus.h> |
43 | |
44 | #include <net/if.h> |
45 | #include <net/if_media.h> |
46 | #include <net/if_ether.h> |
47 | |
48 | #include <net80211/ieee80211_netbsd.h> |
49 | #include <net80211/ieee80211_radiotap.h> |
50 | #include <net80211/ieee80211_var.h> |
51 | |
52 | #include <dev/ic/rtwreg.h> |
53 | #include <dev/ic/max2820reg.h> |
54 | #include <dev/ic/sa2400reg.h> |
55 | #include <dev/ic/si4136reg.h> |
56 | #include <dev/ic/rtwvar.h> |
57 | #include <dev/ic/rtwphyio.h> |
58 | #include <dev/ic/rtwphy.h> |
59 | |
60 | static int rtw_macbangbits_timeout = 100; |
61 | |
62 | uint8_t |
63 | rtw_bbp_read(struct rtw_regs *regs, u_int addr) |
64 | { |
65 | KASSERT((addr & ~__SHIFTOUT_MASK(RTW_BB_ADDR_MASK)) == 0); |
66 | RTW_WRITE(regs, RTW_BB, |
67 | __SHIFTIN(addr, RTW_BB_ADDR_MASK) | RTW_BB_RD_MASK | RTW_BB_WR_MASK); |
68 | delay(10); /* XXX */ |
69 | RTW_WBR(regs, RTW_BB, RTW_BB); |
70 | return __SHIFTOUT(RTW_READ(regs, RTW_BB), RTW_BB_RD_MASK); |
71 | } |
72 | |
73 | int |
74 | rtw_bbp_write(struct rtw_regs *regs, u_int addr, u_int val) |
75 | { |
76 | #define BBP_WRITE_ITERS 50 |
77 | #define BBP_WRITE_DELAY 1 |
78 | int i; |
79 | uint32_t wrbbp, rdbbp; |
80 | |
81 | RTW_DPRINTF(RTW_DEBUG_PHYIO, |
82 | ("%s: bbp[%u] <- %u\n" , __func__, addr, val)); |
83 | |
84 | KASSERT((addr & ~__SHIFTOUT_MASK(RTW_BB_ADDR_MASK)) == 0); |
85 | KASSERT((val & ~__SHIFTOUT_MASK(RTW_BB_WR_MASK)) == 0); |
86 | |
87 | wrbbp = __SHIFTIN(addr, RTW_BB_ADDR_MASK) | RTW_BB_WREN | |
88 | __SHIFTIN(val, RTW_BB_WR_MASK) | RTW_BB_RD_MASK; |
89 | |
90 | rdbbp = __SHIFTIN(addr, RTW_BB_ADDR_MASK) | |
91 | RTW_BB_WR_MASK | RTW_BB_RD_MASK; |
92 | |
93 | RTW_DPRINTF(RTW_DEBUG_PHYIO, |
94 | ("%s: rdbbp = %#08x, wrbbp = %#08x\n" , __func__, rdbbp, wrbbp)); |
95 | |
96 | for (i = BBP_WRITE_ITERS; --i >= 0; ) { |
97 | RTW_RBW(regs, RTW_BB, RTW_BB); |
98 | RTW_WRITE(regs, RTW_BB, wrbbp); |
99 | RTW_SYNC(regs, RTW_BB, RTW_BB); |
100 | RTW_WRITE(regs, RTW_BB, rdbbp); |
101 | RTW_SYNC(regs, RTW_BB, RTW_BB); |
102 | delay(BBP_WRITE_DELAY); /* 1 microsecond */ |
103 | if (__SHIFTOUT(RTW_READ(regs, RTW_BB), |
104 | RTW_BB_RD_MASK) == val) { |
105 | RTW_DPRINTF(RTW_DEBUG_PHYIO, |
106 | ("%s: finished in %dus\n" , __func__, |
107 | BBP_WRITE_DELAY * (BBP_WRITE_ITERS - i))); |
108 | return 0; |
109 | } |
110 | delay(BBP_WRITE_DELAY); /* again */ |
111 | } |
112 | printf("%s: timeout\n" , __func__); |
113 | return -1; |
114 | } |
115 | |
116 | /* Help rtw_rf_hostwrite bang bits to RF over 3-wire interface. */ |
117 | static inline void |
118 | rtw_rf_hostbangbits(struct rtw_regs *regs, uint32_t bits, int lo_to_hi, |
119 | u_int nbits) |
120 | { |
121 | int i; |
122 | uint32_t mask, reg; |
123 | |
124 | KASSERT(nbits <= 32); |
125 | |
126 | RTW_DPRINTF(RTW_DEBUG_PHYIO, |
127 | ("%s: %u bits, %#08x, %s\n" , __func__, nbits, bits, |
128 | (lo_to_hi) ? "lo to hi" : "hi to lo" )); |
129 | |
130 | reg = RTW_PHYCFG_HST; |
131 | RTW_WRITE(regs, RTW_PHYCFG, reg); |
132 | RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG); |
133 | |
134 | if (lo_to_hi) |
135 | mask = 0x1; |
136 | else |
137 | mask = 1 << (nbits - 1); |
138 | |
139 | for (i = 0; i < nbits; i++) { |
140 | RTW_DPRINTF(RTW_DEBUG_PHYBITIO, |
141 | ("%s: bits %#08x mask %#08x -> bit %#08x\n" , |
142 | __func__, bits, mask, bits & mask)); |
143 | |
144 | if ((bits & mask) != 0) |
145 | reg |= RTW_PHYCFG_HST_DATA; |
146 | else |
147 | reg &= ~RTW_PHYCFG_HST_DATA; |
148 | |
149 | reg |= RTW_PHYCFG_HST_CLK; |
150 | RTW_WRITE(regs, RTW_PHYCFG, reg); |
151 | RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG); |
152 | |
153 | DELAY(2); /* arbitrary delay */ |
154 | |
155 | reg &= ~RTW_PHYCFG_HST_CLK; |
156 | RTW_WRITE(regs, RTW_PHYCFG, reg); |
157 | RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG); |
158 | |
159 | if (lo_to_hi) |
160 | mask <<= 1; |
161 | else |
162 | mask >>= 1; |
163 | } |
164 | |
165 | reg |= RTW_PHYCFG_HST_EN; |
166 | KASSERT((reg & RTW_PHYCFG_HST_CLK) == 0); |
167 | RTW_WRITE(regs, RTW_PHYCFG, reg); |
168 | RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG); |
169 | } |
170 | |
171 | /* Help rtw_rf_macwrite: tell MAC to bang bits to RF over the 3-wire |
172 | * interface. |
173 | */ |
174 | static inline int |
175 | rtw_rf_macbangbits(struct rtw_regs *regs, uint32_t reg) |
176 | { |
177 | int i; |
178 | |
179 | RTW_DPRINTF(RTW_DEBUG_PHY, ("%s: %#08x\n" , __func__, reg)); |
180 | |
181 | RTW_WRITE(regs, RTW_PHYCFG, RTW_PHYCFG_MAC_POLL | reg); |
182 | |
183 | RTW_WBR(regs, RTW_PHYCFG, RTW_PHYCFG); |
184 | |
185 | for (i = rtw_macbangbits_timeout; --i >= 0; delay(1)) { |
186 | if ((RTW_READ(regs, RTW_PHYCFG) & RTW_PHYCFG_MAC_POLL) == 0) { |
187 | RTW_DPRINTF(RTW_DEBUG_PHY, |
188 | ("%s: finished in %dus\n" , __func__, |
189 | rtw_macbangbits_timeout - i)); |
190 | return 0; |
191 | } |
192 | RTW_RBR(regs, RTW_PHYCFG, RTW_PHYCFG); /* XXX paranoia? */ |
193 | } |
194 | |
195 | printf("%s: RTW_PHYCFG_MAC_POLL still set.\n" , __func__); |
196 | return -1; |
197 | } |
198 | |
199 | static uint32_t |
200 | rtw_grf5101_host_crypt(u_int addr, uint32_t val) |
201 | { |
202 | /* TBD */ |
203 | return 0; |
204 | } |
205 | |
206 | static uint32_t |
207 | rtw_grf5101_mac_crypt(u_int addr, uint32_t val) |
208 | { |
209 | uint32_t data_and_addr; |
210 | #define (d, which) (((d) >> (4 * (which))) & 0xf) |
211 | static uint8_t caesar[16] = {0x0, 0x8, 0x4, 0xc, |
212 | 0x2, 0xa, 0x6, 0xe, |
213 | 0x1, 0x9, 0x5, 0xd, |
214 | 0x3, 0xb, 0x7, 0xf}; |
215 | |
216 | data_and_addr = caesar[EXTRACT_NIBBLE(val, 2)] | |
217 | (caesar[EXTRACT_NIBBLE(val, 1)] << 4) | |
218 | (caesar[EXTRACT_NIBBLE(val, 0)] << 8) | |
219 | (caesar[(addr >> 1) & 0xf] << 12) | |
220 | ((addr & 0x1) << 16) | |
221 | (caesar[EXTRACT_NIBBLE(val, 3)] << 24); |
222 | return __SHIFTIN(data_and_addr, |
223 | RTW_PHYCFG_MAC_PHILIPS_ADDR_MASK|RTW_PHYCFG_MAC_PHILIPS_DATA_MASK); |
224 | #undef EXTRACT_NIBBLE |
225 | } |
226 | |
227 | #ifdef RTW_DEBUG |
228 | static inline const char * |
229 | rtw_rfchipid_string(enum rtw_rfchipid rfchipid) |
230 | { |
231 | switch (rfchipid) { |
232 | case RTW_RFCHIPID_MAXIM: |
233 | return "Maxim" ; |
234 | case RTW_RFCHIPID_PHILIPS: |
235 | return "Philips" ; |
236 | case RTW_RFCHIPID_GCT: |
237 | return "GCT" ; |
238 | case RTW_RFCHIPID_RFMD: |
239 | return "RFMD" ; |
240 | case RTW_RFCHIPID_INTERSIL: |
241 | return "Intersil" ; |
242 | default: |
243 | return "unknown" ; |
244 | } |
245 | } |
246 | #endif |
247 | |
248 | /* Bang bits over the 3-wire interface. */ |
249 | int |
250 | rtw_rf_hostwrite(struct rtw_regs *regs, enum rtw_rfchipid rfchipid, |
251 | u_int addr, uint32_t val) |
252 | { |
253 | u_int nbits; |
254 | int lo_to_hi; |
255 | uint32_t bits; |
256 | |
257 | RTW_DPRINTF(RTW_DEBUG_PHYIO, ("%s: %s[%u] <- %#08x\n" , __func__, |
258 | rtw_rfchipid_string(rfchipid), addr, val)); |
259 | |
260 | switch (rfchipid) { |
261 | case RTW_RFCHIPID_MAXIM: |
262 | nbits = 16; |
263 | lo_to_hi = 0; |
264 | bits = __SHIFTIN(val, MAX2820_TWI_DATA_MASK) | |
265 | __SHIFTIN(addr, MAX2820_TWI_ADDR_MASK); |
266 | break; |
267 | case RTW_RFCHIPID_PHILIPS: |
268 | KASSERT((addr & ~__SHIFTOUT_MASK(SA2400_TWI_ADDR_MASK)) == 0); |
269 | KASSERT((val & ~__SHIFTOUT_MASK(SA2400_TWI_DATA_MASK)) == 0); |
270 | bits = __SHIFTIN(val, SA2400_TWI_DATA_MASK) | |
271 | __SHIFTIN(addr, SA2400_TWI_ADDR_MASK) | SA2400_TWI_WREN; |
272 | nbits = 32; |
273 | lo_to_hi = 1; |
274 | break; |
275 | case RTW_RFCHIPID_GCT: |
276 | KASSERT((addr & ~__SHIFTOUT_MASK(SI4126_TWI_ADDR_MASK)) == 0); |
277 | KASSERT((val & ~__SHIFTOUT_MASK(SI4126_TWI_DATA_MASK)) == 0); |
278 | bits = rtw_grf5101_host_crypt(addr, val); |
279 | nbits = 21; |
280 | lo_to_hi = 1; |
281 | break; |
282 | case RTW_RFCHIPID_RFMD: |
283 | KASSERT((addr & ~__SHIFTOUT_MASK(SI4126_TWI_ADDR_MASK)) == 0); |
284 | KASSERT((val & ~__SHIFTOUT_MASK(SI4126_TWI_DATA_MASK)) == 0); |
285 | bits = __SHIFTIN(val, SI4126_TWI_DATA_MASK) | |
286 | __SHIFTIN(addr, SI4126_TWI_ADDR_MASK); |
287 | nbits = 22; |
288 | lo_to_hi = 0; |
289 | break; |
290 | case RTW_RFCHIPID_INTERSIL: |
291 | default: |
292 | printf("%s: unknown rfchipid %d\n" , __func__, rfchipid); |
293 | return -1; |
294 | } |
295 | |
296 | rtw_rf_hostbangbits(regs, bits, lo_to_hi, nbits); |
297 | |
298 | return 0; |
299 | } |
300 | |
301 | static uint32_t |
302 | rtw_maxim_swizzle(u_int addr, uint32_t val) |
303 | { |
304 | uint32_t hidata, lodata; |
305 | |
306 | KASSERT((val & ~(RTW_MAXIM_LODATA_MASK|RTW_MAXIM_HIDATA_MASK)) == 0); |
307 | lodata = __SHIFTOUT(val, RTW_MAXIM_LODATA_MASK); |
308 | hidata = __SHIFTOUT(val, RTW_MAXIM_HIDATA_MASK); |
309 | return __SHIFTIN(lodata, RTW_PHYCFG_MAC_MAXIM_LODATA_MASK) | |
310 | __SHIFTIN(hidata, RTW_PHYCFG_MAC_MAXIM_HIDATA_MASK) | |
311 | __SHIFTIN(addr, RTW_PHYCFG_MAC_MAXIM_ADDR_MASK); |
312 | } |
313 | |
314 | /* Tell the MAC what to bang over the 3-wire interface. */ |
315 | int |
316 | rtw_rf_macwrite(struct rtw_regs *regs, enum rtw_rfchipid rfchipid, |
317 | u_int addr, uint32_t val) |
318 | { |
319 | uint32_t reg; |
320 | |
321 | RTW_DPRINTF(RTW_DEBUG_PHYIO, ("%s: %s[%u] <- %#08x\n" , __func__, |
322 | rtw_rfchipid_string(rfchipid), addr, val)); |
323 | |
324 | switch (rfchipid) { |
325 | case RTW_RFCHIPID_GCT: |
326 | reg = rtw_grf5101_mac_crypt(addr, val); |
327 | break; |
328 | case RTW_RFCHIPID_MAXIM: |
329 | reg = rtw_maxim_swizzle(addr, val); |
330 | break; |
331 | default: /* XXX */ |
332 | case RTW_RFCHIPID_PHILIPS: |
333 | KASSERT( |
334 | (addr & ~__SHIFTOUT_MASK(RTW_PHYCFG_MAC_PHILIPS_ADDR_MASK)) == 0); |
335 | KASSERT( |
336 | (val & ~__SHIFTOUT_MASK(RTW_PHYCFG_MAC_PHILIPS_DATA_MASK)) == 0); |
337 | |
338 | reg = __SHIFTIN(addr, RTW_PHYCFG_MAC_PHILIPS_ADDR_MASK) | |
339 | __SHIFTIN(val, RTW_PHYCFG_MAC_PHILIPS_DATA_MASK); |
340 | } |
341 | |
342 | switch (rfchipid) { |
343 | case RTW_RFCHIPID_GCT: |
344 | case RTW_RFCHIPID_MAXIM: |
345 | case RTW_RFCHIPID_RFMD: |
346 | reg |= RTW_PHYCFG_MAC_RFTYPE_RFMD; |
347 | break; |
348 | case RTW_RFCHIPID_INTERSIL: |
349 | reg |= RTW_PHYCFG_MAC_RFTYPE_INTERSIL; |
350 | break; |
351 | case RTW_RFCHIPID_PHILIPS: |
352 | reg |= RTW_PHYCFG_MAC_RFTYPE_PHILIPS; |
353 | break; |
354 | default: |
355 | printf("%s: unknown rfchipid %d\n" , __func__, rfchipid); |
356 | return -1; |
357 | } |
358 | |
359 | return rtw_rf_macbangbits(regs, reg); |
360 | } |
361 | |