1 /* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */
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>
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.
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.
21 #include <sys/cdefs.h>
22 __FBSDID("$FreeBSD$");
26 #include <sys/param.h>
28 #include <sys/mutex.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>
37 #include <sys/endian.h>
40 #include <net/ethernet.h>
41 #include <net/if_media.h>
43 #include <net80211/ieee80211_var.h>
44 #include <net80211/ieee80211_radiotap.h>
46 #include <dev/rtwn/if_rtwnreg.h>
47 #include <dev/rtwn/if_rtwnvar.h>
49 #include <dev/rtwn/if_rtwn_debug.h>
50 #include <dev/rtwn/if_rtwn_efuse.h>
52 #include <dev/rtwn/rtl8192c/r92c_reg.h>
56 rtwn_efuse_switch_power(struct rtwn_softc *sc)
61 error = rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_ON);
65 reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN);
66 if (!(reg & R92C_SYS_FUNC_EN_ELDR)) {
67 error = rtwn_write_2(sc, R92C_SYS_FUNC_EN,
68 reg | R92C_SYS_FUNC_EN_ELDR);
72 reg = rtwn_read_2(sc, R92C_SYS_CLKR);
73 if ((reg & (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) !=
74 (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) {
75 error = rtwn_write_2(sc, R92C_SYS_CLKR,
76 reg | R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M);
85 rtwn_efuse_read_next(struct rtwn_softc *sc, uint8_t *val)
90 if (sc->next_rom_addr >= sc->efuse_maxlen)
93 reg = rtwn_read_4(sc, R92C_EFUSE_CTRL);
94 reg = RW(reg, R92C_EFUSE_CTRL_ADDR, sc->next_rom_addr);
95 reg &= ~R92C_EFUSE_CTRL_VALID;
97 error = rtwn_write_4(sc, R92C_EFUSE_CTRL, reg);
100 /* Wait for read operation to complete. */
101 for (ntries = 0; ntries < 100; ntries++) {
102 reg = rtwn_read_4(sc, R92C_EFUSE_CTRL);
103 if (reg & R92C_EFUSE_CTRL_VALID)
108 device_printf(sc->sc_dev,
109 "could not read efuse byte at address 0x%x\n",
114 *val = MS(reg, R92C_EFUSE_CTRL_DATA);
121 rtwn_efuse_read_data(struct rtwn_softc *sc, uint8_t *rom, uint8_t off,
127 for (i = 0; i < 4; i++) {
131 addr = off * 8 + i * 2;
132 if (addr + 1 >= sc->efuse_maplen)
135 error = rtwn_efuse_read_next(sc, ®);
138 RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "rom[0x%03X] == 0x%02X\n",
142 error = rtwn_efuse_read_next(sc, ®);
145 RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "rom[0x%03X] == 0x%02X\n",
155 rtwn_dump_rom_contents(struct rtwn_softc *sc, uint8_t *rom, uint16_t size)
159 /* Dump ROM contents. */
160 device_printf(sc->sc_dev, "%s:", __func__);
161 for (i = 0; i < size; i++) {
163 printf("\n%03X: ", i);
167 printf("%02X", rom[i]);
174 rtwn_efuse_read(struct rtwn_softc *sc, uint8_t *rom, uint16_t size)
176 #define RTWN_CHK(res) do { \
177 if ((error = res) != 0) \
180 uint8_t msk, off, reg;
183 /* Read full ROM image. */
184 sc->next_rom_addr = 0;
185 memset(rom, 0xff, size);
187 RTWN_CHK(rtwn_efuse_read_next(sc, ®));
188 while (reg != 0xff) {
189 /* check for extended header */
190 if ((sc->sc_flags & RTWN_FLAG_EXT_HDR) &&
191 (reg & 0x1f) == 0x0f) {
193 RTWN_CHK(rtwn_efuse_read_next(sc, ®));
195 if ((reg & 0x0f) != 0x0f)
196 off = ((reg & 0xf0) >> 1) | off;
203 RTWN_CHK(rtwn_efuse_read_data(sc, rom, off, msk));
204 RTWN_CHK(rtwn_efuse_read_next(sc, ®));
210 if (sc->sc_debug & RTWN_DEBUG_ROM)
211 rtwn_dump_rom_contents(sc, rom, size);
214 /* Device-specific. */
215 rtwn_efuse_postread(sc);
218 device_printf(sc->sc_dev, "%s: error while reading ROM\n",
227 rtwn_efuse_read_prepare(struct rtwn_softc *sc, uint8_t *rom, uint16_t size)
231 error = rtwn_efuse_switch_power(sc);
235 error = rtwn_efuse_read(sc, rom, size);
238 rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_OFF);
244 rtwn_read_rom(struct rtwn_softc *sc)
249 rom = malloc(sc->efuse_maplen, M_TEMP, M_WAITOK);
251 /* Read full ROM image. */
253 error = rtwn_efuse_read_prepare(sc, rom, sc->efuse_maplen);
258 /* Parse & save data in softc. */
259 rtwn_parse_rom(sc, rom);