Added Rx A-MPDU statistic counter
[ralink_drivers/rt2860_fbsd8.git] / rt2860_io.c
blob4f69d1c0714648d9d4c9a48c9cf014c8f58ca978
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 "rt2860_io.h"
20 #include "rt2860_reg.h"
23 * Defines and macros
27 * RT2860_IO_EEPROM_RAISE_CLK
29 #define RT2860_IO_EEPROM_RAISE_CLK(sc, val) \
30 do \
31 { \
32 (val) |= RT2860_REG_EESK; \
34 rt2860_io_mac_write((sc), RT2860_REG_EEPROM_CSR, (val)); \
36 DELAY(1); \
37 } while (0)
40 * RT2860_IO_EEPROM_LOWER_CLK
42 #define RT2860_IO_EEPROM_LOWER_CLK(sc, val) \
43 do \
44 { \
45 (val) &= ~RT2860_REG_EESK; \
47 rt2860_io_mac_write((sc), RT2860_REG_EEPROM_CSR, (val)); \
49 DELAY(1); \
50 } while (0)
52 #define RT2860_IO_BYTE_CRC16(byte, crc) \
53 ((uint16_t) (((crc) << 8) ^ rt2860_io_ccitt16[(((crc) >> 8) ^ (byte)) & 255]))
56 * Static function prototypes
59 static void rt2860_io_eeprom_shiftout_bits(struct rt2860_softc *sc,
60 uint16_t val, uint16_t count);
62 static uint16_t rt2860_io_eeprom_shiftin_bits(struct rt2860_softc *sc);
64 static uint8_t rt2860_io_byte_rev(uint8_t byte);
67 * Static variables
70 static const uint16_t rt2860_io_ccitt16[] =
72 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
73 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
74 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
75 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
76 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
77 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
78 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
79 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
80 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
81 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
82 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
83 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
84 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
85 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
86 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
87 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
88 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
89 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
90 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
91 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
92 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
93 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
94 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
95 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
96 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
97 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
98 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
99 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
100 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
101 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
102 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
103 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
107 * rt2860_io_mac_read
109 uint32_t rt2860_io_mac_read(struct rt2860_softc *sc, uint16_t reg)
111 return bus_space_read_4(sc->bst, sc->bsh, reg);
115 * rt2860_io_mac_read_multi
117 void rt2860_io_mac_read_multi(struct rt2860_softc *sc,
118 uint16_t reg, void *buf, size_t len)
120 bus_space_read_region_1(sc->bst, sc->bsh, reg, buf, len);
124 * rt2860_io_mac_write
126 void rt2860_io_mac_write(struct rt2860_softc *sc,
127 uint16_t reg, uint32_t val)
129 bus_space_write_4(sc->bst, sc->bsh, reg, val);
133 * rt2860_io_mac_write_multi
135 void rt2860_io_mac_write_multi(struct rt2860_softc *sc,
136 uint16_t reg, const void *buf, size_t len)
138 bus_space_write_region_1(sc->bst, sc->bsh, reg, buf, len);
142 * rt2860_io_mac_set_region_4
144 void rt2860_io_mac_set_region_4(struct rt2860_softc *sc,
145 uint16_t reg, uint32_t val, size_t len)
147 int i;
149 for (i = 0; i < len; i += sizeof(uint32_t))
150 rt2860_io_mac_write(sc, reg + i, val);
154 * rt2860_io_eeprom_read
156 uint16_t rt2860_io_eeprom_read(struct rt2860_softc *sc, uint16_t addr)
158 uint32_t tmp;
159 uint16_t val;
161 addr = (addr >> 1);
163 tmp = rt2860_io_mac_read(sc, RT2860_REG_EEPROM_CSR);
165 tmp &= ~(RT2860_REG_EEDI | RT2860_REG_EEDO | RT2860_REG_EESK);
166 tmp |= RT2860_REG_EECS;
168 rt2860_io_mac_write(sc, RT2860_REG_EEPROM_CSR, tmp);
170 if (((sc->mac_rev & 0xffff0000) != 0x30710000) &&
171 ((sc->mac_rev & 0xffff0000) != 0x30900000) &&
172 ((sc->mac_rev & 0xffff0000) != 0x35720000) &&
173 ((sc->mac_rev & 0xffff0000) != 0x33900000))
175 RT2860_IO_EEPROM_RAISE_CLK(sc, tmp);
176 RT2860_IO_EEPROM_LOWER_CLK(sc, tmp);
179 rt2860_io_eeprom_shiftout_bits(sc, RT2860_REG_EEOP_READ, 3);
180 rt2860_io_eeprom_shiftout_bits(sc, addr, sc->eeprom_addr_num);
182 val = rt2860_io_eeprom_shiftin_bits(sc);
184 tmp = rt2860_io_mac_read(sc, RT2860_REG_EEPROM_CSR);
186 tmp &= ~(RT2860_REG_EECS | RT2860_REG_EEDI);
188 rt2860_io_mac_write(sc, RT2860_REG_EEPROM_CSR, tmp);
190 RT2860_IO_EEPROM_RAISE_CLK(sc, tmp);
191 RT2860_IO_EEPROM_LOWER_CLK(sc, tmp);
193 return val;
197 * rt2860_io_eeprom_read_multi
199 void rt2860_io_eeprom_read_multi(struct rt2860_softc *sc,
200 uint16_t addr, void *buf, size_t len)
202 uint16_t *ptr;
203 int i;
205 len += len % sizeof(uint16_t);
206 ptr = buf;
208 i = 0;
212 *ptr++ = rt2860_io_eeprom_read(sc, addr + i);
214 i += sizeof(uint16_t);
215 len -= sizeof(uint16_t);
216 } while (len > 0);
220 * rt2860_io_bbp_read
222 uint8_t rt2860_io_bbp_read(struct rt2860_softc *sc, uint8_t reg)
224 int ntries;
225 uint32_t tmp;
227 for (ntries = 0; ntries < 100; ntries++)
229 if (!(rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT) &
230 RT2860_REG_BBP_CSR_BUSY))
231 break;
233 DELAY(1);
236 if (ntries == 100)
238 printf("%s: could not read from BBP through MCU\n",
239 device_get_nameunit(sc->dev));
240 return 0;
243 tmp = RT2860_REG_BBP_RW_MODE_PARALLEL |
244 RT2860_REG_BBP_CSR_BUSY |
245 RT2860_REG_BBP_CSR_READ |
246 ((reg & RT2860_REG_BBP_REG_MASK) << RT2860_REG_BBP_REG_SHIFT);
248 rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT, tmp);
250 rt2860_io_mcu_cmd(sc, RT2860_IO_MCU_CMD_BBP,
251 RT2860_REG_H2M_TOKEN_NO_INTR, 0);
253 DELAY(1000);
255 for (ntries = 0; ntries < 100; ntries++)
257 tmp = rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT);
258 if (!(tmp & RT2860_REG_BBP_CSR_BUSY))
259 return ((tmp >> RT2860_REG_BBP_VAL_SHIFT) &
260 RT2860_REG_BBP_VAL_MASK);
262 DELAY(1);
265 printf("%s: could not read from BBP through MCU\n",
266 device_get_nameunit(sc->dev));
268 return 0;
272 * rt2860_io_bbp_write
274 void rt2860_io_bbp_write(struct rt2860_softc *sc, uint8_t reg, uint8_t val)
276 int ntries;
277 uint32_t tmp;
279 for (ntries = 0; ntries < 100; ntries++)
281 if (!(rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT) &
282 RT2860_REG_BBP_CSR_BUSY))
283 break;
285 DELAY(1);
288 if (ntries == 100)
290 printf("%s: could not write to BBP through MCU\n",
291 device_get_nameunit(sc->dev));
292 return;
295 tmp = RT2860_REG_BBP_RW_MODE_PARALLEL |
296 RT2860_REG_BBP_CSR_BUSY |
297 ((reg & RT2860_REG_BBP_REG_MASK) << RT2860_REG_BBP_REG_SHIFT) |
298 ((val & RT2860_REG_BBP_VAL_MASK) << RT2860_REG_BBP_VAL_SHIFT);
300 rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT, tmp);
302 rt2860_io_mcu_cmd(sc, RT2860_IO_MCU_CMD_BBP,
303 RT2860_REG_H2M_TOKEN_NO_INTR, 0);
305 DELAY(1000);
309 * rt2860_io_rf_write
311 void rt2860_io_rf_write(struct rt2860_softc *sc, uint8_t reg, uint32_t val)
313 int ntries;
315 for (ntries = 0; ntries < 100; ntries++)
316 if (!(rt2860_io_mac_read(sc, RT2860_REG_RF_CSR_CFG0) &
317 RT2860_REG_RF_BUSY))
318 break;
320 if (ntries == 100)
322 printf("%s: could not write to RF\n",
323 device_get_nameunit(sc->dev));
324 return;
327 rt2860_io_mac_write(sc, RT2860_REG_RF_CSR_CFG0, val);
331 * rt2860_io_mcu_cmd
333 void rt2860_io_mcu_cmd(struct rt2860_softc *sc, uint8_t cmd,
334 uint8_t token, uint16_t arg)
336 uint32_t tmp;
337 int ntries;
339 for (ntries = 0; ntries < 100; ntries++)
341 if (!(rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX) &
342 RT2860_REG_H2M_BUSY))
343 break;
345 DELAY(2);
348 if (ntries == 100)
350 printf("%s: could not read H2M\n",
351 device_get_nameunit(sc->dev));
352 return;
355 tmp = RT2860_REG_H2M_BUSY | (token << 16) | arg;
357 rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX, tmp);
358 rt2860_io_mac_write(sc, RT2860_REG_H2M_HOST_CMD, cmd);
362 * rt2860_io_mcu_cmd_check
364 int rt2860_io_mcu_cmd_check(struct rt2860_softc *sc, uint8_t cid)
366 uint32_t tmp, mask, status;
367 int result, ntries;
369 result = -1;
371 for (ntries = 0; ntries < 200; ntries++)
373 tmp = rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX_CID);
375 if (((cid >> RT2860_REG_H2M_CID0_SHIFT) & RT2860_REG_H2M_CID_MASK) == cid)
377 mask = (RT2860_REG_H2M_CID_MASK << RT2860_REG_H2M_CID0_SHIFT);
378 break;
380 else if (((tmp >> RT2860_REG_H2M_CID1_SHIFT) & RT2860_REG_H2M_CID_MASK) == cid)
382 mask = (RT2860_REG_H2M_CID_MASK << RT2860_REG_H2M_CID1_SHIFT);
383 break;
385 else if (((tmp >> RT2860_REG_H2M_CID2_SHIFT) & RT2860_REG_H2M_CID_MASK) == cid)
387 mask = (RT2860_REG_H2M_CID_MASK << RT2860_REG_H2M_CID2_SHIFT);
388 break;
390 else if (((tmp >> RT2860_REG_H2M_CID3_SHIFT) & RT2860_REG_H2M_CID_MASK) == cid)
392 mask = (RT2860_REG_H2M_CID_MASK << RT2860_REG_H2M_CID3_SHIFT);
393 break;
396 DELAY(100);
399 status = rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX_STATUS);
401 if (ntries < 200)
403 status &= mask;
405 if ((status == 0x1) ||
406 (status == 0x100) ||
407 (status == 0x10000) ||
408 (status == 0x1000000))
409 result = 0;
412 rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX_STATUS, 0xffffffff);
413 rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX_CID, 0xffffffff);
415 return result;
419 * rt2860_io_mcu_load_ucode
421 int rt2860_io_mcu_load_ucode(struct rt2860_softc *sc,
422 const uint8_t *ucode, size_t len)
424 int i, ntries;
425 uint16_t crc;
427 for (i = 0, crc = 0xffff; i < len - 2; i++)
428 crc = RT2860_IO_BYTE_CRC16(rt2860_io_byte_rev(ucode[i]), crc);
430 if (ucode[len - 2] != rt2860_io_byte_rev(crc >> 8) ||
431 ucode[len - 1] != rt2860_io_byte_rev(crc))
433 printf("%s: wrong microcode crc\n",
434 device_get_nameunit(sc->dev));
435 return EINVAL;
438 rt2860_io_mac_write(sc, RT2860_REG_PBF_SYS_CTRL, RT2860_REG_HST_PM_SEL);
440 rt2860_io_mac_write_multi(sc, RT2860_REG_MCU_UCODE_BASE, ucode, len);
442 rt2860_io_mac_write(sc, RT2860_REG_PBF_SYS_CTRL, 0);
443 rt2860_io_mac_write(sc, RT2860_REG_PBF_SYS_CTRL, RT2860_REG_MCU_RESET);
445 /* initialize BBP R/W access agent */
447 rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT, 0);
448 rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX, 0);
450 for (ntries = 0; ntries < 1000; ntries++)
452 if (rt2860_io_mac_read(sc, RT2860_REG_PBF_SYS_CTRL) &
453 RT2860_REG_MCU_READY)
454 break;
456 DELAY(1000);
459 if (ntries == 1000)
461 printf("%s: timeout waiting for MCU to initialize\n",
462 device_get_nameunit(sc->dev));
463 return ETIMEDOUT;
466 return 0;
470 * rt2860_io_eeprom_shiftout_bits
472 static void rt2860_io_eeprom_shiftout_bits(struct rt2860_softc *sc,
473 uint16_t val, uint16_t count)
475 uint32_t mask, tmp;
477 mask = (1 << (count - 1));
479 tmp = rt2860_io_mac_read(sc, RT2860_REG_EEPROM_CSR);
481 tmp &= ~(RT2860_REG_EEDO | RT2860_REG_EEDI);
485 tmp &= ~RT2860_REG_EEDI;
487 if(val & mask)
488 tmp |= RT2860_REG_EEDI;
490 rt2860_io_mac_write(sc, RT2860_REG_EEPROM_CSR, tmp);
492 RT2860_IO_EEPROM_RAISE_CLK(sc, tmp);
493 RT2860_IO_EEPROM_LOWER_CLK(sc, tmp);
495 mask = (mask >> 1);
496 } while (mask);
498 tmp &= ~RT2860_REG_EEDI;
500 rt2860_io_mac_write(sc, RT2860_REG_EEPROM_CSR, tmp);
504 * rt2860_io_eeprom_shiftin_bits
506 static uint16_t rt2860_io_eeprom_shiftin_bits(struct rt2860_softc *sc)
508 uint32_t tmp;
509 uint16_t val;
510 int i;
512 val = 0;
514 tmp = rt2860_io_mac_read(sc, RT2860_REG_EEPROM_CSR);
516 tmp &= ~(RT2860_REG_EEDO | RT2860_REG_EEDI);
518 for(i = 0; i < 16; i++)
520 val = (val << 1);
522 RT2860_IO_EEPROM_RAISE_CLK(sc, tmp);
524 tmp = rt2860_io_mac_read(sc, RT2860_REG_EEPROM_CSR);
526 RT2860_IO_EEPROM_LOWER_CLK(sc, tmp);
528 tmp &= ~RT2860_REG_EEDI;
529 if(tmp & RT2860_REG_EEDO)
530 val |= 1;
533 return val;
537 * rt2860_io_byte_rev
539 static uint8_t rt2860_io_byte_rev(uint8_t byte)
541 int i;
542 uint8_t tmp;
544 for(i = 0, tmp = 0; ; i++)
546 if(byte & 0x80)
547 tmp |= 0x80;
549 if(i == 7)
550 break;
552 byte <<= 1;
553 tmp >>= 1;
556 return tmp;