-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
wifi: Add support for specific WiFi 6E/7 USB and PCI devices
This commit adds support for various WiFi 6E and WiFi 7 devices from major manufacturers. The implementation includes: 1. Device Support: - MediaTek: MT7921, MT7922 (PCI), MT7925 (USB) - Realtek: RTL8852BE, RTL8852AE (PCI), RTL8852BU (USB) - Intel: AX211, AX411, BE200 (PCI) - Qualcomm: QCA6490, QCA6750, QCN9074 (PCI) - Broadcom: BCM4389, BCM4398 (PCI)
- Loading branch information
Showing
4 changed files
with
618 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,232 @@ | ||
#include <linux/module.h> | ||
#include <linux/pci.h> | ||
#include <linux/firmware.h> | ||
#include "../supported_devices.h" | ||
#include "../../include/core/wifi67.h" | ||
|
||
/* PCI device private structure */ | ||
struct managh_pci_dev { | ||
struct pci_dev *pdev; | ||
struct wifi67_priv *wifi_priv; | ||
void __iomem *mmio; | ||
|
||
bool initialized; | ||
bool suspended; | ||
|
||
spinlock_t lock; | ||
|
||
/* Device-specific information */ | ||
const struct managh_device_info *dev_info; | ||
}; | ||
|
||
static int managh_pci_probe(struct pci_dev *pdev, | ||
const struct pci_device_id *id) | ||
{ | ||
struct managh_pci_dev *pci_dev; | ||
struct wifi67_priv *wifi_priv; | ||
const struct managh_device_info *dev_info = NULL; | ||
int i, ret; | ||
|
||
/* Find device info */ | ||
for (i = 0; i < ARRAY_SIZE(supported_devices); i++) { | ||
if (supported_devices[i].vendor_id == pdev->vendor && | ||
supported_devices[i].device_id == pdev->device && | ||
!supported_devices[i].is_usb) { | ||
dev_info = &supported_devices[i]; | ||
break; | ||
} | ||
} | ||
|
||
if (!dev_info) { | ||
pr_err("Unsupported PCI device %04x:%04x\n", | ||
pdev->vendor, pdev->device); | ||
return -ENODEV; | ||
} | ||
|
||
/* Allocate PCI device structure */ | ||
pci_dev = kzalloc(sizeof(*pci_dev), GFP_KERNEL); | ||
if (!pci_dev) | ||
return -ENOMEM; | ||
|
||
/* Initialize PCI device */ | ||
pci_dev->pdev = pdev; | ||
pci_dev->dev_info = dev_info; | ||
spin_lock_init(&pci_dev->lock); | ||
|
||
/* Enable PCI device */ | ||
ret = pci_enable_device(pdev); | ||
if (ret) | ||
goto err_free_dev; | ||
|
||
/* Request PCI regions */ | ||
ret = pci_request_regions(pdev, "managh_wifi"); | ||
if (ret) | ||
goto err_disable_device; | ||
|
||
/* Set DMA mask */ | ||
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); | ||
if (ret) { | ||
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); | ||
if (ret) | ||
goto err_release_regions; | ||
} | ||
|
||
/* Map BAR0 */ | ||
pci_dev->mmio = pci_iomap(pdev, 0, 0); | ||
if (!pci_dev->mmio) { | ||
ret = -EIO; | ||
goto err_release_regions; | ||
} | ||
|
||
/* Enable bus mastering */ | ||
pci_set_master(pdev); | ||
|
||
/* Initialize WiFi core */ | ||
wifi_priv = wifi67_core_alloc(); | ||
if (!wifi_priv) { | ||
ret = -ENOMEM; | ||
goto err_iounmap; | ||
} | ||
|
||
pci_dev->wifi_priv = wifi_priv; | ||
wifi_priv->dev = &pdev->dev; | ||
wifi_priv->mmio = pci_dev->mmio; | ||
|
||
/* Set device capabilities */ | ||
wifi_priv->features.has_6ghz = !!(dev_info->capabilities & DEVICE_CAP_WIFI_6E); | ||
wifi_priv->features.has_7ghz = !!(dev_info->capabilities & DEVICE_CAP_WIFI_7); | ||
wifi_priv->features.max_spatial_streams = dev_info->max_spatial_streams; | ||
wifi_priv->features.max_bandwidth = dev_info->max_bandwidth_mhz; | ||
|
||
/* Initialize WiFi core */ | ||
ret = wifi67_core_init(wifi_priv); | ||
if (ret) | ||
goto err_free_wifi; | ||
|
||
/* Set driver data */ | ||
pci_set_drvdata(pdev, pci_dev); | ||
pci_dev->initialized = true; | ||
|
||
pr_info("Initialized %s PCI WiFi device\n", dev_info->name); | ||
return 0; | ||
|
||
err_free_wifi: | ||
wifi67_core_free(wifi_priv); | ||
err_iounmap: | ||
pci_iounmap(pdev, pci_dev->mmio); | ||
err_release_regions: | ||
pci_release_regions(pdev); | ||
err_disable_device: | ||
pci_disable_device(pdev); | ||
err_free_dev: | ||
kfree(pci_dev); | ||
return ret; | ||
} | ||
|
||
static void managh_pci_remove(struct pci_dev *pdev) | ||
{ | ||
struct managh_pci_dev *pci_dev = pci_get_drvdata(pdev); | ||
|
||
if (!pci_dev) | ||
return; | ||
|
||
/* Cleanup WiFi core */ | ||
if (pci_dev->wifi_priv) { | ||
wifi67_core_deinit(pci_dev->wifi_priv); | ||
wifi67_core_free(pci_dev->wifi_priv); | ||
} | ||
|
||
/* Cleanup PCI device */ | ||
pci_iounmap(pdev, pci_dev->mmio); | ||
pci_release_regions(pdev); | ||
pci_disable_device(pdev); | ||
pci_set_drvdata(pdev, NULL); | ||
kfree(pci_dev); | ||
|
||
pr_info("PCI WiFi device removed\n"); | ||
} | ||
|
||
static int managh_pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
{ | ||
struct managh_pci_dev *pci_dev = pci_get_drvdata(pdev); | ||
|
||
if (!pci_dev) | ||
return 0; | ||
|
||
wifi67_core_suspend(pci_dev->wifi_priv); | ||
pci_save_state(pdev); | ||
pci_disable_device(pdev); | ||
pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
pci_dev->suspended = true; | ||
|
||
return 0; | ||
} | ||
|
||
static int managh_pci_resume(struct pci_dev *pdev) | ||
{ | ||
struct managh_pci_dev *pci_dev = pci_get_drvdata(pdev); | ||
int ret; | ||
|
||
if (!pci_dev) | ||
return 0; | ||
|
||
pci_set_power_state(pdev, PCI_D0); | ||
pci_restore_state(pdev); | ||
|
||
ret = pci_enable_device(pdev); | ||
if (ret) | ||
return ret; | ||
|
||
pci_set_master(pdev); | ||
|
||
ret = wifi67_core_resume(pci_dev->wifi_priv); | ||
if (ret) | ||
return ret; | ||
|
||
pci_dev->suspended = false; | ||
return 0; | ||
} | ||
|
||
/* PCI device ID table */ | ||
static const struct pci_device_id managh_pci_ids[] = { | ||
/* MediaTek */ | ||
{ PCI_DEVICE(MT_VENDOR_ID, MT7921_PCI_DEVICE_ID) }, | ||
{ PCI_DEVICE(MT_VENDOR_ID, MT7922_PCI_DEVICE_ID) }, | ||
|
||
/* Realtek */ | ||
{ PCI_DEVICE(RTK_VENDOR_ID, RTL8852BE_DEVICE_ID) }, | ||
{ PCI_DEVICE(RTK_VENDOR_ID, RTL8852AE_DEVICE_ID) }, | ||
|
||
/* Intel */ | ||
{ PCI_DEVICE(INTEL_VENDOR_ID, AX211_DEVICE_ID) }, | ||
{ PCI_DEVICE(INTEL_VENDOR_ID, AX411_DEVICE_ID) }, | ||
{ PCI_DEVICE(INTEL_VENDOR_ID, BE200_DEVICE_ID) }, | ||
|
||
/* Qualcomm */ | ||
{ PCI_DEVICE(QCA_VENDOR_ID, QCA6490_DEVICE_ID) }, | ||
{ PCI_DEVICE(QCA_VENDOR_ID, QCA6750_DEVICE_ID) }, | ||
{ PCI_DEVICE(QCA_VENDOR_ID, QCN9074_DEVICE_ID) }, | ||
|
||
/* Broadcom */ | ||
{ PCI_DEVICE(BCM_VENDOR_ID, BCM4389_DEVICE_ID) }, | ||
{ PCI_DEVICE(BCM_VENDOR_ID, BCM4398_DEVICE_ID) }, | ||
|
||
{ } | ||
}; | ||
MODULE_DEVICE_TABLE(pci, managh_pci_ids); | ||
|
||
/* PCI driver structure */ | ||
static struct pci_driver managh_pci_driver = { | ||
.name = "managh_wifi_pci", | ||
.id_table = managh_pci_ids, | ||
.probe = managh_pci_probe, | ||
.remove = managh_pci_remove, | ||
.suspend = managh_pci_suspend, | ||
.resume = managh_pci_resume, | ||
}; | ||
|
||
module_pci_driver(managh_pci_driver); | ||
|
||
MODULE_AUTHOR("Your Name"); | ||
MODULE_DESCRIPTION("Managh WiFi PCI Driver"); | ||
MODULE_LICENSE("GPL"); |
Oops, something went wrong.