Commit b865273b authored by Kalle Valo's avatar Kalle Valo

Merge tag 'mt76-for-kvalo-2022-02-24' of https://github.com/nbd168/wireless

mt76 patches for 5.18

- bugfixes
- mt7915 thermal management improvements
- SAR support for more mt76 drivers
- mt7986 wmac support on mt7915
parents a0061be4 00a883e6
......@@ -18,7 +18,7 @@ description: |
wireless device. The node is expected to be specified as a child
node of the PCI controller to which the wireless chip is connected.
Alternatively, it can specify the wireless part of the MT7628/MT7688
or MT7622 SoC.
or MT7622/MT7986 SoC.
allOf:
- $ref: ieee80211.yaml#
......@@ -29,9 +29,13 @@ properties:
- mediatek,mt76
- mediatek,mt7628-wmac
- mediatek,mt7622-wmac
- mediatek,mt7986-wmac
reg:
maxItems: 1
minItems: 1
maxItems: 3
description:
MT7986 should contain 3 regions consys, dcm, and sku, in this order.
interrupts:
maxItems: 1
......@@ -39,6 +43,17 @@ properties:
power-domains:
maxItems: 1
memory-region:
maxItems: 1
resets:
maxItems: 1
description:
Specify the consys reset for mt7986.
reset-name:
const: consys
mediatek,infracfg:
$ref: /schemas/types.yaml#/definitions/phandle
description:
......@@ -174,7 +189,7 @@ required:
- compatible
- reg
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......@@ -240,3 +255,15 @@ examples:
power-domains = <&scpsys 3>;
};
- |
wifi@18000000 {
compatible = "mediatek,mt7986-wmac";
resets = <&watchdog 23>;
reset-names = "consys";
reg = <0x18000000 0x1000000>,
<0x10003000 0x1000>,
<0x11d10000 0x1000>;
interrupts = <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>;
memory-region = <&wmcpu_emi>;
};
......@@ -932,6 +932,35 @@ void mt76_wcid_key_setup(struct mt76_dev *dev, struct mt76_wcid *wcid,
}
EXPORT_SYMBOL(mt76_wcid_key_setup);
static int
mt76_rx_signal(struct mt76_rx_status *status)
{
s8 *chain_signal = status->chain_signal;
int signal = -128;
u8 chains;
for (chains = status->chains; chains; chains >>= 1, chain_signal++) {
int cur, diff;
if (!(chains & BIT(0)))
continue;
cur = *chain_signal;
if (cur > signal)
swap(cur, signal);
diff = signal - cur;
if (diff == 0)
signal += 3;
else if (diff <= 2)
signal += 2;
else if (diff <= 6)
signal += 1;
}
return signal;
}
static void
mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
struct ieee80211_hw **hw,
......@@ -960,6 +989,9 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
status->ampdu_reference = mstat.ampdu_ref;
status->device_timestamp = mstat.timestamp;
status->mactime = mstat.timestamp;
status->signal = mt76_rx_signal(&mstat);
if (status->signal <= -128)
status->flag |= RX_FLAG_NO_SIGNAL_VAL;
if (ieee80211_is_beacon(hdr->frame_control) ||
ieee80211_is_probe_resp(hdr->frame_control))
......@@ -1626,7 +1658,7 @@ enum mt76_dfs_state mt76_phy_dfs_state(struct mt76_phy *phy)
return MT_DFS_STATE_DISABLED;
}
if (phy->chandef.chan->dfs_state != NL80211_DFS_AVAILABLE)
if (!cfg80211_reg_can_beacon(hw->wiphy, &phy->chandef, NL80211_IFTYPE_AP))
return MT_DFS_STATE_CAC;
return MT_DFS_STATE_ACTIVE;
......
......@@ -643,11 +643,6 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb)
status->chain_signal[1] = FIELD_GET(MT_RXV4_IB_RSSI1, rxdg3) +
dev->rssi_offset[1];
status->signal = status->chain_signal[0];
if (status->chains & BIT(1))
status->signal = max(status->signal,
status->chain_signal[1]);
if (FIELD_GET(MT_RXV1_FRAME_MODE, rxdg0) == 1)
status->bw = RATE_INFO_BW_40;
......
......@@ -443,11 +443,16 @@ mt7615_ext_mac_addr_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct mt7615_dev *dev = file->private_data;
char buf[32 * ((ETH_ALEN * 3) + 4) + 1];
u32 len = 32 * ((ETH_ALEN * 3) + 4) + 1;
u8 addr[ETH_ALEN];
char *buf;
int ofs = 0;
int i;
buf = kzalloc(len, GFP_KERNEL);
if (!buf)
return -ENOMEM;
for (i = 0; i < 32; i++) {
if (!(dev->muar_mask & BIT(i)))
continue;
......@@ -458,10 +463,13 @@ mt7615_ext_mac_addr_read(struct file *file, char __user *userbuf,
put_unaligned_le32(mt76_rr(dev, MT_WF_RMAC_MAR0), addr);
put_unaligned_le16((mt76_rr(dev, MT_WF_RMAC_MAR1) &
MT_WF_RMAC_MAR1_ADDR), addr + 4);
ofs += snprintf(buf + ofs, sizeof(buf) - ofs, "%d=%pM\n", i, addr);
ofs += snprintf(buf + ofs, len - ofs, "%d=%pM\n", i, addr);
}
return simple_read_from_buffer(userbuf, count, ppos, buf, ofs);
ofs = simple_read_from_buffer(userbuf, count, ppos, buf, ofs);
kfree(buf);
return ofs;
}
static ssize_t
......
......@@ -259,7 +259,7 @@ static int mt7615_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
struct ieee80211_sta *sta;
struct ieee80211_vif *vif;
struct ieee80211_hdr hdr;
__le32 qos_ctrl, ht_ctrl;
u16 frame_control;
if (FIELD_GET(MT_RXD1_NORMAL_ADDR_TYPE, le32_to_cpu(rxd[1])) !=
MT_RXD1_NORMAL_U2M)
......@@ -275,16 +275,15 @@ static int mt7615_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
/* store the info from RXD and ethhdr to avoid being overridden */
hdr.frame_control = FIELD_GET(MT_RXD4_FRAME_CONTROL, rxd[4]);
hdr.seq_ctrl = FIELD_GET(MT_RXD6_SEQ_CTRL, rxd[6]);
qos_ctrl = FIELD_GET(MT_RXD6_QOS_CTL, rxd[6]);
ht_ctrl = FIELD_GET(MT_RXD7_HT_CONTROL, rxd[7]);
frame_control = le32_get_bits(rxd[4], MT_RXD4_FRAME_CONTROL);
hdr.frame_control = cpu_to_le16(frame_control);
hdr.seq_ctrl = cpu_to_le16(le32_get_bits(rxd[6], MT_RXD6_SEQ_CTRL));
hdr.duration_id = 0;
ether_addr_copy(hdr.addr1, vif->addr);
ether_addr_copy(hdr.addr2, sta->addr);
switch (le16_to_cpu(hdr.frame_control) &
(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
switch (frame_control & (IEEE80211_FCTL_TODS |
IEEE80211_FCTL_FROMDS)) {
case 0:
ether_addr_copy(hdr.addr3, vif->bss_conf.bssid);
break;
......@@ -306,15 +305,23 @@ static int mt7615_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
if (eth_hdr->h_proto == cpu_to_be16(ETH_P_AARP) ||
eth_hdr->h_proto == cpu_to_be16(ETH_P_IPX))
ether_addr_copy(skb_push(skb, ETH_ALEN), bridge_tunnel_header);
else if (eth_hdr->h_proto >= cpu_to_be16(ETH_P_802_3_MIN))
else if (be16_to_cpu(eth_hdr->h_proto) >= ETH_P_802_3_MIN)
ether_addr_copy(skb_push(skb, ETH_ALEN), rfc1042_header);
else
skb_pull(skb, 2);
if (ieee80211_has_order(hdr.frame_control))
memcpy(skb_push(skb, 2), &ht_ctrl, 2);
if (ieee80211_is_data_qos(hdr.frame_control))
memcpy(skb_push(skb, 2), &qos_ctrl, 2);
memcpy(skb_push(skb, IEEE80211_HT_CTL_LEN), &rxd[7],
IEEE80211_HT_CTL_LEN);
if (ieee80211_is_data_qos(hdr.frame_control)) {
__le16 qos_ctrl;
qos_ctrl = cpu_to_le16(le32_get_bits(rxd[6], MT_RXD6_QOS_CTL));
memcpy(skb_push(skb, IEEE80211_QOS_CTL_LEN), &qos_ctrl,
IEEE80211_QOS_CTL_LEN);
}
if (ieee80211_has_a4(hdr.frame_control))
memcpy(skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr));
else
......@@ -569,15 +576,6 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
status->chain_signal[1] = to_rssi(MT_RXV4_RCPI1, rxdg3);
status->chain_signal[2] = to_rssi(MT_RXV4_RCPI2, rxdg3);
status->chain_signal[3] = to_rssi(MT_RXV4_RCPI3, rxdg3);
status->signal = status->chain_signal[0];
for (i = 1; i < hweight8(mphy->antenna_mask); i++) {
if (!(status->chains & BIT(i)))
continue;
status->signal = max(status->signal,
status->chain_signal[i]);
}
mt7615_mac_fill_tm_rx(mphy->priv, rxd);
......@@ -1862,7 +1860,7 @@ mt7615_mac_adjust_sensitivity(struct mt7615_phy *phy,
struct mt7615_dev *dev = phy->dev;
int false_cca = ofdm ? phy->false_cca_ofdm : phy->false_cca_cck;
bool ext_phy = phy != &dev->phy;
u16 def_th = ofdm ? -98 : -110;
s16 def_th = ofdm ? -98 : -110;
bool update = false;
s8 *sensitivity;
int signal;
......
......@@ -431,6 +431,29 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return err;
}
static int mt7615_set_sar_specs(struct ieee80211_hw *hw,
const struct cfg80211_sar_specs *sar)
{
struct mt7615_phy *phy = mt7615_hw_phy(hw);
int err;
if (!cfg80211_chandef_valid(&phy->mt76->chandef))
return -EINVAL;
err = mt76_init_sar_power(hw, sar);
if (err)
return err;
if (mt7615_firmware_offload(phy->dev))
return mt76_connac_mcu_set_rate_txpower(phy->mt76);
ieee80211_stop_queues(hw);
err = mt7615_set_channel(phy);
ieee80211_wake_queues(hw);
return err;
}
static int mt7615_config(struct ieee80211_hw *hw, u32 changed)
{
struct mt7615_dev *dev = mt7615_hw_dev(hw);
......@@ -1333,6 +1356,7 @@ const struct ieee80211_ops mt7615_ops = {
.set_wakeup = mt7615_set_wakeup,
.set_rekey_data = mt7615_set_rekey_data,
#endif /* CONFIG_PM */
.set_sar_specs = mt7615_set_sar_specs,
};
EXPORT_SYMBOL_GPL(mt7615_ops);
......
......@@ -2020,7 +2020,7 @@ static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku)
struct mt76_power_limits limits;
s8 *limits_array = (s8 *)&limits;
int n_chains = hweight8(mphy->antenna_mask);
int tx_power;
int tx_power = hw->conf.power_level * 2;
int i;
static const u8 sku_mapping[] = {
#define SKU_FIELD(_type, _field) \
......@@ -2077,9 +2077,8 @@ static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku)
#undef SKU_FIELD
};
tx_power = hw->conf.power_level * 2 -
mt76_tx_power_nss_delta(n_chains);
tx_power = mt76_get_sar_power(mphy, mphy->chandef.chan, tx_power);
tx_power -= mt76_tx_power_nss_delta(n_chains);
tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
&limits, tx_power);
mphy->txpower_cur = tx_power;
......@@ -2152,10 +2151,12 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd)
.center_chan2 = ieee80211_frequency_to_channel(freq2),
};
if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
if (cmd == MCU_EXT_CMD(SET_RX_PATH))
req.switch_reason = CH_SWITCH_NORMAL;
else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
else if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
chandef->chan->dfs_state != NL80211_DFS_AVAILABLE)
else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,
NL80211_IFTYPE_AP))
req.switch_reason = CH_SWITCH_DFS;
else
req.switch_reason = CH_SWITCH_NORMAL;
......
......@@ -117,6 +117,11 @@ static inline bool is_mt7916(struct mt76_dev *dev)
return mt76_chip(dev) == 0x7906;
}
static inline bool is_mt7986(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7986;
}
static inline bool is_mt7622(struct mt76_dev *dev)
{
if (!IS_ENABLED(CONFIG_MT7622_WMAC))
......
......@@ -1501,7 +1501,6 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
int ext_channels_num = max_t(int, sreq->n_channels - 32, 0);
struct ieee80211_channel **scan_list = sreq->channels;
struct mt76_dev *mdev = phy->dev;
bool ext_phy = phy == mdev->phy2;
struct mt76_connac_mcu_scan_channel *chan;
struct mt76_connac_hw_scan_req *req;
struct sk_buff *skb;
......@@ -1515,7 +1514,7 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
req = (struct mt76_connac_hw_scan_req *)skb_put(skb, sizeof(*req));
req->seq_num = mvif->scan_seq_num | ext_phy << 7;
req->seq_num = mvif->scan_seq_num | mvif->band_idx << 7;
req->bss_idx = mvif->idx;
req->scan_type = sreq->n_ssids ? 1 : 0;
req->probe_req_num = sreq->n_ssids ? 2 : 0;
......@@ -1623,7 +1622,6 @@ int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy,
struct mt76_connac_mcu_scan_channel *chan;
struct mt76_connac_sched_scan_req *req;
struct mt76_dev *mdev = phy->dev;
bool ext_phy = phy == mdev->phy2;
struct cfg80211_match_set *match;
struct cfg80211_ssid *ssid;
struct sk_buff *skb;
......@@ -1637,7 +1635,7 @@ int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy,
req = (struct mt76_connac_sched_scan_req *)skb_put(skb, sizeof(*req));
req->version = 1;
req->seq_num = mvif->scan_seq_num | ext_phy << 7;
req->seq_num = mvif->scan_seq_num | mvif->band_idx << 7;
if (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
u8 *addr = is_mt7663(phy->dev) ? req->mt7663.random_mac
......@@ -2656,7 +2654,7 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_bss_ext_tlv);
int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct mt76_phy *phy, u8 wlan_idx,
struct mt76_phy *phy, u16 wlan_idx,
bool enable)
{
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
......
......@@ -1642,7 +1642,7 @@ void mt76_connac_mcu_bss_omac_tlv(struct sk_buff *skb,
int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct mt76_phy *phy, u8 wlan_idx,
struct mt76_phy *phy, u16 wlan_idx,
bool enable);
void mt76_connac_mcu_sta_uapsd(struct sk_buff *skb, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
......
......@@ -860,9 +860,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
status->chain_signal[1] = mt76x02_mac_get_rssi(dev,
rxwi->rssi[1],
1);
signal = max_t(s8, signal, status->chain_signal[1]);
}
status->signal = signal;
status->freq = dev->mphy.chandef.chan->center_freq;
status->band = dev->mphy.chandef.chan->band;
......
......@@ -12,3 +12,13 @@ config MT7915E
OFDMA, spatial reuse and dual carrier modulation.
To compile this driver as a module, choose M here.
config MT7986_WMAC
bool "MT7986 (SoC) WMAC support"
depends on MT7915E
depends on ARCH_MEDIATEK || COMPILE_TEST
select REGMAP
help
This adds support for the built-in WMAC on MT7986 SoC device
which has the same feature set as a MT7915, but enables 6E
support.
......@@ -6,3 +6,4 @@ mt7915e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \
debugfs.o mmio.o
mt7915e-$(CONFIG_NL80211_TESTMODE) += testmode.o
mt7915e-$(CONFIG_MT7986_WMAC) += soc.o
\ No newline at end of file
......@@ -548,12 +548,12 @@ mt7915_ampdu_stat_read_phy(struct mt7915_phy *phy,
/* Tx ampdu stat */
for (i = 0; i < ARRAY_SIZE(range); i++)
range[i] = mt76_rr(dev, MT_MIB_ARNG(ext_phy, i));
range[i] = mt76_rr(dev, MT_MIB_ARNG(phy->band_idx, i));
for (i = 0; i < ARRAY_SIZE(bound); i++)
bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1;
seq_printf(file, "\nPhy %d\n", ext_phy);
seq_printf(file, "\nPhy %d, Phy band %d\n", ext_phy, phy->band_idx);
seq_printf(file, "Length: %8d | ", bound[0]);
for (i = 0; i < ARRAY_SIZE(bound) - 1; i++)
......@@ -561,7 +561,7 @@ mt7915_ampdu_stat_read_phy(struct mt7915_phy *phy,
bound[i] + 1, bound[i + 1]);
seq_puts(file, "\nCount: ");
n = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0;
n = phy->band_idx ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0;
for (i = 0; i < ARRAY_SIZE(bound); i++)
seq_printf(file, "%8d | ", dev->mt76.aggr_stats[i + n]);
seq_puts(file, "\n");
......@@ -898,7 +898,7 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir,
mt7915_twt_stats);
debugfs_create_file("ser_trigger", 0200, dir, dev, &fops_ser_trigger);
if (!dev->dbdc_support || ext_phy) {
if (!dev->dbdc_support || phy->band_idx) {
debugfs_create_u32("dfs_hw_pattern", 0400, dir,
&dev->hw_pattern);
debugfs_create_file("radar_trigger", 0200, dir, dev,
......@@ -947,13 +947,13 @@ void mt7915_debugfs_rx_fw_monitor(struct mt7915_dev *dev, const void *data, int
__le16 len;
} hdr = {
.magic = cpu_to_le32(FW_BIN_LOG_MAGIC),
.msg_type = PKT_TYPE_RX_FW_MONITOR,
.msg_type = cpu_to_le16(PKT_TYPE_RX_FW_MONITOR),
};
if (!dev->relay_fwlog)
return;
hdr.timestamp = mt76_rr(dev, MT_LPON_FRCR(0));
hdr.timestamp = cpu_to_le32(mt76_rr(dev, MT_LPON_FRCR(0)));
hdr.len = *(__le16 *)data;
mt7915_debugfs_write_fwlog(dev, &hdr, sizeof(hdr), data, len);
}
......
......@@ -310,10 +310,12 @@ static int mt7915_dma_enable(struct mt7915_dev *dev)
/* enable interrupts for TX/RX rings */
irq_mask = MT_INT_RX_DONE_MCU |
MT_INT_TX_DONE_MCU |
MT_INT_MCU_CMD |
MT_INT_BAND0_RX_DONE;
MT_INT_MCU_CMD;
if (dev->dbdc_support)
if (!dev->phy.band_idx)
irq_mask |= MT_INT_BAND0_RX_DONE;
if (dev->dbdc_support || dev->phy.band_idx)
irq_mask |= MT_INT_BAND1_RX_DONE;
mt7915_irq_enable(dev, irq_mask);
......@@ -338,7 +340,7 @@ int mt7915_dma_init(struct mt7915_dev *dev)
/* init tx queue */
ret = mt7915_init_tx_queues(&dev->phy,
MT_TXQ_ID(0),
MT_TXQ_ID(dev->phy.band_idx),
MT7915_TX_RING_SIZE,
MT_TXQ_RING_BASE(0));
if (ret)
......@@ -387,6 +389,7 @@ int mt7915_dma_init(struct mt7915_dev *dev)
return ret;
/* rx data queue for band0 */
if (!dev->phy.band_idx) {
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
MT_RXQ_ID(MT_RXQ_MAIN),
MT7915_RX_RING_SIZE,
......@@ -394,6 +397,7 @@ int mt7915_dma_init(struct mt7915_dev *dev)
MT_RXQ_RING_BASE(MT_RXQ_MAIN));
if (ret)
return ret;
}
/* tx free notify event from WA for band0 */
if (!is_mt7915(mdev)) {
......@@ -406,7 +410,7 @@ int mt7915_dma_init(struct mt7915_dev *dev)
return ret;
}
if (dev->dbdc_support) {
if (dev->dbdc_support || dev->phy.band_idx) {
/* rx data queue for band1 */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_EXT],
MT_RXQ_ID(MT_RXQ_EXT),
......
......@@ -36,27 +36,48 @@ static int mt7915_check_eeprom(struct mt7915_dev *dev)
switch (val) {
case 0x7915:
case 0x7916:
case 0x7986:
return 0;
default:
return -EINVAL;
}
}
static char *mt7915_eeprom_name(struct mt7915_dev *dev)
{
switch (mt76_chip(&dev->mt76)) {
case 0x7915:
return dev->dbdc_support ?
MT7915_EEPROM_DEFAULT_DBDC : MT7915_EEPROM_DEFAULT;
case 0x7986:
switch (mt7915_check_adie(dev, true)) {
case MT7976_ONE_ADIE_DBDC:
return MT7986_EEPROM_MT7976_DEFAULT_DBDC;
case MT7975_ONE_ADIE:
return MT7986_EEPROM_MT7975_DEFAULT;
case MT7976_ONE_ADIE:
return MT7986_EEPROM_MT7976_DEFAULT;
case MT7975_DUAL_ADIE:
return MT7986_EEPROM_MT7975_DUAL_DEFAULT;
case MT7976_DUAL_ADIE:
return MT7986_EEPROM_MT7976_DUAL_DEFAULT;
default:
break;
}
return NULL;
default:
return MT7916_EEPROM_DEFAULT;
}
}
static int
mt7915_eeprom_load_default(struct mt7915_dev *dev)
{
char *default_bin = MT7915_EEPROM_DEFAULT;
u8 *eeprom = dev->mt76.eeprom.data;
const struct firmware *fw = NULL;
int ret;
if (dev->dbdc_support)
default_bin = MT7915_EEPROM_DEFAULT_DBDC;
if (!is_mt7915(&dev->mt76))
default_bin = MT7916_EEPROM_DEFAULT;
ret = request_firmware(&fw, default_bin, dev->mt76.dev);
ret = request_firmware(&fw, mt7915_eeprom_name(dev), dev->mt76.dev);
if (ret)
return ret;
......@@ -109,14 +130,14 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev)
static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
bool ext_phy = phy != &dev->phy;
u8 *eeprom = dev->mt76.eeprom.data;
u32 val;
val = eeprom[MT_EE_WIFI_CONF + ext_phy];
val = eeprom[MT_EE_WIFI_CONF + phy->band_idx];
val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
if (val == MT_EE_BAND_SEL_DEFAULT && dev->dbdc_support)
val = ext_phy ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ;
if (val == MT_EE_BAND_SEL_DEFAULT &&
(!is_mt7915(&dev->mt76) || dev->dbdc_support))
val = phy->band_idx ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ;
switch (val) {
case MT_EE_BAND_SEL_5GHZ:
......@@ -135,7 +156,7 @@ static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
struct mt7915_phy *phy)
{
u8 nss, nss_band, *eeprom = dev->mt76.eeprom.data;
u8 nss, nss_band, nss_band_max, *eeprom = dev->mt76.eeprom.data;
struct mt76_phy *mphy = phy->mt76;
bool ext_phy = phy != &dev->phy;
......@@ -147,7 +168,7 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
eeprom[MT_EE_WIFI_CONF]);
} else {
nss = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH,
eeprom[MT_EE_WIFI_CONF + ext_phy]);
eeprom[MT_EE_WIFI_CONF + phy->band_idx]);
}
if (!nss || nss > 4)
......@@ -155,32 +176,42 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
/* read tx/rx stream */
nss_band = nss;
if (dev->dbdc_support) {
if (is_mt7915(&dev->mt76)) {
nss_band = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0,
eeprom[MT_EE_WIFI_CONF + 3]);
if (ext_phy)
if (phy->band_idx)
nss_band = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B1,
eeprom[MT_EE_WIFI_CONF + 3]);
} else {
nss_band = FIELD_GET(MT_EE_WIFI_CONF_STREAM_NUM,
eeprom[MT_EE_WIFI_CONF + 2 + ext_phy]);
eeprom[MT_EE_WIFI_CONF + 2 + phy->band_idx]);
}
if (!nss_band || nss_band > 2)
nss_band = 2;
nss_band_max = is_mt7986(&dev->mt76) ?
MT_EE_NSS_MAX_DBDC_MA7986 : MT_EE_NSS_MAX_DBDC_MA7915;
} else {
nss_band_max = is_mt7986(&dev->mt76) ?
MT_EE_NSS_MAX_MA7986 : MT_EE_NSS_MAX_MA7915;
}
if (!nss_band || nss_band > nss_band_max)
nss_band = nss_band_max;
if (nss_band > nss) {
dev_err(dev->mt76.dev,
"nss mismatch, nss(%d) nss_band(%d) ext_phy(%d)\n",
nss, nss_band, ext_phy);
dev_warn(dev->mt76.dev,
"nss mismatch, nss(%d) nss_band(%d) band(%d) ext_phy(%d)\n",
nss, nss_band, phy->band_idx, ext_phy);
nss = nss_band;
}
mphy->chainmask = ext_phy ? (BIT(nss_band) - 1) << 2 : (BIT(nss_band) - 1);
mphy->antenna_mask = BIT(hweight8(mphy->chainmask)) - 1;
mphy->chainmask = BIT(nss) - 1;
if (ext_phy)
mphy->chainmask <<= dev->chainshift;
mphy->antenna_mask = BIT(nss_band) - 1;
dev->chainmask |= mphy->chainmask;
dev->chainshift = hweight8(dev->mphy.chainmask);
}
int mt7915_eeprom_init(struct mt7915_dev *dev)
......
......@@ -56,6 +56,19 @@ enum mt7915_eeprom_field {
#define MT_EE_RATE_DELTA_SIGN BIT(6)
#define MT_EE_RATE_DELTA_EN BIT(7)
#define MT_EE_NSS_MAX_MA7915 4
#define MT_EE_NSS_MAX_DBDC_MA7915 2
#define MT_EE_NSS_MAX_MA7986 4
#define MT_EE_NSS_MAX_DBDC_MA7986 4
enum mt7915_adie_sku {
MT7976_ONE_ADIE_DBDC = 0x7,
MT7975_ONE_ADIE = 0x8,
MT7976_ONE_ADIE = 0xa,
MT7975_DUAL_ADIE = 0xd,
MT7976_DUAL_ADIE = 0xf,
};
enum mt7915_eeprom_band {
MT_EE_BAND_SEL_DEFAULT,
MT_EE_BAND_SEL_5GHZ,
......
......@@ -50,15 +50,22 @@ static ssize_t mt7915_thermal_temp_show(struct device *dev,
int i = to_sensor_dev_attr(attr)->index;
int temperature;
if (i)
return sprintf(buf, "%u\n", phy->throttle_temp[i - 1] * 1000);
switch (i) {
case 0:
temperature = mt7915_mcu_get_temperature(phy);
if (temperature < 0)
return temperature;
/* display in millidegree celcius */
return sprintf(buf, "%u\n", temperature * 1000);
case 1:
case 2:
return sprintf(buf, "%u\n",
phy->throttle_temp[i - 1] * 1000);
case 3:
return sprintf(buf, "%hhu\n", phy->throttle_state);
default:
return -EINVAL;
}
}
static ssize_t mt7915_thermal_temp_store(struct device *dev,
......@@ -84,11 +91,13 @@ static ssize_t mt7915_thermal_temp_store(struct device *dev,
static SENSOR_DEVICE_ATTR_RO(temp1_input, mt7915_thermal_temp, 0);
static SENSOR_DEVICE_ATTR_RW(temp1_crit, mt7915_thermal_temp, 1);
static SENSOR_DEVICE_ATTR_RW(temp1_max, mt7915_thermal_temp, 2);
static SENSOR_DEVICE_ATTR_RO(throttle1, mt7915_thermal_temp, 3);
static struct attribute *mt7915_hwmon_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_crit.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_throttle1.dev_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(mt7915_hwmon);
......@@ -97,7 +106,7 @@ static int
mt7915_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev,
unsigned long *state)
{
*state = MT7915_THERMAL_THROTTLE_MAX;
*state = MT7915_CDEV_THROTTLE_MAX;
return 0;
}
......@@ -108,7 +117,7 @@ mt7915_thermal_get_cur_throttle_state(struct thermal_cooling_device *cdev,
{
struct mt7915_phy *phy = cdev->devdata;
*state = phy->throttle_state;
*state = phy->cdev_state;
return 0;
}
......@@ -118,22 +127,27 @@ mt7915_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev,
unsigned long state)
{
struct mt7915_phy *phy = cdev->devdata;
u8 throttling = MT7915_THERMAL_THROTTLE_MAX - state;
int ret;
if (state > MT7915_THERMAL_THROTTLE_MAX)
if (state > MT7915_CDEV_THROTTLE_MAX)
return -EINVAL;
if (phy->throttle_temp[0] > phy->throttle_temp[1])
return 0;
if (state == phy->throttle_state)
if (state == phy->cdev_state)
return 0;
ret = mt7915_mcu_set_thermal_throttling(phy, state);
/*
* cooling_device convention: 0 = no cooling, more = more cooling
* mcu convention: 1 = max cooling, more = less cooling
*/
ret = mt7915_mcu_set_thermal_throttling(phy, throttling);
if (ret)
return ret;
phy->throttle_state = state;
phy->cdev_state = state;
return 0;
}
......@@ -186,7 +200,8 @@ static int mt7915_thermal_init(struct mt7915_phy *phy)
phy->throttle_temp[0] = 110;
phy->throttle_temp[1] = 120;
return 0;
return mt7915_mcu_set_thermal_throttling(phy,
MT7915_THERMAL_THROTTLE_MAX);
}
static void mt7915_led_set_config(struct led_classdev *led_cdev,
......@@ -486,6 +501,9 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev)
phy->dev = dev;
phy->mt76 = mphy;
/* Bind main phy to band0 and ext_phy to band1 for dbdc case */
phy->band_idx = 1;
INIT_DELAYED_WORK(&mphy->mac_work, mt7915_mac_work);
mt7915_eeprom_parse_hw_cap(dev, phy);
......@@ -505,7 +523,7 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev)
/* init wiphy according to mphy and phy */
mt7915_init_wiphy(mphy->hw);
ret = mt7915_init_tx_queues(phy, MT_TXQ_ID(1),
ret = mt7915_init_tx_queues(phy, MT_TXQ_ID(phy->band_idx),
MT7915_TX_RING_SIZE,
MT_TXQ_RING_BASE(1));
if (ret)
......@@ -582,6 +600,12 @@ static void mt7915_wfsys_reset(struct mt7915_dev *dev)
mt76_clear(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE);
msleep(100);
} else if (is_mt7986(&dev->mt76)) {
mt7986_wmac_disable(dev);
msleep(20);
mt7986_wmac_enable(dev);
msleep(20);
} else {
mt76_set(dev, MT_WF_SUBSYS_RST, 0x1);
msleep(20);
......@@ -591,6 +615,32 @@ static void mt7915_wfsys_reset(struct mt7915_dev *dev)
}
}
static bool mt7915_band_config(struct mt7915_dev *dev)
{
bool ret = true;
dev->phy.band_idx = 0;
if (is_mt7986(&dev->mt76)) {
u32 sku = mt7915_check_adie(dev, true);
/*
* for mt7986, dbdc support is determined by the number
* of adie chips and the main phy is bound to band1 when
* dbdc is disabled.
*/
if (sku == MT7975_ONE_ADIE || sku == MT7976_ONE_ADIE) {
dev->phy.band_idx = 1;
ret = false;
}
} else {
ret = is_mt7915(&dev->mt76) ?
!!(mt76_rr(dev, MT_HW_BOUND) & BIT(5)) : true;
}
return ret;
}
static int mt7915_init_hardware(struct mt7915_dev *dev)
{
int ret, idx;
......@@ -599,8 +649,7 @@ static int mt7915_init_hardware(struct mt7915_dev *dev)
INIT_WORK(&dev->init_work, mt7915_init_work);
dev->dbdc_support = is_mt7915(&dev->mt76) ?
!!(mt76_rr(dev, MT_HW_BOUND) & BIT(5)) : true;
dev->dbdc_support = mt7915_band_config(dev);
/* If MCU was already running, it is likely in a bad state */
if (mt76_get_field(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE) >
......@@ -767,9 +816,17 @@ static int
mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
struct ieee80211_sband_iftype_data *data)
{
struct mt7915_dev *dev = phy->dev;
int i, idx = 0, nss = hweight8(phy->mt76->chainmask);
u16 mcs_map = 0;
u16 mcs_map_160 = 0;
u8 nss_160;
/* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */
if (is_mt7915(&dev->mt76) && !dev->dbdc_support)
nss_160 = nss / 2;
else
nss_160 = nss;
for (i = 0; i < 8; i++) {
if (i < nss)
......@@ -777,8 +834,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
else
mcs_map |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2));
/* Can do 1/2 of NSS streams in 160Mhz mode. */
if (i < nss / 2)
if (i < nss_160)
mcs_map_160 |= (IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2));
else
mcs_map_160 |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2));
......@@ -1011,5 +1067,8 @@ void mt7915_unregister_device(struct mt7915_dev *dev)
mt7915_dma_cleanup(dev);
tasklet_disable(&dev->irq_tasklet);
if (is_mt7986(&dev->mt76))
mt7986_wmac_disable(dev);
mt76_free_device(&dev->mt76);
}
......@@ -398,7 +398,7 @@ static int mt7915_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
struct ieee80211_sta *sta;
struct ieee80211_vif *vif;
struct ieee80211_hdr hdr;
__le32 qos_ctrl, ht_ctrl;
u16 frame_control;
if (FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, le32_to_cpu(rxd[3])) !=
MT_RXD3_NORMAL_U2M)
......@@ -414,16 +414,15 @@ static int mt7915_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
/* store the info from RXD and ethhdr to avoid being overridden */
hdr.frame_control = FIELD_GET(MT_RXD6_FRAME_CONTROL, rxd[6]);
hdr.seq_ctrl = FIELD_GET(MT_RXD8_SEQ_CTRL, rxd[8]);
qos_ctrl = FIELD_GET(MT_RXD8_QOS_CTL, rxd[8]);
ht_ctrl = FIELD_GET(MT_RXD9_HT_CONTROL, rxd[9]);
frame_control = le32_get_bits(rxd[6], MT_RXD6_FRAME_CONTROL);
hdr.frame_control = cpu_to_le16(frame_control);
hdr.seq_ctrl = cpu_to_le16(le32_get_bits(rxd[8], MT_RXD8_SEQ_CTRL));
hdr.duration_id = 0;
ether_addr_copy(hdr.addr1, vif->addr);
ether_addr_copy(hdr.addr2, sta->addr);
switch (le16_to_cpu(hdr.frame_control) &
(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
switch (frame_control & (IEEE80211_FCTL_TODS |
IEEE80211_FCTL_FROMDS)) {
case 0:
ether_addr_copy(hdr.addr3, vif->bss_conf.bssid);
break;
......@@ -445,15 +444,22 @@ static int mt7915_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
if (eth_hdr->h_proto == cpu_to_be16(ETH_P_AARP) ||
eth_hdr->h_proto == cpu_to_be16(ETH_P_IPX))
ether_addr_copy(skb_push(skb, ETH_ALEN), bridge_tunnel_header);
else if (eth_hdr->h_proto >= cpu_to_be16(ETH_P_802_3_MIN))
else if (be16_to_cpu(eth_hdr->h_proto) >= ETH_P_802_3_MIN)
ether_addr_copy(skb_push(skb, ETH_ALEN), rfc1042_header);
else
skb_pull(skb, 2);
if (ieee80211_has_order(hdr.frame_control))
memcpy(skb_push(skb, 2), &ht_ctrl, 2);
if (ieee80211_is_data_qos(hdr.frame_control))
memcpy(skb_push(skb, 2), &qos_ctrl, 2);
memcpy(skb_push(skb, IEEE80211_HT_CTL_LEN), &rxd[9],
IEEE80211_HT_CTL_LEN);
if (ieee80211_is_data_qos(hdr.frame_control)) {
__le16 qos_ctrl;
qos_ctrl = cpu_to_le16(le32_get_bits(rxd[8], MT_RXD8_QOS_CTL));
memcpy(skb_push(skb, IEEE80211_QOS_CTL_LEN), &qos_ctrl,
IEEE80211_QOS_CTL_LEN);
}
if (ieee80211_has_a4(hdr.frame_control))
memcpy(skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr));
else
......@@ -587,11 +593,11 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
u16 seq_ctrl = 0;
u8 qos_ctl = 0;
__le16 fc = 0;
int i, idx;
int idx;
memset(status, 0, sizeof(*status));
if (rxd1 & MT_RXD1_NORMAL_BAND_IDX) {
if ((rxd1 & MT_RXD1_NORMAL_BAND_IDX) && !phy->band_idx) {
mphy = dev->mt76.phy2;
if (!mphy)
return -EINVAL;
......@@ -747,15 +753,6 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, v1);
status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, v1);
status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, v1);
status->signal = status->chain_signal[0];
for (i = 1; i < hweight8(mphy->antenna_mask); i++) {
if (!(status->chains & BIT(i)))
continue;
status->signal = max(status->signal,
status->chain_signal[i]);
}
/* RXD Group 5 - C-RXV */
if (rxd1 & MT_RXD1_NORMAL_GROUP_5) {
......@@ -764,9 +761,7 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
return -EINVAL;
}
if (!is_mt7915(&dev->mt76) ||
(is_mt7915(&dev->mt76) &&
(rxd1 & MT_RXD1_NORMAL_GROUP_5))) {
if (!is_mt7915(&dev->mt76) || (rxd1 & MT_RXD1_NORMAL_GROUP_5)) {
ret = mt7915_mac_fill_rx_rate(dev, status, sband, rxv);
if (ret < 0)
return ret;
......@@ -859,13 +854,13 @@ mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb)
__le32 *rxv_hdr = rxd + 2;
__le32 *rxv = rxd + 4;
u32 rcpi, ib_rssi, wb_rssi, v20, v21;
bool ext_phy;
u8 band_idx;
s32 foe;
u8 snr;
int i;
ext_phy = FIELD_GET(MT_RXV_HDR_BAND_IDX, le32_to_cpu(rxv_hdr[1]));
if (ext_phy)
band_idx = FIELD_GET(MT_RXV_HDR_BAND_IDX, le32_to_cpu(rxv_hdr[1]));
if (band_idx && !phy->band_idx)
phy = mt7915_ext_phy(dev);
rcpi = le32_to_cpu(rxv[6]);
......@@ -1121,6 +1116,7 @@ mt7915_mac_write_txwi_80211(struct mt7915_dev *dev, __le32 *txwi,
val = MT_TXD3_SN_VALID |
FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
txwi[3] |= cpu_to_le32(val);
txwi[7] &= ~cpu_to_le32(MT_TXD7_HW_AMSDU);
}
val = FIELD_PREP(MT_TXD7_TYPE, fc_type) |
......@@ -1181,7 +1177,7 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
struct ieee80211_vif *vif = info->control.vif;
struct mt76_phy *mphy = &dev->mphy;
bool ext_phy = info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY;
u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0, band_idx = 0;
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
bool mcast = false;
u16 tx_count = 15;
......@@ -1192,6 +1188,7 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
omac_idx = mvif->mt76.omac_idx;
wmm_idx = mvif->mt76.wmm_idx;
band_idx = mvif->mt76.band_idx;
}
if (ext_phy && dev->mt76.phy2)
......@@ -1218,7 +1215,8 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
if (ext_phy && q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0)
if ((ext_phy || band_idx) &&
q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0)
val |= MT_TXD1_TGID;
txwi[1] = cpu_to_le32(val);
......@@ -1427,7 +1425,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
bool v3, wake = false;
u16 total, count = 0;
u32 txd = le32_to_cpu(free->txd);
u32 *cur_info;
__le32 *cur_info;
/* clean DMA queues and unmap buffers first */
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false);
......@@ -1726,6 +1724,7 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
break;
case PKT_TYPE_RX_FW_MONITOR:
mt7915_debugfs_rx_fw_monitor(dev, skb->data, skb->len);
dev_kfree_skb(skb);
break;
case PKT_TYPE_NORMAL:
if (!mt7915_mac_fill_rx(dev, skb)) {
......@@ -1763,8 +1762,7 @@ void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
bool ext_phy = phy != &dev->phy;
u32 reg = MT_WF_PHY_RX_CTRL1(ext_phy);
u32 reg = MT_WF_PHY_RX_CTRL1(phy->band_idx);
mt76_clear(dev, reg, MT_WF_PHY_RX_CTRL1_STSCNT_EN);
mt76_set(dev, reg, BIT(11) | BIT(9));
......@@ -1773,25 +1771,22 @@ void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy)
void mt7915_mac_reset_counters(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
bool ext_phy = phy != &dev->phy;
int i;
for (i = 0; i < 4; i++) {
mt76_rr(dev, MT_TX_AGG_CNT(ext_phy, i));
mt76_rr(dev, MT_TX_AGG_CNT2(ext_phy, i));
mt76_rr(dev, MT_TX_AGG_CNT(phy->band_idx, i));
mt76_rr(dev, MT_TX_AGG_CNT2(phy->band_idx, i));
}
if (ext_phy) {
dev->mt76.phy2->survey_time = ktime_get_boottime();
i = ARRAY_SIZE(dev->mt76.aggr_stats) / 2;
} else {
dev->mt76.phy.survey_time = ktime_get_boottime();
i = 0;
}
phy->mt76->survey_time = ktime_get_boottime();
if (phy->band_idx)
i = ARRAY_SIZE(dev->mt76.aggr_stats) / 2;
memset(&dev->mt76.aggr_stats[i], 0, sizeof(dev->mt76.aggr_stats) / 2);
/* reset airtime counters */
mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(ext_phy),
mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(phy->band_idx),
MT_WF_RMAC_MIB_RXTIME_CLR);
mt7915_mcu_get_chan_mib_info(phy, true);
......@@ -1801,7 +1796,7 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy)
{
s16 coverage_class = phy->coverage_class;
struct mt7915_dev *dev = phy->dev;
bool ext_phy = phy != &dev->phy;
struct mt7915_phy *ext_phy = mt7915_ext_phy(dev);
u32 val, reg_offset;
u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) |
FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48);
......@@ -1813,17 +1808,11 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy)
if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
return;
if (ext_phy) {
if (ext_phy)
coverage_class = max_t(s16, dev->phy.coverage_class,
coverage_class);
} else {
struct mt7915_phy *phy_ext = mt7915_ext_phy(dev);
ext_phy->coverage_class);
if (phy_ext)
coverage_class = max_t(s16, phy_ext->coverage_class,
coverage_class);
}
mt76_set(dev, MT_ARB_SCR(ext_phy),
mt76_set(dev, MT_ARB_SCR(phy->band_idx),
MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
udelay(1);
......@@ -1831,15 +1820,15 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy)
reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) |
FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset);
mt76_wr(dev, MT_TMAC_CDTR(ext_phy), cck + reg_offset);
mt76_wr(dev, MT_TMAC_ODTR(ext_phy), ofdm + reg_offset);
mt76_wr(dev, MT_TMAC_ICR0(ext_phy),
mt76_wr(dev, MT_TMAC_CDTR(phy->band_idx), cck + reg_offset);
mt76_wr(dev, MT_TMAC_ODTR(phy->band_idx), ofdm + reg_offset);
mt76_wr(dev, MT_TMAC_ICR0(phy->band_idx),
FIELD_PREP(MT_IFS_EIFS_OFDM, is_5ghz ? 84 : 78) |
FIELD_PREP(MT_IFS_RIFS, 2) |
FIELD_PREP(MT_IFS_SIFS, 10) |
FIELD_PREP(MT_IFS_SLOT, phy->slottime));
mt76_wr(dev, MT_TMAC_ICR1(ext_phy),
mt76_wr(dev, MT_TMAC_ICR1(phy->band_idx),
FIELD_PREP(MT_IFS_EIFS_CCK, 314));
if (phy->slottime < 20 || is_5ghz)
......@@ -1847,19 +1836,24 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy)
else
val = MT7915_CFEND_RATE_11B;
mt76_rmw_field(dev, MT_AGG_ACR0(ext_phy), MT_AGG_ACR_CFEND_RATE, val);
mt76_clear(dev, MT_ARB_SCR(ext_phy),
mt76_rmw_field(dev, MT_AGG_ACR0(phy->band_idx), MT_AGG_ACR_CFEND_RATE, val);
mt76_clear(dev, MT_ARB_SCR(phy->band_idx),
MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
}
void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy)
{
mt76_set(dev, MT_WF_PHY_RXTD12(ext_phy),
u32 reg;
reg = is_mt7915(&dev->mt76) ? MT_WF_PHY_RXTD12(ext_phy) :
MT_WF_PHY_RXTD12_MT7916(ext_phy);
mt76_set(dev, reg,
MT_WF_PHY_RXTD12_IRPI_SW_CLR_ONLY |
MT_WF_PHY_RXTD12_IRPI_SW_CLR);
mt76_set(dev, MT_WF_PHY_RX_CTRL1(ext_phy),
FIELD_PREP(MT_WF_PHY_RX_CTRL1_IPI_EN, 0x5));
reg = is_mt7915(&dev->mt76) ? MT_WF_PHY_RX_CTRL1(ext_phy) :
MT_WF_PHY_RX_CTRL1_MT7916(ext_phy);
mt76_set(dev, reg, FIELD_PREP(MT_WF_PHY_RX_CTRL1_IPI_EN, 0x5));
}
static u8
......@@ -1871,7 +1865,9 @@ mt7915_phy_get_nf(struct mt7915_phy *phy, int idx)
int nss, i;
for (nss = 0; nss < hweight8(phy->mt76->chainmask); nss++) {
u32 reg = MT_WF_IRPI(nss + (idx << dev->dbdc_support));
u32 reg = is_mt7915(&dev->mt76) ?
MT_WF_IRPI_NSS(0, nss + (idx << dev->dbdc_support)) :
MT_WF_IRPI_NSS_MT7916(idx, nss);
for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) {
val = mt76_rr(dev, reg);
......@@ -1890,12 +1886,11 @@ void mt7915_update_channel(struct mt76_phy *mphy)
{
struct mt7915_phy *phy = (struct mt7915_phy *)mphy->priv;
struct mt76_channel_state *state = mphy->chan_state;
bool ext_phy = phy != &phy->dev->phy;
int nf;
mt7915_mcu_get_chan_mib_info(phy, false);
nf = mt7915_phy_get_nf(phy, ext_phy);
nf = mt7915_phy_get_nf(phy, phy->band_idx);
if (!phy->noise)
phy->noise = nf << 4;
else if (nf)
......@@ -1956,16 +1951,22 @@ mt7915_dma_reset(struct mt7915_dev *dev)
int i;
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN);
if (is_mt7915(&dev->mt76))
mt76_clear(dev, MT_WFDMA1_GLO_CFG,
MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN);
MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_RX_DMA_EN);
if (dev->hif2) {
mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
(MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN));
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN);
if (is_mt7915(&dev->mt76))
mt76_clear(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
(MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_RX_DMA_EN));
MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_RX_DMA_EN);
}
usleep_range(1000, 2000);
......@@ -1989,19 +1990,23 @@ mt7915_dma_reset(struct mt7915_dev *dev)
mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
if (is_mt7915(&dev->mt76))
mt76_set(dev, MT_WFDMA1_GLO_CFG,
MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN |
MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_RX_DMA_EN |
MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
if (dev->hif2) {
mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
(MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN));
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN);
if (is_mt7915(&dev->mt76))
mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
(MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_RX_DMA_EN |
MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA1_GLO_CFG_OMIT_RX_INFO));
MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
}
}
......@@ -2111,118 +2116,117 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
struct mib_stats *mib = &phy->mib;
bool ext_phy = phy != &dev->phy;
int i, aggr0, aggr1, cnt;
u32 val;
cnt = mt76_rr(dev, MT_MIB_SDR3(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR3(phy->band_idx));
mib->fcs_err_cnt += is_mt7915(&dev->mt76) ? FIELD_GET(MT_MIB_SDR3_FCS_ERR_MASK, cnt) :
FIELD_GET(MT_MIB_SDR3_FCS_ERR_MASK_MT7916, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR4(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR4(phy->band_idx));
mib->rx_fifo_full_cnt += FIELD_GET(MT_MIB_SDR4_RX_FIFO_FULL_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR5(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR5(phy->band_idx));
mib->rx_mpdu_cnt += cnt;
cnt = mt76_rr(dev, MT_MIB_SDR6(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR6(phy->band_idx));
mib->channel_idle_cnt += FIELD_GET(MT_MIB_SDR6_CHANNEL_IDL_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR7(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR7(phy->band_idx));
mib->rx_vector_mismatch_cnt += FIELD_GET(MT_MIB_SDR7_RX_VECTOR_MISMATCH_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR8(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR8(phy->band_idx));
mib->rx_delimiter_fail_cnt += FIELD_GET(MT_MIB_SDR8_RX_DELIMITER_FAIL_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR11(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR11(phy->band_idx));
mib->rx_len_mismatch_cnt += FIELD_GET(MT_MIB_SDR11_RX_LEN_MISMATCH_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR12(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR12(phy->band_idx));
mib->tx_ampdu_cnt += cnt;
cnt = mt76_rr(dev, MT_MIB_SDR13(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR13(phy->band_idx));
mib->tx_stop_q_empty_cnt += FIELD_GET(MT_MIB_SDR13_TX_STOP_Q_EMPTY_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR14(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR14(phy->band_idx));
mib->tx_mpdu_attempts_cnt += is_mt7915(&dev->mt76) ?
FIELD_GET(MT_MIB_SDR14_TX_MPDU_ATTEMPTS_CNT_MASK, cnt) :
FIELD_GET(MT_MIB_SDR14_TX_MPDU_ATTEMPTS_CNT_MASK_MT7916, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR15(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR15(phy->band_idx));
mib->tx_mpdu_success_cnt += is_mt7915(&dev->mt76) ?
FIELD_GET(MT_MIB_SDR15_TX_MPDU_SUCCESS_CNT_MASK, cnt) :
FIELD_GET(MT_MIB_SDR15_TX_MPDU_SUCCESS_CNT_MASK_MT7916, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR22(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR22(phy->band_idx));
mib->rx_ampdu_cnt += cnt;
cnt = mt76_rr(dev, MT_MIB_SDR23(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR23(phy->band_idx));
mib->rx_ampdu_bytes_cnt += cnt;
cnt = mt76_rr(dev, MT_MIB_SDR24(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR24(phy->band_idx));
mib->rx_ampdu_valid_subframe_cnt += is_mt7915(&dev->mt76) ?
FIELD_GET(MT_MIB_SDR24_RX_AMPDU_SF_CNT_MASK, cnt) :
FIELD_GET(MT_MIB_SDR24_RX_AMPDU_SF_CNT_MASK_MT7916, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR25(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR25(phy->band_idx));
mib->rx_ampdu_valid_subframe_bytes_cnt += cnt;
cnt = mt76_rr(dev, MT_MIB_SDR27(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR27(phy->band_idx));
mib->tx_rwp_fail_cnt += FIELD_GET(MT_MIB_SDR27_TX_RWP_FAIL_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR28(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR28(phy->band_idx));
mib->tx_rwp_need_cnt += FIELD_GET(MT_MIB_SDR28_TX_RWP_NEED_CNT_MASK, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR29(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR29(phy->band_idx));
mib->rx_pfdrop_cnt += is_mt7915(&dev->mt76) ?
FIELD_GET(MT_MIB_SDR29_RX_PFDROP_CNT_MASK, cnt) :
FIELD_GET(MT_MIB_SDR29_RX_PFDROP_CNT_MASK_MT7916, cnt);
cnt = mt76_rr(dev, MT_MIB_SDRVEC(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDRVEC(phy->band_idx));
mib->rx_vec_queue_overflow_drop_cnt += is_mt7915(&dev->mt76) ?
FIELD_GET(MT_MIB_SDR30_RX_VEC_QUEUE_OVERFLOW_DROP_CNT_MASK, cnt) :
FIELD_GET(MT_MIB_SDR30_RX_VEC_QUEUE_OVERFLOW_DROP_CNT_MASK_MT7916, cnt);
cnt = mt76_rr(dev, MT_MIB_SDR31(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR31(phy->band_idx));
mib->rx_ba_cnt += cnt;
cnt = mt76_rr(dev, MT_MIB_SDR32(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR32(phy->band_idx));
mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT_MASK, cnt);
if (is_mt7915(&dev->mt76))
cnt = mt76_rr(dev, MT_MIB_SDR33(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR33(phy->band_idx));
mib->tx_pkt_ibf_cnt += is_mt7915(&dev->mt76) ?
FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT_MASK, cnt) :
FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT_MASK_MT7916, cnt);
cnt = mt76_rr(dev, MT_MIB_SDRMUBF(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDRMUBF(phy->band_idx));
mib->tx_bf_cnt += FIELD_GET(MT_MIB_MU_BF_TX_CNT, cnt);
cnt = mt76_rr(dev, MT_MIB_DR8(ext_phy));
cnt = mt76_rr(dev, MT_MIB_DR8(phy->band_idx));
mib->tx_mu_mpdu_cnt += cnt;
cnt = mt76_rr(dev, MT_MIB_DR9(ext_phy));
cnt = mt76_rr(dev, MT_MIB_DR9(phy->band_idx));
mib->tx_mu_acked_mpdu_cnt += cnt;
cnt = mt76_rr(dev, MT_MIB_DR11(ext_phy));
cnt = mt76_rr(dev, MT_MIB_DR11(phy->band_idx));
mib->tx_su_acked_mpdu_cnt += cnt;
cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(ext_phy));
cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(phy->band_idx));
mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt);
mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt);
cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(ext_phy));
cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(phy->band_idx));
mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, cnt);
mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, cnt);
mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, cnt);
mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, cnt);
cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(ext_phy));
cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(phy->band_idx));
mib->tx_bf_rx_fb_bw = FIELD_GET(MT_ETBF_RX_FB_BW, cnt);
mib->tx_bf_rx_fb_nc_cnt += FIELD_GET(MT_ETBF_RX_FB_NC, cnt);
mib->tx_bf_rx_fb_nr_cnt += FIELD_GET(MT_ETBF_RX_FB_NR, cnt);
cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(ext_phy));
cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(phy->band_idx));
mib->tx_bf_fb_cpl_cnt += FIELD_GET(MT_ETBF_TX_FB_CPL, cnt);
mib->tx_bf_fb_trig_cnt += FIELD_GET(MT_ETBF_TX_FB_TRI, cnt);
......@@ -2232,52 +2236,52 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy)
mib->tx_amsdu_cnt += cnt;
}
aggr0 = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0;
aggr0 = phy->band_idx ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0;
if (is_mt7915(&dev->mt76)) {
for (i = 0, aggr1 = aggr0 + 4; i < 4; i++) {
val = mt76_rr(dev, MT_MIB_MB_SDR1(ext_phy, (i << 4)));
val = mt76_rr(dev, MT_MIB_MB_SDR1(phy->band_idx, (i << 4)));
mib->ba_miss_cnt += FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val);
mib->ack_fail_cnt +=
FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val);
val = mt76_rr(dev, MT_MIB_MB_SDR0(ext_phy, (i << 4)));
val = mt76_rr(dev, MT_MIB_MB_SDR0(phy->band_idx, (i << 4)));
mib->rts_cnt += FIELD_GET(MT_MIB_RTS_COUNT_MASK, val);
mib->rts_retries_cnt +=
FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val);
val = mt76_rr(dev, MT_TX_AGG_CNT(ext_phy, i));
val = mt76_rr(dev, MT_TX_AGG_CNT(phy->band_idx, i));
dev->mt76.aggr_stats[aggr0++] += val & 0xffff;
dev->mt76.aggr_stats[aggr0++] += val >> 16;
val = mt76_rr(dev, MT_TX_AGG_CNT2(ext_phy, i));
val = mt76_rr(dev, MT_TX_AGG_CNT2(phy->band_idx, i));
dev->mt76.aggr_stats[aggr1++] += val & 0xffff;
dev->mt76.aggr_stats[aggr1++] += val >> 16;
}
} else {
for (i = 0; i < 2; i++) {
/* rts count */
val = mt76_rr(dev, MT_MIB_MB_SDR0(ext_phy, (i << 2)));
val = mt76_rr(dev, MT_MIB_MB_SDR0(phy->band_idx, (i << 2)));
mib->rts_cnt += FIELD_GET(GENMASK(15, 0), val);
mib->rts_cnt += FIELD_GET(GENMASK(31, 16), val);
/* rts retry count */
val = mt76_rr(dev, MT_MIB_MB_SDR1(ext_phy, (i << 2)));
val = mt76_rr(dev, MT_MIB_MB_SDR1(phy->band_idx, (i << 2)));
mib->rts_retries_cnt += FIELD_GET(GENMASK(15, 0), val);
mib->rts_retries_cnt += FIELD_GET(GENMASK(31, 16), val);
/* ba miss count */
val = mt76_rr(dev, MT_MIB_MB_SDR2(ext_phy, (i << 2)));
val = mt76_rr(dev, MT_MIB_MB_SDR2(phy->band_idx, (i << 2)));
mib->ba_miss_cnt += FIELD_GET(GENMASK(15, 0), val);
mib->ba_miss_cnt += FIELD_GET(GENMASK(31, 16), val);
/* ack fail count */
val = mt76_rr(dev, MT_MIB_MB_BFTF(ext_phy, (i << 2)));
val = mt76_rr(dev, MT_MIB_MB_BFTF(phy->band_idx, (i << 2)));
mib->ack_fail_cnt += FIELD_GET(GENMASK(15, 0), val);
mib->ack_fail_cnt += FIELD_GET(GENMASK(31, 16), val);
}
for (i = 0; i < 8; i++) {
val = mt76_rr(dev, MT_TX_AGG_CNT(ext_phy, i));
val = mt76_rr(dev, MT_TX_AGG_CNT(phy->band_idx, i));
dev->mt76.aggr_stats[aggr0++] += FIELD_GET(GENMASK(15, 0), val);
dev->mt76.aggr_stats[aggr0++] += FIELD_GET(GENMASK(31, 16), val);
}
......@@ -2375,20 +2379,22 @@ static int mt7915_dfs_start_radar_detector(struct mt7915_phy *phy)
{
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
struct mt7915_dev *dev = phy->dev;
bool ext_phy = phy != &dev->phy;
int err;
/* start CAC */
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_START, ext_phy,
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_START, phy->band_idx,
MT_RX_SEL0, 0);
if (err < 0)
return err;
err = mt7915_dfs_start_rdd(dev, ext_phy);
err = mt7915_dfs_start_rdd(dev, phy->band_idx);
if (err < 0)
return err;
phy->rdd_state |= BIT(ext_phy);
phy->rdd_state |= BIT(phy->band_idx);
if (!is_mt7915(&dev->mt76))
return 0;
if (chandef->width == NL80211_CHAN_WIDTH_160 ||
chandef->width == NL80211_CHAN_WIDTH_80P80) {
......@@ -2439,7 +2445,6 @@ mt7915_dfs_init_radar_specs(struct mt7915_phy *phy)
int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
bool ext_phy = phy != &dev->phy;
enum mt76_dfs_state dfs_state, prev_state;
int err;
......@@ -2471,7 +2476,7 @@ int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy)
return 0;
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_END,
ext_phy, MT_RX_SEL0, 0);
phy->band_idx, MT_RX_SEL0, 0);
if (err < 0) {
phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN;
return err;
......@@ -2481,8 +2486,8 @@ int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy)
return 0;
stop:
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_NORMAL_START, ext_phy,
MT_RX_SEL0, 0);
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_NORMAL_START,
phy->band_idx, MT_RX_SEL0, 0);
if (err < 0)
return err;
......
......@@ -49,7 +49,7 @@ static int mt7915_start(struct ieee80211_hw *hw)
mt7915_mac_enable_nf(dev, 0);
}
if (phy != &dev->phy) {
if (phy != &dev->phy || phy->band_idx) {
ret = mt76_connac_mcu_set_pm(&dev->mt76, 1, 0);
if (ret)
goto out;
......@@ -217,7 +217,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
}
mvif->mt76.omac_idx = idx;
mvif->phy = phy;
mvif->mt76.band_idx = ext_phy;
mvif->mt76.band_idx = phy->band_idx;
mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP;
if (ext_phy)
......@@ -235,7 +235,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
INIT_LIST_HEAD(&mvif->sta.rc_list);
INIT_LIST_HEAD(&mvif->sta.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.ext_phy = mvif->mt76.band_idx;
mvif->sta.wcid.ext_phy = ext_phy;
mvif->sta.wcid.hw_key_idx = -1;
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
mt76_packet_id_init(&mvif->sta.wcid);
......@@ -654,6 +654,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
bool ext_phy = mvif->phy != &dev->phy;
int ret, idx;
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
......@@ -665,7 +666,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
msta->vif = mvif;
msta->wcid.sta = 1;
msta->wcid.idx = idx;
msta->wcid.ext_phy = mvif->mt76.band_idx;
msta->wcid.ext_phy = ext_phy;
msta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
msta->jiffies = jiffies;
......@@ -969,12 +970,9 @@ mt7915_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
phy->mt76->antenna_mask = tx_ant;
if (ext_phy) {
if (dev->chainmask == 0xf)
tx_ant <<= 2;
else
tx_ant <<= 1;
}
if (ext_phy)
tx_ant <<= dev->chainshift;
phy->mt76->chainmask = tx_ant;
mt76_set_stream_caps(phy->mt76, true);
......@@ -1241,7 +1239,6 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,
};
struct mib_stats *mib = &phy->mib;
/* See mt7915_ampdu_stat_read_phy, etc */
bool ext_phy = phy != &dev->phy;
int i, n, ei = 0;
mutex_lock(&dev->mt76.mutex);
......@@ -1258,7 +1255,7 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,
data[ei++] = mib->tx_pkt_ibf_cnt;
/* Tx ampdu stat */
n = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0;
n = phy->band_idx ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0;
for (i = 0; i < 15 /*ARRAY_SIZE(bound)*/; i++)
data[ei++] = dev->mt76.aggr_stats[i + n];
......
......@@ -64,6 +64,26 @@ struct mt7915_fw_region {
u8 reserved1[15];
} __packed;
#define fw_name(_dev, name, ...) ({ \
char *_fw; \
switch (mt76_chip(&(_dev)->mt76)) { \
case 0x7915: \
_fw = MT7915_##name; \
break; \
case 0x7986: \
_fw = MT7986_##name##__VA_ARGS__; \
break; \
default: \
_fw = MT7916_##name; \
break; \
} \
_fw; \
})
#define fw_name_var(_dev, name) (mt7915_check_adie(dev, false) ? \
fw_name(_dev, name) : \
fw_name(_dev, name, _MT7975))
#define MCU_PATCH_ADDRESS 0x200000
#define HE_PHY(p, c) u8_get_bits(c, IEEE80211_HE_PHY_##p)
......@@ -89,6 +109,7 @@ mt7915_mcu_set_sta_he_mcs(struct ieee80211_sta *sta, __le16 *he_mcs,
u16 mcs_map)
{
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
struct mt7915_dev *dev = msta->vif->phy->dev;
enum nl80211_band band = msta->vif->phy->mt76->chandef.chan->band;
const u16 *mask = msta->vif->bitrate_mask.control[band].he_mcs;
int nss, max_nss = sta->rx_nss > 3 ? 4 : sta->rx_nss;
......@@ -129,8 +150,9 @@ mt7915_mcu_set_sta_he_mcs(struct ieee80211_sta *sta, __le16 *he_mcs,
mcs_map &= ~(0x3 << (nss * 2));
mcs_map |= mcs << (nss * 2);
/* only support 2ss on 160MHz */
if (nss > 1 && (sta->bandwidth == IEEE80211_STA_RX_BW_160))
/* only support 2ss on 160MHz for mt7915 */
if (is_mt7915(&dev->mt76) && nss > 1 &&
sta->bandwidth == IEEE80211_STA_RX_BW_160)
break;
}
......@@ -141,6 +163,8 @@ static void
mt7915_mcu_set_sta_vht_mcs(struct ieee80211_sta *sta, __le16 *vht_mcs,
const u16 *mask)
{
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
struct mt7915_dev *dev = msta->vif->phy->dev;
u16 mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.rx_mcs_map);
int nss, max_nss = sta->rx_nss > 3 ? 4 : sta->rx_nss;
u16 mcs;
......@@ -162,8 +186,9 @@ mt7915_mcu_set_sta_vht_mcs(struct ieee80211_sta *sta, __le16 *vht_mcs,
vht_mcs[nss] = cpu_to_le16(mcs & mask[nss]);
/* only support 2ss on 160MHz */
if (nss > 1 && (sta->bandwidth == IEEE80211_STA_RX_BW_160))
/* only support 2ss on 160MHz for mt7915 */
if (is_mt7915(&dev->mt76) && nss > 1 &&
sta->bandwidth == IEEE80211_STA_RX_BW_160)
break;
}
}
......@@ -309,7 +334,7 @@ mt7915_mcu_rx_csa_notify(struct mt7915_dev *dev, struct sk_buff *skb)
c = (struct mt7915_mcu_csa_notify *)skb->data;
if (c->band_idx && dev->mt76.phy2)
if ((c->band_idx && !dev->phy.band_idx) && dev->mt76.phy2)
mphy = dev->mt76.phy2;
ieee80211_iterate_active_interfaces_atomic(mphy->hw,
......@@ -328,7 +353,7 @@ mt7915_mcu_rx_thermal_notify(struct mt7915_dev *dev, struct sk_buff *skb)
if (t->ctrl.ctrl_id != THERMAL_PROTECT_ENABLE)
return;
if (t->ctrl.band_idx && dev->mt76.phy2)
if ((t->ctrl.band_idx && !dev->phy.band_idx) && dev->mt76.phy2)
mphy = dev->mt76.phy2;
phy = (struct mt7915_phy *)mphy->priv;
......@@ -343,7 +368,7 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
r = (struct mt7915_mcu_rdd_report *)skb->data;
if (r->band_idx && dev->mt76.phy2)
if ((r->band_idx && !dev->phy.band_idx) && dev->mt76.phy2)
mphy = dev->mt76.phy2;
if (r->band_idx == MT_RX_SEL2)
......@@ -390,6 +415,22 @@ mt7915_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
ieee80211_color_change_finish(vif);
}
static void
mt7915_mcu_rx_bcc_notify(struct mt7915_dev *dev, struct sk_buff *skb)
{
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt7915_mcu_bcc_notify *b;
b = (struct mt7915_mcu_bcc_notify *)skb->data;
if ((b->band_idx && !dev->phy.band_idx) && dev->mt76.phy2)
mphy = dev->mt76.phy2;
ieee80211_iterate_active_interfaces_atomic(mphy->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7915_mcu_cca_finish, mphy->hw);
}
static void
mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
{
......@@ -409,9 +450,7 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
mt7915_mcu_rx_log_message(dev, skb);
break;
case MCU_EXT_EVENT_BCC_NOTIFY:
ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7915_mcu_cca_finish, dev);
mt7915_mcu_rx_bcc_notify(dev, skb);
break;
default:
break;
......@@ -533,12 +572,7 @@ mt7915_mcu_bss_rfch_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
}
if (vif->bss_conf.he_support && vif->type == NL80211_IFTYPE_STATION) {
struct mt7915_dev *dev = phy->dev;
struct mt76_phy *mphy = &dev->mt76.phy;
bool ext_phy = phy != &dev->phy;
if (ext_phy && dev->mt76.phy2)
mphy = dev->mt76.phy2;
struct mt76_phy *mphy = phy->mt76;
ch->he_ru26_block =
mt7915_check_he_obss_narrow_bw_ru(mphy->hw, vif);
......@@ -904,9 +938,6 @@ mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
vif->type != NL80211_IFTYPE_AP)
return;
if (!sta->vht_cap.vht_supported)
return;
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru));
muru = (struct sta_rec_muru *)tlv;
......@@ -914,7 +945,10 @@ mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
muru->cfg.mimo_dl_en = mvif->cap.he_mu_ebfer ||
mvif->cap.vht_mu_ebfer ||
mvif->cap.vht_mu_ebfee;
muru->cfg.mimo_ul_en = true;
muru->cfg.ofdma_dl_en = true;
if (sta->vht_cap.vht_supported)
muru->mimo_dl.vht_mu_bfee =
!!(sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
......@@ -924,13 +958,11 @@ mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
muru->mimo_dl.partial_bw_dl_mimo =
HE_PHY(CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO, elem->phy_cap_info[6]);
muru->cfg.mimo_ul_en = true;
muru->mimo_ul.full_ul_mimo =
HE_PHY(CAP2_UL_MU_FULL_MU_MIMO, elem->phy_cap_info[2]);
muru->mimo_ul.partial_ul_mimo =
HE_PHY(CAP2_UL_MU_PARTIAL_MU_MIMO, elem->phy_cap_info[2]);
muru->cfg.ofdma_dl_en = true;
muru->ofdma_dl.punc_pream_rx =
HE_PHY(CAP1_PREAMBLE_PUNC_RX_MASK, elem->phy_cap_info[1]);
muru->ofdma_dl.he_20m_in_40m_2g =
......@@ -1221,8 +1253,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
struct ieee80211_vif *vif, struct ieee80211_sta *sta)
{
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct mt7915_phy *phy =
mvif->mt76.band_idx ? mt7915_ext_phy(dev) : &dev->phy;
struct mt7915_phy *phy = mvif->phy;
int tx_ant = hweight8(phy->mt76->chainmask) - 1;
struct sta_rec_bf *bf;
struct tlv *tlv;
......@@ -1288,8 +1319,7 @@ mt7915_mcu_sta_bfee_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
struct ieee80211_vif *vif, struct ieee80211_sta *sta)
{
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct mt7915_phy *phy =
mvif->mt76.band_idx ? mt7915_ext_phy(dev) : &dev->phy;
struct mt7915_phy *phy = mvif->phy;
int tx_ant = hweight8(phy->mt76->chainmask) - 1;
struct sta_rec_bfee *bfee;
struct tlv *tlv;
......@@ -1518,6 +1548,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
ra->channel = chandef->chan->hw_value;
ra->bw = sta->bandwidth;
ra->phy.bw = sta->bandwidth;
ra->mmps_mode = mt7915_mcu_get_mmps_mode(sta->smps_mode);
if (supp_rate) {
supp_rate &= mask->control[band].legacy;
......@@ -1902,6 +1933,7 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
struct tlv *tlv;
struct bss_info_bcn *bcn;
int len = MT7915_BEACON_UPDATE_SIZE + MAX_BEACON_SIZE;
bool ext_phy = phy != &dev->phy;
rskb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
NULL, len);
......@@ -1925,7 +1957,7 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
return -EINVAL;
}
if (mvif->mt76.band_idx) {
if (ext_phy) {
info = IEEE80211_SKB_CB(skb);
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
}
......@@ -1962,7 +1994,6 @@ static int mt7915_load_patch(struct mt7915_dev *dev)
{
const struct mt7915_patch_hdr *hdr;
const struct firmware *fw = NULL;
const char *patch;
int i, ret, sem;
sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, 1);
......@@ -1976,8 +2007,8 @@ static int mt7915_load_patch(struct mt7915_dev *dev)
return -EAGAIN;
}
patch = is_mt7915(&dev->mt76) ? MT7915_ROM_PATCH : MT7916_ROM_PATCH;
ret = request_firmware(&fw, patch, dev->mt76.dev);
ret = request_firmware(&fw, fw_name_var(dev, ROM_PATCH),
dev->mt76.dev);
if (ret)
goto out;
......@@ -2096,11 +2127,10 @@ static int mt7915_load_ram(struct mt7915_dev *dev)
{
const struct mt7915_fw_trailer *hdr;
const struct firmware *fw;
const char *mcu;
int ret;
mcu = is_mt7915(&dev->mt76) ? MT7915_FIRMWARE_WM : MT7916_FIRMWARE_WM;
ret = request_firmware(&fw, mcu, dev->mt76.dev);
ret = request_firmware(&fw, fw_name_var(dev, FIRMWARE_WM),
dev->mt76.dev);
if (ret)
return ret;
......@@ -2124,8 +2154,8 @@ static int mt7915_load_ram(struct mt7915_dev *dev)
release_firmware(fw);
mcu = is_mt7915(&dev->mt76) ? MT7915_FIRMWARE_WA : MT7916_FIRMWARE_WA;
ret = request_firmware(&fw, mcu, dev->mt76.dev);
ret = request_firmware(&fw, fw_name(dev, FIRMWARE_WA),
dev->mt76.dev);
if (ret)
return ret;
......@@ -2268,7 +2298,7 @@ int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy, void *ms)
u8 band_idx;
} req = {
.cmd = cpu_to_le32(MURU_GET_TXC_TX_STATS),
.band_idx = phy != &dev->phy,
.band_idx = phy->band_idx,
};
ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(MURU_CTRL),
......@@ -2741,7 +2771,6 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
struct mt7915_dev *dev = phy->dev;
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
int freq1 = chandef->center_freq1;
bool ext_phy = phy != &dev->phy;
struct {
u8 control_ch;
u8 center_ch;
......@@ -2765,7 +2794,7 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
.bw = mt76_connac_chan_bw(chandef),
.tx_streams_num = hweight8(phy->mt76->antenna_mask),
.rx_streams = phy->mt76->antenna_mask,
.band_idx = ext_phy,
.band_idx = phy->band_idx,
.channel_band = chandef->chan->band,
};
......@@ -2777,17 +2806,17 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
req.tx_streams_num = fls(phy->mt76->test.tx_antenna_mask);
req.rx_streams = phy->mt76->test.tx_antenna_mask;
if (ext_phy) {
req.tx_streams_num = 2;
req.rx_streams >>= 2;
}
if (phy != &dev->phy)
req.rx_streams >>= dev->chainshift;
}
#endif
if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
if (cmd == MCU_EXT_CMD(SET_RX_PATH))
req.switch_reason = CH_SWITCH_NORMAL;
else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
else if (phy->mt76->hw->conf.radar_enabled &&
chandef->chan->dfs_state != NL80211_DFS_AVAILABLE)
else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,
NL80211_IFTYPE_AP))
req.switch_reason = CH_SWITCH_DFS;
else
req.switch_reason = CH_SWITCH_NORMAL;
......@@ -3064,10 +3093,12 @@ int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch)
struct mt7915_dev *dev = phy->dev;
struct mt7915_mcu_mib *res, req[4];
struct sk_buff *skb;
int i, ret, start = 0;
int i, ret, start = 0, ofs = 20;
if (!is_mt7915(&dev->mt76))
if (!is_mt7915(&dev->mt76)) {
start = 4;
ofs = 0;
}
for (i = 0; i < 4; i++) {
req[i].band = cpu_to_le32(phy != &dev->phy);
......@@ -3079,7 +3110,7 @@ int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch)
if (ret)
return ret;
res = (struct mt7915_mcu_mib *)(skb->data + 20);
res = (struct mt7915_mcu_mib *)(skb->data + ofs);
if (chan_switch)
goto out;
......@@ -3131,7 +3162,7 @@ int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state)
u8 rsv[2];
} __packed req = {
.ctrl = {
.band_idx = phy != &dev->phy,
.band_idx = phy->band_idx,
},
};
int level;
......
......@@ -79,6 +79,15 @@ struct mt7915_mcu_csa_notify {
u8 rsv;
} __packed;
struct mt7915_mcu_bcc_notify {
struct mt7915_mcu_rxd rxd;
u8 band_idx;
u8 omac_idx;
u8 cca_count;
u8 rsv;
} __packed;
struct mt7915_mcu_rdd_report {
struct mt7915_mcu_rxd rxd;
......
......@@ -17,6 +17,11 @@ static const u32 mt7915_reg[] = {
[INT1_MASK_CSR] = 0xd708c,
[INT_MCU_CMD_SOURCE] = 0xd51f0,
[INT_MCU_CMD_EVENT] = 0x3108,
[WFDMA0_ADDR] = 0xd4000,
[WFDMA0_PCIE1_ADDR] = 0xd8000,
[WFDMA_EXT_CSR_ADDR] = 0xd7000,
[CBTOP1_PHY_END] = 0x77ffffff,
[INFRA_MCU_ADDR_END] = 0x7c3fffff,
};
static const u32 mt7916_reg[] = {
......@@ -26,6 +31,25 @@ static const u32 mt7916_reg[] = {
[INT1_MASK_CSR] = 0xd8204,
[INT_MCU_CMD_SOURCE] = 0xd41f0,
[INT_MCU_CMD_EVENT] = 0x2108,
[WFDMA0_ADDR] = 0xd4000,
[WFDMA0_PCIE1_ADDR] = 0xd8000,
[WFDMA_EXT_CSR_ADDR] = 0xd7000,
[CBTOP1_PHY_END] = 0x7fffffff,
[INFRA_MCU_ADDR_END] = 0x7c085fff,
};
static const u32 mt7986_reg[] = {
[INT_SOURCE_CSR] = 0x24200,
[INT_MASK_CSR] = 0x24204,
[INT1_SOURCE_CSR] = 0x28200,
[INT1_MASK_CSR] = 0x28204,
[INT_MCU_CMD_SOURCE] = 0x241f0,
[INT_MCU_CMD_EVENT] = 0x54000108,
[WFDMA0_ADDR] = 0x24000,
[WFDMA0_PCIE1_ADDR] = 0x28000,
[WFDMA_EXT_CSR_ADDR] = 0x27000,
[CBTOP1_PHY_END] = 0x7fffffff,
[INFRA_MCU_ADDR_END] = 0x7c085fff,
};
static const u32 mt7915_offs[] = {
......@@ -264,11 +288,68 @@ static const struct __map mt7916_reg_map[] = {
{ 0x0, 0x0, 0x0 }, /* imply end of search */
};
static const struct __map mt7986_reg_map[] = {
{ 0x54000000, 0x402000, 0x1000 }, /* WFDMA_0 (PCIE0 MCU DMA0) */
{ 0x55000000, 0x403000, 0x1000 }, /* WFDMA_1 (PCIE0 MCU DMA1) */
{ 0x56000000, 0x404000, 0x1000 }, /* WFDMA_2 (Reserved) */
{ 0x57000000, 0x405000, 0x1000 }, /* WFDMA_3 (MCU wrap CR) */
{ 0x58000000, 0x406000, 0x1000 }, /* WFDMA_4 (PCIE1 MCU DMA0) */
{ 0x59000000, 0x407000, 0x1000 }, /* WFDMA_5 (PCIE1 MCU DMA1) */
{ 0x820c0000, 0x408000, 0x4000 }, /* WF_UMAC_TOP (PLE) */
{ 0x820c8000, 0x40c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */
{ 0x820cc000, 0x40e000, 0x2000 }, /* WF_UMAC_TOP (PP) */
{ 0x820e0000, 0x420000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */
{ 0x820e1000, 0x420400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */
{ 0x820e2000, 0x420800, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */
{ 0x820e3000, 0x420c00, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */
{ 0x820e4000, 0x421000, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */
{ 0x820e5000, 0x421400, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */
{ 0x820ce000, 0x421c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */
{ 0x820e7000, 0x421e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */
{ 0x820cf000, 0x422000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */
{ 0x820e9000, 0x423400, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
{ 0x820ea000, 0x424000, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */
{ 0x820eb000, 0x424200, 0x0400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */
{ 0x820ec000, 0x424600, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_INT) */
{ 0x820ed000, 0x424800, 0x0800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */
{ 0x820ca000, 0x426000, 0x2000 }, /* WF_LMAC_TOP BN0 (WF_MUCOP) */
{ 0x820d0000, 0x430000, 0x10000}, /* WF_LMAC_TOP (WF_WTBLON) */
{ 0x00400000, 0x480000, 0x10000}, /* WF_MCU_SYSRAM */
{ 0x00410000, 0x490000, 0x10000}, /* WF_MCU_SYSRAM */
{ 0x820f0000, 0x4a0000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */
{ 0x820f1000, 0x4a0600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */
{ 0x820f2000, 0x4a0800, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */
{ 0x820f3000, 0x4a0c00, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */
{ 0x820f4000, 0x4a1000, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */
{ 0x820f5000, 0x4a1400, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */
{ 0x820f7000, 0x4a1e00, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */
{ 0x820f9000, 0x4a3400, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
{ 0x820fa000, 0x4a4000, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */
{ 0x820fb000, 0x4a4200, 0x0400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */
{ 0x820fc000, 0x4a4600, 0x0200 }, /* WF_LMAC_TOP BN1 (WF_INT) */
{ 0x820fd000, 0x4a4800, 0x0800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */
{ 0x820c4000, 0x4a8000, 0x1000 }, /* WF_LMAC_TOP (WF_UWTBL ) */
{ 0x820b0000, 0x4ae000, 0x1000 }, /* [APB2] WFSYS_ON */
{ 0x80020000, 0x4b0000, 0x10000}, /* WF_TOP_MISC_OFF */
{ 0x81020000, 0x4c0000, 0x10000}, /* WF_TOP_MISC_ON */
{ 0x89000000, 0x4d0000, 0x1000 }, /* WF_MCU_CFG_ON */
{ 0x89010000, 0x4d1000, 0x1000 }, /* WF_MCU_CIRQ */
{ 0x89020000, 0x4d2000, 0x1000 }, /* WF_MCU_GPT */
{ 0x89030000, 0x4d3000, 0x1000 }, /* WF_MCU_WDT */
{ 0x80010000, 0x4d4000, 0x1000 }, /* WF_AXIDMA */
{ 0x0, 0x0, 0x0 }, /* imply end of search */
};
static u32 mt7915_reg_map_l1(struct mt7915_dev *dev, u32 addr)
{
u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr);
u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr);
u32 l1_remap = is_mt7915(&dev->mt76) ?
u32 l1_remap;
if (is_mt7986(&dev->mt76))
return MT_CONN_INFRA_OFFSET(addr);
l1_remap = is_mt7915(&dev->mt76) ?
MT_HIF_REMAP_L1 : MT_HIF_REMAP_L1_MT7916;
dev->bus_ops->rmw(&dev->mt76, l1_remap,
......@@ -295,17 +376,19 @@ static u32 mt7915_reg_map_l2(struct mt7915_dev *dev, u32 addr)
/* use read to push write */
dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L2);
} else {
u32 ofs = is_mt7986(&dev->mt76) ? 0x400000 : 0;
offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET_MT7916, addr);
base = FIELD_GET(MT_HIF_REMAP_L2_BASE_MT7916, addr);
dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L2_MT7916,
dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L2_MT7916 + ofs,
MT_HIF_REMAP_L2_MASK_MT7916,
FIELD_PREP(MT_HIF_REMAP_L2_MASK_MT7916, base));
/* use read to push write */
dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L2_MT7916);
dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L2_MT7916 + ofs);
offset += MT_HIF_REMAP_BASE_L2_MT7916;
offset += (MT_HIF_REMAP_BASE_L2_MT7916 + ofs);
}
return offset;
......@@ -338,11 +421,20 @@ static u32 __mt7915_reg_addr(struct mt7915_dev *dev, u32 addr)
if ((addr >= MT_INFRA_BASE && addr < MT_WFSYS0_PHY_START) ||
(addr >= MT_WFSYS0_PHY_START && addr < MT_WFSYS1_PHY_START) ||
(addr >= MT_WFSYS1_PHY_START && addr <= MT_WFSYS1_PHY_END) ||
(addr >= MT_CBTOP1_PHY_START && addr <= MT_CBTOP1_PHY_END) ||
(addr >= MT_CBTOP2_PHY_START && addr <= MT_CBTOP2_PHY_END))
(addr >= MT_WFSYS1_PHY_START && addr <= MT_WFSYS1_PHY_END))
return mt7915_reg_map_l1(dev, addr);
if (dev_is_pci(dev->mt76.dev) &&
((addr >= MT_CBTOP1_PHY_START && addr <= MT_CBTOP1_PHY_END) ||
(addr >= MT_CBTOP2_PHY_START && addr <= MT_CBTOP2_PHY_END)))
return mt7915_reg_map_l1(dev, addr);
/* CONN_INFRA: covert to phyiscal addr and use layer 1 remap */
if (addr >= MT_INFRA_MCU_START && addr <= MT_INFRA_MCU_END) {
addr = addr - MT_INFRA_MCU_START + MT_INFRA_BASE;
return mt7915_reg_map_l1(dev, addr);
}
return mt7915_reg_map_l2(dev, addr);
}
......@@ -393,6 +485,12 @@ static int mt7915_mmio_init(struct mt76_dev *mdev,
dev->reg.map = mt7916_reg_map;
dev->reg.map_size = ARRAY_SIZE(mt7916_reg_map);
break;
case 0x7986:
dev->reg.reg_rev = mt7986_reg;
dev->reg.offs_rev = mt7916_offs;
dev->reg.map = mt7986_reg_map;
dev->reg.map_size = ARRAY_SIZE(mt7986_reg_map);
break;
default:
return -EINVAL;
}
......@@ -585,6 +683,19 @@ static int __init mt7915_init(void)
ret = pci_register_driver(&mt7915_pci_driver);
if (ret)
goto error_pci;
if (IS_ENABLED(CONFIG_MT7986_WMAC)) {
ret = platform_driver_register(&mt7986_wmac_driver);
if (ret)
goto error_wmac;
}
return 0;
error_wmac:
pci_unregister_driver(&mt7915_pci_driver);
error_pci:
pci_unregister_driver(&mt7915_hif_driver);
return ret;
......@@ -592,6 +703,9 @@ static int __init mt7915_init(void)
static void __exit mt7915_exit(void)
{
if (IS_ENABLED(CONFIG_MT7986_WMAC))
platform_driver_unregister(&mt7986_wmac_driver);
pci_unregister_driver(&mt7915_pci_driver);
pci_unregister_driver(&mt7915_hif_driver);
}
......
......@@ -35,9 +35,20 @@
#define MT7916_FIRMWARE_WM "mediatek/mt7916_wm.bin"
#define MT7916_ROM_PATCH "mediatek/mt7916_rom_patch.bin"
#define MT7986_FIRMWARE_WA "mediatek/mt7986_wa.bin"
#define MT7986_FIRMWARE_WM "mediatek/mt7986_wm.bin"
#define MT7986_FIRMWARE_WM_MT7975 "mediatek/mt7986_wm_mt7975.bin"
#define MT7986_ROM_PATCH "mediatek/mt7986_rom_patch.bin"
#define MT7986_ROM_PATCH_MT7975 "mediatek/mt7986_rom_patch_mt7975.bin"
#define MT7915_EEPROM_DEFAULT "mediatek/mt7915_eeprom.bin"
#define MT7915_EEPROM_DEFAULT_DBDC "mediatek/mt7915_eeprom_dbdc.bin"
#define MT7916_EEPROM_DEFAULT "mediatek/mt7916_eeprom.bin"
#define MT7986_EEPROM_MT7975_DEFAULT "mediatek/mt7986_eeprom_mt7975.bin"
#define MT7986_EEPROM_MT7975_DUAL_DEFAULT "mediatek/mt7986_eeprom_mt7975_dual.bin"
#define MT7986_EEPROM_MT7976_DEFAULT "mediatek/mt7986_eeprom_mt7976.bin"
#define MT7986_EEPROM_MT7976_DEFAULT_DBDC "mediatek/mt7986_eeprom_mt7976_dbdc.bin"
#define MT7986_EEPROM_MT7976_DUAL_DEFAULT "mediatek/mt7986_eeprom_mt7976_dual.bin"
#define MT7915_EEPROM_SIZE 3584
#define MT7916_EEPROM_SIZE 4096
......@@ -49,6 +60,7 @@
#define MT7915_CFEND_RATE_11B 0x03 /* 11B LP, 11M */
#define MT7915_THERMAL_THROTTLE_MAX 100
#define MT7915_CDEV_THROTTLE_MAX 99
#define MT7915_SKU_RATE_NUM 161
......@@ -218,11 +230,13 @@ struct mt7915_phy {
struct ieee80211_vif *monitor_vif;
struct thermal_cooling_device *cdev;
u8 cdev_state;
u8 throttle_state;
u32 throttle_temp[2]; /* 0: critical high, 1: maximum */
u32 rxfilter;
u64 omac_mask;
u8 band_idx;
u16 noise;
......@@ -273,6 +287,7 @@ struct mt7915_dev {
struct mt7915_phy *rdd2_phy;
u16 chainmask;
u16 chainshift;
u32 hif_idx;
struct work_struct init_work;
......@@ -305,6 +320,10 @@ struct mt7915_dev {
u8 table_mask;
u8 n_agrt;
} twt;
struct reset_control *rstc;
void __iomem *dcm;
void __iomem *sku;
};
enum {
......@@ -377,11 +396,35 @@ mt7915_ext_phy(struct mt7915_dev *dev)
return phy->priv;
}
static inline u32 mt7915_check_adie(struct mt7915_dev *dev, bool sku)
{
u32 mask = sku ? MT_CONNINFRA_SKU_MASK : MT_ADIE_TYPE_MASK;
if (!is_mt7986(&dev->mt76))
return 0;
return mt76_rr(dev, MT_CONNINFRA_SKU_DEC_ADDR) & mask;
}
extern const struct ieee80211_ops mt7915_ops;
extern const struct mt76_testmode_ops mt7915_testmode_ops;
extern struct pci_driver mt7915_pci_driver;
extern struct pci_driver mt7915_hif_driver;
extern struct platform_driver mt7986_wmac_driver;
#ifdef CONFIG_MT7986_WMAC
int mt7986_wmac_enable(struct mt7915_dev *dev);
void mt7986_wmac_disable(struct mt7915_dev *dev);
#else
static inline int mt7986_wmac_enable(struct mt7915_dev *dev)
{
return 0;
}
static inline void mt7986_wmac_disable(struct mt7915_dev *dev)
{
}
#endif
struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
void __iomem *mem_base, u32 device_id);
irqreturn_t mt7915_irq_handler(int irq, void *dev_instance);
......
......@@ -25,6 +25,11 @@ enum reg_rev {
INT1_MASK_CSR,
INT_MCU_CMD_SOURCE,
INT_MCU_CMD_EVENT,
WFDMA0_ADDR,
WFDMA0_PCIE1_ADDR,
WFDMA_EXT_CSR_ADDR,
CBTOP1_PHY_END,
INFRA_MCU_ADDR_END,
__MT_REG_MAX,
};
......@@ -497,7 +502,7 @@ enum offs_rev {
#define MT_WF_RMAC_MIB_RXTIME_CLR BIT(31)
/* WFDMA0 */
#define MT_WFDMA0_BASE 0xd4000
#define MT_WFDMA0_BASE __REG(WFDMA0_ADDR)
#define MT_WFDMA0(ofs) (MT_WFDMA0_BASE + (ofs))
#define MT_WFDMA0_RST MT_WFDMA0(0x100)
......@@ -545,7 +550,7 @@ enum offs_rev {
#define MT_WFDMA1_PRI_DLY_INT_CFG0 MT_WFDMA1(0x2f0)
/* WFDMA CSR */
#define MT_WFDMA_EXT_CSR_BASE 0xd7000
#define MT_WFDMA_EXT_CSR_BASE __REG(WFDMA_EXT_CSR_ADDR)
#define MT_WFDMA_EXT_CSR(ofs) (MT_WFDMA_EXT_CSR_BASE + (ofs))
#define MT_WFDMA_HOST_CONFIG MT_WFDMA_EXT_CSR(0x30)
......@@ -559,7 +564,7 @@ enum offs_rev {
#define MT_PCIE_RECOG_ID_SEM BIT(31)
/* WFDMA0 PCIE1 */
#define MT_WFDMA0_PCIE1_BASE 0xd8000
#define MT_WFDMA0_PCIE1_BASE __REG(WFDMA0_PCIE1_ADDR)
#define MT_WFDMA0_PCIE1(ofs) (MT_WFDMA0_PCIE1_BASE + (ofs))
#define MT_WFDMA0_PCIE1_BUSY_ENA MT_WFDMA0_PCIE1(0x13c)
......@@ -662,6 +667,16 @@ enum offs_rev {
#define MT_TOP_PWR_HW_CTRL BIT(4)
#define MT_TOP_PWR_PWR_ON BIT(7)
#define MT_TOP_RGU_SYSRAM_PDN (MT_TOP_RGU_BASE + 0x050)
#define MT_TOP_RGU_SYSRAM_SLP (MT_TOP_RGU_BASE + 0x054)
#define MT_TOP_WFSYS_PWR (MT_TOP_RGU_BASE + 0x010)
#define MT_TOP_PWR_EN_MASK BIT(7)
#define MT_TOP_PWR_ACK_MASK BIT(6)
#define MT_TOP_PWR_KEY_MASK GENMASK(31, 16)
#define MT7986_TOP_WM_RESET (MT_TOP_RGU_BASE + 0x120)
#define MT7986_TOP_WM_RESET_MASK BIT(0)
/* l1/l2 remap */
#define MT_HIF_REMAP_L1 0xf11ac
#define MT_HIF_REMAP_L1_MT7916 0xfe260
......@@ -685,9 +700,203 @@ enum offs_rev {
#define MT_WFSYS1_PHY_START 0x18800000
#define MT_WFSYS1_PHY_END 0x18bfffff
#define MT_CBTOP1_PHY_START 0x70000000
#define MT_CBTOP1_PHY_END 0x7fffffff
#define MT_CBTOP1_PHY_END __REG(CBTOP1_PHY_END)
#define MT_CBTOP2_PHY_START 0xf0000000
#define MT_CBTOP2_PHY_END 0xffffffff
#define MT_INFRA_MCU_START 0x7c000000
#define MT_INFRA_MCU_END __REG(INFRA_MCU_ADDR_END)
#define MT_CONN_INFRA_OFFSET(p) ((p) - MT_INFRA_BASE)
/* CONN INFRA CFG */
#define MT_CONN_INFRA_BASE 0x18001000
#define MT_CONN_INFRA(ofs) (MT_CONN_INFRA_BASE + (ofs))
#define MT_CONN_INFRA_EFUSE MT_CONN_INFRA(0x020)
#define MT_CONN_INFRA_ADIE_RESET MT_CONN_INFRA(0x030)
#define MT_CONN_INFRA_ADIE1_RESET_MASK BIT(0)
#define MT_CONN_INFRA_ADIE2_RESET_MASK BIT(2)
#define MT_CONN_INFRA_OSC_RC_EN MT_CONN_INFRA(0x380)
#define MT_CONN_INFRA_OSC_CTRL MT_CONN_INFRA(0x300)
#define MT_CONN_INFRA_OSC_RC_EN_MASK BIT(7)
#define MT_CONN_INFRA_OSC_STB_TIME_MASK GENMASK(23, 0)
#define MT_CONN_INFRA_HW_CTRL MT_CONN_INFRA(0x200)
#define MT_CONN_INFRA_HW_CTRL_MASK BIT(0)
#define MT_CONN_INFRA_WF_SLP_PROT MT_CONN_INFRA(0x540)
#define MT_CONN_INFRA_WF_SLP_PROT_MASK BIT(0)
#define MT_CONN_INFRA_WF_SLP_PROT_RDY MT_CONN_INFRA(0x544)
#define MT_CONN_INFRA_CONN_WF_MASK (BIT(29) | BIT(31))
#define MT_CONN_INFRA_CONN (BIT(25) | BIT(29) | BIT(31))
#define MT_CONN_INFRA_EMI_REQ MT_CONN_INFRA(0x414)
#define MT_CONN_INFRA_EMI_REQ_MASK BIT(0)
#define MT_CONN_INFRA_INFRA_REQ_MASK BIT(5)
/* AFE */
#define MT_AFE_CTRL_BASE(_band) (0x18003000 + ((_band) << 19))
#define MT_AFE_CTRL(_band, ofs) (MT_AFE_CTRL_BASE(_band) + (ofs))
#define MT_AFE_DIG_EN_01(_band) MT_AFE_CTRL(_band, 0x00)
#define MT_AFE_DIG_EN_02(_band) MT_AFE_CTRL(_band, 0x04)
#define MT_AFE_DIG_EN_03(_band) MT_AFE_CTRL(_band, 0x08)
#define MT_AFE_DIG_TOP_01(_band) MT_AFE_CTRL(_band, 0x0c)
#define MT_AFE_PLL_STB_TIME(_band) MT_AFE_CTRL(_band, 0xf4)
#define MT_AFE_PLL_STB_TIME_MASK (GENMASK(30, 16) | GENMASK(14, 0))
#define MT_AFE_PLL_STB_TIME_VAL (FIELD_PREP(GENMASK(30, 16), 0x4bc) | \
FIELD_PREP(GENMASK(14, 0), 0x7e4))
#define MT_AFE_BPLL_CFG_MASK GENMASK(7, 6)
#define MT_AFE_WPLL_CFG_MASK GENMASK(1, 0)
#define MT_AFE_MCU_WPLL_CFG_MASK GENMASK(3, 2)
#define MT_AFE_MCU_BPLL_CFG_MASK GENMASK(17, 16)
#define MT_AFE_PLL_CFG_MASK (MT_AFE_BPLL_CFG_MASK | \
MT_AFE_WPLL_CFG_MASK | \
MT_AFE_MCU_WPLL_CFG_MASK | \
MT_AFE_MCU_BPLL_CFG_MASK)
#define MT_AFE_PLL_CFG_VAL (FIELD_PREP(MT_AFE_BPLL_CFG_MASK, 0x1) | \
FIELD_PREP(MT_AFE_WPLL_CFG_MASK, 0x2) | \
FIELD_PREP(MT_AFE_MCU_WPLL_CFG_MASK, 0x1) | \
FIELD_PREP(MT_AFE_MCU_BPLL_CFG_MASK, 0x2))
#define MT_AFE_DIG_TOP_01_MASK GENMASK(18, 15)
#define MT_AFE_DIG_TOP_01_VAL FIELD_PREP(MT_AFE_DIG_TOP_01_MASK, 0x9)
#define MT_AFE_RG_WBG_EN_RCK_MASK BIT(0)
#define MT_AFE_RG_WBG_EN_BPLL_UP_MASK BIT(21)
#define MT_AFE_RG_WBG_EN_WPLL_UP_MASK BIT(20)
#define MT_AFE_RG_WBG_EN_PLL_UP_MASK (MT_AFE_RG_WBG_EN_BPLL_UP_MASK | \
MT_AFE_RG_WBG_EN_WPLL_UP_MASK)
#define MT_AFE_RG_WBG_EN_TXCAL_MASK GENMASK(21, 17)
#define MT_ADIE_SLP_CTRL_BASE(_band) (0x18005000 + ((_band) << 19))
#define MT_ADIE_SLP_CTRL(_band, ofs) (MT_ADIE_SLP_CTRL_BASE(_band) + (ofs))
#define MT_ADIE_SLP_CTRL_CK0(_band) MT_ADIE_SLP_CTRL(_band, 0x120)
/* ADIE */
#define MT_ADIE_CHIP_ID 0x02c
#define MT_ADIE_CHIP_ID_MASK GENMASK(31, 16)
#define MT_ADIE_IDX0 GENMASK(15, 0)
#define MT_ADIE_IDX1 GENMASK(31, 16)
#define MT_ADIE_RG_TOP_THADC_BG 0x034
#define MT_ADIE_VRPI_SEL_CR_MASK GENMASK(15, 12)
#define MT_ADIE_VRPI_SEL_EFUSE_MASK GENMASK(6, 3)
#define MT_ADIE_RG_TOP_THADC 0x038
#define MT_ADIE_PGA_GAIN_MASK GENMASK(25, 23)
#define MT_ADIE_PGA_GAIN_EFUSE_MASK GENMASK(2, 0)
#define MT_ADIE_LDO_CTRL_MASK GENMASK(27, 26)
#define MT_ADIE_LDO_CTRL_EFUSE_MASK GENMASK(6, 5)
#define MT_AFE_RG_ENCAL_WBTAC_IF_SW 0x070
#define MT_ADIE_EFUSE_RDATA0 0x130
#define MT_ADIE_EFUSE2_CTRL 0x148
#define MT_ADIE_EFUSE_CTRL_MASK BIT(1)
#define MT_ADIE_EFUSE_CFG 0x144
#define MT_ADIE_EFUSE_MODE_MASK GENMASK(7, 6)
#define MT_ADIE_EFUSE_ADDR_MASK GENMASK(25, 16)
#define MT_ADIE_EFUSE_VALID_MASK BIT(29)
#define MT_ADIE_EFUSE_KICK_MASK BIT(30)
#define MT_ADIE_THADC_ANALOG 0x3a6
#define MT_ADIE_THADC_SLOP 0x3a7
#define MT_ADIE_ANA_EN_MASK BIT(7)
#define MT_ADIE_7975_XTAL_CAL 0x3a1
#define MT_ADIE_TRIM_MASK GENMASK(6, 0)
#define MT_ADIE_EFUSE_TRIM_MASK GENMASK(5, 0)
#define MT_ADIE_XO_TRIM_EN_MASK BIT(7)
#define MT_ADIE_XTAL_DECREASE_MASK BIT(6)
#define MT_ADIE_7975_XO_TRIM2 0x3a2
#define MT_ADIE_7975_XO_TRIM3 0x3a3
#define MT_ADIE_7975_XO_TRIM4 0x3a4
#define MT_ADIE_7975_XTAL_EN 0x3a5
#define MT_ADIE_XO_TRIM_FLOW 0x3ac
#define MT_ADIE_XTAL_AXM_80M_OSC 0x390
#define MT_ADIE_XTAL_AXM_40M_OSC 0x391
#define MT_ADIE_XTAL_TRIM1_80M_OSC 0x398
#define MT_ADIE_XTAL_TRIM1_40M_OSC 0x399
#define MT_ADIE_WRI_CK_SEL 0x4ac
#define MT_ADIE_RG_STRAP_PIN_IN 0x4fc
#define MT_ADIE_XTAL_C1 0x654
#define MT_ADIE_XTAL_C2 0x658
#define MT_ADIE_RG_XO_01 0x65c
#define MT_ADIE_RG_XO_03 0x664
#define MT_ADIE_CLK_EN 0xa00
#define MT_ADIE_7975_XTAL 0xa18
#define MT_ADIE_7975_XTAL_EN_MASK BIT(29)
#define MT_ADIE_7975_COCLK 0xa1c
#define MT_ADIE_7975_XO_2 0xa84
#define MT_ADIE_7975_XO_2_FIX_EN BIT(31)
#define MT_ADIE_7975_XO_CTRL2 0xa94
#define MT_ADIE_7975_XO_CTRL2_C1_MASK GENMASK(26, 20)
#define MT_ADIE_7975_XO_CTRL2_C2_MASK GENMASK(18, 12)
#define MT_ADIE_7975_XO_CTRL2_MASK (MT_ADIE_7975_XO_CTRL2_C1_MASK | \
MT_ADIE_7975_XO_CTRL2_C2_MASK)
#define MT_ADIE_7975_XO_CTRL6 0xaa4
#define MT_ADIE_7975_XO_CTRL6_MASK BIT(16)
/* TOP SPI */
#define MT_TOP_SPI_ADIE_BASE(_band) (0x18004000 + ((_band) << 19))
#define MT_TOP_SPI_ADIE(_band, ofs) (MT_TOP_SPI_ADIE_BASE(_band) + (ofs))
#define MT_TOP_SPI_BUSY_CR(_band) MT_TOP_SPI_ADIE(_band, 0)
#define MT_TOP_SPI_POLLING_BIT BIT(5)
#define MT_TOP_SPI_ADDR_CR(_band) MT_TOP_SPI_ADIE(_band, 0x50)
#define MT_TOP_SPI_READ_ADDR_FORMAT (BIT(12) | BIT(13) | BIT(15))
#define MT_TOP_SPI_WRITE_ADDR_FORMAT (BIT(13) | BIT(15))
#define MT_TOP_SPI_WRITE_DATA_CR(_band) MT_TOP_SPI_ADIE(_band, 0x54)
#define MT_TOP_SPI_READ_DATA_CR(_band) MT_TOP_SPI_ADIE(_band, 0x58)
/* CONN INFRA CKGEN */
#define MT_INFRA_CKGEN_BASE 0x18009000
#define MT_INFRA_CKGEN(ofs) (MT_INFRA_CKGEN_BASE + (ofs))
#define MT_INFRA_CKGEN_BUS MT_INFRA_CKGEN(0xa00)
#define MT_INFRA_CKGEN_BUS_CLK_SEL_MASK BIT(23)
#define MT_INFRA_CKGEN_BUS_RDY_SEL_MASK BIT(29)
#define MT_INFRA_CKGEN_BUS_WPLL_DIV_1 MT_INFRA_CKGEN(0x008)
#define MT_INFRA_CKGEN_BUS_WPLL_DIV_2 MT_INFRA_CKGEN(0x00c)
#define MT_INFRA_CKGEN_RFSPI_WPLL_DIV MT_INFRA_CKGEN(0x040)
#define MT_INFRA_CKGEN_DIV_SEL_MASK GENMASK(7, 2)
#define MT_INFRA_CKGEN_DIV_EN_MASK BIT(0)
/* CONN INFRA BUS */
#define MT_INFRA_BUS_BASE 0x1800e000
#define MT_INFRA_BUS(ofs) (MT_INFRA_BUS_BASE + (ofs))
#define MT_INFRA_BUS_OFF_TIMEOUT MT_INFRA_BUS(0x300)
#define MT_INFRA_BUS_TIMEOUT_LIMIT_MASK GENMASK(14, 7)
#define MT_INFRA_BUS_TIMEOUT_EN_MASK GENMASK(3, 0)
#define MT_INFRA_BUS_ON_TIMEOUT MT_INFRA_BUS(0x31c)
#define MT_INFRA_BUS_EMI_START MT_INFRA_BUS(0x360)
#define MT_INFRA_BUS_EMI_END MT_INFRA_BUS(0x364)
/* CONN_INFRA_SKU */
#define MT_CONNINFRA_SKU_DEC_ADDR 0x18050000
#define MT_CONNINFRA_SKU_MASK GENMASK(15, 0)
#define MT_ADIE_TYPE_MASK BIT(1)
/* FW MODE SYNC */
#define MT_SWDEF_MODE 0x41f23c
......@@ -746,6 +955,67 @@ enum offs_rev {
#define MT_HW_REV 0x70010204
#define MT_WF_SUBSYS_RST 0x70002600
#define MT_TOP_WFSYS_WAKEUP MT_TOP(0x1a4)
#define MT_TOP_WFSYS_WAKEUP_MASK BIT(0)
#define MT_TOP_MCU_EMI_BASE MT_TOP(0x1c4)
#define MT_TOP_MCU_EMI_BASE_MASK GENMASK(19, 0)
#define MT_TOP_CONN_INFRA_WAKEUP MT_TOP(0x1a0)
#define MT_TOP_CONN_INFRA_WAKEUP_MASK BIT(0)
#define MT_TOP_WFSYS_RESET_STATUS MT_TOP(0x2cc)
#define MT_TOP_WFSYS_RESET_STATUS_MASK BIT(30)
/* SEMA */
#define MT_SEMA_BASE 0x18070000
#define MT_SEMA(ofs) (MT_SEMA_BASE + (ofs))
#define MT_SEMA_RFSPI_STATUS (MT_SEMA(0x2000) + (11 * 4))
#define MT_SEMA_RFSPI_RELEASE (MT_SEMA(0x2200) + (11 * 4))
#define MT_SEMA_RFSPI_STATUS_MASK BIT(1)
/* MCU BUS */
#define MT_MCU_BUS_BASE 0x18400000
#define MT_MCU_BUS(ofs) (MT_MCU_BUS_BASE + (ofs))
#define MT_MCU_BUS_TIMEOUT MT_MCU_BUS(0xf0440)
#define MT_MCU_BUS_TIMEOUT_SET_MASK GENMASK(7, 0)
#define MT_MCU_BUS_TIMEOUT_CG_EN_MASK BIT(28)
#define MT_MCU_BUS_TIMEOUT_EN_MASK BIT(31)
#define MT_MCU_BUS_REMAP MT_MCU_BUS(0x120)
/* TOP CFG */
#define MT_TOP_CFG_BASE 0x184b0000
#define MT_TOP_CFG(ofs) (MT_TOP_CFG_BASE + (ofs))
#define MT_TOP_CFG_IP_VERSION_ADDR MT_TOP_CFG(0x010)
/* TOP CFG ON */
#define MT_TOP_CFG_ON_BASE 0x184c1000
#define MT_TOP_CFG_ON(ofs) (MT_TOP_CFG_ON_BASE + (ofs))
#define MT_TOP_CFG_ON_ROM_IDX MT_TOP_CFG_ON(0x604)
/* SLP CTRL */
#define MT_SLP_BASE 0x184c3000
#define MT_SLP(ofs) (MT_SLP_BASE + (ofs))
#define MT_SLP_STATUS MT_SLP(0x00c)
#define MT_SLP_WFDMA2CONN_MASK (BIT(21) | BIT(23))
#define MT_SLP_CTRL_EN_MASK BIT(0)
#define MT_SLP_CTRL_BSY_MASK BIT(1)
/* MCU BUS DBG */
#define MT_MCU_BUS_DBG_BASE 0x18500000
#define MT_MCU_BUS_DBG(ofs) (MT_MCU_BUS_DBG_BASE + (ofs))
#define MT_MCU_BUS_DBG_TIMEOUT MT_MCU_BUS_DBG(0x0)
#define MT_MCU_BUS_DBG_TIMEOUT_SET_MASK GENMASK(31, 16)
#define MT_MCU_BUS_DBG_TIMEOUT_CK_EN_MASK BIT(3)
#define MT_MCU_BUS_DBG_TIMEOUT_EN_MASK BIT(2)
/* PCIE MAC */
#define MT_PCIE_MAC_BASE 0x74030000
#define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs))
......@@ -761,18 +1031,23 @@ enum offs_rev {
#define MT_WF_PP_TOP_RXQ_WFDMA_CF_5 MT_WF_PP_TOP(0x0e8)
#define MT_WF_PP_TOP_RXQ_QID6_WFDMA_HIF_SEL_MASK BIT(6)
#define MT_WF_IRPI_BASE 0x83006000
#define MT_WF_IRPI(ofs) (MT_WF_IRPI_BASE + ((ofs) << 16))
#define MT_WF_IRPI_BASE 0x83000000
#define MT_WF_IRPI(ofs) (MT_WF_IRPI_BASE + (ofs))
#define MT_WF_IRPI_NSS(phy, nss) MT_WF_IRPI(0x6000 + ((phy) << 20) + ((nss) << 16))
#define MT_WF_IRPI_NSS_MT7916(phy, nss) MT_WF_IRPI(0x1000 + ((phy) << 20) + ((nss) << 16))
/* PHY: band 0(0x83080000), band 1(0x83090000) */
/* PHY */
#define MT_WF_PHY_BASE 0x83080000
#define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs))
#define MT_WF_PHY_RX_CTRL1(_phy) MT_WF_PHY(0x2004 + ((_phy) << 16))
#define MT_WF_PHY_RX_CTRL1_MT7916(_phy) MT_WF_PHY(0x2004 + ((_phy) << 20))
#define MT_WF_PHY_RX_CTRL1_IPI_EN GENMASK(2, 0)
#define MT_WF_PHY_RX_CTRL1_STSCNT_EN GENMASK(11, 9)
#define MT_WF_PHY_RXTD12(_phy) MT_WF_PHY(0x8230 + ((_phy) << 16))
#define MT_WF_PHY_RXTD12_MT7916(_phy) MT_WF_PHY(0x8230 + ((_phy) << 20))
#define MT_WF_PHY_RXTD12_IRPI_SW_CLR_ONLY BIT(18)
#define MT_WF_PHY_RXTD12_IRPI_SW_CLR BIT(29)
......
// SPDX-License-Identifier: ISC
/* Copyright (C) 2022 MediaTek Inc. */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_reserved_mem.h>
#include <linux/of_gpio.h>
#include <linux/iopoll.h>
#include <linux/reset.h>
#include <linux/of_net.h>
#include "mt7915.h"
/* INFRACFG */
#define MT_INFRACFG_CONN2AP_SLPPROT 0x0d0
#define MT_INFRACFG_AP2CONN_SLPPROT 0x0d4
#define MT_INFRACFG_RX_EN_MASK BIT(16)
#define MT_INFRACFG_TX_RDY_MASK BIT(4)
#define MT_INFRACFG_TX_EN_MASK BIT(0)
/* TOP POS */
#define MT_TOP_POS_FAST_CTRL 0x114
#define MT_TOP_POS_FAST_EN_MASK BIT(3)
#define MT_TOP_POS_SKU 0x21c
#define MT_TOP_POS_SKU_MASK GENMASK(31, 28)
#define MT_TOP_POS_SKU_ADIE_DBDC_MASK BIT(2)
enum {
ADIE_SB,
ADIE_DBDC
};
static int
mt76_wmac_spi_read(struct mt7915_dev *dev, u8 adie, u32 addr, u32 *val)
{
int ret;
u32 cur;
ret = read_poll_timeout(mt76_rr, cur, !(cur & MT_TOP_SPI_POLLING_BIT),
USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
dev, MT_TOP_SPI_BUSY_CR(adie));
if (ret)
return ret;
mt76_wr(dev, MT_TOP_SPI_ADDR_CR(adie),
MT_TOP_SPI_READ_ADDR_FORMAT | addr);
mt76_wr(dev, MT_TOP_SPI_WRITE_DATA_CR(adie), 0);
ret = read_poll_timeout(mt76_rr, cur, !(cur & MT_TOP_SPI_POLLING_BIT),
USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
dev, MT_TOP_SPI_BUSY_CR(adie));
if (ret)
return ret;
*val = mt76_rr(dev, MT_TOP_SPI_READ_DATA_CR(adie));
return 0;
}
static int
mt76_wmac_spi_write(struct mt7915_dev *dev, u8 adie, u32 addr, u32 val)
{
int ret;
u32 cur;
ret = read_poll_timeout(mt76_rr, cur, !(cur & MT_TOP_SPI_POLLING_BIT),
USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
dev, MT_TOP_SPI_BUSY_CR(adie));
if (ret)
return ret;
mt76_wr(dev, MT_TOP_SPI_ADDR_CR(adie),
MT_TOP_SPI_WRITE_ADDR_FORMAT | addr);
mt76_wr(dev, MT_TOP_SPI_WRITE_DATA_CR(adie), val);
return read_poll_timeout(mt76_rr, cur, !(cur & MT_TOP_SPI_POLLING_BIT),
USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
dev, MT_TOP_SPI_BUSY_CR(adie));
}
static int
mt76_wmac_spi_rmw(struct mt7915_dev *dev, u8 adie,
u32 addr, u32 mask, u32 val)
{
u32 cur, ret;
ret = mt76_wmac_spi_read(dev, adie, addr, &cur);
if (ret)
return ret;
cur &= ~mask;
cur |= val;
return mt76_wmac_spi_write(dev, adie, addr, cur);
}
static int
mt7986_wmac_adie_efuse_read(struct mt7915_dev *dev, u8 adie,
u32 addr, u32 *data)
{
int ret, temp;
u32 val, mask;
ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_EFUSE_CFG,
MT_ADIE_EFUSE_CTRL_MASK);
if (ret)
return ret;
ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_EFUSE2_CTRL, BIT(30), 0x0);
if (ret)
return ret;
mask = (MT_ADIE_EFUSE_MODE_MASK | MT_ADIE_EFUSE_ADDR_MASK |
MT_ADIE_EFUSE_KICK_MASK);
val = FIELD_PREP(MT_ADIE_EFUSE_MODE_MASK, 0) |
FIELD_PREP(MT_ADIE_EFUSE_ADDR_MASK, addr) |
FIELD_PREP(MT_ADIE_EFUSE_KICK_MASK, 1);
ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_EFUSE2_CTRL, mask, val);
if (ret)
return ret;
ret = read_poll_timeout(mt76_wmac_spi_read, temp,
!temp && !FIELD_GET(MT_ADIE_EFUSE_KICK_MASK, val),
USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
dev, adie, MT_ADIE_EFUSE2_CTRL, &val);
if (ret)
return ret;
ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_EFUSE2_CTRL, &val);
if (ret)
return ret;
if (FIELD_GET(MT_ADIE_EFUSE_VALID_MASK, val) == 1)
ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_EFUSE_RDATA0,
data);
return ret;
}
static inline void mt76_wmac_spi_lock(struct mt7915_dev *dev)
{
u32 cur;
read_poll_timeout(mt76_rr, cur,
FIELD_GET(MT_SEMA_RFSPI_STATUS_MASK, cur),
1000, 1000 * MSEC_PER_SEC, false, dev,
MT_SEMA_RFSPI_STATUS);
}
static inline void mt76_wmac_spi_unlock(struct mt7915_dev *dev)
{
mt76_wr(dev, MT_SEMA_RFSPI_RELEASE, 1);
}
static u32 mt76_wmac_rmw(void __iomem *base, u32 offset, u32 mask, u32 val)
{
val |= readl(base + offset) & ~mask;
writel(val, base + offset);
return val;
}
static u8 mt7986_wmac_check_adie_type(struct mt7915_dev *dev)
{
u32 val;
val = readl(dev->sku + MT_TOP_POS_SKU);
return FIELD_GET(MT_TOP_POS_SKU_ADIE_DBDC_MASK, val);
}
static int mt7986_wmac_consys_reset(struct mt7915_dev *dev, bool enable)
{
if (!enable)
return reset_control_assert(dev->rstc);
mt76_wmac_rmw(dev->sku, MT_TOP_POS_FAST_CTRL,
MT_TOP_POS_FAST_EN_MASK,
FIELD_PREP(MT_TOP_POS_FAST_EN_MASK, 0x1));
return reset_control_deassert(dev->rstc);
}
static int mt7986_wmac_gpio_setup(struct mt7915_dev *dev)
{
struct pinctrl_state *state;
struct pinctrl *pinctrl;
int ret;
u8 type;
type = mt7986_wmac_check_adie_type(dev);
pinctrl = devm_pinctrl_get(dev->mt76.dev);
switch (type) {
case ADIE_SB:
state = pinctrl_lookup_state(pinctrl, "default");
if (IS_ERR_OR_NULL(state))
return -EINVAL;
break;
case ADIE_DBDC:
state = pinctrl_lookup_state(pinctrl, "dbdc");
if (IS_ERR_OR_NULL(state))
return -EINVAL;
break;
}
ret = pinctrl_select_state(pinctrl, state);
if (ret)
return ret;
usleep_range(500, 1000);
return 0;
}
static int mt7986_wmac_consys_lockup(struct mt7915_dev *dev, bool enable)
{
int ret;
u32 cur;
mt76_wmac_rmw(dev->dcm, MT_INFRACFG_AP2CONN_SLPPROT,
MT_INFRACFG_RX_EN_MASK,
FIELD_PREP(MT_INFRACFG_RX_EN_MASK, enable));
ret = read_poll_timeout(readl, cur, !(cur & MT_INFRACFG_RX_EN_MASK),
USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
dev->dcm + MT_INFRACFG_AP2CONN_SLPPROT);
if (ret)
return ret;
mt76_wmac_rmw(dev->dcm, MT_INFRACFG_AP2CONN_SLPPROT,
MT_INFRACFG_TX_EN_MASK,
FIELD_PREP(MT_INFRACFG_TX_EN_MASK, enable));
ret = read_poll_timeout(readl, cur, !(cur & MT_INFRACFG_TX_RDY_MASK),
USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
dev->dcm + MT_INFRACFG_AP2CONN_SLPPROT);
if (ret)
return ret;
mt76_wmac_rmw(dev->dcm, MT_INFRACFG_CONN2AP_SLPPROT,
MT_INFRACFG_RX_EN_MASK,
FIELD_PREP(MT_INFRACFG_RX_EN_MASK, enable));
mt76_wmac_rmw(dev->dcm, MT_INFRACFG_CONN2AP_SLPPROT,
MT_INFRACFG_TX_EN_MASK,
FIELD_PREP(MT_INFRACFG_TX_EN_MASK, enable));
return 0;
}
static int mt7986_wmac_coninfra_check(struct mt7915_dev *dev)
{
u32 cur;
return read_poll_timeout(mt76_rr, cur, (cur == 0x02070000),
USEC_PER_MSEC, 50 * USEC_PER_MSEC,
false, dev, MT_CONN_INFRA_BASE);
}
static int mt7986_wmac_coninfra_setup(struct mt7915_dev *dev)
{
struct device *pdev = dev->mt76.dev;
struct reserved_mem *rmem;
struct device_node *np;
u32 val;
np = of_parse_phandle(pdev->of_node, "memory-region", 0);
if (!np)
return -EINVAL;
rmem = of_reserved_mem_lookup(np);
if (!rmem)
return -EINVAL;
val = (rmem->base >> 16) & MT_TOP_MCU_EMI_BASE_MASK;
/* Set conninfra subsys PLL check */
mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS,
MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1);
mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS,
MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1);
mt76_rmw_field(dev, MT_TOP_MCU_EMI_BASE,
MT_TOP_MCU_EMI_BASE_MASK, val);
mt76_wr(dev, MT_INFRA_BUS_EMI_START, rmem->base);
mt76_wr(dev, MT_INFRA_BUS_EMI_END, rmem->size);
mt76_rr(dev, MT_CONN_INFRA_EFUSE);
/* Set conninfra sysram */
mt76_wr(dev, MT_TOP_RGU_SYSRAM_PDN, 0);
mt76_wr(dev, MT_TOP_RGU_SYSRAM_SLP, 1);
return 0;
}
static int mt7986_wmac_sku_setup(struct mt7915_dev *dev, u32 *adie_type)
{
int ret;
u32 adie_main, adie_ext;
mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET,
MT_CONN_INFRA_ADIE1_RESET_MASK, 0x1);
mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET,
MT_CONN_INFRA_ADIE2_RESET_MASK, 0x1);
mt76_wmac_spi_lock(dev);
ret = mt76_wmac_spi_read(dev, 0, MT_ADIE_CHIP_ID, &adie_main);
if (ret)
goto out;
ret = mt76_wmac_spi_read(dev, 1, MT_ADIE_CHIP_ID, &adie_ext);
if (ret)
goto out;
*adie_type = FIELD_GET(MT_ADIE_CHIP_ID_MASK, adie_main) |
(MT_ADIE_CHIP_ID_MASK & adie_ext);
out:
mt76_wmac_spi_unlock(dev);
return 0;
}
static inline u16 mt7986_adie_idx(u8 adie, u32 adie_type)
{
if (adie == 0)
return u32_get_bits(adie_type, MT_ADIE_IDX0);
else
return u32_get_bits(adie_type, MT_ADIE_IDX1);
}
static inline bool is_7975(struct mt7915_dev *dev, u8 adie, u32 adie_type)
{
return mt7986_adie_idx(adie, adie_type) == 0x7975;
}
static inline bool is_7976(struct mt7915_dev *dev, u8 adie, u32 adie_type)
{
return mt7986_adie_idx(adie, adie_type) == 0x7976;
}
static int mt7986_wmac_adie_thermal_cal(struct mt7915_dev *dev, u8 adie)
{
int ret;
u32 data, val;
ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_THADC_ANALOG,
&data);
if (ret || FIELD_GET(MT_ADIE_ANA_EN_MASK, data)) {
val = FIELD_GET(MT_ADIE_VRPI_SEL_EFUSE_MASK, data);
ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_RG_TOP_THADC_BG,
MT_ADIE_VRPI_SEL_CR_MASK,
FIELD_PREP(MT_ADIE_VRPI_SEL_CR_MASK, val));
if (ret)
return ret;
val = FIELD_GET(MT_ADIE_PGA_GAIN_EFUSE_MASK, data);
ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_RG_TOP_THADC,
MT_ADIE_PGA_GAIN_MASK,
FIELD_PREP(MT_ADIE_PGA_GAIN_MASK, val));
if (ret)
return ret;
}
ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_THADC_SLOP,
&data);
if (ret || FIELD_GET(MT_ADIE_ANA_EN_MASK, data)) {
val = FIELD_GET(MT_ADIE_LDO_CTRL_EFUSE_MASK, data);
return mt76_wmac_spi_rmw(dev, adie, MT_ADIE_RG_TOP_THADC,
MT_ADIE_LDO_CTRL_MASK,
FIELD_PREP(MT_ADIE_LDO_CTRL_MASK, val));
}
return 0;
}
static int
mt7986_read_efuse_xo_trim_7976(struct mt7915_dev *dev, u8 adie,
bool is_40m, int *result)
{
int ret;
u32 data, addr;
addr = is_40m ? MT_ADIE_XTAL_AXM_40M_OSC : MT_ADIE_XTAL_AXM_80M_OSC;
ret = mt7986_wmac_adie_efuse_read(dev, adie, addr, &data);
if (ret)
return ret;
if (!FIELD_GET(MT_ADIE_XO_TRIM_EN_MASK, data)) {
*result = 64;
} else {
*result = FIELD_GET(MT_ADIE_TRIM_MASK, data);
addr = is_40m ? MT_ADIE_XTAL_TRIM1_40M_OSC :
MT_ADIE_XTAL_TRIM1_80M_OSC;
ret = mt7986_wmac_adie_efuse_read(dev, adie, addr, &data);
if (ret)
return ret;
if (FIELD_GET(MT_ADIE_XO_TRIM_EN_MASK, data) &&
FIELD_GET(MT_ADIE_XTAL_DECREASE_MASK, data))
*result -= FIELD_GET(MT_ADIE_EFUSE_TRIM_MASK, data);
else if (FIELD_GET(MT_ADIE_XO_TRIM_EN_MASK, data))
*result += FIELD_GET(MT_ADIE_EFUSE_TRIM_MASK, data);
*result = max(0, min(127, *result));
}
return 0;
}
static int mt7986_wmac_adie_xtal_trim_7976(struct mt7915_dev *dev, u8 adie)
{
int ret, trim_80m, trim_40m;
u32 data, val, mode;
ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_XO_TRIM_FLOW,
&data);
if (ret || !FIELD_GET(BIT(1), data))
return 0;
ret = mt7986_read_efuse_xo_trim_7976(dev, adie, false, &trim_80m);
if (ret)
return ret;
ret = mt7986_read_efuse_xo_trim_7976(dev, adie, true, &trim_40m);
if (ret)
return ret;
ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_RG_STRAP_PIN_IN, &val);
if (ret)
return ret;
mode = FIELD_PREP(GENMASK(6, 4), val);
if (!mode || mode == 0x2) {
ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C1,
GENMASK(31, 24),
FIELD_PREP(GENMASK(31, 24), trim_80m));
if (ret)
return ret;
ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C2,
GENMASK(31, 24),
FIELD_PREP(GENMASK(31, 24), trim_80m));
} else if (mode == 0x3 || mode == 0x4 || mode == 0x6) {
ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C1,
GENMASK(23, 16),
FIELD_PREP(GENMASK(23, 16), trim_40m));
if (ret)
return ret;
ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C2,
GENMASK(23, 16),
FIELD_PREP(GENMASK(23, 16), trim_40m));
}
return ret;
}
static int mt7986_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie)
{
int ret;
ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_TOP_THADC, 0x4a563b00);
if (ret)
return ret;
ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_01, 0x1d59080f);
if (ret)
return ret;
return mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_03, 0x34c00fe0);
}
static int
mt7986_read_efuse_xo_trim_7975(struct mt7915_dev *dev, u8 adie,
u32 addr, u32 *result)
{
int ret;
u32 data;
ret = mt7986_wmac_adie_efuse_read(dev, adie, addr, &data);
if (ret)
return ret;
if ((data & MT_ADIE_XO_TRIM_EN_MASK)) {
if ((data & MT_ADIE_XTAL_DECREASE_MASK))
*result -= (data & MT_ADIE_EFUSE_TRIM_MASK);
else
*result += (data & MT_ADIE_EFUSE_TRIM_MASK);
*result = (*result & MT_ADIE_TRIM_MASK);
}
return 0;
}
static int mt7986_wmac_adie_xtal_trim_7975(struct mt7915_dev *dev, u8 adie)
{
int ret;
u32 data, result = 0, value;
ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_7975_XTAL_EN,
&data);
if (ret || !(data & BIT(1)))
return 0;
ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_7975_XTAL_CAL,
&data);
if (ret)
return ret;
if (data & MT_ADIE_XO_TRIM_EN_MASK)
result = (data & MT_ADIE_TRIM_MASK);
ret = mt7986_read_efuse_xo_trim_7975(dev, adie, MT_ADIE_7975_XO_TRIM2,
&result);
if (ret)
return ret;
ret = mt7986_read_efuse_xo_trim_7975(dev, adie, MT_ADIE_7975_XO_TRIM3,
&result);
if (ret)
return ret;
ret = mt7986_read_efuse_xo_trim_7975(dev, adie, MT_ADIE_7975_XO_TRIM4,
&result);
if (ret)
return ret;
/* Update trim value to C1 and C2*/
value = FIELD_GET(MT_ADIE_7975_XO_CTRL2_C1_MASK, result) |
FIELD_GET(MT_ADIE_7975_XO_CTRL2_C2_MASK, result);
ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_XO_CTRL2,
MT_ADIE_7975_XO_CTRL2_MASK, value);
if (ret)
return ret;
ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_7975_XTAL, &value);
if (ret)
return ret;
if (value & MT_ADIE_7975_XTAL_EN_MASK) {
ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_XO_2,
MT_ADIE_7975_XO_2_FIX_EN, 0x0);
if (ret)
return ret;
}
return mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_XO_CTRL6,
MT_ADIE_7975_XO_CTRL6_MASK, 0x1);
}
static int mt7986_wmac_adie_patch_7975(struct mt7915_dev *dev, u8 adie)
{
int ret;
/* disable CAL LDO and fine tune RFDIG LDO */
ret = mt76_wmac_spi_write(dev, adie, 0x348, 0x00000002);
if (ret)
return ret;
ret = mt76_wmac_spi_write(dev, adie, 0x378, 0x00000002);
if (ret)
return ret;
ret = mt76_wmac_spi_write(dev, adie, 0x3a8, 0x00000002);
if (ret)
return ret;
ret = mt76_wmac_spi_write(dev, adie, 0x3d8, 0x00000002);
if (ret)
return ret;
/* set CKA driving and filter */
ret = mt76_wmac_spi_write(dev, adie, 0xa1c, 0x30000aaa);
if (ret)
return ret;
/* set CKB LDO to 1.4V */
ret = mt76_wmac_spi_write(dev, adie, 0xa84, 0x8470008a);
if (ret)
return ret;
/* turn on SX0 LTBUF */
ret = mt76_wmac_spi_write(dev, adie, 0x074, 0x00000002);
if (ret)
return ret;
/* CK_BUF_SW_EN = 1 (all buf in manual mode.) */
ret = mt76_wmac_spi_write(dev, adie, 0xaa4, 0x01001fc0);
if (ret)
return ret;
/* BT mode/WF normal mode 00000005 */
ret = mt76_wmac_spi_write(dev, adie, 0x070, 0x00000005);
if (ret)
return ret;
/* BG thermal sensor offset update */
ret = mt76_wmac_spi_write(dev, adie, 0x344, 0x00000088);
if (ret)
return ret;
ret = mt76_wmac_spi_write(dev, adie, 0x374, 0x00000088);
if (ret)
return ret;
ret = mt76_wmac_spi_write(dev, adie, 0x3a4, 0x00000088);
if (ret)
return ret;
ret = mt76_wmac_spi_write(dev, adie, 0x3d4, 0x00000088);
if (ret)
return ret;
/* set WCON VDD IPTAT to "0000" */
ret = mt76_wmac_spi_write(dev, adie, 0xa80, 0x44d07000);
if (ret)
return ret;
/* change back LTBUF SX3 drving to default value */
ret = mt76_wmac_spi_write(dev, adie, 0xa88, 0x3900aaaa);
if (ret)
return ret;
/* SM input cap off */
ret = mt76_wmac_spi_write(dev, adie, 0x2c4, 0x00000000);
if (ret)
return ret;
/* set CKB driving and filter */
return mt76_wmac_spi_write(dev, adie, 0x2c8, 0x00000072);
}
static int mt7986_wmac_adie_cfg(struct mt7915_dev *dev, u8 adie, u32 adie_type)
{
int ret;
mt76_wmac_spi_lock(dev);
ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_CLK_EN, ~0);
if (ret)
goto out;
if (is_7975(dev, adie, adie_type)) {
ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_COCLK,
BIT(1), 0x1);
if (ret)
goto out;
ret = mt7986_wmac_adie_thermal_cal(dev, adie);
if (ret)
goto out;
ret = mt7986_wmac_adie_xtal_trim_7975(dev, adie);
if (ret)
goto out;
ret = mt7986_wmac_adie_patch_7975(dev, adie);
} else if (is_7976(dev, adie, adie_type)) {
if (mt7986_wmac_check_adie_type(dev) == ADIE_DBDC) {
ret = mt76_wmac_spi_write(dev, adie,
MT_ADIE_WRI_CK_SEL, 0x1c);
if (ret)
goto out;
}
ret = mt7986_wmac_adie_thermal_cal(dev, adie);
if (ret)
goto out;
ret = mt7986_wmac_adie_xtal_trim_7976(dev, adie);
if (ret)
goto out;
ret = mt7986_wmac_adie_patch_7976(dev, adie);
}
out:
mt76_wmac_spi_unlock(dev);
return ret;
}
static int
mt7986_wmac_afe_cal(struct mt7915_dev *dev, u8 adie, bool dbdc, u32 adie_type)
{
int ret;
u8 idx;
mt76_wmac_spi_lock(dev);
if (is_7975(dev, adie, adie_type))
ret = mt76_wmac_spi_write(dev, adie,
MT_AFE_RG_ENCAL_WBTAC_IF_SW,
0x80000000);
else
ret = mt76_wmac_spi_write(dev, adie,
MT_AFE_RG_ENCAL_WBTAC_IF_SW,
0x88888005);
if (ret)
goto out;
idx = dbdc ? ADIE_DBDC : adie;
mt76_rmw_field(dev, MT_AFE_DIG_EN_01(idx),
MT_AFE_RG_WBG_EN_RCK_MASK, 0x1);
usleep_range(60, 100);
mt76_rmw(dev, MT_AFE_DIG_EN_01(idx),
MT_AFE_RG_WBG_EN_RCK_MASK, 0x0);
mt76_rmw_field(dev, MT_AFE_DIG_EN_03(idx),
MT_AFE_RG_WBG_EN_BPLL_UP_MASK, 0x1);
usleep_range(30, 100);
mt76_rmw_field(dev, MT_AFE_DIG_EN_03(idx),
MT_AFE_RG_WBG_EN_WPLL_UP_MASK, 0x1);
usleep_range(60, 100);
mt76_rmw_field(dev, MT_AFE_DIG_EN_01(idx),
MT_AFE_RG_WBG_EN_TXCAL_MASK, 0x1f);
usleep_range(800, 1000);
mt76_rmw(dev, MT_AFE_DIG_EN_01(idx),
MT_AFE_RG_WBG_EN_TXCAL_MASK, 0x0);
mt76_rmw(dev, MT_AFE_DIG_EN_03(idx),
MT_AFE_RG_WBG_EN_PLL_UP_MASK, 0x0);
ret = mt76_wmac_spi_write(dev, adie, MT_AFE_RG_ENCAL_WBTAC_IF_SW,
0x5);
out:
mt76_wmac_spi_unlock(dev);
return ret;
}
static void mt7986_wmac_subsys_pll_initial(struct mt7915_dev *dev, u8 band)
{
mt76_rmw(dev, MT_AFE_PLL_STB_TIME(band),
MT_AFE_PLL_STB_TIME_MASK, MT_AFE_PLL_STB_TIME_VAL);
mt76_rmw(dev, MT_AFE_DIG_EN_02(band),
MT_AFE_PLL_CFG_MASK, MT_AFE_PLL_CFG_VAL);
mt76_rmw(dev, MT_AFE_DIG_TOP_01(band),
MT_AFE_DIG_TOP_01_MASK, MT_AFE_DIG_TOP_01_VAL);
}
static void mt7986_wmac_subsys_setting(struct mt7915_dev *dev)
{
/* Subsys pll init */
mt7986_wmac_subsys_pll_initial(dev, 0);
mt7986_wmac_subsys_pll_initial(dev, 1);
/* Set legacy OSC control stable time*/
mt76_rmw(dev, MT_CONN_INFRA_OSC_RC_EN,
MT_CONN_INFRA_OSC_RC_EN_MASK, 0x0);
mt76_rmw(dev, MT_CONN_INFRA_OSC_CTRL,
MT_CONN_INFRA_OSC_STB_TIME_MASK, 0x80706);
/* prevent subsys from power on/of in a short time interval */
mt76_rmw(dev, MT_TOP_WFSYS_PWR,
MT_TOP_PWR_ACK_MASK | MT_TOP_PWR_KEY_MASK,
MT_TOP_PWR_KEY);
}
static int mt7986_wmac_bus_timeout(struct mt7915_dev *dev)
{
mt76_rmw_field(dev, MT_INFRA_BUS_OFF_TIMEOUT,
MT_INFRA_BUS_TIMEOUT_LIMIT_MASK, 0x2);
mt76_rmw_field(dev, MT_INFRA_BUS_OFF_TIMEOUT,
MT_INFRA_BUS_TIMEOUT_EN_MASK, 0xf);
mt76_rmw_field(dev, MT_INFRA_BUS_ON_TIMEOUT,
MT_INFRA_BUS_TIMEOUT_LIMIT_MASK, 0xc);
mt76_rmw_field(dev, MT_INFRA_BUS_ON_TIMEOUT,
MT_INFRA_BUS_TIMEOUT_EN_MASK, 0xf);
return mt7986_wmac_coninfra_check(dev);
}
static void mt7986_wmac_clock_enable(struct mt7915_dev *dev, u32 adie_type)
{
u32 cur;
mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_1,
MT_INFRA_CKGEN_DIV_SEL_MASK, 0x1);
mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_2,
MT_INFRA_CKGEN_DIV_SEL_MASK, 0x1);
mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_1,
MT_INFRA_CKGEN_DIV_EN_MASK, 0x1);
mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_2,
MT_INFRA_CKGEN_DIV_EN_MASK, 0x1);
mt76_rmw_field(dev, MT_INFRA_CKGEN_RFSPI_WPLL_DIV,
MT_INFRA_CKGEN_DIV_SEL_MASK, 0x8);
mt76_rmw_field(dev, MT_INFRA_CKGEN_RFSPI_WPLL_DIV,
MT_INFRA_CKGEN_DIV_EN_MASK, 0x1);
mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS,
MT_INFRA_CKGEN_BUS_CLK_SEL_MASK, 0x0);
mt76_rmw_field(dev, MT_CONN_INFRA_HW_CTRL,
MT_CONN_INFRA_HW_CTRL_MASK, 0x1);
mt76_rmw(dev, MT_TOP_CONN_INFRA_WAKEUP,
MT_TOP_CONN_INFRA_WAKEUP_MASK, 0x1);
usleep_range(900, 1000);
mt76_wmac_spi_lock(dev);
if (is_7975(dev, 0, adie_type) || is_7976(dev, 0, adie_type)) {
mt76_rmw_field(dev, MT_ADIE_SLP_CTRL_CK0(0),
MT_SLP_CTRL_EN_MASK, 0x1);
read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_CTRL_BSY_MASK),
USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
dev, MT_ADIE_SLP_CTRL_CK0(0));
}
if (is_7975(dev, 1, adie_type) || is_7976(dev, 1, adie_type)) {
mt76_rmw_field(dev, MT_ADIE_SLP_CTRL_CK0(1),
MT_SLP_CTRL_EN_MASK, 0x1);
read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_CTRL_BSY_MASK),
USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
dev, MT_ADIE_SLP_CTRL_CK0(0));
}
mt76_wmac_spi_unlock(dev);
mt76_rmw(dev, MT_TOP_CONN_INFRA_WAKEUP,
MT_TOP_CONN_INFRA_WAKEUP_MASK, 0x0);
usleep_range(900, 1000);
}
static int mt7986_wmac_top_wfsys_wakeup(struct mt7915_dev *dev, bool enable)
{
mt76_rmw_field(dev, MT_TOP_WFSYS_WAKEUP,
MT_TOP_WFSYS_WAKEUP_MASK, enable);
usleep_range(900, 1000);
if (!enable)
return 0;
return mt7986_wmac_coninfra_check(dev);
}
static int mt7986_wmac_wm_enable(struct mt7915_dev *dev, bool enable)
{
u32 cur;
mt76_rmw_field(dev, MT7986_TOP_WM_RESET,
MT7986_TOP_WM_RESET_MASK, enable);
if (!enable)
return 0;
return read_poll_timeout(mt76_rr, cur, (cur == 0x1d1e),
USEC_PER_MSEC, 5000 * USEC_PER_MSEC, false,
dev, MT_TOP_CFG_ON_ROM_IDX);
}
static int mt7986_wmac_wfsys_poweron(struct mt7915_dev *dev, bool enable)
{
u32 mask = MT_TOP_PWR_EN_MASK | MT_TOP_PWR_KEY_MASK;
u32 cur;
mt76_rmw(dev, MT_TOP_WFSYS_PWR, mask,
MT_TOP_PWR_KEY | FIELD_PREP(MT_TOP_PWR_EN_MASK, enable));
return read_poll_timeout(mt76_rr, cur,
(FIELD_GET(MT_TOP_WFSYS_RESET_STATUS_MASK, cur) == enable),
USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
dev, MT_TOP_WFSYS_RESET_STATUS);
}
static int mt7986_wmac_wfsys_setting(struct mt7915_dev *dev)
{
int ret;
u32 cur;
/* Turn off wfsys2conn bus sleep protect */
mt76_rmw(dev, MT_CONN_INFRA_WF_SLP_PROT,
MT_CONN_INFRA_WF_SLP_PROT_MASK, 0x0);
ret = mt7986_wmac_wfsys_poweron(dev, true);
if (ret)
return ret;
/* Check bus sleep protect */
ret = read_poll_timeout(mt76_rr, cur,
!(cur & MT_CONN_INFRA_CONN_WF_MASK),
USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
dev, MT_CONN_INFRA_WF_SLP_PROT_RDY);
if (ret)
return ret;
ret = read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_WFDMA2CONN_MASK),
USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
dev, MT_SLP_STATUS);
if (ret)
return ret;
return read_poll_timeout(mt76_rr, cur, (cur == 0x02060000),
USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
dev, MT_TOP_CFG_IP_VERSION_ADDR);
}
static void mt7986_wmac_wfsys_set_timeout(struct mt7915_dev *dev)
{
u32 mask = MT_MCU_BUS_TIMEOUT_SET_MASK |
MT_MCU_BUS_TIMEOUT_CG_EN_MASK |
MT_MCU_BUS_TIMEOUT_EN_MASK;
u32 val = FIELD_PREP(MT_MCU_BUS_TIMEOUT_SET_MASK, 1) |
FIELD_PREP(MT_MCU_BUS_TIMEOUT_CG_EN_MASK, 1) |
FIELD_PREP(MT_MCU_BUS_TIMEOUT_EN_MASK, 1);
mt76_rmw(dev, MT_MCU_BUS_TIMEOUT, mask, val);
mt76_wr(dev, MT_MCU_BUS_REMAP, 0x810f0000);
mask = MT_MCU_BUS_DBG_TIMEOUT_SET_MASK |
MT_MCU_BUS_DBG_TIMEOUT_CK_EN_MASK |
MT_MCU_BUS_DBG_TIMEOUT_EN_MASK;
val = FIELD_PREP(MT_MCU_BUS_DBG_TIMEOUT_SET_MASK, 0x3aa) |
FIELD_PREP(MT_MCU_BUS_DBG_TIMEOUT_CK_EN_MASK, 1) |
FIELD_PREP(MT_MCU_BUS_DBG_TIMEOUT_EN_MASK, 1);
mt76_rmw(dev, MT_MCU_BUS_DBG_TIMEOUT, mask, val);
}
static int mt7986_wmac_sku_update(struct mt7915_dev *dev, u32 adie_type)
{
u32 val;
if (is_7976(dev, 0, adie_type) && is_7976(dev, 1, adie_type))
val = 0xf;
else if (is_7975(dev, 0, adie_type) && is_7975(dev, 1, adie_type))
val = 0xd;
else if (is_7976(dev, 0, adie_type))
val = 0x7;
else if (is_7975(dev, 1, adie_type))
val = 0x8;
else if (is_7976(dev, 1, adie_type))
val = 0xa;
else
return -EINVAL;
mt76_wmac_rmw(dev->sku, MT_TOP_POS_SKU, MT_TOP_POS_SKU_MASK,
FIELD_PREP(MT_TOP_POS_SKU_MASK, val));
mt76_wr(dev, MT_CONNINFRA_SKU_DEC_ADDR, val);
return 0;
}
static int
mt7986_wmac_adie_setup(struct mt7915_dev *dev, u8 adie, u32 adie_type)
{
int ret;
if (!(is_7975(dev, adie, adie_type) || is_7976(dev, adie, adie_type)))
return 0;
ret = mt7986_wmac_adie_cfg(dev, adie, adie_type);
if (ret)
return ret;
ret = mt7986_wmac_afe_cal(dev, adie, false, adie_type);
if (ret)
return ret;
if (!adie && (mt7986_wmac_check_adie_type(dev) == ADIE_DBDC))
ret = mt7986_wmac_afe_cal(dev, adie, true, adie_type);
return ret;
}
static int mt7986_wmac_subsys_powerup(struct mt7915_dev *dev, u32 adie_type)
{
int ret;
mt7986_wmac_subsys_setting(dev);
ret = mt7986_wmac_bus_timeout(dev);
if (ret)
return ret;
mt7986_wmac_clock_enable(dev, adie_type);
return 0;
}
static int mt7986_wmac_wfsys_powerup(struct mt7915_dev *dev)
{
int ret;
ret = mt7986_wmac_wm_enable(dev, false);
if (ret)
return ret;
ret = mt7986_wmac_wfsys_setting(dev);
if (ret)
return ret;
mt7986_wmac_wfsys_set_timeout(dev);
return mt7986_wmac_wm_enable(dev, true);
}
int mt7986_wmac_enable(struct mt7915_dev *dev)
{
int ret;
u32 adie_type;
ret = mt7986_wmac_consys_reset(dev, true);
if (ret)
return ret;
ret = mt7986_wmac_gpio_setup(dev);
if (ret)
return ret;
ret = mt7986_wmac_consys_lockup(dev, false);
if (ret)
return ret;
ret = mt7986_wmac_coninfra_check(dev);
if (ret)
return ret;
ret = mt7986_wmac_coninfra_setup(dev);
if (ret)
return ret;
ret = mt7986_wmac_sku_setup(dev, &adie_type);
if (ret)
return ret;
ret = mt7986_wmac_adie_setup(dev, 0, adie_type);
if (ret)
return ret;
ret = mt7986_wmac_adie_setup(dev, 1, adie_type);
if (ret)
return ret;
ret = mt7986_wmac_subsys_powerup(dev, adie_type);
if (ret)
return ret;
ret = mt7986_wmac_top_wfsys_wakeup(dev, true);
if (ret)
return ret;
ret = mt7986_wmac_wfsys_powerup(dev);
if (ret)
return ret;
return mt7986_wmac_sku_update(dev, adie_type);
}
void mt7986_wmac_disable(struct mt7915_dev *dev)
{
u32 cur;
mt7986_wmac_top_wfsys_wakeup(dev, true);
/* Turn on wfsys2conn bus sleep protect */
mt76_rmw_field(dev, MT_CONN_INFRA_WF_SLP_PROT,
MT_CONN_INFRA_WF_SLP_PROT_MASK, 0x1);
/* Check wfsys2conn bus sleep protect */
read_poll_timeout(mt76_rr, cur, !(cur ^ MT_CONN_INFRA_CONN),
USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
dev, MT_CONN_INFRA_WF_SLP_PROT_RDY);
mt7986_wmac_wfsys_poweron(dev, false);
/* Turn back wpll setting */
mt76_rmw_field(dev, MT_AFE_DIG_EN_02(0), MT_AFE_MCU_BPLL_CFG_MASK, 0x2);
mt76_rmw_field(dev, MT_AFE_DIG_EN_02(0), MT_AFE_WPLL_CFG_MASK, 0x2);
/* Reset EMI */
mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ,
MT_CONN_INFRA_EMI_REQ_MASK, 0x1);
mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ,
MT_CONN_INFRA_EMI_REQ_MASK, 0x0);
mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ,
MT_CONN_INFRA_INFRA_REQ_MASK, 0x1);
mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ,
MT_CONN_INFRA_INFRA_REQ_MASK, 0x0);
mt7986_wmac_top_wfsys_wakeup(dev, false);
mt7986_wmac_consys_lockup(dev, true);
mt7986_wmac_consys_reset(dev, false);
}
static int mt7986_wmac_init(struct mt7915_dev *dev)
{
struct device *pdev = dev->mt76.dev;
struct platform_device *pfdev = to_platform_device(pdev);
dev->dcm = devm_platform_ioremap_resource(pfdev, 1);
if (IS_ERR(dev->dcm))
return PTR_ERR(dev->dcm);
dev->sku = devm_platform_ioremap_resource(pfdev, 2);
if (IS_ERR(dev->sku))
return PTR_ERR(dev->sku);
dev->rstc = devm_reset_control_get(pdev, "consys");
if (IS_ERR(dev->rstc))
return PTR_ERR(dev->rstc);
return mt7986_wmac_enable(dev);
}
static int mt7986_wmac_probe(struct platform_device *pdev)
{
void __iomem *mem_base;
struct mt7915_dev *dev;
struct mt76_dev *mdev;
int irq, ret;
u32 chip_id;
chip_id = (uintptr_t)of_device_get_match_data(&pdev->dev);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
mem_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mem_base)) {
dev_err(&pdev->dev, "Failed to get memory resource\n");
return PTR_ERR(mem_base);
}
dev = mt7915_mmio_probe(&pdev->dev, mem_base, chip_id);
if (IS_ERR(dev))
return PTR_ERR(dev);
mdev = &dev->mt76;
ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)
goto free_device;
mt76_wr(dev, MT_INT_MASK_CSR, 0);
ret = mt7986_wmac_init(dev);
if (ret)
goto free_irq;
ret = mt7915_register_device(dev);
if (ret)
goto free_irq;
return 0;
free_irq:
devm_free_irq(mdev->dev, irq, dev);
free_device:
mt76_free_device(&dev->mt76);
return ret;
}
static int mt7986_wmac_remove(struct platform_device *pdev)
{
struct mt7915_dev *dev = platform_get_drvdata(pdev);
mt7915_unregister_device(dev);
return 0;
}
static const struct of_device_id mt7986_wmac_of_match[] = {
{ .compatible = "mediatek,mt7986-wmac", .data = (u32 *)0x7986 },
{},
};
struct platform_driver mt7986_wmac_driver = {
.driver = {
.name = "mt7986-wmac",
.of_match_table = mt7986_wmac_of_match,
},
.probe = mt7986_wmac_probe,
.remove = mt7986_wmac_remove,
};
MODULE_FIRMWARE(MT7986_FIRMWARE_WA);
MODULE_FIRMWARE(MT7986_FIRMWARE_WM);
MODULE_FIRMWARE(MT7986_FIRMWARE_WM_MT7975);
MODULE_FIRMWARE(MT7986_ROM_PATCH);
MODULE_FIRMWARE(MT7986_ROM_PATCH_MT7975);
......@@ -198,7 +198,6 @@ mt7915_tm_set_ipg_params(struct mt7915_phy *phy, u32 ipg, u8 mode)
u8 slot_time = 9, sifs = TM_DEFAULT_SIFS;
u8 aifsn = TM_MIN_AIFSN;
u32 i2t_time, tr2t_time, txv_time;
bool ext_phy = phy != &dev->phy;
u16 cw = 0;
if (ipg < sig_ext + slot_time + sifs)
......@@ -228,22 +227,18 @@ mt7915_tm_set_ipg_params(struct mt7915_phy *phy, u32 ipg, u8 mode)
ipg -= aifsn * slot_time;
if (ipg > TM_DEFAULT_SIFS) {
if (ipg < TM_MAX_SIFS)
sifs = ipg;
else
sifs = TM_MAX_SIFS;
}
if (ipg > TM_DEFAULT_SIFS)
sifs = min_t(u32, ipg, TM_MAX_SIFS);
}
done:
txv_time = mt76_get_field(dev, MT_TMAC_ATCR(ext_phy),
txv_time = mt76_get_field(dev, MT_TMAC_ATCR(phy->band_idx),
MT_TMAC_ATCR_TXV_TOUT);
txv_time *= 50; /* normal clock time */
i2t_time = (slot_time * 1000 - txv_time - BBP_PROC_TIME) / 50;
tr2t_time = (sifs * 1000 - txv_time - BBP_PROC_TIME) / 50;
mt76_set(dev, MT_TMAC_TRCR0(ext_phy),
mt76_set(dev, MT_TMAC_TRCR0(phy->band_idx),
FIELD_PREP(MT_TMAC_TRCR0_TR2T_CHK, tr2t_time) |
FIELD_PREP(MT_TMAC_TRCR0_I2T_CHK, i2t_time));
......@@ -337,7 +332,6 @@ mt7915_tm_reg_backup_restore(struct mt7915_phy *phy)
{
int n_regs = ARRAY_SIZE(reg_backup_list);
struct mt7915_dev *dev = phy->dev;
bool ext_phy = phy != &dev->phy;
u32 *b = phy->test.reg_backup;
int i;
......@@ -361,7 +355,7 @@ mt7915_tm_reg_backup_restore(struct mt7915_phy *phy)
if (phy->mt76->test.state == MT76_TM_STATE_OFF) {
for (i = 0; i < n_regs; i++)
mt76_wr(dev, reg_backup_list[i].band[ext_phy], b[i]);
mt76_wr(dev, reg_backup_list[i].band[phy->band_idx], b[i]);
return;
}
......@@ -372,33 +366,33 @@ mt7915_tm_reg_backup_restore(struct mt7915_phy *phy)
phy->test.reg_backup = b;
for (i = 0; i < n_regs; i++)
b[i] = mt76_rr(dev, reg_backup_list[i].band[ext_phy]);
b[i] = mt76_rr(dev, reg_backup_list[i].band[phy->band_idx]);
}
mt76_clear(dev, MT_AGG_PCR0(ext_phy, 0), MT_AGG_PCR0_MM_PROT |
mt76_clear(dev, MT_AGG_PCR0(phy->band_idx, 0), MT_AGG_PCR0_MM_PROT |
MT_AGG_PCR0_GF_PROT | MT_AGG_PCR0_ERP_PROT |
MT_AGG_PCR0_VHT_PROT | MT_AGG_PCR0_BW20_PROT |
MT_AGG_PCR0_BW40_PROT | MT_AGG_PCR0_BW80_PROT);
mt76_set(dev, MT_AGG_PCR0(ext_phy, 0), MT_AGG_PCR0_PTA_WIN_DIS);
mt76_set(dev, MT_AGG_PCR0(phy->band_idx, 0), MT_AGG_PCR0_PTA_WIN_DIS);
mt76_wr(dev, MT_AGG_PCR0(ext_phy, 1), MT_AGG_PCR1_RTS0_NUM_THRES |
mt76_wr(dev, MT_AGG_PCR0(phy->band_idx, 1), MT_AGG_PCR1_RTS0_NUM_THRES |
MT_AGG_PCR1_RTS0_LEN_THRES);
mt76_clear(dev, MT_AGG_MRCR(ext_phy), MT_AGG_MRCR_BAR_CNT_LIMIT |
mt76_clear(dev, MT_AGG_MRCR(phy->band_idx), MT_AGG_MRCR_BAR_CNT_LIMIT |
MT_AGG_MRCR_LAST_RTS_CTS_RN | MT_AGG_MRCR_RTS_FAIL_LIMIT |
MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT);
mt76_rmw(dev, MT_AGG_MRCR(ext_phy), MT_AGG_MRCR_RTS_FAIL_LIMIT |
mt76_rmw(dev, MT_AGG_MRCR(phy->band_idx), MT_AGG_MRCR_RTS_FAIL_LIMIT |
MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT,
FIELD_PREP(MT_AGG_MRCR_RTS_FAIL_LIMIT, 1) |
FIELD_PREP(MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT, 1));
mt76_wr(dev, MT_TMAC_TFCR0(ext_phy), 0);
mt76_clear(dev, MT_TMAC_TCR0(ext_phy), MT_TMAC_TCR0_TBTT_STOP_CTRL);
mt76_wr(dev, MT_TMAC_TFCR0(phy->band_idx), 0);
mt76_clear(dev, MT_TMAC_TCR0(phy->band_idx), MT_TMAC_TCR0_TBTT_STOP_CTRL);
/* config rx filter for testmode rx */
mt76_wr(dev, MT_WF_RFCR(ext_phy), 0xcf70a);
mt76_wr(dev, MT_WF_RFCR1(ext_phy), 0);
mt76_wr(dev, MT_WF_RFCR(phy->band_idx), 0xcf70a);
mt76_wr(dev, MT_WF_RFCR1(phy->band_idx), 0);
}
static void
......@@ -456,7 +450,7 @@ mt7915_tm_set_tx_frames(struct mt7915_phy *phy, bool en)
u8 tx_ant = td->tx_antenna_mask;
if (phy != &dev->phy)
tx_ant >>= 2;
tx_ant >>= dev->chainshift;
phy->test.spe_idx = spe_idx_map[tx_ant];
}
}
......@@ -724,7 +718,6 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
{
struct mt7915_phy *phy = mphy->priv;
struct mt7915_dev *dev = phy->dev;
bool ext_phy = phy != &dev->phy;
enum mt76_rxq_id q;
void *rx, *rssi;
u16 fcs_err;
......@@ -773,11 +766,11 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
nla_nest_end(msg, rx);
cnt = mt76_rr(dev, MT_MIB_SDR3(ext_phy));
cnt = mt76_rr(dev, MT_MIB_SDR3(phy->band_idx));
fcs_err = is_mt7915(&dev->mt76) ? FIELD_GET(MT_MIB_SDR3_FCS_ERR_MASK, cnt) :
FIELD_GET(MT_MIB_SDR3_FCS_ERR_MASK_MT7916, cnt);
q = ext_phy ? MT_RXQ_EXT : MT_RXQ_MAIN;
q = phy->band_idx ? MT_RXQ_EXT : MT_RXQ_MAIN;
mphy->test.rx_stats.packets[q] += fcs_err;
mphy->test.rx_stats.fcs_error[q] += fcs_err;
......
......@@ -407,7 +407,7 @@ static int mt7921_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
struct ieee80211_sta *sta;
struct ieee80211_vif *vif;
struct ieee80211_hdr hdr;
__le32 qos_ctrl, ht_ctrl;
u16 frame_control;
if (FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, le32_to_cpu(rxd[3])) !=
MT_RXD3_NORMAL_U2M)
......@@ -423,16 +423,15 @@ static int mt7921_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
/* store the info from RXD and ethhdr to avoid being overridden */
hdr.frame_control = FIELD_GET(MT_RXD6_FRAME_CONTROL, rxd[6]);
hdr.seq_ctrl = FIELD_GET(MT_RXD8_SEQ_CTRL, rxd[8]);
qos_ctrl = FIELD_GET(MT_RXD8_QOS_CTL, rxd[8]);
ht_ctrl = FIELD_GET(MT_RXD9_HT_CONTROL, rxd[9]);
frame_control = le32_get_bits(rxd[6], MT_RXD6_FRAME_CONTROL);
hdr.frame_control = cpu_to_le16(frame_control);
hdr.seq_ctrl = cpu_to_le16(le32_get_bits(rxd[8], MT_RXD8_SEQ_CTRL));
hdr.duration_id = 0;
ether_addr_copy(hdr.addr1, vif->addr);
ether_addr_copy(hdr.addr2, sta->addr);
switch (le16_to_cpu(hdr.frame_control) &
(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
switch (frame_control & (IEEE80211_FCTL_TODS |
IEEE80211_FCTL_FROMDS)) {
case 0:
ether_addr_copy(hdr.addr3, vif->bss_conf.bssid);
break;
......@@ -454,15 +453,22 @@ static int mt7921_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
if (eth_hdr->h_proto == cpu_to_be16(ETH_P_AARP) ||
eth_hdr->h_proto == cpu_to_be16(ETH_P_IPX))
ether_addr_copy(skb_push(skb, ETH_ALEN), bridge_tunnel_header);
else if (eth_hdr->h_proto >= cpu_to_be16(ETH_P_802_3_MIN))
else if (be16_to_cpu(eth_hdr->h_proto) >= ETH_P_802_3_MIN)
ether_addr_copy(skb_push(skb, ETH_ALEN), rfc1042_header);
else
skb_pull(skb, 2);
if (ieee80211_has_order(hdr.frame_control))
memcpy(skb_push(skb, 2), &ht_ctrl, 2);
if (ieee80211_is_data_qos(hdr.frame_control))
memcpy(skb_push(skb, 2), &qos_ctrl, 2);
memcpy(skb_push(skb, IEEE80211_HT_CTL_LEN), &rxd[9],
IEEE80211_HT_CTL_LEN);
if (ieee80211_is_data_qos(hdr.frame_control)) {
__le16 qos_ctrl;
qos_ctrl = cpu_to_le16(le32_get_bits(rxd[8], MT_RXD8_QOS_CTL));
memcpy(skb_push(skb, IEEE80211_QOS_CTL_LEN), &qos_ctrl,
IEEE80211_QOS_CTL_LEN);
}
if (ieee80211_has_a4(hdr.frame_control))
memcpy(skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr));
else
......@@ -664,9 +670,6 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
status->chain_signal[i]);
}
if (status->signal == -128)
status->flag |= RX_FLAG_NO_SIGNAL_VAL;
stbc = FIELD_GET(MT_PRXV_STBC, v0);
gi = FIELD_GET(MT_PRXV_SGI, v0);
cck = false;
......@@ -910,11 +913,18 @@ mt7921_mac_write_txwi_80211(struct mt7921_dev *dev, __le32 *txwi,
val = MT_TXD3_SN_VALID |
FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
txwi[3] |= cpu_to_le32(val);
txwi[7] &= ~cpu_to_le32(MT_TXD7_HW_AMSDU);
}
if (mt76_is_mmio(&dev->mt76)) {
val = FIELD_PREP(MT_TXD7_TYPE, fc_type) |
FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype);
txwi[7] |= cpu_to_le32(val);
} else {
val = FIELD_PREP(MT_TXD8_L_TYPE, fc_type) |
FIELD_PREP(MT_TXD8_L_SUB_TYPE, fc_stype);
txwi[8] |= cpu_to_le32(val);
}
}
void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
......
......@@ -284,6 +284,9 @@ enum tx_mcu_port_q_idx {
#define MT_TXD7_HW_AMSDU BIT(10)
#define MT_TXD7_TX_TIME GENMASK(9, 0)
#define MT_TXD8_L_TYPE GENMASK(5, 4)
#define MT_TXD8_L_SUB_TYPE GENMASK(3, 0)
#define MT_TX_RATE_STBC BIT(13)
#define MT_TX_RATE_NSS GENMASK(12, 10)
#define MT_TX_RATE_MODE GENMASK(9, 6)
......
......@@ -863,10 +863,12 @@ int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd)
else
req.channel_band = chandef->chan->band;
if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
if (cmd == MCU_EXT_CMD(SET_RX_PATH))
req.switch_reason = CH_SWITCH_NORMAL;
else if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
else if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) &&
chandef->chan->dfs_state != NL80211_DFS_AVAILABLE)
else if (!cfg80211_reg_can_beacon(dev->mt76.hw->wiphy, chandef,
NL80211_IFTYPE_AP))
req.switch_reason = CH_SWITCH_DFS;
else
req.switch_reason = CH_SWITCH_NORMAL;
......
......@@ -409,7 +409,6 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct mt76_dev *dev = phy->dev;
struct mt76_testmode_data *td = &phy->test;
struct nlattr *tb[NUM_MT76_TM_ATTRS];
bool ext_phy = phy != &dev->phy;
u32 state;
int err;
int i;
......@@ -447,8 +446,8 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_LDPC], &td->tx_rate_ldpc, 0, 1) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_STBC], &td->tx_rate_stbc, 0, 1) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_LTF], &td->tx_ltf, 0, 2) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_ANTENNA], &td->tx_antenna_mask,
1 << (ext_phy * 2), phy->antenna_mask << (ext_phy * 2)) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_ANTENNA],
&td->tx_antenna_mask, 0, 0xff) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_SPE_IDX], &td->tx_spe_idx, 0, 27) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_DUTY_CYCLE],
&td->tx_duty_cycle, 0, 99) ||
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment