wifi: mt76: mt7921: fix suspend issue on MediaTek COB platform
authorMichael Lo <michael.lo@mediatek.com>
Wed, 7 Feb 2024 01:39:45 +0000 (09:39 +0800)
committerFelix Fietkau <nbd@nbd.name>
Thu, 22 Feb 2024 08:55:19 +0000 (09:55 +0100)
MediaTek's controller driver on COB platform (e.g. MT8188) is
capable of controlling power supplies and reset pin of a component
(e.g. a WIFI chip) in power-on and power-off process.

Due to this optional feature, mt76 need to inform controller
that mt76 need to keep power during suspend. Otherwise WIFI will be
powered off when system enters suspend process.

The "wakeup-source" property was used for the device that need
this to go into suspend mode so that mt76 suspend handler doesn't
fail and the system is able to enter into a suspend state.

An example:
wifi: mt7921@0 {
wifi0{
reg = <0x0000 0 0 0 0>;
wakeup-source;
};
};

Signed-off-by: Michael Lo <michael.lo@mediatek.com>
Signed-off-by: Ming Yen Hsieh <MingYen.Hsieh@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7921/pci.c

index f85e7c90dd25f19a4e6ae7659c649b6e388d8f23..cda853e86676c74eddf35638f84a332aed96aa25 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/of.h>
 
 #include "mt7921.h"
 #include "../mt76_connac2_mac.h"
@@ -369,6 +370,9 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
        if (ret)
                goto err_free_irq;
 
+       if (of_property_read_bool(dev->mt76.dev->of_node, "wakeup-source"))
+               device_init_wakeup(dev->mt76.dev, true);
+
        return 0;
 
 err_free_irq:
@@ -386,6 +390,9 @@ static void mt7921_pci_remove(struct pci_dev *pdev)
        struct mt76_dev *mdev = pci_get_drvdata(pdev);
        struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
 
+       if (of_property_read_bool(dev->mt76.dev->of_node, "wakeup-source"))
+               device_init_wakeup(dev->mt76.dev, false);
+
        mt7921e_unregister_device(dev);
        set_bit(MT76_REMOVED, &mdev->phy.state);
        devm_free_irq(&pdev->dev, pdev->irq, dev);