Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for 4.16. Major changes: wil6210 * add PCI device id for Talyn * support flashless device ath9k * improve RSSI/signal accuracy on AR9003 series
This commit is contained in:
commit
f7a611707b
|
@ -3310,6 +3310,12 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
|
|||
if (ar9300_check_eeprom_header(ah, read, cptr))
|
||||
goto found;
|
||||
|
||||
cptr = AR9300_BASE_ADDR_4K;
|
||||
ath_dbg(common, EEPROM, "Trying EEPROM access at Address 0x%04x\n",
|
||||
cptr);
|
||||
if (ar9300_check_eeprom_header(ah, read, cptr))
|
||||
goto found;
|
||||
|
||||
cptr = AR9300_BASE_ADDR_512;
|
||||
ath_dbg(common, EEPROM, "Trying EEPROM access at Address 0x%04x\n",
|
||||
cptr);
|
||||
|
@ -3430,6 +3436,60 @@ static u32 ar9003_dump_modal_eeprom(char *buf, u32 len, u32 size,
|
|||
return len;
|
||||
}
|
||||
|
||||
static u32 ar9003_dump_cal_data(struct ath_hw *ah, char *buf, u32 len, u32 size,
|
||||
bool is_2g)
|
||||
{
|
||||
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
|
||||
struct ar9300_base_eep_hdr *pBase;
|
||||
struct ar9300_cal_data_per_freq_op_loop *cal_pier;
|
||||
int cal_pier_nr;
|
||||
int freq;
|
||||
int i, j;
|
||||
|
||||
pBase = &eep->baseEepHeader;
|
||||
|
||||
if (is_2g)
|
||||
cal_pier_nr = AR9300_NUM_2G_CAL_PIERS;
|
||||
else
|
||||
cal_pier_nr = AR9300_NUM_5G_CAL_PIERS;
|
||||
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
if (!((pBase->txrxMask >> i) & 1))
|
||||
continue;
|
||||
|
||||
len += snprintf(buf + len, size - len, "Chain %d\n", i);
|
||||
|
||||
len += snprintf(buf + len, size - len,
|
||||
"Freq\t ref\tvolt\ttemp\tnf_cal\tnf_pow\trx_temp\n");
|
||||
|
||||
for (j = 0; j < cal_pier_nr; j++) {
|
||||
if (is_2g) {
|
||||
cal_pier = &eep->calPierData2G[i][j];
|
||||
freq = 2300 + eep->calFreqPier2G[j];
|
||||
} else {
|
||||
cal_pier = &eep->calPierData5G[i][j];
|
||||
freq = 4800 + eep->calFreqPier5G[j] * 5;
|
||||
}
|
||||
|
||||
len += snprintf(buf + len, size - len,
|
||||
"%d\t", freq);
|
||||
|
||||
len += snprintf(buf + len, size - len,
|
||||
"%d\t%d\t%d\t%d\t%d\t%d\n",
|
||||
cal_pier->refPower,
|
||||
cal_pier->voltMeas,
|
||||
cal_pier->tempMeas,
|
||||
cal_pier->rxTempMeas ?
|
||||
N2DBM(cal_pier->rxNoisefloorCal) : 0,
|
||||
cal_pier->rxTempMeas ?
|
||||
N2DBM(cal_pier->rxNoisefloorPower) : 0,
|
||||
cal_pier->rxTempMeas);
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
|
||||
u8 *buf, u32 len, u32 size)
|
||||
{
|
||||
|
@ -3441,10 +3501,18 @@ static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
|
|||
"%20s :\n", "2GHz modal Header");
|
||||
len = ar9003_dump_modal_eeprom(buf, len, size,
|
||||
&eep->modalHeader2G);
|
||||
len += scnprintf(buf + len, size - len,
|
||||
|
||||
len += scnprintf(buf + len, size - len, "Calibration data\n");
|
||||
len = ar9003_dump_cal_data(ah, buf, len, size, true);
|
||||
|
||||
len += snprintf(buf + len, size - len,
|
||||
"%20s :\n", "5GHz modal Header");
|
||||
len = ar9003_dump_modal_eeprom(buf, len, size,
|
||||
&eep->modalHeader5G);
|
||||
|
||||
len += snprintf(buf + len, size - len, "Calibration data\n");
|
||||
len = ar9003_dump_cal_data(ah, buf, len, size, false);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -4683,7 +4751,8 @@ static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
|
|||
int ichain,
|
||||
int *pfrequency,
|
||||
int *pcorrection,
|
||||
int *ptemperature, int *pvoltage)
|
||||
int *ptemperature, int *pvoltage,
|
||||
int *pnf_cal, int *pnf_power)
|
||||
{
|
||||
u8 *pCalPier;
|
||||
struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct;
|
||||
|
@ -4725,6 +4794,10 @@ static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
|
|||
*pcorrection = pCalPierStruct->refPower;
|
||||
*ptemperature = pCalPierStruct->tempMeas;
|
||||
*pvoltage = pCalPierStruct->voltMeas;
|
||||
*pnf_cal = pCalPierStruct->rxTempMeas ?
|
||||
N2DBM(pCalPierStruct->rxNoisefloorCal) : 0;
|
||||
*pnf_power = pCalPierStruct->rxTempMeas ?
|
||||
N2DBM(pCalPierStruct->rxNoisefloorPower) : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -4889,14 +4962,18 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
|
|||
int mode;
|
||||
int lfrequency[AR9300_MAX_CHAINS],
|
||||
lcorrection[AR9300_MAX_CHAINS],
|
||||
ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS];
|
||||
ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS],
|
||||
lnf_cal[AR9300_MAX_CHAINS], lnf_pwr[AR9300_MAX_CHAINS];
|
||||
int hfrequency[AR9300_MAX_CHAINS],
|
||||
hcorrection[AR9300_MAX_CHAINS],
|
||||
htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS];
|
||||
htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS],
|
||||
hnf_cal[AR9300_MAX_CHAINS], hnf_pwr[AR9300_MAX_CHAINS];
|
||||
int fdiff;
|
||||
int correction[AR9300_MAX_CHAINS],
|
||||
voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS];
|
||||
int pfrequency, pcorrection, ptemperature, pvoltage;
|
||||
voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS],
|
||||
nf_cal[AR9300_MAX_CHAINS], nf_pwr[AR9300_MAX_CHAINS];
|
||||
int pfrequency, pcorrection, ptemperature, pvoltage,
|
||||
pnf_cal, pnf_pwr;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
mode = (frequency >= 4000);
|
||||
|
@ -4914,7 +4991,8 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
|
|||
for (ipier = 0; ipier < npier; ipier++) {
|
||||
if (!ar9003_hw_cal_pier_get(ah, mode, ipier, ichain,
|
||||
&pfrequency, &pcorrection,
|
||||
&ptemperature, &pvoltage)) {
|
||||
&ptemperature, &pvoltage,
|
||||
&pnf_cal, &pnf_pwr)) {
|
||||
fdiff = frequency - pfrequency;
|
||||
|
||||
/*
|
||||
|
@ -4936,6 +5014,8 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
|
|||
htemperature[ichain] =
|
||||
ptemperature;
|
||||
hvoltage[ichain] = pvoltage;
|
||||
hnf_cal[ichain] = pnf_cal;
|
||||
hnf_pwr[ichain] = pnf_pwr;
|
||||
}
|
||||
}
|
||||
if (fdiff >= 0) {
|
||||
|
@ -4952,6 +5032,8 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
|
|||
ltemperature[ichain] =
|
||||
ptemperature;
|
||||
lvoltage[ichain] = pvoltage;
|
||||
lnf_cal[ichain] = pnf_cal;
|
||||
lnf_pwr[ichain] = pnf_pwr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4960,15 +5042,20 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
|
|||
|
||||
/* interpolate */
|
||||
for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
|
||||
ath_dbg(common, EEPROM, "ch=%d f=%d low=%d %d h=%d %d\n",
|
||||
ath_dbg(common, EEPROM,
|
||||
"ch=%d f=%d low=%d %d h=%d %d n=%d %d p=%d %d\n",
|
||||
ichain, frequency, lfrequency[ichain],
|
||||
lcorrection[ichain], hfrequency[ichain],
|
||||
hcorrection[ichain]);
|
||||
hcorrection[ichain], lnf_cal[ichain],
|
||||
hnf_cal[ichain], lnf_pwr[ichain],
|
||||
hnf_pwr[ichain]);
|
||||
/* they're the same, so just pick one */
|
||||
if (hfrequency[ichain] == lfrequency[ichain]) {
|
||||
correction[ichain] = lcorrection[ichain];
|
||||
voltage[ichain] = lvoltage[ichain];
|
||||
temperature[ichain] = ltemperature[ichain];
|
||||
nf_cal[ichain] = lnf_cal[ichain];
|
||||
nf_pwr[ichain] = lnf_pwr[ichain];
|
||||
}
|
||||
/* the low frequency is good */
|
||||
else if (frequency - lfrequency[ichain] < 1000) {
|
||||
|
@ -4992,12 +5079,26 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
|
|||
hfrequency[ichain],
|
||||
lvoltage[ichain],
|
||||
hvoltage[ichain]);
|
||||
|
||||
nf_cal[ichain] = interpolate(frequency,
|
||||
lfrequency[ichain],
|
||||
hfrequency[ichain],
|
||||
lnf_cal[ichain],
|
||||
hnf_cal[ichain]);
|
||||
|
||||
nf_pwr[ichain] = interpolate(frequency,
|
||||
lfrequency[ichain],
|
||||
hfrequency[ichain],
|
||||
lnf_pwr[ichain],
|
||||
hnf_pwr[ichain]);
|
||||
}
|
||||
/* only low is good, use it */
|
||||
else {
|
||||
correction[ichain] = lcorrection[ichain];
|
||||
temperature[ichain] = ltemperature[ichain];
|
||||
voltage[ichain] = lvoltage[ichain];
|
||||
nf_cal[ichain] = lnf_cal[ichain];
|
||||
nf_pwr[ichain] = lnf_pwr[ichain];
|
||||
}
|
||||
}
|
||||
/* only high is good, use it */
|
||||
|
@ -5005,10 +5106,14 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
|
|||
correction[ichain] = hcorrection[ichain];
|
||||
temperature[ichain] = htemperature[ichain];
|
||||
voltage[ichain] = hvoltage[ichain];
|
||||
nf_cal[ichain] = hnf_cal[ichain];
|
||||
nf_pwr[ichain] = hnf_pwr[ichain];
|
||||
} else { /* nothing is good, presume 0???? */
|
||||
correction[ichain] = 0;
|
||||
temperature[ichain] = 0;
|
||||
voltage[ichain] = 0;
|
||||
nf_cal[ichain] = 0;
|
||||
nf_pwr[ichain] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5019,6 +5124,16 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
|
|||
"for frequency=%d, calibration correction = %d %d %d\n",
|
||||
frequency, correction[0], correction[1], correction[2]);
|
||||
|
||||
/* Store calibrated noise floor values */
|
||||
for (ichain = 0; ichain < AR5416_MAX_CHAINS; ichain++)
|
||||
if (mode) {
|
||||
ah->nf_5g.cal[ichain] = nf_cal[ichain];
|
||||
ah->nf_5g.pwr[ichain] = nf_pwr[ichain];
|
||||
} else {
|
||||
ah->nf_2g.cal[ichain] = nf_cal[ichain];
|
||||
ah->nf_2g.pwr[ichain] = nf_pwr[ichain];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,16 @@
|
|||
*/
|
||||
#define AR9300_PWR_TABLE_OFFSET 0
|
||||
|
||||
/* Noise power data definitions
|
||||
* units are: 4 x dBm - NOISE_PWR_DATA_OFFSET
|
||||
* (e.g. -25 = (-25/4 - 90) = -96.25 dBm)
|
||||
* range (for 6 signed bits) is (-32 to 31) + offset => -122dBm to -59dBm
|
||||
* resolution (2 bits) is 0.25dBm
|
||||
*/
|
||||
#define NOISE_PWR_DATA_OFFSET -90
|
||||
#define NOISE_PWR_DBM_2_INT(_p) ((((_p) + 3) >> 2) + NOISE_PWR_DATA_OFFSET)
|
||||
#define N2DBM(_p) NOISE_PWR_DBM_2_INT(_p)
|
||||
|
||||
/* byte addressable */
|
||||
#define AR9300_EEPROM_SIZE (16*1024)
|
||||
|
||||
|
|
|
@ -58,19 +58,25 @@ static struct ath_nf_limits *ath9k_hw_get_nf_limits(struct ath_hw *ah,
|
|||
}
|
||||
|
||||
static s16 ath9k_hw_get_default_nf(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
struct ath9k_channel *chan,
|
||||
int chain)
|
||||
{
|
||||
return ath9k_hw_get_nf_limits(ah, chan)->nominal;
|
||||
s16 calib_nf = ath9k_hw_get_nf_limits(ah, chan)->cal[chain];
|
||||
|
||||
if (calib_nf)
|
||||
return calib_nf;
|
||||
else
|
||||
return ath9k_hw_get_nf_limits(ah, chan)->nominal;
|
||||
}
|
||||
|
||||
s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
s16 nf)
|
||||
{
|
||||
s8 noise = ATH_DEFAULT_NOISE_FLOOR;
|
||||
s8 noise = ath9k_hw_get_default_nf(ah, chan, 0);
|
||||
|
||||
if (nf) {
|
||||
s8 delta = nf - ATH9K_NF_CAL_NOISE_THRESH -
|
||||
ath9k_hw_get_default_nf(ah, chan);
|
||||
ath9k_hw_get_default_nf(ah, chan, 0);
|
||||
if (delta > 0)
|
||||
noise += delta;
|
||||
}
|
||||
|
@ -240,7 +246,7 @@ int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
|
|||
unsigned i, j;
|
||||
u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
s16 default_nf = ath9k_hw_get_default_nf(ah, chan);
|
||||
s16 default_nf = ath9k_hw_get_nf_limits(ah, chan)->nominal;
|
||||
u32 bb_agc_ctl = REG_READ(ah, AR_PHY_AGC_CONTROL);
|
||||
|
||||
if (ah->caldata)
|
||||
|
@ -258,8 +264,13 @@ int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
|
|||
nfval = ah->nf_override;
|
||||
else if (h)
|
||||
nfval = h[i].privNF;
|
||||
else
|
||||
nfval = default_nf;
|
||||
else {
|
||||
/* Try to get calibrated noise floor value */
|
||||
nfval =
|
||||
ath9k_hw_get_nf_limits(ah, chan)->cal[i];
|
||||
if (nfval > -60 || nfval < -127)
|
||||
nfval = default_nf;
|
||||
}
|
||||
|
||||
REG_RMW(ah, ah->nf_regs[i],
|
||||
(((u32) nfval << 1) & 0x1ff), 0x1ff);
|
||||
|
@ -429,20 +440,19 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
|
|||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath9k_nfcal_hist *h;
|
||||
s16 default_nf;
|
||||
int i, j;
|
||||
int i, j, k = 0;
|
||||
|
||||
ah->caldata->channel = chan->channel;
|
||||
ah->caldata->channelFlags = chan->channelFlags;
|
||||
h = ah->caldata->nfCalHist;
|
||||
default_nf = ath9k_hw_get_default_nf(ah, chan);
|
||||
for (i = 0; i < NUM_NF_READINGS; i++) {
|
||||
h[i].currIndex = 0;
|
||||
h[i].privNF = default_nf;
|
||||
h[i].privNF = ath9k_hw_get_default_nf(ah, chan, k);
|
||||
h[i].invalidNFcount = AR_PHY_CCA_FILTERWINDOW_LENGTH;
|
||||
for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
|
||||
h[i].nfCalBuffer[j] = default_nf;
|
||||
}
|
||||
for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++)
|
||||
h[i].nfCalBuffer[j] = h[i].privNF;
|
||||
if (++k >= AR5416_MAX_CHAINS)
|
||||
k = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -754,6 +754,8 @@ struct ath_nf_limits {
|
|||
s16 max;
|
||||
s16 min;
|
||||
s16 nominal;
|
||||
s16 cal[AR5416_MAX_CHAINS];
|
||||
s16 pwr[AR5416_MAX_CHAINS];
|
||||
};
|
||||
|
||||
enum ath_cal_list {
|
||||
|
|
|
@ -826,9 +826,9 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
|
|||
sc->rx.discard_next = false;
|
||||
|
||||
/*
|
||||
* Discard zero-length packets.
|
||||
* Discard zero-length packets and packets smaller than an ACK
|
||||
*/
|
||||
if (!rx_stats->rs_datalen) {
|
||||
if (rx_stats->rs_datalen < 10) {
|
||||
RX_STAT_INC(rx_len_err);
|
||||
goto corrupt;
|
||||
}
|
||||
|
|
|
@ -236,6 +236,14 @@ static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void wcn36xx_dxe_deinit_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn_ch)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc);
|
||||
dma_free_coherent(dev, size,wcn_ch->cpu_addr, wcn_ch->dma_addr);
|
||||
}
|
||||
|
||||
static void wcn36xx_dxe_init_tx_bd(struct wcn36xx_dxe_ch *ch,
|
||||
struct wcn36xx_dxe_mem_pool *pool)
|
||||
{
|
||||
|
@ -722,7 +730,11 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
|
|||
/***************************************/
|
||||
/* Init descriptors for TX LOW channel */
|
||||
/***************************************/
|
||||
wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_l_ch);
|
||||
ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_l_ch);
|
||||
if (ret) {
|
||||
dev_err(wcn->dev, "Error allocating descriptor\n");
|
||||
return ret;
|
||||
}
|
||||
wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool);
|
||||
|
||||
/* Write channel head to a NEXT register */
|
||||
|
@ -740,7 +752,12 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
|
|||
/***************************************/
|
||||
/* Init descriptors for TX HIGH channel */
|
||||
/***************************************/
|
||||
wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_h_ch);
|
||||
ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_h_ch);
|
||||
if (ret) {
|
||||
dev_err(wcn->dev, "Error allocating descriptor\n");
|
||||
goto out_err_txh_ch;
|
||||
}
|
||||
|
||||
wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool);
|
||||
|
||||
/* Write channel head to a NEXT register */
|
||||
|
@ -760,7 +777,12 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
|
|||
/***************************************/
|
||||
/* Init descriptors for RX LOW channel */
|
||||
/***************************************/
|
||||
wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_l_ch);
|
||||
ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_l_ch);
|
||||
if (ret) {
|
||||
dev_err(wcn->dev, "Error allocating descriptor\n");
|
||||
goto out_err_rxl_ch;
|
||||
}
|
||||
|
||||
|
||||
/* For RX we need to preallocated buffers */
|
||||
wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch);
|
||||
|
@ -790,7 +812,11 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
|
|||
/***************************************/
|
||||
/* Init descriptors for RX HIGH channel */
|
||||
/***************************************/
|
||||
wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_h_ch);
|
||||
ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_h_ch);
|
||||
if (ret) {
|
||||
dev_err(wcn->dev, "Error allocating descriptor\n");
|
||||
goto out_err_rxh_ch;
|
||||
}
|
||||
|
||||
/* For RX we need to prealocat buffers */
|
||||
wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch);
|
||||
|
@ -819,11 +845,19 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
|
|||
|
||||
ret = wcn36xx_dxe_request_irqs(wcn);
|
||||
if (ret < 0)
|
||||
goto out_err;
|
||||
goto out_err_irq;
|
||||
|
||||
return 0;
|
||||
|
||||
out_err:
|
||||
out_err_irq:
|
||||
wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_rx_h_ch);
|
||||
out_err_rxh_ch:
|
||||
wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_rx_l_ch);
|
||||
out_err_rxl_ch:
|
||||
wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_tx_h_ch);
|
||||
out_err_txh_ch:
|
||||
wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_tx_l_ch);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* Copyright (c) 2015 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -39,7 +40,8 @@ struct bl_dedicated_registers_v1 {
|
|||
/* valid only for version 2 and above */
|
||||
__le32 bl_assert_code; /* 0x880A58 BL Assert code */
|
||||
__le32 bl_assert_blink; /* 0x880A5C BL Assert Branch */
|
||||
__le32 bl_reserved[22]; /* 0x880A60 - 0x880AB4 */
|
||||
__le32 bl_shutdown_handshake; /* 0x880A60 BL cleaner shutdown */
|
||||
__le32 bl_reserved[21]; /* 0x880A64 - 0x880AB4 */
|
||||
__le32 bl_magic_number; /* 0x880AB8 BL Magic number */
|
||||
} __packed;
|
||||
|
||||
|
@ -58,4 +60,9 @@ struct bl_dedicated_registers_v0 {
|
|||
u8 mac_address[6]; /* 0x880A4c BL mac address */
|
||||
} __packed;
|
||||
|
||||
/* bits for bl_shutdown_handshake */
|
||||
#define BL_SHUTDOWN_HS_GRTD BIT(0)
|
||||
#define BL_SHUTDOWN_HS_RTD BIT(1)
|
||||
#define BL_SHUTDOWN_HS_PROT_VER(x) WIL_GET_BITS(x, 28, 31)
|
||||
|
||||
#endif /* BOOT_LOADER_EXPORT_H_ */
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2014,2016 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -58,15 +59,30 @@ struct wil_fw_record_comment { /* type == wil_fw_type_comment */
|
|||
u8 data[0]; /* free-form data [data_size], see above */
|
||||
} __packed;
|
||||
|
||||
/* Comment header - common for all comment record types */
|
||||
struct wil_fw_record_comment_hdr {
|
||||
__le32 magic;
|
||||
};
|
||||
|
||||
/* FW capabilities encoded inside a comment record */
|
||||
#define WIL_FW_CAPABILITIES_MAGIC (0xabcddcba)
|
||||
struct wil_fw_record_capabilities { /* type == wil_fw_type_comment */
|
||||
/* identifies capabilities record */
|
||||
__le32 magic;
|
||||
struct wil_fw_record_comment_hdr hdr;
|
||||
/* capabilities (variable size), see enum wmi_fw_capability */
|
||||
u8 capabilities[0];
|
||||
};
|
||||
|
||||
/* brd file info encoded inside a comment record */
|
||||
#define WIL_BRD_FILE_MAGIC (0xabcddcbb)
|
||||
struct wil_fw_record_brd_file { /* type == wil_fw_type_comment */
|
||||
/* identifies brd file record */
|
||||
struct wil_fw_record_comment_hdr hdr;
|
||||
__le32 version;
|
||||
__le32 base_addr;
|
||||
__le32 max_size_bytes;
|
||||
} __packed;
|
||||
|
||||
/* perform action
|
||||
* data_size = @head.size - offsetof(struct wil_fw_record_action, data)
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -128,14 +129,13 @@ static int fw_ignore_section(struct wil6210_priv *wil, const void *data,
|
|||
}
|
||||
|
||||
static int
|
||||
fw_handle_comment(struct wil6210_priv *wil, const void *data,
|
||||
size_t size)
|
||||
fw_handle_capabilities(struct wil6210_priv *wil, const void *data,
|
||||
size_t size)
|
||||
{
|
||||
const struct wil_fw_record_capabilities *rec = data;
|
||||
size_t capa_size;
|
||||
|
||||
if (size < sizeof(*rec) ||
|
||||
le32_to_cpu(rec->magic) != WIL_FW_CAPABILITIES_MAGIC) {
|
||||
if (size < sizeof(*rec)) {
|
||||
wil_hex_dump_fw("", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
data, size, true);
|
||||
return 0;
|
||||
|
@ -151,8 +151,56 @@ fw_handle_comment(struct wil6210_priv *wil, const void *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int fw_handle_data(struct wil6210_priv *wil, const void *data,
|
||||
size_t size)
|
||||
static int
|
||||
fw_handle_brd_file(struct wil6210_priv *wil, const void *data,
|
||||
size_t size)
|
||||
{
|
||||
const struct wil_fw_record_brd_file *rec = data;
|
||||
|
||||
if (size < sizeof(*rec)) {
|
||||
wil_hex_dump_fw("", DUMP_PREFIX_OFFSET, 16, 1,
|
||||
data, size, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wil->brd_file_addr = le32_to_cpu(rec->base_addr);
|
||||
wil->brd_file_max_size = le32_to_cpu(rec->max_size_bytes);
|
||||
|
||||
wil_dbg_fw(wil, "brd_file_addr 0x%x, brd_file_max_size %d\n",
|
||||
wil->brd_file_addr, wil->brd_file_max_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
fw_handle_comment(struct wil6210_priv *wil, const void *data,
|
||||
size_t size)
|
||||
{
|
||||
const struct wil_fw_record_comment_hdr *hdr = data;
|
||||
u32 magic;
|
||||
int rc = 0;
|
||||
|
||||
if (size < sizeof(*hdr))
|
||||
return 0;
|
||||
|
||||
magic = le32_to_cpu(hdr->magic);
|
||||
|
||||
switch (magic) {
|
||||
case WIL_FW_CAPABILITIES_MAGIC:
|
||||
wil_dbg_fw(wil, "magic is WIL_FW_CAPABILITIES_MAGIC\n");
|
||||
rc = fw_handle_capabilities(wil, data, size);
|
||||
break;
|
||||
case WIL_BRD_FILE_MAGIC:
|
||||
wil_dbg_fw(wil, "magic is WIL_BRD_FILE_MAGIC\n");
|
||||
rc = fw_handle_brd_file(wil, data, size);
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __fw_handle_data(struct wil6210_priv *wil, const void *data,
|
||||
size_t size, __le32 addr)
|
||||
{
|
||||
const struct wil_fw_record_data *d = data;
|
||||
void __iomem *dst;
|
||||
|
@ -163,16 +211,23 @@ static int fw_handle_data(struct wil6210_priv *wil, const void *data,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!wil_fw_addr_check(wil, &dst, d->addr, s, "address"))
|
||||
if (!wil_fw_addr_check(wil, &dst, addr, s, "address"))
|
||||
return -EINVAL;
|
||||
wil_dbg_fw(wil, "write [0x%08x] <== %zu bytes\n", le32_to_cpu(d->addr),
|
||||
s);
|
||||
wil_dbg_fw(wil, "write [0x%08x] <== %zu bytes\n", le32_to_cpu(addr), s);
|
||||
wil_memcpy_toio_32(dst, d->data, s);
|
||||
wmb(); /* finish before processing next record */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fw_handle_data(struct wil6210_priv *wil, const void *data,
|
||||
size_t size)
|
||||
{
|
||||
const struct wil_fw_record_data *d = data;
|
||||
|
||||
return __fw_handle_data(wil, data, size, d->addr);
|
||||
}
|
||||
|
||||
static int fw_handle_fill(struct wil6210_priv *wil, const void *data,
|
||||
size_t size)
|
||||
{
|
||||
|
@ -551,6 +606,100 @@ out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* wil_brd_process - process section from BRD file
|
||||
*
|
||||
* Return error code
|
||||
*/
|
||||
static int wil_brd_process(struct wil6210_priv *wil, const void *data,
|
||||
size_t size)
|
||||
{
|
||||
int rc = 0;
|
||||
const struct wil_fw_record_head *hdr = data;
|
||||
size_t s, hdr_sz;
|
||||
u16 type;
|
||||
|
||||
/* Assuming the board file includes only one header record and one data
|
||||
* record. Each record starts with wil_fw_record_head.
|
||||
*/
|
||||
if (size < sizeof(*hdr))
|
||||
return -EINVAL;
|
||||
s = sizeof(*hdr) + le32_to_cpu(hdr->size);
|
||||
if (s > size)
|
||||
return -EINVAL;
|
||||
|
||||
/* Skip the header record and handle the data record */
|
||||
hdr = (const void *)hdr + s;
|
||||
size -= s;
|
||||
if (size < sizeof(*hdr))
|
||||
return -EINVAL;
|
||||
hdr_sz = le32_to_cpu(hdr->size);
|
||||
|
||||
if (wil->brd_file_max_size && hdr_sz > wil->brd_file_max_size)
|
||||
return -EINVAL;
|
||||
if (sizeof(*hdr) + hdr_sz > size)
|
||||
return -EINVAL;
|
||||
if (hdr_sz % 4) {
|
||||
wil_err_fw(wil, "unaligned record size: %zu\n",
|
||||
hdr_sz);
|
||||
return -EINVAL;
|
||||
}
|
||||
type = le16_to_cpu(hdr->type);
|
||||
if (type != wil_fw_type_data) {
|
||||
wil_err_fw(wil, "invalid record type for board file: %d\n",
|
||||
type);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (hdr_sz < sizeof(struct wil_fw_record_data)) {
|
||||
wil_err_fw(wil, "data record too short: %zu\n", hdr_sz);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wil_dbg_fw(wil, "using addr from fw file: [0x%08x]\n",
|
||||
wil->brd_file_addr);
|
||||
|
||||
rc = __fw_handle_data(wil, &hdr[1], hdr_sz,
|
||||
cpu_to_le32(wil->brd_file_addr));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* wil_request_board - Request board file
|
||||
*
|
||||
* Request board image from the file
|
||||
* board file address and max size are read from FW file
|
||||
* during initialization.
|
||||
* brd file shall include one header and one data section.
|
||||
*
|
||||
* Return error code
|
||||
*/
|
||||
int wil_request_board(struct wil6210_priv *wil, const char *name)
|
||||
{
|
||||
int rc, dlen;
|
||||
const struct firmware *brd;
|
||||
|
||||
rc = request_firmware(&brd, name, wil_to_dev(wil));
|
||||
if (rc) {
|
||||
wil_err_fw(wil, "Failed to load brd %s\n", name);
|
||||
return rc;
|
||||
}
|
||||
wil_dbg_fw(wil, "Loading <%s>, %zu bytes\n", name, brd->size);
|
||||
|
||||
/* Verify the header */
|
||||
dlen = wil_fw_verify(wil, brd->data, brd->size);
|
||||
if (dlen < 0) {
|
||||
rc = dlen;
|
||||
goto out;
|
||||
}
|
||||
/* Process the data record */
|
||||
rc = wil_brd_process(wil, brd->data, dlen);
|
||||
|
||||
out:
|
||||
release_firmware(brd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* wil_fw_verify_file_exists - checks if firmware file exist
|
||||
*
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -395,8 +396,9 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
|
|||
wil6210_mask_irq_misc(wil, false);
|
||||
|
||||
if (isr & ISR_MISC_FW_ERROR) {
|
||||
u32 fw_assert_code = wil_r(wil, RGF_FW_ASSERT_CODE);
|
||||
u32 ucode_assert_code = wil_r(wil, RGF_UCODE_ASSERT_CODE);
|
||||
u32 fw_assert_code = wil_r(wil, wil->rgf_fw_assert_code_addr);
|
||||
u32 ucode_assert_code =
|
||||
wil_r(wil, wil->rgf_ucode_assert_code_addr);
|
||||
|
||||
wil_err(wil,
|
||||
"Firmware error detected, assert codes FW 0x%08x, UCODE 0x%08x\n",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -637,6 +638,98 @@ void wil_priv_deinit(struct wil6210_priv *wil)
|
|||
destroy_workqueue(wil->wmi_wq);
|
||||
}
|
||||
|
||||
static void wil_shutdown_bl(struct wil6210_priv *wil)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
wil_s(wil, RGF_USER_BL +
|
||||
offsetof(struct bl_dedicated_registers_v1,
|
||||
bl_shutdown_handshake), BL_SHUTDOWN_HS_GRTD);
|
||||
|
||||
usleep_range(100, 150);
|
||||
|
||||
val = wil_r(wil, RGF_USER_BL +
|
||||
offsetof(struct bl_dedicated_registers_v1,
|
||||
bl_shutdown_handshake));
|
||||
if (val & BL_SHUTDOWN_HS_RTD) {
|
||||
wil_dbg_misc(wil, "BL is ready for halt\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wil_err(wil, "BL did not report ready for halt\n");
|
||||
}
|
||||
|
||||
/* this format is used by ARC embedded CPU for instruction memory */
|
||||
static inline u32 ARC_me_imm32(u32 d)
|
||||
{
|
||||
return ((d & 0xffff0000) >> 16) | ((d & 0x0000ffff) << 16);
|
||||
}
|
||||
|
||||
/* defines access to interrupt vectors for wil_freeze_bl */
|
||||
#define ARC_IRQ_VECTOR_OFFSET(N) ((N) * 8)
|
||||
/* ARC long jump instruction */
|
||||
#define ARC_JAL_INST (0x20200f80)
|
||||
|
||||
static void wil_freeze_bl(struct wil6210_priv *wil)
|
||||
{
|
||||
u32 jal, upc, saved;
|
||||
u32 ivt3 = ARC_IRQ_VECTOR_OFFSET(3);
|
||||
|
||||
jal = wil_r(wil, wil->iccm_base + ivt3);
|
||||
if (jal != ARC_me_imm32(ARC_JAL_INST)) {
|
||||
wil_dbg_misc(wil, "invalid IVT entry found, skipping\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* prevent the target from entering deep sleep
|
||||
* and disabling memory access
|
||||
*/
|
||||
saved = wil_r(wil, RGF_USER_USAGE_8);
|
||||
wil_w(wil, RGF_USER_USAGE_8, saved | BIT_USER_PREVENT_DEEP_SLEEP);
|
||||
usleep_range(20, 25); /* let the BL process the bit */
|
||||
|
||||
/* redirect to endless loop in the INT_L1 context and let it trap */
|
||||
wil_w(wil, wil->iccm_base + ivt3 + 4, ARC_me_imm32(ivt3));
|
||||
usleep_range(20, 25); /* let the BL get into the trap */
|
||||
|
||||
/* verify the BL is frozen */
|
||||
upc = wil_r(wil, RGF_USER_CPU_PC);
|
||||
if (upc < ivt3 || (upc > (ivt3 + 8)))
|
||||
wil_dbg_misc(wil, "BL freeze failed, PC=0x%08X\n", upc);
|
||||
|
||||
wil_w(wil, RGF_USER_USAGE_8, saved);
|
||||
}
|
||||
|
||||
static void wil_bl_prepare_halt(struct wil6210_priv *wil)
|
||||
{
|
||||
u32 tmp, ver;
|
||||
|
||||
/* before halting device CPU driver must make sure BL is not accessing
|
||||
* host memory. This is done differently depending on BL version:
|
||||
* 1. For very old BL versions the procedure is skipped
|
||||
* (not supported).
|
||||
* 2. For old BL version we use a special trick to freeze the BL
|
||||
* 3. For new BL versions we shutdown the BL using handshake procedure.
|
||||
*/
|
||||
tmp = wil_r(wil, RGF_USER_BL +
|
||||
offsetof(struct bl_dedicated_registers_v0,
|
||||
boot_loader_struct_version));
|
||||
if (!tmp) {
|
||||
wil_dbg_misc(wil, "old BL, skipping halt preperation\n");
|
||||
return;
|
||||
}
|
||||
|
||||
tmp = wil_r(wil, RGF_USER_BL +
|
||||
offsetof(struct bl_dedicated_registers_v1,
|
||||
bl_shutdown_handshake));
|
||||
ver = BL_SHUTDOWN_HS_PROT_VER(tmp);
|
||||
|
||||
if (ver > 0)
|
||||
wil_shutdown_bl(wil);
|
||||
else
|
||||
wil_freeze_bl(wil);
|
||||
}
|
||||
|
||||
static inline void wil_halt_cpu(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_w(wil, RGF_USER_USER_CPU_0, BIT_USER_USER_CPU_MAN_RST);
|
||||
|
@ -670,7 +763,7 @@ static void wil_set_oob_mode(struct wil6210_priv *wil, u8 mode)
|
|||
}
|
||||
}
|
||||
|
||||
static int wil_target_reset(struct wil6210_priv *wil)
|
||||
static int wil_target_reset(struct wil6210_priv *wil, int no_flash)
|
||||
{
|
||||
int delay = 0;
|
||||
u32 x, x1 = 0;
|
||||
|
@ -684,9 +777,16 @@ static int wil_target_reset(struct wil6210_priv *wil)
|
|||
|
||||
wil_halt_cpu(wil);
|
||||
|
||||
/* clear all boot loader "ready" bits */
|
||||
wil_w(wil, RGF_USER_BL +
|
||||
offsetof(struct bl_dedicated_registers_v0, boot_loader_ready), 0);
|
||||
if (!no_flash) {
|
||||
/* clear all boot loader "ready" bits */
|
||||
wil_w(wil, RGF_USER_BL +
|
||||
offsetof(struct bl_dedicated_registers_v0,
|
||||
boot_loader_ready), 0);
|
||||
/* this should be safe to write even with old BLs */
|
||||
wil_w(wil, RGF_USER_BL +
|
||||
offsetof(struct bl_dedicated_registers_v1,
|
||||
bl_shutdown_handshake), 0);
|
||||
}
|
||||
/* Clear Fw Download notification */
|
||||
wil_c(wil, RGF_USER_USAGE_6, BIT(0));
|
||||
|
||||
|
@ -727,21 +827,33 @@ static int wil_target_reset(struct wil6210_priv *wil)
|
|||
wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
|
||||
|
||||
/* wait until device ready. typical time is 20..80 msec */
|
||||
do {
|
||||
msleep(RST_DELAY);
|
||||
x = wil_r(wil, RGF_USER_BL +
|
||||
offsetof(struct bl_dedicated_registers_v0,
|
||||
boot_loader_ready));
|
||||
if (x1 != x) {
|
||||
wil_dbg_misc(wil, "BL.ready 0x%08x => 0x%08x\n", x1, x);
|
||||
x1 = x;
|
||||
}
|
||||
if (delay++ > RST_COUNT) {
|
||||
wil_err(wil, "Reset not completed, bl.ready 0x%08x\n",
|
||||
x);
|
||||
return -ETIME;
|
||||
}
|
||||
} while (x != BL_READY);
|
||||
if (no_flash)
|
||||
do {
|
||||
msleep(RST_DELAY);
|
||||
x = wil_r(wil, USER_EXT_USER_PMU_3);
|
||||
if (delay++ > RST_COUNT) {
|
||||
wil_err(wil, "Reset not completed, PMU_3 0x%08x\n",
|
||||
x);
|
||||
return -ETIME;
|
||||
}
|
||||
} while ((x & BIT_PMU_DEVICE_RDY) == 0);
|
||||
else
|
||||
do {
|
||||
msleep(RST_DELAY);
|
||||
x = wil_r(wil, RGF_USER_BL +
|
||||
offsetof(struct bl_dedicated_registers_v0,
|
||||
boot_loader_ready));
|
||||
if (x1 != x) {
|
||||
wil_dbg_misc(wil, "BL.ready 0x%08x => 0x%08x\n",
|
||||
x1, x);
|
||||
x1 = x;
|
||||
}
|
||||
if (delay++ > RST_COUNT) {
|
||||
wil_err(wil, "Reset not completed, bl.ready 0x%08x\n",
|
||||
x);
|
||||
return -ETIME;
|
||||
}
|
||||
} while (x != BL_READY);
|
||||
|
||||
wil_c(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
|
||||
|
||||
|
@ -749,6 +861,21 @@ static int wil_target_reset(struct wil6210_priv *wil)
|
|||
wil_s(wil, RGF_DMA_OFUL_NID_0, BIT_DMA_OFUL_NID_0_RX_EXT_TR_EN |
|
||||
BIT_DMA_OFUL_NID_0_RX_EXT_A3_SRC);
|
||||
|
||||
if (no_flash) {
|
||||
/* Reset OTP HW vectors to fit 40MHz */
|
||||
wil_w(wil, RGF_USER_XPM_IFC_RD_TIME1, 0x60001);
|
||||
wil_w(wil, RGF_USER_XPM_IFC_RD_TIME2, 0x20027);
|
||||
wil_w(wil, RGF_USER_XPM_IFC_RD_TIME3, 0x1);
|
||||
wil_w(wil, RGF_USER_XPM_IFC_RD_TIME4, 0x20027);
|
||||
wil_w(wil, RGF_USER_XPM_IFC_RD_TIME5, 0x30003);
|
||||
wil_w(wil, RGF_USER_XPM_IFC_RD_TIME6, 0x20002);
|
||||
wil_w(wil, RGF_USER_XPM_IFC_RD_TIME7, 0x60001);
|
||||
wil_w(wil, RGF_USER_XPM_IFC_RD_TIME8, 0x60001);
|
||||
wil_w(wil, RGF_USER_XPM_IFC_RD_TIME9, 0x60001);
|
||||
wil_w(wil, RGF_USER_XPM_IFC_RD_TIME10, 0x60001);
|
||||
wil_w(wil, RGF_USER_XPM_RD_DOUT_SAMPLE_TIME, 0x57);
|
||||
}
|
||||
|
||||
wil_dbg_misc(wil, "Reset completed in %d ms\n", delay * RST_DELAY);
|
||||
return 0;
|
||||
}
|
||||
|
@ -906,6 +1033,27 @@ static void wil_bl_crash_info(struct wil6210_priv *wil, bool is_err)
|
|||
}
|
||||
}
|
||||
|
||||
static int wil_get_otp_info(struct wil6210_priv *wil)
|
||||
{
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
struct wiphy *wiphy = wil_to_wiphy(wil);
|
||||
u8 mac[8];
|
||||
|
||||
wil_memcpy_fromio_32(mac, wil->csr + HOSTADDR(RGF_OTP_MAC),
|
||||
sizeof(mac));
|
||||
if (!is_valid_ether_addr(mac)) {
|
||||
wil_err(wil, "Invalid MAC %pM\n", mac);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ether_addr_copy(ndev->perm_addr, mac);
|
||||
ether_addr_copy(wiphy->perm_addr, mac);
|
||||
if (!is_valid_ether_addr(ndev->dev_addr))
|
||||
ether_addr_copy(ndev->dev_addr, mac);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wil_wait_for_fw_ready(struct wil6210_priv *wil)
|
||||
{
|
||||
ulong to = msecs_to_jiffies(1000);
|
||||
|
@ -999,6 +1147,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
|
|||
{
|
||||
int rc;
|
||||
unsigned long status_flags = BIT(wil_status_resetting);
|
||||
int no_flash;
|
||||
|
||||
wil_dbg_misc(wil, "reset\n");
|
||||
|
||||
|
@ -1074,20 +1223,28 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
|
|||
flush_workqueue(wil->wq_service);
|
||||
flush_workqueue(wil->wmi_wq);
|
||||
|
||||
wil_bl_crash_info(wil, false);
|
||||
no_flash = test_bit(hw_capa_no_flash, wil->hw_capa);
|
||||
if (!no_flash)
|
||||
wil_bl_crash_info(wil, false);
|
||||
wil_disable_irq(wil);
|
||||
rc = wil_target_reset(wil);
|
||||
rc = wil_target_reset(wil, no_flash);
|
||||
wil6210_clear_irq(wil);
|
||||
wil_enable_irq(wil);
|
||||
wil_rx_fini(wil);
|
||||
if (rc) {
|
||||
wil_bl_crash_info(wil, true);
|
||||
if (!no_flash)
|
||||
wil_bl_crash_info(wil, true);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = wil_get_bl_info(wil);
|
||||
if (rc == -EAGAIN && !load_fw) /* ignore RF error if not going up */
|
||||
rc = 0;
|
||||
if (no_flash) {
|
||||
rc = wil_get_otp_info(wil);
|
||||
} else {
|
||||
rc = wil_get_bl_info(wil);
|
||||
if (rc == -EAGAIN && !load_fw)
|
||||
/* ignore RF error if not going up */
|
||||
rc = 0;
|
||||
}
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
|
@ -1096,13 +1253,21 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
|
|||
wil_info(wil, "Use firmware <%s> + board <%s>\n",
|
||||
wil->wil_fw_name, WIL_BOARD_FILE_NAME);
|
||||
|
||||
if (!no_flash)
|
||||
wil_bl_prepare_halt(wil);
|
||||
|
||||
wil_halt_cpu(wil);
|
||||
memset(wil->fw_version, 0, sizeof(wil->fw_version));
|
||||
/* Loading f/w from the file */
|
||||
rc = wil_request_firmware(wil, wil->wil_fw_name, true);
|
||||
if (rc)
|
||||
goto out;
|
||||
rc = wil_request_firmware(wil, WIL_BOARD_FILE_NAME, true);
|
||||
if (wil->brd_file_addr)
|
||||
rc = wil_request_board(wil, WIL_BOARD_FILE_NAME);
|
||||
else
|
||||
rc = wil_request_firmware(wil,
|
||||
WIL_BOARD_FILE_NAME,
|
||||
true);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -35,15 +36,16 @@ static int wil6210_pm_notify(struct notifier_block *notify_block,
|
|||
unsigned long mode, void *unused);
|
||||
|
||||
static
|
||||
void wil_set_capabilities(struct wil6210_priv *wil)
|
||||
int wil_set_capabilities(struct wil6210_priv *wil)
|
||||
{
|
||||
const char *wil_fw_name;
|
||||
u32 jtag_id = wil_r(wil, RGF_USER_JTAG_DEV_ID);
|
||||
u8 chip_revision = (wil_r(wil, RGF_USER_REVISION_ID) &
|
||||
RGF_USER_REVISION_ID_MASK);
|
||||
int platform_capa;
|
||||
struct fw_map *iccm_section, *sct;
|
||||
|
||||
bitmap_zero(wil->hw_capabilities, hw_capability_last);
|
||||
bitmap_zero(wil->hw_capa, hw_capa_last);
|
||||
bitmap_zero(wil->fw_capabilities, WMI_FW_CAPABILITY_MAX);
|
||||
bitmap_zero(wil->platform_capa, WIL_PLATFORM_CAPA_MAX);
|
||||
wil->wil_fw_name = ftm_mode ? WIL_FW_NAME_FTM_DEFAULT :
|
||||
|
@ -52,6 +54,8 @@ void wil_set_capabilities(struct wil6210_priv *wil)
|
|||
|
||||
switch (jtag_id) {
|
||||
case JTAG_DEV_ID_SPARROW:
|
||||
memcpy(fw_mapping, sparrow_fw_mapping,
|
||||
sizeof(sparrow_fw_mapping));
|
||||
switch (chip_revision) {
|
||||
case REVISION_ID_SPARROW_D0:
|
||||
wil->hw_name = "Sparrow D0";
|
||||
|
@ -61,6 +65,12 @@ void wil_set_capabilities(struct wil6210_priv *wil)
|
|||
|
||||
if (wil_fw_verify_file_exists(wil, wil_fw_name))
|
||||
wil->wil_fw_name = wil_fw_name;
|
||||
sct = wil_find_fw_mapping("mac_rgf_ext");
|
||||
if (!sct) {
|
||||
wil_err(wil, "mac_rgf_ext section not found in fw_mapping\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(sct, &sparrow_d0_mac_rgf_ext, sizeof(*sct));
|
||||
break;
|
||||
case REVISION_ID_SPARROW_B0:
|
||||
wil->hw_name = "Sparrow B0";
|
||||
|
@ -71,15 +81,36 @@ void wil_set_capabilities(struct wil6210_priv *wil)
|
|||
wil->hw_version = HW_VER_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
wil->rgf_fw_assert_code_addr = SPARROW_RGF_FW_ASSERT_CODE;
|
||||
wil->rgf_ucode_assert_code_addr = SPARROW_RGF_UCODE_ASSERT_CODE;
|
||||
break;
|
||||
case JTAG_DEV_ID_TALYN:
|
||||
wil->hw_name = "Talyn";
|
||||
wil->hw_version = HW_VER_TALYN;
|
||||
memcpy(fw_mapping, talyn_fw_mapping, sizeof(talyn_fw_mapping));
|
||||
wil->rgf_fw_assert_code_addr = TALYN_RGF_FW_ASSERT_CODE;
|
||||
wil->rgf_ucode_assert_code_addr = TALYN_RGF_UCODE_ASSERT_CODE;
|
||||
if (wil_r(wil, RGF_USER_OTP_HW_RD_MACHINE_1) &
|
||||
BIT_NO_FLASH_INDICATION)
|
||||
set_bit(hw_capa_no_flash, wil->hw_capa);
|
||||
break;
|
||||
default:
|
||||
wil_err(wil, "Unknown board hardware, chip_id 0x%08x, chip_revision 0x%08x\n",
|
||||
jtag_id, chip_revision);
|
||||
wil->hw_name = "Unknown";
|
||||
wil->hw_version = HW_VER_UNKNOWN;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wil_info(wil, "Board hardware is %s\n", wil->hw_name);
|
||||
iccm_section = wil_find_fw_mapping("fw_code");
|
||||
if (!iccm_section) {
|
||||
wil_err(wil, "fw_code section not found in fw_mapping\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
wil->iccm_base = iccm_section->host;
|
||||
|
||||
wil_info(wil, "Board hardware is %s, flash %sexist\n", wil->hw_name,
|
||||
test_bit(hw_capa_no_flash, wil->hw_capa) ? "doesn't " : "");
|
||||
|
||||
/* Get platform capabilities */
|
||||
if (wil->platform_ops.get_capa) {
|
||||
|
@ -92,6 +123,8 @@ void wil_set_capabilities(struct wil6210_priv *wil)
|
|||
/* extract FW capabilities from file without loading the FW */
|
||||
wil_request_firmware(wil, wil->wil_fw_name, false);
|
||||
wil_refresh_fw_capabilities(wil);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wil_disable_irq(struct wil6210_priv *wil)
|
||||
|
@ -302,7 +335,11 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
/* rollback to err_iounmap */
|
||||
wil_info(wil, "CSR at %pR -> 0x%p\n", &pdev->resource[0], wil->csr);
|
||||
|
||||
wil_set_capabilities(wil);
|
||||
rc = wil_set_capabilities(wil);
|
||||
if (rc) {
|
||||
wil_err(wil, "wil_set_capabilities failed, rc %d\n", rc);
|
||||
goto err_iounmap;
|
||||
}
|
||||
wil6210_clear_irq(wil);
|
||||
|
||||
/* FW should raise IRQ when ready */
|
||||
|
@ -378,6 +415,7 @@ static void wil_pcie_remove(struct pci_dev *pdev)
|
|||
static const struct pci_device_id wil6210_pcie_ids[] = {
|
||||
{ PCI_DEVICE(0x1ae9, 0x0310) },
|
||||
{ PCI_DEVICE(0x1ae9, 0x0302) }, /* same as above, firmware broken */
|
||||
{ PCI_DEVICE(0x17cb, 0x1201) }, /* Talyn */
|
||||
{ /* end: all zeroes */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -169,6 +170,7 @@ struct RGF_ICR {
|
|||
#define HW_MACHINE_BOOT_DONE (0x3fffffd)
|
||||
#define RGF_USER_USER_CPU_0 (0x8801e0)
|
||||
#define BIT_USER_USER_CPU_MAN_RST BIT(1) /* user_cpu_man_rst */
|
||||
#define RGF_USER_CPU_PC (0x8801e8)
|
||||
#define RGF_USER_MAC_CPU_0 (0x8801fc)
|
||||
#define BIT_USER_MAC_CPU_MAN_RST BIT(1) /* mac_cpu_man_rst */
|
||||
#define RGF_USER_USER_SCRATCH_PAD (0x8802bc)
|
||||
|
@ -194,6 +196,19 @@ struct RGF_ICR {
|
|||
#define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1 (0x880c2c)
|
||||
#define RGF_USER_SPARROW_M_4 (0x880c50) /* Sparrow */
|
||||
#define BIT_SPARROW_M_4_SEL_SLEEP_OR_REF BIT(2)
|
||||
#define RGF_USER_OTP_HW_RD_MACHINE_1 (0x880ce0)
|
||||
#define BIT_NO_FLASH_INDICATION BIT(8)
|
||||
#define RGF_USER_XPM_IFC_RD_TIME1 (0x880cec)
|
||||
#define RGF_USER_XPM_IFC_RD_TIME2 (0x880cf0)
|
||||
#define RGF_USER_XPM_IFC_RD_TIME3 (0x880cf4)
|
||||
#define RGF_USER_XPM_IFC_RD_TIME4 (0x880cf8)
|
||||
#define RGF_USER_XPM_IFC_RD_TIME5 (0x880cfc)
|
||||
#define RGF_USER_XPM_IFC_RD_TIME6 (0x880d00)
|
||||
#define RGF_USER_XPM_IFC_RD_TIME7 (0x880d04)
|
||||
#define RGF_USER_XPM_IFC_RD_TIME8 (0x880d08)
|
||||
#define RGF_USER_XPM_IFC_RD_TIME9 (0x880d0c)
|
||||
#define RGF_USER_XPM_IFC_RD_TIME10 (0x880d10)
|
||||
#define RGF_USER_XPM_RD_DOUT_SAMPLE_TIME (0x880d64)
|
||||
|
||||
#define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */
|
||||
#define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0)
|
||||
|
@ -284,22 +299,33 @@ struct RGF_ICR {
|
|||
#define RGF_CAF_PLL_LOCK_STATUS (0x88afec)
|
||||
#define BIT_CAF_OSC_DIG_XTAL_STABLE BIT(0)
|
||||
|
||||
#define USER_EXT_USER_PMU_3 (0x88d00c)
|
||||
#define BIT_PMU_DEVICE_RDY BIT(0)
|
||||
|
||||
#define RGF_USER_JTAG_DEV_ID (0x880b34) /* device ID */
|
||||
#define JTAG_DEV_ID_SPARROW (0x2632072f)
|
||||
#define JTAG_DEV_ID_TALYN (0x7e0e1)
|
||||
|
||||
#define RGF_USER_REVISION_ID (0x88afe4)
|
||||
#define RGF_USER_REVISION_ID_MASK (3)
|
||||
#define REVISION_ID_SPARROW_B0 (0x0)
|
||||
#define REVISION_ID_SPARROW_D0 (0x3)
|
||||
|
||||
#define RGF_OTP_MAC (0x8a0620)
|
||||
|
||||
/* crash codes for FW/Ucode stored here */
|
||||
#define RGF_FW_ASSERT_CODE (0x91f020)
|
||||
#define RGF_UCODE_ASSERT_CODE (0x91f028)
|
||||
|
||||
/* ASSERT RGFs */
|
||||
#define SPARROW_RGF_FW_ASSERT_CODE (0x91f020)
|
||||
#define SPARROW_RGF_UCODE_ASSERT_CODE (0x91f028)
|
||||
#define TALYN_RGF_FW_ASSERT_CODE (0xa37020)
|
||||
#define TALYN_RGF_UCODE_ASSERT_CODE (0xa37028)
|
||||
|
||||
enum {
|
||||
HW_VER_UNKNOWN,
|
||||
HW_VER_SPARROW_B0, /* REVISION_ID_SPARROW_B0 */
|
||||
HW_VER_SPARROW_D0, /* REVISION_ID_SPARROW_D0 */
|
||||
HW_VER_TALYN, /* JTAG_DEV_ID_TALYN */
|
||||
};
|
||||
|
||||
/* popular locations */
|
||||
|
@ -315,6 +341,10 @@ enum {
|
|||
#define WIL_DATA_COMPLETION_TO_MS 200
|
||||
|
||||
/* Hardware definitions end */
|
||||
#define SPARROW_FW_MAPPING_TABLE_SIZE 10
|
||||
#define TALYN_FW_MAPPING_TABLE_SIZE 13
|
||||
#define MAX_FW_MAPPING_TABLE_SIZE 13
|
||||
|
||||
struct fw_map {
|
||||
u32 from; /* linker address - from, inclusive */
|
||||
u32 to; /* linker address - to, exclusive */
|
||||
|
@ -324,7 +354,10 @@ struct fw_map {
|
|||
};
|
||||
|
||||
/* array size should be in sync with actual definition in the wmi.c */
|
||||
extern const struct fw_map fw_mapping[10];
|
||||
extern const struct fw_map sparrow_fw_mapping[SPARROW_FW_MAPPING_TABLE_SIZE];
|
||||
extern const struct fw_map sparrow_d0_mac_rgf_ext;
|
||||
extern const struct fw_map talyn_fw_mapping[TALYN_FW_MAPPING_TABLE_SIZE];
|
||||
extern struct fw_map fw_mapping[MAX_FW_MAPPING_TABLE_SIZE];
|
||||
|
||||
/**
|
||||
* mk_cidxtid - construct @cidxtid field
|
||||
|
@ -570,7 +603,8 @@ enum {
|
|||
};
|
||||
|
||||
enum {
|
||||
hw_capability_last
|
||||
hw_capa_no_flash,
|
||||
hw_capa_last
|
||||
};
|
||||
|
||||
struct wil_probe_client_req {
|
||||
|
@ -646,7 +680,10 @@ struct wil6210_priv {
|
|||
u8 chip_revision;
|
||||
const char *hw_name;
|
||||
const char *wil_fw_name;
|
||||
DECLARE_BITMAP(hw_capabilities, hw_capability_last);
|
||||
char *board_file;
|
||||
u32 brd_file_addr;
|
||||
u32 brd_file_max_size;
|
||||
DECLARE_BITMAP(hw_capa, hw_capa_last);
|
||||
DECLARE_BITMAP(fw_capabilities, WMI_FW_CAPABILITY_MAX);
|
||||
DECLARE_BITMAP(platform_capa, WIL_PLATFORM_CAPA_MAX);
|
||||
u8 n_mids; /* number of additional MIDs as reported by FW */
|
||||
|
@ -720,7 +757,7 @@ struct wil6210_priv {
|
|||
atomic_t isr_count_rx, isr_count_tx;
|
||||
/* debugfs */
|
||||
struct dentry *debug;
|
||||
struct wil_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)];
|
||||
struct wil_blob_wrapper blobs[MAX_FW_MAPPING_TABLE_SIZE];
|
||||
u8 discovery_mode;
|
||||
u8 abft_len;
|
||||
u8 wakeup_trigger;
|
||||
|
@ -755,6 +792,10 @@ struct wil6210_priv {
|
|||
bool suspend_resp_comp;
|
||||
u32 bus_request_kbps;
|
||||
u32 bus_request_kbps_pre_suspend;
|
||||
|
||||
u32 rgf_fw_assert_code_addr;
|
||||
u32 rgf_ucode_assert_code_addr;
|
||||
u32 iccm_base;
|
||||
};
|
||||
|
||||
#define wil_to_wiphy(i) (i->wdev->wiphy)
|
||||
|
@ -880,6 +921,7 @@ void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r);
|
|||
int wil_find_cid(struct wil6210_priv *wil, const u8 *mac);
|
||||
void wil_set_ethtoolops(struct net_device *ndev);
|
||||
|
||||
struct fw_map *wil_find_fw_mapping(const char *section);
|
||||
void __iomem *wmi_buffer_block(struct wil6210_priv *wil, __le32 ptr, u32 size);
|
||||
void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr);
|
||||
void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr);
|
||||
|
@ -1013,6 +1055,7 @@ int wil_iftype_nl2wmi(enum nl80211_iftype type);
|
|||
|
||||
int wil_request_firmware(struct wil6210_priv *wil, const char *name,
|
||||
bool load);
|
||||
int wil_request_board(struct wil6210_priv *wil, const char *name);
|
||||
bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name);
|
||||
|
||||
void wil_pm_runtime_allow(struct wil6210_priv *wil);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -70,23 +71,23 @@ MODULE_PARM_DESC(led_id,
|
|||
* On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing
|
||||
* AHB addresses starting from 0x880000
|
||||
*
|
||||
* Internally, firmware uses addresses that allows faster access but
|
||||
* Internally, firmware uses addresses that allow faster access but
|
||||
* are invisible from the host. To read from these addresses, alternative
|
||||
* AHB address must be used.
|
||||
*
|
||||
* Memory mapping
|
||||
* Linker address PCI/Host address
|
||||
* 0x880000 .. 0xa80000 2Mb BAR0
|
||||
* 0x800000 .. 0x807000 0x900000 .. 0x907000 28k DCCM
|
||||
* 0x840000 .. 0x857000 0x908000 .. 0x91f000 92k PERIPH
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fw_mapping provides memory remapping table
|
||||
* @sparrow_fw_mapping provides memory remapping table for sparrow
|
||||
*
|
||||
* array size should be in sync with the declaration in the wil6210.h
|
||||
*
|
||||
* Sparrow memory mapping:
|
||||
* Linker address PCI/Host address
|
||||
* 0x880000 .. 0xa80000 2Mb BAR0
|
||||
* 0x800000 .. 0x808000 0x900000 .. 0x908000 32k DCCM
|
||||
* 0x840000 .. 0x860000 0x908000 .. 0x928000 128k PERIPH
|
||||
*/
|
||||
const struct fw_map fw_mapping[] = {
|
||||
const struct fw_map sparrow_fw_mapping[] = {
|
||||
/* FW code RAM 256k */
|
||||
{0x000000, 0x040000, 0x8c0000, "fw_code", true},
|
||||
/* FW data RAM 32k */
|
||||
|
@ -112,6 +113,59 @@ const struct fw_map fw_mapping[] = {
|
|||
{0x800000, 0x804000, 0x940000, "uc_data", false},
|
||||
};
|
||||
|
||||
/**
|
||||
* @sparrow_d0_mac_rgf_ext - mac_rgf_ext section for Sparrow D0
|
||||
* it is a bit larger to support extra features
|
||||
*/
|
||||
const struct fw_map sparrow_d0_mac_rgf_ext = {
|
||||
0x88c000, 0x88c500, 0x88c000, "mac_rgf_ext", true
|
||||
};
|
||||
|
||||
/**
|
||||
* @talyn_fw_mapping provides memory remapping table for Talyn
|
||||
*
|
||||
* array size should be in sync with the declaration in the wil6210.h
|
||||
*
|
||||
* Talyn memory mapping:
|
||||
* Linker address PCI/Host address
|
||||
* 0x880000 .. 0xc80000 4Mb BAR0
|
||||
* 0x800000 .. 0x820000 0xa00000 .. 0xa20000 128k DCCM
|
||||
* 0x840000 .. 0x858000 0xa20000 .. 0xa38000 96k PERIPH
|
||||
*/
|
||||
const struct fw_map talyn_fw_mapping[] = {
|
||||
/* FW code RAM 1M */
|
||||
{0x000000, 0x100000, 0x900000, "fw_code", true},
|
||||
/* FW data RAM 128k */
|
||||
{0x800000, 0x820000, 0xa00000, "fw_data", true},
|
||||
/* periph. data RAM 96k */
|
||||
{0x840000, 0x858000, 0xa20000, "fw_peri", true},
|
||||
/* various RGF 40k */
|
||||
{0x880000, 0x88a000, 0x880000, "rgf", true},
|
||||
/* AGC table 4k */
|
||||
{0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true},
|
||||
/* Pcie_ext_rgf 4k */
|
||||
{0x88b000, 0x88c000, 0x88b000, "rgf_ext", true},
|
||||
/* mac_ext_rgf 1344b */
|
||||
{0x88c000, 0x88c540, 0x88c000, "mac_rgf_ext", true},
|
||||
/* ext USER RGF 4k */
|
||||
{0x88d000, 0x88e000, 0x88d000, "ext_user_rgf", true},
|
||||
/* OTP 4k */
|
||||
{0x8a0000, 0x8a1000, 0x8a0000, "otp", true},
|
||||
/* DMA EXT RGF 64k */
|
||||
{0x8b0000, 0x8c0000, 0x8b0000, "dma_ext_rgf", true},
|
||||
/* upper area 1536k */
|
||||
{0x900000, 0xa80000, 0x900000, "upper", true},
|
||||
/* UCODE areas - accessible by debugfs blobs but not by
|
||||
* wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
|
||||
*/
|
||||
/* ucode code RAM 256k */
|
||||
{0x000000, 0x040000, 0xa38000, "uc_code", false},
|
||||
/* ucode data RAM 32k */
|
||||
{0x800000, 0x808000, 0xa78000, "uc_data", false},
|
||||
};
|
||||
|
||||
struct fw_map fw_mapping[MAX_FW_MAPPING_TABLE_SIZE];
|
||||
|
||||
struct blink_on_off_time led_blink_time[] = {
|
||||
{WIL_LED_BLINK_ON_SLOW_MS, WIL_LED_BLINK_OFF_SLOW_MS},
|
||||
{WIL_LED_BLINK_ON_MED_MS, WIL_LED_BLINK_OFF_MED_MS},
|
||||
|
@ -138,6 +192,24 @@ static u32 wmi_addr_remap(u32 x)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* find fw_mapping entry by section name
|
||||
* @section - section name
|
||||
*
|
||||
* Return pointer to section or NULL if not found
|
||||
*/
|
||||
struct fw_map *wil_find_fw_mapping(const char *section)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fw_mapping); i++)
|
||||
if (fw_mapping[i].name &&
|
||||
!strcmp(section, fw_mapping[i].name))
|
||||
return &fw_mapping[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check address validity for WMI buffer; remap if needed
|
||||
* @ptr - internal (linker) fw/ucode address
|
||||
|
|
Loading…
Reference in New Issue