1 2/*- 3 * Copyright (c) 2009-2010 Alexander Egorenkov <egorenar@gmail.com> 4 * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr> 5 * 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. 9 * 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. 17 */ 18 19#include <dev/rt2860/rt2860_io.h> 20#include <dev/rt2860/rt2860_reg.h> 21 22/* 23 * Defines and macros 24 */ 25 26/* 27 * RT2860_IO_EEPROM_RAISE_CLK 28 */ 29#define RT2860_IO_EEPROM_RAISE_CLK(sc, val) \ 30do \ 31{ \ 32 (val) |= RT2860_REG_EESK; \ 33 \ 34 rt2860_io_mac_write((sc), RT2860_REG_EEPROM_CSR, (val)); \ 35 \ 36 DELAY(1); \ 37} while (0) 38 39/* 40 * RT2860_IO_EEPROM_LOWER_CLK 41 */ 42#define RT2860_IO_EEPROM_LOWER_CLK(sc, val) \ 43do \ 44{ \ 45 (val) &= ~RT2860_REG_EESK; \ 46 \ 47 rt2860_io_mac_write((sc), RT2860_REG_EEPROM_CSR, (val)); \ 48 \ 49 DELAY(1); \ 50} while (0) 51 52#define RT2860_IO_BYTE_CRC16(byte, crc) \ 53 ((uint16_t) (((crc) << 8) ^ rt2860_io_ccitt16[(((crc) >> 8) ^ (byte)) & 255])) 54 55/* 56 * Static function prototypes 57 */ 58 59static void rt2860_io_eeprom_shiftout_bits(struct rt2860_softc *sc, 60 uint16_t val, uint16_t count); 61 62static uint16_t rt2860_io_eeprom_shiftin_bits(struct rt2860_softc *sc); 63 64static uint8_t rt2860_io_byte_rev(uint8_t byte); 65 66/* #ifdef RT305X_SOC */ 67static const uint16_t rt3052_eeprom[] = 68{ 69 0x3052, 0x0101, 0x0c00, 0x3043, 0x8852, 0xffff, 0xffff, 0xffff, 70 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 71 0xffff, 0xffff, 0xffff, 0xffff, 0x0c00, 0x3043, 0x7752, 0x0c00, 72 0x3043, 0x6652, 0x0822, 0x0024, 0xffff, 0x012f, 0x7755, 0xaaa8, 73 0x888c, 0xffff, 0x000c, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 74 0xffff, 0x0d0d, 0x0d0d, 0x0c0c, 0x0c0c, 0x0c0c, 0x0c0c, 0x0c0c, 75 0x1010, 0x1111, 0x1211, 0x1212, 0x1313, 0x1413, 0x1414, 0xffff, 76 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 77 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 78 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 79 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 80 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 81 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 82 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6666, 83 0xaacc, 0x6688, 0xaacc, 0x6688, 0xaacc, 0x6688, 0xaacc, 0x6688, 84 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 85 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 86 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 87 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 88 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 89 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 90 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 91 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 92 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 93 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 94 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 95 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 96 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 97 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 98 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 99 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 100 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 101}; 102 103uint8_t rt3052_rf_default[] = { 104 0x50, 105 0x01, 106 0xF7, 107 0x75, 108 0x40, 109 0x03, 110 0x42, 111 0x50, 112 0x39, 113 0x0F, 114 0x60, 115 0x21, 116 0x75, 117 0x75, 118 0x90, 119 0x58, 120 0xB3, 121 0x92, 122 0x2C, 123 0x02, 124 0xBA, 125 0xDB, 126 0x00, 127 0x31, 128 0x08, 129 0x01, 130 0x25, /* Core Power: 0x25=1.25V */ 131 0x23, /* RF: 1.35V */ 132 0x13, /* ADC: must consist with R27 */ 133 0x83, 134 0x00, 135 0x00, 136}; 137/* #endif */ 138 139 140/* 141 * Static variables 142 */ 143 144static const uint16_t rt2860_io_ccitt16[] = 145{ 146 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 147 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 148 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 149 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 150 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 151 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 152 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 153 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 154 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 155 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 156 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 157 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 158 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 159 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 160 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 161 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 162 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 163 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 164 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 165 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 166 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 167 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 168 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 169 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 170 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 171 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 172 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 173 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 174 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 175 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 176 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 177 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 178}; 179 180/* 181 * rt2860_io_mac_read 182 */ 183uint32_t rt2860_io_mac_read(struct rt2860_softc *sc, uint16_t reg) 184{ 185 bus_space_read_4(sc->bst, sc->bsh, RT2860_REG_MAC_CSR0); 186 return bus_space_read_4(sc->bst, sc->bsh, reg); 187} 188 189/* 190 * rt2860_io_mac_read_multi 191 */ 192void rt2860_io_mac_read_multi(struct rt2860_softc *sc, 193 uint16_t reg, void *buf, size_t len) 194{ 195 bus_space_read_4(sc->bst, sc->bsh, RT2860_REG_MAC_CSR0); 196 bus_space_read_region_1(sc->bst, sc->bsh, reg, buf, len); 197} 198 199/* 200 * rt2860_io_mac_write 201 */ 202void rt2860_io_mac_write(struct rt2860_softc *sc, 203 uint16_t reg, uint32_t val) 204{ 205 bus_space_read_4(sc->bst, sc->bsh, RT2860_REG_MAC_CSR0); 206 bus_space_write_4(sc->bst, sc->bsh, reg, val); 207} 208 209/* 210 * rt2860_io_mac_write_multi 211 */ 212void rt2860_io_mac_write_multi(struct rt2860_softc *sc, 213 uint16_t reg, const void *buf, size_t len) 214{ 215 int i; 216 const uint8_t *p; 217 218 bus_space_read_4(sc->bst, sc->bsh, RT2860_REG_MAC_CSR0); 219 220 p = buf; 221 for (i = 0; i < len; i ++) 222 bus_space_write_1(sc->bst, sc->bsh, reg + i, *(p+i)); 223// bus_space_write_region_1(sc->bst, sc->bsh, reg, buf, len); 224} 225 226/* 227 * rt2860_io_mac_set_region_4 228 */ 229void rt2860_io_mac_set_region_4(struct rt2860_softc *sc, 230 uint16_t reg, uint32_t val, size_t len) 231{ 232 int i; 233 234 for (i = 0; i < len; i += sizeof(uint32_t)) 235 rt2860_io_mac_write(sc, reg + i, val); 236} 237 238/* Read 16-bit from eFUSE ROM (>=RT3071 only.) */ 239static uint16_t 240rt3090_efuse_read_2(struct rt2860_softc *sc, uint16_t addr) 241{ 242 uint32_t tmp; 243 uint16_t reg; 244 int ntries; 245 246 addr *= 2; 247 /*- 248 * Read one 16-byte block into registers EFUSE_DATA[0-3]: 249 * DATA0: F E D C 250 * DATA1: B A 9 8 251 * DATA2: 7 6 5 4 252 * DATA3: 3 2 1 0 253 */ 254 tmp = rt2860_io_mac_read(sc, RT3070_EFUSE_CTRL); 255 tmp &= ~(RT3070_EFSROM_MODE_MASK | RT3070_EFSROM_AIN_MASK); 256 tmp |= (addr & ~0xf) << RT3070_EFSROM_AIN_SHIFT | RT3070_EFSROM_KICK; 257 rt2860_io_mac_write(sc, RT3070_EFUSE_CTRL, tmp); 258 for (ntries = 0; ntries < 500; ntries++) { 259 tmp = rt2860_io_mac_read(sc, RT3070_EFUSE_CTRL); 260 if (!(tmp & RT3070_EFSROM_KICK)) 261 break; 262 DELAY(2); 263 } 264 if (ntries == 500) 265 return 0xffff; 266 267 if ((tmp & RT3070_EFUSE_AOUT_MASK) == RT3070_EFUSE_AOUT_MASK) 268 return 0xffff; /* address not found */ 269 270 /* determine to which 32-bit register our 16-bit word belongs */ 271 reg = RT3070_EFUSE_DATA3 - (addr & 0xc); 272 tmp = rt2860_io_mac_read(sc, reg); 273 274 return (addr & 2) ? tmp >> 16 : tmp & 0xffff; 275} 276 277 278/* 279 * rt2860_io_eeprom_read 280 */ 281uint16_t rt2860_io_eeprom_read(struct rt2860_softc *sc, uint16_t addr) 282{ 283 uint32_t tmp; 284 uint16_t val; 285 286 addr = (addr >> 1); 287 288 if (sc->mac_rev == 0x28720200) { 289 return (rt3052_eeprom[addr]); 290 } else if ((sc->mac_rev & 0xffff0000) >= 0x30710000) { 291 tmp = rt2860_io_mac_read(sc, RT3070_EFUSE_CTRL); 292 if (tmp & RT3070_SEL_EFUSE) 293 return (rt3090_efuse_read_2(sc, addr)); 294 } 295 296 tmp = rt2860_io_mac_read(sc, RT2860_REG_EEPROM_CSR); 297 298 tmp &= ~(RT2860_REG_EEDI | RT2860_REG_EEDO | RT2860_REG_EESK); 299 tmp |= RT2860_REG_EECS; 300 301 rt2860_io_mac_write(sc, RT2860_REG_EEPROM_CSR, tmp); 302 303 if (((sc->mac_rev & 0xffff0000) != 0x30710000) && 304 ((sc->mac_rev & 0xffff0000) != 0x30900000) && 305 ((sc->mac_rev & 0xffff0000) != 0x35720000) && 306 ((sc->mac_rev & 0xffff0000) != 0x33900000)) 307 { 308 RT2860_IO_EEPROM_RAISE_CLK(sc, tmp); 309 RT2860_IO_EEPROM_LOWER_CLK(sc, tmp); 310 } 311 312 rt2860_io_eeprom_shiftout_bits(sc, RT2860_REG_EEOP_READ, 3); 313 rt2860_io_eeprom_shiftout_bits(sc, addr, sc->eeprom_addr_num); 314 315 val = rt2860_io_eeprom_shiftin_bits(sc); 316 317 tmp = rt2860_io_mac_read(sc, RT2860_REG_EEPROM_CSR); 318 319 tmp &= ~(RT2860_REG_EECS | RT2860_REG_EEDI); 320 321 rt2860_io_mac_write(sc, RT2860_REG_EEPROM_CSR, tmp); 322 323 RT2860_IO_EEPROM_RAISE_CLK(sc, tmp); 324 RT2860_IO_EEPROM_LOWER_CLK(sc, tmp); 325 326 return val; 327} 328 329/* 330 * rt2860_io_eeprom_read_multi 331 */ 332void rt2860_io_eeprom_read_multi(struct rt2860_softc *sc, 333 uint16_t addr, void *buf, size_t len) 334{ 335 uint16_t *ptr; 336 int i; 337 338 len += len % sizeof(uint16_t); 339 ptr = buf; 340 341 i = 0; 342 343 do 344 { 345 *ptr++ = rt2860_io_eeprom_read(sc, addr + i); 346 347 i += sizeof(uint16_t); 348 len -= sizeof(uint16_t); 349 } while (len > 0); 350} 351 352/* 353 * rt2860_io_bbp_read 354 */ 355uint8_t rt2860_io_bbp_read(struct rt2860_softc *sc, uint8_t reg) 356{ 357 int ntries; 358 uint32_t tmp; 359 360 if (sc->mac_rev == 0x28720200) 361 { 362 for (ntries = 0; ntries < 100; ntries ++) { 363 if ( !(rt2860_io_mac_read(sc, RT2860_REG_BBP_CSR_CFG) & 364 RT2860_REG_BBP_CSR_BUSY) ) 365 break; 366 DELAY(1); 367 } 368 if (ntries == 100) { 369 printf("%s:%s: BBP busy after 100 probes\n", 370 device_get_nameunit(sc->dev), __func__); 371 return (0); 372 } 373 rt2860_io_mac_write(sc, RT2860_REG_BBP_CSR_CFG, 374 RT2860_REG_BBP_CSR_READ | 375 RT2860_REG_BBP_CSR_KICK | RT2860_REG_BBP_RW_MODE_PARALLEL | 376 (reg & RT2860_REG_BBP_REG_MASK) << RT2860_REG_BBP_REG_SHIFT); 377 for (ntries = 0; ntries < 100; ntries ++) { 378 if ( !(rt2860_io_mac_read(sc, RT2860_REG_BBP_CSR_CFG) & 379 RT2860_REG_BBP_CSR_BUSY) ) 380 break; 381 DELAY(1); 382 } 383 if (ntries == 100) { 384 printf("%s:%s: BBP busy after 100 probes\n", 385 device_get_nameunit(sc->dev), __func__); 386 return (0); 387 } 388 else { 389 return 390 ((rt2860_io_mac_read(sc, RT2860_REG_BBP_CSR_CFG) >> 391 RT2860_REG_BBP_VAL_SHIFT) & 392 RT2860_REG_BBP_VAL_MASK); 393 } 394 return (0); 395 } 396 397 for (ntries = 0; ntries < 100; ntries++) 398 { 399 if (!(rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT) & 400 RT2860_REG_BBP_CSR_BUSY)) 401 break; 402 403 DELAY(1); 404 } 405 406 if (ntries == 100) 407 { 408 printf("%s: could not read from BBP through MCU: reg=0x%02x\n", 409 device_get_nameunit(sc->dev), reg); 410 return 0; 411 } 412 413 tmp = RT2860_REG_BBP_RW_MODE_PARALLEL | 414 RT2860_REG_BBP_CSR_BUSY | 415 RT2860_REG_BBP_CSR_READ | 416 ((reg & RT2860_REG_BBP_REG_MASK) << RT2860_REG_BBP_REG_SHIFT); 417 418 rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT, tmp); 419 420 rt2860_io_mcu_cmd(sc, RT2860_IO_MCU_CMD_BBP, 421 RT2860_REG_H2M_TOKEN_NO_INTR, 0); 422 423 DELAY(1000); 424 425 for (ntries = 0; ntries < 100; ntries++) 426 { 427 tmp = rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT); 428 if (!(tmp & RT2860_REG_BBP_CSR_BUSY)) 429 return ((tmp >> RT2860_REG_BBP_VAL_SHIFT) & 430 RT2860_REG_BBP_VAL_MASK); 431 432 DELAY(1); 433 } 434 435 printf("%s: could not read from BBP through MCU: reg=0x%02x\n", 436 device_get_nameunit(sc->dev), reg); 437 438 return 0; 439} 440 441/* 442 * rt2860_io_bbp_write 443 */ 444void rt2860_io_bbp_write(struct rt2860_softc *sc, uint8_t reg, uint8_t val) 445{ 446 int ntries; 447 uint32_t tmp; 448 449 if (sc->mac_rev == 0x28720200) 450 { 451 for (ntries = 0; ntries < 100; ntries ++) { 452 if ( !(rt2860_io_mac_read(sc, RT2860_REG_BBP_CSR_CFG) & 453 RT2860_REG_BBP_CSR_BUSY) ) 454 break; 455 DELAY(1); 456 } 457 if (ntries == 100) { 458 printf("%s:%s: BBP busy after 100 probes\n", 459 device_get_nameunit(sc->dev), __func__); 460 return; 461 } 462 rt2860_io_mac_write(sc, RT2860_REG_BBP_CSR_CFG, 463 RT2860_REG_BBP_CSR_KICK | RT2860_REG_BBP_RW_MODE_PARALLEL | 464 (reg & RT2860_REG_BBP_REG_MASK) << RT2860_REG_BBP_REG_SHIFT | 465 (val & RT2860_REG_BBP_VAL_MASK) << RT2860_REG_BBP_VAL_SHIFT ); 466 rt2860_io_bbp_read(sc, reg); 467 return; 468 } 469 470 for (ntries = 0; ntries < 100; ntries++) 471 { 472 if (!(rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT) & 473 RT2860_REG_BBP_CSR_BUSY)) 474 break; 475 476 DELAY(1); 477 } 478 479 if (ntries == 100) 480 { 481 printf("%s: could not write to BBP through MCU: reg=0x%02x\n", 482 device_get_nameunit(sc->dev), reg); 483 return; 484 } 485 486 tmp = RT2860_REG_BBP_RW_MODE_PARALLEL | 487 RT2860_REG_BBP_CSR_BUSY | 488 ((reg & RT2860_REG_BBP_REG_MASK) << RT2860_REG_BBP_REG_SHIFT) | 489 ((val & RT2860_REG_BBP_VAL_MASK) << RT2860_REG_BBP_VAL_SHIFT); 490 491 rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT, tmp); 492 493 rt2860_io_mcu_cmd(sc, RT2860_IO_MCU_CMD_BBP, 494 RT2860_REG_H2M_TOKEN_NO_INTR, 0); 495 496 DELAY(1000); 497} 498 499/* 500 * rt2860_io_rf_write 501 */ 502void rt2860_io_rf_write(struct rt2860_softc *sc, uint8_t reg, uint32_t val) 503{ 504 int ntries; 505 if (sc->mac_rev == 0x28720200) 506 { 507 for (ntries = 0; ntries < 100; ntries ++) { 508 if ( !(rt2860_io_mac_read(sc, RT2872_REG_RF_CSR_CFG) & 509 RT2872_REG_RF_CSR_BUSY) ) 510 break; 511 DELAY(1); 512 } 513 if (ntries == 100) { 514 printf("%s:%s: RF busy after 100 probes\n", 515 device_get_nameunit(sc->dev), __func__); 516 return; 517 } 518 rt2860_io_mac_write(sc, RT2872_REG_RF_CSR_CFG, 519 RT2872_REG_RF_CSR_KICK | RT2872_REG_RF_CSR_WRITE | 520 (reg & RT2872_REG_RF_ID_MASK) << RT2872_REG_RF_ID_SHIFT | 521 (val & RT2872_REG_RF_VAL_MASK) << RT2872_REG_RF_VAL_SHIFT ); 522 rt2860_io_rf_read(sc, reg); 523 return; 524 } 525 526 527 for (ntries = 0; ntries < 100; ntries++) 528 if (!(rt2860_io_mac_read(sc, RT2860_REG_RF_CSR_CFG0) & 529 RT2860_REG_RF_BUSY)) 530 break; 531 532 if (ntries == 100) 533 { 534 printf("%s: could not write to RF: reg=0x%02x\n", 535 device_get_nameunit(sc->dev), reg); 536 return; 537 } 538 539 rt2860_io_mac_write(sc, RT2860_REG_RF_CSR_CFG0, val); 540} 541 542/* 543 * rt2860_io_rf_read 544 */ 545int32_t rt2860_io_rf_read(struct rt2860_softc *sc, uint8_t reg) 546{ 547 int ntries; 548 if (sc->mac_rev == 0x28720200) 549 { 550 for (ntries = 0; ntries < 100; ntries ++) { 551 if ( !(rt2860_io_mac_read(sc, RT2872_REG_RF_CSR_CFG) & 552 RT2872_REG_RF_CSR_BUSY) ) 553 break; 554 DELAY(1); 555 } 556 if (ntries == 100) { 557 printf("%s:%s: RF busy after 100 probes\n", 558 device_get_nameunit(sc->dev), __func__); 559 return (-1); 560 } 561 rt2860_io_mac_write(sc, RT2872_REG_RF_CSR_CFG, 562 RT2872_REG_RF_CSR_KICK | 563 (reg & RT2872_REG_RF_ID_MASK) << RT2872_REG_RF_ID_SHIFT ); 564 565 for (ntries = 0; ntries < 100; ntries ++) { 566 if ( !(rt2860_io_mac_read(sc, RT2872_REG_RF_CSR_CFG) & 567 RT2872_REG_RF_CSR_BUSY) ) 568 break; 569 DELAY(1); 570 } 571 if (ntries == 100) { 572 printf("%s:%s: RF busy after 100 probes\n", 573 device_get_nameunit(sc->dev), __func__); 574 } 575 576 return (rt2860_io_mac_read(sc, RT2872_REG_RF_CSR_CFG) & RT2872_REG_RF_VAL_MASK); 577 } 578 return (-1); 579} 580 581/* 582 * rt2860_io_rf_load_defaults 583 */ 584void rt2860_io_rf_load_defaults(struct rt2860_softc *sc) 585{ 586 int i; 587 588 if (sc->mac_rev == 0x28720200) { 589 for (i = 0; i < 32; i ++) 590 rt2860_io_rf_write(sc, i, rt3052_rf_default[i]); 591 } 592} 593 594/* 595 * rt2860_io_mcu_cmd 596 */ 597void rt2860_io_mcu_cmd(struct rt2860_softc *sc, uint8_t cmd, 598 uint8_t token, uint16_t arg) 599{ 600 uint32_t tmp; 601 int ntries; 602 603 if (sc->mac_rev == 0x28720200) 604 return; 605 606 for (ntries = 0; ntries < 100; ntries++) 607 { 608 if (!(rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX) & 609 RT2860_REG_H2M_BUSY)) 610 break; 611 612 DELAY(2); 613 } 614 615 if (ntries == 100) 616 { 617 printf("%s: could not read H2M: cmd=0x%02x\n", 618 device_get_nameunit(sc->dev), cmd); 619 return; 620 } 621 622 tmp = RT2860_REG_H2M_BUSY | (token << 16) | arg; 623 624 rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX, tmp); 625 rt2860_io_mac_write(sc, RT2860_REG_H2M_HOST_CMD, cmd); 626} 627 628/* 629 * rt2860_io_mcu_cmd_check 630 */ 631int rt2860_io_mcu_cmd_check(struct rt2860_softc *sc, uint8_t cid) 632{ 633 uint32_t tmp, mask, status; 634 int result, ntries; 635 636 result = -1; 637 638 for (ntries = 0; ntries < 200; ntries++) 639 { 640 tmp = rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX_CID); 641 642 if (((cid >> RT2860_REG_H2M_CID0_SHIFT) & RT2860_REG_H2M_CID_MASK) == cid) 643 { 644 mask = (RT2860_REG_H2M_CID_MASK << RT2860_REG_H2M_CID0_SHIFT); 645 break; 646 } 647 else if (((tmp >> RT2860_REG_H2M_CID1_SHIFT) & RT2860_REG_H2M_CID_MASK) == cid) 648 { 649 mask = (RT2860_REG_H2M_CID_MASK << RT2860_REG_H2M_CID1_SHIFT); 650 break; 651 } 652 else if (((tmp >> RT2860_REG_H2M_CID2_SHIFT) & RT2860_REG_H2M_CID_MASK) == cid) 653 { 654 mask = (RT2860_REG_H2M_CID_MASK << RT2860_REG_H2M_CID2_SHIFT); 655 break; 656 } 657 else if (((tmp >> RT2860_REG_H2M_CID3_SHIFT) & RT2860_REG_H2M_CID_MASK) == cid) 658 { 659 mask = (RT2860_REG_H2M_CID_MASK << RT2860_REG_H2M_CID3_SHIFT); 660 break; 661 } 662 663 DELAY(100); 664 } 665 666 status = rt2860_io_mac_read(sc, RT2860_REG_H2M_MAILBOX_STATUS); 667 668 if (ntries < 200) 669 { 670 status &= mask; 671 672 if ((status == 0x1) || 673 (status == 0x100) || 674 (status == 0x10000) || 675 (status == 0x1000000)) 676 result = 0; 677 } 678 679 rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX_STATUS, 0xffffffff); 680 rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX_CID, 0xffffffff); 681 682 return result; 683} 684 685/* 686 * rt2860_io_mcu_load_ucode 687 */ 688int rt2860_io_mcu_load_ucode(struct rt2860_softc *sc, 689 const uint8_t *ucode, size_t len) 690{ 691 int i, ntries; 692 uint16_t crc; 693 694 for (i = 0, crc = 0xffff; i < len - 2; i++) 695 crc = RT2860_IO_BYTE_CRC16(rt2860_io_byte_rev(ucode[i]), crc); 696 697 if (ucode[len - 2] != rt2860_io_byte_rev(crc >> 8) || 698 ucode[len - 1] != rt2860_io_byte_rev(crc)) 699 { 700 printf("%s: wrong microcode crc\n", 701 device_get_nameunit(sc->dev)); 702 return EINVAL; 703 } 704 705 rt2860_io_mac_write(sc, RT2860_REG_PBF_SYS_CTRL, RT2860_REG_HST_PM_SEL); 706 707 for(i = 0; i < len; i += 4) 708 { 709 rt2860_io_mac_write(sc, RT2860_REG_MCU_UCODE_BASE + i, 710 (ucode[i+3] << 24) | (ucode[i+2] << 16) | 711 (ucode[i+1] << 8) | ucode[i]); 712 } 713 714 if (sc->mac_rev != 0x28720200) 715 rt2860_io_mac_write_multi(sc, RT2860_REG_MCU_UCODE_BASE, 716 ucode, len); 717 718 rt2860_io_mac_write(sc, RT2860_REG_PBF_SYS_CTRL, 0); 719 720 if (sc->mac_rev != 0x28720200) 721 rt2860_io_mac_write(sc, RT2860_REG_PBF_SYS_CTRL, 722 RT2860_REG_MCU_RESET); 723 724 DELAY(10000); 725 726 /* initialize BBP R/W access agent */ 727 728 rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX_BBP_AGENT, 0); 729 rt2860_io_mac_write(sc, RT2860_REG_H2M_MAILBOX, 0); 730 731 if (sc->mac_rev != 0x28720200) { 732 733 for (ntries = 0; ntries < 1000; ntries++) 734 { 735 if (rt2860_io_mac_read(sc, RT2860_REG_PBF_SYS_CTRL) & 736 RT2860_REG_MCU_READY) 737 break; 738 739 DELAY(1000); 740 } 741 742 if (ntries == 1000) 743 { 744 printf("%s: timeout waiting for MCU to initialize\n", 745 device_get_nameunit(sc->dev)); 746 return ETIMEDOUT; 747 } 748 } 749 750 return 0; 751} 752 753/* 754 * rt2860_io_eeprom_shiftout_bits 755 */ 756static void rt2860_io_eeprom_shiftout_bits(struct rt2860_softc *sc, 757 uint16_t val, uint16_t count) 758{ 759 uint32_t mask, tmp; 760 761 mask = (1 << (count - 1)); 762 763 tmp = rt2860_io_mac_read(sc, RT2860_REG_EEPROM_CSR); 764 765 tmp &= ~(RT2860_REG_EEDO | RT2860_REG_EEDI); 766 767 do 768 { 769 tmp &= ~RT2860_REG_EEDI; 770 771 if(val & mask) 772 tmp |= RT2860_REG_EEDI; 773 774 rt2860_io_mac_write(sc, RT2860_REG_EEPROM_CSR, tmp); 775 776 RT2860_IO_EEPROM_RAISE_CLK(sc, tmp); 777 RT2860_IO_EEPROM_LOWER_CLK(sc, tmp); 778 779 mask = (mask >> 1); 780 } while (mask); 781 782 tmp &= ~RT2860_REG_EEDI; 783 784 rt2860_io_mac_write(sc, RT2860_REG_EEPROM_CSR, tmp); 785} 786 787/* 788 * rt2860_io_eeprom_shiftin_bits 789 */ 790static uint16_t rt2860_io_eeprom_shiftin_bits(struct rt2860_softc *sc) 791{ 792 uint32_t tmp; 793 uint16_t val; 794 int i; 795 796 val = 0; 797 798 tmp = rt2860_io_mac_read(sc, RT2860_REG_EEPROM_CSR); 799 800 tmp &= ~(RT2860_REG_EEDO | RT2860_REG_EEDI); 801 802 for(i = 0; i < 16; i++) 803 { 804 val = (val << 1); 805 806 RT2860_IO_EEPROM_RAISE_CLK(sc, tmp); 807 808 tmp = rt2860_io_mac_read(sc, RT2860_REG_EEPROM_CSR); 809 810 RT2860_IO_EEPROM_LOWER_CLK(sc, tmp); 811 812 tmp &= ~RT2860_REG_EEDI; 813 if(tmp & RT2860_REG_EEDO) 814 val |= 1; 815 } 816 817 return val; 818} 819 820/* 821 * rt2860_io_byte_rev 822 */ 823static uint8_t rt2860_io_byte_rev(uint8_t byte) 824{ 825 int i; 826 uint8_t tmp; 827 828 for(i = 0, tmp = 0; ; i++) 829 { 830 if(byte & 0x80) 831 tmp |= 0x80; 832 833 if(i == 7) 834 break; 835 836 byte <<= 1; 837 tmp >>= 1; 838 } 839 840 return tmp; 841} 842