Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (C) 2020 MediaTek Inc.
  3 *
  4 * Author: Felix Fietkau <nbd@nbd.name>
  5 *	   Lorenzo Bianconi <lorenzo@kernel.org>
  6 *	   Sean Wang <sean.wang@mediatek.com>
  7 */
  8#include <linux/kernel.h>
  9#include <linux/mmc/sdio_func.h>
 10#include <linux/module.h>
 11#include <linux/iopoll.h>
 12
 13#include "../sdio.h"
 14#include "mt7615.h"
 15#include "mac.h"
 16#include "mcu.h"
 17#include "regs.h"
 18
 19static int mt7663s_mcu_init_sched(struct mt7615_dev *dev)
 20{
 21	struct mt76_sdio *sdio = &dev->mt76.sdio;
 22	u32 txdwcnt;
 23
 24	sdio->sched.pse_data_quota = mt76_get_field(dev, MT_PSE_PG_HIF0_GROUP,
 25						    MT_HIF0_MIN_QUOTA);
 26	sdio->sched.pse_mcu_quota = mt76_get_field(dev, MT_PSE_PG_HIF1_GROUP,
 27						   MT_HIF1_MIN_QUOTA);
 28	sdio->sched.ple_data_quota = mt76_get_field(dev, MT_PLE_PG_HIF0_GROUP,
 29						    MT_HIF0_MIN_QUOTA);
 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;
 34
 35	return 0;
 36}
 37
 38static int
 39mt7663s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
 40			 int cmd, int *seq)
 41{
 42	struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
 43	int ret;
 44
 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);
 47	if (ret)
 48		return ret;
 49
 50	mt76_queue_kick(dev, mdev->q_mcu[MT_MCUQ_WM]);
 51
 52	return ret;
 53}
 54
 55static int __mt7663s_mcu_drv_pmctrl(struct mt7615_dev *dev)
 56{
 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;
 60	u32 status;
 61	int ret;
 62
 63	sdio_claim_host(func);
 64
 65	sdio_writel(func, WHLPCR_FW_OWN_REQ_CLR, MCR_WHLPCR, NULL);
 66
 67	ret = readx_poll_timeout(mt76s_read_pcr, &dev->mt76, status,
 68				 status & WHLPCR_IS_DRIVER_OWN, 2000, 1000000);
 69	if (ret < 0) {
 70		dev_err(dev->mt76.dev, "Cannot get ownership from device");
 71	} else {
 72		clear_bit(MT76_STATE_PM, &mphy->state);
 73
 74		pm->stats.last_wake_event = jiffies;
 75		pm->stats.doze_time += pm->stats.last_wake_event -
 76				       pm->stats.last_doze_event;
 77	}
 78	sdio_release_host(func);
 79
 80	return ret;
 81}
 82
 83static int mt7663s_mcu_drv_pmctrl(struct mt7615_dev *dev)
 84{
 85	struct mt76_phy *mphy = &dev->mt76.phy;
 86	int ret = 0;
 87
 88	mutex_lock(&dev->pm.mutex);
 89
 90	if (test_bit(MT76_STATE_PM, &mphy->state))
 91		ret = __mt7663s_mcu_drv_pmctrl(dev);
 92
 93	mutex_unlock(&dev->pm.mutex);
 94
 95	return ret;
 96}
 97
 98static int mt7663s_mcu_fw_pmctrl(struct mt7615_dev *dev)
 99{
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;
103	int ret = 0;
104	u32 status;
105
106	mutex_lock(&pm->mutex);
107
108	if (mt76_connac_skip_fw_pmctrl(mphy, pm))
109		goto out;
110
111	sdio_claim_host(func);
112
113	sdio_writel(func, WHLPCR_FW_OWN_REQ_SET, MCR_WHLPCR, NULL);
114
115	ret = readx_poll_timeout(mt76s_read_pcr, &dev->mt76, status,
116				 !(status & WHLPCR_IS_DRIVER_OWN), 2000, 1000000);
117	if (ret < 0) {
118		dev_err(dev->mt76.dev, "Cannot set ownership to device");
119		clear_bit(MT76_STATE_PM, &mphy->state);
120	} else {
121		pm->stats.last_doze_event = jiffies;
122		pm->stats.awake_time += pm->stats.last_doze_event -
123					pm->stats.last_wake_event;
124	}
125
126	sdio_release_host(func);
127out:
128	mutex_unlock(&pm->mutex);
129
130	return ret;
131}
132
133int mt7663s_mcu_init(struct mt7615_dev *dev)
134{
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,
142	};
143	struct mt7615_mcu_ops *mcu_ops;
144	int ret;
145
146	ret = __mt7663s_mcu_drv_pmctrl(dev);
147	if (ret)
148		return ret;
149
150	dev->mt76.mcu_ops = &mt7663s_mcu_ops,
151
152	ret = mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY);
153	if (ret) {
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))
157			return -EIO;
158	}
159
160	ret = __mt7663_load_firmware(dev);
161	if (ret)
162		return ret;
163
164	mcu_ops = devm_kmemdup(dev->mt76.dev, dev->mcu_ops, sizeof(*mcu_ops),
165			       GFP_KERNEL);
166	if (!mcu_ops)
167		return -ENOMEM;
168
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;
172
173	ret = mt7663s_mcu_init_sched(dev);
174	if (ret)
175		return ret;
176
177	set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
178
179	return 0;
180}