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