The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/rtwphyio.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 89e88278290b30d520e3db2cb4107983


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.