1 /* 2 * Copyright 2007 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 input/output with the Philips SA2400 RF front-end and 37 * the baseband processor built into the Realtek RTL8180. 38 */ 39 40 #pragma ident "%Z%%M% %I% %E% SMI" 41 42 43 #include <sys/param.h> 44 #include <sys/types.h> 45 #include <sys/signal.h> 46 #include <sys/stream.h> 47 #include <sys/termio.h> 48 #include <sys/errno.h> 49 #include <sys/file.h> 50 #include <sys/cmn_err.h> 51 #include <sys/stropts.h> 52 #include <sys/strtty.h> 53 #include <sys/kbio.h> 54 #include <sys/cred.h> 55 #include <sys/stat.h> 56 #include <sys/consdev.h> 57 #include <sys/kmem.h> 58 #include <sys/modctl.h> 59 #include <sys/ddi.h> 60 #include <sys/sunddi.h> 61 #include <sys/pci.h> 62 #include <sys/errno.h> 63 #include <sys/gld.h> 64 #include <sys/dlpi.h> 65 #include <sys/ethernet.h> 66 #include <sys/list.h> 67 #include <sys/byteorder.h> 68 #include <sys/strsun.h> 69 #include <inet/common.h> 70 #include <inet/nd.h> 71 #include <inet/mi.h> 72 73 74 #include "rtwreg.h" 75 #include "max2820reg.h" 76 #include "sa2400reg.h" 77 #include "si4136reg.h" 78 #include "rtwvar.h" 79 #include "rtwphyio.h" 80 #include "rtwphy.h" 81 82 static int rtw_macbangbits_timeout = 100; 83 84 uint8_t 85 rtw_bbp_read(struct rtw_regs *regs, uint_t addr) 86 { 87 RTW_WRITE(regs, RTW_BB, 88 LSHIFT(addr, RTW_BB_ADDR_MASK) | RTW_BB_RD_MASK | RTW_BB_WR_MASK); 89 DELAY(10); 90 RTW_WBR(regs, RTW_BB, RTW_BB); 91 return (MASK_AND_RSHIFT(RTW_READ(regs, RTW_BB), RTW_BB_RD_MASK)); 92 } 93 94 int 95 rtw_bbp_write(struct rtw_regs *regs, uint_t addr, uint_t val) 96 { 97 #define BBP_WRITE_ITERS 50 98 #define BBP_WRITE_DELAY 1 99 int i; 100 uint32_t wrbbp, rdbbp; 101 102 RTW_DPRINTF(RTW_DEBUG_PHYIO, 103 "%s: bbp[%u] <- %u\n", __func__, addr, val); 104 105 wrbbp = LSHIFT(addr, RTW_BB_ADDR_MASK) | RTW_BB_WREN | 106 LSHIFT(val, RTW_BB_WR_MASK) | RTW_BB_RD_MASK, 107 rdbbp = LSHIFT(addr, RTW_BB_ADDR_MASK) | 108 RTW_BB_WR_MASK | RTW_BB_RD_MASK; 109 110 RTW_DPRINTF(RTW_DEBUG_PHYIO, 111 "%s: rdbbp = %08x, wrbbp = %08x\n", __func__, rdbbp, wrbbp); 112 113 for (i = BBP_WRITE_ITERS; --i >= 0; ) { 114 RTW_RBW(regs, RTW_BB, RTW_BB); 115 RTW_WRITE(regs, RTW_BB, wrbbp); 116 RTW_SYNC(regs, RTW_BB, RTW_BB); 117 RTW_WRITE(regs, RTW_BB, rdbbp); 118 RTW_SYNC(regs, RTW_BB, RTW_BB); 119 DELAY(BBP_WRITE_DELAY); /* 1 microsecond */ 120 if (MASK_AND_RSHIFT(RTW_READ(regs, RTW_BB), 121 RTW_BB_RD_MASK) == val) { 122 RTW_DPRINTF(RTW_DEBUG_PHYIO, 123 "%s: finished in %dus\n", __func__, 124 BBP_WRITE_DELAY * (BBP_WRITE_ITERS - i)); 125 return (0); 126 } 127 DELAY(BBP_WRITE_DELAY); /* again */ 128 } 129 cmn_err(CE_NOTE, "%s: timeout\n", __func__); 130 return (-1); 131 } 132 133 /* 134 * Help rtw_rf_hostwrite bang bits to RF over 3-wire interface. 135 */ 136 static void 137 rtw_rf_hostbangbits(struct rtw_regs *regs, uint32_t bits, int lo_to_hi, 138 uint_t nbits) 139 { 140 int i; 141 uint32_t mask, reg; 142 143 RTW_DPRINTF(RTW_DEBUG_PHYIO, 144 "%s: %u bits, %08x, %s\n", __func__, nbits, bits, 145 (lo_to_hi) ? "lo to hi" : "hi to lo"); 146 147 reg = RTW_PHYCFG_HST; 148 RTW_WRITE(regs, RTW_PHYCFG, reg); 149 RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG); 150 151 if (lo_to_hi) 152 mask = 0x1; 153 else 154 mask = 1 << (nbits - 1); 155 156 for (i = 0; i < nbits; i++) { 157 RTW_DPRINTF(RTW_DEBUG_PHYBITIO, 158 "%s: bits %08x mask %08x -> bit %08x\n", 159 __func__, bits, mask, bits & mask); 160 161 if ((bits & mask) != 0) 162 reg |= RTW_PHYCFG_HST_DATA; 163 else 164 reg &= ~RTW_PHYCFG_HST_DATA; 165 166 reg |= RTW_PHYCFG_HST_CLK; 167 RTW_WRITE(regs, RTW_PHYCFG, reg); 168 RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG); 169 170 DELAY(2); /* arbitrary delay */ 171 172 reg &= ~RTW_PHYCFG_HST_CLK; 173 RTW_WRITE(regs, RTW_PHYCFG, reg); 174 RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG); 175 176 if (lo_to_hi) 177 mask <<= 1; 178 else 179 mask >>= 1; 180 } 181 182 reg |= RTW_PHYCFG_HST_EN; 183 RTW_WRITE(regs, RTW_PHYCFG, reg); 184 RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG); 185 } 186 187 /* 188 * Help rtw_rf_macwrite: tell MAC to bang bits to RF over the 3-wire 189 * interface. 190 */ 191 static int 192 rtw_rf_macbangbits(struct rtw_regs *regs, uint32_t reg) 193 { 194 int i; 195 196 RTW_DPRINTF(RTW_DEBUG_PHY, "%s: %08x\n", __func__, reg); 197 198 RTW_WRITE(regs, RTW_PHYCFG, RTW_PHYCFG_MAC_POLL | reg); 199 200 RTW_WBR(regs, RTW_PHYCFG, RTW_PHYCFG); 201 202 for (i = rtw_macbangbits_timeout; --i >= 0; DELAY(1)) { 203 if ((RTW_READ(regs, RTW_PHYCFG) & RTW_PHYCFG_MAC_POLL) == 0) { 204 RTW_DPRINTF(RTW_DEBUG_PHY, 205 "%s: finished in %dus\n", __func__, 206 rtw_macbangbits_timeout - i); 207 return (0); 208 } 209 RTW_RBR(regs, RTW_PHYCFG, RTW_PHYCFG); /* paranoia? */ 210 } 211 212 cmn_err(CE_NOTE, "%s: RTW_PHYCFG_MAC_POLL still set.\n", __func__); 213 return (-1); 214 } 215 216 /*ARGSUSED*/ 217 static uint32_t 218 rtw_grf5101_host_crypt(uint_t addr, uint32_t val) 219 { 220 /* TBD */ 221 return (0); 222 } 223 224 static uint32_t 225 rtw_grf5101_mac_crypt(uint_t addr, uint32_t val) 226 { 227 uint32_t data_and_addr; 228 #define EXTRACT_NIBBLE(d, which) (((d) >> (4 * (which))) & 0xf) 229 static uint8_t caesar[16] = 230 { 231 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 232 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf 233 }; 234 235 data_and_addr = caesar[EXTRACT_NIBBLE(val, 2)] | 236 (caesar[EXTRACT_NIBBLE(val, 1)] << 4) | 237 (caesar[EXTRACT_NIBBLE(val, 0)] << 8) | 238 (caesar[(addr >> 1) & 0xf] << 12) | 239 ((addr & 0x1) << 16) | 240 (caesar[EXTRACT_NIBBLE(val, 3)] << 24); 241 return (LSHIFT(data_and_addr, RTW_PHYCFG_MAC_PHILIPS_ADDR_MASK | 242 RTW_PHYCFG_MAC_PHILIPS_DATA_MASK)); 243 #undef EXTRACT_NIBBLE 244 } 245 246 static const char * 247 rtw_rfchipid_string(enum rtw_rfchipid rfchipid) 248 { 249 switch (rfchipid) { 250 case RTW_RFCHIPID_MAXIM: 251 return ("Maxim"); 252 case RTW_RFCHIPID_PHILIPS: 253 return ("Philips"); 254 case RTW_RFCHIPID_GCT: 255 return ("GCT"); 256 case RTW_RFCHIPID_RFMD: 257 return ("RFMD"); 258 case RTW_RFCHIPID_INTERSIL: 259 return ("Intersil"); 260 default: 261 return ("unknown"); 262 } 263 } 264 265 /* 266 * Bang bits over the 3-wire interface. 267 */ 268 int 269 rtw_rf_hostwrite(struct rtw_regs *regs, enum rtw_rfchipid rfchipid, 270 uint_t addr, uint32_t val) 271 { 272 uint_t nbits; 273 int lo_to_hi; 274 uint32_t bits; 275 276 RTW_DPRINTF(RTW_DEBUG_PHYIO, "%s: %s[%u] <- %08x\n", __func__, 277 rtw_rfchipid_string(rfchipid), addr, val); 278 279 switch (rfchipid) { 280 case RTW_RFCHIPID_MAXIM: 281 nbits = 16; 282 lo_to_hi = 0; 283 bits = LSHIFT(val, MAX2820_TWI_DATA_MASK) | 284 LSHIFT(addr, MAX2820_TWI_ADDR_MASK); 285 break; 286 case RTW_RFCHIPID_PHILIPS: 287 bits = LSHIFT(val, SA2400_TWI_DATA_MASK) | 288 LSHIFT(addr, SA2400_TWI_ADDR_MASK) | SA2400_TWI_WREN; 289 nbits = 32; 290 lo_to_hi = 1; 291 break; 292 case RTW_RFCHIPID_GCT: 293 case RTW_RFCHIPID_RFMD: 294 if (rfchipid == RTW_RFCHIPID_GCT) 295 bits = rtw_grf5101_host_crypt(addr, val); 296 else { 297 bits = LSHIFT(val, SI4126_TWI_DATA_MASK) | 298 LSHIFT(addr, SI4126_TWI_ADDR_MASK); 299 } 300 nbits = 22; 301 lo_to_hi = 0; 302 break; 303 case RTW_RFCHIPID_INTERSIL: 304 default: 305 cmn_err(CE_WARN, "%s: unknown rfchipid %d\n", 306 __func__, rfchipid); 307 return (-1); 308 } 309 310 rtw_rf_hostbangbits(regs, bits, lo_to_hi, nbits); 311 312 return (0); 313 } 314 315 static uint32_t 316 rtw_maxim_swizzle(uint_t addr, uint32_t val) 317 { 318 uint32_t hidata, lodata; 319 320 lodata = MASK_AND_RSHIFT(val, RTW_MAXIM_LODATA_MASK); 321 hidata = MASK_AND_RSHIFT(val, RTW_MAXIM_HIDATA_MASK); 322 return (LSHIFT(lodata, RTW_PHYCFG_MAC_MAXIM_LODATA_MASK) | 323 LSHIFT(hidata, RTW_PHYCFG_MAC_MAXIM_HIDATA_MASK) | 324 LSHIFT(addr, RTW_PHYCFG_MAC_MAXIM_ADDR_MASK)); 325 } 326 327 /* 328 * Tell the MAC what to bang over the 3-wire interface. 329 */ 330 int 331 rtw_rf_macwrite(struct rtw_regs *regs, enum rtw_rfchipid rfchipid, 332 uint_t addr, uint32_t val) 333 { 334 uint32_t reg; 335 336 RTW_DPRINTF(RTW_DEBUG_PHYIO, "%s: %s[%u] <- %08x\n", __func__, 337 rtw_rfchipid_string(rfchipid), addr, val); 338 339 switch (rfchipid) { 340 case RTW_RFCHIPID_GCT: 341 reg = rtw_grf5101_mac_crypt(addr, val); 342 break; 343 case RTW_RFCHIPID_MAXIM: 344 reg = rtw_maxim_swizzle(addr, val); 345 break; 346 default: 347 case RTW_RFCHIPID_PHILIPS: 348 349 reg = LSHIFT(addr, RTW_PHYCFG_MAC_PHILIPS_ADDR_MASK) | 350 LSHIFT(val, RTW_PHYCFG_MAC_PHILIPS_DATA_MASK); 351 } 352 353 switch (rfchipid) { 354 case RTW_RFCHIPID_GCT: 355 case RTW_RFCHIPID_MAXIM: 356 case RTW_RFCHIPID_RFMD: 357 reg |= RTW_PHYCFG_MAC_RFTYPE_RFMD; 358 break; 359 case RTW_RFCHIPID_INTERSIL: 360 reg |= RTW_PHYCFG_MAC_RFTYPE_INTERSIL; 361 break; 362 case RTW_RFCHIPID_PHILIPS: 363 reg |= RTW_PHYCFG_MAC_RFTYPE_PHILIPS; 364 break; 365 default: 366 cmn_err(CE_WARN, "%s: unknown rfchipid %d\n", 367 __func__, rfchipid); 368 return (-1); 369 } 370 371 return (rtw_rf_macbangbits(regs, reg)); 372 } 373