Path: blob/main/sys/dev/ath/ath_hal/ah_eeprom_v1.c
39537 views
/*-1* SPDX-License-Identifier: ISC2*3* Copyright (c) 2008 Sam Leffler, Errno Consulting4* Copyright (c) 2008 Atheros Communications, Inc.5*6* Permission to use, copy, modify, and/or distribute this software for any7* purpose with or without fee is hereby granted, provided that the above8* copyright notice and this permission notice appear in all copies.9*10* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES11* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF12* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR13* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES14* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN15* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF16* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.17*/18#include "opt_ah.h"1920#include "ah.h"21#include "ah_internal.h"22#include "ah_eeprom_v1.h"2324static HAL_STATUS25v1EepromGet(struct ath_hal *ah, int param, void *val)26{27HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom;28uint32_t sum;29uint16_t eeval;30uint8_t *macaddr;31int i;3233switch (param) {34case AR_EEP_MACADDR: /* Get MAC Address */35sum = 0;36macaddr = val;37for (i = 0; i < 3; i++) {38if (!ath_hal_eepromRead(ah, AR_EEPROM_MAC(i), &eeval)) {39HALDEBUG(ah, HAL_DEBUG_ANY,40"%s: cannot read EEPROM location %u\n",41__func__, i);42return HAL_EEREAD;43}44sum += eeval;45macaddr[2*i + 0] = eeval >> 8;46macaddr[2*i + 1] = eeval & 0xff;47}48if (sum == 0 || sum == 0xffff*3) {49HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad mac address %s\n",50__func__, ath_hal_ether_sprintf(macaddr));51return HAL_EEBADMAC;52}53return HAL_OK;54case AR_EEP_REGDMN_0:55*(uint16_t *) val = ee->ee_regDomain[0];56return HAL_OK;57case AR_EEP_RFKILL:58HALASSERT(val == AH_NULL);59return ee->ee_rfKill ? HAL_OK : HAL_EIO;60case AR_EEP_WRITEPROTECT:61HALASSERT(val == AH_NULL);62return (ee->ee_protect & AR_EEPROM_PROTOTECT_WP_128_191) ?63HAL_OK : HAL_EIO;64default:65HALASSERT(0);66return HAL_EINVAL;67}68}6970static HAL_STATUS71v1EepromSet(struct ath_hal *ah, int param, int v)72{73return HAL_EINVAL;74}7576static HAL_BOOL77v1EepromDiag(struct ath_hal *ah, int request,78const void *args, uint32_t argsize, void **result, uint32_t *resultsize)79{80HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom;8182switch (request) {83case HAL_DIAG_EEPROM:84*result = ee;85*resultsize = sizeof(*ee);86return AH_TRUE;87}88return AH_FALSE;89}9091static uint16_t92v1EepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz)93{94return AR_NO_SPUR;95}9697/*98* Reclaim any EEPROM-related storage.99*/100static void101v1EepromDetach(struct ath_hal *ah)102{103HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom;104105ath_hal_free(ee);106AH_PRIVATE(ah)->ah_eeprom = AH_NULL;107}108109HAL_STATUS110ath_hal_v1EepromAttach(struct ath_hal *ah)111{112HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom;113uint16_t athvals[AR_EEPROM_ATHEROS_MAX]; /* XXX off stack */114uint16_t protect, eeprom_version, eeval;115uint32_t sum;116int i, loc;117118HALASSERT(ee == AH_NULL);119120if (!ath_hal_eepromRead(ah, AR_EEPROM_MAGIC, &eeval)) {121HALDEBUG(ah, HAL_DEBUG_ANY,122"%s: cannot read EEPROM magic number\n", __func__);123return HAL_EEREAD;124}125if (eeval != 0x5aa5) {126HALDEBUG(ah, HAL_DEBUG_ANY,127"%s: invalid EEPROM magic number 0x%x\n", __func__, eeval);128return HAL_EEMAGIC;129}130131if (!ath_hal_eepromRead(ah, AR_EEPROM_PROTECT, &protect)) {132HALDEBUG(ah, HAL_DEBUG_ANY,133"%s: cannot read EEPROM protection bits; read locked?\n",134__func__);135return HAL_EEREAD;136}137HALDEBUG(ah, HAL_DEBUG_ATTACH, "EEPROM protect 0x%x\n", protect);138/* XXX check proper access before continuing */139140if (!ath_hal_eepromRead(ah, AR_EEPROM_VERSION, &eeprom_version)) {141HALDEBUG(ah, HAL_DEBUG_ANY,142"%s: unable to read EEPROM version\n", __func__);143return HAL_EEREAD;144}145if (((eeprom_version>>12) & 0xf) != 1) {146/*147* This code only groks the version 1 EEPROM layout.148*/149HALDEBUG(ah, HAL_DEBUG_ANY,150"%s: unsupported EEPROM version 0x%x found\n",151__func__, eeprom_version);152return HAL_EEVERSION;153}154155/*156* Read the Atheros EEPROM entries and calculate the checksum.157*/158sum = 0;159for (i = 0; i < AR_EEPROM_ATHEROS_MAX; i++) {160if (!ath_hal_eepromRead(ah, AR_EEPROM_ATHEROS(i), &athvals[i]))161return HAL_EEREAD;162sum ^= athvals[i];163}164if (sum != 0xffff) {165HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad EEPROM checksum 0x%x\n",166__func__, sum);167return HAL_EEBADSUM;168}169170/*171* Valid checksum, fetch the regulatory domain and save values.172*/173if (!ath_hal_eepromRead(ah, AR_EEPROM_REG_DOMAIN, &eeval)) {174HALDEBUG(ah, HAL_DEBUG_ANY,175"%s: cannot read regdomain from EEPROM\n", __func__);176return HAL_EEREAD;177}178179ee = ath_hal_malloc(sizeof(HAL_EEPROM_v1));180if (ee == AH_NULL) {181/* XXX message */182return HAL_ENOMEM;183}184185ee->ee_version = eeprom_version;186ee->ee_protect = protect;187ee->ee_antenna = athvals[2];188ee->ee_biasCurrents = athvals[3];189ee->ee_thresh62 = athvals[4] & 0xff;190ee->ee_xlnaOn = (athvals[4] >> 8) & 0xff;191ee->ee_xpaOn = athvals[5] & 0xff;192ee->ee_xpaOff = (athvals[5] >> 8) & 0xff;193ee->ee_regDomain[0] = (athvals[6] >> 8) & 0xff;194ee->ee_regDomain[1] = athvals[6] & 0xff;195ee->ee_regDomain[2] = (athvals[7] >> 8) & 0xff;196ee->ee_regDomain[3] = athvals[7] & 0xff;197ee->ee_rfKill = athvals[8] & 0x1;198ee->ee_devType = (athvals[8] >> 1) & 0x7;199200for (i = 0, loc = AR_EEPROM_ATHEROS_TP_SETTINGS; i < AR_CHANNELS_MAX; i++, loc += AR_TP_SETTINGS_SIZE) {201struct tpcMap *chan = &ee->ee_tpc[i];202203/* Copy pcdac and gain_f values from EEPROM */204chan->pcdac[0] = (athvals[loc] >> 10) & 0x3F;205chan->gainF[0] = (athvals[loc] >> 4) & 0x3F;206chan->pcdac[1] = ((athvals[loc] << 2) & 0x3C)207| ((athvals[loc+1] >> 14) & 0x03);208chan->gainF[1] = (athvals[loc+1] >> 8) & 0x3F;209chan->pcdac[2] = (athvals[loc+1] >> 2) & 0x3F;210chan->gainF[2] = ((athvals[loc+1] << 4) & 0x30)211| ((athvals[loc+2] >> 12) & 0x0F);212chan->pcdac[3] = (athvals[loc+2] >> 6) & 0x3F;213chan->gainF[3] = athvals[loc+2] & 0x3F;214chan->pcdac[4] = (athvals[loc+3] >> 10) & 0x3F;215chan->gainF[4] = (athvals[loc+3] >> 4) & 0x3F;216chan->pcdac[5] = ((athvals[loc+3] << 2) & 0x3C)217| ((athvals[loc+4] >> 14) & 0x03);218chan->gainF[5] = (athvals[loc+4] >> 8) & 0x3F;219chan->pcdac[6] = (athvals[loc+4] >> 2) & 0x3F;220chan->gainF[6] = ((athvals[loc+4] << 4) & 0x30)221| ((athvals[loc+5] >> 12) & 0x0F);222chan->pcdac[7] = (athvals[loc+5] >> 6) & 0x3F;223chan->gainF[7] = athvals[loc+5] & 0x3F;224chan->pcdac[8] = (athvals[loc+6] >> 10) & 0x3F;225chan->gainF[8] = (athvals[loc+6] >> 4) & 0x3F;226chan->pcdac[9] = ((athvals[loc+6] << 2) & 0x3C)227| ((athvals[loc+7] >> 14) & 0x03);228chan->gainF[9] = (athvals[loc+7] >> 8) & 0x3F;229chan->pcdac[10] = (athvals[loc+7] >> 2) & 0x3F;230chan->gainF[10] = ((athvals[loc+7] << 4) & 0x30)231| ((athvals[loc+8] >> 12) & 0x0F);232233/* Copy Regulatory Domain and Rate Information from EEPROM */234chan->rate36 = (athvals[loc+8] >> 6) & 0x3F;235chan->rate48 = athvals[loc+8] & 0x3F;236chan->rate54 = (athvals[loc+9] >> 10) & 0x3F;237chan->regdmn[0] = (athvals[loc+9] >> 4) & 0x3F;238chan->regdmn[1] = ((athvals[loc+9] << 2) & 0x3C)239| ((athvals[loc+10] >> 14) & 0x03);240chan->regdmn[2] = (athvals[loc+10] >> 8) & 0x3F;241chan->regdmn[3] = (athvals[loc+10] >> 2) & 0x3F;242}243244AH_PRIVATE(ah)->ah_eeprom = ee;245AH_PRIVATE(ah)->ah_eeversion = eeprom_version;246AH_PRIVATE(ah)->ah_eepromDetach = v1EepromDetach;247AH_PRIVATE(ah)->ah_eepromGet = v1EepromGet;248AH_PRIVATE(ah)->ah_eepromSet = v1EepromSet;249AH_PRIVATE(ah)->ah_getSpurChan = v1EepromGetSpurChan;250AH_PRIVATE(ah)->ah_eepromDiag = v1EepromDiag;251return HAL_OK;252}253254255