16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC
26c92544dSBjoern A. Zeeb /*
36c92544dSBjoern A. Zeeb  * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
46c92544dSBjoern A. Zeeb  */
56c92544dSBjoern A. Zeeb 
66c92544dSBjoern A. Zeeb #include <linux/delay.h>
76c92544dSBjoern A. Zeeb 
86c92544dSBjoern A. Zeeb #include "mt76x2u.h"
96c92544dSBjoern A. Zeeb #include "eeprom.h"
106c92544dSBjoern A. Zeeb #include "../mt76x02_phy.h"
116c92544dSBjoern A. Zeeb #include "../mt76x02_usb.h"
126c92544dSBjoern A. Zeeb 
mt76x2u_init_dma(struct mt76x02_dev * dev)136c92544dSBjoern A. Zeeb static void mt76x2u_init_dma(struct mt76x02_dev *dev)
146c92544dSBjoern A. Zeeb {
156c92544dSBjoern A. Zeeb 	u32 val = mt76_rr(dev, MT_VEND_ADDR(CFG, MT_USB_U3DMA_CFG));
166c92544dSBjoern A. Zeeb 
176c92544dSBjoern A. Zeeb 	val |= MT_USB_DMA_CFG_RX_DROP_OR_PAD |
186c92544dSBjoern A. Zeeb 	       MT_USB_DMA_CFG_RX_BULK_EN |
196c92544dSBjoern A. Zeeb 	       MT_USB_DMA_CFG_TX_BULK_EN;
206c92544dSBjoern A. Zeeb 
216c92544dSBjoern A. Zeeb 	/* disable AGGR_BULK_RX in order to receive one
226c92544dSBjoern A. Zeeb 	 * frame in each rx urb and avoid copies
236c92544dSBjoern A. Zeeb 	 */
246c92544dSBjoern A. Zeeb 	val &= ~MT_USB_DMA_CFG_RX_BULK_AGG_EN;
256c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_VEND_ADDR(CFG, MT_USB_U3DMA_CFG), val);
266c92544dSBjoern A. Zeeb }
276c92544dSBjoern A. Zeeb 
mt76x2u_power_on_rf_patch(struct mt76x02_dev * dev)286c92544dSBjoern A. Zeeb static void mt76x2u_power_on_rf_patch(struct mt76x02_dev *dev)
296c92544dSBjoern A. Zeeb {
306c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_VEND_ADDR(CFG, 0x130), BIT(0) | BIT(16));
316c92544dSBjoern A. Zeeb 	udelay(1);
326c92544dSBjoern A. Zeeb 
336c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_VEND_ADDR(CFG, 0x1c), 0xff);
346c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_VEND_ADDR(CFG, 0x1c), 0x30);
356c92544dSBjoern A. Zeeb 
366c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_VEND_ADDR(CFG, 0x14), 0x484f);
376c92544dSBjoern A. Zeeb 	udelay(1);
386c92544dSBjoern A. Zeeb 
396c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_VEND_ADDR(CFG, 0x130), BIT(17));
406c92544dSBjoern A. Zeeb 	usleep_range(150, 200);
416c92544dSBjoern A. Zeeb 
426c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_VEND_ADDR(CFG, 0x130), BIT(16));
436c92544dSBjoern A. Zeeb 	usleep_range(50, 100);
446c92544dSBjoern A. Zeeb 
456c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_VEND_ADDR(CFG, 0x14c), BIT(19) | BIT(20));
466c92544dSBjoern A. Zeeb }
476c92544dSBjoern A. Zeeb 
mt76x2u_power_on_rf(struct mt76x02_dev * dev,int unit)486c92544dSBjoern A. Zeeb static void mt76x2u_power_on_rf(struct mt76x02_dev *dev, int unit)
496c92544dSBjoern A. Zeeb {
506c92544dSBjoern A. Zeeb 	int shift = unit ? 8 : 0;
516c92544dSBjoern A. Zeeb 	u32 val = (BIT(1) | BIT(3) | BIT(4) | BIT(5)) << shift;
526c92544dSBjoern A. Zeeb 
536c92544dSBjoern A. Zeeb 	/* Enable RF BG */
546c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_VEND_ADDR(CFG, 0x130), BIT(0) << shift);
556c92544dSBjoern A. Zeeb 	usleep_range(10, 20);
566c92544dSBjoern A. Zeeb 
576c92544dSBjoern A. Zeeb 	/* Enable RFDIG LDO/AFE/ABB/ADDA */
586c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_VEND_ADDR(CFG, 0x130), val);
596c92544dSBjoern A. Zeeb 	usleep_range(10, 20);
606c92544dSBjoern A. Zeeb 
616c92544dSBjoern A. Zeeb 	/* Switch RFDIG power to internal LDO */
626c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_VEND_ADDR(CFG, 0x130), BIT(2) << shift);
636c92544dSBjoern A. Zeeb 	usleep_range(10, 20);
646c92544dSBjoern A. Zeeb 
656c92544dSBjoern A. Zeeb 	mt76x2u_power_on_rf_patch(dev);
666c92544dSBjoern A. Zeeb 
676c92544dSBjoern A. Zeeb 	mt76_set(dev, 0x530, 0xf);
686c92544dSBjoern A. Zeeb }
696c92544dSBjoern A. Zeeb 
mt76x2u_power_on(struct mt76x02_dev * dev)706c92544dSBjoern A. Zeeb static void mt76x2u_power_on(struct mt76x02_dev *dev)
716c92544dSBjoern A. Zeeb {
726c92544dSBjoern A. Zeeb 	u32 val;
736c92544dSBjoern A. Zeeb 
746c92544dSBjoern A. Zeeb 	/* Turn on WL MTCMOS */
756c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_VEND_ADDR(CFG, 0x148),
766c92544dSBjoern A. Zeeb 		 MT_WLAN_MTC_CTRL_MTCMOS_PWR_UP);
776c92544dSBjoern A. Zeeb 
786c92544dSBjoern A. Zeeb 	val = MT_WLAN_MTC_CTRL_STATE_UP |
796c92544dSBjoern A. Zeeb 	      MT_WLAN_MTC_CTRL_PWR_ACK |
806c92544dSBjoern A. Zeeb 	      MT_WLAN_MTC_CTRL_PWR_ACK_S;
816c92544dSBjoern A. Zeeb 
826c92544dSBjoern A. Zeeb 	mt76_poll(dev, MT_VEND_ADDR(CFG, 0x148), val, val, 1000);
836c92544dSBjoern A. Zeeb 
846c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_VEND_ADDR(CFG, 0x148), 0x7f << 16);
856c92544dSBjoern A. Zeeb 	usleep_range(10, 20);
866c92544dSBjoern A. Zeeb 
876c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_VEND_ADDR(CFG, 0x148), 0xf << 24);
886c92544dSBjoern A. Zeeb 	usleep_range(10, 20);
896c92544dSBjoern A. Zeeb 
906c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_VEND_ADDR(CFG, 0x148), 0xf << 24);
916c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_VEND_ADDR(CFG, 0x148), 0xfff);
926c92544dSBjoern A. Zeeb 
936c92544dSBjoern A. Zeeb 	/* Turn on AD/DA power down */
946c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_VEND_ADDR(CFG, 0x1204), BIT(3));
956c92544dSBjoern A. Zeeb 
966c92544dSBjoern A. Zeeb 	/* WLAN function enable */
976c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_VEND_ADDR(CFG, 0x80), BIT(0));
986c92544dSBjoern A. Zeeb 
996c92544dSBjoern A. Zeeb 	/* Release BBP software reset */
1006c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_VEND_ADDR(CFG, 0x64), BIT(18));
1016c92544dSBjoern A. Zeeb 
1026c92544dSBjoern A. Zeeb 	mt76x2u_power_on_rf(dev, 0);
1036c92544dSBjoern A. Zeeb 	mt76x2u_power_on_rf(dev, 1);
1046c92544dSBjoern A. Zeeb }
1056c92544dSBjoern A. Zeeb 
mt76x2u_init_eeprom(struct mt76x02_dev * dev)1066c92544dSBjoern A. Zeeb static int mt76x2u_init_eeprom(struct mt76x02_dev *dev)
1076c92544dSBjoern A. Zeeb {
1086c92544dSBjoern A. Zeeb 	u32 val, i;
1096c92544dSBjoern A. Zeeb 
1106c92544dSBjoern A. Zeeb 	dev->mt76.eeprom.data = devm_kzalloc(dev->mt76.dev,
1116c92544dSBjoern A. Zeeb 					     MT7612U_EEPROM_SIZE,
1126c92544dSBjoern A. Zeeb 					     GFP_KERNEL);
1136c92544dSBjoern A. Zeeb 	dev->mt76.eeprom.size = MT7612U_EEPROM_SIZE;
1146c92544dSBjoern A. Zeeb 	if (!dev->mt76.eeprom.data)
1156c92544dSBjoern A. Zeeb 		return -ENOMEM;
1166c92544dSBjoern A. Zeeb 
1176c92544dSBjoern A. Zeeb 	for (i = 0; i + 4 <= MT7612U_EEPROM_SIZE; i += 4) {
1186c92544dSBjoern A. Zeeb 		val = mt76_rr(dev, MT_VEND_ADDR(EEPROM, i));
1196c92544dSBjoern A. Zeeb 		put_unaligned_le32(val, dev->mt76.eeprom.data + i);
1206c92544dSBjoern A. Zeeb 	}
1216c92544dSBjoern A. Zeeb 
1226c92544dSBjoern A. Zeeb 	mt76x02_eeprom_parse_hw_cap(dev);
1236c92544dSBjoern A. Zeeb 	return 0;
1246c92544dSBjoern A. Zeeb }
1256c92544dSBjoern A. Zeeb 
mt76x2u_init_hardware(struct mt76x02_dev * dev)1266c92544dSBjoern A. Zeeb int mt76x2u_init_hardware(struct mt76x02_dev *dev)
1276c92544dSBjoern A. Zeeb {
1286c92544dSBjoern A. Zeeb 	int i, k, err;
1296c92544dSBjoern A. Zeeb 
1306c92544dSBjoern A. Zeeb 	mt76x2_reset_wlan(dev, true);
1316c92544dSBjoern A. Zeeb 	mt76x2u_power_on(dev);
1326c92544dSBjoern A. Zeeb 
1336c92544dSBjoern A. Zeeb 	if (!mt76x02_wait_for_mac(&dev->mt76))
1346c92544dSBjoern A. Zeeb 		return -ETIMEDOUT;
1356c92544dSBjoern A. Zeeb 
1366c92544dSBjoern A. Zeeb 	err = mt76x2u_mcu_fw_init(dev);
1376c92544dSBjoern A. Zeeb 	if (err < 0)
1386c92544dSBjoern A. Zeeb 		return err;
1396c92544dSBjoern A. Zeeb 
1406c92544dSBjoern A. Zeeb 	if (!mt76_poll_msec(dev, MT_WPDMA_GLO_CFG,
1416c92544dSBjoern A. Zeeb 			    MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
1426c92544dSBjoern A. Zeeb 			    MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 100))
1436c92544dSBjoern A. Zeeb 		return -EIO;
1446c92544dSBjoern A. Zeeb 
1456c92544dSBjoern A. Zeeb 	/* wait for asic ready after fw load. */
1466c92544dSBjoern A. Zeeb 	if (!mt76x02_wait_for_mac(&dev->mt76))
1476c92544dSBjoern A. Zeeb 		return -ETIMEDOUT;
1486c92544dSBjoern A. Zeeb 
1496c92544dSBjoern A. Zeeb 	mt76x2u_init_dma(dev);
1506c92544dSBjoern A. Zeeb 
1516c92544dSBjoern A. Zeeb 	err = mt76x2u_mcu_init(dev);
1526c92544dSBjoern A. Zeeb 	if (err < 0)
1536c92544dSBjoern A. Zeeb 		return err;
1546c92544dSBjoern A. Zeeb 
1556c92544dSBjoern A. Zeeb 	err = mt76x2u_mac_reset(dev);
1566c92544dSBjoern A. Zeeb 	if (err < 0)
1576c92544dSBjoern A. Zeeb 		return err;
1586c92544dSBjoern A. Zeeb 
1596c92544dSBjoern A. Zeeb 	mt76x02_mac_setaddr(dev, dev->mt76.eeprom.data + MT_EE_MAC_ADDR);
1606c92544dSBjoern A. Zeeb 	dev->mt76.rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG);
1616c92544dSBjoern A. Zeeb 
1626c92544dSBjoern A. Zeeb 	if (!mt76x02_wait_for_txrx_idle(&dev->mt76))
1636c92544dSBjoern A. Zeeb 		return -ETIMEDOUT;
1646c92544dSBjoern A. Zeeb 
1656c92544dSBjoern A. Zeeb 	/* reset wcid table */
1666c92544dSBjoern A. Zeeb 	for (i = 0; i < 256; i++)
1676c92544dSBjoern A. Zeeb 		mt76x02_mac_wcid_setup(dev, i, 0, NULL);
1686c92544dSBjoern A. Zeeb 
1696c92544dSBjoern A. Zeeb 	/* reset shared key table and pairwise key table */
1706c92544dSBjoern A. Zeeb 	for (i = 0; i < 16; i++) {
1716c92544dSBjoern A. Zeeb 		for (k = 0; k < 4; k++)
1726c92544dSBjoern A. Zeeb 			mt76x02_mac_shared_key_setup(dev, i, k, NULL);
1736c92544dSBjoern A. Zeeb 	}
1746c92544dSBjoern A. Zeeb 
1756c92544dSBjoern A. Zeeb 	mt76x02u_init_beacon_config(dev);
1766c92544dSBjoern A. Zeeb 
1776c92544dSBjoern A. Zeeb 	mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e);
1786c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x583f);
1796c92544dSBjoern A. Zeeb 
1806c92544dSBjoern A. Zeeb 	err = mt76x2_mcu_load_cr(dev, MT_RF_BBP_CR, 0, 0);
1816c92544dSBjoern A. Zeeb 	if (err < 0)
1826c92544dSBjoern A. Zeeb 		return err;
1836c92544dSBjoern A. Zeeb 
1846c92544dSBjoern A. Zeeb 	mt76x02_phy_set_rxpath(dev);
1856c92544dSBjoern A. Zeeb 	mt76x02_phy_set_txdac(dev);
1866c92544dSBjoern A. Zeeb 
1876c92544dSBjoern A. Zeeb 	return mt76x2u_mac_stop(dev);
1886c92544dSBjoern A. Zeeb }
1896c92544dSBjoern A. Zeeb 
mt76x2u_register_device(struct mt76x02_dev * dev)1906c92544dSBjoern A. Zeeb int mt76x2u_register_device(struct mt76x02_dev *dev)
1916c92544dSBjoern A. Zeeb {
1926c92544dSBjoern A. Zeeb 	struct ieee80211_hw *hw = mt76_hw(dev);
1936c92544dSBjoern A. Zeeb 	struct mt76_usb *usb = &dev->mt76.usb;
1946c92544dSBjoern A. Zeeb 	int err;
1956c92544dSBjoern A. Zeeb 
1966c92544dSBjoern A. Zeeb 	INIT_DELAYED_WORK(&dev->cal_work, mt76x2u_phy_calibrate);
1976c92544dSBjoern A. Zeeb 	err = mt76x02_init_device(dev);
1986c92544dSBjoern A. Zeeb 	if (err)
1996c92544dSBjoern A. Zeeb 		return err;
2006c92544dSBjoern A. Zeeb 
2016c92544dSBjoern A. Zeeb 	err = mt76x2u_init_eeprom(dev);
2026c92544dSBjoern A. Zeeb 	if (err < 0)
2036c92544dSBjoern A. Zeeb 		return err;
2046c92544dSBjoern A. Zeeb 
2056c92544dSBjoern A. Zeeb 	usb->mcu.data = devm_kmalloc(dev->mt76.dev, MCU_RESP_URB_SIZE,
2066c92544dSBjoern A. Zeeb 				     GFP_KERNEL);
2076c92544dSBjoern A. Zeeb 	if (!usb->mcu.data)
2086c92544dSBjoern A. Zeeb 		return -ENOMEM;
2096c92544dSBjoern A. Zeeb 
2106c92544dSBjoern A. Zeeb 	err = mt76u_alloc_queues(&dev->mt76);
2116c92544dSBjoern A. Zeeb 	if (err < 0)
2126c92544dSBjoern A. Zeeb 		goto fail;
2136c92544dSBjoern A. Zeeb 
2146c92544dSBjoern A. Zeeb 	err = mt76x2u_init_hardware(dev);
2156c92544dSBjoern A. Zeeb 	if (err < 0)
2166c92544dSBjoern A. Zeeb 		goto fail;
2176c92544dSBjoern A. Zeeb 
2186c92544dSBjoern A. Zeeb 	/* check hw sg support in order to enable AMSDU */
2196c92544dSBjoern A. Zeeb 	hw->max_tx_fragments = dev->mt76.usb.sg_en ? MT_TX_SG_MAX_SIZE : 1;
2206c92544dSBjoern A. Zeeb 	err = mt76_register_device(&dev->mt76, true, mt76x02_rates,
2216c92544dSBjoern A. Zeeb 				   ARRAY_SIZE(mt76x02_rates));
2226c92544dSBjoern A. Zeeb 	if (err)
2236c92544dSBjoern A. Zeeb 		goto fail;
2246c92544dSBjoern A. Zeeb 
2256c92544dSBjoern A. Zeeb 	set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
2266c92544dSBjoern A. Zeeb 
2276c92544dSBjoern A. Zeeb 	mt76x02_init_debugfs(dev);
2286c92544dSBjoern A. Zeeb 	mt76x2_init_txpower(dev, &dev->mphy.sband_2g.sband);
2296c92544dSBjoern A. Zeeb 	mt76x2_init_txpower(dev, &dev->mphy.sband_5g.sband);
2306c92544dSBjoern A. Zeeb 
2316c92544dSBjoern A. Zeeb 	return 0;
2326c92544dSBjoern A. Zeeb 
2336c92544dSBjoern A. Zeeb fail:
2346c92544dSBjoern A. Zeeb 	mt76x2u_cleanup(dev);
2356c92544dSBjoern A. Zeeb 	return err;
2366c92544dSBjoern A. Zeeb }
2376c92544dSBjoern A. Zeeb 
mt76x2u_stop_hw(struct mt76x02_dev * dev)2386c92544dSBjoern A. Zeeb void mt76x2u_stop_hw(struct mt76x02_dev *dev)
2396c92544dSBjoern A. Zeeb {
2406c92544dSBjoern A. Zeeb 	cancel_delayed_work_sync(&dev->cal_work);
2416c92544dSBjoern A. Zeeb 	cancel_delayed_work_sync(&dev->mphy.mac_work);
2426c92544dSBjoern A. Zeeb 	mt76x2u_mac_stop(dev);
2436c92544dSBjoern A. Zeeb }
2446c92544dSBjoern A. Zeeb 
mt76x2u_cleanup(struct mt76x02_dev * dev)2456c92544dSBjoern A. Zeeb void mt76x2u_cleanup(struct mt76x02_dev *dev)
2466c92544dSBjoern A. Zeeb {
2476c92544dSBjoern A. Zeeb 	mt76x02_mcu_set_radio_state(dev, false);
2486c92544dSBjoern A. Zeeb 	mt76x2u_stop_hw(dev);
2496c92544dSBjoern A. Zeeb 	mt76u_queues_deinit(&dev->mt76);
2506c92544dSBjoern A. Zeeb }
251