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