1 // SPDX-License-Identifier: ISC 2 /* Copyright (C) 2019 MediaTek Inc. 3 * 4 * Author: Roy Luo <royluo@google.com> 5 * Ryder Lee <ryder.lee@mediatek.com> 6 * Felix Fietkau <nbd@nbd.name> 7 * Lorenzo Bianconi <lorenzo@kernel.org> 8 */ 9 10 #include <linux/etherdevice.h> 11 #if defined(__FreeBSD__) 12 #include <linux/delay.h> 13 #endif 14 #include "mt7615.h" 15 #include "mac.h" 16 #include "eeprom.h" 17 18 static void mt7615_pci_init_work(struct work_struct *work) 19 { 20 struct mt7615_dev *dev = container_of(work, struct mt7615_dev, 21 mcu_work); 22 int i, ret; 23 24 ret = mt7615_mcu_init(dev); 25 for (i = 0; (ret == -EAGAIN) && (i < 10); i++) { 26 msleep(200); 27 ret = mt7615_mcu_init(dev); 28 } 29 30 if (ret) 31 return; 32 33 mt7615_init_work(dev); 34 } 35 36 static int mt7615_init_hardware(struct mt7615_dev *dev) 37 { 38 u32 addr = mt7615_reg_map(dev, MT_EFUSE_BASE); 39 int ret, idx; 40 41 mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); 42 43 INIT_WORK(&dev->mcu_work, mt7615_pci_init_work); 44 ret = mt7615_eeprom_init(dev, addr); 45 if (ret < 0) 46 return ret; 47 48 if (is_mt7663(&dev->mt76)) { 49 /* Reset RGU */ 50 mt76_clear(dev, MT_MCU_CIRQ_IRQ_SEL(4), BIT(1)); 51 mt76_set(dev, MT_MCU_CIRQ_IRQ_SEL(4), BIT(1)); 52 } 53 54 ret = mt7615_dma_init(dev); 55 if (ret) 56 return ret; 57 58 set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); 59 60 /* Beacon and mgmt frames should occupy wcid 0 */ 61 idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7615_WTBL_STA - 1); 62 if (idx) 63 return -ENOSPC; 64 65 dev->mt76.global_wcid.idx = idx; 66 dev->mt76.global_wcid.hw_key_idx = -1; 67 rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid); 68 69 return 0; 70 } 71 72 int mt7615_register_device(struct mt7615_dev *dev) 73 { 74 int ret; 75 76 mt7615_init_device(dev); 77 INIT_WORK(&dev->reset_work, mt7615_mac_reset_work); 78 79 /* init led callbacks */ 80 if (IS_ENABLED(CONFIG_MT76_LEDS)) { 81 dev->mphy.leds.cdev.brightness_set = mt7615_led_set_brightness; 82 dev->mphy.leds.cdev.blink_set = mt7615_led_set_blink; 83 } 84 85 ret = mt7622_wmac_init(dev); 86 if (ret) 87 return ret; 88 89 ret = mt7615_init_hardware(dev); 90 if (ret) 91 return ret; 92 93 ret = mt76_register_device(&dev->mt76, true, mt76_rates, 94 ARRAY_SIZE(mt76_rates)); 95 if (ret) 96 return ret; 97 98 #if defined(__linux__) 99 ret = mt7615_thermal_init(dev); 100 if (ret) 101 return ret; 102 #endif 103 104 ieee80211_queue_work(mt76_hw(dev), &dev->mcu_work); 105 mt7615_init_txpower(dev, &dev->mphy.sband_2g.sband); 106 mt7615_init_txpower(dev, &dev->mphy.sband_5g.sband); 107 108 if (dev->dbdc_support) { 109 ret = mt7615_register_ext_phy(dev); 110 if (ret) 111 return ret; 112 } 113 114 return mt7615_init_debugfs(dev); 115 } 116 117 void mt7615_unregister_device(struct mt7615_dev *dev) 118 { 119 bool mcu_running; 120 121 mcu_running = mt7615_wait_for_mcu_init(dev); 122 123 mt7615_unregister_ext_phy(dev); 124 mt76_unregister_device(&dev->mt76); 125 if (mcu_running) 126 mt7615_mcu_exit(dev); 127 128 mt7615_tx_token_put(dev); 129 mt7615_dma_cleanup(dev); 130 tasklet_disable(&dev->mt76.irq_tasklet); 131 132 mt76_free_device(&dev->mt76); 133 } 134