16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC
26c92544dSBjoern A. Zeeb /* Copyright (C) 2019 MediaTek Inc.
36c92544dSBjoern A. Zeeb *
46c92544dSBjoern A. Zeeb * Author: Roy Luo <royluo@google.com>
56c92544dSBjoern A. Zeeb * Ryder Lee <ryder.lee@mediatek.com>
66c92544dSBjoern A. Zeeb * Felix Fietkau <nbd@nbd.name>
76c92544dSBjoern A. Zeeb * Lorenzo Bianconi <lorenzo@kernel.org>
86c92544dSBjoern A. Zeeb */
96c92544dSBjoern A. Zeeb
106c92544dSBjoern A. Zeeb #include <linux/etherdevice.h>
1177285868SBjoern A. Zeeb #if defined(__FreeBSD__)
1277285868SBjoern A. Zeeb #include <linux/delay.h>
1377285868SBjoern A. Zeeb #endif
146c92544dSBjoern A. Zeeb #include "mt7615.h"
156c92544dSBjoern A. Zeeb #include "mac.h"
166c92544dSBjoern A. Zeeb #include "eeprom.h"
176c92544dSBjoern A. Zeeb
mt7615_pci_init_work(struct work_struct * work)186c92544dSBjoern A. Zeeb static void mt7615_pci_init_work(struct work_struct *work)
196c92544dSBjoern A. Zeeb {
206c92544dSBjoern A. Zeeb struct mt7615_dev *dev = container_of(work, struct mt7615_dev,
216c92544dSBjoern A. Zeeb mcu_work);
226c92544dSBjoern A. Zeeb int i, ret;
236c92544dSBjoern A. Zeeb
246c92544dSBjoern A. Zeeb ret = mt7615_mcu_init(dev);
256c92544dSBjoern A. Zeeb for (i = 0; (ret == -EAGAIN) && (i < 10); i++) {
266c92544dSBjoern A. Zeeb msleep(200);
276c92544dSBjoern A. Zeeb ret = mt7615_mcu_init(dev);
286c92544dSBjoern A. Zeeb }
296c92544dSBjoern A. Zeeb
306c92544dSBjoern A. Zeeb if (ret)
316c92544dSBjoern A. Zeeb return;
326c92544dSBjoern A. Zeeb
336c92544dSBjoern A. Zeeb mt7615_init_work(dev);
346c92544dSBjoern A. Zeeb }
356c92544dSBjoern A. Zeeb
mt7615_init_hardware(struct mt7615_dev * dev)366c92544dSBjoern A. Zeeb static int mt7615_init_hardware(struct mt7615_dev *dev)
376c92544dSBjoern A. Zeeb {
386c92544dSBjoern A. Zeeb u32 addr = mt7615_reg_map(dev, MT_EFUSE_BASE);
396c92544dSBjoern A. Zeeb int ret, idx;
406c92544dSBjoern A. Zeeb
416c92544dSBjoern A. Zeeb mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
426c92544dSBjoern A. Zeeb
436c92544dSBjoern A. Zeeb INIT_WORK(&dev->mcu_work, mt7615_pci_init_work);
446c92544dSBjoern A. Zeeb ret = mt7615_eeprom_init(dev, addr);
456c92544dSBjoern A. Zeeb if (ret < 0)
466c92544dSBjoern A. Zeeb return ret;
476c92544dSBjoern A. Zeeb
486c92544dSBjoern A. Zeeb if (is_mt7663(&dev->mt76)) {
496c92544dSBjoern A. Zeeb /* Reset RGU */
506c92544dSBjoern A. Zeeb mt76_clear(dev, MT_MCU_CIRQ_IRQ_SEL(4), BIT(1));
516c92544dSBjoern A. Zeeb mt76_set(dev, MT_MCU_CIRQ_IRQ_SEL(4), BIT(1));
526c92544dSBjoern A. Zeeb }
536c92544dSBjoern A. Zeeb
546c92544dSBjoern A. Zeeb ret = mt7615_dma_init(dev);
556c92544dSBjoern A. Zeeb if (ret)
566c92544dSBjoern A. Zeeb return ret;
576c92544dSBjoern A. Zeeb
586c92544dSBjoern A. Zeeb set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
596c92544dSBjoern A. Zeeb
606c92544dSBjoern A. Zeeb /* Beacon and mgmt frames should occupy wcid 0 */
616c92544dSBjoern A. Zeeb idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7615_WTBL_STA - 1);
626c92544dSBjoern A. Zeeb if (idx)
636c92544dSBjoern A. Zeeb return -ENOSPC;
646c92544dSBjoern A. Zeeb
656c92544dSBjoern A. Zeeb dev->mt76.global_wcid.idx = idx;
666c92544dSBjoern A. Zeeb dev->mt76.global_wcid.hw_key_idx = -1;
676c92544dSBjoern A. Zeeb rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid);
686c92544dSBjoern A. Zeeb
696c92544dSBjoern A. Zeeb return 0;
706c92544dSBjoern A. Zeeb }
716c92544dSBjoern A. Zeeb
mt7615_register_device(struct mt7615_dev * dev)726c92544dSBjoern A. Zeeb int mt7615_register_device(struct mt7615_dev *dev)
736c92544dSBjoern A. Zeeb {
746c92544dSBjoern A. Zeeb int ret;
756c92544dSBjoern A. Zeeb
766c92544dSBjoern A. Zeeb mt7615_init_device(dev);
776c92544dSBjoern A. Zeeb INIT_WORK(&dev->reset_work, mt7615_mac_reset_work);
786c92544dSBjoern A. Zeeb
796c92544dSBjoern A. Zeeb /* init led callbacks */
806c92544dSBjoern A. Zeeb if (IS_ENABLED(CONFIG_MT76_LEDS)) {
81cbb3ec25SBjoern A. Zeeb dev->mphy.leds.cdev.brightness_set = mt7615_led_set_brightness;
82cbb3ec25SBjoern A. Zeeb dev->mphy.leds.cdev.blink_set = mt7615_led_set_blink;
836c92544dSBjoern A. Zeeb }
846c92544dSBjoern A. Zeeb
856c92544dSBjoern A. Zeeb ret = mt7622_wmac_init(dev);
866c92544dSBjoern A. Zeeb if (ret)
876c92544dSBjoern A. Zeeb return ret;
886c92544dSBjoern A. Zeeb
896c92544dSBjoern A. Zeeb ret = mt7615_init_hardware(dev);
906c92544dSBjoern A. Zeeb if (ret)
916c92544dSBjoern A. Zeeb return ret;
926c92544dSBjoern A. Zeeb
936c92544dSBjoern A. Zeeb ret = mt76_register_device(&dev->mt76, true, mt76_rates,
946c92544dSBjoern A. Zeeb ARRAY_SIZE(mt76_rates));
956c92544dSBjoern A. Zeeb if (ret)
966c92544dSBjoern A. Zeeb return ret;
976c92544dSBjoern A. Zeeb
9877285868SBjoern A. Zeeb #if defined(__linux__)
996c92544dSBjoern A. Zeeb ret = mt7615_thermal_init(dev);
1006c92544dSBjoern A. Zeeb if (ret)
1016c92544dSBjoern A. Zeeb return ret;
10277285868SBjoern A. Zeeb #endif
1036c92544dSBjoern A. Zeeb
1046c92544dSBjoern A. Zeeb ieee80211_queue_work(mt76_hw(dev), &dev->mcu_work);
1056c92544dSBjoern A. Zeeb mt7615_init_txpower(dev, &dev->mphy.sband_2g.sband);
1066c92544dSBjoern A. Zeeb mt7615_init_txpower(dev, &dev->mphy.sband_5g.sband);
1076c92544dSBjoern A. Zeeb
1086c92544dSBjoern A. Zeeb if (dev->dbdc_support) {
1096c92544dSBjoern A. Zeeb ret = mt7615_register_ext_phy(dev);
1106c92544dSBjoern A. Zeeb if (ret)
1116c92544dSBjoern A. Zeeb return ret;
1126c92544dSBjoern A. Zeeb }
1136c92544dSBjoern A. Zeeb
114*8ba4d145SBjoern A. Zeeb #if defined(CONFIG_MT7615_DEBUGFS)
1156c92544dSBjoern A. Zeeb return mt7615_init_debugfs(dev);
116*8ba4d145SBjoern A. Zeeb #else
117*8ba4d145SBjoern A. Zeeb return 0;
118*8ba4d145SBjoern A. Zeeb #endif
1196c92544dSBjoern A. Zeeb }
1206c92544dSBjoern A. Zeeb
mt7615_unregister_device(struct mt7615_dev * dev)1216c92544dSBjoern A. Zeeb void mt7615_unregister_device(struct mt7615_dev *dev)
1226c92544dSBjoern A. Zeeb {
1236c92544dSBjoern A. Zeeb bool mcu_running;
1246c92544dSBjoern A. Zeeb
1256c92544dSBjoern A. Zeeb mcu_running = mt7615_wait_for_mcu_init(dev);
1266c92544dSBjoern A. Zeeb
1276c92544dSBjoern A. Zeeb mt7615_unregister_ext_phy(dev);
1286c92544dSBjoern A. Zeeb mt76_unregister_device(&dev->mt76);
1296c92544dSBjoern A. Zeeb if (mcu_running)
1306c92544dSBjoern A. Zeeb mt7615_mcu_exit(dev);
1316c92544dSBjoern A. Zeeb
1326c92544dSBjoern A. Zeeb mt7615_tx_token_put(dev);
1336c92544dSBjoern A. Zeeb mt7615_dma_cleanup(dev);
134cbb3ec25SBjoern A. Zeeb tasklet_disable(&dev->mt76.irq_tasklet);
1356c92544dSBjoern A. Zeeb
1366c92544dSBjoern A. Zeeb mt76_free_device(&dev->mt76);
1376c92544dSBjoern A. Zeeb }
138