Added new USB device Ralink RT2870
[ralink_drivers/rt2870_fbsd8.git] / rt2870_io.c
blob65dadef9e69c2329008e4e0a45c7e0967e0228e1
2 /*-
3 * Copyright (c) 2009-2010 Alexander Egorenkov <egorenar@gmail.com>
4 * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include "rt2870_io.h"
20 #include "rt2870_reg.h"
23 * Defines and macros
26 #define RT2870_IO_USB_REQ_MCU_CNTL 0x1
27 #define RT2870_IO_USB_REQ_MAC_WRITE_MULTI 0x2
28 #define RT2870_IO_USB_REQ_MAC_READ_MULTI 0x7
29 #define RT2870_IO_USB_REQ_EEPROM_READ_MULTI 0x9
31 #define RT2870_IO_USB_VALUE_MCU_RESET 0x1
32 #define RT2870_IO_USB_VALUE_MCU_RUN 0x8
34 #define RT2870_IO_BYTE_CRC16(byte, crc) \
35 ((uint16_t) (((crc) << 8) ^ rt2870_io_ccitt16[(((crc) >> 8) ^ (byte)) & 255]))
38 * Static function prototypes
41 static int rt2870_io_vendor_req(struct rt2870_softc *sc,
42 uint8_t reqtype, uint8_t req, uint16_t value, uint16_t index,
43 void *buf, uint16_t len);
45 static uint8_t rt2870_io_byte_rev(uint8_t byte);
48 * Static variables
51 static const uint16_t rt2870_io_ccitt16[] =
53 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
54 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
55 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
56 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
57 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
58 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
59 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
60 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
61 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
62 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
63 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
64 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
65 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
66 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
67 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
68 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
69 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
70 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
71 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
72 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
73 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
74 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
75 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
76 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
77 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
78 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
79 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
80 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
81 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
82 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
83 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
84 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
88 * rt2870_io_mac_read
90 uint32_t rt2870_io_mac_read(struct rt2870_softc *sc, uint16_t reg)
92 uint32_t val;
94 rt2870_io_mac_read_multi(sc, reg, &val, sizeof(val));
96 return le32toh(val);
100 * rt2870_io_mac_read_multi
102 void rt2870_io_mac_read_multi(struct rt2870_softc *sc,
103 uint16_t reg, void *buf, size_t len)
105 int error;
107 error = rt2870_io_vendor_req(sc, UT_READ_VENDOR_DEVICE,
108 RT2870_IO_USB_REQ_MAC_READ_MULTI, 0, reg, buf, len);
109 if (error != 0)
110 printf("%s: could not multi read MAC register: reg=0x%04x, error=%s\n",
111 device_get_nameunit(sc->dev), reg, usbd_errstr(error));
115 * rt2870_io_mac_write
117 void rt2870_io_mac_write(struct rt2870_softc *sc,
118 uint16_t reg, uint32_t val)
120 uint32_t tmp;
122 tmp = htole32(val);
124 rt2870_io_mac_write_multi(sc, reg, &tmp, sizeof(uint32_t));
128 * rt2870_io_mac_write_multi
130 void rt2870_io_mac_write_multi(struct rt2870_softc *sc,
131 uint16_t reg, const void *buf, size_t len)
133 const uint16_t *ptr;
134 int i, error;
136 len += len % sizeof(uint16_t);
137 ptr = buf;
139 i = 0;
143 error = rt2870_io_vendor_req(sc, UT_WRITE_VENDOR_DEVICE,
144 RT2870_IO_USB_REQ_MAC_WRITE_MULTI, *ptr++, reg + i, NULL, 0);
146 i += sizeof(uint16_t);
147 len -= sizeof(uint16_t);
148 } while (len > 0 && error == 0);
150 if (error != 0)
151 printf("%s: could not multi write MAC register: reg=0x%04x, error=%s\n",
152 device_get_nameunit(sc->dev), reg, usbd_errstr(error));
156 * rt2870_io_mac_set_region_4
158 void rt2870_io_mac_set_region_4(struct rt2870_softc *sc,
159 uint16_t reg, uint32_t val, size_t len)
161 int i;
163 for (i = 0; i < len; i += sizeof(uint32_t))
164 rt2870_io_mac_write(sc, reg + i, val);
168 * rt2870_io_eeprom_read
170 uint16_t rt2870_io_eeprom_read(struct rt2870_softc *sc, uint16_t addr)
172 uint16_t val;
174 rt2870_io_eeprom_read_multi(sc, addr, &val, sizeof(val));
176 return le16toh(val);
180 * rt2870_io_eeprom_read_multi
182 void rt2870_io_eeprom_read_multi(struct rt2870_softc *sc,
183 uint16_t addr, void *buf, size_t len)
185 int error;
187 error = rt2870_io_vendor_req(sc, UT_READ_VENDOR_DEVICE,
188 RT2870_IO_USB_REQ_EEPROM_READ_MULTI, 0, addr, buf, len);
189 if (error != 0)
190 printf("%s: could not multi read EEPROM: addr=0x%04x, error=%s\n",
191 device_get_nameunit(sc->dev), addr, usbd_errstr(error));
195 * rt2870_io_bbp_read
197 uint8_t rt2870_io_bbp_read(struct rt2870_softc *sc, uint8_t reg)
199 uint32_t val;
200 int ntries;
202 for (ntries = 0; ntries < 10; ntries++)
203 if (!(rt2870_io_mac_read(sc, RT2870_REG_BBP_CSR_CFG) &
204 RT2870_REG_BBP_CSR_BUSY))
205 break;
207 if (ntries == 10)
209 printf("%s: could not read BBP: reg=0x%02x\n",
210 device_get_nameunit(sc->dev), reg);
211 return 0;
214 val = RT2870_REG_BBP_CSR_BUSY |
215 RT2870_REG_BBP_CSR_READ |
216 ((reg & RT2870_REG_BBP_REG_MASK) << RT2870_REG_BBP_REG_SHIFT);
218 rt2870_io_mac_write(sc, RT2870_REG_BBP_CSR_CFG, val);
220 for (ntries = 0; ntries < 10; ntries++)
222 val = rt2870_io_mac_read(sc, RT2870_REG_BBP_CSR_CFG);
223 if (!(val & RT2870_REG_BBP_CSR_BUSY))
224 return ((val >> RT2870_REG_BBP_VAL_SHIFT) &
225 RT2870_REG_BBP_VAL_MASK);
227 DELAY(1);
230 printf("%s: could not read BBP: reg=0x%02x\n",
231 device_get_nameunit(sc->dev), reg);
233 return 0;
237 * rt2870_io_bbp_write
239 void rt2870_io_bbp_write(struct rt2870_softc *sc, uint8_t reg, uint8_t val)
241 uint32_t tmp;
242 int ntries;
244 for (ntries = 0; ntries < 10; ntries++)
245 if (!(rt2870_io_mac_read(sc, RT2870_REG_BBP_CSR_CFG) &
246 RT2870_REG_BBP_CSR_BUSY))
247 break;
249 if (ntries == 10)
251 printf("%s: could not write to BBP: reg=0x%02x\n",
252 device_get_nameunit(sc->dev), reg);
253 return;
256 tmp = RT2870_REG_BBP_CSR_BUSY |
257 ((reg & RT2870_REG_BBP_REG_MASK) << RT2870_REG_BBP_REG_SHIFT) |
258 ((val & RT2870_REG_BBP_VAL_MASK) << RT2870_REG_BBP_VAL_SHIFT);
260 rt2870_io_mac_write(sc, RT2870_REG_BBP_CSR_CFG, tmp);
264 * rt2870_io_rf_write
266 void rt2870_io_rf_write(struct rt2870_softc *sc, uint8_t reg, uint32_t val)
268 int ntries;
270 for (ntries = 0; ntries < 10; ntries++)
271 if (!(rt2870_io_mac_read(sc, RT2870_REG_RF_CSR_CFG0) &
272 RT2870_REG_RF_BUSY))
273 break;
275 if (ntries == 10)
277 printf("%s: could not write to RF: reg=0x%02x\n",
278 device_get_nameunit(sc->dev), reg);
279 return;
282 rt2870_io_mac_write(sc, RT2870_REG_RF_CSR_CFG0, val);
286 * rt2870_io_mcu_cmd
288 void rt2870_io_mcu_cmd(struct rt2870_softc *sc, uint8_t cmd,
289 uint8_t token, uint16_t arg)
291 uint32_t tmp;
292 int ntries;
294 for (ntries = 0; ntries < 100; ntries++)
296 if (!(rt2870_io_mac_read(sc, RT2870_REG_H2M_MAILBOX) &
297 RT2870_REG_H2M_BUSY))
298 break;
300 DELAY(2);
303 if (ntries == 100)
305 printf("%s: could not read H2M: cmd=0x%02x\n",
306 device_get_nameunit(sc->dev), cmd);
307 return;
310 tmp = RT2870_REG_H2M_BUSY | (token << 16) | arg;
312 rt2870_io_mac_write(sc, RT2870_REG_H2M_MAILBOX, tmp);
313 rt2870_io_mac_write(sc, RT2870_REG_H2M_HOST_CMD, cmd);
317 * rt2870_io_mcu_load_ucode
319 int rt2870_io_mcu_load_ucode(struct rt2870_softc *sc,
320 const uint8_t *ucode, size_t len)
322 int i, error, ntries;
323 uint16_t crc;
325 for (i = 0, crc = 0xffff; i < len - 2; i++)
326 crc = RT2870_IO_BYTE_CRC16(rt2870_io_byte_rev(ucode[i]), crc);
328 if (ucode[len - 2] != rt2870_io_byte_rev(crc >> 8) ||
329 ucode[len - 1] != rt2870_io_byte_rev(crc))
331 printf("%s: wrong microcode crc\n",
332 device_get_nameunit(sc->dev));
333 return EINVAL;
336 rt2870_io_mac_write_multi(sc, RT2870_REG_MCU_UCODE_BASE, ucode, len);
338 rt2870_io_mac_write(sc, RT2870_REG_H2M_MAILBOX_CID, 0xffffffff);
339 rt2870_io_mac_write(sc, RT2870_REG_H2M_MAILBOX_STATUS, 0xffffffff);
341 error = rt2870_io_vendor_req(sc, UT_WRITE_VENDOR_DEVICE,
342 RT2870_IO_USB_REQ_MCU_CNTL, RT2870_IO_USB_VALUE_MCU_RUN, 0, NULL, 0);
343 if (error != 0)
345 printf("%s: could not run firmware: error=%s\n",
346 device_get_nameunit(sc->dev), usbd_errstr(error));
347 return error;
350 for (ntries = 0; ntries < 1000; ntries++)
352 if (rt2870_io_mac_read(sc, RT2870_REG_PBF_SYS_CTRL) &
353 RT2870_REG_MCU_READY)
354 break;
356 DELAY(1000);
359 if (ntries == 1000)
361 printf("%s: timeout waiting for MCU to initialize\n",
362 device_get_nameunit(sc->dev));
363 return ETIMEDOUT;
366 return 0;
370 * rt2870_io_mcu_reset
372 int rt2870_io_mcu_reset(struct rt2870_softc *sc)
374 return rt2870_io_vendor_req(sc, UT_WRITE_VENDOR_DEVICE,
375 RT2870_IO_USB_REQ_MCU_CNTL, RT2870_IO_USB_VALUE_MCU_RESET, 0, NULL, 0);
379 * rt2870_io_vendor_req
381 static int rt2870_io_vendor_req(struct rt2870_softc *sc,
382 uint8_t reqtype, uint8_t req, uint16_t value, uint16_t index,
383 void *buf, uint16_t len)
385 struct usb_device_request usb_req;
386 usb_error_t error;
387 int ntries;
389 for (ntries = 0; ntries < 10; ntries++)
391 usb_req.bmRequestType = reqtype;
392 usb_req.bRequest = req;
393 USETW(usb_req.wValue, value);
394 USETW(usb_req.wIndex, index);
395 USETW(usb_req.wLength, len);
397 error = usbd_do_request_flags(sc->usb_dev, &sc->lock, &usb_req, buf,
398 0, NULL, 250);
399 if (error == 0)
400 break;
402 DELAY(5000);
405 return error;
409 * rt2870_io_byte_rev
411 static uint8_t rt2870_io_byte_rev(uint8_t byte)
413 int i;
414 uint8_t tmp;
416 for(i = 0, tmp = 0; ; i++)
418 if(byte & 0x80)
419 tmp |= 0x80;
421 if(i == 7)
422 break;
424 byte <<= 1;
425 tmp >>= 1;
428 return tmp;