10e3d6777SRyder Lee // SPDX-License-Identifier: ISC
21613c621SLorenzo Bianconi /*
31613c621SLorenzo Bianconi * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
41613c621SLorenzo Bianconi * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
51613c621SLorenzo Bianconi */
61613c621SLorenzo Bianconi
71613c621SLorenzo Bianconi #include "mt76x2.h"
81613c621SLorenzo Bianconi #include "eeprom.h"
91613c621SLorenzo Bianconi #include "../mt76x02_phy.h"
101613c621SLorenzo Bianconi
mt76x2_set_sar_specs(struct ieee80211_hw * hw,const struct cfg80211_sar_specs * sar)11633f77b5SLorenzo Bianconi int mt76x2_set_sar_specs(struct ieee80211_hw *hw,
12633f77b5SLorenzo Bianconi const struct cfg80211_sar_specs *sar)
13633f77b5SLorenzo Bianconi {
14633f77b5SLorenzo Bianconi int err = -EINVAL, power = hw->conf.power_level * 2;
15633f77b5SLorenzo Bianconi struct mt76x02_dev *dev = hw->priv;
16633f77b5SLorenzo Bianconi struct mt76_phy *mphy = &dev->mphy;
17633f77b5SLorenzo Bianconi
18633f77b5SLorenzo Bianconi mutex_lock(&dev->mt76.mutex);
19633f77b5SLorenzo Bianconi if (!cfg80211_chandef_valid(&mphy->chandef))
20633f77b5SLorenzo Bianconi goto out;
21633f77b5SLorenzo Bianconi
22633f77b5SLorenzo Bianconi err = mt76_init_sar_power(hw, sar);
23633f77b5SLorenzo Bianconi if (err)
24633f77b5SLorenzo Bianconi goto out;
25633f77b5SLorenzo Bianconi
26633f77b5SLorenzo Bianconi dev->txpower_conf = mt76_get_sar_power(mphy, mphy->chandef.chan,
27633f77b5SLorenzo Bianconi power);
28633f77b5SLorenzo Bianconi /* convert to per-chain power for 2x2 devices */
29633f77b5SLorenzo Bianconi dev->txpower_conf -= 6;
30633f77b5SLorenzo Bianconi
31633f77b5SLorenzo Bianconi if (test_bit(MT76_STATE_RUNNING, &mphy->state))
32633f77b5SLorenzo Bianconi mt76x2_phy_set_txpower(dev);
33633f77b5SLorenzo Bianconi out:
34633f77b5SLorenzo Bianconi mutex_unlock(&dev->mt76.mutex);
35633f77b5SLorenzo Bianconi
36633f77b5SLorenzo Bianconi return err;
37633f77b5SLorenzo Bianconi }
38633f77b5SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76x2_set_sar_specs);
39633f77b5SLorenzo Bianconi
401613c621SLorenzo Bianconi static void
mt76x2_set_wlan_state(struct mt76x02_dev * dev,bool enable)41e40803f2SLorenzo Bianconi mt76x2_set_wlan_state(struct mt76x02_dev *dev, bool enable)
421613c621SLorenzo Bianconi {
431613c621SLorenzo Bianconi u32 val = mt76_rr(dev, MT_WLAN_FUN_CTRL);
441613c621SLorenzo Bianconi
451613c621SLorenzo Bianconi if (enable)
461613c621SLorenzo Bianconi val |= (MT_WLAN_FUN_CTRL_WLAN_EN |
471613c621SLorenzo Bianconi MT_WLAN_FUN_CTRL_WLAN_CLK_EN);
481613c621SLorenzo Bianconi else
491613c621SLorenzo Bianconi val &= ~(MT_WLAN_FUN_CTRL_WLAN_EN |
501613c621SLorenzo Bianconi MT_WLAN_FUN_CTRL_WLAN_CLK_EN);
511613c621SLorenzo Bianconi
521613c621SLorenzo Bianconi mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
531613c621SLorenzo Bianconi udelay(20);
541613c621SLorenzo Bianconi }
551613c621SLorenzo Bianconi
mt76x2_reset_wlan(struct mt76x02_dev * dev,bool enable)56e40803f2SLorenzo Bianconi void mt76x2_reset_wlan(struct mt76x02_dev *dev, bool enable)
571613c621SLorenzo Bianconi {
581613c621SLorenzo Bianconi u32 val;
591613c621SLorenzo Bianconi
601613c621SLorenzo Bianconi if (!enable)
611613c621SLorenzo Bianconi goto out;
621613c621SLorenzo Bianconi
631613c621SLorenzo Bianconi val = mt76_rr(dev, MT_WLAN_FUN_CTRL);
641613c621SLorenzo Bianconi
651613c621SLorenzo Bianconi val &= ~MT_WLAN_FUN_CTRL_FRC_WL_ANT_SEL;
661613c621SLorenzo Bianconi
671613c621SLorenzo Bianconi if (val & MT_WLAN_FUN_CTRL_WLAN_EN) {
681613c621SLorenzo Bianconi val |= MT_WLAN_FUN_CTRL_WLAN_RESET_RF;
691613c621SLorenzo Bianconi mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
701613c621SLorenzo Bianconi udelay(20);
711613c621SLorenzo Bianconi
721613c621SLorenzo Bianconi val &= ~MT_WLAN_FUN_CTRL_WLAN_RESET_RF;
731613c621SLorenzo Bianconi }
741613c621SLorenzo Bianconi
751613c621SLorenzo Bianconi mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
761613c621SLorenzo Bianconi udelay(20);
771613c621SLorenzo Bianconi
781613c621SLorenzo Bianconi out:
791613c621SLorenzo Bianconi mt76x2_set_wlan_state(dev, enable);
801613c621SLorenzo Bianconi }
811613c621SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76x2_reset_wlan);
821613c621SLorenzo Bianconi
mt76_write_mac_initvals(struct mt76x02_dev * dev)83e40803f2SLorenzo Bianconi void mt76_write_mac_initvals(struct mt76x02_dev *dev)
841613c621SLorenzo Bianconi {
851613c621SLorenzo Bianconi #define DEFAULT_PROT_CFG_CCK \
861613c621SLorenzo Bianconi (FIELD_PREP(MT_PROT_CFG_RATE, 0x3) | \
871613c621SLorenzo Bianconi FIELD_PREP(MT_PROT_CFG_NAV, 1) | \
881613c621SLorenzo Bianconi FIELD_PREP(MT_PROT_CFG_TXOP_ALLOW, 0x3f) | \
891613c621SLorenzo Bianconi MT_PROT_CFG_RTS_THRESH)
901613c621SLorenzo Bianconi
911613c621SLorenzo Bianconi #define DEFAULT_PROT_CFG_OFDM \
921613c621SLorenzo Bianconi (FIELD_PREP(MT_PROT_CFG_RATE, 0x2004) | \
931613c621SLorenzo Bianconi FIELD_PREP(MT_PROT_CFG_NAV, 1) | \
941613c621SLorenzo Bianconi FIELD_PREP(MT_PROT_CFG_TXOP_ALLOW, 0x3f) | \
951613c621SLorenzo Bianconi MT_PROT_CFG_RTS_THRESH)
961613c621SLorenzo Bianconi
971613c621SLorenzo Bianconi #define DEFAULT_PROT_CFG_20 \
981613c621SLorenzo Bianconi (FIELD_PREP(MT_PROT_CFG_RATE, 0x2004) | \
991613c621SLorenzo Bianconi FIELD_PREP(MT_PROT_CFG_CTRL, 1) | \
1001613c621SLorenzo Bianconi FIELD_PREP(MT_PROT_CFG_NAV, 1) | \
1011613c621SLorenzo Bianconi FIELD_PREP(MT_PROT_CFG_TXOP_ALLOW, 0x17))
1021613c621SLorenzo Bianconi
1031613c621SLorenzo Bianconi #define DEFAULT_PROT_CFG_40 \
1041613c621SLorenzo Bianconi (FIELD_PREP(MT_PROT_CFG_RATE, 0x2084) | \
1051613c621SLorenzo Bianconi FIELD_PREP(MT_PROT_CFG_CTRL, 1) | \
1061613c621SLorenzo Bianconi FIELD_PREP(MT_PROT_CFG_NAV, 1) | \
1071613c621SLorenzo Bianconi FIELD_PREP(MT_PROT_CFG_TXOP_ALLOW, 0x3f))
1081613c621SLorenzo Bianconi
1091613c621SLorenzo Bianconi static const struct mt76_reg_pair vals[] = {
1101613c621SLorenzo Bianconi /* Copied from MediaTek reference source */
1111613c621SLorenzo Bianconi { MT_PBF_SYS_CTRL, 0x00080c00 },
1121613c621SLorenzo Bianconi { MT_PBF_CFG, 0x1efebcff },
1131613c621SLorenzo Bianconi { MT_FCE_PSE_CTRL, 0x00000001 },
114049019c2SFelix Fietkau { MT_MAC_SYS_CTRL, 0x00000000 },
1151613c621SLorenzo Bianconi { MT_MAX_LEN_CFG, 0x003e3f00 },
1161613c621SLorenzo Bianconi { MT_AMPDU_MAX_LEN_20M1S, 0xaaa99887 },
1171613c621SLorenzo Bianconi { MT_AMPDU_MAX_LEN_20M2S, 0x000000aa },
1181613c621SLorenzo Bianconi { MT_XIFS_TIME_CFG, 0x33a40d0a },
1191613c621SLorenzo Bianconi { MT_BKOFF_SLOT_CFG, 0x00000209 },
1201613c621SLorenzo Bianconi { MT_TBTT_SYNC_CFG, 0x00422010 },
1211613c621SLorenzo Bianconi { MT_PWR_PIN_CFG, 0x00000000 },
1221613c621SLorenzo Bianconi { 0x1238, 0x001700c8 },
1231613c621SLorenzo Bianconi { MT_TX_SW_CFG0, 0x00101001 },
1241613c621SLorenzo Bianconi { MT_TX_SW_CFG1, 0x00010000 },
1251613c621SLorenzo Bianconi { MT_TX_SW_CFG2, 0x00000000 },
1261613c621SLorenzo Bianconi { MT_TXOP_CTRL_CFG, 0x0400583f },
1277dfc45e6SStanislaw Gruszka { MT_TX_RTS_CFG, 0x00ffff20 },
1281613c621SLorenzo Bianconi { MT_TX_TIMEOUT_CFG, 0x000a2290 },
1291613c621SLorenzo Bianconi { MT_TX_RETRY_CFG, 0x47f01f0f },
1301613c621SLorenzo Bianconi { MT_EXP_ACK_TIME, 0x002c00dc },
1311613c621SLorenzo Bianconi { MT_TX_PROT_CFG6, 0xe3f42004 },
1321613c621SLorenzo Bianconi { MT_TX_PROT_CFG7, 0xe3f42084 },
1331613c621SLorenzo Bianconi { MT_TX_PROT_CFG8, 0xe3f42104 },
1341613c621SLorenzo Bianconi { MT_PIFS_TX_CFG, 0x00060fff },
1351613c621SLorenzo Bianconi { MT_RX_FILTR_CFG, 0x00015f97 },
1361613c621SLorenzo Bianconi { MT_LEGACY_BASIC_RATE, 0x0000017f },
1371613c621SLorenzo Bianconi { MT_HT_BASIC_RATE, 0x00004003 },
1381613c621SLorenzo Bianconi { MT_PN_PAD_MODE, 0x00000003 },
1391613c621SLorenzo Bianconi { MT_TXOP_HLDR_ET, 0x00000002 },
1401613c621SLorenzo Bianconi { 0xa44, 0x00000000 },
1411613c621SLorenzo Bianconi { MT_HEADER_TRANS_CTRL_REG, 0x00000000 },
1421613c621SLorenzo Bianconi { MT_TSO_CTRL, 0x00000000 },
1431613c621SLorenzo Bianconi { MT_AUX_CLK_CFG, 0x00000000 },
1441613c621SLorenzo Bianconi { MT_DACCLK_EN_DLY_CFG, 0x00000000 },
1451613c621SLorenzo Bianconi { MT_TX_ALC_CFG_4, 0x00000000 },
1461613c621SLorenzo Bianconi { MT_TX_ALC_VGA3, 0x00000000 },
1471613c621SLorenzo Bianconi { MT_TX_PWR_CFG_0, 0x3a3a3a3a },
1481613c621SLorenzo Bianconi { MT_TX_PWR_CFG_1, 0x3a3a3a3a },
1491613c621SLorenzo Bianconi { MT_TX_PWR_CFG_2, 0x3a3a3a3a },
1501613c621SLorenzo Bianconi { MT_TX_PWR_CFG_3, 0x3a3a3a3a },
1511613c621SLorenzo Bianconi { MT_TX_PWR_CFG_4, 0x3a3a3a3a },
1521613c621SLorenzo Bianconi { MT_TX_PWR_CFG_7, 0x3a3a3a3a },
1531613c621SLorenzo Bianconi { MT_TX_PWR_CFG_8, 0x0000003a },
1541613c621SLorenzo Bianconi { MT_TX_PWR_CFG_9, 0x0000003a },
1551613c621SLorenzo Bianconi { MT_EFUSE_CTRL, 0x0000d000 },
1561613c621SLorenzo Bianconi { MT_PAUSE_ENABLE_CONTROL1, 0x0000000a },
1571613c621SLorenzo Bianconi { MT_FCE_WLAN_FLOW_CONTROL1, 0x60401c18 },
1581613c621SLorenzo Bianconi { MT_WPDMA_DELAY_INT_CFG, 0x94ff0000 },
1591613c621SLorenzo Bianconi { MT_TX_SW_CFG3, 0x00000004 },
1601613c621SLorenzo Bianconi { MT_HT_FBK_TO_LEGACY, 0x00001818 },
1611613c621SLorenzo Bianconi { MT_VHT_HT_FBK_CFG1, 0xedcba980 },
1621613c621SLorenzo Bianconi { MT_PROT_AUTO_TX_CFG, 0x00830083 },
1631613c621SLorenzo Bianconi { MT_HT_CTRL_CFG, 0x000001ff },
1643fd612dfSLorenzo Bianconi { MT_TX_LINK_CFG, 0x00001020 },
1651613c621SLorenzo Bianconi };
1661613c621SLorenzo Bianconi struct mt76_reg_pair prot_vals[] = {
1671613c621SLorenzo Bianconi { MT_CCK_PROT_CFG, DEFAULT_PROT_CFG_CCK },
1681613c621SLorenzo Bianconi { MT_OFDM_PROT_CFG, DEFAULT_PROT_CFG_OFDM },
1691613c621SLorenzo Bianconi { MT_MM20_PROT_CFG, DEFAULT_PROT_CFG_20 },
1701613c621SLorenzo Bianconi { MT_MM40_PROT_CFG, DEFAULT_PROT_CFG_40 },
1711613c621SLorenzo Bianconi { MT_GF20_PROT_CFG, DEFAULT_PROT_CFG_20 },
1721613c621SLorenzo Bianconi { MT_GF40_PROT_CFG, DEFAULT_PROT_CFG_40 },
1731613c621SLorenzo Bianconi };
1741613c621SLorenzo Bianconi
1751613c621SLorenzo Bianconi mt76_wr_rp(dev, 0, vals, ARRAY_SIZE(vals));
1761613c621SLorenzo Bianconi mt76_wr_rp(dev, 0, prot_vals, ARRAY_SIZE(prot_vals));
1771613c621SLorenzo Bianconi }
1781613c621SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_write_mac_initvals);
1791613c621SLorenzo Bianconi
mt76x2_init_txpower(struct mt76x02_dev * dev,struct ieee80211_supported_band * sband)180e40803f2SLorenzo Bianconi void mt76x2_init_txpower(struct mt76x02_dev *dev,
1811613c621SLorenzo Bianconi struct ieee80211_supported_band *sband)
1821613c621SLorenzo Bianconi {
1831613c621SLorenzo Bianconi struct ieee80211_channel *chan;
1841613c621SLorenzo Bianconi struct mt76x2_tx_power_info txp;
185*b376d963SFelix Fietkau struct mt76x02_rate_power t = {};
1861613c621SLorenzo Bianconi int i;
1871613c621SLorenzo Bianconi
1881613c621SLorenzo Bianconi for (i = 0; i < sband->n_channels; i++) {
1891613c621SLorenzo Bianconi chan = &sband->channels[i];
1901613c621SLorenzo Bianconi
1911613c621SLorenzo Bianconi mt76x2_get_power_info(dev, &txp, chan);
1921613c621SLorenzo Bianconi mt76x2_get_rate_power(dev, &t, chan);
1931613c621SLorenzo Bianconi
19409952572SFelix Fietkau chan->orig_mpwr = mt76x02_get_max_rate_power(&t) +
195cee646d6SFelix Fietkau txp.target_power;
19609952572SFelix Fietkau chan->orig_mpwr = DIV_ROUND_UP(chan->orig_mpwr, 2);
1971613c621SLorenzo Bianconi
1981613c621SLorenzo Bianconi /* convert to combined output power on 2x2 devices */
19909952572SFelix Fietkau chan->orig_mpwr += 3;
20009952572SFelix Fietkau chan->max_power = min_t(int, chan->max_reg_power,
20109952572SFelix Fietkau chan->orig_mpwr);
2021613c621SLorenzo Bianconi }
2031613c621SLorenzo Bianconi }
2041613c621SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76x2_init_txpower);
205