1/* $NetBSD: rtwphyio.c,v 1.16 2008/03/03 12:30:57 tsutsui 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.16 2008/03/03 12:30:57 tsutsui 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 60static int rtw_macbangbits_timeout = 100; 61 62uint8_t 63rtw_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 73int 74rtw_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. */ 117static inline void 118rtw_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 */ 174static inline int 175rtw_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 199static uint32_t 200rtw_grf5101_host_crypt(u_int addr, uint32_t val) 201{ 202 /* TBD */ 203 return 0; 204} 205 206static uint32_t 207rtw_grf5101_mac_crypt(u_int addr, uint32_t val) 208{ 209 uint32_t data_and_addr; 210#define EXTRACT_NIBBLE(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 227static inline const char * 228rtw_rfchipid_string(enum rtw_rfchipid rfchipid) 229{ 230 switch (rfchipid) { 231 case RTW_RFCHIPID_MAXIM: 232 return "Maxim"; 233 case RTW_RFCHIPID_PHILIPS: 234 return "Philips"; 235 case RTW_RFCHIPID_GCT: 236 return "GCT"; 237 case RTW_RFCHIPID_RFMD: 238 return "RFMD"; 239 case RTW_RFCHIPID_INTERSIL: 240 return "Intersil"; 241 default: 242 return "unknown"; 243 } 244} 245 246/* Bang bits over the 3-wire interface. */ 247int 248rtw_rf_hostwrite(struct rtw_regs *regs, enum rtw_rfchipid rfchipid, 249 u_int addr, uint32_t val) 250{ 251 u_int nbits; 252 int lo_to_hi; 253 uint32_t bits; 254 255 RTW_DPRINTF(RTW_DEBUG_PHYIO, ("%s: %s[%u] <- %#08x\n", __func__, 256 rtw_rfchipid_string(rfchipid), addr, val)); 257 258 switch (rfchipid) { 259 case RTW_RFCHIPID_MAXIM: 260 nbits = 16; 261 lo_to_hi = 0; 262 bits = __SHIFTIN(val, MAX2820_TWI_DATA_MASK) | 263 __SHIFTIN(addr, MAX2820_TWI_ADDR_MASK); 264 break; 265 case RTW_RFCHIPID_PHILIPS: 266 KASSERT((addr & ~__SHIFTOUT_MASK(SA2400_TWI_ADDR_MASK)) == 0); 267 KASSERT((val & ~__SHIFTOUT_MASK(SA2400_TWI_DATA_MASK)) == 0); 268 bits = __SHIFTIN(val, SA2400_TWI_DATA_MASK) | 269 __SHIFTIN(addr, SA2400_TWI_ADDR_MASK) | SA2400_TWI_WREN; 270 nbits = 32; 271 lo_to_hi = 1; 272 break; 273 case RTW_RFCHIPID_GCT: 274 KASSERT((addr & ~__SHIFTOUT_MASK(SI4126_TWI_ADDR_MASK)) == 0); 275 KASSERT((val & ~__SHIFTOUT_MASK(SI4126_TWI_DATA_MASK)) == 0); 276 bits = rtw_grf5101_host_crypt(addr, val); 277 nbits = 21; 278 lo_to_hi = 1; 279 break; 280 case RTW_RFCHIPID_RFMD: 281 KASSERT((addr & ~__SHIFTOUT_MASK(SI4126_TWI_ADDR_MASK)) == 0); 282 KASSERT((val & ~__SHIFTOUT_MASK(SI4126_TWI_DATA_MASK)) == 0); 283 bits = __SHIFTIN(val, SI4126_TWI_DATA_MASK) | 284 __SHIFTIN(addr, SI4126_TWI_ADDR_MASK); 285 nbits = 22; 286 lo_to_hi = 0; 287 break; 288 case RTW_RFCHIPID_INTERSIL: 289 default: 290 printf("%s: unknown rfchipid %d\n", __func__, rfchipid); 291 return -1; 292 } 293 294 rtw_rf_hostbangbits(regs, bits, lo_to_hi, nbits); 295 296 return 0; 297} 298 299static uint32_t 300rtw_maxim_swizzle(u_int addr, uint32_t val) 301{ 302 uint32_t hidata, lodata; 303 304 KASSERT((val & ~(RTW_MAXIM_LODATA_MASK|RTW_MAXIM_HIDATA_MASK)) == 0); 305 lodata = __SHIFTOUT(val, RTW_MAXIM_LODATA_MASK); 306 hidata = __SHIFTOUT(val, RTW_MAXIM_HIDATA_MASK); 307 return __SHIFTIN(lodata, RTW_PHYCFG_MAC_MAXIM_LODATA_MASK) | 308 __SHIFTIN(hidata, RTW_PHYCFG_MAC_MAXIM_HIDATA_MASK) | 309 __SHIFTIN(addr, RTW_PHYCFG_MAC_MAXIM_ADDR_MASK); 310} 311 312/* Tell the MAC what to bang over the 3-wire interface. */ 313int 314rtw_rf_macwrite(struct rtw_regs *regs, enum rtw_rfchipid rfchipid, 315 u_int addr, uint32_t val) 316{ 317 uint32_t reg; 318 319 RTW_DPRINTF(RTW_DEBUG_PHYIO, ("%s: %s[%u] <- %#08x\n", __func__, 320 rtw_rfchipid_string(rfchipid), addr, val)); 321 322 switch (rfchipid) { 323 case RTW_RFCHIPID_GCT: 324 reg = rtw_grf5101_mac_crypt(addr, val); 325 break; 326 case RTW_RFCHIPID_MAXIM: 327 reg = rtw_maxim_swizzle(addr, val); 328 break; 329 default: /* XXX */ 330 case RTW_RFCHIPID_PHILIPS: 331 KASSERT( 332 (addr & ~__SHIFTOUT_MASK(RTW_PHYCFG_MAC_PHILIPS_ADDR_MASK)) == 0); 333 KASSERT( 334 (val & ~__SHIFTOUT_MASK(RTW_PHYCFG_MAC_PHILIPS_DATA_MASK)) == 0); 335 336 reg = __SHIFTIN(addr, RTW_PHYCFG_MAC_PHILIPS_ADDR_MASK) | 337 __SHIFTIN(val, RTW_PHYCFG_MAC_PHILIPS_DATA_MASK); 338 } 339 340 switch (rfchipid) { 341 case RTW_RFCHIPID_GCT: 342 case RTW_RFCHIPID_MAXIM: 343 case RTW_RFCHIPID_RFMD: 344 reg |= RTW_PHYCFG_MAC_RFTYPE_RFMD; 345 break; 346 case RTW_RFCHIPID_INTERSIL: 347 reg |= RTW_PHYCFG_MAC_RFTYPE_INTERSIL; 348 break; 349 case RTW_RFCHIPID_PHILIPS: 350 reg |= RTW_PHYCFG_MAC_RFTYPE_PHILIPS; 351 break; 352 default: 353 printf("%s: unknown rfchipid %d\n", __func__, rfchipid); 354 return -1; 355 } 356 357 return rtw_rf_macbangbits(regs, reg); 358} 359