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 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 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