@@ -330,6 +330,14 @@ int mt76x2_mac_reset(struct mt76x2_dev *dev, bool hard)
return 0;
}
+int mt76x0_mac_reset(struct mt76x2_dev *dev)
+{
+ mt76_set(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR);
+ udelay(50);
+ mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR);
+ return 0;
+}
+
int mt76x2_mac_start(struct mt76x2_dev *dev)
{
int i;
@@ -364,6 +372,34 @@ int mt76x2_mac_start(struct mt76x2_dev *dev)
return 0;
}
+int mt76x0_mac_start(struct mt76x2_dev *dev)
+{
+ mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
+
+ if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
+ MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 200000))
+ return -ETIMEDOUT;
+
+ dev->rxfilter = MT_RX_FILTR_CFG_CRC_ERR |
+ MT_RX_FILTR_CFG_PHY_ERR | MT_RX_FILTR_CFG_PROMISC |
+ MT_RX_FILTR_CFG_VER_ERR | MT_RX_FILTR_CFG_DUP |
+ MT_RX_FILTR_CFG_CFACK | MT_RX_FILTR_CFG_CFEND |
+ MT_RX_FILTR_CFG_ACK | MT_RX_FILTR_CFG_CTS |
+ MT_RX_FILTR_CFG_RTS | MT_RX_FILTR_CFG_PSPOLL |
+ MT_RX_FILTR_CFG_BA | MT_RX_FILTR_CFG_CTRL_RSV;
+
+ mt76_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter);
+
+ mt76_wr(dev, MT_MAC_SYS_CTRL,
+ MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
+
+ if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
+ MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 50))
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
void mt76x2_mac_stop(struct mt76x2_dev *dev, bool force)
{
bool stopped = false;
@@ -399,6 +435,38 @@ void mt76x2_mac_stop(struct mt76x2_dev *dev, bool force)
mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg);
}
+void mt76x0_mac_stop(struct mt76x2_dev *dev) {
+ int i, ok;
+
+ mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN |
+ MT_BEACON_TIME_CFG_SYNC_MODE | MT_BEACON_TIME_CFG_TBTT_EN |
+ MT_BEACON_TIME_CFG_BEACON_TX);
+
+ /* Page count on TxQ */
+ i = 200;
+ while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) ||
+ (mt76_rr(dev, 0x0a30) & 0x000000ff) ||
+ (mt76_rr(dev, 0x0a34) & 0x00ff00ff)))
+ msleep(10);
+
+ mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_RX |
+ MT_MAC_SYS_CTRL_ENABLE_TX);
+
+ /* Page count on RxQ */
+ ok = 0;
+ i = 200;
+ while (i--) {
+ if (!(mt76_rr(dev, MT_RXQ_STA) & 0x00ff0000) &&
+ !mt76_rr(dev, 0x0a30) &&
+ !mt76_rr(dev, 0x0a34)) {
+ if (ok++ > 5)
+ break;
+ continue;
+ }
+ msleep(1);
+ }
+}
+
void mt76x2_mac_resume(struct mt76x2_dev *dev)
{
mt76_wr(dev, MT_MAC_SYS_CTRL,
@@ -485,6 +553,34 @@ mt76x2_power_on(struct mt76x2_dev *dev)
mt76x2_power_on_rf(dev, 1);
}
+/* Big thanks to the author(s?) of mt7601U, upstream version */
+static void
+mt76x2_power_on_76x0(struct mt76x2_dev *dev)
+{
+ int i;
+ u32 val;
+
+ val = mt76_rr(dev, MT_WLAN_FUN_CTRL);
+
+ /* Note: we don't turn off WLAN_CLK because that may make the device not responsive. */
+ val |= (MT_WLAN_FUN_CTRL_WLAN_EN |
+ MT_WLAN_FUN_CTRL_WLAN_CLK_EN);
+
+ mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
+ udelay(50);
+
+ for (i = 200; i; i--) {
+ val = mt76_rr(dev, MT_CMB_CTRL);
+ if (val & MT_CMB_CTRL_XTAL_RDY && val & MT_CMB_CTRL_PLL_LD)
+ break;
+
+ udelay(50);
+ }
+
+ if (!i)
+ dev_err(dev->mt76.dev, "Error: PLL and XTAL check failed!\n");
+}
+
void mt76x2_set_tx_ackto(struct mt76x2_dev *dev)
{
u8 ackto, sifs, slottime = dev->slottime;
@@ -543,23 +639,21 @@ int mt76x2_init_hardware(struct mt76x2_dev *dev)
static const u16 beacon_offsets[16] = {
/* 1024 byte per beacon */
0xc000,
+ 0xc200,
0xc400,
+ 0xc600,
0xc800,
+ 0xca00,
0xcc00,
+ 0xce00,
0xd000,
+ 0xd200,
0xd400,
+ 0xd600,
0xd800,
+ 0xda00,
0xdc00,
-
- /* BSS idx 8-15 not used for beacons */
- 0xc000,
- 0xc000,
- 0xc000,
- 0xc000,
- 0xc000,
- 0xc000,
- 0xc000,
- 0xc000,
+ 0xde00,
};
u32 val;
int ret;
@@ -581,24 +675,28 @@ int mt76x2_init_hardware(struct mt76x2_dev *dev)
mt76_wr(dev, MT_WPDMA_GLO_CFG, val);
mt76x2_reset_wlan(dev, true);
- mt76x2_power_on(dev);
+ mt76x2_power_on_76x0(dev);
- ret = mt76x2_eeprom_init(dev);
+ /* Note: at this point the vendor driver does write some things to MT_CMB_CTRL; we aren't. */
+
+ /* Note: at this point the vendor driver does write some things to MT_CMB_CTRL; we aren't. */
+
+ /* ret = mt76x2_eeprom_init(dev);
if (ret)
- return ret;
+ return ret; */
- ret = mt76x2_mac_reset(dev, true);
+ ret = mt76x0_mac_reset(dev);
if (ret)
return ret;
dev->rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG);
- ret = mt76x2_dma_init(dev);
+ //ret = mt76x0_dma_init(dev); XXX MISSING BUT NEEDED
if (ret)
return ret;
set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
- ret = mt76x2_mac_start(dev);
+ ret = mt76x0_mac_start(dev);
if (ret)
return ret;
@@ -47,6 +47,7 @@
#define MT_WLAN_FUN_CTRL_WLAN_RESET_RF BIT(2)
#define MT_WLAN_FUN_CTRL_WLAN_RESET BIT(3) /* MT76x0 */
+#define MT_RXQ_STA 0x0430
#define MT_WLAN_FUN_CTRL_CSR_F20M_CKEN BIT(3) /* MT76x2 */
#define MT_WLAN_FUN_CTRL_PCIE_CLK_REQ BIT(4)