ar9300_eeprom.c revision 291437
1250003Sadrian/* 2250003Sadrian * Copyright (c) 2013 Qualcomm Atheros, Inc. 3250003Sadrian * 4250003Sadrian * Permission to use, copy, modify, and/or distribute this software for any 5250003Sadrian * purpose with or without fee is hereby granted, provided that the above 6250003Sadrian * copyright notice and this permission notice appear in all copies. 7250003Sadrian * 8250003Sadrian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9250003Sadrian * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10250003Sadrian * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11250003Sadrian * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12250003Sadrian * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 13250003Sadrian * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14250003Sadrian * PERFORMANCE OF THIS SOFTWARE. 15250003Sadrian */ 16250003Sadrian 17250003Sadrian#include "opt_ah.h" 18250003Sadrian 19250003Sadrian#include "ah.h" 20250003Sadrian#include "ah_internal.h" 21250003Sadrian#include "ah_devid.h" 22250003Sadrian#ifdef AH_DEBUG 23250003Sadrian#include "ah_desc.h" /* NB: for HAL_PHYERR* */ 24250003Sadrian#endif 25250003Sadrian#include "ar9300/ar9300.h" 26250003Sadrian#include "ar9300/ar9300eep.h" 27250003Sadrian#include "ar9300/ar9300template_generic.h" 28250003Sadrian#include "ar9300/ar9300template_xb112.h" 29250003Sadrian#include "ar9300/ar9300template_hb116.h" 30250003Sadrian#include "ar9300/ar9300template_xb113.h" 31250003Sadrian#include "ar9300/ar9300template_hb112.h" 32250003Sadrian#include "ar9300/ar9300template_ap121.h" 33250003Sadrian#include "ar9300/ar9300template_osprey_k31.h" 34250003Sadrian#include "ar9300/ar9300template_wasp_2.h" 35250003Sadrian#include "ar9300/ar9300template_wasp_k31.h" 36250003Sadrian#include "ar9300/ar9300template_aphrodite.h" 37250003Sadrian#include "ar9300/ar9300reg.h" 38250003Sadrian#include "ar9300/ar9300phy.h" 39250003Sadrian 40250003Sadrian 41250003Sadrian 42250003Sadrian#if AH_BYTE_ORDER == AH_BIG_ENDIAN 43250003Sadrianvoid ar9300_swap_eeprom(ar9300_eeprom_t *eep); 44250003Sadrianvoid ar9300_eeprom_template_swap(void); 45250003Sadrian#endif 46250003Sadrian 47250003Sadrianstatic u_int16_t ar9300_eeprom_get_spur_chan(struct ath_hal *ah, 48250008Sadrian int spur_chan, HAL_BOOL is_2ghz); 49250003Sadrian#ifdef UNUSED 50250003Sadrianstatic inline HAL_BOOL ar9300_fill_eeprom(struct ath_hal *ah); 51250003Sadrianstatic inline HAL_STATUS ar9300_check_eeprom(struct ath_hal *ah); 52250003Sadrian#endif 53250003Sadrian 54250003Sadrianstatic ar9300_eeprom_t *default9300[] = 55250003Sadrian{ 56250003Sadrian &ar9300_template_generic, 57250003Sadrian &ar9300_template_xb112, 58250003Sadrian &ar9300_template_hb116, 59250003Sadrian &ar9300_template_hb112, 60250003Sadrian &ar9300_template_xb113, 61250003Sadrian &ar9300_template_ap121, 62250003Sadrian &ar9300_template_wasp_2, 63250003Sadrian &ar9300_template_wasp_k31, 64250003Sadrian &ar9300_template_osprey_k31, 65250003Sadrian &ar9300_template_aphrodite, 66250003Sadrian}; 67250003Sadrian 68250003Sadrian/* 69250003Sadrian * Different types of memory where the calibration data might be stored. 70250003Sadrian * All types are searched in ar9300_eeprom_restore() 71250003Sadrian * in the order flash, eeprom, otp. 72250003Sadrian * To disable searching a type, set its parameter to 0. 73250003Sadrian */ 74250003Sadrian 75250003Sadrian/* 76250003Sadrian * This is where we look for the calibration data. 77250003Sadrian * must be set before ath_attach() is called 78250003Sadrian */ 79250003Sadrianstatic int calibration_data_try = calibration_data_none; 80250003Sadrianstatic int calibration_data_try_address = 0; 81250003Sadrian 82250003Sadrian/* 83250003Sadrian * Set the type of memory used to store calibration data. 84250003Sadrian * Used by nart to force reading/writing of a specific type. 85250003Sadrian * The driver can normally allow autodetection 86250003Sadrian * by setting source to calibration_data_none=0. 87250003Sadrian */ 88250003Sadrianvoid ar9300_calibration_data_set(struct ath_hal *ah, int32_t source) 89250003Sadrian{ 90250003Sadrian if (ah != 0) { 91250003Sadrian AH9300(ah)->calibration_data_source = source; 92250003Sadrian } else { 93250003Sadrian calibration_data_try = source; 94250003Sadrian } 95250003Sadrian} 96250003Sadrian 97250003Sadrianint32_t ar9300_calibration_data_get(struct ath_hal *ah) 98250003Sadrian{ 99250003Sadrian if (ah != 0) { 100250003Sadrian return AH9300(ah)->calibration_data_source; 101250003Sadrian } else { 102250003Sadrian return calibration_data_try; 103250003Sadrian } 104250003Sadrian} 105250003Sadrian 106250003Sadrian/* 107250003Sadrian * Set the address of first byte used to store calibration data. 108250003Sadrian * Used by nart to force reading/writing at a specific address. 109250003Sadrian * The driver can normally allow autodetection by setting size=0. 110250003Sadrian */ 111250003Sadrianvoid ar9300_calibration_data_address_set(struct ath_hal *ah, int32_t size) 112250003Sadrian{ 113250003Sadrian if (ah != 0) { 114250003Sadrian AH9300(ah)->calibration_data_source_address = size; 115250003Sadrian } else { 116250003Sadrian calibration_data_try_address = size; 117250003Sadrian } 118250003Sadrian} 119250003Sadrian 120250003Sadrianint32_t ar9300_calibration_data_address_get(struct ath_hal *ah) 121250003Sadrian{ 122250003Sadrian if (ah != 0) { 123250003Sadrian return AH9300(ah)->calibration_data_source_address; 124250003Sadrian } else { 125250003Sadrian return calibration_data_try_address; 126250003Sadrian } 127250003Sadrian} 128250003Sadrian 129250003Sadrian/* 130250003Sadrian * This is the template that is loaded if ar9300_eeprom_restore() 131250003Sadrian * can't find valid data in the memory. 132250003Sadrian */ 133250003Sadrianstatic int Ar9300_eeprom_template_preference = ar9300_eeprom_template_generic; 134250003Sadrian 135250003Sadrianvoid ar9300_eeprom_template_preference(int32_t value) 136250003Sadrian{ 137250003Sadrian Ar9300_eeprom_template_preference = value; 138250003Sadrian} 139250003Sadrian 140250003Sadrian/* 141250003Sadrian * Install the specified default template. 142250003Sadrian * Overwrites any existing calibration and configuration information in memory. 143250003Sadrian */ 144250003Sadrianint32_t ar9300_eeprom_template_install(struct ath_hal *ah, int32_t value) 145250003Sadrian{ 146250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 147250003Sadrian ar9300_eeprom_t *mptr, *dptr; 148250003Sadrian int mdata_size; 149250003Sadrian 150250003Sadrian mptr = &ahp->ah_eeprom; 151250003Sadrian mdata_size = ar9300_eeprom_struct_size(); 152250003Sadrian if (mptr != 0) { 153250003Sadrian#if 0 154250003Sadrian calibration_data_source = calibration_data_none; 155250003Sadrian calibration_data_source_address = 0; 156250003Sadrian#endif 157250003Sadrian dptr = ar9300_eeprom_struct_default_find_by_id(value); 158250003Sadrian if (dptr != 0) { 159250003Sadrian OS_MEMCPY(mptr, dptr, mdata_size); 160250003Sadrian return 0; 161250003Sadrian } 162250003Sadrian } 163250003Sadrian return -1; 164250003Sadrian} 165250003Sadrian 166250003Sadrianstatic int 167250003Sadrianar9300_eeprom_restore_something(struct ath_hal *ah, ar9300_eeprom_t *mptr, 168250003Sadrian int mdata_size) 169250003Sadrian{ 170250003Sadrian int it; 171250003Sadrian ar9300_eeprom_t *dptr; 172250003Sadrian int nptr; 173250003Sadrian 174250003Sadrian nptr = -1; 175250003Sadrian /* 176250003Sadrian * if we didn't find any blocks in the memory, 177250003Sadrian * put the prefered template in place 178250003Sadrian */ 179250003Sadrian if (nptr < 0) { 180250003Sadrian AH9300(ah)->calibration_data_source = calibration_data_none; 181250003Sadrian AH9300(ah)->calibration_data_source_address = 0; 182250003Sadrian dptr = ar9300_eeprom_struct_default_find_by_id( 183250003Sadrian Ar9300_eeprom_template_preference); 184250003Sadrian if (dptr != 0) { 185250003Sadrian OS_MEMCPY(mptr, dptr, mdata_size); 186250003Sadrian nptr = 0; 187250003Sadrian } 188250003Sadrian } 189250003Sadrian /* 190250003Sadrian * if we didn't find the prefered one, 191250003Sadrian * put the normal default template in place 192250003Sadrian */ 193250003Sadrian if (nptr < 0) { 194250003Sadrian AH9300(ah)->calibration_data_source = calibration_data_none; 195250003Sadrian AH9300(ah)->calibration_data_source_address = 0; 196250003Sadrian dptr = ar9300_eeprom_struct_default_find_by_id( 197250003Sadrian ar9300_eeprom_template_default); 198250003Sadrian if (dptr != 0) { 199250003Sadrian OS_MEMCPY(mptr, dptr, mdata_size); 200250003Sadrian nptr = 0; 201250003Sadrian } 202250003Sadrian } 203250003Sadrian /* 204250003Sadrian * if we can't find the best template, put any old template in place 205250003Sadrian * presume that newer ones are better, so search backwards 206250003Sadrian */ 207250003Sadrian if (nptr < 0) { 208250003Sadrian AH9300(ah)->calibration_data_source = calibration_data_none; 209250003Sadrian AH9300(ah)->calibration_data_source_address = 0; 210250003Sadrian for (it = ar9300_eeprom_struct_default_many() - 1; it >= 0; it--) { 211250003Sadrian dptr = ar9300_eeprom_struct_default(it); 212250003Sadrian if (dptr != 0) { 213250003Sadrian OS_MEMCPY(mptr, dptr, mdata_size); 214250003Sadrian nptr = 0; 215250003Sadrian break; 216250003Sadrian } 217250003Sadrian } 218250003Sadrian } 219250003Sadrian return nptr; 220250003Sadrian} 221250003Sadrian 222250003Sadrian/* 223250003Sadrian * Read 16 bits of data from offset into *data 224250003Sadrian */ 225250003SadrianHAL_BOOL 226250003Sadrianar9300_eeprom_read_word(struct ath_hal *ah, u_int off, u_int16_t *data) 227250003Sadrian{ 228250003Sadrian if (AR_SREV_OSPREY(ah) || AR_SREV_POSEIDON(ah)) 229250003Sadrian { 230250003Sadrian (void) OS_REG_READ(ah, AR9300_EEPROM_OFFSET + (off << AR9300_EEPROM_S)); 231250003Sadrian if (!ath_hal_wait(ah, 232250003Sadrian AR_HOSTIF_REG(ah, AR_EEPROM_STATUS_DATA), 233250003Sadrian AR_EEPROM_STATUS_DATA_BUSY | AR_EEPROM_STATUS_DATA_PROT_ACCESS, 234250008Sadrian 0)) 235250003Sadrian { 236250003Sadrian return AH_FALSE; 237250003Sadrian } 238250003Sadrian *data = MS(OS_REG_READ(ah, 239250003Sadrian AR_HOSTIF_REG(ah, AR_EEPROM_STATUS_DATA)), AR_EEPROM_STATUS_DATA_VAL); 240250003Sadrian return AH_TRUE; 241250003Sadrian } 242250003Sadrian else 243250003Sadrian { 244250003Sadrian *data = 0; 245250003Sadrian return AH_FALSE; 246250003Sadrian } 247250003Sadrian} 248250003Sadrian 249250003Sadrian 250250003SadrianHAL_BOOL 251250003Sadrianar9300_otp_read(struct ath_hal *ah, u_int off, u_int32_t *data, HAL_BOOL is_wifi) 252250003Sadrian{ 253250003Sadrian int time_out = 1000; 254250003Sadrian int status = 0; 255250003Sadrian u_int32_t addr; 256250003Sadrian 257291437Sadrian if (AR_SREV_HONEYBEE(ah)){ /* no OTP for Honeybee */ 258291437Sadrian return false; 259291437Sadrian } 260250003Sadrian addr = (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah))? 261250003Sadrian OTP_MEM_START_ADDRESS_WASP : OTP_MEM_START_ADDRESS; 262250003Sadrian if (!is_wifi) { 263250003Sadrian addr = BTOTP_MEM_START_ADDRESS; 264250003Sadrian } 265250003Sadrian addr += off * 4; /* OTP is 32 bit addressable */ 266250003Sadrian (void) OS_REG_READ(ah, addr); 267250003Sadrian 268250003Sadrian addr = (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) ? 269250003Sadrian OTP_STATUS0_OTP_SM_BUSY_WASP : OTP_STATUS0_OTP_SM_BUSY; 270250003Sadrian if (!is_wifi) { 271250003Sadrian addr = BTOTP_STATUS0_OTP_SM_BUSY; 272250003Sadrian } 273250003Sadrian while ((time_out > 0) && (!status)) { /* wait for access complete */ 274250003Sadrian /* Read data valid, access not busy, sm not busy */ 275250003Sadrian status = ((OS_REG_READ(ah, addr) & 0x7) == 0x4) ? 1 : 0; 276250003Sadrian time_out--; 277250003Sadrian } 278250003Sadrian if (time_out == 0) { 279250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 280250003Sadrian "%s: Timed out during OTP Status0 validation\n", __func__); 281250003Sadrian return AH_FALSE; 282250003Sadrian } 283250003Sadrian 284250003Sadrian addr = (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) ? 285250003Sadrian OTP_STATUS1_EFUSE_READ_DATA_WASP : OTP_STATUS1_EFUSE_READ_DATA; 286250003Sadrian if (!is_wifi) { 287250003Sadrian addr = BTOTP_STATUS1_EFUSE_READ_DATA; 288250003Sadrian } 289250003Sadrian *data = OS_REG_READ(ah, addr); 290250003Sadrian return AH_TRUE; 291250003Sadrian} 292250003Sadrian 293250003Sadrian 294250003Sadrian 295250003Sadrian 296250003Sadrianstatic HAL_STATUS 297250003Sadrianar9300_flash_map(struct ath_hal *ah) 298250003Sadrian{ 299250008Sadrian /* XXX disable flash remapping for now (ie, SoC support) */ 300250008Sadrian ath_hal_printf(ah, "%s: unimplemented for now\n", __func__); 301250008Sadrian#if 0 302250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 303250003Sadrian#if defined(AR9100) || defined(__NetBSD__) 304250003Sadrian ahp->ah_cal_mem = OS_REMAP(ah, AR9300_EEPROM_START_ADDR, AR9300_EEPROM_MAX); 305250003Sadrian#else 306250003Sadrian ahp->ah_cal_mem = OS_REMAP((uintptr_t)(AH_PRIVATE(ah)->ah_st), 307250003Sadrian (AR9300_EEPROM_MAX + AR9300_FLASH_CAL_START_OFFSET)); 308250003Sadrian#endif 309250003Sadrian if (!ahp->ah_cal_mem) { 310250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 311250003Sadrian "%s: cannot remap eeprom region \n", __func__); 312250003Sadrian return HAL_EIO; 313250003Sadrian } 314250008Sadrian#endif 315250003Sadrian return HAL_OK; 316250003Sadrian} 317250003Sadrian 318250003SadrianHAL_BOOL 319250003Sadrianar9300_flash_read(struct ath_hal *ah, u_int off, u_int16_t *data) 320250003Sadrian{ 321250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 322250003Sadrian 323250003Sadrian *data = ((u_int16_t *)ahp->ah_cal_mem)[off]; 324250003Sadrian return AH_TRUE; 325250003Sadrian} 326250003Sadrian 327250003SadrianHAL_BOOL 328250003Sadrianar9300_flash_write(struct ath_hal *ah, u_int off, u_int16_t data) 329250003Sadrian{ 330250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 331250003Sadrian 332250003Sadrian ((u_int16_t *)ahp->ah_cal_mem)[off] = data; 333250003Sadrian return AH_TRUE; 334250003Sadrian} 335250003Sadrian 336250003SadrianHAL_STATUS 337250003Sadrianar9300_eeprom_attach(struct ath_hal *ah) 338250003Sadrian{ 339250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 340250003Sadrian ahp->try_dram = 1; 341250003Sadrian ahp->try_eeprom = 1; 342250003Sadrian ahp->try_otp = 1; 343250003Sadrian#ifdef ATH_CAL_NAND_FLASH 344250003Sadrian ahp->try_nand = 1; 345250003Sadrian#else 346250003Sadrian ahp->try_flash = 1; 347250003Sadrian#endif 348250003Sadrian ahp->calibration_data_source = calibration_data_none; 349250003Sadrian ahp->calibration_data_source_address = 0; 350250003Sadrian ahp->calibration_data_try = calibration_data_try; 351250003Sadrian ahp->calibration_data_try_address = 0; 352250003Sadrian 353250003Sadrian /* 354250003Sadrian * In case flash will be used for EEPROM. Otherwise ahp->ah_cal_mem 355250003Sadrian * must be set to NULL or the real EEPROM address. 356250003Sadrian */ 357250003Sadrian ar9300_flash_map(ah); 358250003Sadrian /* 359250003Sadrian * ###### This function always return NO SPUR. 360291437Sadrian * This is not true for many board designs. 361250003Sadrian * Does anyone use this? 362250003Sadrian */ 363250008Sadrian AH_PRIVATE(ah)->ah_getSpurChan = ar9300_eeprom_get_spur_chan; 364250003Sadrian 365250003Sadrian#ifdef OLDCODE 366250003Sadrian /* XXX Needs to be moved for dynamic selection */ 367250003Sadrian ahp->ah_eeprom = *(default9300[ar9300_eeprom_template_default]); 368250003Sadrian 369250003Sadrian 370250003Sadrian if (AR_SREV_HORNET(ah)) { 371250003Sadrian /* Set default values for Hornet. */ 372250003Sadrian ahp->ah_eeprom.base_eep_header.op_cap_flags.op_flags = 373250003Sadrian AR9300_OPFLAGS_11G; 374250003Sadrian ahp->ah_eeprom.base_eep_header.txrx_mask = 0x11; 375250003Sadrian } else if (AR_SREV_POSEIDON(ah)) { 376250003Sadrian /* Set default values for Poseidon. */ 377250003Sadrian ahp->ah_eeprom.base_eep_header.op_cap_flags.op_flags = 378250003Sadrian AR9300_OPFLAGS_11G; 379250003Sadrian ahp->ah_eeprom.base_eep_header.txrx_mask = 0x11; 380250003Sadrian } 381250003Sadrian 382250003Sadrian if (AH_PRIVATE(ah)->ah_config.ath_hal_skip_eeprom_read) { 383250003Sadrian ahp->ah_emu_eeprom = 1; 384250003Sadrian return HAL_OK; 385250003Sadrian } 386250003Sadrian 387250003Sadrian ahp->ah_emu_eeprom = 1; 388250003Sadrian 389250003Sadrian#ifdef UNUSED 390250003Sadrian#endif 391250003Sadrian 392250003Sadrian if (!ar9300_fill_eeprom(ah)) { 393250003Sadrian return HAL_EIO; 394250003Sadrian } 395250003Sadrian 396250003Sadrian return HAL_OK; 397250003Sadrian /* return ar9300_check_eeprom(ah); */ 398250003Sadrian#else 399250003Sadrian ahp->ah_emu_eeprom = 1; 400250003Sadrian 401250003Sadrian#if 0 402250003Sadrian/*#ifdef MDK_AP*/ /* MDK_AP is defined only in NART AP build */ 403250003Sadrian u_int8_t buffer[10]; 404250003Sadrian int caldata_check = 0; 405250003Sadrian 406250003Sadrian ar9300_calibration_data_read_flash( 407250003Sadrian ah, FLASH_BASE_CALDATA_OFFSET, buffer, 4); 408250003Sadrian printf("flash caldata:: %x\n", buffer[0]); 409250003Sadrian if (buffer[0] != 0xff) { 410250003Sadrian caldata_check = 1; 411250003Sadrian } 412250003Sadrian if (!caldata_check) { 413250003Sadrian ar9300_eeprom_t *mptr; 414250003Sadrian int mdata_size; 415250003Sadrian if (AR_SREV_HORNET(ah)) { 416250003Sadrian /* XXX: For initial testing */ 417250003Sadrian mptr = &ahp->ah_eeprom; 418250003Sadrian mdata_size = ar9300_eeprom_struct_size(); 419250003Sadrian ahp->ah_eeprom = ar9300_template_ap121; 420250003Sadrian ahp->ah_emu_eeprom = 1; 421250003Sadrian /* need it to let art save in to flash ????? */ 422250003Sadrian calibration_data_source = calibration_data_flash; 423250003Sadrian } else if (AR_SREV_WASP(ah)) { 424250003Sadrian /* XXX: For initial testing */ 425250003Sadrian ath_hal_printf(ah, " wasp eep attach\n"); 426250003Sadrian mptr = &ahp->ah_eeprom; 427250003Sadrian mdata_size = ar9300_eeprom_struct_size(); 428250003Sadrian ahp->ah_eeprom = ar9300_template_generic; 429250003Sadrian ahp->ah_eeprom.mac_addr[0] = 0x00; 430250003Sadrian ahp->ah_eeprom.mac_addr[1] = 0x03; 431250003Sadrian ahp->ah_eeprom.mac_addr[2] = 0x7F; 432250003Sadrian ahp->ah_eeprom.mac_addr[3] = 0xBA; 433250003Sadrian ahp->ah_eeprom.mac_addr[4] = 0xD0; 434250003Sadrian ahp->ah_eeprom.mac_addr[5] = 0x00; 435250003Sadrian ahp->ah_emu_eeprom = 1; 436250003Sadrian ahp->ah_eeprom.base_eep_header.txrx_mask = 0x33; 437250003Sadrian ahp->ah_eeprom.base_eep_header.txrxgain = 0x10; 438250003Sadrian /* need it to let art save in to flash ????? */ 439250003Sadrian calibration_data_source = calibration_data_flash; 440250003Sadrian } 441250003Sadrian return HAL_OK; 442250003Sadrian } 443250003Sadrian#endif 444291437Sadrian if (AR_SREV_HORNET(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah) 445291437Sadrian || AR_SREV_HONEYBEE(ah)) { 446250003Sadrian ahp->try_eeprom = 0; 447250003Sadrian } 448250003Sadrian 449291437Sadrian if (AR_SREV_HONEYBEE(ah)) { 450291437Sadrian ahp->try_otp = 0; 451291437Sadrian } 452291437Sadrian 453250003Sadrian if (!ar9300_eeprom_restore(ah)) { 454250003Sadrian return HAL_EIO; 455250003Sadrian } 456250003Sadrian return HAL_OK; 457250003Sadrian#endif 458250003Sadrian} 459250003Sadrian 460250003Sadrianu_int32_t 461250003Sadrianar9300_eeprom_get(struct ath_hal_9300 *ahp, EEPROM_PARAM param) 462250003Sadrian{ 463250003Sadrian ar9300_eeprom_t *eep = &ahp->ah_eeprom; 464250003Sadrian OSPREY_BASE_EEP_HEADER *p_base = &eep->base_eep_header; 465250003Sadrian OSPREY_BASE_EXTENSION_1 *base_ext1 = &eep->base_ext1; 466250003Sadrian 467250003Sadrian switch (param) { 468250008Sadrian#ifdef NOTYET 469250003Sadrian case EEP_NFTHRESH_5: 470250003Sadrian return p_modal[0].noise_floor_thresh_ch[0]; 471250003Sadrian case EEP_NFTHRESH_2: 472250003Sadrian return p_modal[1].noise_floor_thresh_ch[0]; 473250003Sadrian#endif 474250003Sadrian case EEP_MAC_LSW: 475250003Sadrian return eep->mac_addr[0] << 8 | eep->mac_addr[1]; 476250003Sadrian case EEP_MAC_MID: 477250003Sadrian return eep->mac_addr[2] << 8 | eep->mac_addr[3]; 478250003Sadrian case EEP_MAC_MSW: 479250003Sadrian return eep->mac_addr[4] << 8 | eep->mac_addr[5]; 480250003Sadrian case EEP_REG_0: 481250003Sadrian return p_base->reg_dmn[0]; 482250003Sadrian case EEP_REG_1: 483250003Sadrian return p_base->reg_dmn[1]; 484250003Sadrian case EEP_OP_CAP: 485250003Sadrian return p_base->device_cap; 486250003Sadrian case EEP_OP_MODE: 487250003Sadrian return p_base->op_cap_flags.op_flags; 488250003Sadrian case EEP_RF_SILENT: 489250003Sadrian return p_base->rf_silent; 490250008Sadrian#ifdef NOTYET 491250003Sadrian case EEP_OB_5: 492250003Sadrian return p_modal[0].ob; 493250003Sadrian case EEP_DB_5: 494250003Sadrian return p_modal[0].db; 495250003Sadrian case EEP_OB_2: 496250003Sadrian return p_modal[1].ob; 497250003Sadrian case EEP_DB_2: 498250003Sadrian return p_modal[1].db; 499250003Sadrian case EEP_MINOR_REV: 500250003Sadrian return p_base->eeprom_version & AR9300_EEP_VER_MINOR_MASK; 501250003Sadrian#endif 502250003Sadrian case EEP_TX_MASK: 503250003Sadrian return (p_base->txrx_mask >> 4) & 0xf; 504250003Sadrian case EEP_RX_MASK: 505250003Sadrian return p_base->txrx_mask & 0xf; 506250008Sadrian#ifdef NOTYET 507250003Sadrian case EEP_FSTCLK_5G: 508250003Sadrian return p_base->fast_clk5g; 509250003Sadrian case EEP_RXGAIN_TYPE: 510250003Sadrian return p_base->rx_gain_type; 511250003Sadrian#endif 512250003Sadrian case EEP_DRIVE_STRENGTH: 513250003Sadrian#define AR9300_EEP_BASE_DRIVE_STRENGTH 0x1 514250003Sadrian return p_base->misc_configuration & AR9300_EEP_BASE_DRIVE_STRENGTH; 515250003Sadrian case EEP_INTERNAL_REGULATOR: 516250003Sadrian /* Bit 4 is internal regulator flag */ 517250003Sadrian return ((p_base->feature_enable & 0x10) >> 4); 518250003Sadrian case EEP_SWREG: 519250003Sadrian return (p_base->swreg); 520250003Sadrian case EEP_PAPRD_ENABLED: 521250003Sadrian /* Bit 5 is paprd flag */ 522250003Sadrian return ((p_base->feature_enable & 0x20) >> 5); 523250003Sadrian case EEP_ANTDIV_control: 524250003Sadrian return (u_int32_t)(base_ext1->ant_div_control); 525250003Sadrian case EEP_CHAIN_MASK_REDUCE: 526250003Sadrian return ((p_base->misc_configuration >> 3) & 0x1); 527250003Sadrian case EEP_OL_PWRCTRL: 528250003Sadrian return 0; 529250003Sadrian case EEP_DEV_TYPE: 530250003Sadrian return p_base->device_type; 531250003Sadrian default: 532250003Sadrian HALASSERT(0); 533250003Sadrian return 0; 534250003Sadrian } 535250003Sadrian} 536250003Sadrian 537250003Sadrian 538250003Sadrian 539250003Sadrian/******************************************************************************/ 540250003Sadrian/*! 541250003Sadrian** \brief EEPROM fixup code for INI values 542250003Sadrian** 543250003Sadrian** This routine provides a place to insert "fixup" code for specific devices 544250003Sadrian** that need to modify INI values based on EEPROM values, BEFORE the INI values 545250003Sadrian** are written. 546250003Sadrian** Certain registers in the INI file can only be written once without 547250003Sadrian** undesired side effects, and this provides a place for EEPROM overrides 548250003Sadrian** in these cases. 549250003Sadrian** 550250003Sadrian** This is called at attach time once. It should not affect run time 551250003Sadrian** performance at all 552250003Sadrian** 553250003Sadrian** \param ah Pointer to HAL object (this) 554250003Sadrian** \param p_eep_data Pointer to (filled in) eeprom data structure 555250003Sadrian** \param reg register being inspected on this call 556250003Sadrian** \param value value in INI file 557250003Sadrian** 558250003Sadrian** \return Updated value for INI file. 559250003Sadrian*/ 560250003Sadrianu_int32_t 561250003Sadrianar9300_ini_fixup(struct ath_hal *ah, ar9300_eeprom_t *p_eep_data, 562250003Sadrian u_int32_t reg, u_int32_t value) 563250003Sadrian{ 564250003Sadrian HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, 565250003Sadrian "ar9300_eeprom_def_ini_fixup: FIXME\n"); 566250003Sadrian#if 0 567250003Sadrian BASE_EEPDEF_HEADER *p_base = &(p_eep_data->base_eep_header); 568250003Sadrian 569250003Sadrian switch (AH_PRIVATE(ah)->ah_devid) 570250003Sadrian { 571250003Sadrian case AR9300_DEVID_AR9300_PCI: 572250003Sadrian /* 573250003Sadrian ** Need to set the external/internal regulator bit to the proper value. 574250003Sadrian ** Can only write this ONCE. 575250003Sadrian */ 576250003Sadrian 577250003Sadrian if ( reg == 0x7894 ) 578250003Sadrian { 579250003Sadrian /* 580250003Sadrian ** Check for an EEPROM data structure of "0x0b" or better 581250003Sadrian */ 582250003Sadrian 583250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, "ini VAL: %x EEPROM: %x\n", 584250003Sadrian value, (p_base->version & 0xff)); 585250003Sadrian 586250003Sadrian if ( (p_base->version & 0xff) > 0x0a) { 587250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 588250003Sadrian "PWDCLKIND: %d\n", p_base->pwdclkind); 589250003Sadrian value &= ~AR_AN_TOP2_PWDCLKIND; 590250003Sadrian value |= 591250003Sadrian AR_AN_TOP2_PWDCLKIND & 592250003Sadrian (p_base->pwdclkind << AR_AN_TOP2_PWDCLKIND_S); 593250003Sadrian } else { 594250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, "PWDCLKIND Earlier Rev\n"); 595250003Sadrian } 596250003Sadrian 597250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, "final ini VAL: %x\n", value); 598250003Sadrian } 599250003Sadrian break; 600250003Sadrian 601250003Sadrian } 602250003Sadrian 603250003Sadrian return (value); 604250003Sadrian#else 605250003Sadrian return 0; 606250003Sadrian#endif 607250003Sadrian} 608250003Sadrian 609250003Sadrian/* 610250003Sadrian * Returns the interpolated y value corresponding to the specified x value 611250003Sadrian * from the np ordered pairs of data (px,py). 612250003Sadrian * The pairs do not have to be in any order. 613250003Sadrian * If the specified x value is less than any of the px, 614250003Sadrian * the returned y value is equal to the py for the lowest px. 615250003Sadrian * If the specified x value is greater than any of the px, 616250003Sadrian * the returned y value is equal to the py for the highest px. 617250003Sadrian */ 618250003Sadrianstatic int 619250003Sadrianinterpolate(int32_t x, int32_t *px, int32_t *py, u_int16_t np) 620250003Sadrian{ 621250003Sadrian int ip = 0; 622250003Sadrian int lx = 0, ly = 0, lhave = 0; 623250003Sadrian int hx = 0, hy = 0, hhave = 0; 624250003Sadrian int dx = 0; 625250003Sadrian int y = 0; 626250003Sadrian int bf, factor, plus; 627250003Sadrian 628250003Sadrian lhave = 0; 629250003Sadrian hhave = 0; 630250003Sadrian /* 631250003Sadrian * identify best lower and higher x calibration measurement 632250003Sadrian */ 633250003Sadrian for (ip = 0; ip < np; ip++) { 634250003Sadrian dx = x - px[ip]; 635250003Sadrian /* this measurement is higher than our desired x */ 636250003Sadrian if (dx <= 0) { 637250003Sadrian if (!hhave || dx > (x - hx)) { 638250003Sadrian /* new best higher x measurement */ 639250003Sadrian hx = px[ip]; 640250003Sadrian hy = py[ip]; 641250003Sadrian hhave = 1; 642250003Sadrian } 643250003Sadrian } 644250003Sadrian /* this measurement is lower than our desired x */ 645250003Sadrian if (dx >= 0) { 646250003Sadrian if (!lhave || dx < (x - lx)) { 647250003Sadrian /* new best lower x measurement */ 648250003Sadrian lx = px[ip]; 649250003Sadrian ly = py[ip]; 650250003Sadrian lhave = 1; 651250003Sadrian } 652250003Sadrian } 653250003Sadrian } 654250003Sadrian /* the low x is good */ 655250003Sadrian if (lhave) { 656250003Sadrian /* so is the high x */ 657250003Sadrian if (hhave) { 658250003Sadrian /* they're the same, so just pick one */ 659250003Sadrian if (hx == lx) { 660250003Sadrian y = ly; 661250003Sadrian } else { 662250003Sadrian /* interpolate with round off */ 663250003Sadrian bf = (2 * (hy - ly) * (x - lx)) / (hx - lx); 664250003Sadrian plus = (bf % 2); 665250003Sadrian factor = bf / 2; 666250003Sadrian y = ly + factor + plus; 667250003Sadrian } 668250003Sadrian } else { 669250003Sadrian /* only low is good, use it */ 670250003Sadrian y = ly; 671250003Sadrian } 672250003Sadrian } else if (hhave) { 673250003Sadrian /* only high is good, use it */ 674250003Sadrian y = hy; 675250003Sadrian } else { 676250003Sadrian /* nothing is good,this should never happen unless np=0, ???? */ 677250003Sadrian y = -(1 << 30); 678250003Sadrian } 679250003Sadrian 680250003Sadrian return y; 681250003Sadrian} 682250003Sadrian 683250003Sadrianu_int8_t 684250003Sadrianar9300_eeprom_get_legacy_trgt_pwr(struct ath_hal *ah, u_int16_t rate_index, 685250003Sadrian u_int16_t freq, HAL_BOOL is_2ghz) 686250003Sadrian{ 687250003Sadrian u_int16_t num_piers, i; 688250003Sadrian int32_t target_power_array[OSPREY_NUM_5G_20_TARGET_POWERS]; 689250003Sadrian int32_t freq_array[OSPREY_NUM_5G_20_TARGET_POWERS]; 690250003Sadrian u_int8_t *p_freq_bin; 691250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 692250003Sadrian CAL_TARGET_POWER_LEG *p_eeprom_target_pwr; 693250003Sadrian 694250003Sadrian if (is_2ghz) { 695250003Sadrian num_piers = OSPREY_NUM_2G_20_TARGET_POWERS; 696250003Sadrian p_eeprom_target_pwr = eep->cal_target_power_2g; 697250003Sadrian p_freq_bin = eep->cal_target_freqbin_2g; 698250003Sadrian } else { 699250003Sadrian num_piers = OSPREY_NUM_5G_20_TARGET_POWERS; 700250003Sadrian p_eeprom_target_pwr = eep->cal_target_power_5g; 701250003Sadrian p_freq_bin = eep->cal_target_freqbin_5g; 702250003Sadrian } 703250003Sadrian 704250003Sadrian /* 705250003Sadrian * create array of channels and targetpower from 706250003Sadrian * targetpower piers stored on eeprom 707250003Sadrian */ 708250003Sadrian for (i = 0; i < num_piers; i++) { 709250003Sadrian freq_array[i] = FBIN2FREQ(p_freq_bin[i], is_2ghz); 710250003Sadrian target_power_array[i] = p_eeprom_target_pwr[i].t_pow2x[rate_index]; 711250003Sadrian } 712250003Sadrian 713250003Sadrian /* interpolate to get target power for given frequency */ 714250003Sadrian return 715250003Sadrian ((u_int8_t)interpolate( 716250003Sadrian (int32_t)freq, freq_array, target_power_array, num_piers)); 717250003Sadrian} 718250003Sadrian 719250003Sadrianu_int8_t 720250003Sadrianar9300_eeprom_get_ht20_trgt_pwr(struct ath_hal *ah, u_int16_t rate_index, 721250003Sadrian u_int16_t freq, HAL_BOOL is_2ghz) 722250003Sadrian{ 723250003Sadrian u_int16_t num_piers, i; 724250003Sadrian int32_t target_power_array[OSPREY_NUM_5G_20_TARGET_POWERS]; 725250003Sadrian int32_t freq_array[OSPREY_NUM_5G_20_TARGET_POWERS]; 726250003Sadrian u_int8_t *p_freq_bin; 727250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 728250003Sadrian OSP_CAL_TARGET_POWER_HT *p_eeprom_target_pwr; 729250003Sadrian 730250003Sadrian if (is_2ghz) { 731250003Sadrian num_piers = OSPREY_NUM_2G_20_TARGET_POWERS; 732250003Sadrian p_eeprom_target_pwr = eep->cal_target_power_2g_ht20; 733250003Sadrian p_freq_bin = eep->cal_target_freqbin_2g_ht20; 734250003Sadrian } else { 735250003Sadrian num_piers = OSPREY_NUM_5G_20_TARGET_POWERS; 736250003Sadrian p_eeprom_target_pwr = eep->cal_target_power_5g_ht20; 737250003Sadrian p_freq_bin = eep->cal_target_freqbin_5g_ht20; 738250003Sadrian } 739250003Sadrian 740250003Sadrian /* 741250003Sadrian * create array of channels and targetpower from 742250003Sadrian * targetpower piers stored on eeprom 743250003Sadrian */ 744250003Sadrian for (i = 0; i < num_piers; i++) { 745250003Sadrian freq_array[i] = FBIN2FREQ(p_freq_bin[i], is_2ghz); 746250003Sadrian target_power_array[i] = p_eeprom_target_pwr[i].t_pow2x[rate_index]; 747250003Sadrian } 748250003Sadrian 749250003Sadrian /* interpolate to get target power for given frequency */ 750250003Sadrian return 751250003Sadrian ((u_int8_t)interpolate( 752250003Sadrian (int32_t)freq, freq_array, target_power_array, num_piers)); 753250003Sadrian} 754250003Sadrian 755250003Sadrianu_int8_t 756250003Sadrianar9300_eeprom_get_ht40_trgt_pwr(struct ath_hal *ah, u_int16_t rate_index, 757250003Sadrian u_int16_t freq, HAL_BOOL is_2ghz) 758250003Sadrian{ 759250003Sadrian u_int16_t num_piers, i; 760250003Sadrian int32_t target_power_array[OSPREY_NUM_5G_40_TARGET_POWERS]; 761250003Sadrian int32_t freq_array[OSPREY_NUM_5G_40_TARGET_POWERS]; 762250003Sadrian u_int8_t *p_freq_bin; 763250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 764250003Sadrian OSP_CAL_TARGET_POWER_HT *p_eeprom_target_pwr; 765250003Sadrian 766250003Sadrian if (is_2ghz) { 767250003Sadrian num_piers = OSPREY_NUM_2G_40_TARGET_POWERS; 768250003Sadrian p_eeprom_target_pwr = eep->cal_target_power_2g_ht40; 769250003Sadrian p_freq_bin = eep->cal_target_freqbin_2g_ht40; 770250003Sadrian } else { 771250003Sadrian num_piers = OSPREY_NUM_5G_40_TARGET_POWERS; 772250003Sadrian p_eeprom_target_pwr = eep->cal_target_power_5g_ht40; 773250003Sadrian p_freq_bin = eep->cal_target_freqbin_5g_ht40; 774250003Sadrian } 775250003Sadrian 776250003Sadrian /* 777250003Sadrian * create array of channels and targetpower from 778250003Sadrian * targetpower piers stored on eeprom 779250003Sadrian */ 780250003Sadrian for (i = 0; i < num_piers; i++) { 781250003Sadrian freq_array[i] = FBIN2FREQ(p_freq_bin[i], is_2ghz); 782250003Sadrian target_power_array[i] = p_eeprom_target_pwr[i].t_pow2x[rate_index]; 783250003Sadrian } 784250003Sadrian 785250003Sadrian /* interpolate to get target power for given frequency */ 786250003Sadrian return 787250003Sadrian ((u_int8_t)interpolate( 788250003Sadrian (int32_t)freq, freq_array, target_power_array, num_piers)); 789250003Sadrian} 790250003Sadrian 791250003Sadrianu_int8_t 792250003Sadrianar9300_eeprom_get_cck_trgt_pwr(struct ath_hal *ah, u_int16_t rate_index, 793250003Sadrian u_int16_t freq) 794250003Sadrian{ 795250003Sadrian u_int16_t num_piers = OSPREY_NUM_2G_CCK_TARGET_POWERS, i; 796250003Sadrian int32_t target_power_array[OSPREY_NUM_2G_CCK_TARGET_POWERS]; 797250003Sadrian int32_t freq_array[OSPREY_NUM_2G_CCK_TARGET_POWERS]; 798250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 799250003Sadrian u_int8_t *p_freq_bin = eep->cal_target_freqbin_cck; 800250003Sadrian CAL_TARGET_POWER_LEG *p_eeprom_target_pwr = eep->cal_target_power_cck; 801250003Sadrian 802250003Sadrian /* 803250003Sadrian * create array of channels and targetpower from 804250003Sadrian * targetpower piers stored on eeprom 805250003Sadrian */ 806250003Sadrian for (i = 0; i < num_piers; i++) { 807250003Sadrian freq_array[i] = FBIN2FREQ(p_freq_bin[i], 1); 808250003Sadrian target_power_array[i] = p_eeprom_target_pwr[i].t_pow2x[rate_index]; 809250003Sadrian } 810250003Sadrian 811250003Sadrian /* interpolate to get target power for given frequency */ 812250003Sadrian return 813250003Sadrian ((u_int8_t)interpolate( 814250003Sadrian (int32_t)freq, freq_array, target_power_array, num_piers)); 815250003Sadrian} 816250003Sadrian 817250003Sadrian/* 818250003Sadrian * Set tx power registers to array of values passed in 819250003Sadrian */ 820250003Sadrianint 821250003Sadrianar9300_transmit_power_reg_write(struct ath_hal *ah, u_int8_t *p_pwr_array) 822250003Sadrian{ 823250003Sadrian#define POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) 824250003Sadrian /* make sure forced gain is not set */ 825250003Sadrian#if 0 826250003Sadrian field_write("force_dac_gain", 0); 827250003Sadrian OS_REG_WRITE(ah, 0xa3f8, 0); 828250003Sadrian field_write("force_tx_gain", 0); 829250003Sadrian#endif 830250003Sadrian 831250003Sadrian OS_REG_WRITE(ah, 0xa458, 0); 832250003Sadrian 833250003Sadrian /* Write the OFDM power per rate set */ 834250003Sadrian /* 6 (LSB), 9, 12, 18 (MSB) */ 835250003Sadrian OS_REG_WRITE(ah, 0xa3c0, 836250003Sadrian POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 24) 837250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 16) 838250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 8) 839250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 0) 840250003Sadrian ); 841250003Sadrian /* 24 (LSB), 36, 48, 54 (MSB) */ 842250003Sadrian OS_REG_WRITE(ah, 0xa3c4, 843250003Sadrian POW_SM(p_pwr_array[ALL_TARGET_LEGACY_54], 24) 844250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_48], 16) 845250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_36], 8) 846250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 0) 847250003Sadrian ); 848250003Sadrian 849250003Sadrian /* Write the CCK power per rate set */ 850250003Sadrian /* 1L (LSB), reserved, 2L, 2S (MSB) */ 851250003Sadrian OS_REG_WRITE(ah, 0xa3c8, 852250003Sadrian POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 24) 853250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 16) 854250003Sadrian/* | POW_SM(tx_power_times2, 8)*/ /* this is reserved for Osprey */ 855250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 0) 856250003Sadrian ); 857250003Sadrian /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */ 858250003Sadrian OS_REG_WRITE(ah, 0xa3cc, 859250003Sadrian POW_SM(p_pwr_array[ALL_TARGET_LEGACY_11S], 24) 860250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_11L], 16) 861250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_5S], 8) 862250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 0) 863250003Sadrian ); 864250003Sadrian 865250003Sadrian /* write the power for duplicated frames - HT40 */ 866250003Sadrian /* dup40_cck (LSB), dup40_ofdm, ext20_cck, ext20_ofdm (MSB) */ 867250003Sadrian OS_REG_WRITE(ah, 0xa3e0, 868250003Sadrian POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 24) 869250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 16) 870250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 8) 871250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 0) 872250003Sadrian ); 873250003Sadrian 874250003Sadrian /* Write the HT20 power per rate set */ 875250003Sadrian /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */ 876250003Sadrian OS_REG_WRITE(ah, 0xa3d0, 877250003Sadrian POW_SM(p_pwr_array[ALL_TARGET_HT20_5], 24) 878250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT20_4], 16) 879250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT20_1_3_9_11_17_19], 8) 880250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT20_0_8_16], 0) 881250003Sadrian ); 882250003Sadrian 883250003Sadrian /* 6 (LSB), 7, 12, 13 (MSB) */ 884250003Sadrian OS_REG_WRITE(ah, 0xa3d4, 885250003Sadrian POW_SM(p_pwr_array[ALL_TARGET_HT20_13], 24) 886250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT20_12], 16) 887250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT20_7], 8) 888250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT20_6], 0) 889250003Sadrian ); 890250003Sadrian 891250003Sadrian /* 14 (LSB), 15, 20, 21 */ 892250003Sadrian OS_REG_WRITE(ah, 0xa3e4, 893250003Sadrian POW_SM(p_pwr_array[ALL_TARGET_HT20_21], 24) 894250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT20_20], 16) 895250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT20_15], 8) 896250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT20_14], 0) 897250003Sadrian ); 898250003Sadrian 899250003Sadrian /* Mixed HT20 and HT40 rates */ 900250003Sadrian /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */ 901250003Sadrian OS_REG_WRITE(ah, 0xa3e8, 902250003Sadrian POW_SM(p_pwr_array[ALL_TARGET_HT40_23], 24) 903250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT40_22], 16) 904250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT20_23], 8) 905250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT20_22], 0) 906250003Sadrian ); 907250003Sadrian 908250003Sadrian /* Write the HT40 power per rate set */ 909250003Sadrian /* correct PAR difference between HT40 and HT20/LEGACY */ 910250003Sadrian /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */ 911250003Sadrian OS_REG_WRITE(ah, 0xa3d8, 912250003Sadrian POW_SM(p_pwr_array[ALL_TARGET_HT40_5], 24) 913250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT40_4], 16) 914250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT40_1_3_9_11_17_19], 8) 915250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT40_0_8_16], 0) 916250003Sadrian ); 917250003Sadrian 918250003Sadrian /* 6 (LSB), 7, 12, 13 (MSB) */ 919250003Sadrian OS_REG_WRITE(ah, 0xa3dc, 920250003Sadrian POW_SM(p_pwr_array[ALL_TARGET_HT40_13], 24) 921250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT40_12], 16) 922250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT40_7], 8) 923250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT40_6], 0) 924250003Sadrian ); 925250003Sadrian 926250003Sadrian /* 14 (LSB), 15, 20, 21 */ 927250003Sadrian OS_REG_WRITE(ah, 0xa3ec, 928250003Sadrian POW_SM(p_pwr_array[ALL_TARGET_HT40_21], 24) 929250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT40_20], 16) 930250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT40_15], 8) 931250003Sadrian | POW_SM(p_pwr_array[ALL_TARGET_HT40_14], 0) 932250003Sadrian ); 933250003Sadrian 934250003Sadrian return 0; 935250003Sadrian#undef POW_SM 936250003Sadrian} 937250003Sadrian 938250003Sadrianstatic void 939250008Sadrianar9300_selfgen_tpc_reg_write(struct ath_hal *ah, const struct ieee80211_channel *chan, 940250003Sadrian u_int8_t *p_pwr_array) 941250003Sadrian{ 942250003Sadrian u_int32_t tpc_reg_val; 943250003Sadrian 944250003Sadrian /* Set the target power values for self generated frames (ACK,RTS/CTS) to 945250003Sadrian * be within limits. This is just a safety measure.With per packet TPC mode 946250003Sadrian * enabled the target power value used with self generated frames will be 947250003Sadrian * MIN( TPC reg, BB_powertx_rate register) 948250003Sadrian */ 949250003Sadrian 950250008Sadrian if (IEEE80211_IS_CHAN_2GHZ(chan)) { 951250003Sadrian tpc_reg_val = (SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], AR_TPC_ACK) | 952250003Sadrian SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], AR_TPC_CTS) | 953250003Sadrian SM(0x3f, AR_TPC_CHIRP) | 954250003Sadrian SM(0x3f, AR_TPC_RPT)); 955250003Sadrian } else { 956250003Sadrian tpc_reg_val = (SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], AR_TPC_ACK) | 957250003Sadrian SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], AR_TPC_CTS) | 958250003Sadrian SM(0x3f, AR_TPC_CHIRP) | 959250003Sadrian SM(0x3f, AR_TPC_RPT)); 960250003Sadrian } 961250003Sadrian OS_REG_WRITE(ah, AR_TPC, tpc_reg_val); 962250003Sadrian} 963250003Sadrian 964250003Sadrianvoid 965250003Sadrianar9300_set_target_power_from_eeprom(struct ath_hal *ah, u_int16_t freq, 966250003Sadrian u_int8_t *target_power_val_t2) 967250003Sadrian{ 968250003Sadrian /* hard code for now, need to get from eeprom struct */ 969250003Sadrian u_int8_t ht40_power_inc_for_pdadc = 0; 970250003Sadrian HAL_BOOL is_2ghz = 0; 971250003Sadrian 972250003Sadrian if (freq < 4000) { 973250003Sadrian is_2ghz = 1; 974250003Sadrian } 975250003Sadrian 976250003Sadrian target_power_val_t2[ALL_TARGET_LEGACY_6_24] = 977250003Sadrian ar9300_eeprom_get_legacy_trgt_pwr( 978250003Sadrian ah, LEGACY_TARGET_RATE_6_24, freq, is_2ghz); 979250003Sadrian target_power_val_t2[ALL_TARGET_LEGACY_36] = 980250003Sadrian ar9300_eeprom_get_legacy_trgt_pwr( 981250003Sadrian ah, LEGACY_TARGET_RATE_36, freq, is_2ghz); 982250003Sadrian target_power_val_t2[ALL_TARGET_LEGACY_48] = 983250003Sadrian ar9300_eeprom_get_legacy_trgt_pwr( 984250003Sadrian ah, LEGACY_TARGET_RATE_48, freq, is_2ghz); 985250003Sadrian target_power_val_t2[ALL_TARGET_LEGACY_54] = 986250003Sadrian ar9300_eeprom_get_legacy_trgt_pwr( 987250003Sadrian ah, LEGACY_TARGET_RATE_54, freq, is_2ghz); 988250003Sadrian target_power_val_t2[ALL_TARGET_LEGACY_1L_5L] = 989250003Sadrian ar9300_eeprom_get_cck_trgt_pwr( 990250003Sadrian ah, LEGACY_TARGET_RATE_1L_5L, freq); 991250003Sadrian target_power_val_t2[ALL_TARGET_LEGACY_5S] = 992250003Sadrian ar9300_eeprom_get_cck_trgt_pwr( 993250003Sadrian ah, LEGACY_TARGET_RATE_5S, freq); 994250003Sadrian target_power_val_t2[ALL_TARGET_LEGACY_11L] = 995250003Sadrian ar9300_eeprom_get_cck_trgt_pwr( 996250003Sadrian ah, LEGACY_TARGET_RATE_11L, freq); 997250003Sadrian target_power_val_t2[ALL_TARGET_LEGACY_11S] = 998250003Sadrian ar9300_eeprom_get_cck_trgt_pwr( 999250003Sadrian ah, LEGACY_TARGET_RATE_11S, freq); 1000250003Sadrian target_power_val_t2[ALL_TARGET_HT20_0_8_16] = 1001250003Sadrian ar9300_eeprom_get_ht20_trgt_pwr( 1002250003Sadrian ah, HT_TARGET_RATE_0_8_16, freq, is_2ghz); 1003250003Sadrian target_power_val_t2[ALL_TARGET_HT20_1_3_9_11_17_19] = 1004250003Sadrian ar9300_eeprom_get_ht20_trgt_pwr( 1005250003Sadrian ah, HT_TARGET_RATE_1_3_9_11_17_19, freq, is_2ghz); 1006250003Sadrian target_power_val_t2[ALL_TARGET_HT20_4] = 1007250003Sadrian ar9300_eeprom_get_ht20_trgt_pwr( 1008250003Sadrian ah, HT_TARGET_RATE_4, freq, is_2ghz); 1009250003Sadrian target_power_val_t2[ALL_TARGET_HT20_5] = 1010250003Sadrian ar9300_eeprom_get_ht20_trgt_pwr( 1011250003Sadrian ah, HT_TARGET_RATE_5, freq, is_2ghz); 1012250003Sadrian target_power_val_t2[ALL_TARGET_HT20_6] = 1013250003Sadrian ar9300_eeprom_get_ht20_trgt_pwr( 1014250003Sadrian ah, HT_TARGET_RATE_6, freq, is_2ghz); 1015250003Sadrian target_power_val_t2[ALL_TARGET_HT20_7] = 1016250003Sadrian ar9300_eeprom_get_ht20_trgt_pwr( 1017250003Sadrian ah, HT_TARGET_RATE_7, freq, is_2ghz); 1018250003Sadrian target_power_val_t2[ALL_TARGET_HT20_12] = 1019250003Sadrian ar9300_eeprom_get_ht20_trgt_pwr( 1020250003Sadrian ah, HT_TARGET_RATE_12, freq, is_2ghz); 1021250003Sadrian target_power_val_t2[ALL_TARGET_HT20_13] = 1022250003Sadrian ar9300_eeprom_get_ht20_trgt_pwr( 1023250003Sadrian ah, HT_TARGET_RATE_13, freq, is_2ghz); 1024250003Sadrian target_power_val_t2[ALL_TARGET_HT20_14] = 1025250003Sadrian ar9300_eeprom_get_ht20_trgt_pwr( 1026250003Sadrian ah, HT_TARGET_RATE_14, freq, is_2ghz); 1027250003Sadrian target_power_val_t2[ALL_TARGET_HT20_15] = 1028250003Sadrian ar9300_eeprom_get_ht20_trgt_pwr( 1029250003Sadrian ah, HT_TARGET_RATE_15, freq, is_2ghz); 1030250003Sadrian target_power_val_t2[ALL_TARGET_HT20_20] = 1031250003Sadrian ar9300_eeprom_get_ht20_trgt_pwr( 1032250003Sadrian ah, HT_TARGET_RATE_20, freq, is_2ghz); 1033250003Sadrian target_power_val_t2[ALL_TARGET_HT20_21] = 1034250003Sadrian ar9300_eeprom_get_ht20_trgt_pwr( 1035250003Sadrian ah, HT_TARGET_RATE_21, freq, is_2ghz); 1036250003Sadrian target_power_val_t2[ALL_TARGET_HT20_22] = 1037250003Sadrian ar9300_eeprom_get_ht20_trgt_pwr( 1038250003Sadrian ah, HT_TARGET_RATE_22, freq, is_2ghz); 1039250003Sadrian target_power_val_t2[ALL_TARGET_HT20_23] = 1040250003Sadrian ar9300_eeprom_get_ht20_trgt_pwr( 1041250003Sadrian ah, HT_TARGET_RATE_23, freq, is_2ghz); 1042250003Sadrian target_power_val_t2[ALL_TARGET_HT40_0_8_16] = 1043250003Sadrian ar9300_eeprom_get_ht40_trgt_pwr( 1044250003Sadrian ah, HT_TARGET_RATE_0_8_16, freq, is_2ghz) + 1045250003Sadrian ht40_power_inc_for_pdadc; 1046250003Sadrian target_power_val_t2[ALL_TARGET_HT40_1_3_9_11_17_19] = 1047250003Sadrian ar9300_eeprom_get_ht40_trgt_pwr( 1048250003Sadrian ah, HT_TARGET_RATE_1_3_9_11_17_19, freq, is_2ghz) + 1049250003Sadrian ht40_power_inc_for_pdadc; 1050250003Sadrian target_power_val_t2[ALL_TARGET_HT40_4] = 1051250003Sadrian ar9300_eeprom_get_ht40_trgt_pwr( 1052250003Sadrian ah, HT_TARGET_RATE_4, freq, is_2ghz) + ht40_power_inc_for_pdadc; 1053250003Sadrian target_power_val_t2[ALL_TARGET_HT40_5] = 1054250003Sadrian ar9300_eeprom_get_ht40_trgt_pwr( 1055250003Sadrian ah, HT_TARGET_RATE_5, freq, is_2ghz) + ht40_power_inc_for_pdadc; 1056250003Sadrian target_power_val_t2[ALL_TARGET_HT40_6] = 1057250003Sadrian ar9300_eeprom_get_ht40_trgt_pwr( 1058250003Sadrian ah, HT_TARGET_RATE_6, freq, is_2ghz) + ht40_power_inc_for_pdadc; 1059250003Sadrian target_power_val_t2[ALL_TARGET_HT40_7] = 1060250003Sadrian ar9300_eeprom_get_ht40_trgt_pwr( 1061250003Sadrian ah, HT_TARGET_RATE_7, freq, is_2ghz) + ht40_power_inc_for_pdadc; 1062250003Sadrian target_power_val_t2[ALL_TARGET_HT40_12] = 1063250003Sadrian ar9300_eeprom_get_ht40_trgt_pwr( 1064250003Sadrian ah, HT_TARGET_RATE_12, freq, is_2ghz) + ht40_power_inc_for_pdadc; 1065250003Sadrian target_power_val_t2[ALL_TARGET_HT40_13] = 1066250003Sadrian ar9300_eeprom_get_ht40_trgt_pwr( 1067250003Sadrian ah, HT_TARGET_RATE_13, freq, is_2ghz) + ht40_power_inc_for_pdadc; 1068250003Sadrian target_power_val_t2[ALL_TARGET_HT40_14] = 1069250003Sadrian ar9300_eeprom_get_ht40_trgt_pwr( 1070250003Sadrian ah, HT_TARGET_RATE_14, freq, is_2ghz) + ht40_power_inc_for_pdadc; 1071250003Sadrian target_power_val_t2[ALL_TARGET_HT40_15] = 1072250003Sadrian ar9300_eeprom_get_ht40_trgt_pwr( 1073250003Sadrian ah, HT_TARGET_RATE_15, freq, is_2ghz) + ht40_power_inc_for_pdadc; 1074250003Sadrian target_power_val_t2[ALL_TARGET_HT40_20] = 1075250003Sadrian ar9300_eeprom_get_ht40_trgt_pwr( 1076250003Sadrian ah, HT_TARGET_RATE_20, freq, is_2ghz) + ht40_power_inc_for_pdadc; 1077250003Sadrian target_power_val_t2[ALL_TARGET_HT40_21] = 1078250003Sadrian ar9300_eeprom_get_ht40_trgt_pwr( 1079250003Sadrian ah, HT_TARGET_RATE_21, freq, is_2ghz) + ht40_power_inc_for_pdadc; 1080250003Sadrian target_power_val_t2[ALL_TARGET_HT40_22] = 1081250003Sadrian ar9300_eeprom_get_ht40_trgt_pwr( 1082250003Sadrian ah, HT_TARGET_RATE_22, freq, is_2ghz) + ht40_power_inc_for_pdadc; 1083250003Sadrian target_power_val_t2[ALL_TARGET_HT40_23] = 1084250003Sadrian ar9300_eeprom_get_ht40_trgt_pwr( 1085250003Sadrian ah, HT_TARGET_RATE_23, freq, is_2ghz) + ht40_power_inc_for_pdadc; 1086250003Sadrian 1087250003Sadrian#ifdef AH_DEBUG 1088250003Sadrian { 1089250003Sadrian int i = 0; 1090250003Sadrian 1091250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: APPLYING TARGET POWERS\n", __func__); 1092250003Sadrian while (i < ar9300_rate_size) { 1093250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: TPC[%02d] 0x%08x ", 1094250003Sadrian __func__, i, target_power_val_t2[i]); 1095250003Sadrian i++; 1096250003Sadrian if (i == ar9300_rate_size) { 1097250003Sadrian break; 1098250003Sadrian } 1099250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: TPC[%02d] 0x%08x ", 1100250003Sadrian __func__, i, target_power_val_t2[i]); 1101250003Sadrian i++; 1102250003Sadrian if (i == ar9300_rate_size) { 1103250003Sadrian break; 1104250003Sadrian } 1105250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: TPC[%02d] 0x%08x ", 1106250003Sadrian __func__, i, target_power_val_t2[i]); 1107250003Sadrian i++; 1108250003Sadrian if (i == ar9300_rate_size) { 1109250003Sadrian break; 1110250003Sadrian } 1111250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: TPC[%02d] 0x%08x \n", 1112250003Sadrian __func__, i, target_power_val_t2[i]); 1113250003Sadrian i++; 1114250003Sadrian } 1115250003Sadrian } 1116250003Sadrian#endif 1117250003Sadrian} 1118250003Sadrian 1119250003Sadrianu_int16_t *ar9300_regulatory_domain_get(struct ath_hal *ah) 1120250003Sadrian{ 1121250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 1122250003Sadrian return eep->base_eep_header.reg_dmn; 1123250003Sadrian} 1124250003Sadrian 1125250003Sadrian 1126250003Sadrianint32_t 1127250003Sadrianar9300_eeprom_write_enable_gpio_get(struct ath_hal *ah) 1128250003Sadrian{ 1129250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 1130250003Sadrian return eep->base_eep_header.eeprom_write_enable_gpio; 1131250003Sadrian} 1132250003Sadrian 1133250003Sadrianint32_t 1134250003Sadrianar9300_wlan_disable_gpio_get(struct ath_hal *ah) 1135250003Sadrian{ 1136250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 1137250003Sadrian return eep->base_eep_header.wlan_disable_gpio; 1138250003Sadrian} 1139250003Sadrian 1140250003Sadrianint32_t 1141250003Sadrianar9300_wlan_led_gpio_get(struct ath_hal *ah) 1142250003Sadrian{ 1143250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 1144250003Sadrian return eep->base_eep_header.wlan_led_gpio; 1145250003Sadrian} 1146250003Sadrian 1147250003Sadrianint32_t 1148250003Sadrianar9300_rx_band_select_gpio_get(struct ath_hal *ah) 1149250003Sadrian{ 1150250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 1151250003Sadrian return eep->base_eep_header.rx_band_select_gpio; 1152250003Sadrian} 1153250003Sadrian 1154250003Sadrian/* 1155250003Sadrian * since valid noise floor values are negative, returns 1 on error 1156250003Sadrian */ 1157250003Sadrianint32_t 1158250003Sadrianar9300_noise_floor_cal_or_power_get(struct ath_hal *ah, int32_t frequency, 1159250003Sadrian int32_t ichain, HAL_BOOL use_cal) 1160250003Sadrian{ 1161250003Sadrian int nf_use = 1; /* start with an error return value */ 1162250003Sadrian int32_t fx[OSPREY_NUM_5G_CAL_PIERS + OSPREY_NUM_2G_CAL_PIERS]; 1163250003Sadrian int32_t nf[OSPREY_NUM_5G_CAL_PIERS + OSPREY_NUM_2G_CAL_PIERS]; 1164250003Sadrian int nnf; 1165250003Sadrian int is_2ghz; 1166250003Sadrian int ipier, npier; 1167250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 1168250003Sadrian u_int8_t *p_cal_pier; 1169250003Sadrian OSP_CAL_DATA_PER_FREQ_OP_LOOP *p_cal_pier_struct; 1170250003Sadrian 1171250003Sadrian /* 1172250003Sadrian * check chain value 1173250003Sadrian */ 1174250003Sadrian if (ichain < 0 || ichain >= OSPREY_MAX_CHAINS) { 1175250003Sadrian return 1; 1176250003Sadrian } 1177250003Sadrian 1178250003Sadrian /* figure out which band we're using */ 1179250003Sadrian is_2ghz = (frequency < 4000); 1180250003Sadrian if (is_2ghz) { 1181250003Sadrian npier = OSPREY_NUM_2G_CAL_PIERS; 1182250003Sadrian p_cal_pier = eep->cal_freq_pier_2g; 1183250003Sadrian p_cal_pier_struct = eep->cal_pier_data_2g[ichain]; 1184250003Sadrian } else { 1185250003Sadrian npier = OSPREY_NUM_5G_CAL_PIERS; 1186250003Sadrian p_cal_pier = eep->cal_freq_pier_5g; 1187250003Sadrian p_cal_pier_struct = eep->cal_pier_data_5g[ichain]; 1188250003Sadrian } 1189250003Sadrian /* look for valid noise floor values */ 1190250003Sadrian nnf = 0; 1191250003Sadrian for (ipier = 0; ipier < npier; ipier++) { 1192250003Sadrian fx[nnf] = FBIN2FREQ(p_cal_pier[ipier], is_2ghz); 1193250003Sadrian nf[nnf] = use_cal ? 1194250003Sadrian p_cal_pier_struct[ipier].rx_noisefloor_cal : 1195250003Sadrian p_cal_pier_struct[ipier].rx_noisefloor_power; 1196250003Sadrian if (nf[nnf] < 0) { 1197250003Sadrian nnf++; 1198250003Sadrian } 1199250003Sadrian } 1200250003Sadrian /* 1201250003Sadrian * If we have some valid values, interpolate to find the value 1202250003Sadrian * at the desired frequency. 1203250003Sadrian */ 1204250003Sadrian if (nnf > 0) { 1205250003Sadrian nf_use = interpolate(frequency, fx, nf, nnf); 1206250003Sadrian } 1207250003Sadrian 1208250003Sadrian return nf_use; 1209250003Sadrian} 1210250003Sadrian 1211278741Sadrian/* 1212278741Sadrian * Return the Rx NF offset for specific channel. 1213278741Sadrian * The values saved in EEPROM/OTP/Flash is converted through the following way: 1214278741Sadrian * ((_p) - NOISE_PWR_DATA_OFFSET) << 2 1215278741Sadrian * So we need to convert back to the original values. 1216278741Sadrian */ 1217278741Sadrianint ar9300_get_rx_nf_offset(struct ath_hal *ah, struct ieee80211_channel *chan, int8_t *nf_pwr, int8_t *nf_cal) { 1218278741Sadrian HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); 1219278741Sadrian int8_t rx_nf_pwr, rx_nf_cal; 1220278741Sadrian int i; 1221278741Sadrian //HALASSERT(ichan); 1222278741Sadrian 1223278741Sadrian /* Fill 0 if valid internal channel is not found */ 1224278741Sadrian if (ichan == AH_NULL) { 1225278741Sadrian OS_MEMZERO(nf_pwr, sizeof(nf_pwr[0])*OSPREY_MAX_CHAINS); 1226278741Sadrian OS_MEMZERO(nf_cal, sizeof(nf_cal[0])*OSPREY_MAX_CHAINS); 1227278741Sadrian return -1; 1228278741Sadrian } 1229278741Sadrian 1230278741Sadrian for (i = 0; i < OSPREY_MAX_CHAINS; i++) { 1231278741Sadrian if ((rx_nf_pwr = ar9300_noise_floor_cal_or_power_get(ah, ichan->channel, i, 0)) == 1) { 1232278741Sadrian nf_pwr[i] = 0; 1233278741Sadrian } else { 1234278741Sadrian //printk("%s: raw nf_pwr[%d] = %d\n", __func__, i, rx_nf_pwr); 1235278741Sadrian nf_pwr[i] = NOISE_PWR_DBM_2_INT(rx_nf_pwr); 1236278741Sadrian } 1237278741Sadrian 1238278741Sadrian if ((rx_nf_cal = ar9300_noise_floor_cal_or_power_get(ah, ichan->channel, i, 1)) == 1) { 1239278741Sadrian nf_cal[i] = 0; 1240278741Sadrian } else { 1241278741Sadrian //printk("%s: raw nf_cal[%d] = %d\n", __func__, i, rx_nf_cal); 1242278741Sadrian nf_cal[i] = NOISE_PWR_DBM_2_INT(rx_nf_cal); 1243278741Sadrian } 1244278741Sadrian } 1245278741Sadrian 1246278741Sadrian return 0; 1247278741Sadrian} 1248278741Sadrian 1249250003Sadrianint32_t ar9300_rx_gain_index_get(struct ath_hal *ah) 1250250003Sadrian{ 1251250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 1252250003Sadrian 1253250003Sadrian return (eep->base_eep_header.txrxgain) & 0xf; /* bits 3:0 */ 1254250003Sadrian} 1255250003Sadrian 1256250003Sadrian 1257250003Sadrianint32_t ar9300_tx_gain_index_get(struct ath_hal *ah) 1258250003Sadrian{ 1259250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 1260250003Sadrian 1261250003Sadrian return (eep->base_eep_header.txrxgain >> 4) & 0xf; /* bits 7:4 */ 1262250003Sadrian} 1263250003Sadrian 1264250003SadrianHAL_BOOL ar9300_internal_regulator_apply(struct ath_hal *ah) 1265250003Sadrian{ 1266250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 1267250003Sadrian int internal_regulator = ar9300_eeprom_get(ahp, EEP_INTERNAL_REGULATOR); 1268250003Sadrian int reg_pmu1, reg_pmu2, reg_pmu1_set, reg_pmu2_set; 1269250003Sadrian u_int32_t reg_PMU1, reg_PMU2; 1270250003Sadrian unsigned long eep_addr; 1271250003Sadrian u_int32_t reg_val, reg_usb = 0, reg_pmu = 0; 1272250003Sadrian int usb_valid = 0, pmu_valid = 0; 1273250003Sadrian unsigned char pmu_refv; 1274250003Sadrian 1275250003Sadrian if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { 1276250003Sadrian reg_PMU1 = AR_PHY_PMU1_JUPITER; 1277250003Sadrian reg_PMU2 = AR_PHY_PMU2_JUPITER; 1278250003Sadrian } 1279250003Sadrian else { 1280250003Sadrian reg_PMU1 = AR_PHY_PMU1; 1281250003Sadrian reg_PMU2 = AR_PHY_PMU2; 1282250003Sadrian } 1283250003Sadrian 1284250003Sadrian if (internal_regulator) { 1285250003Sadrian if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah)) { 1286250003Sadrian if (AR_SREV_HORNET(ah)) { 1287250003Sadrian /* Read OTP first */ 1288250003Sadrian for (eep_addr = 0x14; ; eep_addr -= 0x10) { 1289250003Sadrian 1290250003Sadrian ar9300_otp_read(ah, eep_addr / 4, ®_val, 1); 1291250003Sadrian 1292250003Sadrian if ((reg_val & 0x80) == 0x80){ 1293250003Sadrian usb_valid = 1; 1294250003Sadrian reg_usb = reg_val & 0x000000ff; 1295250003Sadrian } 1296250003Sadrian 1297250003Sadrian if ((reg_val & 0x80000000) == 0x80000000){ 1298250003Sadrian pmu_valid = 1; 1299250003Sadrian reg_pmu = (reg_val & 0xff000000) >> 24; 1300250003Sadrian } 1301250003Sadrian 1302250003Sadrian if (eep_addr == 0x4) { 1303250003Sadrian break; 1304250003Sadrian } 1305250003Sadrian } 1306250003Sadrian 1307250003Sadrian if (pmu_valid) { 1308250003Sadrian pmu_refv = reg_pmu & 0xf; 1309250003Sadrian } else { 1310250003Sadrian pmu_refv = 0x8; 1311250003Sadrian } 1312250003Sadrian 1313250003Sadrian /* 1314250003Sadrian * If (valid) { 1315250003Sadrian * Usb_phy_ctrl2_tx_cal_en -> 0 1316250003Sadrian * Usb_phy_ctrl2_tx_cal_sel -> 0 1317250003Sadrian * Usb_phy_ctrl2_tx_man_cal -> 0, 1, 3, 7 or 15 from OTP 1318250003Sadrian * } 1319250003Sadrian */ 1320250003Sadrian if (usb_valid) { 1321250003Sadrian OS_REG_RMW_FIELD(ah, 0x16c88, AR_PHY_CTRL2_TX_CAL_EN, 0x0); 1322250003Sadrian OS_REG_RMW_FIELD(ah, 0x16c88, AR_PHY_CTRL2_TX_CAL_SEL, 0x0); 1323250003Sadrian OS_REG_RMW_FIELD(ah, 0x16c88, 1324250003Sadrian AR_PHY_CTRL2_TX_MAN_CAL, (reg_usb & 0xf)); 1325250003Sadrian } 1326250003Sadrian 1327250003Sadrian } else { 1328250003Sadrian pmu_refv = 0x8; 1329250003Sadrian } 1330250003Sadrian /*#ifndef USE_HIF*/ 1331250003Sadrian /* Follow the MDK settings for Hornet PMU. 1332250003Sadrian * my $pwd = 0x0; 1333250003Sadrian * my $Nfdiv = 0x3; # xtal_freq = 25MHz 1334250003Sadrian * my $Nfdiv = 0x4; # xtal_freq = 40MHz 1335250003Sadrian * my $Refv = 0x7; # 0x5:1.22V; 0x8:1.29V 1336250003Sadrian * my $Gm1 = 0x3; #Poseidon $Gm1=1 1337250003Sadrian * my $classb = 0x0; 1338250003Sadrian * my $Cc = 0x1; #Poseidon $Cc=7 1339250003Sadrian * my $Rc = 0x6; 1340250003Sadrian * my $ramp_slope = 0x1; 1341250003Sadrian * my $Segm = 0x3; 1342250003Sadrian * my $use_local_osc = 0x0; 1343250003Sadrian * my $force_xosc_stable = 0x0; 1344250003Sadrian * my $Selfb = 0x0; #Poseidon $Selfb=1 1345250003Sadrian * my $Filterfb = 0x3; #Poseidon $Filterfb=0 1346250003Sadrian * my $Filtervc = 0x0; 1347250003Sadrian * my $disc = 0x0; 1348250003Sadrian * my $discdel = 0x4; 1349250003Sadrian * my $spare = 0x0; 1350250003Sadrian * $reg_PMU1 = 1351250003Sadrian * $pwd | ($Nfdiv<<1) | ($Refv<<4) | ($Gm1<<8) | 1352250003Sadrian * ($classb<<11) | ($Cc<<14) | ($Rc<<17) | ($ramp_slope<<20) | 1353250003Sadrian * ($Segm<<24) | ($use_local_osc<<26) | 1354250003Sadrian * ($force_xosc_stable<<27) | ($Selfb<<28) | ($Filterfb<<29); 1355250003Sadrian * $reg_PMU2 = $handle->reg_rd("ch0_PMU2"); 1356250003Sadrian * $reg_PMU2 = ($reg_PMU2 & 0xfe3fffff) | ($Filtervc<<22); 1357250003Sadrian * $reg_PMU2 = ($reg_PMU2 & 0xe3ffffff) | ($discdel<<26); 1358250003Sadrian * $reg_PMU2 = ($reg_PMU2 & 0x1fffffff) | ($spare<<29); 1359250003Sadrian */ 1360250003Sadrian if (ahp->clk_25mhz) { 1361250003Sadrian reg_pmu1_set = 0 | 1362250003Sadrian (3 << 1) | (pmu_refv << 4) | (3 << 8) | (0 << 11) | 1363250003Sadrian (1 << 14) | (6 << 17) | (1 << 20) | (3 << 24) | 1364250003Sadrian (0 << 26) | (0 << 27) | (0 << 28) | (0 << 29); 1365250003Sadrian } else { 1366250003Sadrian if (AR_SREV_POSEIDON(ah)) { 1367250003Sadrian reg_pmu1_set = 0 | 1368250003Sadrian (5 << 1) | (7 << 4) | (2 << 8) | (0 << 11) | 1369250003Sadrian (2 << 14) | (6 << 17) | (1 << 20) | (3 << 24) | 1370250003Sadrian (0 << 26) | (0 << 27) | (1 << 28) | (0 << 29) ; 1371250003Sadrian } else { 1372250003Sadrian reg_pmu1_set = 0 | 1373250003Sadrian (4 << 1) | (7 << 4) | (3 << 8) | (0 << 11) | 1374250003Sadrian (1 << 14) | (6 << 17) | (1 << 20) | (3 << 24) | 1375250003Sadrian (0 << 26) | (0 << 27) | (0 << 28) | (0 << 29) ; 1376250003Sadrian } 1377250003Sadrian } 1378250003Sadrian OS_REG_RMW_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM, 0x0); 1379250003Sadrian 1380250003Sadrian OS_REG_WRITE(ah, reg_PMU1, reg_pmu1_set); /* 0x638c8376 */ 1381250003Sadrian reg_pmu1 = OS_REG_READ(ah, reg_PMU1); 1382250003Sadrian while (reg_pmu1 != reg_pmu1_set) { 1383250003Sadrian OS_REG_WRITE(ah, reg_PMU1, reg_pmu1_set); /* 0x638c8376 */ 1384250003Sadrian OS_DELAY(10); 1385250003Sadrian reg_pmu1 = OS_REG_READ(ah, reg_PMU1); 1386250003Sadrian } 1387250003Sadrian 1388250003Sadrian reg_pmu2_set = 1389250003Sadrian (OS_REG_READ(ah, reg_PMU2) & (~0xFFC00000)) | (4 << 26); 1390250003Sadrian OS_REG_WRITE(ah, reg_PMU2, reg_pmu2_set); 1391250003Sadrian reg_pmu2 = OS_REG_READ(ah, reg_PMU2); 1392250003Sadrian while (reg_pmu2 != reg_pmu2_set) { 1393250003Sadrian OS_REG_WRITE(ah, reg_PMU2, reg_pmu2_set); 1394250003Sadrian OS_DELAY(10); 1395250003Sadrian reg_pmu2 = OS_REG_READ(ah, reg_PMU2); 1396250003Sadrian } 1397250003Sadrian reg_pmu2_set = 1398250003Sadrian (OS_REG_READ(ah, reg_PMU2) & (~0x00200000)) | (1 << 21); 1399250003Sadrian OS_REG_WRITE(ah, reg_PMU2, reg_pmu2_set); 1400250003Sadrian reg_pmu2 = OS_REG_READ(ah, reg_PMU2); 1401250003Sadrian while (reg_pmu2 != reg_pmu2_set) { 1402250003Sadrian OS_REG_WRITE(ah, reg_PMU2, reg_pmu2_set); 1403250003Sadrian OS_DELAY(10); 1404250003Sadrian reg_pmu2 = OS_REG_READ(ah, reg_PMU2); 1405250003Sadrian } 1406250003Sadrian /*#endif*/ 1407250003Sadrian } else if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { 1408250003Sadrian /* Internal regulator is ON. Write swreg register. */ 1409250003Sadrian int swreg = ar9300_eeprom_get(ahp, EEP_SWREG); 1410250003Sadrian OS_REG_WRITE(ah, reg_PMU1, swreg); 1411250003Sadrian } else { 1412250003Sadrian /* Internal regulator is ON. Write swreg register. */ 1413250003Sadrian int swreg = ar9300_eeprom_get(ahp, EEP_SWREG); 1414250003Sadrian OS_REG_WRITE(ah, AR_RTC_REG_CONTROL1, 1415250003Sadrian OS_REG_READ(ah, AR_RTC_REG_CONTROL1) & 1416250003Sadrian (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM)); 1417250003Sadrian OS_REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg); 1418250003Sadrian /* Set REG_CONTROL1.SWREG_PROGRAM */ 1419250003Sadrian OS_REG_WRITE(ah, AR_RTC_REG_CONTROL1, 1420250003Sadrian OS_REG_READ(ah, AR_RTC_REG_CONTROL1) | 1421250003Sadrian AR_RTC_REG_CONTROL1_SWREG_PROGRAM); 1422250003Sadrian } 1423250003Sadrian } else { 1424250003Sadrian if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah)) { 1425250003Sadrian OS_REG_RMW_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM, 0x0); 1426250003Sadrian reg_pmu2 = OS_REG_READ_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM); 1427250003Sadrian while (reg_pmu2) { 1428250003Sadrian OS_DELAY(10); 1429250003Sadrian reg_pmu2 = OS_REG_READ_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM); 1430250003Sadrian } 1431250003Sadrian OS_REG_RMW_FIELD(ah, reg_PMU1, AR_PHY_PMU1_PWD, 0x1); 1432250003Sadrian reg_pmu1 = OS_REG_READ_FIELD(ah, reg_PMU1, AR_PHY_PMU1_PWD); 1433250003Sadrian while (!reg_pmu1) { 1434250003Sadrian OS_DELAY(10); 1435250003Sadrian reg_pmu1 = OS_REG_READ_FIELD(ah, reg_PMU1, AR_PHY_PMU1_PWD); 1436250003Sadrian } 1437250003Sadrian OS_REG_RMW_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM, 0x1); 1438250003Sadrian reg_pmu2 = OS_REG_READ_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM); 1439250003Sadrian while (!reg_pmu2) { 1440250003Sadrian OS_DELAY(10); 1441250003Sadrian reg_pmu2 = OS_REG_READ_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM); 1442250003Sadrian } 1443250003Sadrian } else if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { 1444250003Sadrian OS_REG_RMW_FIELD(ah, reg_PMU1, AR_PHY_PMU1_PWD, 0x1); 1445250003Sadrian } else { 1446250003Sadrian OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, 1447250003Sadrian (OS_REG_READ(ah, AR_RTC_SLEEP_CLK) | 1448250003Sadrian AR_RTC_FORCE_SWREG_PRD | AR_RTC_PCIE_RST_PWDN_EN)); 1449250003Sadrian } 1450250003Sadrian } 1451250003Sadrian 1452250003Sadrian return 0; 1453250003Sadrian} 1454250003Sadrian 1455250003SadrianHAL_BOOL ar9300_drive_strength_apply(struct ath_hal *ah) 1456250003Sadrian{ 1457250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 1458250003Sadrian int drive_strength; 1459250003Sadrian unsigned long reg; 1460250003Sadrian 1461250003Sadrian drive_strength = ar9300_eeprom_get(ahp, EEP_DRIVE_STRENGTH); 1462250003Sadrian if (drive_strength) { 1463250003Sadrian reg = OS_REG_READ(ah, AR_PHY_65NM_CH0_BIAS1); 1464250003Sadrian reg &= ~0x00ffffc0; 1465250003Sadrian reg |= 0x5 << 21; 1466250003Sadrian reg |= 0x5 << 18; 1467250003Sadrian reg |= 0x5 << 15; 1468250003Sadrian reg |= 0x5 << 12; 1469250003Sadrian reg |= 0x5 << 9; 1470250003Sadrian reg |= 0x5 << 6; 1471250003Sadrian OS_REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS1, reg); 1472250003Sadrian 1473250003Sadrian reg = OS_REG_READ(ah, AR_PHY_65NM_CH0_BIAS2); 1474250003Sadrian reg &= ~0xffffffe0; 1475250003Sadrian reg |= 0x5 << 29; 1476250003Sadrian reg |= 0x5 << 26; 1477250003Sadrian reg |= 0x5 << 23; 1478250003Sadrian reg |= 0x5 << 20; 1479250003Sadrian reg |= 0x5 << 17; 1480250003Sadrian reg |= 0x5 << 14; 1481250003Sadrian reg |= 0x5 << 11; 1482250003Sadrian reg |= 0x5 << 8; 1483250003Sadrian reg |= 0x5 << 5; 1484250003Sadrian OS_REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS2, reg); 1485250003Sadrian 1486250003Sadrian reg = OS_REG_READ(ah, AR_PHY_65NM_CH0_BIAS4); 1487250003Sadrian reg &= ~0xff800000; 1488250003Sadrian reg |= 0x5 << 29; 1489250003Sadrian reg |= 0x5 << 26; 1490250003Sadrian reg |= 0x5 << 23; 1491250003Sadrian OS_REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg); 1492250003Sadrian } 1493250003Sadrian return 0; 1494250003Sadrian} 1495250003Sadrian 1496250003Sadrianint32_t ar9300_xpa_bias_level_get(struct ath_hal *ah, HAL_BOOL is_2ghz) 1497250003Sadrian{ 1498250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 1499250003Sadrian if (is_2ghz) { 1500250003Sadrian return eep->modal_header_2g.xpa_bias_lvl; 1501250003Sadrian } else { 1502250003Sadrian return eep->modal_header_5g.xpa_bias_lvl; 1503250003Sadrian } 1504250003Sadrian} 1505250003Sadrian 1506250003SadrianHAL_BOOL ar9300_xpa_bias_level_apply(struct ath_hal *ah, HAL_BOOL is_2ghz) 1507250003Sadrian{ 1508250003Sadrian /* 1509250003Sadrian * In ar9330 emu, we can't access radio registers, 1510250003Sadrian * merlin is used for radio part. 1511250003Sadrian */ 1512250003Sadrian int bias; 1513250003Sadrian bias = ar9300_xpa_bias_level_get(ah, is_2ghz); 1514250003Sadrian 1515250003Sadrian if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_WASP(ah)) { 1516250003Sadrian OS_REG_RMW_FIELD(ah, 1517250003Sadrian AR_HORNET_CH0_TOP2, AR_HORNET_CH0_TOP2_XPABIASLVL, bias); 1518250003Sadrian } else if (AR_SREV_SCORPION(ah)) { 1519250003Sadrian OS_REG_RMW_FIELD(ah, 1520250003Sadrian AR_SCORPION_CH0_TOP, AR_SCORPION_CH0_TOP_XPABIASLVL, bias); 1521250003Sadrian } else if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { 1522250003Sadrian OS_REG_RMW_FIELD(ah, 1523250003Sadrian AR_PHY_65NM_CH0_TOP_JUPITER, AR_PHY_65NM_CH0_TOP_XPABIASLVL, bias); 1524250003Sadrian } else { 1525250003Sadrian OS_REG_RMW_FIELD(ah, 1526250003Sadrian AR_PHY_65NM_CH0_TOP, AR_PHY_65NM_CH0_TOP_XPABIASLVL, bias); 1527250003Sadrian OS_REG_RMW_FIELD(ah, 1528250003Sadrian AR_PHY_65NM_CH0_THERM, AR_PHY_65NM_CH0_THERM_XPABIASLVL_MSB, 1529250003Sadrian bias >> 2); 1530250003Sadrian OS_REG_RMW_FIELD(ah, 1531250003Sadrian AR_PHY_65NM_CH0_THERM, AR_PHY_65NM_CH0_THERM_XPASHORT2GND, 1); 1532250003Sadrian } 1533250003Sadrian return 0; 1534250003Sadrian} 1535250003Sadrian 1536250003Sadrianu_int32_t ar9300_ant_ctrl_common_get(struct ath_hal *ah, HAL_BOOL is_2ghz) 1537250003Sadrian{ 1538250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 1539250003Sadrian if (is_2ghz) { 1540250003Sadrian return eep->modal_header_2g.ant_ctrl_common; 1541250003Sadrian } else { 1542250003Sadrian return eep->modal_header_5g.ant_ctrl_common; 1543250003Sadrian } 1544250003Sadrian} 1545250003Sadrianstatic u_int16_t 1546250003Sadrianar9300_switch_com_spdt_get(struct ath_hal *ah, HAL_BOOL is_2ghz) 1547250003Sadrian{ 1548250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 1549250003Sadrian if (is_2ghz) { 1550250003Sadrian return eep->modal_header_2g.switchcomspdt; 1551250003Sadrian } else { 1552250003Sadrian return eep->modal_header_5g.switchcomspdt; 1553250003Sadrian } 1554250003Sadrian} 1555250003Sadrianu_int32_t ar9300_ant_ctrl_common2_get(struct ath_hal *ah, HAL_BOOL is_2ghz) 1556250003Sadrian{ 1557250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 1558250003Sadrian if (is_2ghz) { 1559250003Sadrian return eep->modal_header_2g.ant_ctrl_common2; 1560250003Sadrian } else { 1561250003Sadrian return eep->modal_header_5g.ant_ctrl_common2; 1562250003Sadrian } 1563250003Sadrian} 1564250003Sadrian 1565250003Sadrianu_int16_t ar9300_ant_ctrl_chain_get(struct ath_hal *ah, int chain, 1566250003Sadrian HAL_BOOL is_2ghz) 1567250003Sadrian{ 1568250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 1569250003Sadrian if (chain >= 0 && chain < OSPREY_MAX_CHAINS) { 1570250003Sadrian if (is_2ghz) { 1571250003Sadrian return eep->modal_header_2g.ant_ctrl_chain[chain]; 1572250003Sadrian } else { 1573250003Sadrian return eep->modal_header_5g.ant_ctrl_chain[chain]; 1574250003Sadrian } 1575250003Sadrian } 1576250003Sadrian return 0; 1577250003Sadrian} 1578250003Sadrian 1579278741Sadrian/* 1580278741Sadrian * Select the usage of antenna via the RF switch. 1581278741Sadrian * Default values are loaded from eeprom. 1582278741Sadrian */ 1583278741SadrianHAL_BOOL ar9300_ant_swcom_sel(struct ath_hal *ah, u_int8_t ops, 1584278741Sadrian u_int32_t *common_tbl1, u_int32_t *common_tbl2) 1585278741Sadrian{ 1586278741Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 1587278741Sadrian struct ath_hal_private *ap = AH_PRIVATE(ah); 1588278741Sadrian const struct ieee80211_channel *curchan = ap->ah_curchan; 1589278741Sadrian enum { 1590278741Sadrian ANT_SELECT_OPS_GET, 1591278741Sadrian ANT_SELECT_OPS_SET, 1592278741Sadrian }; 1593278741Sadrian 1594278741Sadrian if (AR_SREV_JUPITER(ah) || AR_SREV_SCORPION(ah)) 1595278741Sadrian return AH_FALSE; 1596278741Sadrian 1597278741Sadrian if (!curchan) 1598278741Sadrian return AH_FALSE; 1599278741Sadrian 1600278741Sadrian#define AR_SWITCH_TABLE_COM_ALL (0xffff) 1601278741Sadrian#define AR_SWITCH_TABLE_COM_ALL_S (0) 1602278741Sadrian#define AR_SWITCH_TABLE_COM2_ALL (0xffffff) 1603278741Sadrian#define AR_SWITCH_TABLE_COM2_ALL_S (0) 1604278741Sadrian switch (ops) { 1605278741Sadrian case ANT_SELECT_OPS_GET: 1606278741Sadrian *common_tbl1 = OS_REG_READ_FIELD(ah, AR_PHY_SWITCH_COM, 1607278741Sadrian AR_SWITCH_TABLE_COM_ALL); 1608278741Sadrian *common_tbl2 = OS_REG_READ_FIELD(ah, AR_PHY_SWITCH_COM_2, 1609278741Sadrian AR_SWITCH_TABLE_COM2_ALL); 1610278741Sadrian break; 1611278741Sadrian case ANT_SELECT_OPS_SET: 1612278741Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, 1613278741Sadrian AR_SWITCH_TABLE_COM_ALL, *common_tbl1); 1614278741Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, 1615278741Sadrian AR_SWITCH_TABLE_COM2_ALL, *common_tbl2); 1616278741Sadrian 1617278741Sadrian /* write back to eeprom */ 1618278741Sadrian if (IEEE80211_IS_CHAN_2GHZ(curchan)) { 1619278741Sadrian eep->modal_header_2g.ant_ctrl_common = *common_tbl1; 1620278741Sadrian eep->modal_header_2g.ant_ctrl_common2 = *common_tbl2; 1621278741Sadrian } else { 1622278741Sadrian eep->modal_header_5g.ant_ctrl_common = *common_tbl1; 1623278741Sadrian eep->modal_header_5g.ant_ctrl_common2 = *common_tbl2; 1624278741Sadrian } 1625278741Sadrian 1626278741Sadrian break; 1627278741Sadrian default: 1628278741Sadrian break; 1629278741Sadrian } 1630278741Sadrian 1631278741Sadrian return AH_TRUE; 1632278741Sadrian} 1633278741Sadrian 1634250003SadrianHAL_BOOL ar9300_ant_ctrl_apply(struct ath_hal *ah, HAL_BOOL is_2ghz) 1635250003Sadrian{ 1636250003Sadrian u_int32_t value; 1637250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 1638250003Sadrian u_int32_t regval; 1639250003Sadrian struct ath_hal_private *ahpriv = AH_PRIVATE(ah); 1640250003Sadrian#if ATH_ANT_DIV_COMB 1641250003Sadrian HAL_CAPABILITIES *pcap = &ahpriv->ah_caps; 1642250003Sadrian#endif /* ATH_ANT_DIV_COMB */ 1643250003Sadrian u_int32_t xlan_gpio_cfg; 1644250003Sadrian u_int8_t i; 1645250003Sadrian 1646250003Sadrian if (AR_SREV_POSEIDON(ah)) { 1647250008Sadrian xlan_gpio_cfg = ah->ah_config.ath_hal_ext_lna_ctl_gpio; 1648250003Sadrian if (xlan_gpio_cfg) { 1649250003Sadrian for (i = 0; i < 32; i++) { 1650250003Sadrian if (xlan_gpio_cfg & (1 << i)) { 1651250008Sadrian ath_hal_gpioCfgOutput(ah, i, 1652250008Sadrian HAL_GPIO_OUTPUT_MUX_PCIE_ATTENTION_LED); 1653250003Sadrian } 1654250003Sadrian } 1655250003Sadrian } 1656250003Sadrian } 1657250003Sadrian#define AR_SWITCH_TABLE_COM_ALL (0xffff) 1658250003Sadrian#define AR_SWITCH_TABLE_COM_ALL_S (0) 1659250003Sadrian#define AR_SWITCH_TABLE_COM_JUPITER_ALL (0xffffff) 1660250003Sadrian#define AR_SWITCH_TABLE_COM_JUPITER_ALL_S (0) 1661250003Sadrian#define AR_SWITCH_TABLE_COM_SCORPION_ALL (0xffffff) 1662250003Sadrian#define AR_SWITCH_TABLE_COM_SCORPION_ALL_S (0) 1663291437Sadrian#define AR_SWITCH_TABLE_COM_HONEYBEE_ALL (0xffffff) 1664291437Sadrian#define AR_SWITCH_TABLE_COM_HONEYBEE_ALL_S (0) 1665250003Sadrian#define AR_SWITCH_TABLE_COM_SPDT (0x00f00000) 1666250003Sadrian value = ar9300_ant_ctrl_common_get(ah, is_2ghz); 1667250003Sadrian if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { 1668250003Sadrian if (AR_SREV_JUPITER_10(ah)) { 1669250003Sadrian /* Force SPDT setting for Jupiter 1.0 chips. */ 1670250003Sadrian value &= ~AR_SWITCH_TABLE_COM_SPDT; 1671250003Sadrian value |= 0x00100000; 1672250003Sadrian } 1673250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, 1674250003Sadrian AR_SWITCH_TABLE_COM_JUPITER_ALL, value); 1675250003Sadrian } 1676250003Sadrian else if (AR_SREV_SCORPION(ah)) { 1677250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, 1678250003Sadrian AR_SWITCH_TABLE_COM_SCORPION_ALL, value); 1679250003Sadrian } 1680291437Sadrian else if (AR_SREV_HONEYBEE(ah)) { 1681291437Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, 1682291437Sadrian AR_SWITCH_TABLE_COM_HONEYBEE_ALL, value); 1683291437Sadrian } 1684250003Sadrian else { 1685250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, 1686250003Sadrian AR_SWITCH_TABLE_COM_ALL, value); 1687250003Sadrian } 1688250003Sadrian/* 1689250003Sadrian* Jupiter2.0 defines new switch table for BT/WLAN, 1690250003Sadrian* here's new field name in WB222.ref for both 2G and 5G. 1691250003Sadrian* Register: [GLB_CONTROL] GLB_CONTROL (@0x20044) 1692250003Sadrian* 15:12 R/W SWITCH_TABLE_COM_SPDT_WLAN_RX SWITCH_TABLE_COM_SPDT_WLAN_RX 1693250003Sadrian* 11:8 R/W SWITCH_TABLE_COM_SPDT_WLAN_TX SWITCH_TABLE_COM_SPDT_WLAN_TX 1694250003Sadrian* 7:4 R/W SWITCH_TABLE_COM_SPDT_WLAN_IDLE SWITCH_TABLE_COM_SPDT_WLAN_IDLE 1695250003Sadrian*/ 1696250003Sadrian#define AR_SWITCH_TABLE_COM_SPDT_ALL (0x0000fff0) 1697250003Sadrian#define AR_SWITCH_TABLE_COM_SPDT_ALL_S (4) 1698250003Sadrian if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) { 1699250003Sadrian value = ar9300_switch_com_spdt_get(ah, is_2ghz); 1700250003Sadrian OS_REG_RMW_FIELD(ah, AR_GLB_CONTROL, 1701250003Sadrian AR_SWITCH_TABLE_COM_SPDT_ALL, value); 1702250003Sadrian 1703250003Sadrian OS_REG_SET_BIT(ah, AR_GLB_CONTROL, 1704250003Sadrian AR_BTCOEX_CTRL_SPDT_ENABLE); 1705250003Sadrian //OS_REG_SET_BIT(ah, AR_GLB_CONTROL, 1706250003Sadrian // AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); 1707250003Sadrian } 1708250003Sadrian 1709250003Sadrian#define AR_SWITCH_TABLE_COM2_ALL (0xffffff) 1710250003Sadrian#define AR_SWITCH_TABLE_COM2_ALL_S (0) 1711250003Sadrian value = ar9300_ant_ctrl_common2_get(ah, is_2ghz); 1712250003Sadrian#if ATH_ANT_DIV_COMB 1713250003Sadrian if ( AR_SREV_POSEIDON(ah) && (ahp->ah_lna_div_use_bt_ant_enable == TRUE) ) { 1714250003Sadrian value &= ~AR_SWITCH_TABLE_COM2_ALL; 1715250008Sadrian value |= ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable; 1716272292Sadrian HALDEBUG(ah, HAL_DEBUG_RESET, "%s: com2=0x%08x\n", __func__, value) 1717250003Sadrian } 1718250003Sadrian#endif /* ATH_ANT_DIV_COMB */ 1719250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); 1720250003Sadrian 1721250003Sadrian#define AR_SWITCH_TABLE_ALL (0xfff) 1722250003Sadrian#define AR_SWITCH_TABLE_ALL_S (0) 1723250003Sadrian value = ar9300_ant_ctrl_chain_get(ah, 0, is_2ghz); 1724250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value); 1725250003Sadrian 1726250003Sadrian if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah) && !AR_SREV_APHRODITE(ah)) { 1727250003Sadrian value = ar9300_ant_ctrl_chain_get(ah, 1, is_2ghz); 1728250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value); 1729250003Sadrian 1730291437Sadrian if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah)) { 1731250003Sadrian value = ar9300_ant_ctrl_chain_get(ah, 2, is_2ghz); 1732250003Sadrian OS_REG_RMW_FIELD(ah, 1733250003Sadrian AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value); 1734250003Sadrian } 1735250003Sadrian } 1736250003Sadrian if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah)) { 1737250003Sadrian value = ar9300_eeprom_get(ahp, EEP_ANTDIV_control); 1738250003Sadrian /* main_lnaconf, alt_lnaconf, main_tb, alt_tb */ 1739250003Sadrian regval = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL); 1740250003Sadrian regval &= (~ANT_DIV_CONTROL_ALL); /* clear bit 25~30 */ 1741250003Sadrian regval |= (value & 0x3f) << ANT_DIV_CONTROL_ALL_S; 1742250003Sadrian /* enable_lnadiv */ 1743250003Sadrian regval &= (~MULTICHAIN_GAIN_CTRL__ENABLE_ANT_DIV_LNADIV__MASK); 1744250003Sadrian regval |= ((value >> 6) & 0x1) << 1745250003Sadrian MULTICHAIN_GAIN_CTRL__ENABLE_ANT_DIV_LNADIV__SHIFT; 1746250003Sadrian#if ATH_ANT_DIV_COMB 1747250003Sadrian if ( AR_SREV_POSEIDON(ah) && (ahp->ah_lna_div_use_bt_ant_enable == TRUE) ) { 1748250003Sadrian regval |= ANT_DIV_ENABLE; 1749250003Sadrian } 1750250003Sadrian#endif /* ATH_ANT_DIV_COMB */ 1751250003Sadrian OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); 1752250003Sadrian 1753250003Sadrian /* enable fast_div */ 1754250003Sadrian regval = OS_REG_READ(ah, AR_PHY_CCK_DETECT); 1755250003Sadrian regval &= (~BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__MASK); 1756250003Sadrian regval |= ((value >> 7) & 0x1) << 1757250003Sadrian BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__SHIFT; 1758250003Sadrian#if ATH_ANT_DIV_COMB 1759250003Sadrian if ( AR_SREV_POSEIDON(ah) && (ahp->ah_lna_div_use_bt_ant_enable == TRUE) ) { 1760250003Sadrian regval |= FAST_DIV_ENABLE; 1761250003Sadrian } 1762250003Sadrian#endif /* ATH_ANT_DIV_COMB */ 1763250003Sadrian OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); 1764250003Sadrian } 1765250003Sadrian 1766250003Sadrian#if ATH_ANT_DIV_COMB 1767250003Sadrian if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON_11_OR_LATER(ah)) { 1768250008Sadrian if (pcap->halAntDivCombSupport) { 1769250003Sadrian /* If support DivComb, set MAIN to LNA1, ALT to LNA2 at beginning */ 1770250003Sadrian regval = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL); 1771250003Sadrian /* clear bit 25~30 main_lnaconf, alt_lnaconf, main_tb, alt_tb */ 1772250003Sadrian regval &= (~(MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__MASK | 1773250003Sadrian MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__MASK | 1774250003Sadrian MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_GAINTB__MASK | 1775250003Sadrian MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_GAINTB__MASK)); 1776250003Sadrian regval |= (HAL_ANT_DIV_COMB_LNA1 << 1777250003Sadrian MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__SHIFT); 1778250003Sadrian regval |= (HAL_ANT_DIV_COMB_LNA2 << 1779250003Sadrian MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__SHIFT); 1780250003Sadrian OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); 1781250003Sadrian } 1782250003Sadrian 1783250003Sadrian } 1784250003Sadrian#endif /* ATH_ANT_DIV_COMB */ 1785250003Sadrian if (AR_SREV_POSEIDON(ah) && ( ahp->ah_diversity_control == HAL_ANT_FIXED_A 1786250003Sadrian || ahp->ah_diversity_control == HAL_ANT_FIXED_B)) 1787250003Sadrian { 1788250003Sadrian u_int32_t reg_val = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL); 1789250003Sadrian reg_val &= ~(MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__MASK | 1790250003Sadrian MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__MASK | 1791250003Sadrian MULTICHAIN_GAIN_CTRL__ANT_FAST_DIV_BIAS__MASK | 1792250003Sadrian MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_GAINTB__MASK | 1793250003Sadrian MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_GAINTB__MASK ); 1794250003Sadrian 1795250003Sadrian switch (ahp->ah_diversity_control) { 1796250003Sadrian case HAL_ANT_FIXED_A: 1797250003Sadrian /* Enable first antenna only */ 1798250003Sadrian reg_val |= (HAL_ANT_DIV_COMB_LNA1 << 1799250003Sadrian MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__SHIFT); 1800250003Sadrian reg_val |= (HAL_ANT_DIV_COMB_LNA2 << 1801250003Sadrian MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__SHIFT); 1802250003Sadrian /* main/alt gain table and Fast Div Bias all set to 0 */ 1803250003Sadrian OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, reg_val); 1804250003Sadrian regval = OS_REG_READ(ah, AR_PHY_CCK_DETECT); 1805250003Sadrian regval &= (~BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__MASK); 1806250003Sadrian OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); 1807250003Sadrian break; 1808250003Sadrian case HAL_ANT_FIXED_B: 1809250003Sadrian /* Enable second antenna only, after checking capability */ 1810250003Sadrian reg_val |= (HAL_ANT_DIV_COMB_LNA2 << 1811250003Sadrian MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__SHIFT); 1812250003Sadrian reg_val |= (HAL_ANT_DIV_COMB_LNA1 << 1813250003Sadrian MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__SHIFT); 1814250003Sadrian /* main/alt gain table and Fast Div all set to 0 */ 1815250003Sadrian OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, reg_val); 1816250003Sadrian regval = OS_REG_READ(ah, AR_PHY_CCK_DETECT); 1817250003Sadrian regval &= (~BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__MASK); 1818250003Sadrian OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); 1819250003Sadrian /* For WB225, need to swith ANT2 from BT to Wifi 1820250003Sadrian * This will not affect HB125 LNA diversity feature. 1821250003Sadrian */ 1822272292Sadrian HALDEBUG(ah, HAL_DEBUG_RESET, "%s: com2=0x%08x\n", __func__, 1823272292Sadrian ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable) 1824250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, 1825250008Sadrian ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable); 1826250003Sadrian break; 1827250003Sadrian default: 1828250003Sadrian break; 1829250003Sadrian } 1830250003Sadrian } 1831250003Sadrian return 0; 1832250003Sadrian} 1833250003Sadrian 1834250003Sadrianstatic u_int16_t 1835250003Sadrianar9300_attenuation_chain_get(struct ath_hal *ah, int chain, u_int16_t channel) 1836250003Sadrian{ 1837250003Sadrian int32_t f[3], t[3]; 1838250003Sadrian u_int16_t value; 1839250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 1840250003Sadrian if (chain >= 0 && chain < OSPREY_MAX_CHAINS) { 1841250003Sadrian if (channel < 4000) { 1842250003Sadrian return eep->modal_header_2g.xatten1_db[chain]; 1843250003Sadrian } else { 1844250003Sadrian if (eep->base_ext2.xatten1_db_low[chain] != 0) { 1845250003Sadrian t[0] = eep->base_ext2.xatten1_db_low[chain]; 1846250003Sadrian f[0] = 5180; 1847250003Sadrian t[1] = eep->modal_header_5g.xatten1_db[chain]; 1848250003Sadrian f[1] = 5500; 1849250003Sadrian t[2] = eep->base_ext2.xatten1_db_high[chain]; 1850250003Sadrian f[2] = 5785; 1851250003Sadrian value = interpolate(channel, f, t, 3); 1852250003Sadrian return value; 1853250003Sadrian } else { 1854250003Sadrian return eep->modal_header_5g.xatten1_db[chain]; 1855250003Sadrian } 1856250003Sadrian } 1857250003Sadrian } 1858250003Sadrian return 0; 1859250003Sadrian} 1860250003Sadrian 1861250003Sadrianstatic u_int16_t 1862250003Sadrianar9300_attenuation_margin_chain_get(struct ath_hal *ah, int chain, 1863250003Sadrian u_int16_t channel) 1864250003Sadrian{ 1865250003Sadrian int32_t f[3], t[3]; 1866250003Sadrian u_int16_t value; 1867250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 1868250003Sadrian if (chain >= 0 && chain < OSPREY_MAX_CHAINS) { 1869250003Sadrian if (channel < 4000) { 1870250003Sadrian return eep->modal_header_2g.xatten1_margin[chain]; 1871250003Sadrian } else { 1872250003Sadrian if (eep->base_ext2.xatten1_margin_low[chain] != 0) { 1873250003Sadrian t[0] = eep->base_ext2.xatten1_margin_low[chain]; 1874250003Sadrian f[0] = 5180; 1875250003Sadrian t[1] = eep->modal_header_5g.xatten1_margin[chain]; 1876250003Sadrian f[1] = 5500; 1877250003Sadrian t[2] = eep->base_ext2.xatten1_margin_high[chain]; 1878250003Sadrian f[2] = 5785; 1879250003Sadrian value = interpolate(channel, f, t, 3); 1880250003Sadrian return value; 1881250003Sadrian } else { 1882250003Sadrian return eep->modal_header_5g.xatten1_margin[chain]; 1883250003Sadrian } 1884250003Sadrian } 1885250003Sadrian } 1886250003Sadrian return 0; 1887250003Sadrian} 1888250003Sadrian 1889272292Sadrian#if 0 1890250003SadrianHAL_BOOL ar9300_attenuation_apply(struct ath_hal *ah, u_int16_t channel) 1891250003Sadrian{ 1892250003Sadrian u_int32_t value; 1893250008Sadrian// struct ath_hal_private *ahpriv = AH_PRIVATE(ah); 1894250003Sadrian 1895250003Sadrian /* Test value. if 0 then attenuation is unused. Don't load anything. */ 1896250003Sadrian value = ar9300_attenuation_chain_get(ah, 0, channel); 1897250003Sadrian OS_REG_RMW_FIELD(ah, 1898250003Sadrian AR_PHY_EXT_ATTEN_CTL_0, AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); 1899250003Sadrian value = ar9300_attenuation_margin_chain_get(ah, 0, channel); 1900250003Sadrian if (ar9300_rx_gain_index_get(ah) == 0 1901250008Sadrian && ah->ah_config.ath_hal_ext_atten_margin_cfg) 1902250003Sadrian { 1903250003Sadrian value = 5; 1904250003Sadrian } 1905250003Sadrian OS_REG_RMW_FIELD(ah, 1906250003Sadrian AR_PHY_EXT_ATTEN_CTL_0, AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); 1907250003Sadrian 1908250003Sadrian if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) { 1909250003Sadrian value = ar9300_attenuation_chain_get(ah, 1, channel); 1910250003Sadrian OS_REG_RMW_FIELD(ah, 1911250003Sadrian AR_PHY_EXT_ATTEN_CTL_1, AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); 1912250003Sadrian value = ar9300_attenuation_margin_chain_get(ah, 1, channel); 1913250003Sadrian OS_REG_RMW_FIELD(ah, 1914250003Sadrian AR_PHY_EXT_ATTEN_CTL_1, AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, 1915250003Sadrian value); 1916291437Sadrian if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)&& !AR_SREV_HONEYBEE(ah) ) { 1917250003Sadrian value = ar9300_attenuation_chain_get(ah, 2, channel); 1918250003Sadrian OS_REG_RMW_FIELD(ah, 1919250003Sadrian AR_PHY_EXT_ATTEN_CTL_2, AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); 1920250003Sadrian value = ar9300_attenuation_margin_chain_get(ah, 2, channel); 1921250003Sadrian OS_REG_RMW_FIELD(ah, 1922250003Sadrian AR_PHY_EXT_ATTEN_CTL_2, AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, 1923250003Sadrian value); 1924250003Sadrian } 1925250003Sadrian } 1926250003Sadrian return 0; 1927250003Sadrian} 1928272292Sadrian#endif 1929272292SadrianHAL_BOOL 1930272292Sadrianar9300_attenuation_apply(struct ath_hal *ah, u_int16_t channel) 1931272292Sadrian{ 1932272292Sadrian int i; 1933272292Sadrian uint32_t value; 1934272292Sadrian uint32_t ext_atten_reg[3] = { 1935272292Sadrian AR_PHY_EXT_ATTEN_CTL_0, 1936272292Sadrian AR_PHY_EXT_ATTEN_CTL_1, 1937272292Sadrian AR_PHY_EXT_ATTEN_CTL_2 1938272292Sadrian }; 1939250003Sadrian 1940272292Sadrian /* 1941272292Sadrian * If it's an AR9462 and we're receiving on the second 1942272292Sadrian * chain only, set the chain 0 details from chain 1 1943272292Sadrian * calibration. 1944272292Sadrian * 1945272292Sadrian * This is from ath9k. 1946272292Sadrian */ 1947272292Sadrian if (AR_SREV_JUPITER(ah) && (AH9300(ah)->ah_rx_chainmask == 0x2)) { 1948272292Sadrian value = ar9300_attenuation_chain_get(ah, 1, channel); 1949272292Sadrian OS_REG_RMW_FIELD(ah, ext_atten_reg[0], 1950272292Sadrian AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); 1951272292Sadrian value = ar9300_attenuation_margin_chain_get(ah, 1, channel); 1952272292Sadrian OS_REG_RMW_FIELD(ah, ext_atten_reg[0], 1953272292Sadrian AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); 1954272292Sadrian } 1955272292Sadrian 1956272292Sadrian /* 1957272292Sadrian * Now, loop over the configured transmit chains and 1958272292Sadrian * load in the attenuation/margin settings as appropriate. 1959272292Sadrian */ 1960272292Sadrian for (i = 0; i < 3; i++) { 1961272292Sadrian if ((AH9300(ah)->ah_tx_chainmask & (1 << i)) == 0) 1962272292Sadrian continue; 1963272292Sadrian 1964272292Sadrian value = ar9300_attenuation_chain_get(ah, i, channel); 1965272292Sadrian OS_REG_RMW_FIELD(ah, ext_atten_reg[i], 1966272292Sadrian AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, 1967272292Sadrian value); 1968272292Sadrian 1969272292Sadrian if (AR_SREV_POSEIDON(ah) && 1970272292Sadrian (ar9300_rx_gain_index_get(ah) == 0) && 1971272292Sadrian ah->ah_config.ath_hal_ext_atten_margin_cfg) { 1972272292Sadrian value = 5; 1973272292Sadrian } else { 1974272292Sadrian value = ar9300_attenuation_margin_chain_get(ah, 0, 1975272292Sadrian channel); 1976272292Sadrian } 1977272292Sadrian 1978272292Sadrian /* 1979272292Sadrian * I'm not sure why it's loading in this setting into 1980272292Sadrian * the chain 0 margin regardless of the current chain. 1981272292Sadrian */ 1982272292Sadrian if (ah->ah_config.ath_hal_min_gainidx) 1983272292Sadrian OS_REG_RMW_FIELD(ah, 1984272292Sadrian AR_PHY_EXT_ATTEN_CTL_0, 1985272292Sadrian AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, 1986272292Sadrian value); 1987272292Sadrian 1988272292Sadrian OS_REG_RMW_FIELD(ah, 1989272292Sadrian ext_atten_reg[i], 1990272292Sadrian AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, 1991272292Sadrian value); 1992272292Sadrian } 1993272292Sadrian 1994272292Sadrian return (0); 1995272292Sadrian} 1996272292Sadrian 1997272292Sadrian 1998250003Sadrianstatic u_int16_t ar9300_quick_drop_get(struct ath_hal *ah, 1999250003Sadrian int chain, u_int16_t channel) 2000250003Sadrian{ 2001250003Sadrian int32_t f[3], t[3]; 2002250003Sadrian u_int16_t value; 2003250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 2004250003Sadrian 2005250003Sadrian if (channel < 4000) { 2006250003Sadrian return eep->modal_header_2g.quick_drop; 2007250003Sadrian } else { 2008250003Sadrian t[0] = eep->base_ext1.quick_drop_low; 2009250003Sadrian f[0] = 5180; 2010250003Sadrian t[1] = eep->modal_header_5g.quick_drop; 2011250003Sadrian f[1] = 5500; 2012250003Sadrian t[2] = eep->base_ext1.quick_drop_high; 2013250003Sadrian f[2] = 5785; 2014250003Sadrian value = interpolate(channel, f, t, 3); 2015250003Sadrian return value; 2016250003Sadrian } 2017250003Sadrian} 2018250003Sadrian 2019250003Sadrian 2020250003Sadrianstatic HAL_BOOL ar9300_quick_drop_apply(struct ath_hal *ah, u_int16_t channel) 2021250003Sadrian{ 2022250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 2023250003Sadrian u_int32_t value; 2024250003Sadrian // 2025250003Sadrian // Test value. if 0 then quickDrop is unused. Don't load anything. 2026250003Sadrian // 2027250003Sadrian if (eep->base_eep_header.misc_configuration & 0x10) 2028250003Sadrian { 2029250003Sadrian if (AR_SREV_OSPREY(ah) || AR_SREV_AR9580(ah) || AR_SREV_WASP(ah)) 2030250003Sadrian { 2031250003Sadrian value = ar9300_quick_drop_get(ah, 0, channel); 2032250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, value); 2033250003Sadrian } 2034250003Sadrian } 2035250003Sadrian return 0; 2036250003Sadrian} 2037250003Sadrian 2038250003Sadrianstatic u_int16_t ar9300_tx_end_to_xpa_off_get(struct ath_hal *ah, u_int16_t channel) 2039250003Sadrian{ 2040250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 2041250003Sadrian 2042250003Sadrian if (channel < 4000) { 2043250003Sadrian return eep->modal_header_2g.tx_end_to_xpa_off; 2044250003Sadrian } else { 2045250003Sadrian return eep->modal_header_5g.tx_end_to_xpa_off; 2046250003Sadrian } 2047250003Sadrian} 2048250003Sadrian 2049250003Sadrianstatic HAL_BOOL ar9300_tx_end_to_xpab_off_apply(struct ath_hal *ah, u_int16_t channel) 2050250003Sadrian{ 2051250003Sadrian u_int32_t value; 2052250003Sadrian 2053250003Sadrian value = ar9300_tx_end_to_xpa_off_get(ah, channel); 2054250003Sadrian /* Apply to both xpaa and xpab */ 2055250003Sadrian if (AR_SREV_OSPREY(ah) || AR_SREV_AR9580(ah) || AR_SREV_WASP(ah)) 2056250003Sadrian { 2057250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_XPA_TIMING_CTL, 2058250003Sadrian AR_PHY_XPA_TIMING_CTL_TX_END_XPAB_OFF, value); 2059250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_XPA_TIMING_CTL, 2060250003Sadrian AR_PHY_XPA_TIMING_CTL_TX_END_XPAA_OFF, value); 2061250003Sadrian } 2062250003Sadrian return 0; 2063250003Sadrian} 2064250003Sadrian 2065250003Sadrianstatic int 2066250003Sadrianar9300_eeprom_cal_pier_get(struct ath_hal *ah, int mode, int ipier, int ichain, 2067250003Sadrian int *pfrequency, int *pcorrection, int *ptemperature, int *pvoltage) 2068250003Sadrian{ 2069250003Sadrian u_int8_t *p_cal_pier; 2070250003Sadrian OSP_CAL_DATA_PER_FREQ_OP_LOOP *p_cal_pier_struct; 2071250003Sadrian int is_2ghz; 2072250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 2073250003Sadrian 2074250003Sadrian if (ichain >= OSPREY_MAX_CHAINS) { 2075250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 2076250003Sadrian "%s: Invalid chain index, must be less than %d\n", 2077250003Sadrian __func__, OSPREY_MAX_CHAINS); 2078250003Sadrian return -1; 2079250003Sadrian } 2080250003Sadrian 2081250003Sadrian if (mode) {/* 5GHz */ 2082250003Sadrian if (ipier >= OSPREY_NUM_5G_CAL_PIERS){ 2083250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 2084250003Sadrian "%s: Invalid 5GHz cal pier index, must be less than %d\n", 2085250003Sadrian __func__, OSPREY_NUM_5G_CAL_PIERS); 2086250003Sadrian return -1; 2087250003Sadrian } 2088250003Sadrian p_cal_pier = &(eep->cal_freq_pier_5g[ipier]); 2089250003Sadrian p_cal_pier_struct = &(eep->cal_pier_data_5g[ichain][ipier]); 2090250003Sadrian is_2ghz = 0; 2091250003Sadrian } else { 2092250003Sadrian if (ipier >= OSPREY_NUM_2G_CAL_PIERS){ 2093250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 2094250003Sadrian "%s: Invalid 2GHz cal pier index, must be less than %d\n", 2095250003Sadrian __func__, OSPREY_NUM_2G_CAL_PIERS); 2096250003Sadrian return -1; 2097250003Sadrian } 2098250003Sadrian 2099250003Sadrian p_cal_pier = &(eep->cal_freq_pier_2g[ipier]); 2100250003Sadrian p_cal_pier_struct = &(eep->cal_pier_data_2g[ichain][ipier]); 2101250003Sadrian is_2ghz = 1; 2102250003Sadrian } 2103250003Sadrian *pfrequency = FBIN2FREQ(*p_cal_pier, is_2ghz); 2104250003Sadrian *pcorrection = p_cal_pier_struct->ref_power; 2105250003Sadrian *ptemperature = p_cal_pier_struct->temp_meas; 2106250003Sadrian *pvoltage = p_cal_pier_struct->volt_meas; 2107250003Sadrian return 0; 2108250003Sadrian} 2109250003Sadrian 2110250003Sadrian/* 2111250003Sadrian * Apply the recorded correction values. 2112250003Sadrian */ 2113250003Sadrianstatic int 2114250003Sadrianar9300_calibration_apply(struct ath_hal *ah, int frequency) 2115250003Sadrian{ 2116250008Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 2117250008Sadrian 2118250003Sadrian int ichain, ipier, npier; 2119250003Sadrian int mode; 2120250003Sadrian int fdiff; 2121250003Sadrian int pfrequency, pcorrection, ptemperature, pvoltage; 2122250003Sadrian int bf, factor, plus; 2123250003Sadrian 2124250003Sadrian int lfrequency[AR9300_MAX_CHAINS]; 2125250003Sadrian int hfrequency[AR9300_MAX_CHAINS]; 2126250003Sadrian 2127250003Sadrian int lcorrection[AR9300_MAX_CHAINS]; 2128250003Sadrian int hcorrection[AR9300_MAX_CHAINS]; 2129250003Sadrian int correction[AR9300_MAX_CHAINS]; 2130250003Sadrian 2131250003Sadrian int ltemperature[AR9300_MAX_CHAINS]; 2132250003Sadrian int htemperature[AR9300_MAX_CHAINS]; 2133250003Sadrian int temperature[AR9300_MAX_CHAINS]; 2134250003Sadrian 2135250003Sadrian int lvoltage[AR9300_MAX_CHAINS]; 2136250003Sadrian int hvoltage[AR9300_MAX_CHAINS]; 2137250003Sadrian int voltage[AR9300_MAX_CHAINS]; 2138250003Sadrian 2139250003Sadrian mode = (frequency >= 4000); 2140250003Sadrian npier = (mode) ? OSPREY_NUM_5G_CAL_PIERS : OSPREY_NUM_2G_CAL_PIERS; 2141250003Sadrian 2142250003Sadrian for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { 2143250003Sadrian lfrequency[ichain] = 0; 2144250003Sadrian hfrequency[ichain] = 100000; 2145250003Sadrian } 2146250003Sadrian /* 2147250003Sadrian * identify best lower and higher frequency calibration measurement 2148250003Sadrian */ 2149250003Sadrian for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { 2150250003Sadrian for (ipier = 0; ipier < npier; ipier++) { 2151250003Sadrian if (ar9300_eeprom_cal_pier_get( 2152250003Sadrian ah, mode, ipier, ichain, 2153250003Sadrian &pfrequency, &pcorrection, &ptemperature, &pvoltage) == 0) 2154250003Sadrian { 2155250003Sadrian fdiff = frequency - pfrequency; 2156250003Sadrian /* 2157250003Sadrian * this measurement is higher than our desired frequency 2158250003Sadrian */ 2159250003Sadrian if (fdiff <= 0) { 2160250003Sadrian if (hfrequency[ichain] <= 0 || 2161250003Sadrian hfrequency[ichain] >= 100000 || 2162250003Sadrian fdiff > (frequency - hfrequency[ichain])) 2163250003Sadrian { 2164250003Sadrian /* 2165250003Sadrian * new best higher frequency measurement 2166250003Sadrian */ 2167250003Sadrian hfrequency[ichain] = pfrequency; 2168250003Sadrian hcorrection[ichain] = pcorrection; 2169250003Sadrian htemperature[ichain] = ptemperature; 2170250003Sadrian hvoltage[ichain] = pvoltage; 2171250003Sadrian } 2172250003Sadrian } 2173250003Sadrian if (fdiff >= 0) { 2174250003Sadrian if (lfrequency[ichain] <= 0 || 2175250003Sadrian fdiff < (frequency - lfrequency[ichain])) 2176250003Sadrian { 2177250003Sadrian /* 2178250003Sadrian * new best lower frequency measurement 2179250003Sadrian */ 2180250003Sadrian lfrequency[ichain] = pfrequency; 2181250003Sadrian lcorrection[ichain] = pcorrection; 2182250003Sadrian ltemperature[ichain] = ptemperature; 2183250003Sadrian lvoltage[ichain] = pvoltage; 2184250003Sadrian } 2185250003Sadrian } 2186250003Sadrian } 2187250003Sadrian } 2188250003Sadrian } 2189250003Sadrian /* interpolate */ 2190250003Sadrian for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { 2191250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 2192250003Sadrian "%s: ch=%d f=%d low=%d %d h=%d %d\n", 2193250003Sadrian __func__, ichain, frequency, 2194250003Sadrian lfrequency[ichain], lcorrection[ichain], 2195250003Sadrian hfrequency[ichain], hcorrection[ichain]); 2196250003Sadrian /* 2197250003Sadrian * they're the same, so just pick one 2198250003Sadrian */ 2199250003Sadrian if (hfrequency[ichain] == lfrequency[ichain]) { 2200250003Sadrian correction[ichain] = lcorrection[ichain]; 2201250003Sadrian voltage[ichain] = lvoltage[ichain]; 2202250003Sadrian temperature[ichain] = ltemperature[ichain]; 2203250003Sadrian } else if (frequency - lfrequency[ichain] < 1000) { 2204250003Sadrian /* the low frequency is good */ 2205250003Sadrian if (hfrequency[ichain] - frequency < 1000) { 2206250003Sadrian /* 2207250003Sadrian * The high frequency is good too - 2208250003Sadrian * interpolate with round off. 2209250003Sadrian */ 2210250003Sadrian int mult, div, diff; 2211250003Sadrian mult = frequency - lfrequency[ichain]; 2212250003Sadrian div = hfrequency[ichain] - lfrequency[ichain]; 2213250003Sadrian 2214250003Sadrian diff = hcorrection[ichain] - lcorrection[ichain]; 2215250003Sadrian bf = 2 * diff * mult / div; 2216250003Sadrian plus = (bf % 2); 2217250003Sadrian factor = bf / 2; 2218250003Sadrian correction[ichain] = lcorrection[ichain] + factor + plus; 2219250003Sadrian 2220250003Sadrian diff = htemperature[ichain] - ltemperature[ichain]; 2221250003Sadrian bf = 2 * diff * mult / div; 2222250003Sadrian plus = (bf % 2); 2223250003Sadrian factor = bf / 2; 2224250003Sadrian temperature[ichain] = ltemperature[ichain] + factor + plus; 2225250003Sadrian 2226250003Sadrian diff = hvoltage[ichain] - lvoltage[ichain]; 2227250003Sadrian bf = 2 * diff * mult / div; 2228250003Sadrian plus = (bf % 2); 2229250003Sadrian factor = bf / 2; 2230250003Sadrian voltage[ichain] = lvoltage[ichain] + factor + plus; 2231250003Sadrian } else { 2232250003Sadrian /* only low is good, use it */ 2233250003Sadrian correction[ichain] = lcorrection[ichain]; 2234250003Sadrian temperature[ichain] = ltemperature[ichain]; 2235250003Sadrian voltage[ichain] = lvoltage[ichain]; 2236250003Sadrian } 2237250003Sadrian } else if (hfrequency[ichain] - frequency < 1000) { 2238250003Sadrian /* only high is good, use it */ 2239250003Sadrian correction[ichain] = hcorrection[ichain]; 2240250003Sadrian temperature[ichain] = htemperature[ichain]; 2241250003Sadrian voltage[ichain] = hvoltage[ichain]; 2242250003Sadrian } else { 2243250003Sadrian /* nothing is good, presume 0???? */ 2244250003Sadrian correction[ichain] = 0; 2245250003Sadrian temperature[ichain] = 0; 2246250003Sadrian voltage[ichain] = 0; 2247250003Sadrian } 2248250003Sadrian } 2249250003Sadrian 2250250008Sadrian /* GreenTx isn't currently supported */ 2251250003Sadrian /* GreenTx */ 2252250008Sadrian if (ah->ah_config.ath_hal_sta_update_tx_pwr_enable) { 2253250003Sadrian if (AR_SREV_POSEIDON(ah)) { 2254250003Sadrian /* Get calibrated OLPC gain delta value for GreenTx */ 2255250008Sadrian ahp->ah_db2[POSEIDON_STORED_REG_G2_OLPC_OFFSET] = 2256250003Sadrian (u_int32_t) correction[0]; 2257250003Sadrian } 2258250003Sadrian } 2259250003Sadrian 2260250003Sadrian ar9300_power_control_override( 2261250003Sadrian ah, frequency, correction, voltage, temperature); 2262250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 2263250003Sadrian "%s: for frequency=%d, calibration correction = %d %d %d\n", 2264250003Sadrian __func__, frequency, correction[0], correction[1], correction[2]); 2265250003Sadrian 2266250003Sadrian return 0; 2267250003Sadrian} 2268250003Sadrian 2269250003Sadrianint 2270250003Sadrianar9300_power_control_override(struct ath_hal *ah, int frequency, 2271250003Sadrian int *correction, int *voltage, int *temperature) 2272250003Sadrian{ 2273250003Sadrian int temp_slope = 0; 2274250003Sadrian int temp_slope_1 = 0; 2275250003Sadrian int temp_slope_2 = 0; 2276250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 2277250003Sadrian int32_t f[8], t[8],t1[3], t2[3]; 2278250003Sadrian int i; 2279250003Sadrian 2280250003Sadrian OS_REG_RMW(ah, AR_PHY_TPC_11_B0, 2281250003Sadrian (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), 2282250003Sadrian AR_PHY_TPC_OLPC_GAIN_DELTA); 2283250003Sadrian if (!AR_SREV_POSEIDON(ah)) { 2284250003Sadrian OS_REG_RMW(ah, AR_PHY_TPC_11_B1, 2285250003Sadrian (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), 2286250003Sadrian AR_PHY_TPC_OLPC_GAIN_DELTA); 2287291437Sadrian if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah) ) { 2288250003Sadrian OS_REG_RMW(ah, AR_PHY_TPC_11_B2, 2289250003Sadrian (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), 2290250003Sadrian AR_PHY_TPC_OLPC_GAIN_DELTA); 2291250003Sadrian } 2292250003Sadrian } 2293250003Sadrian /* 2294250003Sadrian * enable open loop power control on chip 2295250003Sadrian */ 2296250003Sadrian OS_REG_RMW(ah, AR_PHY_TPC_6_B0, 2297250003Sadrian (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), AR_PHY_TPC_6_ERROR_EST_MODE); 2298250003Sadrian if (!AR_SREV_POSEIDON(ah)) { 2299250003Sadrian OS_REG_RMW(ah, AR_PHY_TPC_6_B1, 2300250003Sadrian (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), AR_PHY_TPC_6_ERROR_EST_MODE); 2301291437Sadrian if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah) ) { 2302250003Sadrian OS_REG_RMW(ah, AR_PHY_TPC_6_B2, 2303250003Sadrian (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), 2304250003Sadrian AR_PHY_TPC_6_ERROR_EST_MODE); 2305250003Sadrian } 2306250003Sadrian } 2307250003Sadrian 2308250003Sadrian /* 2309250003Sadrian * Enable temperature compensation 2310250003Sadrian * Need to use register names 2311250003Sadrian */ 2312250003Sadrian if (frequency < 4000) { 2313250003Sadrian temp_slope = eep->modal_header_2g.temp_slope; 2314250003Sadrian } else { 2315250003Sadrian if ((eep->base_eep_header.misc_configuration & 0x20) != 0) 2316250003Sadrian { 2317250003Sadrian for(i=0;i<8;i++) 2318250003Sadrian { 2319250003Sadrian t[i]=eep->base_ext1.tempslopextension[i]; 2320250003Sadrian f[i]=FBIN2FREQ(eep->cal_freq_pier_5g[i], 0); 2321250003Sadrian } 2322250003Sadrian temp_slope=interpolate(frequency,f,t,8); 2323250003Sadrian } 2324250003Sadrian else 2325250003Sadrian { 2326250003Sadrian if(!AR_SREV_SCORPION(ah)) { 2327250003Sadrian if (eep->base_ext2.temp_slope_low != 0) { 2328250003Sadrian t[0] = eep->base_ext2.temp_slope_low; 2329250003Sadrian f[0] = 5180; 2330250003Sadrian t[1] = eep->modal_header_5g.temp_slope; 2331250003Sadrian f[1] = 5500; 2332250003Sadrian t[2] = eep->base_ext2.temp_slope_high; 2333250003Sadrian f[2] = 5785; 2334250003Sadrian temp_slope = interpolate(frequency, f, t, 3); 2335250003Sadrian } else { 2336250003Sadrian temp_slope = eep->modal_header_5g.temp_slope; 2337250003Sadrian } 2338250003Sadrian } else { 2339250003Sadrian /* 2340250003Sadrian * Scorpion has individual chain tempslope values 2341250003Sadrian */ 2342250003Sadrian t[0] = eep->base_ext1.tempslopextension[2]; 2343250003Sadrian t1[0]= eep->base_ext1.tempslopextension[3]; 2344250003Sadrian t2[0]= eep->base_ext1.tempslopextension[4]; 2345250003Sadrian f[0] = 5180; 2346250003Sadrian t[1] = eep->modal_header_5g.temp_slope; 2347250003Sadrian t1[1]= eep->base_ext1.tempslopextension[0]; 2348250003Sadrian t2[1]= eep->base_ext1.tempslopextension[1]; 2349250003Sadrian f[1] = 5500; 2350250003Sadrian t[2] = eep->base_ext1.tempslopextension[5]; 2351250003Sadrian t1[2]= eep->base_ext1.tempslopextension[6]; 2352250003Sadrian t2[2]= eep->base_ext1.tempslopextension[7]; 2353250003Sadrian f[2] = 5785; 2354250003Sadrian temp_slope = interpolate(frequency, f, t, 3); 2355250003Sadrian temp_slope_1=interpolate(frequency, f, t1,3); 2356250003Sadrian temp_slope_2=interpolate(frequency, f, t2,3); 2357250003Sadrian } 2358250003Sadrian } 2359250003Sadrian } 2360250003Sadrian 2361291437Sadrian if (!AR_SREV_SCORPION(ah) && !AR_SREV_HONEYBEE(ah)) { 2362250003Sadrian OS_REG_RMW_FIELD(ah, 2363250003Sadrian AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, temp_slope); 2364250003Sadrian } else { 2365291437Sadrian /*Scorpion and Honeybee has tempSlope register for each chain*/ 2366250003Sadrian /*Check whether temp_compensation feature is enabled or not*/ 2367250003Sadrian if (eep->base_eep_header.feature_enable & 0x1){ 2368250003Sadrian if(frequency < 4000) { 2369291437Sadrian if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x1) { 2370250003Sadrian OS_REG_RMW_FIELD(ah, 2371250003Sadrian AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, 2372250003Sadrian eep->base_ext2.temp_slope_low); 2373291437Sadrian } 2374291437Sadrian if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x2) { 2375250003Sadrian OS_REG_RMW_FIELD(ah, 2376250003Sadrian AR_SCORPION_PHY_TPC_19_B1, AR_PHY_TPC_19_ALPHA_THERM, 2377250003Sadrian temp_slope); 2378291437Sadrian } 2379291437Sadrian if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x4) { 2380250003Sadrian OS_REG_RMW_FIELD(ah, 2381250003Sadrian AR_SCORPION_PHY_TPC_19_B2, AR_PHY_TPC_19_ALPHA_THERM, 2382250003Sadrian eep->base_ext2.temp_slope_high); 2383291437Sadrian } 2384250003Sadrian } else { 2385291437Sadrian if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x1) { 2386250003Sadrian OS_REG_RMW_FIELD(ah, 2387250003Sadrian AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, 2388250003Sadrian temp_slope); 2389291437Sadrian } 2390291437Sadrian if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x2) { 2391250003Sadrian OS_REG_RMW_FIELD(ah, 2392250003Sadrian AR_SCORPION_PHY_TPC_19_B1, AR_PHY_TPC_19_ALPHA_THERM, 2393250003Sadrian temp_slope_1); 2394291437Sadrian } 2395291437Sadrian if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x4) { 2396250003Sadrian OS_REG_RMW_FIELD(ah, 2397250003Sadrian AR_SCORPION_PHY_TPC_19_B2, AR_PHY_TPC_19_ALPHA_THERM, 2398250003Sadrian temp_slope_2); 2399291437Sadrian } 2400250003Sadrian } 2401250003Sadrian }else { 2402250003Sadrian /* If temp compensation is not enabled, set all registers to 0*/ 2403291437Sadrian if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x1) { 2404250003Sadrian OS_REG_RMW_FIELD(ah, 2405250003Sadrian AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, 0); 2406291437Sadrian } 2407291437Sadrian if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x2) { 2408250003Sadrian OS_REG_RMW_FIELD(ah, 2409250003Sadrian AR_SCORPION_PHY_TPC_19_B1, AR_PHY_TPC_19_ALPHA_THERM, 0); 2410291437Sadrian } 2411291437Sadrian if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x4) { 2412250003Sadrian OS_REG_RMW_FIELD(ah, 2413250003Sadrian AR_SCORPION_PHY_TPC_19_B2, AR_PHY_TPC_19_ALPHA_THERM, 0); 2414291437Sadrian } 2415250003Sadrian } 2416250003Sadrian } 2417250003Sadrian OS_REG_RMW_FIELD(ah, 2418250003Sadrian AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE, temperature[0]); 2419250003Sadrian 2420250003Sadrian return 0; 2421250003Sadrian} 2422250003Sadrian 2423250003Sadrian/************************************************************** 2424250003Sadrian * ar9300_eep_def_get_max_edge_power 2425250003Sadrian * 2426250003Sadrian * Find the maximum conformance test limit for the given channel and CTL info 2427250003Sadrian */ 2428250003Sadrianstatic inline u_int16_t 2429250003Sadrianar9300_eep_def_get_max_edge_power(ar9300_eeprom_t *p_eep_data, u_int16_t freq, 2430250003Sadrian int idx, HAL_BOOL is_2ghz) 2431250003Sadrian{ 2432250003Sadrian u_int16_t twice_max_edge_power = AR9300_MAX_RATE_POWER; 2433250003Sadrian u_int8_t *ctl_freqbin = is_2ghz ? 2434250003Sadrian &p_eep_data->ctl_freqbin_2G[idx][0] : 2435250003Sadrian &p_eep_data->ctl_freqbin_5G[idx][0]; 2436250003Sadrian u_int16_t num_edges = is_2ghz ? 2437250003Sadrian OSPREY_NUM_BAND_EDGES_2G : OSPREY_NUM_BAND_EDGES_5G; 2438250003Sadrian int i; 2439250003Sadrian 2440250003Sadrian /* Get the edge power */ 2441250003Sadrian for (i = 0; (i < num_edges) && (ctl_freqbin[i] != AR9300_BCHAN_UNUSED); i++) 2442250003Sadrian { 2443250003Sadrian /* 2444250003Sadrian * If there's an exact channel match or an inband flag set 2445250003Sadrian * on the lower channel use the given rd_edge_power 2446250003Sadrian */ 2447250003Sadrian if (freq == fbin2freq(ctl_freqbin[i], is_2ghz)) { 2448250003Sadrian if (is_2ghz) { 2449250003Sadrian twice_max_edge_power = 2450250003Sadrian p_eep_data->ctl_power_data_2g[idx].ctl_edges[i].t_power; 2451250003Sadrian } else { 2452250003Sadrian twice_max_edge_power = 2453250003Sadrian p_eep_data->ctl_power_data_5g[idx].ctl_edges[i].t_power; 2454250003Sadrian } 2455250003Sadrian break; 2456250003Sadrian } else if ((i > 0) && (freq < fbin2freq(ctl_freqbin[i], is_2ghz))) { 2457250003Sadrian if (is_2ghz) { 2458250003Sadrian if (fbin2freq(ctl_freqbin[i - 1], 1) < freq && 2459250003Sadrian p_eep_data->ctl_power_data_2g[idx].ctl_edges[i - 1].flag) 2460250003Sadrian { 2461250003Sadrian twice_max_edge_power = 2462250003Sadrian p_eep_data->ctl_power_data_2g[idx]. 2463250003Sadrian ctl_edges[i - 1].t_power; 2464250003Sadrian } 2465250003Sadrian } else { 2466250003Sadrian if (fbin2freq(ctl_freqbin[i - 1], 0) < freq && 2467250003Sadrian p_eep_data->ctl_power_data_5g[idx].ctl_edges[i - 1].flag) 2468250003Sadrian { 2469250003Sadrian twice_max_edge_power = 2470250003Sadrian p_eep_data->ctl_power_data_5g[idx]. 2471250003Sadrian ctl_edges[i - 1].t_power; 2472250003Sadrian } 2473250003Sadrian } 2474250003Sadrian /* 2475250003Sadrian * Leave loop - no more affecting edges possible 2476250003Sadrian * in this monotonic increasing list 2477250003Sadrian */ 2478250003Sadrian break; 2479250003Sadrian } 2480250003Sadrian } 2481250003Sadrian /* 2482250003Sadrian * EV89475: EEPROM might contain 0 txpower in CTL table for certain 2483250003Sadrian * 2.4GHz channels. We workaround it by overwriting 60 (30 dBm) here. 2484250003Sadrian */ 2485250003Sadrian if (is_2ghz && (twice_max_edge_power == 0)) { 2486250003Sadrian twice_max_edge_power = 60; 2487250003Sadrian } 2488250003Sadrian 2489250003Sadrian HALASSERT(twice_max_edge_power > 0); 2490250003Sadrian return twice_max_edge_power; 2491250003Sadrian} 2492250003Sadrian 2493250003SadrianHAL_BOOL 2494250003Sadrianar9300_eeprom_set_power_per_rate_table( 2495250003Sadrian struct ath_hal *ah, 2496250003Sadrian ar9300_eeprom_t *p_eep_data, 2497250008Sadrian const struct ieee80211_channel *chan, 2498250003Sadrian u_int8_t *p_pwr_array, 2499250003Sadrian u_int16_t cfg_ctl, 2500250003Sadrian u_int16_t antenna_reduction, 2501250003Sadrian u_int16_t twice_max_regulatory_power, 2502250003Sadrian u_int16_t power_limit, 2503250003Sadrian u_int8_t chainmask) 2504250003Sadrian{ 2505250003Sadrian /* Local defines to distinguish between extension and control CTL's */ 2506250003Sadrian#define EXT_ADDITIVE (0x8000) 2507250003Sadrian#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE) 2508250003Sadrian#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE) 2509250003Sadrian#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE) 2510250003Sadrian#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ 2511250003Sadrian#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ 2512250003Sadrian#define PWRINCR_3_TO_1_CHAIN 9 /* 10*log(3)*2 */ 2513250003Sadrian#define PWRINCR_3_TO_2_CHAIN 3 /* floor(10*log(3/2)*2) */ 2514250003Sadrian#define PWRINCR_2_TO_1_CHAIN 6 /* 10*log(2)*2 */ 2515250003Sadrian 2516250003Sadrian static const u_int16_t tp_scale_reduction_table[5] = 2517250003Sadrian { 0, 3, 6, 9, AR9300_MAX_RATE_POWER }; 2518250003Sadrian int i; 2519250003Sadrian int16_t twice_largest_antenna; 2520250003Sadrian u_int16_t twice_antenna_reduction = 2*antenna_reduction ; 2521250003Sadrian int16_t scaled_power = 0, min_ctl_power, max_reg_allowed_power; 2522250003Sadrian#define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */ 2523250003Sadrian#define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */ 2524250003Sadrian u_int16_t ctl_modes_for11a[] = 2525250003Sadrian {CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40}; 2526250003Sadrian u_int16_t ctl_modes_for11g[] = 2527250003Sadrian {CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40}; 2528250003Sadrian u_int16_t num_ctl_modes, *p_ctl_mode, ctl_mode, freq; 2529250003Sadrian CHAN_CENTERS centers; 2530250003Sadrian int tx_chainmask; 2531250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 2532250003Sadrian u_int8_t *ctl_index; 2533250003Sadrian u_int8_t ctl_num; 2534250003Sadrian u_int16_t twice_min_edge_power; 2535250003Sadrian u_int16_t twice_max_edge_power = AR9300_MAX_RATE_POWER; 2536250008Sadrian#ifdef AH_DEBUG 2537250008Sadrian HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); 2538250008Sadrian#endif 2539250003Sadrian 2540278741Sadrian if (chainmask) 2541278741Sadrian tx_chainmask = chainmask; 2542278741Sadrian else 2543278741Sadrian tx_chainmask = ahp->ah_tx_chainmaskopt ? 2544278741Sadrian ahp->ah_tx_chainmaskopt :ahp->ah_tx_chainmask; 2545250003Sadrian 2546250003Sadrian ar9300_get_channel_centers(ah, chan, ¢ers); 2547250003Sadrian 2548278741Sadrian#if 1 2549250008Sadrian if (IEEE80211_IS_CHAN_2GHZ(chan)) { 2550250003Sadrian ahp->twice_antenna_gain = p_eep_data->modal_header_2g.antenna_gain; 2551250003Sadrian } else { 2552250003Sadrian ahp->twice_antenna_gain = p_eep_data->modal_header_5g.antenna_gain; 2553250003Sadrian } 2554250003Sadrian 2555278741Sadrian#else 2556278741Sadrian if (IEEE80211_IS_CHAN_2GHZ(chan)) { 2557278741Sadrian ahp->twice_antenna_gain = AH_MAX(p_eep_data->modal_header_2g.antenna_gain, 2558278741Sadrian AH_PRIVATE(ah)->ah_antenna_gain_2g); 2559278741Sadrian } else { 2560278741Sadrian ahp->twice_antenna_gain = AH_MAX(p_eep_data->modal_header_5g.antenna_gain, 2561278741Sadrian AH_PRIVATE(ah)->ah_antenna_gain_5g); 2562278741Sadrian } 2563278741Sadrian#endif 2564278741Sadrian 2565250003Sadrian /* Save max allowed antenna gain to ease future lookups */ 2566250003Sadrian ahp->twice_antenna_reduction = twice_antenna_reduction; 2567250003Sadrian 2568250003Sadrian /* Deduct antenna gain from EIRP to get the upper limit */ 2569250003Sadrian twice_largest_antenna = (int16_t)AH_MIN((twice_antenna_reduction - 2570250003Sadrian ahp->twice_antenna_gain), 0); 2571250003Sadrian max_reg_allowed_power = twice_max_regulatory_power + twice_largest_antenna; 2572250003Sadrian 2573250003Sadrian /* Use ah_tp_scale - see bug 30070. */ 2574250008Sadrian if (AH_PRIVATE(ah)->ah_tpScale != HAL_TP_SCALE_MAX) { 2575250003Sadrian max_reg_allowed_power -= 2576250008Sadrian (tp_scale_reduction_table[(AH_PRIVATE(ah)->ah_tpScale)] * 2); 2577250003Sadrian } 2578250003Sadrian 2579250003Sadrian scaled_power = AH_MIN(power_limit, max_reg_allowed_power); 2580250003Sadrian 2581250003Sadrian /* 2582250003Sadrian * Reduce scaled Power by number of chains active to get to 2583250003Sadrian * per chain tx power level 2584250003Sadrian */ 2585250003Sadrian /* TODO: better value than these? */ 2586250003Sadrian switch (ar9300_get_ntxchains(tx_chainmask)) { 2587250003Sadrian case 1: 2588250003Sadrian ahp->upper_limit[0] = AH_MAX(0, scaled_power); 2589250003Sadrian break; 2590250003Sadrian case 2: 2591250003Sadrian scaled_power -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; 2592250003Sadrian ahp->upper_limit[1] = AH_MAX(0, scaled_power); 2593250003Sadrian break; 2594250003Sadrian case 3: 2595250003Sadrian scaled_power -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; 2596250003Sadrian ahp->upper_limit[2] = AH_MAX(0, scaled_power); 2597250003Sadrian break; 2598250003Sadrian default: 2599250003Sadrian HALASSERT(0); /* Unsupported number of chains */ 2600250003Sadrian } 2601250003Sadrian 2602250003Sadrian scaled_power = AH_MAX(0, scaled_power); 2603250003Sadrian 2604250003Sadrian /* Get target powers from EEPROM - our baseline for TX Power */ 2605250008Sadrian if (IEEE80211_IS_CHAN_2GHZ(chan)) { 2606250003Sadrian /* Setup for CTL modes */ 2607250003Sadrian /* CTL_11B, CTL_11G, CTL_2GHT20 */ 2608250003Sadrian num_ctl_modes = 2609250003Sadrian ARRAY_LENGTH(ctl_modes_for11g) - SUB_NUM_CTL_MODES_AT_2G_40; 2610250003Sadrian p_ctl_mode = ctl_modes_for11g; 2611250003Sadrian 2612250008Sadrian if (IEEE80211_IS_CHAN_HT40(chan)) { 2613250003Sadrian num_ctl_modes = ARRAY_LENGTH(ctl_modes_for11g); /* All 2G CTL's */ 2614250003Sadrian } 2615250003Sadrian } else { 2616250003Sadrian /* Setup for CTL modes */ 2617250003Sadrian /* CTL_11A, CTL_5GHT20 */ 2618250003Sadrian num_ctl_modes = 2619250003Sadrian ARRAY_LENGTH(ctl_modes_for11a) - SUB_NUM_CTL_MODES_AT_5G_40; 2620250003Sadrian p_ctl_mode = ctl_modes_for11a; 2621250003Sadrian 2622250008Sadrian if (IEEE80211_IS_CHAN_HT40(chan)) { 2623250003Sadrian num_ctl_modes = ARRAY_LENGTH(ctl_modes_for11a); /* All 5G CTL's */ 2624250003Sadrian } 2625250003Sadrian } 2626250003Sadrian 2627250003Sadrian /* 2628250003Sadrian * For MIMO, need to apply regulatory caps individually across dynamically 2629250003Sadrian * running modes: CCK, OFDM, HT20, HT40 2630250003Sadrian * 2631250003Sadrian * The outer loop walks through each possible applicable runtime mode. 2632250003Sadrian * The inner loop walks through each ctl_index entry in EEPROM. 2633250003Sadrian * The ctl value is encoded as [7:4] == test group, [3:0] == test mode. 2634250003Sadrian * 2635250003Sadrian */ 2636250003Sadrian for (ctl_mode = 0; ctl_mode < num_ctl_modes; ctl_mode++) { 2637250003Sadrian HAL_BOOL is_ht40_ctl_mode = 2638250003Sadrian (p_ctl_mode[ctl_mode] == CTL_5GHT40) || 2639250003Sadrian (p_ctl_mode[ctl_mode] == CTL_2GHT40); 2640250003Sadrian if (is_ht40_ctl_mode) { 2641250003Sadrian freq = centers.synth_center; 2642250003Sadrian } else if (p_ctl_mode[ctl_mode] & EXT_ADDITIVE) { 2643250003Sadrian freq = centers.ext_center; 2644250003Sadrian } else { 2645250003Sadrian freq = centers.ctl_center; 2646250003Sadrian } 2647250003Sadrian 2648250003Sadrian HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, 2649250003Sadrian "LOOP-Mode ctl_mode %d < %d, " 2650250003Sadrian "is_ht40_ctl_mode %d, EXT_ADDITIVE %d\n", 2651250003Sadrian ctl_mode, num_ctl_modes, is_ht40_ctl_mode, 2652250003Sadrian (p_ctl_mode[ctl_mode] & EXT_ADDITIVE)); 2653250003Sadrian /* walk through each CTL index stored in EEPROM */ 2654250008Sadrian if (IEEE80211_IS_CHAN_2GHZ(chan)) { 2655250003Sadrian ctl_index = p_eep_data->ctl_index_2g; 2656250003Sadrian ctl_num = OSPREY_NUM_CTLS_2G; 2657250003Sadrian } else { 2658250003Sadrian ctl_index = p_eep_data->ctl_index_5g; 2659250003Sadrian ctl_num = OSPREY_NUM_CTLS_5G; 2660250003Sadrian } 2661250003Sadrian 2662250003Sadrian for (i = 0; (i < ctl_num) && ctl_index[i]; i++) { 2663250003Sadrian HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, 2664250003Sadrian " LOOP-Ctlidx %d: cfg_ctl 0x%2.2x p_ctl_mode 0x%2.2x " 2665250003Sadrian "ctl_index 0x%2.2x chan %d chanctl 0x%x\n", 2666250003Sadrian i, cfg_ctl, p_ctl_mode[ctl_mode], ctl_index[i], 2667250008Sadrian ichan->channel, ath_hal_getctl(ah, chan)); 2668250003Sadrian 2669250008Sadrian 2670250003Sadrian /* 2671250003Sadrian * compare test group from regulatory channel list 2672250003Sadrian * with test mode from p_ctl_mode list 2673250003Sadrian */ 2674250003Sadrian if ((((cfg_ctl & ~CTL_MODE_M) | 2675250003Sadrian (p_ctl_mode[ctl_mode] & CTL_MODE_M)) == ctl_index[i]) || 2676250003Sadrian (((cfg_ctl & ~CTL_MODE_M) | 2677250003Sadrian (p_ctl_mode[ctl_mode] & CTL_MODE_M)) == 2678250003Sadrian ((ctl_index[i] & CTL_MODE_M) | SD_NO_CTL))) 2679250003Sadrian { 2680250003Sadrian twice_min_edge_power = 2681250003Sadrian ar9300_eep_def_get_max_edge_power( 2682250008Sadrian p_eep_data, freq, i, IEEE80211_IS_CHAN_2GHZ(chan)); 2683250003Sadrian 2684250003Sadrian HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, 2685250003Sadrian " MATCH-EE_IDX %d: ch %d is2 %d " 2686250003Sadrian "2xMinEdge %d chainmask %d chains %d\n", 2687250008Sadrian i, freq, IEEE80211_IS_CHAN_2GHZ(chan), 2688250003Sadrian twice_min_edge_power, tx_chainmask, 2689250003Sadrian ar9300_get_ntxchains(tx_chainmask)); 2690250003Sadrian 2691250003Sadrian if ((cfg_ctl & ~CTL_MODE_M) == SD_NO_CTL) { 2692250003Sadrian /* 2693250003Sadrian * Find the minimum of all CTL edge powers 2694250003Sadrian * that apply to this channel 2695250003Sadrian */ 2696250003Sadrian twice_max_edge_power = 2697250003Sadrian AH_MIN(twice_max_edge_power, twice_min_edge_power); 2698250003Sadrian } else { 2699250003Sadrian /* specific */ 2700250003Sadrian twice_max_edge_power = twice_min_edge_power; 2701250003Sadrian break; 2702250003Sadrian } 2703250003Sadrian } 2704250003Sadrian } 2705250003Sadrian 2706250003Sadrian min_ctl_power = (u_int8_t)AH_MIN(twice_max_edge_power, scaled_power); 2707250003Sadrian 2708250003Sadrian HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, 2709250003Sadrian " SEL-Min ctl_mode %d p_ctl_mode %d " 2710250003Sadrian "2xMaxEdge %d sP %d min_ctl_pwr %d\n", 2711250003Sadrian ctl_mode, p_ctl_mode[ctl_mode], 2712250003Sadrian twice_max_edge_power, scaled_power, min_ctl_power); 2713250003Sadrian 2714250003Sadrian /* Apply ctl mode to correct target power set */ 2715250003Sadrian switch (p_ctl_mode[ctl_mode]) { 2716250003Sadrian case CTL_11B: 2717250003Sadrian for (i = ALL_TARGET_LEGACY_1L_5L; i <= ALL_TARGET_LEGACY_11S; i++) { 2718250003Sadrian p_pwr_array[i] = 2719250003Sadrian (u_int8_t)AH_MIN(p_pwr_array[i], min_ctl_power); 2720250003Sadrian } 2721250003Sadrian break; 2722250003Sadrian case CTL_11A: 2723250003Sadrian case CTL_11G: 2724250003Sadrian for (i = ALL_TARGET_LEGACY_6_24; i <= ALL_TARGET_LEGACY_54; i++) { 2725250003Sadrian p_pwr_array[i] = 2726250003Sadrian (u_int8_t)AH_MIN(p_pwr_array[i], min_ctl_power); 2727250003Sadrian#ifdef ATH_BT_COEX 2728250003Sadrian if ((ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_3WIRE) || 2729250003Sadrian (ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_MCI)) 2730250003Sadrian { 2731250003Sadrian if ((ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_LOWER_TX_PWR) 2732250003Sadrian && (ahp->ah_bt_wlan_isolation 2733250003Sadrian < HAL_BT_COEX_ISOLATION_FOR_NO_COEX)) 2734250003Sadrian { 2735250003Sadrian 2736250003Sadrian u_int8_t reduce_pow; 2737250003Sadrian 2738250003Sadrian reduce_pow = (HAL_BT_COEX_ISOLATION_FOR_NO_COEX 2739250003Sadrian - ahp->ah_bt_wlan_isolation) << 1; 2740250003Sadrian 2741250003Sadrian if (reduce_pow <= p_pwr_array[i]) { 2742250003Sadrian p_pwr_array[i] -= reduce_pow; 2743250003Sadrian } 2744250003Sadrian } 2745250003Sadrian if ((ahp->ah_bt_coex_flag & 2746250003Sadrian HAL_BT_COEX_FLAG_LOW_ACK_PWR) && 2747250003Sadrian (i != ALL_TARGET_LEGACY_36) && 2748250003Sadrian (i != ALL_TARGET_LEGACY_48) && 2749250003Sadrian (i != ALL_TARGET_LEGACY_54) && 2750250003Sadrian (p_ctl_mode[ctl_mode] == CTL_11G)) 2751250003Sadrian { 2752250003Sadrian p_pwr_array[i] = 0; 2753250003Sadrian } 2754250003Sadrian } 2755250003Sadrian#endif 2756250003Sadrian } 2757250003Sadrian break; 2758250003Sadrian case CTL_5GHT20: 2759250003Sadrian case CTL_2GHT20: 2760250003Sadrian for (i = ALL_TARGET_HT20_0_8_16; i <= ALL_TARGET_HT20_23; i++) { 2761250003Sadrian p_pwr_array[i] = 2762250003Sadrian (u_int8_t)AH_MIN(p_pwr_array[i], min_ctl_power); 2763250003Sadrian#ifdef ATH_BT_COEX 2764250003Sadrian if (((ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_3WIRE) || 2765250003Sadrian (ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_MCI)) && 2766250003Sadrian (ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_LOWER_TX_PWR) && 2767250003Sadrian (ahp->ah_bt_wlan_isolation 2768250003Sadrian < HAL_BT_COEX_ISOLATION_FOR_NO_COEX)) { 2769250003Sadrian 2770250003Sadrian u_int8_t reduce_pow = (HAL_BT_COEX_ISOLATION_FOR_NO_COEX 2771250003Sadrian - ahp->ah_bt_wlan_isolation) << 1; 2772250003Sadrian 2773250003Sadrian if (reduce_pow <= p_pwr_array[i]) { 2774250003Sadrian p_pwr_array[i] -= reduce_pow; 2775250003Sadrian } 2776250003Sadrian } 2777250003Sadrian#if ATH_SUPPORT_MCI 2778250003Sadrian else if ((ahp->ah_bt_coex_flag & 2779250003Sadrian HAL_BT_COEX_FLAG_MCI_MAX_TX_PWR) && 2780250003Sadrian (p_ctl_mode[ctl_mode] == CTL_2GHT20) && 2781250003Sadrian (ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_MCI)) 2782250003Sadrian { 2783250003Sadrian u_int8_t max_pwr; 2784250003Sadrian 2785250003Sadrian max_pwr = MS(mci_concur_tx_max_pwr[2][1], 2786250003Sadrian ATH_MCI_CONCUR_TX_LOWEST_PWR_MASK); 2787250003Sadrian if (p_pwr_array[i] > max_pwr) { 2788250003Sadrian p_pwr_array[i] = max_pwr; 2789250003Sadrian } 2790250003Sadrian } 2791250003Sadrian#endif 2792250003Sadrian#endif 2793250003Sadrian } 2794250003Sadrian break; 2795250003Sadrian case CTL_11B_EXT: 2796250003Sadrian#ifdef NOT_YET 2797250003Sadrian target_power_cck_ext.t_pow2x[0] = (u_int8_t) 2798250003Sadrian AH_MIN(target_power_cck_ext.t_pow2x[0], min_ctl_power); 2799250003Sadrian#endif /* NOT_YET */ 2800250003Sadrian break; 2801250003Sadrian case CTL_11A_EXT: 2802250003Sadrian case CTL_11G_EXT: 2803250003Sadrian#ifdef NOT_YET 2804250003Sadrian target_power_ofdm_ext.t_pow2x[0] = (u_int8_t) 2805250003Sadrian AH_MIN(target_power_ofdm_ext.t_pow2x[0], min_ctl_power); 2806250003Sadrian#endif /* NOT_YET */ 2807250003Sadrian break; 2808250003Sadrian case CTL_5GHT40: 2809250003Sadrian case CTL_2GHT40: 2810250003Sadrian for (i = ALL_TARGET_HT40_0_8_16; i <= ALL_TARGET_HT40_23; i++) { 2811250003Sadrian p_pwr_array[i] = (u_int8_t) 2812250003Sadrian AH_MIN(p_pwr_array[i], min_ctl_power); 2813250003Sadrian#ifdef ATH_BT_COEX 2814250003Sadrian if (((ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_3WIRE) || 2815250003Sadrian (ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_MCI)) && 2816250003Sadrian (ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_LOWER_TX_PWR) && 2817250003Sadrian (ahp->ah_bt_wlan_isolation 2818250003Sadrian < HAL_BT_COEX_ISOLATION_FOR_NO_COEX)) { 2819250003Sadrian 2820250003Sadrian u_int8_t reduce_pow = (HAL_BT_COEX_ISOLATION_FOR_NO_COEX 2821250003Sadrian - ahp->ah_bt_wlan_isolation) << 1; 2822250003Sadrian 2823250003Sadrian if (reduce_pow <= p_pwr_array[i]) { 2824250003Sadrian p_pwr_array[i] -= reduce_pow; 2825250003Sadrian } 2826250003Sadrian } 2827250003Sadrian#if ATH_SUPPORT_MCI 2828250003Sadrian else if ((ahp->ah_bt_coex_flag & 2829250003Sadrian HAL_BT_COEX_FLAG_MCI_MAX_TX_PWR) && 2830250003Sadrian (p_ctl_mode[ctl_mode] == CTL_2GHT40) && 2831250003Sadrian (ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_MCI)) 2832250003Sadrian { 2833250003Sadrian u_int8_t max_pwr; 2834250003Sadrian 2835250003Sadrian max_pwr = MS(mci_concur_tx_max_pwr[3][1], 2836250003Sadrian ATH_MCI_CONCUR_TX_LOWEST_PWR_MASK); 2837250003Sadrian if (p_pwr_array[i] > max_pwr) { 2838250003Sadrian p_pwr_array[i] = max_pwr; 2839250003Sadrian } 2840250003Sadrian } 2841250003Sadrian#endif 2842250003Sadrian#endif 2843250003Sadrian } 2844250003Sadrian break; 2845250003Sadrian default: 2846250003Sadrian HALASSERT(0); 2847250003Sadrian break; 2848250003Sadrian } 2849250003Sadrian } /* end ctl mode checking */ 2850250003Sadrian 2851250003Sadrian return AH_TRUE; 2852250003Sadrian#undef EXT_ADDITIVE 2853250003Sadrian#undef CTL_11A_EXT 2854250003Sadrian#undef CTL_11G_EXT 2855250003Sadrian#undef CTL_11B_EXT 2856250003Sadrian#undef REDUCE_SCALED_POWER_BY_TWO_CHAIN 2857250003Sadrian#undef REDUCE_SCALED_POWER_BY_THREE_CHAIN 2858250003Sadrian} 2859250003Sadrian 2860250003Sadrian/************************************************************** 2861250003Sadrian * ar9300_eeprom_set_transmit_power 2862250003Sadrian * 2863250003Sadrian * Set the transmit power in the baseband for the given 2864250003Sadrian * operating channel and mode. 2865250003Sadrian */ 2866250003SadrianHAL_STATUS 2867250003Sadrianar9300_eeprom_set_transmit_power(struct ath_hal *ah, 2868250008Sadrian ar9300_eeprom_t *p_eep_data, const struct ieee80211_channel *chan, u_int16_t cfg_ctl, 2869250003Sadrian u_int16_t antenna_reduction, u_int16_t twice_max_regulatory_power, 2870250003Sadrian u_int16_t power_limit) 2871250003Sadrian{ 2872250003Sadrian#define ABS(_x, _y) ((int)_x > (int)_y ? (int)_x - (int)_y : (int)_y - (int)_x) 2873250003Sadrian#define INCREASE_MAXPOW_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ 2874250003Sadrian#define INCREASE_MAXPOW_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ 2875250003Sadrian u_int8_t target_power_val_t2[ar9300_rate_size]; 2876250003Sadrian u_int8_t target_power_val_t2_eep[ar9300_rate_size]; 2877250003Sadrian int16_t twice_array_gain = 0, max_power_level = 0; 2878250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 2879250003Sadrian int i = 0; 2880250003Sadrian u_int32_t tmp_paprd_rate_mask = 0, *tmp_ptr = NULL; 2881250003Sadrian int paprd_scale_factor = 5; 2882250008Sadrian HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); 2883250003Sadrian 2884250003Sadrian u_int8_t *ptr_mcs_rate2power_table_index; 2885250003Sadrian u_int8_t mcs_rate2power_table_index_ht20[24] = 2886250003Sadrian { 2887250003Sadrian ALL_TARGET_HT20_0_8_16, 2888250003Sadrian ALL_TARGET_HT20_1_3_9_11_17_19, 2889250003Sadrian ALL_TARGET_HT20_1_3_9_11_17_19, 2890250003Sadrian ALL_TARGET_HT20_1_3_9_11_17_19, 2891250003Sadrian ALL_TARGET_HT20_4, 2892250003Sadrian ALL_TARGET_HT20_5, 2893250003Sadrian ALL_TARGET_HT20_6, 2894250003Sadrian ALL_TARGET_HT20_7, 2895250003Sadrian ALL_TARGET_HT20_0_8_16, 2896250003Sadrian ALL_TARGET_HT20_1_3_9_11_17_19, 2897250003Sadrian ALL_TARGET_HT20_1_3_9_11_17_19, 2898250003Sadrian ALL_TARGET_HT20_1_3_9_11_17_19, 2899250003Sadrian ALL_TARGET_HT20_12, 2900250003Sadrian ALL_TARGET_HT20_13, 2901250003Sadrian ALL_TARGET_HT20_14, 2902250003Sadrian ALL_TARGET_HT20_15, 2903250003Sadrian ALL_TARGET_HT20_0_8_16, 2904250003Sadrian ALL_TARGET_HT20_1_3_9_11_17_19, 2905250003Sadrian ALL_TARGET_HT20_1_3_9_11_17_19, 2906250003Sadrian ALL_TARGET_HT20_1_3_9_11_17_19, 2907250003Sadrian ALL_TARGET_HT20_20, 2908250003Sadrian ALL_TARGET_HT20_21, 2909250003Sadrian ALL_TARGET_HT20_22, 2910250003Sadrian ALL_TARGET_HT20_23 2911250003Sadrian }; 2912250003Sadrian 2913250003Sadrian u_int8_t mcs_rate2power_table_index_ht40[24] = 2914250003Sadrian { 2915250003Sadrian ALL_TARGET_HT40_0_8_16, 2916250003Sadrian ALL_TARGET_HT40_1_3_9_11_17_19, 2917250003Sadrian ALL_TARGET_HT40_1_3_9_11_17_19, 2918250003Sadrian ALL_TARGET_HT40_1_3_9_11_17_19, 2919250003Sadrian ALL_TARGET_HT40_4, 2920250003Sadrian ALL_TARGET_HT40_5, 2921250003Sadrian ALL_TARGET_HT40_6, 2922250003Sadrian ALL_TARGET_HT40_7, 2923250003Sadrian ALL_TARGET_HT40_0_8_16, 2924250003Sadrian ALL_TARGET_HT40_1_3_9_11_17_19, 2925250003Sadrian ALL_TARGET_HT40_1_3_9_11_17_19, 2926250003Sadrian ALL_TARGET_HT40_1_3_9_11_17_19, 2927250003Sadrian ALL_TARGET_HT40_12, 2928250003Sadrian ALL_TARGET_HT40_13, 2929250003Sadrian ALL_TARGET_HT40_14, 2930250003Sadrian ALL_TARGET_HT40_15, 2931250003Sadrian ALL_TARGET_HT40_0_8_16, 2932250003Sadrian ALL_TARGET_HT40_1_3_9_11_17_19, 2933250003Sadrian ALL_TARGET_HT40_1_3_9_11_17_19, 2934250003Sadrian ALL_TARGET_HT40_1_3_9_11_17_19, 2935250003Sadrian ALL_TARGET_HT40_20, 2936250003Sadrian ALL_TARGET_HT40_21, 2937250003Sadrian ALL_TARGET_HT40_22, 2938250003Sadrian ALL_TARGET_HT40_23, 2939250003Sadrian }; 2940250003Sadrian 2941250003Sadrian HALDEBUG(ah, HAL_DEBUG_CALIBRATE, 2942250003Sadrian "%s[%d] +++chan %d,cfgctl 0x%04x " 2943250003Sadrian "antenna_reduction 0x%04x, twice_max_regulatory_power 0x%04x " 2944250003Sadrian "power_limit 0x%04x\n", 2945250008Sadrian __func__, __LINE__, ichan->channel, cfg_ctl, 2946250003Sadrian antenna_reduction, twice_max_regulatory_power, power_limit); 2947250008Sadrian ar9300_set_target_power_from_eeprom(ah, ichan->channel, target_power_val_t2); 2948250003Sadrian 2949250003Sadrian if (ar9300_eeprom_get(ahp, EEP_PAPRD_ENABLED)) { 2950250008Sadrian if (IEEE80211_IS_CHAN_2GHZ(chan)) { 2951250008Sadrian if (IEEE80211_IS_CHAN_HT40(chan)) { 2952250003Sadrian tmp_paprd_rate_mask = 2953250003Sadrian p_eep_data->modal_header_2g.paprd_rate_mask_ht40; 2954250003Sadrian tmp_ptr = &AH9300(ah)->ah_2g_paprd_rate_mask_ht40; 2955250003Sadrian } else { 2956250003Sadrian tmp_paprd_rate_mask = 2957250003Sadrian p_eep_data->modal_header_2g.paprd_rate_mask_ht20; 2958250003Sadrian tmp_ptr = &AH9300(ah)->ah_2g_paprd_rate_mask_ht20; 2959250003Sadrian } 2960250003Sadrian } else { 2961250008Sadrian if (IEEE80211_IS_CHAN_HT40(chan)) { 2962250003Sadrian tmp_paprd_rate_mask = 2963250003Sadrian p_eep_data->modal_header_5g.paprd_rate_mask_ht40; 2964250003Sadrian tmp_ptr = &AH9300(ah)->ah_5g_paprd_rate_mask_ht40; 2965250003Sadrian } else { 2966250003Sadrian tmp_paprd_rate_mask = 2967250003Sadrian p_eep_data->modal_header_5g.paprd_rate_mask_ht20; 2968250003Sadrian tmp_ptr = &AH9300(ah)->ah_5g_paprd_rate_mask_ht20; 2969250003Sadrian } 2970250003Sadrian } 2971250003Sadrian AH_PAPRD_GET_SCALE_FACTOR( 2972250008Sadrian paprd_scale_factor, p_eep_data, IEEE80211_IS_CHAN_2GHZ(chan), ichan->channel); 2973250003Sadrian HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s[%d] paprd_scale_factor %d\n", 2974250003Sadrian __func__, __LINE__, paprd_scale_factor); 2975250003Sadrian /* PAPRD is not done yet, Scale down the EEP power */ 2976250008Sadrian if (IEEE80211_IS_CHAN_HT40(chan)) { 2977250003Sadrian ptr_mcs_rate2power_table_index = 2978250003Sadrian &mcs_rate2power_table_index_ht40[0]; 2979250003Sadrian } else { 2980250003Sadrian ptr_mcs_rate2power_table_index = 2981250003Sadrian &mcs_rate2power_table_index_ht20[0]; 2982250003Sadrian } 2983250008Sadrian if (! ichan->paprd_table_write_done) { 2984250003Sadrian for (i = 0; i < 24; i++) { 2985250003Sadrian /* PAPRD is done yet, so Scale down Power for PAPRD Rates*/ 2986250003Sadrian if (tmp_paprd_rate_mask & (1 << i)) { 2987250003Sadrian target_power_val_t2[ptr_mcs_rate2power_table_index[i]] -= 2988250003Sadrian paprd_scale_factor; 2989250003Sadrian HALDEBUG(ah, HAL_DEBUG_CALIBRATE, 2990250003Sadrian "%s[%d]: Chan %d " 2991250003Sadrian "Scale down target_power_val_t2[%d] = 0x%04x\n", 2992250003Sadrian __func__, __LINE__, 2993250008Sadrian ichan->channel, i, target_power_val_t2[i]); 2994250003Sadrian } 2995250003Sadrian } 2996250003Sadrian } else { 2997250003Sadrian HALDEBUG(ah, HAL_DEBUG_CALIBRATE, 2998250003Sadrian "%s[%d]: PAPRD Done No TGT PWR Scaling\n", __func__, __LINE__); 2999250003Sadrian } 3000250003Sadrian } 3001250003Sadrian 3002250003Sadrian /* Save the Target power for future use */ 3003250003Sadrian OS_MEMCPY(target_power_val_t2_eep, target_power_val_t2, 3004250003Sadrian sizeof(target_power_val_t2)); 3005250003Sadrian ar9300_eeprom_set_power_per_rate_table(ah, p_eep_data, chan, 3006250003Sadrian target_power_val_t2, cfg_ctl, 3007250003Sadrian antenna_reduction, 3008250003Sadrian twice_max_regulatory_power, 3009250003Sadrian power_limit, 0); 3010250003Sadrian 3011250003Sadrian /* Save this for quick lookup */ 3012250008Sadrian ahp->reg_dmn = ath_hal_getctl(ah, chan); 3013250003Sadrian 3014250003Sadrian /* 3015250003Sadrian * Always use CDD/direct per rate power table for register based approach. 3016250003Sadrian * For FCC, CDD calculations should factor in the array gain, hence 3017250003Sadrian * this adjust call. ETSI and MKK does not have this requirement. 3018250003Sadrian */ 3019250003Sadrian if (is_reg_dmn_fcc(ahp->reg_dmn)) { 3020250008Sadrian HALDEBUG(ah, HAL_DEBUG_CALIBRATE, 3021250008Sadrian "%s: FCC regdomain, calling reg_txpower_cdd\n", 3022250008Sadrian __func__); 3023250003Sadrian ar9300_adjust_reg_txpower_cdd(ah, target_power_val_t2); 3024250003Sadrian } 3025250003Sadrian 3026250003Sadrian if (ar9300_eeprom_get(ahp, EEP_PAPRD_ENABLED)) { 3027250003Sadrian for (i = 0; i < ar9300_rate_size; i++) { 3028250003Sadrian /* 3029250003Sadrian * EEPROM TGT PWR is not same as current TGT PWR, 3030250003Sadrian * so Disable PAPRD for this rate. 3031250003Sadrian * Some of APs might ask to reduce Target Power, 3032250003Sadrian * if target power drops significantly, 3033250003Sadrian * disable PAPRD for that rate. 3034250003Sadrian */ 3035250003Sadrian if (tmp_paprd_rate_mask & (1 << i)) { 3036250003Sadrian if (ABS(target_power_val_t2_eep[i], target_power_val_t2[i]) > 3037250003Sadrian paprd_scale_factor) 3038250003Sadrian { 3039250003Sadrian tmp_paprd_rate_mask &= ~(1 << i); 3040250003Sadrian HALDEBUG(ah, HAL_DEBUG_CALIBRATE, 3041250003Sadrian "%s: EEP TPC[%02d] 0x%08x " 3042250003Sadrian "Curr TPC[%02d] 0x%08x mask = 0x%08x\n", 3043250003Sadrian __func__, i, target_power_val_t2_eep[i], i, 3044250003Sadrian target_power_val_t2[i], tmp_paprd_rate_mask); 3045250003Sadrian } 3046250003Sadrian } 3047250003Sadrian 3048250003Sadrian } 3049250003Sadrian HALDEBUG(ah, HAL_DEBUG_CALIBRATE, 3050250003Sadrian "%s: Chan %d After tmp_paprd_rate_mask = 0x%08x\n", 3051250008Sadrian __func__, ichan->channel, tmp_paprd_rate_mask); 3052250003Sadrian if (tmp_ptr) { 3053250003Sadrian *tmp_ptr = tmp_paprd_rate_mask; 3054250003Sadrian } 3055250003Sadrian } 3056250003Sadrian 3057250003Sadrian /* Write target power array to registers */ 3058250003Sadrian ar9300_transmit_power_reg_write(ah, target_power_val_t2); 3059250003Sadrian 3060250003Sadrian /* Write target power for self generated frames to the TPC register */ 3061250003Sadrian ar9300_selfgen_tpc_reg_write(ah, chan, target_power_val_t2); 3062250003Sadrian 3063250003Sadrian /* GreenTx or Paprd */ 3064250008Sadrian if (ah->ah_config.ath_hal_sta_update_tx_pwr_enable || 3065250008Sadrian AH_PRIVATE(ah)->ah_caps.halPaprdEnabled) 3066250003Sadrian { 3067250003Sadrian if (AR_SREV_POSEIDON(ah)) { 3068250003Sadrian /*For HAL_RSSI_TX_POWER_NONE array*/ 3069250003Sadrian OS_MEMCPY(ahp->ah_default_tx_power, 3070250003Sadrian target_power_val_t2, 3071250003Sadrian sizeof(target_power_val_t2)); 3072250003Sadrian /* Get defautl tx related register setting for GreenTx */ 3073250003Sadrian /* Record OB/DB */ 3074250008Sadrian ahp->ah_ob_db1[POSEIDON_STORED_REG_OBDB] = 3075250003Sadrian OS_REG_READ(ah, AR_PHY_65NM_CH0_TXRF2); 3076250003Sadrian /* Record TPC settting */ 3077250008Sadrian ahp->ah_ob_db1[POSEIDON_STORED_REG_TPC] = 3078250003Sadrian OS_REG_READ(ah, AR_TPC); 3079250003Sadrian /* Record BB_powertx_rate9 setting */ 3080250008Sadrian ahp->ah_ob_db1[POSEIDON_STORED_REG_BB_PWRTX_RATE9] = 3081250003Sadrian OS_REG_READ(ah, AR_PHY_BB_POWERTX_RATE9); 3082250003Sadrian } 3083250003Sadrian } 3084250003Sadrian 3085250003Sadrian /* 3086250003Sadrian * Return tx power used to iwconfig. 3087250003Sadrian * Since power is rate dependent, use one of the indices from the 3088250003Sadrian * AR9300_Rates enum to select an entry from target_power_val_t2[] 3089250003Sadrian * to report. 3090250003Sadrian * Currently returns the power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps 3091250003Sadrian * as CCK power is less interesting (?). 3092250003Sadrian */ 3093250003Sadrian i = ALL_TARGET_LEGACY_6_24; /* legacy */ 3094250008Sadrian if (IEEE80211_IS_CHAN_HT40(chan)) { 3095250003Sadrian i = ALL_TARGET_HT40_0_8_16; /* ht40 */ 3096250008Sadrian } else if (IEEE80211_IS_CHAN_HT20(chan)) { 3097250003Sadrian i = ALL_TARGET_HT20_0_8_16; /* ht20 */ 3098250003Sadrian } 3099250003Sadrian max_power_level = target_power_val_t2[i]; 3100250003Sadrian /* Adjusting the ah_max_power_level based on chains and antennaGain*/ 3101278741Sadrian switch (ar9300_get_ntxchains(((ahp->ah_tx_chainmaskopt > 0) ? 3102278741Sadrian ahp->ah_tx_chainmaskopt : ahp->ah_tx_chainmask))) 3103250003Sadrian { 3104250003Sadrian case 1: 3105250003Sadrian break; 3106250003Sadrian case 2: 3107250003Sadrian twice_array_gain = (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? 0: 3108250003Sadrian ((int16_t)AH_MIN((ahp->twice_antenna_reduction - 3109250003Sadrian (ahp->twice_antenna_gain + INCREASE_MAXPOW_BY_TWO_CHAIN)), 0)); 3110250003Sadrian /* Adjusting maxpower with antennaGain */ 3111250003Sadrian max_power_level -= twice_array_gain; 3112250003Sadrian /* Adjusting maxpower based on chain */ 3113250003Sadrian max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; 3114250003Sadrian break; 3115250003Sadrian case 3: 3116250003Sadrian twice_array_gain = (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? 0: 3117250003Sadrian ((int16_t)AH_MIN((ahp->twice_antenna_reduction - 3118250003Sadrian (ahp->twice_antenna_gain + INCREASE_MAXPOW_BY_THREE_CHAIN)), 0)); 3119250003Sadrian 3120250003Sadrian /* Adjusting maxpower with antennaGain */ 3121250003Sadrian max_power_level -= twice_array_gain; 3122250003Sadrian /* Adjusting maxpower based on chain */ 3123250003Sadrian max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; 3124250003Sadrian break; 3125250003Sadrian default: 3126250003Sadrian HALASSERT(0); /* Unsupported number of chains */ 3127250003Sadrian } 3128250008Sadrian AH_PRIVATE(ah)->ah_maxPowerLevel = (int8_t)max_power_level; 3129250003Sadrian 3130250008Sadrian ar9300_calibration_apply(ah, ichan->channel); 3131250003Sadrian#undef ABS 3132250003Sadrian 3133250003Sadrian /* Handle per packet TPC initializations */ 3134250008Sadrian if (ah->ah_config.ath_hal_desc_tpc) { 3135250003Sadrian /* Transmit Power per-rate per-chain are computed here. A separate 3136250003Sadrian * power table is maintained for different MIMO modes (i.e. TXBF ON, 3137250003Sadrian * STBC) to enable easy lookup during packet transmit. 3138250003Sadrian * The reason for maintaing each of these tables per chain is that 3139250003Sadrian * the transmit power used for different number of chains is different 3140250003Sadrian * depending on whether the power has been limited by the target power, 3141250003Sadrian * the regulatory domain or the CTL limits. 3142250003Sadrian */ 3143250003Sadrian u_int mode = ath_hal_get_curmode(ah, chan); 3144250003Sadrian u_int32_t val = 0; 3145250003Sadrian u_int8_t chainmasks[AR9300_MAX_CHAINS] = 3146250003Sadrian {OSPREY_1_CHAINMASK, OSPREY_2LOHI_CHAINMASK, OSPREY_3_CHAINMASK}; 3147250003Sadrian for (i = 0; i < AR9300_MAX_CHAINS; i++) { 3148250003Sadrian OS_MEMCPY(target_power_val_t2, target_power_val_t2_eep, 3149250003Sadrian sizeof(target_power_val_t2_eep)); 3150250003Sadrian ar9300_eeprom_set_power_per_rate_table(ah, p_eep_data, chan, 3151250003Sadrian target_power_val_t2, cfg_ctl, 3152250003Sadrian antenna_reduction, 3153250003Sadrian twice_max_regulatory_power, 3154250003Sadrian power_limit, chainmasks[i]); 3155250003Sadrian HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, 3156250003Sadrian " Channel = %d Chainmask = %d, Upper Limit = [%2d.%1d dBm]\n", 3157250008Sadrian ichan->channel, i, ahp->upper_limit[i]/2, 3158250003Sadrian ahp->upper_limit[i]%2 * 5); 3159250003Sadrian ar9300_init_rate_txpower(ah, mode, chan, target_power_val_t2, 3160250003Sadrian chainmasks[i]); 3161250003Sadrian 3162250003Sadrian } 3163250003Sadrian 3164250003Sadrian /* Enable TPC */ 3165250003Sadrian OS_REG_WRITE(ah, AR_PHY_PWRTX_MAX, AR_PHY_PWRTX_MAX_TPC_ENABLE); 3166250003Sadrian /* 3167250003Sadrian * Disable per chain power reduction since we are already 3168250003Sadrian * accounting for this in our calculations 3169250003Sadrian */ 3170250003Sadrian val = OS_REG_READ(ah, AR_PHY_POWER_TX_SUB); 3171250003Sadrian if (AR_SREV_WASP(ah)) { 3172250003Sadrian OS_REG_WRITE(ah, AR_PHY_POWER_TX_SUB, 3173250003Sadrian val & AR_PHY_POWER_TX_SUB_2_DISABLE); 3174250003Sadrian } else { 3175250003Sadrian OS_REG_WRITE(ah, AR_PHY_POWER_TX_SUB, 3176250003Sadrian val & AR_PHY_POWER_TX_SUB_3_DISABLE); 3177250003Sadrian } 3178250003Sadrian } 3179250003Sadrian 3180250003Sadrian return HAL_OK; 3181250003Sadrian} 3182250003Sadrian 3183250003Sadrian/************************************************************** 3184250003Sadrian * ar9300_eeprom_set_addac 3185250003Sadrian * 3186250003Sadrian * Set the ADDAC from eeprom. 3187250003Sadrian */ 3188250003Sadrianvoid 3189250008Sadrianar9300_eeprom_set_addac(struct ath_hal *ah, struct ieee80211_channel *chan) 3190250003Sadrian{ 3191250003Sadrian 3192250003Sadrian HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, 3193250003Sadrian "FIXME: ar9300_eeprom_def_set_addac called\n"); 3194250003Sadrian#if 0 3195250003Sadrian MODAL_EEPDEF_HEADER *p_modal; 3196250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 3197250003Sadrian ar9300_eeprom_t *eep = &ahp->ah_eeprom.def; 3198250003Sadrian u_int8_t biaslevel; 3199250003Sadrian 3200250003Sadrian if (AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_SOWL) { 3201250003Sadrian return; 3202250003Sadrian } 3203250003Sadrian 3204250003Sadrian HALASSERT(owl_get_eepdef_ver(ahp) == AR9300_EEP_VER); 3205250003Sadrian 3206250003Sadrian /* Xpa bias levels in eeprom are valid from rev 14.7 */ 3207250003Sadrian if (owl_get_eepdef_rev(ahp) < AR9300_EEP_MINOR_VER_7) { 3208250003Sadrian return; 3209250003Sadrian } 3210250003Sadrian 3211250003Sadrian if (ahp->ah_emu_eeprom) { 3212250003Sadrian return; 3213250003Sadrian } 3214250003Sadrian 3215250008Sadrian p_modal = &(eep->modal_header[IEEE80211_IS_CHAN_2GHZ(chan)]); 3216250003Sadrian 3217250003Sadrian if (p_modal->xpa_bias_lvl != 0xff) { 3218250003Sadrian biaslevel = p_modal->xpa_bias_lvl; 3219250003Sadrian } else { 3220250003Sadrian /* Use freqeuncy specific xpa bias level */ 3221250003Sadrian u_int16_t reset_freq_bin, freq_bin, freq_count = 0; 3222250003Sadrian CHAN_CENTERS centers; 3223250003Sadrian 3224250003Sadrian ar9300_get_channel_centers(ah, chan, ¢ers); 3225250003Sadrian 3226250008Sadrian reset_freq_bin = FREQ2FBIN(centers.synth_center, IEEE80211_IS_CHAN_2GHZ(chan)); 3227250003Sadrian freq_bin = p_modal->xpa_bias_lvl_freq[0] & 0xff; 3228250003Sadrian biaslevel = (u_int8_t)(p_modal->xpa_bias_lvl_freq[0] >> 14); 3229250003Sadrian 3230250003Sadrian freq_count++; 3231250003Sadrian 3232250003Sadrian while (freq_count < 3) { 3233250003Sadrian if (p_modal->xpa_bias_lvl_freq[freq_count] == 0x0) { 3234250003Sadrian break; 3235250003Sadrian } 3236250003Sadrian 3237250003Sadrian freq_bin = p_modal->xpa_bias_lvl_freq[freq_count] & 0xff; 3238250003Sadrian if (reset_freq_bin >= freq_bin) { 3239250003Sadrian biaslevel = 3240250003Sadrian (u_int8_t)(p_modal->xpa_bias_lvl_freq[freq_count] >> 14); 3241250003Sadrian } else { 3242250003Sadrian break; 3243250003Sadrian } 3244250003Sadrian freq_count++; 3245250003Sadrian } 3246250003Sadrian } 3247250003Sadrian 3248250003Sadrian /* Apply bias level to the ADDAC values in the INI array */ 3249250008Sadrian if (IEEE80211_IS_CHAN_2GHZ(chan)) { 3250250003Sadrian INI_RA(&ahp->ah_ini_addac, 7, 1) = 3251250003Sadrian (INI_RA(&ahp->ah_ini_addac, 7, 1) & (~0x18)) | biaslevel << 3; 3252250003Sadrian } else { 3253250003Sadrian INI_RA(&ahp->ah_ini_addac, 6, 1) = 3254250003Sadrian (INI_RA(&ahp->ah_ini_addac, 6, 1) & (~0xc0)) | biaslevel << 6; 3255250003Sadrian } 3256250003Sadrian#endif 3257250003Sadrian} 3258250003Sadrian 3259250003Sadrianu_int 3260250003Sadrianar9300_eeprom_dump_support(struct ath_hal *ah, void **pp_e) 3261250003Sadrian{ 3262250003Sadrian *pp_e = &(AH9300(ah)->ah_eeprom); 3263250003Sadrian return sizeof(ar9300_eeprom_t); 3264250003Sadrian} 3265250003Sadrian 3266250003Sadrianu_int8_t 3267250003Sadrianar9300_eeprom_get_num_ant_config(struct ath_hal_9300 *ahp, 3268250003Sadrian HAL_FREQ_BAND freq_band) 3269250003Sadrian{ 3270250003Sadrian#if 0 3271250003Sadrian ar9300_eeprom_t *eep = &ahp->ah_eeprom.def; 3272250003Sadrian MODAL_EEPDEF_HEADER *p_modal = 3273250003Sadrian &(eep->modal_header[HAL_FREQ_BAND_2GHZ == freq_band]); 3274250003Sadrian BASE_EEPDEF_HEADER *p_base = &eep->base_eep_header; 3275250003Sadrian u_int8_t num_ant_config; 3276250003Sadrian 3277250003Sadrian num_ant_config = 1; /* default antenna configuration */ 3278250003Sadrian 3279250003Sadrian if (p_base->version >= 0x0E0D) { 3280250003Sadrian if (p_modal->use_ant1) { 3281250003Sadrian num_ant_config += 1; 3282250003Sadrian } 3283250003Sadrian } 3284250003Sadrian 3285250003Sadrian return num_ant_config; 3286250003Sadrian#else 3287250003Sadrian return 1; 3288250003Sadrian#endif 3289250003Sadrian} 3290250003Sadrian 3291250003SadrianHAL_STATUS 3292250008Sadrianar9300_eeprom_get_ant_cfg(struct ath_hal_9300 *ahp, 3293250008Sadrian const struct ieee80211_channel *chan, 3294250008Sadrian u_int8_t index, u_int16_t *config) 3295250003Sadrian{ 3296250003Sadrian#if 0 3297250003Sadrian ar9300_eeprom_t *eep = &ahp->ah_eeprom.def; 3298250008Sadrian MODAL_EEPDEF_HEADER *p_modal = &(eep->modal_header[IEEE80211_IS_CHAN_2GHZ(chan)]); 3299250003Sadrian BASE_EEPDEF_HEADER *p_base = &eep->base_eep_header; 3300250003Sadrian 3301250003Sadrian switch (index) { 3302250003Sadrian case 0: 3303250003Sadrian *config = p_modal->ant_ctrl_common & 0xFFFF; 3304250003Sadrian return HAL_OK; 3305250003Sadrian case 1: 3306250003Sadrian if (p_base->version >= 0x0E0D) { 3307250003Sadrian if (p_modal->use_ant1) { 3308250003Sadrian *config = ((p_modal->ant_ctrl_common & 0xFFFF0000) >> 16); 3309250003Sadrian return HAL_OK; 3310250003Sadrian } 3311250003Sadrian } 3312250003Sadrian break; 3313250003Sadrian default: 3314250003Sadrian break; 3315250003Sadrian } 3316250003Sadrian#endif 3317250003Sadrian return HAL_EINVAL; 3318250003Sadrian} 3319250003Sadrian 3320250003Sadrianu_int8_t* 3321250003Sadrianar9300_eeprom_get_cust_data(struct ath_hal_9300 *ahp) 3322250003Sadrian{ 3323250003Sadrian return (u_int8_t *)ahp; 3324250003Sadrian} 3325250003Sadrian 3326250003Sadrian#ifdef UNUSED 3327250003Sadrianstatic inline HAL_STATUS 3328250003Sadrianar9300_check_eeprom(struct ath_hal *ah) 3329250003Sadrian{ 3330250003Sadrian#if 0 3331250003Sadrian u_int32_t sum = 0, el; 3332250003Sadrian u_int16_t *eepdata; 3333250003Sadrian int i; 3334250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 3335250003Sadrian HAL_BOOL need_swap = AH_FALSE; 3336250003Sadrian ar9300_eeprom_t *eep = (ar9300_eeprom_t *)&ahp->ah_eeprom.def; 3337250003Sadrian u_int16_t magic, magic2; 3338250003Sadrian int addr; 3339250003Sadrian u_int16_t temp; 3340250003Sadrian 3341250003Sadrian /* 3342250003Sadrian ** We need to check the EEPROM data regardless of if it's in flash or 3343250003Sadrian ** in EEPROM. 3344250003Sadrian */ 3345250003Sadrian 3346250003Sadrian if (!ahp->ah_priv.priv.ah_eeprom_read( 3347250003Sadrian ah, AR9300_EEPROM_MAGIC_OFFSET, &magic)) 3348250003Sadrian { 3349250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Reading Magic # failed\n", __func__); 3350250003Sadrian return AH_FALSE; 3351250003Sadrian } 3352250003Sadrian 3353250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Read Magic = 0x%04X\n", __func__, magic); 3354250003Sadrian 3355250003Sadrian if (!ar9300_eep_data_in_flash(ah)) { 3356250003Sadrian 3357250003Sadrian if (magic != AR9300_EEPROM_MAGIC) { 3358250003Sadrian magic2 = SWAP16(magic); 3359250003Sadrian 3360250003Sadrian if (magic2 == AR9300_EEPROM_MAGIC) { 3361250003Sadrian need_swap = AH_TRUE; 3362250003Sadrian eepdata = (u_int16_t *)(&ahp->ah_eeprom); 3363250003Sadrian 3364250003Sadrian for (addr = 0; 3365250003Sadrian addr < sizeof(ar9300_eeprom_t) / sizeof(u_int16_t); 3366250003Sadrian addr++) 3367250003Sadrian { 3368250003Sadrian temp = SWAP16(*eepdata); 3369250003Sadrian *eepdata = temp; 3370250003Sadrian eepdata++; 3371250003Sadrian 3372250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM_DUMP, "0x%04X ", *eepdata); 3373250003Sadrian if (((addr + 1) % 6) == 0) { 3374250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM_DUMP, "\n"); 3375250003Sadrian } 3376250003Sadrian } 3377250003Sadrian } else { 3378250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 3379250003Sadrian "Invalid EEPROM Magic. endianness missmatch.\n"); 3380250003Sadrian return HAL_EEBADSUM; 3381250003Sadrian } 3382250003Sadrian } 3383250003Sadrian } else { 3384250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 3385250003Sadrian "EEPROM being read from flash @0x%p\n", AH_PRIVATE(ah)->ah_st); 3386250003Sadrian } 3387250003Sadrian 3388250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, "need_swap = %s.\n", need_swap?"True":"False"); 3389250003Sadrian 3390250003Sadrian if (need_swap) { 3391250003Sadrian el = SWAP16(ahp->ah_eeprom.def.base_eep_header.length); 3392250003Sadrian } else { 3393250003Sadrian el = ahp->ah_eeprom.def.base_eep_header.length; 3394250003Sadrian } 3395250003Sadrian 3396250003Sadrian eepdata = (u_int16_t *)(&ahp->ah_eeprom.def); 3397250003Sadrian for (i = 0; 3398250003Sadrian i < AH_MIN(el, sizeof(ar9300_eeprom_t)) / sizeof(u_int16_t); 3399250003Sadrian i++) { 3400250003Sadrian sum ^= *eepdata++; 3401250003Sadrian } 3402250003Sadrian 3403250003Sadrian if (need_swap) { 3404250003Sadrian /* 3405250003Sadrian * preddy: EEPROM endianness does not match. So change it 3406250003Sadrian * 8bit values in eeprom data structure does not need to be swapped 3407250003Sadrian * Only >8bits (16 & 32) values need to be swapped 3408250003Sadrian * If a new 16 or 32 bit field is added to the EEPROM contents, 3409250003Sadrian * please make sure to swap the field here 3410250003Sadrian */ 3411250003Sadrian u_int32_t integer, j; 3412250003Sadrian u_int16_t word; 3413250003Sadrian 3414250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 3415250003Sadrian "EEPROM Endianness is not native.. Changing \n"); 3416250003Sadrian 3417250003Sadrian /* convert Base Eep header */ 3418250003Sadrian word = SWAP16(eep->base_eep_header.length); 3419250003Sadrian eep->base_eep_header.length = word; 3420250003Sadrian 3421250003Sadrian word = SWAP16(eep->base_eep_header.checksum); 3422250003Sadrian eep->base_eep_header.checksum = word; 3423250003Sadrian 3424250003Sadrian word = SWAP16(eep->base_eep_header.version); 3425250003Sadrian eep->base_eep_header.version = word; 3426250003Sadrian 3427250003Sadrian word = SWAP16(eep->base_eep_header.reg_dmn[0]); 3428250003Sadrian eep->base_eep_header.reg_dmn[0] = word; 3429250003Sadrian 3430250003Sadrian word = SWAP16(eep->base_eep_header.reg_dmn[1]); 3431250003Sadrian eep->base_eep_header.reg_dmn[1] = word; 3432250003Sadrian 3433250003Sadrian word = SWAP16(eep->base_eep_header.rf_silent); 3434250003Sadrian eep->base_eep_header.rf_silent = word; 3435250003Sadrian 3436250003Sadrian word = SWAP16(eep->base_eep_header.blue_tooth_options); 3437250003Sadrian eep->base_eep_header.blue_tooth_options = word; 3438250003Sadrian 3439250003Sadrian word = SWAP16(eep->base_eep_header.device_cap); 3440250003Sadrian eep->base_eep_header.device_cap = word; 3441250003Sadrian 3442250003Sadrian /* convert Modal Eep header */ 3443250003Sadrian for (j = 0; j < ARRAY_LENGTH(eep->modal_header); j++) { 3444250003Sadrian MODAL_EEPDEF_HEADER *p_modal = &eep->modal_header[j]; 3445250003Sadrian integer = SWAP32(p_modal->ant_ctrl_common); 3446250003Sadrian p_modal->ant_ctrl_common = integer; 3447250003Sadrian 3448250003Sadrian for (i = 0; i < AR9300_MAX_CHAINS; i++) { 3449250003Sadrian integer = SWAP32(p_modal->ant_ctrl_chain[i]); 3450250003Sadrian p_modal->ant_ctrl_chain[i] = integer; 3451250003Sadrian } 3452250003Sadrian 3453250003Sadrian for (i = 0; i < AR9300_EEPROM_MODAL_SPURS; i++) { 3454250003Sadrian word = SWAP16(p_modal->spur_chans[i].spur_chan); 3455250003Sadrian p_modal->spur_chans[i].spur_chan = word; 3456250003Sadrian } 3457250003Sadrian } 3458250003Sadrian } 3459250003Sadrian 3460250003Sadrian /* Check CRC - Attach should fail on a bad checksum */ 3461250003Sadrian if (sum != 0xffff || owl_get_eepdef_ver(ahp) != AR9300_EEP_VER || 3462250003Sadrian owl_get_eepdef_rev(ahp) < AR9300_EEP_NO_BACK_VER) { 3463250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 3464250003Sadrian "Bad EEPROM checksum 0x%x or revision 0x%04x\n", 3465250003Sadrian sum, owl_get_eepdef_ver(ahp)); 3466250003Sadrian return HAL_EEBADSUM; 3467250003Sadrian } 3468250003Sadrian#ifdef EEPROM_DUMP 3469250003Sadrian ar9300_eeprom_def_dump(ah, eep); 3470250003Sadrian#endif 3471250003Sadrian 3472250003Sadrian#if 0 3473250003Sadrian#ifdef AH_AR9300_OVRD_TGT_PWR 3474250003Sadrian 3475250003Sadrian /* 3476250003Sadrian * 14.4 EEPROM contains low target powers. 3477250003Sadrian * Hardcode until EEPROM > 14.4 3478250003Sadrian */ 3479250003Sadrian if (owl_get_eepdef_ver(ahp) == 14 && owl_get_eepdef_rev(ahp) <= 4) { 3480250003Sadrian MODAL_EEPDEF_HEADER *p_modal; 3481250003Sadrian 3482250003Sadrian#ifdef EEPROM_DUMP 3483250003Sadrian HALDEBUG(ah, HAL_DEBUG_POWER_OVERRIDE, "Original Target Powers\n"); 3484250003Sadrian ar9300_eep_def_dump_tgt_power(ah, eep); 3485250003Sadrian#endif 3486250003Sadrian HALDEBUG(ah, HAL_DEBUG_POWER_OVERRIDE, 3487250003Sadrian "Override Target Powers. EEPROM Version is %d.%d, " 3488250003Sadrian "Device Type %d\n", 3489250003Sadrian owl_get_eepdef_ver(ahp), 3490250003Sadrian owl_get_eepdef_rev(ahp), 3491250003Sadrian eep->base_eep_header.device_type); 3492250003Sadrian 3493250003Sadrian 3494250003Sadrian ar9300_eep_def_override_tgt_power(ah, eep); 3495250003Sadrian 3496250003Sadrian if (eep->base_eep_header.device_type == 5) { 3497250003Sadrian /* for xb72 only: improve transmit EVM for interop */ 3498250003Sadrian p_modal = &eep->modal_header[1]; 3499250003Sadrian p_modal->tx_frame_to_data_start = 0x23; 3500250003Sadrian p_modal->tx_frame_to_xpa_on = 0x23; 3501250003Sadrian p_modal->tx_frame_to_pa_on = 0x23; 3502250003Sadrian } 3503250003Sadrian 3504250003Sadrian#ifdef EEPROM_DUMP 3505250003Sadrian HALDEBUG(ah, HAL_DEBUG_POWER_OVERRIDE, "Modified Target Powers\n"); 3506250003Sadrian ar9300_eep_def_dump_tgt_power(ah, eep); 3507250003Sadrian#endif 3508250003Sadrian } 3509250003Sadrian#endif /* AH_AR9300_OVRD_TGT_PWR */ 3510250003Sadrian#endif 3511250003Sadrian#endif 3512250003Sadrian return HAL_OK; 3513250003Sadrian} 3514250003Sadrian#endif 3515250003Sadrian 3516250003Sadrianstatic u_int16_t 3517250008Sadrianar9300_eeprom_get_spur_chan(struct ath_hal *ah, int i, HAL_BOOL is_2ghz) 3518250003Sadrian{ 3519250003Sadrian u_int16_t spur_val = AR_NO_SPUR; 3520250003Sadrian#if 0 3521250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 3522250003Sadrian ar9300_eeprom_t *eep = (ar9300_eeprom_t *)&ahp->ah_eeprom; 3523250003Sadrian 3524250003Sadrian HALASSERT(i < AR_EEPROM_MODAL_SPURS ); 3525250003Sadrian 3526250003Sadrian HALDEBUG(ah, HAL_DEBUG_ANI, 3527250003Sadrian "Getting spur idx %d is2Ghz. %d val %x\n", 3528250003Sadrian i, is_2ghz, 3529250003Sadrian AH_PRIVATE(ah)->ah_config.ath_hal_spur_chans[i][is_2ghz]); 3530250003Sadrian 3531250003Sadrian switch (AH_PRIVATE(ah)->ah_config.ath_hal_spur_mode) { 3532250003Sadrian case SPUR_DISABLE: 3533250003Sadrian /* returns AR_NO_SPUR */ 3534250003Sadrian break; 3535250003Sadrian case SPUR_ENABLE_IOCTL: 3536250003Sadrian spur_val = AH_PRIVATE(ah)->ah_config.ath_hal_spur_chans[i][is_2ghz]; 3537250003Sadrian HALDEBUG(ah, HAL_DEBUG_ANI, 3538250003Sadrian "Getting spur val from new loc. %d\n", spur_val); 3539250003Sadrian break; 3540250003Sadrian case SPUR_ENABLE_EEPROM: 3541250003Sadrian spur_val = eep->modal_header[is_2ghz].spur_chans[i].spur_chan; 3542250003Sadrian break; 3543250003Sadrian 3544250003Sadrian } 3545250003Sadrian#endif 3546250003Sadrian return spur_val; 3547250003Sadrian} 3548250003Sadrian 3549250003Sadrian#ifdef UNUSED 3550250003Sadrianstatic inline HAL_BOOL 3551250003Sadrianar9300_fill_eeprom(struct ath_hal *ah) 3552250003Sadrian{ 3553250003Sadrian return ar9300_eeprom_restore(ah); 3554250003Sadrian} 3555250003Sadrian#endif 3556250003Sadrian 3557250003Sadrianu_int16_t 3558250003Sadrianar9300_eeprom_struct_size(void) 3559250003Sadrian{ 3560250003Sadrian return sizeof(ar9300_eeprom_t); 3561250003Sadrian} 3562250003Sadrian 3563250003Sadrianint ar9300_eeprom_struct_default_many(void) 3564250003Sadrian{ 3565250003Sadrian return ARRAY_LENGTH(default9300); 3566250003Sadrian} 3567250003Sadrian 3568250003Sadrian 3569250003Sadrianar9300_eeprom_t * 3570250003Sadrianar9300_eeprom_struct_default(int default_index) 3571250003Sadrian{ 3572250003Sadrian if (default_index >= 0 && 3573250003Sadrian default_index < ARRAY_LENGTH(default9300)) 3574250003Sadrian { 3575250003Sadrian return default9300[default_index]; 3576250003Sadrian } else { 3577250003Sadrian return 0; 3578250003Sadrian } 3579250003Sadrian} 3580250003Sadrian 3581250003Sadrianar9300_eeprom_t * 3582250003Sadrianar9300_eeprom_struct_default_find_by_id(int id) 3583250003Sadrian{ 3584250003Sadrian int it; 3585250003Sadrian 3586250003Sadrian for (it = 0; it < ARRAY_LENGTH(default9300); it++) { 3587250003Sadrian if (default9300[it] != 0 && default9300[it]->template_version == id) { 3588250003Sadrian return default9300[it]; 3589250003Sadrian } 3590250003Sadrian } 3591250003Sadrian return 0; 3592250003Sadrian} 3593250003Sadrian 3594250003Sadrian 3595250003SadrianHAL_BOOL 3596250003Sadrianar9300_calibration_data_read_flash(struct ath_hal *ah, long address, 3597250003Sadrian u_int8_t *buffer, int many) 3598250003Sadrian{ 3599250003Sadrian 3600250003Sadrian if (((address) < 0) || ((address + many) > AR9300_EEPROM_SIZE - 1)) { 3601250003Sadrian return AH_FALSE; 3602250003Sadrian } 3603250003Sadrian return AH_FALSE; 3604250003Sadrian} 3605250003Sadrian 3606250003SadrianHAL_BOOL 3607250003Sadrianar9300_calibration_data_read_eeprom(struct ath_hal *ah, long address, 3608250003Sadrian u_int8_t *buffer, int many) 3609250003Sadrian{ 3610250003Sadrian int i; 3611250003Sadrian u_int8_t value[2]; 3612250003Sadrian unsigned long eep_addr; 3613250003Sadrian unsigned long byte_addr; 3614250003Sadrian u_int16_t *svalue; 3615250003Sadrian 3616250003Sadrian if (((address) < 0) || ((address + many) > AR9300_EEPROM_SIZE)) { 3617250003Sadrian return AH_FALSE; 3618250003Sadrian } 3619250003Sadrian 3620250003Sadrian for (i = 0; i < many; i++) { 3621250003Sadrian eep_addr = (u_int16_t) (address + i) / 2; 3622250003Sadrian byte_addr = (u_int16_t) (address + i) % 2; 3623250003Sadrian svalue = (u_int16_t *) value; 3624250008Sadrian if (! ath_hal_eepromRead(ah, eep_addr, svalue)) { 3625250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 3626250003Sadrian "%s: Unable to read eeprom region \n", __func__); 3627250003Sadrian return AH_FALSE; 3628250003Sadrian } 3629250003Sadrian buffer[i] = (*svalue >> (8 * byte_addr)) & 0xff; 3630250003Sadrian } 3631250003Sadrian return AH_TRUE; 3632250003Sadrian} 3633250003Sadrian 3634250003SadrianHAL_BOOL 3635250003Sadrianar9300_calibration_data_read_otp(struct ath_hal *ah, long address, 3636250003Sadrian u_int8_t *buffer, int many, HAL_BOOL is_wifi) 3637250003Sadrian{ 3638250003Sadrian int i; 3639250003Sadrian unsigned long eep_addr; 3640250003Sadrian unsigned long byte_addr; 3641250003Sadrian u_int32_t svalue; 3642250003Sadrian 3643250003Sadrian if (((address) < 0) || ((address + many) > 0x400)) { 3644250003Sadrian return AH_FALSE; 3645250003Sadrian } 3646250003Sadrian 3647250003Sadrian for (i = 0; i < many; i++) { 3648250003Sadrian eep_addr = (u_int16_t) (address + i) / 4; /* otp is 4 bytes long???? */ 3649250003Sadrian byte_addr = (u_int16_t) (address + i) % 4; 3650250003Sadrian if (!ar9300_otp_read(ah, eep_addr, &svalue, is_wifi)) { 3651250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 3652250003Sadrian "%s: Unable to read otp region \n", __func__); 3653250003Sadrian return AH_FALSE; 3654250003Sadrian } 3655250003Sadrian buffer[i] = (svalue >> (8 * byte_addr)) & 0xff; 3656250003Sadrian } 3657250003Sadrian return AH_TRUE; 3658250003Sadrian} 3659250003Sadrian 3660250003Sadrian#ifdef ATH_CAL_NAND_FLASH 3661250003SadrianHAL_BOOL 3662250003Sadrianar9300_calibration_data_read_nand(struct ath_hal *ah, long address, 3663250003Sadrian u_int8_t *buffer, int many) 3664250003Sadrian{ 3665250003Sadrian int ret_len; 3666250003Sadrian int ret_val = 1; 3667250003Sadrian 3668250003Sadrian /* Calling OS based API to read NAND */ 3669250003Sadrian ret_val = OS_NAND_FLASH_READ(ATH_CAL_NAND_PARTITION, address, many, &ret_len, buffer); 3670250003Sadrian 3671250003Sadrian return (ret_val ? AH_FALSE: AH_TRUE); 3672250003Sadrian} 3673250003Sadrian#endif 3674250003Sadrian 3675250003SadrianHAL_BOOL 3676250003Sadrianar9300_calibration_data_read(struct ath_hal *ah, long address, 3677250003Sadrian u_int8_t *buffer, int many) 3678250003Sadrian{ 3679250003Sadrian switch (AH9300(ah)->calibration_data_source) { 3680250003Sadrian case calibration_data_flash: 3681250003Sadrian return ar9300_calibration_data_read_flash(ah, address, buffer, many); 3682250003Sadrian case calibration_data_eeprom: 3683250003Sadrian return ar9300_calibration_data_read_eeprom(ah, address, buffer, many); 3684250003Sadrian case calibration_data_otp: 3685250003Sadrian return ar9300_calibration_data_read_otp(ah, address, buffer, many, 1); 3686250003Sadrian#ifdef ATH_CAL_NAND_FLASH 3687250003Sadrian case calibration_data_nand: 3688250003Sadrian return ar9300_calibration_data_read_nand(ah,address,buffer,many); 3689250003Sadrian#endif 3690250003Sadrian 3691250003Sadrian } 3692250003Sadrian return AH_FALSE; 3693250003Sadrian} 3694250003Sadrian 3695250003Sadrian 3696250003SadrianHAL_BOOL 3697250003Sadrianar9300_calibration_data_read_array(struct ath_hal *ah, int address, 3698250003Sadrian u_int8_t *buffer, int many) 3699250003Sadrian{ 3700250003Sadrian int it; 3701250003Sadrian 3702250003Sadrian for (it = 0; it < many; it++) { 3703250003Sadrian (void)ar9300_calibration_data_read(ah, address - it, buffer + it, 1); 3704250003Sadrian } 3705250003Sadrian return AH_TRUE; 3706250003Sadrian} 3707250003Sadrian 3708250003Sadrian 3709250003Sadrian/* 3710250003Sadrian * the address where the first configuration block is written 3711250003Sadrian */ 3712250003Sadrianstatic const int base_address = 0x3ff; /* 1KB */ 3713250003Sadrianstatic const int base_address_512 = 0x1ff; /* 512Bytes */ 3714250003Sadrian 3715250003Sadrian/* 3716250003Sadrian * the address where the NAND first configuration block is written 3717250003Sadrian */ 3718250003Sadrian#ifdef ATH_CAL_NAND_FLASH 3719250003Sadrianstatic const int base_address_nand = AR9300_FLASH_CAL_START_OFFSET; 3720250003Sadrian#endif 3721250003Sadrian 3722250003Sadrian 3723250003Sadrian/* 3724250003Sadrian * the lower limit on configuration data 3725250003Sadrian */ 3726250003Sadrianstatic const int low_limit = 0x040; 3727250003Sadrian 3728250003Sadrian/* 3729250003Sadrian * returns size of the physical eeprom in bytes. 3730250003Sadrian * 1024 and 2048 are normal sizes. 3731250003Sadrian * 0 means there is no eeprom. 3732250003Sadrian */ 3733250003Sadrianint32_t 3734250003Sadrianar9300_eeprom_size(struct ath_hal *ah) 3735250003Sadrian{ 3736250003Sadrian u_int16_t data; 3737250003Sadrian /* 3738250003Sadrian * first we'll try for 4096 bytes eeprom 3739250003Sadrian */ 3740250003Sadrian if (ar9300_eeprom_read_word(ah, 2047, &data)) { 3741250003Sadrian if (data != 0) { 3742250003Sadrian return 4096; 3743250003Sadrian } 3744250003Sadrian } 3745250003Sadrian /* 3746250003Sadrian * then we'll try for 2048 bytes eeprom 3747250003Sadrian */ 3748250003Sadrian if (ar9300_eeprom_read_word(ah, 1023, &data)) { 3749250003Sadrian if (data != 0) { 3750250003Sadrian return 2048; 3751250003Sadrian } 3752250003Sadrian } 3753250003Sadrian /* 3754250003Sadrian * then we'll try for 1024 bytes eeprom 3755250003Sadrian */ 3756250003Sadrian if (ar9300_eeprom_read_word(ah, 511, &data)) { 3757250003Sadrian if (data != 0) { 3758250003Sadrian return 1024; 3759250003Sadrian } 3760250003Sadrian } 3761250003Sadrian return 0; 3762250003Sadrian} 3763250003Sadrian 3764250003Sadrian/* 3765250003Sadrian * returns size of the physical otp in bytes. 3766250003Sadrian * 1024 and 2048 are normal sizes. 3767250003Sadrian * 0 means there is no eeprom. 3768250003Sadrian */ 3769250003Sadrianint32_t 3770250003Sadrianar9300_otp_size(struct ath_hal *ah) 3771250003Sadrian{ 3772250003Sadrian if (AR_SREV_POSEIDON(ah) || AR_SREV_HORNET(ah)) { 3773250003Sadrian return base_address_512+1; 3774250003Sadrian } else { 3775250003Sadrian return base_address+1; 3776250003Sadrian } 3777250003Sadrian} 3778250003Sadrian 3779250003Sadrian 3780250003Sadrian/* 3781250003Sadrian * find top of memory 3782250003Sadrian */ 3783250003Sadrianint 3784250003Sadrianar9300_eeprom_base_address(struct ath_hal *ah) 3785250003Sadrian{ 3786250003Sadrian int size; 3787250003Sadrian 3788250003Sadrian if (AH9300(ah)->calibration_data_source == calibration_data_otp) { 3789250003Sadrian return ar9300_otp_size(ah)-1; 3790250003Sadrian } 3791250003Sadrian else 3792250003Sadrian { 3793250003Sadrian size = ar9300_eeprom_size(ah); 3794250003Sadrian if (size > 0) { 3795250003Sadrian return size - 1; 3796250003Sadrian } else { 3797250003Sadrian return ar9300_otp_size(ah)-1; 3798250003Sadrian } 3799250003Sadrian } 3800250003Sadrian} 3801250003Sadrian 3802250003Sadrianint 3803250003Sadrianar9300_eeprom_volatile(struct ath_hal *ah) 3804250003Sadrian{ 3805250003Sadrian if (AH9300(ah)->calibration_data_source == calibration_data_otp) { 3806250003Sadrian return 0; /* no eeprom, use otp */ 3807250003Sadrian } else { 3808250003Sadrian return 1; /* board has eeprom or flash */ 3809250003Sadrian } 3810250003Sadrian} 3811250003Sadrian 3812250003Sadrian/* 3813250003Sadrian * need to change this to look for the pcie data in the low parts of memory 3814250003Sadrian * cal data needs to stop a few locations above 3815250003Sadrian */ 3816250003Sadrianint 3817250003Sadrianar9300_eeprom_low_limit(struct ath_hal *ah) 3818250003Sadrian{ 3819250003Sadrian return low_limit; 3820250003Sadrian} 3821250003Sadrian 3822250003Sadrianu_int16_t 3823250003Sadrianar9300_compression_checksum(u_int8_t *data, int dsize) 3824250003Sadrian{ 3825250003Sadrian int it; 3826250003Sadrian int checksum = 0; 3827250003Sadrian 3828250003Sadrian for (it = 0; it < dsize; it++) { 3829250003Sadrian checksum += data[it]; 3830250003Sadrian checksum &= 0xffff; 3831250003Sadrian } 3832250003Sadrian 3833250003Sadrian return checksum; 3834250003Sadrian} 3835250003Sadrian 3836250003Sadrianint 3837250003Sadrianar9300_compression_header_unpack(u_int8_t *best, int *code, int *reference, 3838250003Sadrian int *length, int *major, int *minor) 3839250003Sadrian{ 3840250003Sadrian unsigned long value[4]; 3841250003Sadrian 3842250003Sadrian value[0] = best[0]; 3843250003Sadrian value[1] = best[1]; 3844250003Sadrian value[2] = best[2]; 3845250003Sadrian value[3] = best[3]; 3846250003Sadrian *code = ((value[0] >> 5) & 0x0007); 3847250003Sadrian *reference = (value[0] & 0x001f) | ((value[1] >> 2) & 0x0020); 3848250003Sadrian *length = ((value[1] << 4) & 0x07f0) | ((value[2] >> 4) & 0x000f); 3849250003Sadrian *major = (value[2] & 0x000f); 3850250003Sadrian *minor = (value[3] & 0x00ff); 3851250003Sadrian 3852250003Sadrian return 4; 3853250003Sadrian} 3854250003Sadrian 3855250003Sadrian 3856250003Sadrianstatic HAL_BOOL 3857250003Sadrianar9300_uncompress_block(struct ath_hal *ah, u_int8_t *mptr, int mdata_size, 3858250003Sadrian u_int8_t *block, int size) 3859250003Sadrian{ 3860250003Sadrian int it; 3861250003Sadrian int spot; 3862250003Sadrian int offset; 3863250003Sadrian int length; 3864250003Sadrian 3865250003Sadrian spot = 0; 3866250003Sadrian for (it = 0; it < size; it += (length + 2)) { 3867250003Sadrian offset = block[it]; 3868250003Sadrian offset &= 0xff; 3869250003Sadrian spot += offset; 3870250003Sadrian length = block[it + 1]; 3871250003Sadrian length &= 0xff; 3872250003Sadrian if (length > 0 && spot >= 0 && spot + length <= mdata_size) { 3873250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 3874250003Sadrian "%s: Restore at %d: spot=%d offset=%d length=%d\n", 3875250003Sadrian __func__, it, spot, offset, length); 3876250003Sadrian OS_MEMCPY(&mptr[spot], &block[it + 2], length); 3877250003Sadrian spot += length; 3878250003Sadrian } else if (length > 0) { 3879250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 3880250003Sadrian "%s: Bad restore at %d: spot=%d offset=%d length=%d\n", 3881250003Sadrian __func__, it, spot, offset, length); 3882250003Sadrian return AH_FALSE; 3883250003Sadrian } 3884250003Sadrian } 3885250003Sadrian return AH_TRUE; 3886250003Sadrian} 3887250003Sadrian 3888250003Sadrianstatic int 3889250003Sadrianar9300_eeprom_restore_internal_address(struct ath_hal *ah, 3890250003Sadrian ar9300_eeprom_t *mptr, int mdata_size, int cptr, u_int8_t blank) 3891250003Sadrian{ 3892250003Sadrian u_int8_t word[MOUTPUT]; 3893250003Sadrian ar9300_eeprom_t *dptr; /* was uint8 */ 3894250003Sadrian int code; 3895250003Sadrian int reference, length, major, minor; 3896250003Sadrian int osize; 3897250003Sadrian int it; 3898250003Sadrian int restored; 3899250003Sadrian u_int16_t checksum, mchecksum; 3900250003Sadrian 3901250003Sadrian restored = 0; 3902250003Sadrian for (it = 0; it < MSTATE; it++) { 3903250003Sadrian (void) ar9300_calibration_data_read_array( 3904250003Sadrian ah, cptr, word, compression_header_length); 3905250003Sadrian if (word[0] == blank && word[1] == blank && word[2] == blank && word[3] == blank) 3906250003Sadrian { 3907250003Sadrian break; 3908250003Sadrian } 3909250003Sadrian ar9300_compression_header_unpack( 3910250003Sadrian word, &code, &reference, &length, &major, &minor); 3911250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 3912250003Sadrian "%s: Found block at %x: " 3913250003Sadrian "code=%d ref=%d length=%d major=%d minor=%d\n", 3914250003Sadrian __func__, cptr, code, reference, length, major, minor); 3915250003Sadrian#ifdef DONTUSE 3916250003Sadrian if (length >= 1024) { 3917250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Skipping bad header\n", __func__); 3918250003Sadrian cptr -= compression_header_length; 3919250003Sadrian continue; 3920250003Sadrian } 3921250003Sadrian#endif 3922250003Sadrian osize = length; 3923250003Sadrian (void) ar9300_calibration_data_read_array( 3924250003Sadrian ah, cptr, word, 3925250003Sadrian compression_header_length + osize + compression_checksum_length); 3926250003Sadrian checksum = ar9300_compression_checksum( 3927250003Sadrian &word[compression_header_length], length); 3928250003Sadrian mchecksum = 3929250003Sadrian word[compression_header_length + osize] | 3930250003Sadrian (word[compression_header_length + osize + 1] << 8); 3931250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 3932250003Sadrian "%s: checksum %x %x\n", __func__, checksum, mchecksum); 3933250003Sadrian if (checksum == mchecksum) { 3934250003Sadrian switch (code) { 3935250003Sadrian case _compress_none: 3936250003Sadrian if (length != mdata_size) { 3937250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 3938250003Sadrian "%s: EEPROM structure size mismatch " 3939250003Sadrian "memory=%d eeprom=%d\n", __func__, mdata_size, length); 3940250003Sadrian return -1; 3941250003Sadrian } 3942250003Sadrian OS_MEMCPY((u_int8_t *)mptr, 3943250003Sadrian (u_int8_t *)(word + compression_header_length), length); 3944250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 3945250003Sadrian "%s: restored eeprom %d: uncompressed, length %d\n", 3946250003Sadrian __func__, it, length); 3947250003Sadrian restored = 1; 3948250003Sadrian break; 3949250003Sadrian#ifdef UNUSED 3950250003Sadrian case _compress_lzma: 3951250003Sadrian if (reference == reference_current) { 3952250003Sadrian dptr = mptr; 3953250003Sadrian } else { 3954250003Sadrian dptr = (u_int8_t *)ar9300_eeprom_struct_default_find_by_id( 3955250003Sadrian reference); 3956250003Sadrian if (dptr == 0) { 3957250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 3958250003Sadrian "%s: Can't find reference eeprom struct %d\n", 3959250003Sadrian __func__, reference); 3960250003Sadrian goto done; 3961250003Sadrian } 3962250003Sadrian } 3963250003Sadrian usize = -1; 3964250003Sadrian if (usize != mdata_size) { 3965250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 3966250003Sadrian "%s: uncompressed data is wrong size %d %d\n", 3967250003Sadrian __func__, usize, mdata_size); 3968250003Sadrian goto done; 3969250003Sadrian } 3970250003Sadrian 3971250003Sadrian for (ib = 0; ib < mdata_size; ib++) { 3972250003Sadrian mptr[ib] = dptr[ib] ^ word[ib + overhead]; 3973250003Sadrian } 3974250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 3975250003Sadrian "%s: restored eeprom %d: compressed, " 3976250003Sadrian "reference %d, length %d\n", 3977250003Sadrian __func__, it, reference, length); 3978250003Sadrian break; 3979250003Sadrian case _compress_pairs: 3980250003Sadrian if (reference == reference_current) { 3981250003Sadrian dptr = mptr; 3982250003Sadrian } else { 3983250003Sadrian dptr = (u_int8_t *)ar9300_eeprom_struct_default_find_by_id( 3984250003Sadrian reference); 3985250003Sadrian if (dptr == 0) { 3986250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 3987250003Sadrian "%s: Can't find the reference " 3988250003Sadrian "eeprom structure %d\n", 3989250003Sadrian __func__, reference); 3990250003Sadrian goto done; 3991250003Sadrian } 3992250003Sadrian } 3993250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 3994250003Sadrian "%s: restored eeprom %d: " 3995250003Sadrian "pairs, reference %d, length %d,\n", 3996250003Sadrian __func__, it, reference, length); 3997250003Sadrian break; 3998250003Sadrian#endif 3999250003Sadrian case _compress_block: 4000250003Sadrian if (reference == reference_current) { 4001250003Sadrian dptr = mptr; 4002250003Sadrian } else { 4003250003Sadrian dptr = ar9300_eeprom_struct_default_find_by_id(reference); 4004250003Sadrian if (dptr == 0) { 4005250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 4006250003Sadrian "%s: cant find reference eeprom struct %d\n", 4007250003Sadrian __func__, reference); 4008250003Sadrian break; 4009250003Sadrian } 4010250003Sadrian OS_MEMCPY(mptr, dptr, mdata_size); 4011250003Sadrian } 4012250003Sadrian 4013250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 4014250003Sadrian "%s: restore eeprom %d: block, reference %d, length %d\n", 4015250003Sadrian __func__, it, reference, length); 4016250003Sadrian (void) ar9300_uncompress_block(ah, 4017250003Sadrian (u_int8_t *) mptr, mdata_size, 4018250003Sadrian (u_int8_t *) (word + compression_header_length), length); 4019250003Sadrian restored = 1; 4020250003Sadrian break; 4021250003Sadrian default: 4022250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 4023250003Sadrian "%s: unknown compression code %d\n", __func__, code); 4024250003Sadrian break; 4025250003Sadrian } 4026250003Sadrian } else { 4027250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM, 4028250003Sadrian "%s: skipping block with bad checksum\n", __func__); 4029250003Sadrian } 4030250003Sadrian cptr -= compression_header_length + osize + compression_checksum_length; 4031250003Sadrian } 4032250003Sadrian 4033250003Sadrian if (!restored) { 4034250003Sadrian cptr = -1; 4035250003Sadrian } 4036250003Sadrian return cptr; 4037250003Sadrian} 4038250003Sadrian 4039250003Sadrianstatic int 4040250003Sadrianar9300_eeprom_restore_from_dram(struct ath_hal *ah, ar9300_eeprom_t *mptr, 4041250003Sadrian int mdata_size) 4042250003Sadrian{ 4043250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 4044250003Sadrian#if !defined(USE_PLATFORM_FRAMEWORK) 4045250003Sadrian char *cal_ptr; 4046250003Sadrian#endif 4047250003Sadrian 4048250003Sadrian HALASSERT(mdata_size > 0); 4049250003Sadrian 4050250003Sadrian /* if cal_in_flash is AH_TRUE, the address sent by LMAC to HAL 4051250003Sadrian (i.e. ah->ah_st) is corresponding to Flash. so return from 4052250003Sadrian here if ar9300_eep_data_in_flash(ah) returns AH_TRUE */ 4053250003Sadrian if(ar9300_eep_data_in_flash(ah)) 4054250003Sadrian return -1; 4055250003Sadrian 4056250008Sadrian#if 0 4057250003Sadrian /* check if LMAC sent DRAM address is valid */ 4058250003Sadrian if (!(uintptr_t)(AH_PRIVATE(ah)->ah_st)) { 4059250003Sadrian return -1; 4060250003Sadrian } 4061250008Sadrian#endif 4062250003Sadrian 4063250003Sadrian /* When calibration data is from host, Host will copy the 4064250003Sadrian compressed data to the predefined DRAM location saved at ah->ah_st */ 4065250008Sadrian#if 0 4066250003Sadrian ath_hal_printf(ah, "Restoring Cal data from DRAM\n"); 4067250003Sadrian ahp->ah_cal_mem = OS_REMAP((uintptr_t)(AH_PRIVATE(ah)->ah_st), 4068250003Sadrian HOST_CALDATA_SIZE); 4069250008Sadrian#endif 4070250003Sadrian if (!ahp->ah_cal_mem) 4071250003Sadrian { 4072250003Sadrian HALDEBUG(ah, HAL_DEBUG_EEPROM,"%s: can't remap dram region\n", __func__); 4073250003Sadrian return -1; 4074250003Sadrian } 4075250003Sadrian#if !defined(USE_PLATFORM_FRAMEWORK) 4076250003Sadrian cal_ptr = &((char *)(ahp->ah_cal_mem))[AR9300_FLASH_CAL_START_OFFSET]; 4077250003Sadrian OS_MEMCPY(mptr, cal_ptr, mdata_size); 4078250003Sadrian#else 4079250003Sadrian OS_MEMCPY(mptr, ahp->ah_cal_mem, mdata_size); 4080250003Sadrian#endif 4081250003Sadrian 4082250003Sadrian if (mptr->eeprom_version == 0xff || 4083250003Sadrian mptr->template_version == 0xff || 4084250003Sadrian mptr->eeprom_version == 0 || 4085250003Sadrian mptr->template_version == 0) 4086250003Sadrian { 4087250003Sadrian /* The board is uncalibrated */ 4088250003Sadrian return -1; 4089250003Sadrian } 4090250003Sadrian if (mptr->eeprom_version != 0x2) 4091250003Sadrian { 4092250003Sadrian return -1; 4093250003Sadrian } 4094250003Sadrian 4095250003Sadrian return mdata_size; 4096250003Sadrian 4097250003Sadrian} 4098250003Sadrian 4099250003Sadrianstatic int 4100250003Sadrianar9300_eeprom_restore_from_flash(struct ath_hal *ah, ar9300_eeprom_t *mptr, 4101250003Sadrian int mdata_size) 4102250003Sadrian{ 4103250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 4104250003Sadrian char *cal_ptr; 4105250003Sadrian 4106250003Sadrian HALASSERT(mdata_size > 0); 4107250003Sadrian 4108250003Sadrian if (!ahp->ah_cal_mem) { 4109250003Sadrian return -1; 4110250003Sadrian } 4111250003Sadrian 4112250003Sadrian ath_hal_printf(ah, "Restoring Cal data from Flash\n"); 4113250003Sadrian /* 4114250003Sadrian * When calibration data is saved in flash, read 4115250003Sadrian * uncompressed eeprom structure from flash and return 4116250003Sadrian */ 4117250003Sadrian cal_ptr = &((char *)(ahp->ah_cal_mem))[AR9300_FLASH_CAL_START_OFFSET]; 4118250003Sadrian OS_MEMCPY(mptr, cal_ptr, mdata_size); 4119250003Sadrian#if 0 4120250003Sadrian ar9300_swap_eeprom((ar9300_eeprom_t *)mptr); DONE IN ar9300_restore() 4121250003Sadrian#endif 4122250003Sadrian if (mptr->eeprom_version == 0xff || 4123250003Sadrian mptr->template_version == 0xff || 4124250003Sadrian mptr->eeprom_version == 0 || 4125250003Sadrian mptr->template_version == 0) 4126250003Sadrian { 4127250003Sadrian /* The board is uncalibrated */ 4128250003Sadrian return -1; 4129250003Sadrian } 4130250003Sadrian if (mptr->eeprom_version != 0x2) 4131250003Sadrian { 4132250003Sadrian return -1; 4133250003Sadrian } 4134250003Sadrian return mdata_size; 4135250003Sadrian} 4136250003Sadrian 4137250003Sadrian/* 4138250003Sadrian * Read the configuration data from the storage. We try the order with: 4139250003Sadrian * EEPROM, Flash, OTP. If all of above failed, use the default template. 4140250003Sadrian * The data can be put in any specified memory buffer. 4141250003Sadrian * 4142250003Sadrian * Returns -1 on error. 4143250003Sadrian * Returns address of next memory location on success. 4144250003Sadrian */ 4145250003Sadrianint 4146250003Sadrianar9300_eeprom_restore_internal(struct ath_hal *ah, ar9300_eeprom_t *mptr, 4147250003Sadrian int mdata_size) 4148250003Sadrian{ 4149250003Sadrian int nptr; 4150250003Sadrian 4151250003Sadrian nptr = -1; 4152250003Sadrian 4153250003Sadrian if ((AH9300(ah)->calibration_data_try == calibration_data_none || 4154250003Sadrian AH9300(ah)->calibration_data_try == calibration_data_dram) && 4155250003Sadrian AH9300(ah)->try_dram && nptr < 0) 4156250003Sadrian { 4157250008Sadrian ath_hal_printf(ah, "Restoring Cal data from DRAM\n"); 4158250003Sadrian AH9300(ah)->calibration_data_source = calibration_data_dram; 4159250003Sadrian AH9300(ah)->calibration_data_source_address = 0; 4160250003Sadrian nptr = ar9300_eeprom_restore_from_dram(ah, mptr, mdata_size); 4161250003Sadrian if (nptr < 0) { 4162250003Sadrian AH9300(ah)->calibration_data_source = calibration_data_none; 4163250003Sadrian AH9300(ah)->calibration_data_source_address = 0; 4164250003Sadrian } 4165250003Sadrian } 4166250003Sadrian 4167250003Sadrian if ((AH9300(ah)->calibration_data_try == calibration_data_none || 4168250003Sadrian AH9300(ah)->calibration_data_try == calibration_data_eeprom) && 4169250003Sadrian AH9300(ah)->try_eeprom && nptr < 0) 4170250003Sadrian { 4171250003Sadrian /* 4172250003Sadrian * need to look at highest eeprom address as well as at 4173250003Sadrian * base_address=0x3ff where we used to write the data 4174250003Sadrian */ 4175250008Sadrian ath_hal_printf(ah, "Restoring Cal data from EEPROM\n"); 4176250003Sadrian AH9300(ah)->calibration_data_source = calibration_data_eeprom; 4177250003Sadrian if (AH9300(ah)->calibration_data_try_address != 0) { 4178250003Sadrian AH9300(ah)->calibration_data_source_address = 4179250003Sadrian AH9300(ah)->calibration_data_try_address; 4180250003Sadrian nptr = ar9300_eeprom_restore_internal_address( 4181250003Sadrian ah, mptr, mdata_size, 4182250003Sadrian AH9300(ah)->calibration_data_source_address, 0xff); 4183250003Sadrian } else { 4184250003Sadrian AH9300(ah)->calibration_data_source_address = 4185250003Sadrian ar9300_eeprom_base_address(ah); 4186250003Sadrian nptr = ar9300_eeprom_restore_internal_address( 4187250003Sadrian ah, mptr, mdata_size, 4188250003Sadrian AH9300(ah)->calibration_data_source_address, 0xff); 4189250003Sadrian if (nptr < 0 && 4190250003Sadrian AH9300(ah)->calibration_data_source_address != base_address) 4191250003Sadrian { 4192250003Sadrian AH9300(ah)->calibration_data_source_address = base_address; 4193250003Sadrian nptr = ar9300_eeprom_restore_internal_address( 4194250003Sadrian ah, mptr, mdata_size, 4195250003Sadrian AH9300(ah)->calibration_data_source_address, 0xff); 4196250003Sadrian } 4197250003Sadrian } 4198250003Sadrian if (nptr < 0) { 4199250003Sadrian AH9300(ah)->calibration_data_source = calibration_data_none; 4200250003Sadrian AH9300(ah)->calibration_data_source_address = 0; 4201250003Sadrian } 4202250003Sadrian } 4203250003Sadrian 4204250003Sadrian /* 4205250003Sadrian * ##### should be an ifdef test for any AP usage, 4206250003Sadrian * either in driver or in nart 4207250003Sadrian */ 4208250003Sadrian if ((AH9300(ah)->calibration_data_try == calibration_data_none || 4209250003Sadrian AH9300(ah)->calibration_data_try == calibration_data_flash) && 4210250003Sadrian AH9300(ah)->try_flash && nptr < 0) 4211250003Sadrian { 4212250008Sadrian ath_hal_printf(ah, "Restoring Cal data from Flash\n"); 4213250003Sadrian AH9300(ah)->calibration_data_source = calibration_data_flash; 4214250003Sadrian /* how are we supposed to set this for flash? */ 4215250003Sadrian AH9300(ah)->calibration_data_source_address = 0; 4216250003Sadrian nptr = ar9300_eeprom_restore_from_flash(ah, mptr, mdata_size); 4217250003Sadrian if (nptr < 0) { 4218250003Sadrian AH9300(ah)->calibration_data_source = calibration_data_none; 4219250003Sadrian AH9300(ah)->calibration_data_source_address = 0; 4220250003Sadrian } 4221250003Sadrian } 4222250003Sadrian 4223250003Sadrian if ((AH9300(ah)->calibration_data_try == calibration_data_none || 4224250003Sadrian AH9300(ah)->calibration_data_try == calibration_data_otp) && 4225250003Sadrian AH9300(ah)->try_otp && nptr < 0) 4226250003Sadrian { 4227250008Sadrian ath_hal_printf(ah, "Restoring Cal data from OTP\n"); 4228250003Sadrian AH9300(ah)->calibration_data_source = calibration_data_otp; 4229250003Sadrian if (AH9300(ah)->calibration_data_try_address != 0) { 4230250003Sadrian AH9300(ah)->calibration_data_source_address = 4231250003Sadrian AH9300(ah)->calibration_data_try_address; 4232250003Sadrian } else { 4233250003Sadrian AH9300(ah)->calibration_data_source_address = 4234250003Sadrian ar9300_eeprom_base_address(ah); 4235250003Sadrian } 4236250003Sadrian nptr = ar9300_eeprom_restore_internal_address( 4237250003Sadrian ah, mptr, mdata_size, AH9300(ah)->calibration_data_source_address, 0); 4238250003Sadrian if (nptr < 0) { 4239250003Sadrian AH9300(ah)->calibration_data_source = calibration_data_none; 4240250003Sadrian AH9300(ah)->calibration_data_source_address = 0; 4241250003Sadrian } 4242250003Sadrian } 4243250003Sadrian 4244250003Sadrian#ifdef ATH_CAL_NAND_FLASH 4245250003Sadrian if ((AH9300(ah)->calibration_data_try == calibration_data_none || 4246250003Sadrian AH9300(ah)->calibration_data_try == calibration_data_nand) && 4247250003Sadrian AH9300(ah)->try_nand && nptr < 0) 4248250003Sadrian { 4249250003Sadrian AH9300(ah)->calibration_data_source = calibration_data_nand; 4250250003Sadrian AH9300(ah)->calibration_data_source_address = ((unsigned int)(AH_PRIVATE(ah)->ah_st)) + base_address_nand; 4251250003Sadrian if(ar9300_calibration_data_read( 4252250003Sadrian ah, AH9300(ah)->calibration_data_source_address, 4253250003Sadrian (u_int8_t *)mptr, mdata_size) == AH_TRUE) 4254250003Sadrian { 4255250003Sadrian nptr = mdata_size; 4256250003Sadrian } 4257250003Sadrian /*nptr=ar9300EepromRestoreInternalAddress(ah, mptr, mdataSize, CalibrationDataSourceAddress);*/ 4258250003Sadrian if(nptr < 0) 4259250003Sadrian { 4260250003Sadrian AH9300(ah)->calibration_data_source = calibration_data_none; 4261250003Sadrian AH9300(ah)->calibration_data_source_address = 0; 4262250003Sadrian } 4263250003Sadrian } 4264250003Sadrian#endif 4265250003Sadrian if (nptr < 0) { 4266250003Sadrian ath_hal_printf(ah, "%s[%d] No vaid CAL, calling default template\n", 4267250003Sadrian __func__, __LINE__); 4268250003Sadrian nptr = ar9300_eeprom_restore_something(ah, mptr, mdata_size); 4269250003Sadrian } 4270250003Sadrian 4271250003Sadrian return nptr; 4272250003Sadrian} 4273250003Sadrian 4274250003Sadrian/******************************************************************************/ 4275250003Sadrian/*! 4276250003Sadrian** \brief Eeprom Swapping Function 4277250003Sadrian** 4278250003Sadrian** This function will swap the contents of the "longer" EEPROM data items 4279250003Sadrian** to ensure they are consistent with the endian requirements for the platform 4280250003Sadrian** they are being compiled for 4281250003Sadrian** 4282250003Sadrian** \param eh Pointer to the EEPROM data structure 4283250003Sadrian** \return N/A 4284250003Sadrian*/ 4285250003Sadrian#if AH_BYTE_ORDER == AH_BIG_ENDIAN 4286250003Sadrianvoid 4287250003Sadrianar9300_swap_eeprom(ar9300_eeprom_t *eep) 4288250003Sadrian{ 4289250003Sadrian u_int32_t dword; 4290250003Sadrian u_int16_t word; 4291250003Sadrian int i; 4292250003Sadrian 4293250003Sadrian word = __bswap16(eep->base_eep_header.reg_dmn[0]); 4294250003Sadrian eep->base_eep_header.reg_dmn[0] = word; 4295250003Sadrian 4296250003Sadrian word = __bswap16(eep->base_eep_header.reg_dmn[1]); 4297250003Sadrian eep->base_eep_header.reg_dmn[1] = word; 4298250003Sadrian 4299250003Sadrian dword = __bswap32(eep->base_eep_header.swreg); 4300250003Sadrian eep->base_eep_header.swreg = dword; 4301250003Sadrian 4302250003Sadrian dword = __bswap32(eep->modal_header_2g.ant_ctrl_common); 4303250003Sadrian eep->modal_header_2g.ant_ctrl_common = dword; 4304250003Sadrian 4305250003Sadrian dword = __bswap32(eep->modal_header_2g.ant_ctrl_common2); 4306250003Sadrian eep->modal_header_2g.ant_ctrl_common2 = dword; 4307250003Sadrian 4308250003Sadrian dword = __bswap32(eep->modal_header_2g.paprd_rate_mask_ht20); 4309250003Sadrian eep->modal_header_2g.paprd_rate_mask_ht20 = dword; 4310250003Sadrian 4311250003Sadrian dword = __bswap32(eep->modal_header_2g.paprd_rate_mask_ht40); 4312250003Sadrian eep->modal_header_2g.paprd_rate_mask_ht40 = dword; 4313250003Sadrian 4314250003Sadrian dword = __bswap32(eep->modal_header_5g.ant_ctrl_common); 4315250003Sadrian eep->modal_header_5g.ant_ctrl_common = dword; 4316250003Sadrian 4317250003Sadrian dword = __bswap32(eep->modal_header_5g.ant_ctrl_common2); 4318250003Sadrian eep->modal_header_5g.ant_ctrl_common2 = dword; 4319250003Sadrian 4320250003Sadrian dword = __bswap32(eep->modal_header_5g.paprd_rate_mask_ht20); 4321250003Sadrian eep->modal_header_5g.paprd_rate_mask_ht20 = dword; 4322250003Sadrian 4323250003Sadrian dword = __bswap32(eep->modal_header_5g.paprd_rate_mask_ht40); 4324250003Sadrian eep->modal_header_5g.paprd_rate_mask_ht40 = dword; 4325250003Sadrian 4326250003Sadrian for (i = 0; i < OSPREY_MAX_CHAINS; i++) { 4327250003Sadrian word = __bswap16(eep->modal_header_2g.ant_ctrl_chain[i]); 4328250003Sadrian eep->modal_header_2g.ant_ctrl_chain[i] = word; 4329250003Sadrian 4330250003Sadrian word = __bswap16(eep->modal_header_5g.ant_ctrl_chain[i]); 4331250003Sadrian eep->modal_header_5g.ant_ctrl_chain[i] = word; 4332250003Sadrian } 4333250003Sadrian} 4334250003Sadrian 4335250003Sadrianvoid ar9300_eeprom_template_swap(void) 4336250003Sadrian{ 4337250003Sadrian int it; 4338250003Sadrian ar9300_eeprom_t *dptr; 4339250003Sadrian 4340250003Sadrian for (it = 0; it < ARRAY_LENGTH(default9300); it++) { 4341250003Sadrian dptr = ar9300_eeprom_struct_default(it); 4342250003Sadrian if (dptr != 0) { 4343250003Sadrian ar9300_swap_eeprom(dptr); 4344250003Sadrian } 4345250003Sadrian } 4346250003Sadrian} 4347250003Sadrian#endif 4348250003Sadrian 4349250003Sadrian 4350250003Sadrian/* 4351250003Sadrian * Restore the configuration structure by reading the eeprom. 4352250003Sadrian * This function destroys any existing in-memory structure content. 4353250003Sadrian */ 4354250003SadrianHAL_BOOL 4355250003Sadrianar9300_eeprom_restore(struct ath_hal *ah) 4356250003Sadrian{ 4357250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 4358250003Sadrian ar9300_eeprom_t *mptr; 4359250003Sadrian int mdata_size; 4360250003Sadrian HAL_BOOL status = AH_FALSE; 4361250003Sadrian 4362250003Sadrian mptr = &ahp->ah_eeprom; 4363250003Sadrian mdata_size = ar9300_eeprom_struct_size(); 4364250003Sadrian 4365250003Sadrian if (mptr != 0 && mdata_size > 0) { 4366250003Sadrian#if AH_BYTE_ORDER == AH_BIG_ENDIAN 4367250003Sadrian ar9300_eeprom_template_swap(); 4368250003Sadrian ar9300_swap_eeprom(mptr); 4369250003Sadrian#endif 4370250003Sadrian /* 4371250003Sadrian * At this point, mptr points to the eeprom data structure 4372250003Sadrian * in it's "default" state. If this is big endian, swap the 4373250003Sadrian * data structures back to "little endian" form. 4374250003Sadrian */ 4375250003Sadrian if (ar9300_eeprom_restore_internal(ah, mptr, mdata_size) >= 0) { 4376250003Sadrian status = AH_TRUE; 4377250003Sadrian } 4378250003Sadrian 4379250003Sadrian#if AH_BYTE_ORDER == AH_BIG_ENDIAN 4380250003Sadrian /* Second Swap, back to Big Endian */ 4381250003Sadrian ar9300_eeprom_template_swap(); 4382250003Sadrian ar9300_swap_eeprom(mptr); 4383250003Sadrian#endif 4384250003Sadrian 4385250003Sadrian } 4386250003Sadrian ahp->ah_2g_paprd_rate_mask_ht40 = 4387250003Sadrian mptr->modal_header_2g.paprd_rate_mask_ht40; 4388250003Sadrian ahp->ah_2g_paprd_rate_mask_ht20 = 4389250003Sadrian mptr->modal_header_2g.paprd_rate_mask_ht20; 4390250003Sadrian ahp->ah_5g_paprd_rate_mask_ht40 = 4391250003Sadrian mptr->modal_header_5g.paprd_rate_mask_ht40; 4392250003Sadrian ahp->ah_5g_paprd_rate_mask_ht20 = 4393250003Sadrian mptr->modal_header_5g.paprd_rate_mask_ht20; 4394250003Sadrian return status; 4395250003Sadrian} 4396250003Sadrian 4397250003Sadrianint32_t ar9300_thermometer_get(struct ath_hal *ah) 4398250003Sadrian{ 4399250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 4400250003Sadrian int thermometer; 4401250003Sadrian thermometer = 4402250003Sadrian (ahp->ah_eeprom.base_eep_header.misc_configuration >> 1) & 0x3; 4403250003Sadrian thermometer--; 4404250003Sadrian return thermometer; 4405250003Sadrian} 4406250003Sadrian 4407250003SadrianHAL_BOOL ar9300_thermometer_apply(struct ath_hal *ah) 4408250003Sadrian{ 4409250003Sadrian int thermometer = ar9300_thermometer_get(ah); 4410250003Sadrian 4411250003Sadrian/* ch0_RXTX4 */ 4412250003Sadrian/*#define AR_PHY_65NM_CH0_RXTX4 AR_PHY_65NM(ch0_RXTX4)*/ 4413250003Sadrian#define AR_PHY_65NM_CH1_RXTX4 AR_PHY_65NM(ch1_RXTX4) 4414250003Sadrian#define AR_PHY_65NM_CH2_RXTX4 AR_PHY_65NM(ch2_RXTX4) 4415250003Sadrian/*#define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000*/ 4416250003Sadrian/*#define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28*/ 4417250003Sadrian#define AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR_S 29 4418250003Sadrian#define AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR \ 4419250003Sadrian (0x1<<AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR_S) 4420250003Sadrian 4421250003Sadrian if (thermometer < 0) { 4422250003Sadrian OS_REG_RMW_FIELD(ah, 4423250003Sadrian AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 0); 4424250003Sadrian if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) { 4425250003Sadrian OS_REG_RMW_FIELD(ah, 4426250003Sadrian AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 0); 4427291437Sadrian if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah) ) { 4428250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, 4429250003Sadrian AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 0); 4430250003Sadrian } 4431250003Sadrian } 4432250003Sadrian OS_REG_RMW_FIELD(ah, 4433250003Sadrian AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0); 4434250003Sadrian if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) { 4435250003Sadrian OS_REG_RMW_FIELD(ah, 4436250003Sadrian AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0); 4437291437Sadrian if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah) ) { 4438250003Sadrian OS_REG_RMW_FIELD(ah, 4439250003Sadrian AR_PHY_65NM_CH2_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0); 4440250003Sadrian } 4441250003Sadrian } 4442250003Sadrian } else { 4443250003Sadrian OS_REG_RMW_FIELD(ah, 4444250003Sadrian AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 1); 4445250003Sadrian if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) { 4446250003Sadrian OS_REG_RMW_FIELD(ah, 4447250003Sadrian AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 1); 4448291437Sadrian if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah) ) { 4449250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, 4450250003Sadrian AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 1); 4451250003Sadrian } 4452250003Sadrian } 4453250003Sadrian if (thermometer == 0) { 4454250003Sadrian OS_REG_RMW_FIELD(ah, 4455250003Sadrian AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 1); 4456250003Sadrian if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) { 4457250003Sadrian OS_REG_RMW_FIELD(ah, 4458250003Sadrian AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0); 4459291437Sadrian if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah) ) { 4460250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, 4461250003Sadrian AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0); 4462250003Sadrian } 4463250003Sadrian } 4464250003Sadrian } else if (thermometer == 1) { 4465250003Sadrian OS_REG_RMW_FIELD(ah, 4466250003Sadrian AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0); 4467250003Sadrian if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) { 4468250003Sadrian OS_REG_RMW_FIELD(ah, 4469250003Sadrian AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 1); 4470291437Sadrian if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah) ) { 4471250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, 4472250003Sadrian AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0); 4473250003Sadrian } 4474250003Sadrian } 4475250003Sadrian } else if (thermometer == 2) { 4476250003Sadrian OS_REG_RMW_FIELD(ah, 4477250003Sadrian AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0); 4478250003Sadrian if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) { 4479250003Sadrian OS_REG_RMW_FIELD(ah, 4480250003Sadrian AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0); 4481291437Sadrian if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah) ) { 4482250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, 4483250003Sadrian AR_PHY_65NM_CH0_RXTX4_THERM_ON, 1); 4484250003Sadrian } 4485250003Sadrian } 4486250003Sadrian } 4487250003Sadrian } 4488250003Sadrian return AH_TRUE; 4489250003Sadrian} 4490250003Sadrian 4491250003Sadrianstatic int32_t ar9300_tuning_caps_params_get(struct ath_hal *ah) 4492250003Sadrian{ 4493250003Sadrian int tuning_caps_params; 4494250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 4495250003Sadrian tuning_caps_params = eep->base_eep_header.params_for_tuning_caps[0]; 4496250003Sadrian return tuning_caps_params; 4497250003Sadrian} 4498250003Sadrian 4499250003Sadrian/* 4500250003Sadrian * Read the tuning caps params from eeprom and set to correct register. 4501250003Sadrian * To regulation the frequency accuracy. 4502250003Sadrian */ 4503250003SadrianHAL_BOOL ar9300_tuning_caps_apply(struct ath_hal *ah) 4504250003Sadrian{ 4505250003Sadrian int tuning_caps_params; 4506250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 4507250003Sadrian tuning_caps_params = ar9300_tuning_caps_params_get(ah); 4508250003Sadrian if ((eep->base_eep_header.feature_enable & 0x40) >> 6) { 4509250003Sadrian tuning_caps_params &= 0x7f; 4510250003Sadrian 4511291437Sadrian if (AR_SREV_POSEIDON(ah) || AR_SREV_WASP(ah) || AR_SREV_HONEYBEE(ah)) { 4512291437Sadrian return true; 4513283309Sadrian } else if (AR_SREV_HORNET(ah)) { 4514283309Sadrian OS_REG_RMW_FIELD(ah, 4515283309Sadrian AR_HORNET_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPINDAC, 4516283309Sadrian tuning_caps_params); 4517283309Sadrian OS_REG_RMW_FIELD(ah, 4518283309Sadrian AR_HORNET_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPOUTDAC, 4519283309Sadrian tuning_caps_params); 4520250003Sadrian } else if (AR_SREV_SCORPION(ah)) { 4521250003Sadrian OS_REG_RMW_FIELD(ah, 4522250003Sadrian AR_SCORPION_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPINDAC, 4523250003Sadrian tuning_caps_params); 4524250003Sadrian OS_REG_RMW_FIELD(ah, 4525250003Sadrian AR_SCORPION_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPOUTDAC, 4526250003Sadrian tuning_caps_params); 4527250003Sadrian } else { 4528250003Sadrian OS_REG_RMW_FIELD(ah, 4529250003Sadrian AR_OSPREY_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPINDAC, 4530250003Sadrian tuning_caps_params); 4531250003Sadrian OS_REG_RMW_FIELD(ah, 4532250003Sadrian AR_OSPREY_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPOUTDAC, 4533250003Sadrian tuning_caps_params); 4534250003Sadrian } 4535250003Sadrian 4536250003Sadrian } 4537250003Sadrian return AH_TRUE; 4538250003Sadrian} 4539250003Sadrian 4540250003Sadrian/* 4541250003Sadrian * Read the tx_frame_to_xpa_on param from eeprom and apply the value to 4542250003Sadrian * correct register. 4543250003Sadrian */ 4544250003SadrianHAL_BOOL ar9300_xpa_timing_control_apply(struct ath_hal *ah, HAL_BOOL is_2ghz) 4545250003Sadrian{ 4546250003Sadrian u_int8_t xpa_timing_control; 4547250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 4548250003Sadrian if ((eep->base_eep_header.feature_enable & 0x80) >> 7) { 4549291437Sadrian if (AR_SREV_OSPREY(ah) || AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_HONEYBEE(ah)) { 4550250003Sadrian if (is_2ghz) { 4551250003Sadrian xpa_timing_control = eep->modal_header_2g.tx_frame_to_xpa_on; 4552250003Sadrian OS_REG_RMW_FIELD(ah, 4553250003Sadrian AR_PHY_XPA_TIMING_CTL, AR_PHY_XPA_TIMING_CTL_FRAME_XPAB_ON, 4554250003Sadrian xpa_timing_control); 4555250003Sadrian } else { 4556250003Sadrian xpa_timing_control = eep->modal_header_5g.tx_frame_to_xpa_on; 4557250003Sadrian OS_REG_RMW_FIELD(ah, 4558250003Sadrian AR_PHY_XPA_TIMING_CTL, AR_PHY_XPA_TIMING_CTL_FRAME_XPAA_ON, 4559250003Sadrian xpa_timing_control); 4560250003Sadrian } 4561250003Sadrian } 4562250003Sadrian } 4563250003Sadrian return AH_TRUE; 4564250003Sadrian} 4565250003Sadrian 4566250003Sadrian 4567250003Sadrian/* 4568250003Sadrian * Read the xLNA_bias_strength param from eeprom and apply the value to 4569250003Sadrian * correct register. 4570250003Sadrian */ 4571250003SadrianHAL_BOOL ar9300_x_lNA_bias_strength_apply(struct ath_hal *ah, HAL_BOOL is_2ghz) 4572250003Sadrian{ 4573250003Sadrian u_int8_t x_lNABias; 4574250003Sadrian u_int32_t value = 0; 4575250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 4576250003Sadrian 4577250003Sadrian if ((eep->base_eep_header.misc_configuration & 0x40) >> 6) { 4578250003Sadrian if (AR_SREV_OSPREY(ah)) { 4579250003Sadrian if (is_2ghz) { 4580250003Sadrian x_lNABias = eep->modal_header_2g.xLNA_bias_strength; 4581250003Sadrian } else { 4582250003Sadrian x_lNABias = eep->modal_header_5g.xLNA_bias_strength; 4583250003Sadrian } 4584250003Sadrian value = x_lNABias & ( 0x03 ); // bit0,1 for chain0 4585250003Sadrian OS_REG_RMW_FIELD(ah, 4586250003Sadrian AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_RXTX4_XLNA_BIAS, value); 4587250003Sadrian value = (x_lNABias >> 2) & ( 0x03 ); // bit2,3 for chain1 4588250003Sadrian OS_REG_RMW_FIELD(ah, 4589250003Sadrian AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_RXTX4_XLNA_BIAS, value); 4590250003Sadrian value = (x_lNABias >> 4) & ( 0x03 ); // bit4,5 for chain2 4591250003Sadrian OS_REG_RMW_FIELD(ah, 4592250003Sadrian AR_PHY_65NM_CH2_RXTX4, AR_PHY_65NM_RXTX4_XLNA_BIAS, value); 4593250003Sadrian } 4594250003Sadrian } 4595250003Sadrian return AH_TRUE; 4596250003Sadrian} 4597250003Sadrian 4598250003Sadrian 4599250003Sadrian/* 4600250003Sadrian * Read EEPROM header info and program the device for correct operation 4601250003Sadrian * given the channel value. 4602250003Sadrian */ 4603250003SadrianHAL_BOOL 4604250008Sadrianar9300_eeprom_set_board_values(struct ath_hal *ah, const struct ieee80211_channel *chan) 4605250003Sadrian{ 4606250008Sadrian HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); 4607250003Sadrian 4608250008Sadrian ar9300_xpa_bias_level_apply(ah, IEEE80211_IS_CHAN_2GHZ(chan)); 4609250003Sadrian 4610250008Sadrian ar9300_xpa_timing_control_apply(ah, IEEE80211_IS_CHAN_2GHZ(chan)); 4611250008Sadrian 4612250008Sadrian ar9300_ant_ctrl_apply(ah, IEEE80211_IS_CHAN_2GHZ(chan)); 4613250003Sadrian ar9300_drive_strength_apply(ah); 4614250003Sadrian 4615250008Sadrian ar9300_x_lNA_bias_strength_apply(ah, IEEE80211_IS_CHAN_2GHZ(chan)); 4616250003Sadrian 4617250003Sadrian /* wait for Poseidon internal regular turnning */ 4618250003Sadrian /* for Hornet we move it before initPLL to avoid an access issue */ 4619250003Sadrian /* Function not used when EMULATION. */ 4620291437Sadrian if (!AR_SREV_HORNET(ah) && !AR_SREV_WASP(ah) && !AR_SREV_HONEYBEE(ah)) { 4621250003Sadrian ar9300_internal_regulator_apply(ah); 4622250003Sadrian } 4623250003Sadrian 4624250008Sadrian ar9300_attenuation_apply(ah, ichan->channel); 4625250008Sadrian ar9300_quick_drop_apply(ah, ichan->channel); 4626250003Sadrian ar9300_thermometer_apply(ah); 4627250003Sadrian if(!AR_SREV_WASP(ah)) 4628250003Sadrian { 4629250003Sadrian ar9300_tuning_caps_apply(ah); 4630250003Sadrian } 4631250003Sadrian 4632250008Sadrian ar9300_tx_end_to_xpab_off_apply(ah, ichan->channel); 4633250003Sadrian 4634250003Sadrian return AH_TRUE; 4635250003Sadrian} 4636250003Sadrian 4637250003Sadrianu_int8_t * 4638250003Sadrianar9300_eeprom_get_spur_chans_ptr(struct ath_hal *ah, HAL_BOOL is_2ghz) 4639250003Sadrian{ 4640250003Sadrian ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom; 4641250003Sadrian 4642250003Sadrian if (is_2ghz) { 4643250003Sadrian return &(eep->modal_header_2g.spur_chans[0]); 4644250003Sadrian } else { 4645250003Sadrian return &(eep->modal_header_5g.spur_chans[0]); 4646250003Sadrian } 4647250003Sadrian} 4648250003Sadrian 4649250003Sadrianstatic u_int8_t ar9300_eeprom_get_tx_gain_table_number_max(struct ath_hal *ah) 4650250003Sadrian{ 4651250003Sadrian unsigned long tx_gain_table_max; 4652250003Sadrian tx_gain_table_max = OS_REG_READ_FIELD(ah, 4653250003Sadrian AR_PHY_TPC_7, AR_PHY_TPC_7_TX_GAIN_TABLE_MAX); 4654250003Sadrian return tx_gain_table_max; 4655250003Sadrian} 4656250003Sadrian 4657250003Sadrianu_int8_t ar9300_eeprom_tx_gain_table_index_max_apply(struct ath_hal *ah, u_int16_t channel) 4658250003Sadrian{ 4659250003Sadrian unsigned int index; 4660250003Sadrian ar9300_eeprom_t *ahp_Eeprom; 4661250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 4662250003Sadrian 4663250003Sadrian ahp_Eeprom = &ahp->ah_eeprom; 4664250003Sadrian 4665250003Sadrian if (ahp_Eeprom->base_ext1.misc_enable == 0) 4666250003Sadrian return AH_FALSE; 4667250003Sadrian 4668250003Sadrian if (channel < 4000) 4669250003Sadrian { 4670250003Sadrian index = ahp_Eeprom->modal_header_2g.tx_gain_cap; 4671250003Sadrian } 4672250003Sadrian else 4673250003Sadrian { 4674250003Sadrian index = ahp_Eeprom->modal_header_5g.tx_gain_cap; 4675250003Sadrian } 4676250003Sadrian 4677250003Sadrian OS_REG_RMW_FIELD(ah, 4678250003Sadrian AR_PHY_TPC_7, AR_PHY_TPC_7_TX_GAIN_TABLE_MAX, index); 4679250003Sadrian return AH_TRUE; 4680250003Sadrian} 4681250003Sadrian 4682250003Sadrianstatic u_int8_t ar9300_eeprom_get_pcdac_tx_gain_table_i(struct ath_hal *ah, 4683250003Sadrian int i, u_int8_t *pcdac) 4684250003Sadrian{ 4685250003Sadrian unsigned long tx_gain; 4686250003Sadrian u_int8_t tx_gain_table_max; 4687250003Sadrian tx_gain_table_max = ar9300_eeprom_get_tx_gain_table_number_max(ah); 4688250003Sadrian if (i <= 0 || i > tx_gain_table_max) { 4689250003Sadrian *pcdac = 0; 4690250003Sadrian return AH_FALSE; 4691250003Sadrian } 4692250003Sadrian 4693250003Sadrian tx_gain = OS_REG_READ(ah, AR_PHY_TXGAIN_TAB(1) + i * 4); 4694250003Sadrian *pcdac = ((tx_gain >> 24) & 0xff); 4695250003Sadrian return AH_TRUE; 4696250003Sadrian} 4697250003Sadrian 4698250003Sadrianu_int8_t ar9300_eeprom_set_tx_gain_cap(struct ath_hal *ah, 4699250003Sadrian int *tx_gain_max) 4700250003Sadrian// pcdac read back from reg, read back value depends on reset 2GHz/5GHz ini 4701250003Sadrian// tx_gain_table, this function will be called twice after each 4702250003Sadrian// band's calibration. 4703250003Sadrian// after 2GHz cal, tx_gain_max[0] has 2GHz, calibration max txgain, 4704250003Sadrian// tx_gain_max[1]=-100 4705250003Sadrian// after 5GHz cal, tx_gain_max[0],tx_gain_max[1] have calibration 4706250003Sadrian// value for both band 4707250003Sadrian// reset is on 5GHz, reg reading from tx_gain_table is for 5GHz, 4708250003Sadrian// so program can't recalculate 2g.tx_gain_cap at this point. 4709250003Sadrian{ 4710250003Sadrian int i = 0, ig, im = 0; 4711250003Sadrian u_int8_t pcdac = 0; 4712250003Sadrian u_int8_t tx_gain_table_max; 4713250003Sadrian ar9300_eeprom_t *ahp_Eeprom; 4714250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 4715250003Sadrian 4716250003Sadrian ahp_Eeprom = &ahp->ah_eeprom; 4717250003Sadrian 4718250003Sadrian if (ahp_Eeprom->base_ext1.misc_enable == 0) 4719250003Sadrian return AH_FALSE; 4720250003Sadrian 4721250003Sadrian tx_gain_table_max = ar9300_eeprom_get_tx_gain_table_number_max(ah); 4722250003Sadrian 4723250003Sadrian for (i = 0; i < 2; i++) { 4724250003Sadrian if (tx_gain_max[i]>-100) { // -100 didn't cal that band. 4725250003Sadrian if ( i== 0) { 4726250003Sadrian if (tx_gain_max[1]>-100) { 4727250003Sadrian continue; 4728250003Sadrian // both band are calibrated, skip 2GHz 2g.tx_gain_cap reset 4729250003Sadrian } 4730250003Sadrian } 4731250003Sadrian for (ig = 1; ig <= tx_gain_table_max; ig++) { 4732250003Sadrian if (ah != 0 && ah->ah_reset != 0) 4733250003Sadrian { 4734250003Sadrian ar9300_eeprom_get_pcdac_tx_gain_table_i(ah, ig, &pcdac); 4735250003Sadrian if (pcdac >= tx_gain_max[i]) 4736250003Sadrian break; 4737250003Sadrian } 4738250003Sadrian } 4739250003Sadrian if (ig+1 <= tx_gain_table_max) { 4740250003Sadrian if (pcdac == tx_gain_max[i]) 4741250003Sadrian im = ig; 4742250003Sadrian else 4743250003Sadrian im = ig + 1; 4744250003Sadrian if (i == 0) { 4745250003Sadrian ahp_Eeprom->modal_header_2g.tx_gain_cap = im; 4746250003Sadrian } else { 4747250003Sadrian ahp_Eeprom->modal_header_5g.tx_gain_cap = im; 4748250003Sadrian } 4749250003Sadrian } else { 4750250003Sadrian if (i == 0) { 4751250003Sadrian ahp_Eeprom->modal_header_2g.tx_gain_cap = ig; 4752250003Sadrian } else { 4753250003Sadrian ahp_Eeprom->modal_header_5g.tx_gain_cap = ig; 4754250003Sadrian } 4755250003Sadrian } 4756250003Sadrian } 4757250003Sadrian } 4758250003Sadrian return AH_TRUE; 4759250003Sadrian} 4760