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

Cache object: 00141fb5bf2e8d7555cd3e084304b40f


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