]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/rtwn/if_rtwn_efuse.c
Import riscv DTS files
[FreeBSD/FreeBSD.git] / sys / dev / rtwn / if_rtwn_efuse.c
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
55 static int
56 rtwn_efuse_switch_power(struct rtwn_softc *sc)
57 {
58         uint32_t reg;
59         int error;
60
61         error = rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_ON);
62         if (error != 0)
63                 return (error);
64
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);
69                 if (error != 0)
70                         return (error);
71         }
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);
77                 if (error != 0)
78                         return (error);
79         }
80
81         return (0);
82 }
83
84 int
85 rtwn_efuse_read_next(struct rtwn_softc *sc, uint8_t *val)
86 {
87         uint32_t reg;
88         int ntries, error;
89
90         if (sc->next_rom_addr >= sc->efuse_maxlen)
91                 return (EFAULT);
92
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;
96
97         error = rtwn_write_4(sc, R92C_EFUSE_CTRL, reg);
98         if (error != 0)
99                 return (error);
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)
104                         break;
105                 rtwn_delay(sc, 10);
106         }
107         if (ntries == 100) {
108                 device_printf(sc->sc_dev,
109                     "could not read efuse byte at address 0x%x\n",
110                     sc->next_rom_addr);
111                 return (ETIMEDOUT);
112         }
113
114         *val = MS(reg, R92C_EFUSE_CTRL_DATA);
115         sc->next_rom_addr++;
116
117         return (0);
118 }
119
120 static int
121 rtwn_efuse_read_data(struct rtwn_softc *sc, uint8_t *rom, uint8_t off,
122     uint8_t msk)
123 {
124         uint8_t reg;
125         int addr, i, error;
126
127         for (i = 0; i < 4; i++) {
128                 if (msk & (1 << i))
129                         continue;
130
131                 addr = off * 8 + i * 2;
132                 if (addr + 1 >= sc->efuse_maplen)
133                         return (EFAULT);
134
135                 error = rtwn_efuse_read_next(sc, &reg);
136                 if (error != 0)
137                         return (error);
138                 RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "rom[0x%03X] == 0x%02X\n",
139                     addr, reg);
140                 rom[addr] = reg;
141
142                 error = rtwn_efuse_read_next(sc, &reg);
143                 if (error != 0)
144                         return (error);
145                 RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "rom[0x%03X] == 0x%02X\n",
146                     addr + 1, reg);
147                 rom[addr + 1] = reg;
148         }
149
150         return (0);
151 }
152
153 #ifdef RTWN_DEBUG
154 static void
155 rtwn_dump_rom_contents(struct rtwn_softc *sc, uint8_t *rom, uint16_t size)
156 {
157         int i;
158
159         /* Dump ROM contents. */
160         device_printf(sc->sc_dev, "%s:", __func__);
161         for (i = 0; i < size; i++) {
162                 if (i % 32 == 0)
163                         printf("\n%03X: ", i);
164                 else if (i % 4 == 0)
165                         printf(" ");
166
167                 printf("%02X", rom[i]);
168         }
169         printf("\n");
170 }
171 #endif
172
173 static int
174 rtwn_efuse_read(struct rtwn_softc *sc, uint8_t *rom, uint16_t size)
175 {
176 #define RTWN_CHK(res) do {      \
177         if ((error = res) != 0) \
178                 goto end;       \
179 } while(0)
180         uint8_t msk, off, reg;
181         int error;
182
183         /* Read full ROM image. */
184         sc->next_rom_addr = 0;
185         memset(rom, 0xff, size);
186
187         RTWN_CHK(rtwn_efuse_read_next(sc, &reg));
188         while (reg != 0xff) {
189                 /* check for extended header */
190                 if ((sc->sc_flags & RTWN_FLAG_EXT_HDR) &&
191                     (reg & 0x1f) == 0x0f) {
192                         off = reg >> 5;
193                         RTWN_CHK(rtwn_efuse_read_next(sc, &reg));
194
195                         if ((reg & 0x0f) != 0x0f)
196                                 off = ((reg & 0xf0) >> 1) | off;
197                         else
198                                 continue;
199                 } else
200                         off = reg >> 4;
201                 msk = reg & 0xf;
202
203                 RTWN_CHK(rtwn_efuse_read_data(sc, rom, off, msk));
204                 RTWN_CHK(rtwn_efuse_read_next(sc, &reg));
205         }
206
207 end:
208
209 #ifdef RTWN_DEBUG
210         if (sc->sc_debug & RTWN_DEBUG_ROM)
211                 rtwn_dump_rom_contents(sc, rom, size);
212 #endif
213
214         /* Device-specific. */
215         rtwn_efuse_postread(sc);
216
217         if (error != 0) {
218                 device_printf(sc->sc_dev, "%s: error while reading ROM\n",
219                     __func__);
220         }
221
222         return (error);
223 #undef RTWN_CHK
224 }
225
226 static int
227 rtwn_efuse_read_prepare(struct rtwn_softc *sc, uint8_t *rom, uint16_t size)
228 {
229         int error;
230
231         error = rtwn_efuse_switch_power(sc);
232         if (error != 0)
233                 goto fail;
234
235         error = rtwn_efuse_read(sc, rom, size);
236
237 fail:
238         rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_OFF);
239
240         return (error);
241 }
242
243 int
244 rtwn_read_rom(struct rtwn_softc *sc)
245 {
246         uint8_t *rom;
247         int error;
248
249         rom = malloc(sc->efuse_maplen, M_TEMP, M_WAITOK);
250
251         /* Read full ROM image. */
252         RTWN_LOCK(sc);
253         error = rtwn_efuse_read_prepare(sc, rom, sc->efuse_maplen);
254         RTWN_UNLOCK(sc);
255         if (error != 0)
256                 goto fail;
257
258         /* Parse & save data in softc. */
259         rtwn_parse_rom(sc, rom);
260
261 fail:
262         free(rom, M_TEMP);
263
264         return (error);
265 }