Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: ISC
0002 /* Copyright (C) 2021 MediaTek Inc. */
0003 
0004 #include <linux/kernel.h>
0005 #include <linux/mmc/sdio_func.h>
0006 #include <linux/module.h>
0007 #include <linux/iopoll.h>
0008 
0009 #include "mt7921.h"
0010 #include "../sdio.h"
0011 #include "mac.h"
0012 #include "mcu.h"
0013 #include "regs.h"
0014 
0015 static int
0016 mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
0017              int cmd, int *seq)
0018 {
0019     struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
0020     enum mt7921_sdio_pkt_type type = MT7921_SDIO_CMD;
0021     enum mt76_mcuq_id txq = MT_MCUQ_WM;
0022     int ret, pad;
0023 
0024     /* We just return in case firmware assertion to avoid blocking the
0025      * common workqueue to run, for example, the coredump work might be
0026      * blocked by mt7921_mac_work that is excuting register access via sdio
0027      * bus.
0028      */
0029     if (dev->fw_assert)
0030         return -EBUSY;
0031 
0032     ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, seq);
0033     if (ret)
0034         return ret;
0035 
0036     if (cmd == MCU_UNI_CMD(HIF_CTRL) ||
0037         cmd == MCU_UNI_CMD(SUSPEND) ||
0038         cmd == MCU_UNI_CMD(OFFLOAD))
0039         mdev->mcu.timeout = HZ;
0040     else
0041         mdev->mcu.timeout = 3 * HZ;
0042 
0043     if (cmd == MCU_CMD(FW_SCATTER))
0044         type = MT7921_SDIO_FWDL;
0045 
0046     mt7921_skb_add_usb_sdio_hdr(dev, skb, type);
0047     pad = round_up(skb->len, 4) - skb->len;
0048     __skb_put_zero(skb, pad);
0049 
0050     ret = mt76_tx_queue_skb_raw(dev, mdev->q_mcu[txq], skb, 0);
0051     if (ret)
0052         return ret;
0053 
0054     mt76_queue_kick(dev, mdev->q_mcu[txq]);
0055 
0056     return ret;
0057 }
0058 
0059 static u32 mt7921s_read_rm3r(struct mt7921_dev *dev)
0060 {
0061     struct mt76_sdio *sdio = &dev->mt76.sdio;
0062 
0063     return sdio_readl(sdio->func, MCR_D2HRM3R, NULL);
0064 }
0065 
0066 static u32 mt7921s_clear_rm3r_drv_own(struct mt7921_dev *dev)
0067 {
0068     struct mt76_sdio *sdio = &dev->mt76.sdio;
0069     u32 val;
0070 
0071     val = sdio_readl(sdio->func, MCR_D2HRM3R, NULL);
0072     if (val)
0073         sdio_writel(sdio->func, H2D_SW_INT_CLEAR_MAILBOX_ACK,
0074                 MCR_WSICR, NULL);
0075 
0076     return val;
0077 }
0078 
0079 int mt7921s_mcu_init(struct mt7921_dev *dev)
0080 {
0081     static const struct mt76_mcu_ops mt7921s_mcu_ops = {
0082         .headroom = MT_SDIO_HDR_SIZE +
0083                 sizeof(struct mt76_connac2_mcu_txd),
0084         .tailroom = MT_SDIO_TAIL_SIZE,
0085         .mcu_skb_send_msg = mt7921s_mcu_send_message,
0086         .mcu_parse_response = mt7921_mcu_parse_response,
0087         .mcu_rr = mt76_connac_mcu_reg_rr,
0088         .mcu_wr = mt76_connac_mcu_reg_wr,
0089     };
0090     int ret;
0091 
0092     mt7921s_mcu_drv_pmctrl(dev);
0093 
0094     dev->mt76.mcu_ops = &mt7921s_mcu_ops;
0095 
0096     ret = mt7921_run_firmware(dev);
0097     if (ret)
0098         return ret;
0099 
0100     set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
0101 
0102     return 0;
0103 }
0104 
0105 int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev)
0106 {
0107     struct sdio_func *func = dev->mt76.sdio.func;
0108     struct mt76_phy *mphy = &dev->mt76.phy;
0109     struct mt76_connac_pm *pm = &dev->pm;
0110     u32 status;
0111     int err;
0112 
0113     sdio_claim_host(func);
0114 
0115     sdio_writel(func, WHLPCR_FW_OWN_REQ_CLR, MCR_WHLPCR, NULL);
0116 
0117     err = readx_poll_timeout(mt76s_read_pcr, &dev->mt76, status,
0118                  status & WHLPCR_IS_DRIVER_OWN, 2000, 1000000);
0119 
0120     if (!err && test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state))
0121         err = readx_poll_timeout(mt7921s_read_rm3r, dev, status,
0122                      status & D2HRM3R_IS_DRIVER_OWN,
0123                      2000, 1000000);
0124 
0125     sdio_release_host(func);
0126 
0127     if (err < 0) {
0128         dev_err(dev->mt76.dev, "driver own failed\n");
0129         return -EIO;
0130     }
0131 
0132     clear_bit(MT76_STATE_PM, &mphy->state);
0133 
0134     pm->stats.last_wake_event = jiffies;
0135     pm->stats.doze_time += pm->stats.last_wake_event -
0136                    pm->stats.last_doze_event;
0137 
0138     return 0;
0139 }
0140 
0141 int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev)
0142 {
0143     struct sdio_func *func = dev->mt76.sdio.func;
0144     struct mt76_phy *mphy = &dev->mt76.phy;
0145     struct mt76_connac_pm *pm = &dev->pm;
0146     u32 status;
0147     int err;
0148 
0149     sdio_claim_host(func);
0150 
0151     if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) {
0152         err = readx_poll_timeout(mt7921s_clear_rm3r_drv_own,
0153                      dev, status,
0154                      !(status & D2HRM3R_IS_DRIVER_OWN),
0155                      2000, 1000000);
0156         if (err < 0) {
0157             dev_err(dev->mt76.dev, "mailbox ACK not cleared\n");
0158             goto out;
0159         }
0160     }
0161 
0162     sdio_writel(func, WHLPCR_FW_OWN_REQ_SET, MCR_WHLPCR, NULL);
0163 
0164     err = readx_poll_timeout(mt76s_read_pcr, &dev->mt76, status,
0165                  !(status & WHLPCR_IS_DRIVER_OWN), 2000, 1000000);
0166 out:
0167     sdio_release_host(func);
0168 
0169     if (err < 0) {
0170         dev_err(dev->mt76.dev, "firmware own failed\n");
0171         clear_bit(MT76_STATE_PM, &mphy->state);
0172         return -EIO;
0173     }
0174 
0175     pm->stats.last_doze_event = jiffies;
0176     pm->stats.awake_time += pm->stats.last_doze_event -
0177                 pm->stats.last_wake_event;
0178 
0179     return 0;
0180 }