Commit 71a1238b authored by Kalle Valo's avatar Kalle Valo

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

mt76 patches for 5.1

* add driver for MT7603E/MT7628
* fix ED/CCA issues
* fix USB issues
* more code unification
* fix beacon timer issues
* fix recovery from MCU timeout issues
parents bd16693f c8846e10
...@@ -4,6 +4,13 @@ This node provides properties for configuring the MediaTek mt76xx wireless ...@@ -4,6 +4,13 @@ This node provides properties for configuring the MediaTek mt76xx wireless
device. The node is expected to be specified as a child node of the PCI device. The node is expected to be specified as a child node of the PCI
controller to which the wireless chip is connected. controller to which the wireless chip is connected.
Alternatively, it can specify the wireless part of the MT7628/MT7688 SoC.
For SoC, use the compatible string "mediatek,mt7628-wmac" and the following
properties:
- reg: Address and length of the register set for the device.
- interrupts: Main device interrupt
Optional properties: Optional properties:
- mac-address: See ethernet.txt in the parent directory - mac-address: See ethernet.txt in the parent directory
...@@ -30,3 +37,15 @@ Optional nodes: ...@@ -30,3 +37,15 @@ Optional nodes:
}; };
}; };
}; };
MT7628 example:
wmac: wmac@10300000 {
compatible = "mediatek,mt7628-wmac";
reg = <0x10300000 0x100000>;
interrupt-parent = <&cpuintc>;
interrupts = <6>;
mediatek,mtd-eeprom = <&factory 0x0000>;
};
...@@ -21,3 +21,4 @@ config MT76x02_USB ...@@ -21,3 +21,4 @@ config MT76x02_USB
source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig"
source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig"
source "drivers/net/wireless/mediatek/mt76/mt7603/Kconfig"
...@@ -7,7 +7,7 @@ mt76-y := \ ...@@ -7,7 +7,7 @@ mt76-y := \
mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \ mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \
tx.o agg-rx.o mcu.o tx.o agg-rx.o mcu.o
mt76-usb-y := usb.o usb_trace.o usb_mcu.o mt76-usb-y := usb.o usb_trace.o
CFLAGS_trace.o := -I$(src) CFLAGS_trace.o := -I$(src)
CFLAGS_usb_trace.o := -I$(src) CFLAGS_usb_trace.o := -I$(src)
...@@ -22,3 +22,4 @@ mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o ...@@ -22,3 +22,4 @@ mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o
obj-$(CONFIG_MT76x0_COMMON) += mt76x0/ obj-$(CONFIG_MT76x0_COMMON) += mt76x0/
obj-$(CONFIG_MT76x2_COMMON) += mt76x2/ obj-$(CONFIG_MT76x2_COMMON) += mt76x2/
obj-$(CONFIG_MT7603E) += mt7603/
...@@ -714,6 +714,11 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ...@@ -714,6 +714,11 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
new_state == IEEE80211_STA_NONE) new_state == IEEE80211_STA_NONE)
return mt76_sta_add(dev, vif, sta); return mt76_sta_add(dev, vif, sta);
if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_ASSOC &&
dev->drv->sta_assoc)
dev->drv->sta_assoc(dev, vif, sta);
if (old_state == IEEE80211_STA_NONE && if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_NOTEXIST) new_state == IEEE80211_STA_NOTEXIST)
mt76_sta_remove(dev, vif, sta); mt76_sta_remove(dev, vif, sta);
......
...@@ -304,6 +304,9 @@ struct mt76_driver_ops { ...@@ -304,6 +304,9 @@ struct mt76_driver_ops {
int (*sta_add)(struct mt76_dev *dev, struct ieee80211_vif *vif, int (*sta_add)(struct mt76_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta); struct ieee80211_sta *sta);
void (*sta_assoc)(struct mt76_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void (*sta_remove)(struct mt76_dev *dev, struct ieee80211_vif *vif, void (*sta_remove)(struct mt76_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta); struct ieee80211_sta *sta);
}; };
...@@ -384,8 +387,7 @@ struct mt76_usb { ...@@ -384,8 +387,7 @@ struct mt76_usb {
struct mt76u_mcu { struct mt76u_mcu {
struct mutex mutex; struct mutex mutex;
struct completion cmpl; u8 *data;
struct mt76u_buf res;
u32 msg_seq; u32 msg_seq;
/* multiple reads */ /* multiple reads */
...@@ -729,16 +731,20 @@ static inline u8 q2ep(u8 qid) ...@@ -729,16 +731,20 @@ static inline u8 q2ep(u8 qid)
} }
static inline int static inline int
mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int timeout) mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
int timeout)
{ {
struct usb_interface *intf = to_usb_interface(dev->dev); struct usb_interface *intf = to_usb_interface(dev->dev);
struct usb_device *udev = interface_to_usbdev(intf); struct usb_device *udev = interface_to_usbdev(intf);
struct mt76_usb *usb = &dev->usb; struct mt76_usb *usb = &dev->usb;
unsigned int pipe; unsigned int pipe;
int sent;
pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]); if (actual_len)
return usb_bulk_msg(udev, pipe, data, len, &sent, timeout); pipe = usb_rcvbulkpipe(udev, usb->in_ep[MT_EP_IN_CMD_RESP]);
else
pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]);
return usb_bulk_msg(udev, pipe, data, len, actual_len, timeout);
} }
int mt76u_vendor_request(struct mt76_dev *dev, u8 req, int mt76u_vendor_request(struct mt76_dev *dev, u8 req,
...@@ -747,13 +753,6 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req, ...@@ -747,13 +753,6 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req,
void mt76u_single_wr(struct mt76_dev *dev, const u8 req, void mt76u_single_wr(struct mt76_dev *dev, const u8 req,
const u16 offset, const u32 val); const u16 offset, const u32 val);
int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf); int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf);
void mt76u_deinit(struct mt76_dev *dev);
int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf,
int len, int data_len, gfp_t gfp);
void mt76u_buf_free(struct mt76u_buf *buf);
int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index,
struct mt76u_buf *buf, gfp_t gfp,
usb_complete_t complete_fn, void *context);
int mt76u_submit_rx_buffers(struct mt76_dev *dev); int mt76u_submit_rx_buffers(struct mt76_dev *dev);
int mt76u_alloc_queues(struct mt76_dev *dev); int mt76u_alloc_queues(struct mt76_dev *dev);
void mt76u_stop_queues(struct mt76_dev *dev); void mt76u_stop_queues(struct mt76_dev *dev);
...@@ -767,8 +766,4 @@ void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb); ...@@ -767,8 +766,4 @@ void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb);
struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev,
unsigned long expires); unsigned long expires);
void mt76u_mcu_complete_urb(struct urb *urb);
int mt76u_mcu_init_rx(struct mt76_dev *dev);
void mt76u_mcu_deinit(struct mt76_dev *dev);
#endif #endif
config MT7603E
tristate "MediaTek MT7603E (PCIe) and MT76x8 WLAN support"
select MT76_CORE
depends on MAC80211
depends on PCI
help
This adds support for MT7603E wireless PCIe devices and the WLAN core on
MT7628/MT7688 SoC devices
obj-$(CONFIG_MT7603E) += mt7603e.o
mt7603e-y := \
pci.o soc.o main.o init.o mcu.o \
core.o dma.o mac.o eeprom.o \
beacon.o debugfs.o
/* SPDX-License-Identifier: ISC */
#include "mt7603.h"
struct beacon_bc_data {
struct mt7603_dev *dev;
struct sk_buff_head q;
struct sk_buff *tail[MT7603_MAX_INTERFACES];
int count[MT7603_MAX_INTERFACES];
};
static void
mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
struct mt7603_dev *dev = (struct mt7603_dev *)priv;
struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
struct sk_buff *skb = NULL;
if (!(dev->beacon_mask & BIT(mvif->idx)))
return;
skb = ieee80211_beacon_get(mt76_hw(dev), vif);
if (!skb)
return;
mt76_dma_tx_queue_skb(&dev->mt76, &dev->mt76.q_tx[MT_TXQ_BEACON], skb,
&mvif->sta.wcid, NULL);
spin_lock_bh(&dev->ps_lock);
mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY |
FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, mvif->sta.wcid.idx) |
FIELD_PREP(MT_DMA_FQCR0_TARGET_QID,
dev->mt76.q_tx[MT_TXQ_CAB].hw_idx) |
FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) |
FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8));
if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000))
dev->beacon_check = MT7603_WATCHDOG_TIMEOUT;
spin_unlock_bh(&dev->ps_lock);
}
static void
mt7603_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
struct beacon_bc_data *data = priv;
struct mt7603_dev *dev = data->dev;
struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
struct ieee80211_tx_info *info;
struct sk_buff *skb;
if (!(dev->beacon_mask & BIT(mvif->idx)))
return;
skb = ieee80211_get_buffered_bc(mt76_hw(dev), vif);
if (!skb)
return;
info = IEEE80211_SKB_CB(skb);
info->control.vif = vif;
info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
mt76_skb_set_moredata(skb, true);
__skb_queue_tail(&data->q, skb);
data->tail[mvif->idx] = skb;
data->count[mvif->idx]++;
}
void mt7603_pre_tbtt_tasklet(unsigned long arg)
{
struct mt7603_dev *dev = (struct mt7603_dev *)arg;
struct mt76_queue *q;
struct beacon_bc_data data = {};
struct sk_buff *skb;
int i, nframes;
data.dev = dev;
__skb_queue_head_init(&data.q);
q = &dev->mt76.q_tx[MT_TXQ_BEACON];
spin_lock_bh(&q->lock);
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7603_update_beacon_iter, dev);
mt76_queue_kick(dev, q);
spin_unlock_bh(&q->lock);
/* Flush all previous CAB queue packets */
mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0));
mt76_queue_tx_cleanup(dev, MT_TXQ_CAB, false);
mt76_csa_check(&dev->mt76);
if (dev->mt76.csa_complete)
goto out;
q = &dev->mt76.q_tx[MT_TXQ_CAB];
do {
nframes = skb_queue_len(&data.q);
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7603_add_buffered_bc, &data);
} while (nframes != skb_queue_len(&data.q) &&
skb_queue_len(&data.q) < 8);
if (skb_queue_empty(&data.q))
goto out;
for (i = 0; i < ARRAY_SIZE(data.tail); i++) {
if (!data.tail[i])
continue;
mt76_skb_set_moredata(data.tail[i], false);
}
spin_lock_bh(&q->lock);
while ((skb = __skb_dequeue(&data.q)) != NULL) {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif;
struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
mt76_dma_tx_queue_skb(&dev->mt76, q, skb, &mvif->sta.wcid,
NULL);
}
mt76_queue_kick(dev, q);
spin_unlock_bh(&q->lock);
for (i = 0; i < ARRAY_SIZE(data.count); i++)
mt76_wr(dev, MT_WF_ARB_CAB_COUNT_B0_REG(i),
data.count[i] << MT_WF_ARB_CAB_COUNT_B0_SHIFT(i));
mt76_wr(dev, MT_WF_ARB_CAB_START,
MT_WF_ARB_CAB_START_BSSn(0) |
(MT_WF_ARB_CAB_START_BSS0n(1) *
((1 << (MT7603_MAX_INTERFACES - 1)) - 1)));
out:
mt76_queue_tx_cleanup(dev, MT_TXQ_BEACON, false);
if (dev->mt76.q_tx[MT_TXQ_BEACON].queued >
__sw_hweight8(dev->beacon_mask))
dev->beacon_check++;
}
void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval)
{
u32 pre_tbtt = MT7603_PRE_TBTT_TIME / 64;
if (idx >= 0) {
if (intval)
dev->beacon_mask |= BIT(idx);
else
dev->beacon_mask &= ~BIT(idx);
}
if (!dev->beacon_mask || (!intval && idx < 0)) {
mt7603_irq_disable(dev, MT_INT_MAC_IRQ3);
mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_BCNQ_OPMODE_MASK);
mt76_wr(dev, MT_HW_INT_MASK(3), 0);
return;
}
dev->beacon_int = intval;
mt76_wr(dev, MT_TBTT,
FIELD_PREP(MT_TBTT_PERIOD, intval) | MT_TBTT_CAL_ENABLE);
mt76_wr(dev, MT_TBTT_TIMER_CFG, 0x99); /* start timer */
mt76_rmw_field(dev, MT_ARB_SCR, MT_ARB_SCR_BCNQ_OPMODE_MASK,
MT_BCNQ_OPMODE_AP);
mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_TBTT_BCN_PRIO);
mt76_set(dev, MT_ARB_SCR, MT_ARB_SCR_TBTT_BCAST_PRIO);
mt76_wr(dev, MT_PRE_TBTT, pre_tbtt);
mt76_set(dev, MT_HW_INT_MASK(3),
MT_HW_INT3_PRE_TBTT0 | MT_HW_INT3_TBTT0);
mt76_set(dev, MT_WF_ARB_BCN_START,
MT_WF_ARB_BCN_START_BSSn(0) |
((dev->beacon_mask >> 1) * MT_WF_ARB_BCN_START_BSS0n(1)));
mt7603_irq_enable(dev, MT_INT_MAC_IRQ3);
if (dev->beacon_mask & ~BIT(0))
mt76_set(dev, MT_LPON_SBTOR(0), MT_LPON_SBTOR_SUB_BSS_EN);
else
mt76_clear(dev, MT_LPON_SBTOR(0), MT_LPON_SBTOR_SUB_BSS_EN);
}
/* SPDX-License-Identifier: ISC */
#include "mt7603.h"
void mt7603_set_irq_mask(struct mt7603_dev *dev, u32 clear, u32 set)
{
unsigned long flags;
spin_lock_irqsave(&dev->mt76.mmio.irq_lock, flags);
dev->mt76.mmio.irqmask &= ~clear;
dev->mt76.mmio.irqmask |= set;
mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask);
spin_unlock_irqrestore(&dev->mt76.mmio.irq_lock, flags);
}
void mt7603_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
{
struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
mt7603_irq_enable(dev, MT_INT_RX_DONE(q));
}
irqreturn_t mt7603_irq_handler(int irq, void *dev_instance)
{
struct mt7603_dev *dev = dev_instance;
u32 intr;
intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state))
return IRQ_NONE;
intr &= dev->mt76.mmio.irqmask;
if (intr & MT_INT_MAC_IRQ3) {
u32 hwintr = mt76_rr(dev, MT_HW_INT_STATUS(3));
mt76_wr(dev, MT_HW_INT_STATUS(3), hwintr);
if (hwintr & MT_HW_INT3_PRE_TBTT0)
tasklet_schedule(&dev->pre_tbtt_tasklet);
if ((hwintr & MT_HW_INT3_TBTT0) && dev->mt76.csa_complete)
mt76_csa_finish(&dev->mt76);
}
if (intr & MT_INT_TX_DONE_ALL) {
mt7603_irq_disable(dev, MT_INT_TX_DONE_ALL);
tasklet_schedule(&dev->tx_tasklet);
}
if (intr & MT_INT_RX_DONE(0)) {
mt7603_irq_disable(dev, MT_INT_RX_DONE(0));
napi_schedule(&dev->mt76.napi[0]);
}
if (intr & MT_INT_RX_DONE(1)) {
mt7603_irq_disable(dev, MT_INT_RX_DONE(1));
napi_schedule(&dev->mt76.napi[1]);
}
return IRQ_HANDLED;
}
u32 mt7603_reg_map(struct mt7603_dev *dev, u32 addr)
{
u32 base = addr & GENMASK(31, 19);
u32 offset = addr & GENMASK(18, 0);
dev->bus_ops->wr(&dev->mt76, MT_MCU_PCIE_REMAP_2, base);
return MT_PCIE_REMAP_BASE_2 + offset;
}
/* SPDX-License-Identifier: ISC */
#include "mt7603.h"
static int
mt7603_reset_read(struct seq_file *s, void *data)
{
struct mt7603_dev *dev = dev_get_drvdata(s->private);
static const char * const reset_cause_str[] = {
[RESET_CAUSE_TX_HANG] = "TX hang",
[RESET_CAUSE_TX_BUSY] = "TX DMA busy stuck",
[RESET_CAUSE_RX_BUSY] = "RX DMA busy stuck",
[RESET_CAUSE_RX_PSE_BUSY] = "RX PSE busy stuck",
[RESET_CAUSE_BEACON_STUCK] = "Beacon stuck",
[RESET_CAUSE_MCU_HANG] = "MCU hang",
[RESET_CAUSE_RESET_FAILED] = "PSE reset failed",
};
int i;
for (i = 0; i < ARRAY_SIZE(reset_cause_str); i++) {
if (!reset_cause_str[i])
continue;
seq_printf(s, "%20s: %u\n", reset_cause_str[i],
dev->reset_cause[i]);
}
return 0;
}
static int
mt7603_radio_read(struct seq_file *s, void *data)
{
struct mt7603_dev *dev = dev_get_drvdata(s->private);
seq_printf(s, "Sensitivity: %d\n", dev->sensitivity);
seq_printf(s, "False CCA: ofdm=%d cck=%d\n",
dev->false_cca_ofdm, dev->false_cca_cck);
return 0;
}
void mt7603_init_debugfs(struct mt7603_dev *dev)
{
struct dentry *dir;
dir = mt76_register_debugfs(&dev->mt76);
if (!dir)
return;
debugfs_create_u32("reset_test", 0600, dir, &dev->reset_test);
debugfs_create_devm_seqfile(dev->mt76.dev, "reset", dir,
mt7603_reset_read);
debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir,
mt7603_radio_read);
}
/* SPDX-License-Identifier: ISC */
#include "mt7603.h"
#include "mac.h"
#include "../dma.h"
static int
mt7603_init_tx_queue(struct mt7603_dev *dev, struct mt76_queue *q,
int idx, int n_desc)
{
int ret;
q->hw_idx = idx;
q->regs = dev->mt76.mmio.regs + MT_TX_RING_BASE + idx * MT_RING_SIZE;
q->ndesc = n_desc;
ret = mt76_queue_alloc(dev, q);
if (ret)
return ret;
mt7603_irq_enable(dev, MT_INT_TX_DONE(idx));
return 0;
}
static void
mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb)
{
__le32 *txd = (__le32 *)skb->data;
struct mt7603_sta *msta;
struct mt76_wcid *wcid;
int idx;
u32 val;
if (skb->len < sizeof(MT_TXD_SIZE) + sizeof(struct ieee80211_hdr))
goto free;
val = le32_to_cpu(txd[1]);
idx = FIELD_GET(MT_TXD1_WLAN_IDX, val);
skb->priority = FIELD_GET(MT_TXD1_TID, val);
if (idx >= MT7603_WTBL_STA - 1)
goto free;
wcid = rcu_dereference(dev->mt76.wcid[idx]);
if (!wcid)
goto free;
msta = container_of(wcid, struct mt7603_sta, wcid);
val = le32_to_cpu(txd[0]);
skb_set_queue_mapping(skb, FIELD_GET(MT_TXD0_Q_IDX, val));
spin_lock_bh(&dev->ps_lock);
__skb_queue_tail(&msta->psq, skb);
if (skb_queue_len(&msta->psq) >= 64) {
skb = __skb_dequeue(&msta->psq);
dev_kfree_skb(skb);
}
spin_unlock_bh(&dev->ps_lock);
return;
free:
dev_kfree_skb(skb);
}
void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb)
{
struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
__le32 *rxd = (__le32 *)skb->data;
__le32 *end = (__le32 *)&skb->data[skb->len];
enum rx_pkt_type type;
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
if (q == MT_RXQ_MCU) {
if (type == PKT_TYPE_RX_EVENT)
mt76_mcu_rx_event(&dev->mt76, skb);
else
mt7603_rx_loopback_skb(dev, skb);
return;
}
switch (type) {
case PKT_TYPE_TXS:
for (rxd++; rxd + 5 <= end; rxd += 5)
mt7603_mac_add_txs(dev, rxd);
dev_kfree_skb(skb);
break;
case PKT_TYPE_RX_EVENT:
mt76_mcu_rx_event(&dev->mt76, skb);
return;
case PKT_TYPE_NORMAL:
if (mt7603_mac_fill_rx(dev, skb) == 0) {
mt76_rx(&dev->mt76, q, skb);
return;
}
/* fall through */
default:
dev_kfree_skb(skb);
break;
}
}
static int
mt7603_init_rx_queue(struct mt7603_dev *dev, struct mt76_queue *q,
int idx, int n_desc, int bufsize)
{
int ret;
q->regs = dev->mt76.mmio.regs + MT_RX_RING_BASE + idx * MT_RING_SIZE;
q->ndesc = n_desc;
q->buf_size = bufsize;
ret = mt76_queue_alloc(dev, q);
if (ret)
return ret;
mt7603_irq_enable(dev, MT_INT_RX_DONE(idx));
return 0;
}
static void
mt7603_tx_tasklet(unsigned long data)
{
struct mt7603_dev *dev = (struct mt7603_dev *)data;
int i;
dev->tx_dma_check = 0;
for (i = MT_TXQ_MCU; i >= 0; i--)
mt76_queue_tx_cleanup(dev, i, false);
mt7603_irq_enable(dev, MT_INT_TX_DONE_ALL);
}
int mt7603_dma_init(struct mt7603_dev *dev)
{
static const u8 wmm_queue_map[] = {
[IEEE80211_AC_BK] = 0,
[IEEE80211_AC_BE] = 1,
[IEEE80211_AC_VI] = 2,
[IEEE80211_AC_VO] = 3,
};
int ret;
int i;
mt76_dma_attach(&dev->mt76);
init_waitqueue_head(&dev->mt76.mmio.mcu.wait);
skb_queue_head_init(&dev->mt76.mmio.mcu.res_q);
tasklet_init(&dev->tx_tasklet, mt7603_tx_tasklet, (unsigned long)dev);
mt76_clear(dev, MT_WPDMA_GLO_CFG,
MT_WPDMA_GLO_CFG_TX_DMA_EN |
MT_WPDMA_GLO_CFG_RX_DMA_EN |
MT_WPDMA_GLO_CFG_DMA_BURST_SIZE |
MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
mt76_wr(dev, MT_WPDMA_RST_IDX, ~0);
mt7603_pse_client_reset(dev);
for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) {
ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[i],
wmm_queue_map[i],
MT_TX_RING_SIZE);
if (ret)
return ret;
}
ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_PSD],
MT_TX_HW_QUEUE_MGMT, MT_TX_RING_SIZE);
if (ret)
return ret;
ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU],
MT_TX_HW_QUEUE_MCU, MT_MCU_RING_SIZE);
if (ret)
return ret;
ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_BEACON],
MT_TX_HW_QUEUE_BCN, MT_MCU_RING_SIZE);
if (ret)
return ret;
ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_CAB],
MT_TX_HW_QUEUE_BMC, MT_MCU_RING_SIZE);
if (ret)
return ret;
ret = mt7603_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1,
MT_MCU_RING_SIZE, MT_RX_BUF_SIZE);
if (ret)
return ret;
ret = mt7603_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0,
MT7603_RX_RING_SIZE, MT_RX_BUF_SIZE);
if (ret)
return ret;
mt76_wr(dev, MT_DELAY_INT_CFG, 0);
return mt76_init_queues(dev);
}
void mt7603_dma_cleanup(struct mt7603_dev *dev)
{
mt76_clear(dev, MT_WPDMA_GLO_CFG,
MT_WPDMA_GLO_CFG_TX_DMA_EN |
MT_WPDMA_GLO_CFG_RX_DMA_EN |
MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE);
tasklet_kill(&dev->tx_tasklet);
mt76_dma_cleanup(&dev->mt76);
}
/* SPDX-License-Identifier: ISC */
#include "mt7603.h"
#include "eeprom.h"
static int
mt7603_efuse_read(struct mt7603_dev *dev, u32 base, u16 addr, u8 *data)
{
u32 val;
int i;
val = mt76_rr(dev, base + MT_EFUSE_CTRL);
val &= ~(MT_EFUSE_CTRL_AIN |
MT_EFUSE_CTRL_MODE);
val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf);
val |= MT_EFUSE_CTRL_KICK;
mt76_wr(dev, base + MT_EFUSE_CTRL, val);
if (!mt76_poll(dev, base + MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
return -ETIMEDOUT;
udelay(2);
val = mt76_rr(dev, base + MT_EFUSE_CTRL);
if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT ||
WARN_ON_ONCE(!(val & MT_EFUSE_CTRL_VALID))) {
memset(data, 0xff, 16);
return 0;
}
for (i = 0; i < 4; i++) {
val = mt76_rr(dev, base + MT_EFUSE_RDATA(i));
put_unaligned_le32(val, data + 4 * i);
}
return 0;
}
static int
mt7603_efuse_init(struct mt7603_dev *dev)
{
u32 base = mt7603_reg_map(dev, MT_EFUSE_BASE);
int len = MT7603_EEPROM_SIZE;
void *buf;
int ret, i;
if (mt76_rr(dev, base + MT_EFUSE_BASE_CTRL) & MT_EFUSE_BASE_CTRL_EMPTY)
return 0;
dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL);
dev->mt76.otp.size = len;
if (!dev->mt76.otp.data)
return -ENOMEM;
buf = dev->mt76.otp.data;
for (i = 0; i + 16 <= len; i += 16) {
ret = mt7603_efuse_read(dev, base, i, buf + i);
if (ret)
return ret;
}
return 0;
}
static bool
mt7603_has_cal_free_data(struct mt7603_dev *dev, u8 *efuse)
{
if (!efuse[MT_EE_TEMP_SENSOR_CAL])
return false;
if (get_unaligned_le16(efuse + MT_EE_TX_POWER_0_START_2G) == 0)
return false;
if (get_unaligned_le16(efuse + MT_EE_TX_POWER_1_START_2G) == 0)
return false;
if (!efuse[MT_EE_CP_FT_VERSION])
return false;
if (!efuse[MT_EE_XTAL_FREQ_OFFSET])
return false;
if (!efuse[MT_EE_XTAL_WF_RFCAL])
return false;
return true;
}
static void
mt7603_apply_cal_free_data(struct mt7603_dev *dev, u8 *efuse)
{
static const u8 cal_free_bytes[] = {
MT_EE_TEMP_SENSOR_CAL,
MT_EE_CP_FT_VERSION,
MT_EE_XTAL_FREQ_OFFSET,
MT_EE_XTAL_WF_RFCAL,
/* Skip for MT7628 */
MT_EE_TX_POWER_0_START_2G,
MT_EE_TX_POWER_0_START_2G + 1,
MT_EE_TX_POWER_1_START_2G,
MT_EE_TX_POWER_1_START_2G + 1,
};
u8 *eeprom = dev->mt76.eeprom.data;
int n = ARRAY_SIZE(cal_free_bytes);
int i;
if (!mt7603_has_cal_free_data(dev, efuse))
return;
if (is_mt7628(dev))
n -= 4;
for (i = 0; i < n; i++) {
int offset = cal_free_bytes[i];
eeprom[offset] = efuse[offset];
}
}
static int
mt7603_eeprom_load(struct mt7603_dev *dev)
{
int ret;
ret = mt76_eeprom_init(&dev->mt76, MT7603_EEPROM_SIZE);
if (ret < 0)
return ret;
return mt7603_efuse_init(dev);
}
static int mt7603_check_eeprom(struct mt76_dev *dev)
{
u16 val = get_unaligned_le16(dev->eeprom.data);
switch (val) {
case 0x7628:
case 0x7603:
return 0;
default:
return -EINVAL;
}
}
int mt7603_eeprom_init(struct mt7603_dev *dev)
{
int ret;
ret = mt7603_eeprom_load(dev);
if (ret < 0)
return ret;
if (dev->mt76.otp.data) {
if (mt7603_check_eeprom(&dev->mt76) == 0)
mt7603_apply_cal_free_data(dev, dev->mt76.otp.data);
else
memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data,
MT7603_EEPROM_SIZE);
}
dev->mt76.cap.has_2ghz = true;
memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
ETH_ALEN);
mt76_eeprom_override(&dev->mt76);
return 0;
}
/* SPDX-License-Identifier: ISC */
#ifndef __MT7603_EEPROM_H
#define __MT7603_EEPROM_H
#include "mt7603.h"
enum mt7603_eeprom_field {
MT_EE_CHIP_ID = 0x000,
MT_EE_VERSION = 0x002,
MT_EE_MAC_ADDR = 0x004,
MT_EE_NIC_CONF_0 = 0x034,
MT_EE_NIC_CONF_1 = 0x036,
MT_EE_NIC_CONF_2 = 0x042,
MT_EE_XTAL_TRIM_1 = 0x03a,
MT_EE_RSSI_OFFSET_2G = 0x046,
MT_EE_WIFI_RF_SETTING = 0x048,
MT_EE_RSSI_OFFSET_5G = 0x04a,
MT_EE_TX_POWER_DELTA_BW40 = 0x050,
MT_EE_TX_POWER_DELTA_BW80 = 0x052,
MT_EE_TX_POWER_EXT_PA_5G = 0x054,
MT_EE_TEMP_SENSOR_CAL = 0x055,
MT_EE_TX_POWER_0_START_2G = 0x056,
MT_EE_TX_POWER_1_START_2G = 0x05c,
/* used as byte arrays */
#define MT_TX_POWER_GROUP_SIZE_5G 5
#define MT_TX_POWER_GROUPS_5G 6
MT_EE_TX_POWER_0_START_5G = 0x062,
MT_EE_TX_POWER_0_GRP3_TX_POWER_DELTA = 0x074,
MT_EE_TX_POWER_0_GRP4_TSSI_SLOPE = 0x076,
MT_EE_TX_POWER_1_START_5G = 0x080,
MT_EE_TX_POWER_CCK = 0x0a0,
MT_EE_TX_POWER_OFDM_2G_6M = 0x0a2,
MT_EE_TX_POWER_OFDM_2G_24M = 0x0a4,
MT_EE_TX_POWER_OFDM_2G_54M = 0x0a6,
MT_EE_TX_POWER_HT_BPSK_QPSK = 0x0a8,
MT_EE_TX_POWER_HT_16_64_QAM = 0x0aa,
MT_EE_TX_POWER_HT_64_QAM = 0x0ac,
MT_EE_ELAN_RX_MODE_GAIN = 0x0c0,
MT_EE_ELAN_RX_MODE_NF = 0x0c1,
MT_EE_ELAN_RX_MODE_P1DB = 0x0c2,
MT_EE_ELAN_BYPASS_MODE_GAIN = 0x0c3,
MT_EE_ELAN_BYPASS_MODE_NF = 0x0c4,
MT_EE_ELAN_BYPASS_MODE_P1DB = 0x0c5,
MT_EE_STEP_NUM_NEG_6_7 = 0x0c6,
MT_EE_STEP_NUM_NEG_4_5 = 0x0c8,
MT_EE_STEP_NUM_NEG_2_3 = 0x0ca,
MT_EE_STEP_NUM_NEG_0_1 = 0x0cc,
MT_EE_REF_STEP_24G = 0x0ce,
MT_EE_STEP_NUM_PLUS_1_2 = 0x0d0,
MT_EE_STEP_NUM_PLUS_3_4 = 0x0d2,
MT_EE_STEP_NUM_PLUS_5_6 = 0x0d4,
MT_EE_STEP_NUM_PLUS_7 = 0x0d6,
MT_EE_CP_FT_VERSION = 0x0f0,
MT_EE_XTAL_FREQ_OFFSET = 0x0f4,
MT_EE_XTAL_TRIM_2_COMP = 0x0f5,
MT_EE_XTAL_TRIM_3_COMP = 0x0f6,
MT_EE_XTAL_WF_RFCAL = 0x0f7,
__MT_EE_MAX
};
enum mt7603_eeprom_source {
MT_EE_SRC_PROM,
MT_EE_SRC_EFUSE,
MT_EE_SRC_FLASH,
};
#endif
This diff is collapsed.
This diff is collapsed.
/* SPDX-License-Identifier: ISC */
#ifndef __MT7603_MAC_H
#define __MT7603_MAC_H
#define MT_RXD0_LENGTH GENMASK(15, 0)
#define MT_RXD0_PKT_TYPE GENMASK(31, 29)
#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16)
#define MT_RXD0_NORMAL_IP_SUM BIT(23)
#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24)
#define MT_RXD0_NORMAL_GROUP_1 BIT(25)
#define MT_RXD0_NORMAL_GROUP_2 BIT(26)
#define MT_RXD0_NORMAL_GROUP_3 BIT(27)
#define MT_RXD0_NORMAL_GROUP_4 BIT(28)
enum rx_pkt_type {
PKT_TYPE_TXS = 0,
PKT_TYPE_TXRXV = 1,
PKT_TYPE_NORMAL = 2,
PKT_TYPE_RX_DUP_RFB = 3,
PKT_TYPE_RX_TMR = 4,
PKT_TYPE_RETRIEVE = 5,
PKT_TYPE_RX_EVENT = 7,
};
#define MT_RXD1_NORMAL_BSSID GENMASK(31, 26)
#define MT_RXD1_NORMAL_PAYLOAD_FORMAT GENMASK(25, 24)
#define MT_RXD1_NORMAL_HDR_TRANS BIT(23)
#define MT_RXD1_NORMAL_HDR_OFFSET BIT(22)
#define MT_RXD1_NORMAL_MAC_HDR_LEN GENMASK(21, 16)
#define MT_RXD1_NORMAL_CH_FREQ GENMASK(15, 8)
#define MT_RXD1_NORMAL_KEY_ID GENMASK(7, 6)
#define MT_RXD1_NORMAL_BEACON_UC BIT(5)
#define MT_RXD1_NORMAL_BEACON_MC BIT(4)
#define MT_RXD1_NORMAL_BCAST BIT(3)
#define MT_RXD1_NORMAL_MCAST BIT(2)
#define MT_RXD1_NORMAL_U2M BIT(1)
#define MT_RXD1_NORMAL_HTC_VLD BIT(0)
#define MT_RXD2_NORMAL_NON_AMPDU BIT(31)
#define MT_RXD2_NORMAL_NON_AMPDU_SUB BIT(30)
#define MT_RXD2_NORMAL_NDATA BIT(29)
#define MT_RXD2_NORMAL_NULL_FRAME BIT(28)
#define MT_RXD2_NORMAL_FRAG BIT(27)
#define MT_RXD2_NORMAL_UDF_VALID BIT(26)
#define MT_RXD2_NORMAL_LLC_MIS BIT(25)
#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24)
#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23)
#define MT_RXD2_NORMAL_LEN_MISMATCH BIT(22)
#define MT_RXD2_NORMAL_TKIP_MIC_ERR BIT(21)
#define MT_RXD2_NORMAL_ICV_ERR BIT(20)
#define MT_RXD2_NORMAL_CLM BIT(19)
#define MT_RXD2_NORMAL_CM BIT(18)
#define MT_RXD2_NORMAL_FCS_ERR BIT(17)
#define MT_RXD2_NORMAL_SW_BIT BIT(16)
#define MT_RXD2_NORMAL_SEC_MODE GENMASK(15, 12)
#define MT_RXD2_NORMAL_TID GENMASK(11, 8)
#define MT_RXD2_NORMAL_WLAN_IDX GENMASK(7, 0)
#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30)
#define MT_RXD3_NORMAL_PF_MODE BIT(29)
#define MT_RXD3_NORMAL_CLS_BITMAP GENMASK(28, 19)
#define MT_RXD3_NORMAL_WOL GENMASK(18, 14)
#define MT_RXD3_NORMAL_MAGIC_PKT BIT(13)
#define MT_RXD3_NORMAL_OFLD GENMASK(12, 11)
#define MT_RXD3_NORMAL_CLS BIT(10)
#define MT_RXD3_NORMAL_PATTERN_DROP BIT(9)
#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(8)
#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0)
#define MT_RXV1_VHTA1_B5_B4 GENMASK(31, 30)
#define MT_RXV1_VHTA2_B8_B1 GENMASK(29, 22)
#define MT_RXV1_HT_NO_SOUND BIT(21)
#define MT_RXV1_HT_SMOOTH BIT(20)
#define MT_RXV1_HT_SHORT_GI BIT(19)
#define MT_RXV1_HT_AGGR BIT(18)
#define MT_RXV1_VHTA1_B22 BIT(17)
#define MT_RXV1_FRAME_MODE GENMASK(16, 15)
#define MT_RXV1_TX_MODE GENMASK(14, 12)
#define MT_RXV1_HT_EXT_LTF GENMASK(11, 10)
#define MT_RXV1_HT_AD_CODE BIT(9)
#define MT_RXV1_HT_STBC GENMASK(8, 7)
#define MT_RXV1_TX_RATE GENMASK(6, 0)
#define MT_RXV2_VHTA1_B16_B6 GENMASK(31, 21)
#define MT_RXV2_LENGTH GENMASK(20, 0)
#define MT_RXV3_F_AGC1_CAL_GAIN GENMASK(31, 29)
#define MT_RXV3_F_AGC1_EQ_CAL BIT(28)
#define MT_RXV3_RCPI1 GENMASK(27, 20)
#define MT_RXV3_F_AGC0_CAL_GAIN GENMASK(19, 17)
#define MT_RXV3_F_AGC0_EQ_CAL BIT(16)
#define MT_RXV3_RCPI0 GENMASK(15, 8)
#define MT_RXV3_SEL_ANT BIT(7)
#define MT_RXV3_ACI_DET_X BIT(6)
#define MT_RXV3_OFDM_FREQ_TRANS_DETECT BIT(5)
#define MT_RXV3_VHTA1_B21_B17 GENMASK(4, 0)
#define MT_RXV4_F_AGC_CAL_GAIN GENMASK(31, 29)
#define MT_RXV4_F_AGC2_EQ_CAL BIT(28)
#define MT_RXV4_IB_RSSI1 GENMASK(27, 20)
#define MT_RXV4_F_AGC_LPF_GAIN_X GENMASK(19, 16)
#define MT_RXV4_WB_RSSI_X GENMASK(15, 8)
#define MT_RXV4_IB_RSSI0 GENMASK(7, 0)
#define MT_RXV5_LTF_SNR0 GENMASK(31, 26)
#define MT_RXV5_LTF_PROC_TIME GENMASK(25, 19)
#define MT_RXV5_FOE GENMASK(18, 7)
#define MT_RXV5_C_AGC_SATE GENMASK(6, 4)
#define MT_RXV5_F_AGC_LNA_GAIN_0 GENMASK(3, 2)
#define MT_RXV5_F_AGC_LNA_GAIN_1 GENMASK(1, 0)
#define MT_RXV6_C_AGC_STATE GENMASK(30, 28)
#define MT_RXV6_NS_TS_FIELD GENMASK(27, 25)
#define MT_RXV6_RX_VALID BIT(24)
#define MT_RXV6_NF2 GENMASK(23, 16)
#define MT_RXV6_NF1 GENMASK(15, 8)
#define MT_RXV6_NF0 GENMASK(7, 0)
enum mt7603_tx_header_format {
MT_HDR_FORMAT_802_3,
MT_HDR_FORMAT_CMD,
MT_HDR_FORMAT_802_11,
MT_HDR_FORMAT_802_11_EXT,
};
#define MT_TXD_SIZE (8 * 4)
#define MT_TXD0_P_IDX BIT(31)
#define MT_TXD0_Q_IDX GENMASK(30, 27)
#define MT_TXD0_UTXB BIT(26)
#define MT_TXD0_UNXV BIT(25)
#define MT_TXD0_UDP_TCP_SUM BIT(24)
#define MT_TXD0_IP_SUM BIT(23)
#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
#define MT_TXD0_TX_BYTES GENMASK(15, 0)
#define MT_TXD1_OWN_MAC GENMASK(31, 26)
#define MT_TXD1_PROTECTED BIT(23)
#define MT_TXD1_TID GENMASK(22, 20)
#define MT_TXD1_NO_ACK BIT(19)
#define MT_TXD1_HDR_PAD GENMASK(18, 16)
#define MT_TXD1_LONG_FORMAT BIT(15)
#define MT_TXD1_HDR_FORMAT GENMASK(14, 13)
#define MT_TXD1_HDR_INFO GENMASK(12, 8)
#define MT_TXD1_WLAN_IDX GENMASK(7, 0)
#define MT_TXD2_FIX_RATE BIT(31)
#define MT_TXD2_TIMING_MEASURE BIT(30)
#define MT_TXD2_BA_DISABLE BIT(29)
#define MT_TXD2_POWER_OFFSET GENMASK(28, 24)
#define MT_TXD2_MAX_TX_TIME GENMASK(23, 16)
#define MT_TXD2_FRAG GENMASK(15, 14)
#define MT_TXD2_HTC_VLD BIT(13)
#define MT_TXD2_DURATION BIT(12)
#define MT_TXD2_BIP BIT(11)
#define MT_TXD2_MULTICAST BIT(10)
#define MT_TXD2_RTS BIT(9)
#define MT_TXD2_SOUNDING BIT(8)
#define MT_TXD2_NDPA BIT(7)
#define MT_TXD2_NDP BIT(6)
#define MT_TXD2_FRAME_TYPE GENMASK(5, 4)
#define MT_TXD2_SUB_TYPE GENMASK(3, 0)
#define MT_TXD3_SN_VALID BIT(31)
#define MT_TXD3_PN_VALID BIT(30)
#define MT_TXD3_SEQ GENMASK(27, 16)
#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11)
#define MT_TXD3_TX_COUNT GENMASK(10, 6)
#define MT_TXD4_PN_LOW GENMASK(31, 0)
#define MT_TXD5_PN_HIGH GENMASK(31, 16)
#define MT_TXD5_SW_POWER_MGMT BIT(13)
#define MT_TXD5_BA_SEQ_CTRL BIT(12)
#define MT_TXD5_DA_SELECT BIT(11)
#define MT_TXD5_TX_STATUS_HOST BIT(10)
#define MT_TXD5_TX_STATUS_MCU BIT(9)
#define MT_TXD5_TX_STATUS_FMT BIT(8)
#define MT_TXD5_PID GENMASK(7, 0)
#define MT_TXD6_SGI BIT(31)
#define MT_TXD6_LDPC BIT(30)
#define MT_TXD6_TX_RATE GENMASK(29, 18)
#define MT_TXD6_I_TXBF BIT(17)
#define MT_TXD6_E_TXBF BIT(16)
#define MT_TXD6_DYN_BW BIT(15)
#define MT_TXD6_ANT_PRI GENMASK(14, 12)
#define MT_TXD6_SPE_EN BIT(11)
#define MT_TXD6_FIXED_BW BIT(10)
#define MT_TXD6_BW GENMASK(9, 8)
#define MT_TXD6_ANT_ID GENMASK(7, 2)
#define MT_TXD6_FIXED_RATE BIT(0)
#define MT_TX_RATE_STBC BIT(11)
#define MT_TX_RATE_NSS GENMASK(10, 9)
#define MT_TX_RATE_MODE GENMASK(8, 6)
#define MT_TX_RATE_IDX GENMASK(5, 0)
#define MT_TXS0_ANTENNA GENMASK(31, 26)
#define MT_TXS0_TID GENMASK(25, 22)
#define MT_TXS0_BA_ERROR BIT(22)
#define MT_TXS0_PS_FLAG BIT(21)
#define MT_TXS0_TXOP_TIMEOUT BIT(20)
#define MT_TXS0_BIP_ERROR BIT(19)
#define MT_TXS0_QUEUE_TIMEOUT BIT(18)
#define MT_TXS0_RTS_TIMEOUT BIT(17)
#define MT_TXS0_ACK_TIMEOUT BIT(16)
#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16)
#define MT_TXS0_TX_STATUS_HOST BIT(15)
#define MT_TXS0_TX_STATUS_MCU BIT(14)
#define MT_TXS0_TXS_FORMAT BIT(13)
#define MT_TXS0_FIXED_RATE BIT(12)
#define MT_TXS0_TX_RATE GENMASK(11, 0)
#define MT_TXS1_F0_TIMESTAMP GENMASK(31, 0)
#define MT_TXS1_F1_NOISE_2 GENMASK(23, 16)
#define MT_TXS1_F1_NOISE_1 GENMASK(15, 8)
#define MT_TXS1_F1_NOISE_0 GENMASK(7, 0)
#define MT_TXS2_F0_FRONT_TIME GENMASK(24, 0)
#define MT_TXS2_F1_RCPI_2 GENMASK(23, 16)
#define MT_TXS2_F1_RCPI_1 GENMASK(15, 8)
#define MT_TXS2_F1_RCPI_0 GENMASK(7, 0)
#define MT_TXS3_WCID GENMASK(31, 24)
#define MT_TXS3_RXV_SEQNO GENMASK(23, 16)
#define MT_TXS3_TX_DELAY GENMASK(15, 0)
#define MT_TXS4_LAST_TX_RATE GENMASK(31, 29)
#define MT_TXS4_TX_COUNT GENMASK(28, 24)
#define MT_TXS4_AMPDU BIT(23)
#define MT_TXS4_ACKED_MPDU BIT(22)
#define MT_TXS4_PID GENMASK(21, 14)
#define MT_TXS4_BW GENMASK(13, 12)
#define MT_TXS4_F0_SEQNO GENMASK(11, 0)
#define MT_TXS4_F1_TSSI GENMASK(11, 0)
#endif
This diff is collapsed.
This diff is collapsed.
/* SPDX-License-Identifier: ISC */
#ifndef __MT7603_MCU_H
#define __MT7603_MCU_H
struct mt7603_mcu_txd {
__le16 len;
__le16 pq_id;
u8 cid;
u8 pkt_type;
u8 set_query;
u8 seq;
u8 uc_d2b0_rev;
u8 ext_cid;
u8 uc_d2b2_rev;
u8 ext_cid_ack;
u32 au4_d3_to_d7_rev[5];
} __packed __aligned(4);
struct mt7603_mcu_rxd {
__le16 len;
__le16 pkt_type_id;
u8 eid;
u8 seq;
__le16 __rsv;
u8 ext_eid;
u8 __rsv1[3];
};
#define MCU_PKT_ID 0xa0
#define MCU_PORT_QUEUE 0x8000
#define MCU_PORT_QUEUE_FW 0xc000
#define MCU_FIRMWARE_ADDRESS 0x100000
enum {
MCU_Q_QUERY,
MCU_Q_SET,
MCU_Q_RESERVED,
MCU_Q_NA
};
enum {
MCU_CMD_TARGET_ADDRESS_LEN_REQ = 0x01,
MCU_CMD_FW_START_REQ = 0x02,
MCU_CMD_INIT_ACCESS_REG = 0x3,
MCU_CMD_PATCH_START_REQ = 0x05,
MCU_CMD_PATCH_FINISH_REQ = 0x07,
MCU_CMD_PATCH_SEM_CONTROL = 0x10,
MCU_CMD_HIF_LOOPBACK = 0x20,
MCU_CMD_CH_PRIVILEGE = 0x20,
MCU_CMD_ACCESS_REG = 0xC2,
MCU_CMD_EXT_CID = 0xED,
MCU_CMD_FW_SCATTER = 0xEE,
MCU_CMD_RESTART_DL_REQ = 0xEF,
};
enum {
MCU_EXT_CMD_RF_REG_ACCESS = 0x02,
MCU_EXT_CMD_RF_TEST = 0x04,
MCU_EXT_CMD_RADIO_ON_OFF_CTRL = 0x05,
MCU_EXT_CMD_WIFI_RX_DISABLE = 0x06,
MCU_EXT_CMD_PM_STATE_CTRL = 0x07,
MCU_EXT_CMD_CHANNEL_SWITCH = 0x08,
MCU_EXT_CMD_NIC_CAPABILITY = 0x09,
MCU_EXT_CMD_PWR_SAVING = 0x0A,
MCU_EXT_CMD_MULTIPLE_REG_ACCESS = 0x0E,
MCU_EXT_CMD_AP_PWR_SAVING_CAPABILITY = 0xF,
MCU_EXT_CMD_SEC_ADDREMOVE_KEY = 0x10,
MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11,
MCU_EXT_CMD_FW_LOG_2_HOST = 0x13,
MCU_EXT_CMD_PS_RETRIEVE_START = 0x14,
MCU_EXT_CMD_LED_CTRL = 0x17,
MCU_EXT_CMD_PACKET_FILTER = 0x18,
MCU_EXT_CMD_PWR_MGT_BIT_WIFI = 0x1B,
MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21,
MCU_EXT_CMD_THERMAL_PROTECT = 0x23,
MCU_EXT_CMD_EDCA_SET = 0x27,
MCU_EXT_CMD_SLOT_TIME_SET = 0x28,
MCU_EXT_CMD_CONFIG_INTERNAL_SETTING = 0x29,
MCU_EXT_CMD_NOA_OFFLOAD_CTRL = 0x2B,
MCU_EXT_CMD_GET_THEMAL_SENSOR = 0x2C,
MCU_EXT_CMD_WAKEUP_OPTION = 0x2E,
MCU_EXT_CMD_AC_QUEUE_CONTROL = 0x31,
MCU_EXT_CMD_BCN_UPDATE = 0x33
};
enum {
MCU_EXT_EVENT_CMD_RESULT = 0x0,
MCU_EXT_EVENT_RF_REG_ACCESS = 0x2,
MCU_EXT_EVENT_MULTI_CR_ACCESS = 0x0E,
MCU_EXT_EVENT_FW_LOG_2_HOST = 0x13,
MCU_EXT_EVENT_BEACON_LOSS = 0x1A,
MCU_EXT_EVENT_THERMAL_PROTECT = 0x22,
MCU_EXT_EVENT_BCN_UPDATE = 0x31,
};
static inline struct sk_buff *
mt7603_mcu_msg_alloc(const void *data, int len)
{
return mt76_mcu_msg_alloc(data, sizeof(struct mt7603_mcu_txd),
len, 0);
}
#endif
This diff is collapsed.
/* SPDX-License-Identifier: ISC */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include "mt7603.h"
static const struct pci_device_id mt76pci_device_table[] = {
{ PCI_DEVICE(0x14c3, 0x7603) },
{ },
};
static int
mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct mt7603_dev *dev;
struct mt76_dev *mdev;
int ret;
ret = pcim_enable_device(pdev);
if (ret)
return ret;
ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
if (ret)
return ret;
pci_set_master(pdev);
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (ret)
return ret;
mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7603_ops,
&mt7603_drv_ops);
if (!mdev)
return -ENOMEM;
dev = container_of(mdev, struct mt7603_dev, mt76);
mt76_mmio_init(mdev, pcim_iomap_table(pdev)[0]);
mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
(mt76_rr(dev, MT_HW_REV) & 0xff);
dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
ret = devm_request_irq(mdev->dev, pdev->irq, mt7603_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)
goto error;
ret = mt7603_register_device(dev);
if (ret)
goto error;
return 0;
error:
ieee80211_free_hw(mt76_hw(dev));
return ret;
}
static void
mt76pci_remove(struct pci_dev *pdev)
{
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
mt7603_unregister_device(dev);
}
MODULE_DEVICE_TABLE(pci, mt76pci_device_table);
MODULE_FIRMWARE(MT7603_FIRMWARE_E1);
MODULE_FIRMWARE(MT7603_FIRMWARE_E2);
struct pci_driver mt7603_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = mt76pci_device_table,
.probe = mt76pci_probe,
.remove = mt76pci_remove,
};
This diff is collapsed.
/* SPDX-License-Identifier: ISC */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include "mt7603.h"
static int
mt76_wmac_probe(struct platform_device *pdev)
{
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct mt7603_dev *dev;
void __iomem *mem_base;
struct mt76_dev *mdev;
int irq;
int ret;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "Failed to get device IRQ\n");
return irq;
}
mem_base = devm_ioremap_resource(&pdev->dev, res);
if (!mem_base) {
dev_err(&pdev->dev, "Failed to get memory resource\n");
return -EINVAL;
}
mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7603_ops,
&mt7603_drv_ops);
if (!mdev)
return -ENOMEM;
dev = container_of(mdev, struct mt7603_dev, mt76);
mt76_mmio_init(mdev, mem_base);
mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
(mt76_rr(dev, MT_HW_REV) & 0xff);
dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
ret = devm_request_irq(mdev->dev, irq, mt7603_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)
goto error;
ret = mt7603_register_device(dev);
if (ret)
goto error;
return 0;
error:
ieee80211_free_hw(mt76_hw(dev));
return ret;
}
static int
mt76_wmac_remove(struct platform_device *pdev)
{
struct mt76_dev *mdev = platform_get_drvdata(pdev);
struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
mt7603_unregister_device(dev);
return 0;
}
static const struct of_device_id of_wmac_match[] = {
{ .compatible = "mediatek,mt7628-wmac" },
{},
};
MODULE_DEVICE_TABLE(of, of_wmac_match);
MODULE_FIRMWARE(MT7628_FIRMWARE_E1);
MODULE_FIRMWARE(MT7628_FIRMWARE_E2);
struct platform_driver mt76_wmac_driver = {
.probe = mt76_wmac_probe,
.remove = mt76_wmac_remove,
.driver = {
.name = "mt76_wmac",
.of_match_table = of_wmac_match,
},
};
...@@ -187,6 +187,8 @@ void mt76x0_mac_stop(struct mt76x02_dev *dev) ...@@ -187,6 +187,8 @@ void mt76x0_mac_stop(struct mt76x02_dev *dev)
{ {
int i = 200, ok = 0; int i = 200, ok = 0;
mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
/* Page count on TxQ */ /* Page count on TxQ */
while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) || while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) ||
(mt76_rr(dev, 0x0a30) & 0x000000ff) || (mt76_rr(dev, 0x0a30) & 0x000000ff) ||
......
...@@ -34,6 +34,8 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) ...@@ -34,6 +34,8 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef)
mt76_rr(dev, MT_CH_IDLE); mt76_rr(dev, MT_CH_IDLE);
mt76_rr(dev, MT_CH_BUSY); mt76_rr(dev, MT_CH_BUSY);
mt76x02_edcca_init(dev, true);
if (mt76_is_mmio(dev)) { if (mt76_is_mmio(dev)) {
mt76x02_dfs_init_params(dev); mt76x02_dfs_init_params(dev);
tasklet_enable(&dev->pre_tbtt_tasklet); tasklet_enable(&dev->pre_tbtt_tasklet);
......
...@@ -1007,17 +1007,13 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev, ...@@ -1007,17 +1007,13 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
/* enable vco */ /* enable vco */
mt76x0_rf_set(dev, MT_RF(0, 4), BIT(7)); mt76x0_rf_set(dev, MT_RF(0, 4), BIT(7));
if (scan) { if (scan)
mt76x02_edcca_init(dev, false);
return 0; return 0;
}
mt76x02_init_agc_gain(dev); mt76x02_init_agc_gain(dev);
mt76x0_phy_calibrate(dev, false); mt76x0_phy_calibrate(dev, false);
mt76x0_phy_set_txpower(dev); mt76x0_phy_set_txpower(dev);
mt76x02_edcca_init(dev, true);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
MT_CALIBRATE_INTERVAL); MT_CALIBRATE_INTERVAL);
......
...@@ -98,6 +98,7 @@ struct mt76x02_dev { ...@@ -98,6 +98,7 @@ struct mt76x02_dev {
u32 tx_hang_reset; u32 tx_hang_reset;
u8 tx_hang_check; u8 tx_hang_check;
u8 mcu_timeout;
struct mt76x02_calibration cal; struct mt76x02_calibration cal;
......
This diff is collapsed.
This diff is collapsed.
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