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/rtwn/if_rtwn_efuse.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 /*      $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $   */
    2 
    3 /*-
    4  * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
    5  * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
    6  * Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
    7  *
    8  * Permission to use, copy, modify, and distribute this software for any
    9  * purpose with or without fee is hereby granted, provided that the above
   10  * copyright notice and this permission notice appear in all copies.
   11  *
   12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   19  */
   20 
   21 #include <sys/cdefs.h>
   22 __FBSDID("$FreeBSD$");
   23 
   24 #include "opt_wlan.h"
   25 
   26 #include <sys/param.h>
   27 #include <sys/lock.h>
   28 #include <sys/mutex.h>
   29 #include <sys/mbuf.h>
   30 #include <sys/kernel.h>
   31 #include <sys/socket.h>
   32 #include <sys/systm.h>
   33 #include <sys/malloc.h>
   34 #include <sys/queue.h>
   35 #include <sys/taskqueue.h>
   36 #include <sys/bus.h>
   37 #include <sys/endian.h>
   38 
   39 #include <net/if.h>
   40 #include <net/ethernet.h>
   41 #include <net/if_media.h>
   42 
   43 #include <net80211/ieee80211_var.h>
   44 #include <net80211/ieee80211_radiotap.h>
   45 
   46 #include <dev/rtwn/if_rtwnreg.h>
   47 #include <dev/rtwn/if_rtwnvar.h>
   48 
   49 #include <dev/rtwn/if_rtwn_debug.h>
   50 #include <dev/rtwn/if_rtwn_efuse.h>
   51 
   52 #include <dev/rtwn/rtl8192c/r92c_reg.h>
   53 
   54 static int
   55 rtwn_efuse_switch_power(struct rtwn_softc *sc)
   56 {
   57         uint32_t reg;
   58         int error;
   59 
   60         error = rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_ON);
   61         if (error != 0)
   62                 return (error);
   63 
   64         reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN);
   65         if (!(reg & R92C_SYS_FUNC_EN_ELDR)) {
   66                 error = rtwn_write_2(sc, R92C_SYS_FUNC_EN,
   67                     reg | R92C_SYS_FUNC_EN_ELDR);
   68                 if (error != 0)
   69                         return (error);
   70         }
   71         reg = rtwn_read_2(sc, R92C_SYS_CLKR);
   72         if ((reg & (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) !=
   73             (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) {
   74                 error = rtwn_write_2(sc, R92C_SYS_CLKR,
   75                     reg | R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M);
   76                 if (error != 0)
   77                         return (error);
   78         }
   79 
   80         return (0);
   81 }
   82 
   83 int
   84 rtwn_efuse_read_next(struct rtwn_softc *sc, uint8_t *val)
   85 {
   86         uint32_t reg;
   87         int ntries, error;
   88 
   89         if (sc->next_rom_addr >= sc->efuse_maxlen)
   90                 return (EFAULT);
   91 
   92         reg = rtwn_read_4(sc, R92C_EFUSE_CTRL);
   93         reg = RW(reg, R92C_EFUSE_CTRL_ADDR, sc->next_rom_addr);
   94         reg &= ~R92C_EFUSE_CTRL_VALID;
   95 
   96         error = rtwn_write_4(sc, R92C_EFUSE_CTRL, reg);
   97         if (error != 0)
   98                 return (error);
   99         /* Wait for read operation to complete. */
  100         for (ntries = 0; ntries < 100; ntries++) {
  101                 reg = rtwn_read_4(sc, R92C_EFUSE_CTRL);
  102                 if (reg & R92C_EFUSE_CTRL_VALID)
  103                         break;
  104                 rtwn_delay(sc, 10);
  105         }
  106         if (ntries == 100) {
  107                 device_printf(sc->sc_dev,
  108                     "could not read efuse byte at address 0x%x\n",
  109                     sc->next_rom_addr);
  110                 return (ETIMEDOUT);
  111         }
  112 
  113         *val = MS(reg, R92C_EFUSE_CTRL_DATA);
  114         sc->next_rom_addr++;
  115 
  116         return (0);
  117 }
  118 
  119 static int
  120 rtwn_efuse_read_data(struct rtwn_softc *sc, uint8_t *rom, uint8_t off,
  121     uint8_t msk)
  122 {
  123         uint8_t reg;
  124         int addr, i, error;
  125 
  126         for (i = 0; i < 4; i++) {
  127                 if (msk & (1 << i))
  128                         continue;
  129 
  130                 addr = off * 8 + i * 2;
  131                 if (addr + 1 >= sc->efuse_maplen)
  132                         return (EFAULT);
  133 
  134                 error = rtwn_efuse_read_next(sc, &reg);
  135                 if (error != 0)
  136                         return (error);
  137                 RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "rom[0x%03X] == 0x%02X\n",
  138                     addr, reg);
  139                 rom[addr] = reg;
  140 
  141                 error = rtwn_efuse_read_next(sc, &reg);
  142                 if (error != 0)
  143                         return (error);
  144                 RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "rom[0x%03X] == 0x%02X\n",
  145                     addr + 1, reg);
  146                 rom[addr + 1] = reg;
  147         }
  148 
  149         return (0);
  150 }
  151 
  152 #ifdef RTWN_DEBUG
  153 static void
  154 rtwn_dump_rom_contents(struct rtwn_softc *sc, uint8_t *rom, uint16_t size)
  155 {
  156         int i;
  157 
  158         /* Dump ROM contents. */
  159         device_printf(sc->sc_dev, "%s:", __func__);
  160         for (i = 0; i < size; i++) {
  161                 if (i % 32 == 0)
  162                         printf("\n%03X: ", i);
  163                 else if (i % 4 == 0)
  164                         printf(" ");
  165 
  166                 printf("%02X", rom[i]);
  167         }
  168         printf("\n");
  169 }
  170 #endif
  171 
  172 static int
  173 rtwn_efuse_read(struct rtwn_softc *sc, uint8_t *rom, uint16_t size)
  174 {
  175 #define RTWN_CHK(res) do {      \
  176         if ((error = res) != 0) \
  177                 goto end;       \
  178 } while(0)
  179         uint8_t msk, off, reg;
  180         int error;
  181 
  182         /* Read full ROM image. */
  183         sc->next_rom_addr = 0;
  184         memset(rom, 0xff, size);
  185 
  186         RTWN_CHK(rtwn_efuse_read_next(sc, &reg));
  187         while (reg != 0xff) {
  188                 /* check for extended header */
  189                 if ((sc->sc_flags & RTWN_FLAG_EXT_HDR) &&
  190                     (reg & 0x1f) == 0x0f) {
  191                         off = reg >> 5;
  192                         RTWN_CHK(rtwn_efuse_read_next(sc, &reg));
  193 
  194                         if ((reg & 0x0f) != 0x0f)
  195                                 off = ((reg & 0xf0) >> 1) | off;
  196                         else
  197                                 continue;
  198                 } else
  199                         off = reg >> 4;
  200                 msk = reg & 0xf;
  201 
  202                 RTWN_CHK(rtwn_efuse_read_data(sc, rom, off, msk));
  203                 RTWN_CHK(rtwn_efuse_read_next(sc, &reg));
  204         }
  205 
  206 end:
  207 
  208 #ifdef RTWN_DEBUG
  209         if (sc->sc_debug & RTWN_DEBUG_ROM)
  210                 rtwn_dump_rom_contents(sc, rom, size);
  211 #endif
  212 
  213         /* Device-specific. */
  214         rtwn_efuse_postread(sc);
  215 
  216         if (error != 0) {
  217                 device_printf(sc->sc_dev, "%s: error while reading ROM\n",
  218                     __func__);
  219         }
  220 
  221         return (error);
  222 #undef RTWN_CHK
  223 }
  224 
  225 static int
  226 rtwn_efuse_read_prepare(struct rtwn_softc *sc, uint8_t *rom, uint16_t size)
  227 {
  228         int error;
  229 
  230         error = rtwn_efuse_switch_power(sc);
  231         if (error != 0)
  232                 goto fail;
  233 
  234         error = rtwn_efuse_read(sc, rom, size);
  235 
  236 fail:
  237         rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_OFF);
  238 
  239         return (error);
  240 }
  241 
  242 int
  243 rtwn_read_rom(struct rtwn_softc *sc)
  244 {
  245         uint8_t *rom;
  246         int error;
  247 
  248         rom = malloc(sc->efuse_maplen, M_TEMP, M_WAITOK);
  249 
  250         /* Read full ROM image. */
  251         RTWN_LOCK(sc);
  252         error = rtwn_efuse_read_prepare(sc, rom, sc->efuse_maplen);
  253         RTWN_UNLOCK(sc);
  254         if (error != 0)
  255                 goto fail;
  256 
  257         /* Parse & save data in softc. */
  258         rtwn_parse_rom(sc, rom);
  259 
  260 fail:
  261         free(rom, M_TEMP);
  262 
  263         return (error);
  264 }

Cache object: 7f5f5c98e3041855c85f673aabbddf56


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