wifi: mt76: mt7921e: add LED control support
authorHao Zhang <hao.zhang@mediatek.com>
Thu, 11 Apr 2024 05:41:35 +0000 (13:41 +0800)
committerFelix Fietkau <nbd@nbd.name>
Thu, 2 May 2024 10:47:04 +0000 (12:47 +0200)
Introduce wifi LED switch control, add flow to Control a wifi
gpio pin based on the status of WIFI radio, if the pin is connected
to an LED, the LED will indicate the status of the WiFi radio.

Signed-off-by: Hao Zhang <hao.zhang@mediatek.com>
Co-developed-by: Quan Zhou <quan.zhou@mediatek.com>
Signed-off-by: Quan Zhou <quan.zhou@mediatek.com>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
drivers/net/wireless/mediatek/mt76/mt7921/main.c
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
drivers/net/wireless/mediatek/mt76/mt7921/pci.c

index 01a65d41b86ed8ad536480145ff1970307a9e3ca..6873ce14d299ddc2905fddc780c21b546fce4cd9 100644 (file)
@@ -1190,6 +1190,7 @@ enum {
        MCU_EXT_CMD_EFUSE_ACCESS = 0x01,
        MCU_EXT_CMD_RF_REG_ACCESS = 0x02,
        MCU_EXT_CMD_RF_TEST = 0x04,
+       MCU_EXT_CMD_ID_RADIO_ON_OFF_CTRL = 0x05,
        MCU_EXT_CMD_PM_STATE_CTRL = 0x07,
        MCU_EXT_CMD_CHANNEL_SWITCH = 0x08,
        MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11,
index afcda7c481e08244e315754c09faa04fd62c034a..3e3ad3518d85f99f6d4588f25b61cfb2d32c002d 100644 (file)
@@ -242,6 +242,15 @@ int __mt7921_start(struct mt792x_phy *phy)
 
        ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
                                     MT792x_WATCHDOG_TIME);
+       if (mt76_is_mmio(mphy->dev)) {
+               err = mt7921_mcu_radio_led_ctrl(phy->dev, EXT_CMD_RADIO_LED_CTRL_ENABLE);
+               if (err)
+                       return err;
+
+               err = mt7921_mcu_radio_led_ctrl(phy->dev, EXT_CMD_RADIO_ON_LED);
+               if (err)
+                       return err;
+       }
 
        return 0;
 }
@@ -259,6 +268,22 @@ static int mt7921_start(struct ieee80211_hw *hw)
        return err;
 }
 
+static void mt7921_stop(struct ieee80211_hw *hw)
+{
+       struct mt792x_dev *dev = mt792x_hw_dev(hw);
+       int err = 0;
+
+       if (mt76_is_mmio(&dev->mt76)) {
+               mt792x_mutex_acquire(dev);
+               err = mt7921_mcu_radio_led_ctrl(dev, EXT_CMD_RADIO_OFF_LED);
+               mt792x_mutex_release(dev);
+               if (err)
+                       return;
+       }
+
+       mt792x_stop(hw);
+}
+
 static int
 mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
@@ -1377,7 +1402,7 @@ static void mt7921_mgd_complete_tx(struct ieee80211_hw *hw,
 const struct ieee80211_ops mt7921_ops = {
        .tx = mt792x_tx,
        .start = mt7921_start,
-       .stop = mt792x_stop,
+       .stop = mt7921_stop,
        .add_interface = mt7921_add_interface,
        .remove_interface = mt792x_remove_interface,
        .config = mt7921_config,
index f0b89b03083abd03747684b67f61e84fbef81794..bdd8b5f19b241940987e7ea85c343a2b19297819 100644 (file)
@@ -646,6 +646,20 @@ int mt7921_run_firmware(struct mt792x_dev *dev)
 }
 EXPORT_SYMBOL_GPL(mt7921_run_firmware);
 
+int mt7921_mcu_radio_led_ctrl(struct mt792x_dev *dev, u8 value)
+{
+       struct {
+               u8 ctrlid;
+               u8 rsv[3];
+       } __packed req = {
+               .ctrlid = value,
+       };
+
+       return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ID_RADIO_ON_OFF_CTRL),
+                               &req, sizeof(req), false);
+}
+EXPORT_SYMBOL_GPL(mt7921_mcu_radio_led_ctrl);
+
 int mt7921_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif)
 {
        struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
index 62617589a84fa8e12cacfdcc1a19327115af3935..6c5392c5d207e6909d65aafeb3c17f633714a9bd 100644 (file)
 #define MCU_UNI_EVENT_ROC  0x27
 #define MCU_UNI_EVENT_CLC  0x80
 
+#define EXT_CMD_RADIO_LED_CTRL_ENABLE   0x1
+#define EXT_CMD_RADIO_ON_LED            0x2
+#define EXT_CMD_RADIO_OFF_LED           0x3
+
 enum {
        UNI_ROC_ACQUIRE,
        UNI_ROC_ABORT,
@@ -196,6 +200,7 @@ int mt7921_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl);
 void mt7921_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb);
 int mt7921_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif,
                            u8 bit_op, u32 bit_map);
+int mt7921_mcu_radio_led_ctrl(struct mt792x_dev *dev, u8 value);
 
 static inline u32
 mt7921_reg_map_l1(struct mt792x_dev *dev, u32 addr)
index 0b69b225bc16cf4c65ca7670aac2225ea38153bf..f768e9389ac6c947c9de00b97e99ddf3bcf5ea3b 100644 (file)
@@ -427,6 +427,10 @@ static int mt7921_pci_suspend(struct device *device)
        wait_event_timeout(dev->wait,
                           !dev->regd_in_progress, 5 * HZ);
 
+       err = mt7921_mcu_radio_led_ctrl(dev, EXT_CMD_RADIO_OFF_LED);
+       if (err < 0)
+               goto restore_suspend;
+
        err = mt76_connac_mcu_set_hif_suspend(mdev, true);
        if (err)
                goto restore_suspend;
@@ -525,9 +529,11 @@ static int mt7921_pci_resume(struct device *device)
                mt76_connac_mcu_set_deep_sleep(&dev->mt76, false);
 
        err = mt76_connac_mcu_set_hif_suspend(mdev, false);
+       if (err < 0)
+               goto failed;
 
        mt7921_regd_update(dev);
-
+       err = mt7921_mcu_radio_led_ctrl(dev, EXT_CMD_RADIO_ON_LED);
 failed:
        pm->suspended = false;