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