Path: blob/main/sys/contrib/dev/mediatek/mt76/mt76x2/phy.c
48525 views
// SPDX-License-Identifier: ISC1/*2* Copyright (C) 2016 Felix Fietkau <[email protected]>3* Copyright (C) 2018 Lorenzo Bianconi <[email protected]>4*/56#include "mt76x2.h"7#include "eeprom.h"8#include "mcu.h"9#include "../mt76x02_phy.h"1011static void12mt76x2_adjust_high_lna_gain(struct mt76x02_dev *dev, int reg, s8 offset)13{14s8 gain;1516gain = FIELD_GET(MT_BBP_AGC_LNA_HIGH_GAIN,17mt76_rr(dev, MT_BBP(AGC, reg)));18gain -= offset / 2;19mt76_rmw_field(dev, MT_BBP(AGC, reg), MT_BBP_AGC_LNA_HIGH_GAIN, gain);20}2122static void23mt76x2_adjust_agc_gain(struct mt76x02_dev *dev, int reg, s8 offset)24{25s8 gain;2627gain = FIELD_GET(MT_BBP_AGC_GAIN, mt76_rr(dev, MT_BBP(AGC, reg)));28gain += offset;29mt76_rmw_field(dev, MT_BBP(AGC, reg), MT_BBP_AGC_GAIN, gain);30}3132void mt76x2_apply_gain_adj(struct mt76x02_dev *dev)33{34s8 *gain_adj = dev->cal.rx.high_gain;3536mt76x2_adjust_high_lna_gain(dev, 4, gain_adj[0]);37mt76x2_adjust_high_lna_gain(dev, 5, gain_adj[1]);3839mt76x2_adjust_agc_gain(dev, 8, gain_adj[0]);40mt76x2_adjust_agc_gain(dev, 9, gain_adj[1]);41}42EXPORT_SYMBOL_GPL(mt76x2_apply_gain_adj);4344void mt76x2_phy_set_txpower_regs(struct mt76x02_dev *dev,45enum nl80211_band band)46{47u32 pa_mode[2];48u32 pa_mode_adj;4950if (band == NL80211_BAND_2GHZ) {51pa_mode[0] = 0x010055ff;52pa_mode[1] = 0x00550055;5354mt76_wr(dev, MT_TX_ALC_CFG_2, 0x35160a00);55mt76_wr(dev, MT_TX_ALC_CFG_3, 0x35160a06);5657if (mt76x02_ext_pa_enabled(dev, band)) {58mt76_wr(dev, MT_RF_PA_MODE_ADJ0, 0x0000ec00);59mt76_wr(dev, MT_RF_PA_MODE_ADJ1, 0x0000ec00);60} else {61mt76_wr(dev, MT_RF_PA_MODE_ADJ0, 0xf4000200);62mt76_wr(dev, MT_RF_PA_MODE_ADJ1, 0xfa000200);63}64} else {65pa_mode[0] = 0x0000ffff;66pa_mode[1] = 0x00ff00ff;6768if (mt76x02_ext_pa_enabled(dev, band)) {69mt76_wr(dev, MT_TX_ALC_CFG_2, 0x2f0f0400);70mt76_wr(dev, MT_TX_ALC_CFG_3, 0x2f0f0476);71} else {72mt76_wr(dev, MT_TX_ALC_CFG_2, 0x1b0f0400);73mt76_wr(dev, MT_TX_ALC_CFG_3, 0x1b0f0476);74}7576if (mt76x02_ext_pa_enabled(dev, band))77pa_mode_adj = 0x04000000;78else79pa_mode_adj = 0;8081mt76_wr(dev, MT_RF_PA_MODE_ADJ0, pa_mode_adj);82mt76_wr(dev, MT_RF_PA_MODE_ADJ1, pa_mode_adj);83}8485mt76_wr(dev, MT_BB_PA_MODE_CFG0, pa_mode[0]);86mt76_wr(dev, MT_BB_PA_MODE_CFG1, pa_mode[1]);87mt76_wr(dev, MT_RF_PA_MODE_CFG0, pa_mode[0]);88mt76_wr(dev, MT_RF_PA_MODE_CFG1, pa_mode[1]);8990if (mt76x02_ext_pa_enabled(dev, band)) {91u32 val;9293if (band == NL80211_BAND_2GHZ)94val = 0x3c3c023c;95else96val = 0x363c023c;9798mt76_wr(dev, MT_TX0_RF_GAIN_CORR, val);99mt76_wr(dev, MT_TX1_RF_GAIN_CORR, val);100mt76_wr(dev, MT_TX_ALC_CFG_4, 0x00001818);101} else {102if (band == NL80211_BAND_2GHZ) {103u32 val = 0x0f3c3c3c;104105mt76_wr(dev, MT_TX0_RF_GAIN_CORR, val);106mt76_wr(dev, MT_TX1_RF_GAIN_CORR, val);107mt76_wr(dev, MT_TX_ALC_CFG_4, 0x00000606);108} else {109mt76_wr(dev, MT_TX0_RF_GAIN_CORR, 0x383c023c);110mt76_wr(dev, MT_TX1_RF_GAIN_CORR, 0x24282e28);111mt76_wr(dev, MT_TX_ALC_CFG_4, 0);112}113}114}115EXPORT_SYMBOL_GPL(mt76x2_phy_set_txpower_regs);116117static int118mt76x2_get_min_rate_power(struct mt76x02_rate_power *r)119{120int i;121s8 ret = 0;122123for (i = 0; i < sizeof(r->all); i++) {124if (!r->all[i])125continue;126127if (ret)128ret = min(ret, r->all[i]);129else130ret = r->all[i];131}132133return ret;134}135136void mt76x2_phy_set_txpower(struct mt76x02_dev *dev)137{138enum nl80211_chan_width width = dev->mphy.chandef.width;139struct ieee80211_channel *chan = dev->mphy.chandef.chan;140struct mt76x2_tx_power_info txp;141int txp_0, txp_1, delta = 0;142struct mt76x02_rate_power t = {};143int base_power, gain;144145mt76x2_get_power_info(dev, &txp, chan);146147if (width == NL80211_CHAN_WIDTH_40)148delta = txp.delta_bw40;149else if (width == NL80211_CHAN_WIDTH_80)150delta = txp.delta_bw80;151152mt76x2_get_rate_power(dev, &t, chan);153mt76x02_add_rate_power_offset(&t, txp.target_power + delta);154mt76x02_limit_rate_power(&t, dev->txpower_conf);155dev->mphy.txpower_cur = mt76x02_get_max_rate_power(&t);156157base_power = mt76x2_get_min_rate_power(&t);158delta = base_power - txp.target_power;159txp_0 = txp.chain[0].target_power + txp.chain[0].delta + delta;160txp_1 = txp.chain[1].target_power + txp.chain[1].delta + delta;161162gain = min(txp_0, txp_1);163if (gain < 0) {164base_power -= gain;165txp_0 -= gain;166txp_1 -= gain;167} else if (gain > 0x2f) {168base_power -= gain - 0x2f;169txp_0 = 0x2f;170txp_1 = 0x2f;171}172173mt76x02_add_rate_power_offset(&t, -base_power);174dev->target_power = txp.target_power;175dev->target_power_delta[0] = txp_0 - txp.chain[0].target_power;176dev->target_power_delta[1] = txp_1 - txp.chain[0].target_power;177dev->rate_power = t;178179mt76x02_phy_set_txpower(dev, txp_0, txp_1);180}181EXPORT_SYMBOL_GPL(mt76x2_phy_set_txpower);182183void mt76x2_configure_tx_delay(struct mt76x02_dev *dev,184enum nl80211_band band, u8 bw)185{186u32 cfg0, cfg1;187188if (mt76x02_ext_pa_enabled(dev, band)) {189cfg0 = bw ? 0x000b0c01 : 0x00101101;190cfg1 = 0x00011414;191} else {192cfg0 = bw ? 0x000b0b01 : 0x00101001;193cfg1 = 0x00021414;194}195mt76_wr(dev, MT_TX_SW_CFG0, cfg0);196mt76_wr(dev, MT_TX_SW_CFG1, cfg1);197198mt76_rmw_field(dev, MT_XIFS_TIME_CFG, MT_XIFS_TIME_CFG_OFDM_SIFS, 15);199}200EXPORT_SYMBOL_GPL(mt76x2_configure_tx_delay);201202void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev)203{204struct ieee80211_channel *chan = dev->mphy.chandef.chan;205struct mt76x2_tx_power_info txp;206struct mt76x2_tssi_comp t = {};207208if (!dev->cal.tssi_cal_done)209return;210211if (!dev->cal.tssi_comp_pending) {212/* TSSI trigger */213t.cal_mode = BIT(0);214mt76x2_mcu_tssi_comp(dev, &t);215dev->cal.tssi_comp_pending = true;216} else {217if (mt76_rr(dev, MT_BBP(CORE, 34)) & BIT(4))218return;219220dev->cal.tssi_comp_pending = false;221mt76x2_get_power_info(dev, &txp, chan);222223if (mt76x02_ext_pa_enabled(dev, chan->band))224t.pa_mode = 1;225226t.cal_mode = BIT(1);227t.slope0 = txp.chain[0].tssi_slope;228t.offset0 = txp.chain[0].tssi_offset;229t.slope1 = txp.chain[1].tssi_slope;230t.offset1 = txp.chain[1].tssi_offset;231mt76x2_mcu_tssi_comp(dev, &t);232233if (t.pa_mode || dev->cal.dpd_cal_done || dev->ed_tx_blocked)234return;235236usleep_range(10000, 20000);237mt76x02_mcu_calibrate(dev, MCU_CAL_DPD, chan->hw_value);238dev->cal.dpd_cal_done = true;239}240}241EXPORT_SYMBOL_GPL(mt76x2_phy_tssi_compensate);242243static void244mt76x2_phy_set_gain_val(struct mt76x02_dev *dev)245{246u32 val;247u8 gain_val[2];248249gain_val[0] = dev->cal.agc_gain_cur[0] - dev->cal.agc_gain_adjust;250gain_val[1] = dev->cal.agc_gain_cur[1] - dev->cal.agc_gain_adjust;251252val = 0x1836 << 16;253if (!mt76x2_has_ext_lna(dev) &&254dev->mphy.chandef.width >= NL80211_CHAN_WIDTH_40)255val = 0x1e42 << 16;256257if (mt76x2_has_ext_lna(dev) &&258dev->mphy.chandef.chan->band == NL80211_BAND_2GHZ &&259dev->mphy.chandef.width < NL80211_CHAN_WIDTH_40)260val = 0x0f36 << 16;261262val |= 0xf8;263264mt76_wr(dev, MT_BBP(AGC, 8),265val | FIELD_PREP(MT_BBP_AGC_GAIN, gain_val[0]));266mt76_wr(dev, MT_BBP(AGC, 9),267val | FIELD_PREP(MT_BBP_AGC_GAIN, gain_val[1]));268269if (dev->mphy.chandef.chan->flags & IEEE80211_CHAN_RADAR)270mt76x02_phy_dfs_adjust_agc(dev);271}272273void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev)274{275u8 *gain = dev->cal.agc_gain_init;276u8 low_gain_delta, gain_delta;277u32 agc_35, agc_37;278bool gain_change;279int low_gain;280u32 val;281282dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76, 0);283if (!dev->cal.avg_rssi_all)284dev->cal.avg_rssi_all = -75;285286low_gain = (dev->cal.avg_rssi_all > mt76x02_get_rssi_gain_thresh(dev)) +287(dev->cal.avg_rssi_all > mt76x02_get_low_rssi_gain_thresh(dev));288289gain_change = dev->cal.low_gain < 0 ||290(dev->cal.low_gain & 2) ^ (low_gain & 2);291dev->cal.low_gain = low_gain;292293if (!gain_change) {294if (mt76x02_phy_adjust_vga_gain(dev))295mt76x2_phy_set_gain_val(dev);296return;297}298299if (dev->mphy.chandef.width == NL80211_CHAN_WIDTH_80) {300mt76_wr(dev, MT_BBP(RXO, 14), 0x00560211);301val = mt76_rr(dev, MT_BBP(AGC, 26)) & ~0xf;302if (low_gain == 2)303val |= 0x3;304else305val |= 0x5;306mt76_wr(dev, MT_BBP(AGC, 26), val);307} else {308mt76_wr(dev, MT_BBP(RXO, 14), 0x00560423);309}310311if (mt76x2_has_ext_lna(dev))312low_gain_delta = 10;313else314low_gain_delta = 14;315316agc_37 = 0x2121262c;317if (dev->mphy.chandef.chan->band == NL80211_BAND_2GHZ)318agc_35 = 0x11111516;319else if (low_gain == 2)320agc_35 = agc_37 = 0x08080808;321else if (dev->mphy.chandef.width == NL80211_CHAN_WIDTH_80)322agc_35 = 0x10101014;323else324agc_35 = 0x11111116;325326if (low_gain == 2) {327mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a990);328mt76_wr(dev, MT_BBP(AGC, 35), 0x08080808);329mt76_wr(dev, MT_BBP(AGC, 37), 0x08080808);330gain_delta = low_gain_delta;331dev->cal.agc_gain_adjust = 0;332} else {333mt76_wr(dev, MT_BBP(RXO, 18), 0xf000a991);334gain_delta = 0;335dev->cal.agc_gain_adjust = low_gain_delta;336}337338mt76_wr(dev, MT_BBP(AGC, 35), agc_35);339mt76_wr(dev, MT_BBP(AGC, 37), agc_37);340341dev->cal.agc_gain_cur[0] = gain[0] - gain_delta;342dev->cal.agc_gain_cur[1] = gain[1] - gain_delta;343mt76x2_phy_set_gain_val(dev);344345/* clear false CCA counters */346mt76_rr(dev, MT_RX_STAT_1);347}348EXPORT_SYMBOL_GPL(mt76x2_phy_update_channel_gain);349350351