1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2020 MediaTek Inc.
4 * Author: Felix Fietkau <nbd@nbd.name>
5 * Lorenzo Bianconi <lorenzo@kernel.org>
6 * Sean Wang <sean.wang@mediatek.com>
8 #include <linux/kernel.h>
9 #include <linux/mmc/sdio_func.h>
10 #include <linux/module.h>
11 #include <linux/iopoll.h>
19 static int mt7663s_mcu_init_sched(struct mt7615_dev
*dev
)
21 struct mt76_sdio
*sdio
= &dev
->mt76
.sdio
;
24 sdio
->sched
.pse_data_quota
= mt76_get_field(dev
, MT_PSE_PG_HIF0_GROUP
,
26 sdio
->sched
.pse_mcu_quota
= mt76_get_field(dev
, MT_PSE_PG_HIF1_GROUP
,
28 sdio
->sched
.ple_data_quota
= mt76_get_field(dev
, MT_PLE_PG_HIF0_GROUP
,
30 sdio
->sched
.pse_page_size
= MT_PSE_PAGE_SZ
;
31 txdwcnt
= mt76_get_field(dev
, MT_PP_TXDWCNT
,
32 MT_PP_TXDWCNT_TX1_ADD_DW_CNT
);
33 sdio
->sched
.deficit
= txdwcnt
<< 2;
39 mt7663s_mcu_send_message(struct mt76_dev
*mdev
, struct sk_buff
*skb
,
42 struct mt7615_dev
*dev
= container_of(mdev
, struct mt7615_dev
, mt76
);
45 mt7615_mcu_fill_msg(dev
, skb
, cmd
, seq
);
46 ret
= mt76_tx_queue_skb_raw(dev
, mdev
->q_mcu
[MT_MCUQ_WM
], skb
, 0);
50 mt76_queue_kick(dev
, mdev
->q_mcu
[MT_MCUQ_WM
]);
55 static int __mt7663s_mcu_drv_pmctrl(struct mt7615_dev
*dev
)
57 struct sdio_func
*func
= dev
->mt76
.sdio
.func
;
58 struct mt76_phy
*mphy
= &dev
->mt76
.phy
;
59 struct mt76_connac_pm
*pm
= &dev
->pm
;
63 sdio_claim_host(func
);
65 sdio_writel(func
, WHLPCR_FW_OWN_REQ_CLR
, MCR_WHLPCR
, NULL
);
67 ret
= readx_poll_timeout(mt76s_read_pcr
, &dev
->mt76
, status
,
68 status
& WHLPCR_IS_DRIVER_OWN
, 2000, 1000000);
70 dev_err(dev
->mt76
.dev
, "Cannot get ownership from device");
72 clear_bit(MT76_STATE_PM
, &mphy
->state
);
74 pm
->stats
.last_wake_event
= jiffies
;
75 pm
->stats
.doze_time
+= pm
->stats
.last_wake_event
-
76 pm
->stats
.last_doze_event
;
78 sdio_release_host(func
);
83 static int mt7663s_mcu_drv_pmctrl(struct mt7615_dev
*dev
)
85 struct mt76_phy
*mphy
= &dev
->mt76
.phy
;
88 mutex_lock(&dev
->pm
.mutex
);
90 if (test_bit(MT76_STATE_PM
, &mphy
->state
))
91 ret
= __mt7663s_mcu_drv_pmctrl(dev
);
93 mutex_unlock(&dev
->pm
.mutex
);
98 static int mt7663s_mcu_fw_pmctrl(struct mt7615_dev
*dev
)
100 struct sdio_func
*func
= dev
->mt76
.sdio
.func
;
101 struct mt76_phy
*mphy
= &dev
->mt76
.phy
;
102 struct mt76_connac_pm
*pm
= &dev
->pm
;
106 mutex_lock(&pm
->mutex
);
108 if (mt76_connac_skip_fw_pmctrl(mphy
, pm
))
111 sdio_claim_host(func
);
113 sdio_writel(func
, WHLPCR_FW_OWN_REQ_SET
, MCR_WHLPCR
, NULL
);
115 ret
= readx_poll_timeout(mt76s_read_pcr
, &dev
->mt76
, status
,
116 !(status
& WHLPCR_IS_DRIVER_OWN
), 2000, 1000000);
118 dev_err(dev
->mt76
.dev
, "Cannot set ownership to device");
119 clear_bit(MT76_STATE_PM
, &mphy
->state
);
121 pm
->stats
.last_doze_event
= jiffies
;
122 pm
->stats
.awake_time
+= pm
->stats
.last_doze_event
-
123 pm
->stats
.last_wake_event
;
126 sdio_release_host(func
);
128 mutex_unlock(&pm
->mutex
);
133 int mt7663s_mcu_init(struct mt7615_dev
*dev
)
135 static const struct mt76_mcu_ops mt7663s_mcu_ops
= {
136 .headroom
= sizeof(struct mt7615_mcu_txd
),
137 .tailroom
= MT_USB_TAIL_SIZE
,
138 .mcu_skb_send_msg
= mt7663s_mcu_send_message
,
139 .mcu_parse_response
= mt7615_mcu_parse_response
,
140 .mcu_rr
= mt76_connac_mcu_reg_rr
,
141 .mcu_wr
= mt76_connac_mcu_reg_wr
,
143 struct mt7615_mcu_ops
*mcu_ops
;
146 ret
= __mt7663s_mcu_drv_pmctrl(dev
);
150 dev
->mt76
.mcu_ops
= &mt7663s_mcu_ops
;
152 ret
= mt76_get_field(dev
, MT_CONN_ON_MISC
, MT_TOP_MISC2_FW_N9_RDY
);
154 mt7615_mcu_restart(&dev
->mt76
);
155 if (!mt76_poll_msec(dev
, MT_CONN_ON_MISC
,
156 MT_TOP_MISC2_FW_N9_RDY
, 0, 500))
160 ret
= __mt7663_load_firmware(dev
);
164 mcu_ops
= devm_kmemdup(dev
->mt76
.dev
, dev
->mcu_ops
, sizeof(*mcu_ops
),
169 mcu_ops
->set_drv_ctrl
= mt7663s_mcu_drv_pmctrl
;
170 mcu_ops
->set_fw_ctrl
= mt7663s_mcu_fw_pmctrl
;
171 dev
->mcu_ops
= mcu_ops
;
173 ret
= mt7663s_mcu_init_sched(dev
);
177 set_bit(MT76_STATE_MCU_RUNNING
, &dev
->mphy
.state
);