14689Sql147931 /*
2*10448SMikore.Li@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
34689Sql147931 * Use is subject to license terms.
44689Sql147931 */
54689Sql147931 /*
64689Sql147931 * Copyright (c) 2004, 2005 David Young. All rights reserved.
74689Sql147931 *
84689Sql147931 * Programmed for NetBSD by David Young.
94689Sql147931 *
104689Sql147931 * Redistribution and use in source and binary forms, with or without
114689Sql147931 * modification, are permitted provided that the following conditions
124689Sql147931 * are met:
134689Sql147931 * 1. Redistributions of source code must retain the above copyright
144689Sql147931 * notice, this list of conditions and the following disclaimer.
154689Sql147931 * 2. Redistributions in binary form must reproduce the above copyright
164689Sql147931 * notice, this list of conditions and the following disclaimer in the
174689Sql147931 * documentation and/or other materials provided with the distribution.
184689Sql147931 * 3. The name of David Young may not be used to endorse or promote
194689Sql147931 * products derived from this software without specific prior
204689Sql147931 * written permission.
214689Sql147931 *
224689Sql147931 * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY
234689Sql147931 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
244689Sql147931 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
254689Sql147931 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David
264689Sql147931 * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
274689Sql147931 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
284689Sql147931 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
294689Sql147931 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
304689Sql147931 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
314689Sql147931 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
324689Sql147931 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
334689Sql147931 * OF SUCH DAMAGE.
344689Sql147931 */
354689Sql147931 /*
364689Sql147931 * Control input/output with the Philips SA2400 RF front-end and
374689Sql147931 * the baseband processor built into the Realtek RTL8180.
384689Sql147931 */
394689Sql147931 #include <sys/types.h>
40*10448SMikore.Li@Sun.COM #include <sys/sysmacros.h>
414689Sql147931 #include "rtwreg.h"
424689Sql147931 #include "max2820reg.h"
434689Sql147931 #include "sa2400reg.h"
444689Sql147931 #include "si4136reg.h"
454689Sql147931 #include "rtwvar.h"
464689Sql147931 #include "rtwphyio.h"
474689Sql147931 #include "rtwphy.h"
484689Sql147931
494689Sql147931 static int rtw_macbangbits_timeout = 100;
504689Sql147931
514689Sql147931 uint8_t
rtw_bbp_read(struct rtw_regs * regs,uint_t addr)524689Sql147931 rtw_bbp_read(struct rtw_regs *regs, uint_t addr)
534689Sql147931 {
544689Sql147931 RTW_WRITE(regs, RTW_BB,
554689Sql147931 LSHIFT(addr, RTW_BB_ADDR_MASK) | RTW_BB_RD_MASK | RTW_BB_WR_MASK);
564689Sql147931 DELAY(10);
574689Sql147931 RTW_WBR(regs, RTW_BB, RTW_BB);
584689Sql147931 return (MASK_AND_RSHIFT(RTW_READ(regs, RTW_BB), RTW_BB_RD_MASK));
594689Sql147931 }
604689Sql147931
614689Sql147931 int
rtw_bbp_write(struct rtw_regs * regs,uint_t addr,uint_t val)624689Sql147931 rtw_bbp_write(struct rtw_regs *regs, uint_t addr, uint_t val)
634689Sql147931 {
644689Sql147931 #define BBP_WRITE_ITERS 50
654689Sql147931 #define BBP_WRITE_DELAY 1
664689Sql147931 int i;
674689Sql147931 uint32_t wrbbp, rdbbp;
684689Sql147931
694689Sql147931 RTW_DPRINTF(RTW_DEBUG_PHYIO,
704689Sql147931 "%s: bbp[%u] <- %u\n", __func__, addr, val);
714689Sql147931
724689Sql147931 wrbbp = LSHIFT(addr, RTW_BB_ADDR_MASK) | RTW_BB_WREN |
734689Sql147931 LSHIFT(val, RTW_BB_WR_MASK) | RTW_BB_RD_MASK,
744689Sql147931 rdbbp = LSHIFT(addr, RTW_BB_ADDR_MASK) |
754689Sql147931 RTW_BB_WR_MASK | RTW_BB_RD_MASK;
764689Sql147931
774689Sql147931 RTW_DPRINTF(RTW_DEBUG_PHYIO,
784689Sql147931 "%s: rdbbp = %08x, wrbbp = %08x\n", __func__, rdbbp, wrbbp);
794689Sql147931
804689Sql147931 for (i = BBP_WRITE_ITERS; --i >= 0; ) {
814689Sql147931 RTW_RBW(regs, RTW_BB, RTW_BB);
824689Sql147931 RTW_WRITE(regs, RTW_BB, wrbbp);
834689Sql147931 RTW_SYNC(regs, RTW_BB, RTW_BB);
844689Sql147931 RTW_WRITE(regs, RTW_BB, rdbbp);
854689Sql147931 RTW_SYNC(regs, RTW_BB, RTW_BB);
864689Sql147931 DELAY(BBP_WRITE_DELAY); /* 1 microsecond */
874689Sql147931 if (MASK_AND_RSHIFT(RTW_READ(regs, RTW_BB),
884689Sql147931 RTW_BB_RD_MASK) == val) {
894689Sql147931 RTW_DPRINTF(RTW_DEBUG_PHYIO,
904689Sql147931 "%s: finished in %dus\n", __func__,
914689Sql147931 BBP_WRITE_DELAY * (BBP_WRITE_ITERS - i));
924689Sql147931 return (0);
934689Sql147931 }
944689Sql147931 DELAY(BBP_WRITE_DELAY); /* again */
954689Sql147931 }
964689Sql147931 cmn_err(CE_NOTE, "%s: timeout\n", __func__);
974689Sql147931 return (-1);
984689Sql147931 }
994689Sql147931
1004689Sql147931 /*
1014689Sql147931 * Help rtw_rf_hostwrite bang bits to RF over 3-wire interface.
1024689Sql147931 */
1034689Sql147931 static void
rtw_rf_hostbangbits(struct rtw_regs * regs,uint32_t bits,int lo_to_hi,uint_t nbits)1044689Sql147931 rtw_rf_hostbangbits(struct rtw_regs *regs, uint32_t bits, int lo_to_hi,
1054689Sql147931 uint_t nbits)
1064689Sql147931 {
1074689Sql147931 int i;
1084689Sql147931 uint32_t mask, reg;
1094689Sql147931
1104689Sql147931 RTW_DPRINTF(RTW_DEBUG_PHYIO,
1114689Sql147931 "%s: %u bits, %08x, %s\n", __func__, nbits, bits,
1124689Sql147931 (lo_to_hi) ? "lo to hi" : "hi to lo");
1134689Sql147931
1144689Sql147931 reg = RTW_PHYCFG_HST;
1154689Sql147931 RTW_WRITE(regs, RTW_PHYCFG, reg);
1164689Sql147931 RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG);
1174689Sql147931
1184689Sql147931 if (lo_to_hi)
1194689Sql147931 mask = 0x1;
1204689Sql147931 else
1214689Sql147931 mask = 1 << (nbits - 1);
1224689Sql147931
1234689Sql147931 for (i = 0; i < nbits; i++) {
1244689Sql147931 RTW_DPRINTF(RTW_DEBUG_PHYBITIO,
1254689Sql147931 "%s: bits %08x mask %08x -> bit %08x\n",
1264689Sql147931 __func__, bits, mask, bits & mask);
1274689Sql147931
1284689Sql147931 if ((bits & mask) != 0)
1294689Sql147931 reg |= RTW_PHYCFG_HST_DATA;
1304689Sql147931 else
1314689Sql147931 reg &= ~RTW_PHYCFG_HST_DATA;
1324689Sql147931
1334689Sql147931 reg |= RTW_PHYCFG_HST_CLK;
1344689Sql147931 RTW_WRITE(regs, RTW_PHYCFG, reg);
1354689Sql147931 RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG);
1364689Sql147931
1374689Sql147931 DELAY(2); /* arbitrary delay */
1384689Sql147931
1394689Sql147931 reg &= ~RTW_PHYCFG_HST_CLK;
1404689Sql147931 RTW_WRITE(regs, RTW_PHYCFG, reg);
1414689Sql147931 RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG);
1424689Sql147931
1434689Sql147931 if (lo_to_hi)
1444689Sql147931 mask <<= 1;
1454689Sql147931 else
1464689Sql147931 mask >>= 1;
1474689Sql147931 }
1484689Sql147931
1494689Sql147931 reg |= RTW_PHYCFG_HST_EN;
1504689Sql147931 RTW_WRITE(regs, RTW_PHYCFG, reg);
1514689Sql147931 RTW_SYNC(regs, RTW_PHYCFG, RTW_PHYCFG);
1524689Sql147931 }
1534689Sql147931
1544689Sql147931 /*
1554689Sql147931 * Help rtw_rf_macwrite: tell MAC to bang bits to RF over the 3-wire
1564689Sql147931 * interface.
1574689Sql147931 */
1584689Sql147931 static int
rtw_rf_macbangbits(struct rtw_regs * regs,uint32_t reg)1594689Sql147931 rtw_rf_macbangbits(struct rtw_regs *regs, uint32_t reg)
1604689Sql147931 {
1614689Sql147931 int i;
1624689Sql147931
1634689Sql147931 RTW_DPRINTF(RTW_DEBUG_PHY, "%s: %08x\n", __func__, reg);
1644689Sql147931
1654689Sql147931 RTW_WRITE(regs, RTW_PHYCFG, RTW_PHYCFG_MAC_POLL | reg);
1664689Sql147931
1674689Sql147931 RTW_WBR(regs, RTW_PHYCFG, RTW_PHYCFG);
1684689Sql147931
1694689Sql147931 for (i = rtw_macbangbits_timeout; --i >= 0; DELAY(1)) {
1704689Sql147931 if ((RTW_READ(regs, RTW_PHYCFG) & RTW_PHYCFG_MAC_POLL) == 0) {
1714689Sql147931 RTW_DPRINTF(RTW_DEBUG_PHY,
1724689Sql147931 "%s: finished in %dus\n", __func__,
1734689Sql147931 rtw_macbangbits_timeout - i);
1744689Sql147931 return (0);
1754689Sql147931 }
1764689Sql147931 RTW_RBR(regs, RTW_PHYCFG, RTW_PHYCFG); /* paranoia? */
1774689Sql147931 }
1784689Sql147931
1794689Sql147931 cmn_err(CE_NOTE, "%s: RTW_PHYCFG_MAC_POLL still set.\n", __func__);
1804689Sql147931 return (-1);
1814689Sql147931 }
1824689Sql147931
1834689Sql147931 /*ARGSUSED*/
1844689Sql147931 static uint32_t
rtw_grf5101_host_crypt(uint_t addr,uint32_t val)1854689Sql147931 rtw_grf5101_host_crypt(uint_t addr, uint32_t val)
1864689Sql147931 {
1874689Sql147931 /* TBD */
1884689Sql147931 return (0);
1894689Sql147931 }
1904689Sql147931
1914689Sql147931 static uint32_t
rtw_grf5101_mac_crypt(uint_t addr,uint32_t val)1924689Sql147931 rtw_grf5101_mac_crypt(uint_t addr, uint32_t val)
1934689Sql147931 {
1944689Sql147931 uint32_t data_and_addr;
1954689Sql147931 #define EXTRACT_NIBBLE(d, which) (((d) >> (4 * (which))) & 0xf)
1964689Sql147931 static uint8_t caesar[16] =
1974689Sql147931 {
1984689Sql147931 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
1994689Sql147931 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
2004689Sql147931 };
2014689Sql147931
2024689Sql147931 data_and_addr = caesar[EXTRACT_NIBBLE(val, 2)] |
2034689Sql147931 (caesar[EXTRACT_NIBBLE(val, 1)] << 4) |
2044689Sql147931 (caesar[EXTRACT_NIBBLE(val, 0)] << 8) |
2054689Sql147931 (caesar[(addr >> 1) & 0xf] << 12) |
2064689Sql147931 ((addr & 0x1) << 16) |
2074689Sql147931 (caesar[EXTRACT_NIBBLE(val, 3)] << 24);
2084689Sql147931 return (LSHIFT(data_and_addr, RTW_PHYCFG_MAC_PHILIPS_ADDR_MASK |
2094689Sql147931 RTW_PHYCFG_MAC_PHILIPS_DATA_MASK));
2104689Sql147931 #undef EXTRACT_NIBBLE
2114689Sql147931 }
2124689Sql147931
2134689Sql147931 static const char *
rtw_rfchipid_string(enum rtw_rfchipid rfchipid)2144689Sql147931 rtw_rfchipid_string(enum rtw_rfchipid rfchipid)
2154689Sql147931 {
2164689Sql147931 switch (rfchipid) {
2174689Sql147931 case RTW_RFCHIPID_MAXIM:
2184689Sql147931 return ("Maxim");
2194689Sql147931 case RTW_RFCHIPID_PHILIPS:
2204689Sql147931 return ("Philips");
2214689Sql147931 case RTW_RFCHIPID_GCT:
2224689Sql147931 return ("GCT");
2234689Sql147931 case RTW_RFCHIPID_RFMD:
2244689Sql147931 return ("RFMD");
2254689Sql147931 case RTW_RFCHIPID_INTERSIL:
2264689Sql147931 return ("Intersil");
2274689Sql147931 default:
2284689Sql147931 return ("unknown");
2294689Sql147931 }
2304689Sql147931 }
2314689Sql147931
2324689Sql147931 /*
2334689Sql147931 * Bang bits over the 3-wire interface.
2344689Sql147931 */
2354689Sql147931 int
rtw_rf_hostwrite(struct rtw_regs * regs,enum rtw_rfchipid rfchipid,uint_t addr,uint32_t val)2364689Sql147931 rtw_rf_hostwrite(struct rtw_regs *regs, enum rtw_rfchipid rfchipid,
2374689Sql147931 uint_t addr, uint32_t val)
2384689Sql147931 {
2394689Sql147931 uint_t nbits;
2404689Sql147931 int lo_to_hi;
2414689Sql147931 uint32_t bits;
2424689Sql147931
2434689Sql147931 RTW_DPRINTF(RTW_DEBUG_PHYIO, "%s: %s[%u] <- %08x\n", __func__,
2444689Sql147931 rtw_rfchipid_string(rfchipid), addr, val);
2454689Sql147931
2464689Sql147931 switch (rfchipid) {
2474689Sql147931 case RTW_RFCHIPID_MAXIM:
2484689Sql147931 nbits = 16;
2494689Sql147931 lo_to_hi = 0;
2504689Sql147931 bits = LSHIFT(val, MAX2820_TWI_DATA_MASK) |
2514689Sql147931 LSHIFT(addr, MAX2820_TWI_ADDR_MASK);
2524689Sql147931 break;
2534689Sql147931 case RTW_RFCHIPID_PHILIPS:
2544689Sql147931 bits = LSHIFT(val, SA2400_TWI_DATA_MASK) |
2554689Sql147931 LSHIFT(addr, SA2400_TWI_ADDR_MASK) | SA2400_TWI_WREN;
2564689Sql147931 nbits = 32;
2574689Sql147931 lo_to_hi = 1;
2584689Sql147931 break;
2594689Sql147931 case RTW_RFCHIPID_GCT:
2604689Sql147931 case RTW_RFCHIPID_RFMD:
2614689Sql147931 if (rfchipid == RTW_RFCHIPID_GCT)
2624689Sql147931 bits = rtw_grf5101_host_crypt(addr, val);
2634689Sql147931 else {
2644689Sql147931 bits = LSHIFT(val, SI4126_TWI_DATA_MASK) |
2654689Sql147931 LSHIFT(addr, SI4126_TWI_ADDR_MASK);
2664689Sql147931 }
2674689Sql147931 nbits = 22;
2684689Sql147931 lo_to_hi = 0;
2694689Sql147931 break;
2704689Sql147931 case RTW_RFCHIPID_INTERSIL:
2714689Sql147931 default:
2724689Sql147931 cmn_err(CE_WARN, "%s: unknown rfchipid %d\n",
2734689Sql147931 __func__, rfchipid);
2744689Sql147931 return (-1);
2754689Sql147931 }
2764689Sql147931
2774689Sql147931 rtw_rf_hostbangbits(regs, bits, lo_to_hi, nbits);
2784689Sql147931
2794689Sql147931 return (0);
2804689Sql147931 }
2814689Sql147931
2824689Sql147931 static uint32_t
rtw_maxim_swizzle(uint_t addr,uint32_t val)2834689Sql147931 rtw_maxim_swizzle(uint_t addr, uint32_t val)
2844689Sql147931 {
2854689Sql147931 uint32_t hidata, lodata;
2864689Sql147931
2874689Sql147931 lodata = MASK_AND_RSHIFT(val, RTW_MAXIM_LODATA_MASK);
2884689Sql147931 hidata = MASK_AND_RSHIFT(val, RTW_MAXIM_HIDATA_MASK);
2894689Sql147931 return (LSHIFT(lodata, RTW_PHYCFG_MAC_MAXIM_LODATA_MASK) |
2904689Sql147931 LSHIFT(hidata, RTW_PHYCFG_MAC_MAXIM_HIDATA_MASK) |
2914689Sql147931 LSHIFT(addr, RTW_PHYCFG_MAC_MAXIM_ADDR_MASK));
2924689Sql147931 }
2934689Sql147931
2944689Sql147931 /*
2954689Sql147931 * Tell the MAC what to bang over the 3-wire interface.
2964689Sql147931 */
2974689Sql147931 int
rtw_rf_macwrite(struct rtw_regs * regs,enum rtw_rfchipid rfchipid,uint_t addr,uint32_t val)2984689Sql147931 rtw_rf_macwrite(struct rtw_regs *regs, enum rtw_rfchipid rfchipid,
2994689Sql147931 uint_t addr, uint32_t val)
3004689Sql147931 {
3014689Sql147931 uint32_t reg;
3024689Sql147931
3034689Sql147931 RTW_DPRINTF(RTW_DEBUG_PHYIO, "%s: %s[%u] <- %08x\n", __func__,
3044689Sql147931 rtw_rfchipid_string(rfchipid), addr, val);
3054689Sql147931
3064689Sql147931 switch (rfchipid) {
3074689Sql147931 case RTW_RFCHIPID_GCT:
3084689Sql147931 reg = rtw_grf5101_mac_crypt(addr, val);
3094689Sql147931 break;
3104689Sql147931 case RTW_RFCHIPID_MAXIM:
3114689Sql147931 reg = rtw_maxim_swizzle(addr, val);
3124689Sql147931 break;
3134689Sql147931 default:
3144689Sql147931 case RTW_RFCHIPID_PHILIPS:
3154689Sql147931
3164689Sql147931 reg = LSHIFT(addr, RTW_PHYCFG_MAC_PHILIPS_ADDR_MASK) |
3174689Sql147931 LSHIFT(val, RTW_PHYCFG_MAC_PHILIPS_DATA_MASK);
3184689Sql147931 }
3194689Sql147931
3204689Sql147931 switch (rfchipid) {
3214689Sql147931 case RTW_RFCHIPID_GCT:
3224689Sql147931 case RTW_RFCHIPID_MAXIM:
3234689Sql147931 case RTW_RFCHIPID_RFMD:
3244689Sql147931 reg |= RTW_PHYCFG_MAC_RFTYPE_RFMD;
3254689Sql147931 break;
3264689Sql147931 case RTW_RFCHIPID_INTERSIL:
3274689Sql147931 reg |= RTW_PHYCFG_MAC_RFTYPE_INTERSIL;
3284689Sql147931 break;
3294689Sql147931 case RTW_RFCHIPID_PHILIPS:
3304689Sql147931 reg |= RTW_PHYCFG_MAC_RFTYPE_PHILIPS;
3314689Sql147931 break;
3324689Sql147931 default:
3334689Sql147931 cmn_err(CE_WARN, "%s: unknown rfchipid %d\n",
3344689Sql147931 __func__, rfchipid);
3354689Sql147931 return (-1);
3364689Sql147931 }
3374689Sql147931
3384689Sql147931 return (rtw_rf_macbangbits(regs, reg));
3394689Sql147931 }
340