Path: blob/main/sys/contrib/dev/mediatek/mt76/mt76x0/pci.c
48525 views
// SPDX-License-Identifier: ISC1/*2* Copyright (C) 2016 Felix Fietkau <[email protected]>3*/45#include <linux/kernel.h>6#include <linux/module.h>7#include <linux/pci.h>89#include "mt76x0.h"10#include "mcu.h"1112static int mt76x0e_start(struct ieee80211_hw *hw)13{14struct mt76x02_dev *dev = hw->priv;1516mt76x02_mac_start(dev);17mt76x0_phy_calibrate(dev, true);18ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mphy.mac_work,19MT_MAC_WORK_INTERVAL);20ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,21MT_CALIBRATE_INTERVAL);22set_bit(MT76_STATE_RUNNING, &dev->mphy.state);2324return 0;25}2627static void mt76x0e_stop_hw(struct mt76x02_dev *dev)28{29cancel_delayed_work_sync(&dev->cal_work);30cancel_delayed_work_sync(&dev->mphy.mac_work);31clear_bit(MT76_RESTART, &dev->mphy.state);3233if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY,340, 1000))35dev_warn(dev->mt76.dev, "TX DMA did not stop\n");36mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN);3738mt76x0_mac_stop(dev);3940if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_RX_DMA_BUSY,410, 1000))42dev_warn(dev->mt76.dev, "TX DMA did not stop\n");43mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_RX_DMA_EN);44}4546static void mt76x0e_stop(struct ieee80211_hw *hw, bool suspend)47{48struct mt76x02_dev *dev = hw->priv;4950clear_bit(MT76_STATE_RUNNING, &dev->mphy.state);51mt76x0e_stop_hw(dev);52}5354static void55mt76x0e_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,56u32 queues, bool drop)57{58}5960static const struct ieee80211_ops mt76x0e_ops = {61.add_chanctx = ieee80211_emulate_add_chanctx,62.remove_chanctx = ieee80211_emulate_remove_chanctx,63.change_chanctx = ieee80211_emulate_change_chanctx,64.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,65.tx = mt76x02_tx,66.start = mt76x0e_start,67.stop = mt76x0e_stop,68.add_interface = mt76x02_add_interface,69.remove_interface = mt76x02_remove_interface,70.config = mt76x0_config,71.configure_filter = mt76x02_configure_filter,72.bss_info_changed = mt76x02_bss_info_changed,73.sta_state = mt76_sta_state,74.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,75.set_key = mt76x02_set_key,76.conf_tx = mt76x02_conf_tx,77.sw_scan_start = mt76_sw_scan,78.sw_scan_complete = mt76x02_sw_scan_complete,79.ampdu_action = mt76x02_ampdu_action,80.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,81.wake_tx_queue = mt76_wake_tx_queue,82.get_survey = mt76_get_survey,83.get_txpower = mt76_get_txpower,84.flush = mt76x0e_flush,85.set_tim = mt76_set_tim,86.release_buffered_frames = mt76_release_buffered_frames,87.set_coverage_class = mt76x02_set_coverage_class,88.set_rts_threshold = mt76x02_set_rts_threshold,89.get_antenna = mt76_get_antenna,90.reconfig_complete = mt76x02_reconfig_complete,91.set_sar_specs = mt76x0_set_sar_specs,92};9394static int mt76x0e_init_hardware(struct mt76x02_dev *dev, bool resume)95{96int err;9798mt76x0_chip_onoff(dev, true, false);99if (!mt76x02_wait_for_mac(&dev->mt76))100return -ETIMEDOUT;101102mt76x02_dma_disable(dev);103err = mt76x0e_mcu_init(dev);104if (err < 0)105return err;106107if (!resume) {108err = mt76x02_dma_init(dev);109if (err < 0)110return err;111}112113err = mt76x0_init_hardware(dev);114if (err < 0)115return err;116117mt76x02e_init_beacon_config(dev);118119if (mt76_chip(&dev->mt76) == 0x7610) {120u16 val;121122mt76_clear(dev, MT_COEXCFG0, BIT(0));123124val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0);125if (!(val & MT_EE_NIC_CONF_0_PA_IO_CURRENT))126mt76_set(dev, MT_XO_CTRL7, 0xc03);127}128129mt76_clear(dev, 0x110, BIT(9));130mt76_set(dev, MT_MAX_LEN_CFG, BIT(13));131132return 0;133}134135static int mt76x0e_register_device(struct mt76x02_dev *dev)136{137int err;138139err = mt76x0e_init_hardware(dev, false);140if (err < 0)141return err;142143err = mt76x0_register_device(dev);144if (err < 0)145return err;146147set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);148149return 0;150}151152static int153mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)154{155static const struct mt76_driver_ops drv_ops = {156.txwi_size = sizeof(struct mt76x02_txwi),157.drv_flags = MT_DRV_TX_ALIGNED4_SKBS |158MT_DRV_SW_RX_AIRTIME |159MT_DRV_IGNORE_TXS_FAILED,160.survey_flags = SURVEY_INFO_TIME_TX,161.update_survey = mt76x02_update_channel,162.set_channel = mt76x0_set_channel,163.tx_prepare_skb = mt76x02_tx_prepare_skb,164.tx_complete_skb = mt76x02_tx_complete_skb,165.rx_skb = mt76x02_queue_rx_skb,166.rx_poll_complete = mt76x02_rx_poll_complete,167.sta_ps = mt76x02_sta_ps,168.sta_add = mt76x02_sta_add,169.sta_remove = mt76x02_sta_remove,170};171struct mt76x02_dev *dev;172struct mt76_dev *mdev;173int ret;174175ret = pcim_enable_device(pdev);176if (ret)177return ret;178179ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));180if (ret)181return ret;182183pci_set_master(pdev);184185ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));186if (ret)187return ret;188189mt76_pci_disable_aspm(pdev);190191mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt76x0e_ops,192&drv_ops);193if (!mdev)194return -ENOMEM;195196dev = container_of(mdev, struct mt76x02_dev, mt76);197mutex_init(&dev->phy_mutex);198199mt76_mmio_init(mdev, pcim_iomap_table(pdev)[0]);200201mdev->rev = mt76_rr(dev, MT_ASIC_VERSION);202dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev);203204mt76_wr(dev, MT_INT_MASK_CSR, 0);205206ret = devm_request_irq(mdev->dev, pdev->irq, mt76x02_irq_handler,207IRQF_SHARED, KBUILD_MODNAME, dev);208if (ret)209goto error;210211ret = mt76x0e_register_device(dev);212if (ret < 0)213goto error;214215return 0;216217error:218mt76_free_device(&dev->mt76);219220return ret;221}222223static void mt76x0e_cleanup(struct mt76x02_dev *dev)224{225clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);226tasklet_disable(&dev->mt76.pre_tbtt_tasklet);227mt76x0_chip_onoff(dev, false, false);228mt76x0e_stop_hw(dev);229mt76_dma_cleanup(&dev->mt76);230mt76x02_mcu_cleanup(dev);231}232233static void234mt76x0e_remove(struct pci_dev *pdev)235{236struct mt76_dev *mdev = pci_get_drvdata(pdev);237struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);238239mt76_unregister_device(mdev);240mt76x0e_cleanup(dev);241mt76_free_device(mdev);242}243244#ifdef CONFIG_PM245static int mt76x0e_suspend(struct pci_dev *pdev, pm_message_t state)246{247struct mt76_dev *mdev = pci_get_drvdata(pdev);248struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);249int i;250251mt76_worker_disable(&mdev->tx_worker);252for (i = 0; i < ARRAY_SIZE(mdev->phy.q_tx); i++)253mt76_queue_tx_cleanup(dev, mdev->phy.q_tx[i], true);254for (i = 0; i < ARRAY_SIZE(mdev->q_mcu); i++)255mt76_queue_tx_cleanup(dev, mdev->q_mcu[i], true);256napi_disable(&mdev->tx_napi);257258mt76_for_each_q_rx(mdev, i)259napi_disable(&mdev->napi[i]);260261mt76x02_dma_disable(dev);262mt76x02_mcu_cleanup(dev);263mt76x0_chip_onoff(dev, false, false);264265pci_enable_wake(pdev, pci_choose_state(pdev, state), true);266pci_save_state(pdev);267268return pci_set_power_state(pdev, pci_choose_state(pdev, state));269}270271static int mt76x0e_resume(struct pci_dev *pdev)272{273struct mt76_dev *mdev = pci_get_drvdata(pdev);274struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);275int err, i;276277err = pci_set_power_state(pdev, PCI_D0);278if (err)279return err;280281pci_restore_state(pdev);282283mt76_worker_enable(&mdev->tx_worker);284285mt76_for_each_q_rx(mdev, i) {286mt76_queue_rx_reset(dev, i);287napi_enable(&mdev->napi[i]);288}289napi_enable(&mdev->tx_napi);290291local_bh_disable();292mt76_for_each_q_rx(mdev, i) {293napi_schedule(&mdev->napi[i]);294}295napi_schedule(&mdev->tx_napi);296local_bh_enable();297298return mt76x0e_init_hardware(dev, true);299}300#endif /* CONFIG_PM */301302static const struct pci_device_id mt76x0e_device_table[] = {303{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7610) },304{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7630) },305{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7650) },306{ },307};308309MODULE_DEVICE_TABLE(pci, mt76x0e_device_table);310MODULE_FIRMWARE(MT7610E_FIRMWARE);311MODULE_FIRMWARE(MT7650E_FIRMWARE);312MODULE_DESCRIPTION("MediaTek MT76x0E (PCIe) wireless driver");313MODULE_LICENSE("Dual BSD/GPL");314315static struct pci_driver mt76x0e_driver = {316.name = KBUILD_MODNAME,317.id_table = mt76x0e_device_table,318.probe = mt76x0e_probe,319.remove = mt76x0e_remove,320#ifdef CONFIG_PM321.suspend = mt76x0e_suspend,322.resume = mt76x0e_resume,323#endif /* CONFIG_PM */324};325326module_pci_driver(mt76x0e_driver);327328329