xref: /openbmc/linux/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c (revision 57904291176fa16a981cefca5cbe1a0b50196792)
148fab5bbSSean Wang // SPDX-License-Identifier: ISC
248fab5bbSSean Wang /* Copyright (C) 2021 MediaTek Inc. */
348fab5bbSSean Wang 
448fab5bbSSean Wang #include <linux/iopoll.h>
548fab5bbSSean Wang #include <linux/mmc/sdio_func.h>
648fab5bbSSean Wang #include "mt7921.h"
7140efef3SLorenzo Bianconi #include "../mt76_connac2_mac.h"
8ca74b9b9SSean Wang #include "../sdio.h"
9ca74b9b9SSean Wang 
mt7921s_enable_irq(struct mt76_dev * dev)10ca74b9b9SSean Wang static void mt7921s_enable_irq(struct mt76_dev *dev)
11ca74b9b9SSean Wang {
12ca74b9b9SSean Wang 	struct mt76_sdio *sdio = &dev->sdio;
13ca74b9b9SSean Wang 
14ca74b9b9SSean Wang 	sdio_claim_host(sdio->func);
15ca74b9b9SSean Wang 	sdio_writel(sdio->func, WHLPCR_INT_EN_SET, MCR_WHLPCR, NULL);
16ca74b9b9SSean Wang 	sdio_release_host(sdio->func);
17ca74b9b9SSean Wang }
18ca74b9b9SSean Wang 
mt7921s_disable_irq(struct mt76_dev * dev)19ca74b9b9SSean Wang static void mt7921s_disable_irq(struct mt76_dev *dev)
20ca74b9b9SSean Wang {
21ca74b9b9SSean Wang 	struct mt76_sdio *sdio = &dev->sdio;
22ca74b9b9SSean Wang 
23ca74b9b9SSean Wang 	sdio_claim_host(sdio->func);
24ca74b9b9SSean Wang 	sdio_writel(sdio->func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, NULL);
25ca74b9b9SSean Wang 	sdio_release_host(sdio->func);
26ca74b9b9SSean Wang }
27ca74b9b9SSean Wang 
mt7921s_read_whcr(struct mt76_dev * dev)28ca74b9b9SSean Wang static u32 mt7921s_read_whcr(struct mt76_dev *dev)
29ca74b9b9SSean Wang {
30ca74b9b9SSean Wang 	return sdio_readl(dev->sdio.func, MCR_WHCR, NULL);
31ca74b9b9SSean Wang }
32ca74b9b9SSean Wang 
mt7921s_wfsys_reset(struct mt792x_dev * dev)33975e122dSLorenzo Bianconi int mt7921s_wfsys_reset(struct mt792x_dev *dev)
34ca74b9b9SSean Wang {
35ca74b9b9SSean Wang 	struct mt76_sdio *sdio = &dev->mt76.sdio;
36ca74b9b9SSean Wang 	u32 val, status;
37ca74b9b9SSean Wang 
38ca74b9b9SSean Wang 	mt7921s_mcu_drv_pmctrl(dev);
39ca74b9b9SSean Wang 
40ca74b9b9SSean Wang 	sdio_claim_host(sdio->func);
41ca74b9b9SSean Wang 
42ca74b9b9SSean Wang 	val = sdio_readl(sdio->func, MCR_WHCR, NULL);
43ca74b9b9SSean Wang 	val &= ~WF_WHOLE_PATH_RSTB;
44ca74b9b9SSean Wang 	sdio_writel(sdio->func, val, MCR_WHCR, NULL);
45ca74b9b9SSean Wang 
46ca74b9b9SSean Wang 	msleep(50);
47ca74b9b9SSean Wang 
48ca74b9b9SSean Wang 	val = sdio_readl(sdio->func, MCR_WHCR, NULL);
49ca74b9b9SSean Wang 	val &= ~WF_SDIO_WF_PATH_RSTB;
50ca74b9b9SSean Wang 	sdio_writel(sdio->func, val, MCR_WHCR, NULL);
51ca74b9b9SSean Wang 
52ca74b9b9SSean Wang 	usleep_range(1000, 2000);
53ca74b9b9SSean Wang 
54ca74b9b9SSean Wang 	val = sdio_readl(sdio->func, MCR_WHCR, NULL);
55ca74b9b9SSean Wang 	val |= WF_WHOLE_PATH_RSTB;
56ca74b9b9SSean Wang 	sdio_writel(sdio->func, val, MCR_WHCR, NULL);
57ca74b9b9SSean Wang 
58ca74b9b9SSean Wang 	readx_poll_timeout(mt7921s_read_whcr, &dev->mt76, status,
59ca74b9b9SSean Wang 			   status & WF_RST_DONE, 50000, 2000000);
60ca74b9b9SSean Wang 
61ca74b9b9SSean Wang 	sdio_release_host(sdio->func);
62ca74b9b9SSean Wang 
63898422c1SSean Wang 	clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
64898422c1SSean Wang 
65ca74b9b9SSean Wang 	/* activate mt7921s again */
66b71d3911SYN Chen 	mt7921s_mcu_drv_pmctrl(dev);
67b71d3911SYN Chen 	mt76_clear(dev, MT_CONN_STATUS, MT_WIFI_PATCH_DL_STATE);
68ca74b9b9SSean Wang 	mt7921s_mcu_fw_pmctrl(dev);
69ca74b9b9SSean Wang 	mt7921s_mcu_drv_pmctrl(dev);
70ca74b9b9SSean Wang 
71ca74b9b9SSean Wang 	return 0;
72ca74b9b9SSean Wang }
73ca74b9b9SSean Wang 
mt7921s_init_reset(struct mt792x_dev * dev)74975e122dSLorenzo Bianconi int mt7921s_init_reset(struct mt792x_dev *dev)
75ca74b9b9SSean Wang {
76ca74b9b9SSean Wang 	set_bit(MT76_MCU_RESET, &dev->mphy.state);
77ca74b9b9SSean Wang 
78ca74b9b9SSean Wang 	wake_up(&dev->mt76.mcu.wait);
79ca74b9b9SSean Wang 	skb_queue_purge(&dev->mt76.mcu.res_q);
80ca74b9b9SSean Wang 	wait_event_timeout(dev->mt76.sdio.wait,
81ca74b9b9SSean Wang 			   mt76s_txqs_empty(&dev->mt76), 5 * HZ);
82ca74b9b9SSean Wang 	mt76_worker_disable(&dev->mt76.sdio.txrx_worker);
83ca74b9b9SSean Wang 
84ca74b9b9SSean Wang 	mt7921s_disable_irq(&dev->mt76);
85ca74b9b9SSean Wang 	mt7921s_wfsys_reset(dev);
86ca74b9b9SSean Wang 
87ca74b9b9SSean Wang 	mt76_worker_enable(&dev->mt76.sdio.txrx_worker);
88ca74b9b9SSean Wang 	clear_bit(MT76_MCU_RESET, &dev->mphy.state);
89ca74b9b9SSean Wang 	mt7921s_enable_irq(&dev->mt76);
90ca74b9b9SSean Wang 
91ca74b9b9SSean Wang 	return 0;
92ca74b9b9SSean Wang }
93ca74b9b9SSean Wang 
mt7921s_mac_reset(struct mt792x_dev * dev)94975e122dSLorenzo Bianconi int mt7921s_mac_reset(struct mt792x_dev *dev)
95ca74b9b9SSean Wang {
96ca74b9b9SSean Wang 	int err;
97ca74b9b9SSean Wang 
98ca74b9b9SSean Wang 	mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
99ca74b9b9SSean Wang 	mt76_txq_schedule_all(&dev->mphy);
100ca74b9b9SSean Wang 	mt76_worker_disable(&dev->mt76.tx_worker);
101ca74b9b9SSean Wang 	set_bit(MT76_MCU_RESET, &dev->mphy.state);
102ca74b9b9SSean Wang 	wake_up(&dev->mt76.mcu.wait);
103ca74b9b9SSean Wang 	skb_queue_purge(&dev->mt76.mcu.res_q);
104ca74b9b9SSean Wang 	wait_event_timeout(dev->mt76.sdio.wait,
105ca74b9b9SSean Wang 			   mt76s_txqs_empty(&dev->mt76), 5 * HZ);
106ca74b9b9SSean Wang 	mt76_worker_disable(&dev->mt76.sdio.txrx_worker);
107ca74b9b9SSean Wang 	mt76_worker_disable(&dev->mt76.sdio.status_worker);
108ca74b9b9SSean Wang 	mt76_worker_disable(&dev->mt76.sdio.net_worker);
109*e89d025dSWang Zhao 	mt76_worker_disable(&dev->mt76.sdio.stat_worker);
110ca74b9b9SSean Wang 
111ca74b9b9SSean Wang 	mt7921s_disable_irq(&dev->mt76);
112ca74b9b9SSean Wang 	mt7921s_wfsys_reset(dev);
113ca74b9b9SSean Wang 
114ca74b9b9SSean Wang 	mt76_worker_enable(&dev->mt76.sdio.txrx_worker);
115ca74b9b9SSean Wang 	mt76_worker_enable(&dev->mt76.sdio.status_worker);
116ca74b9b9SSean Wang 	mt76_worker_enable(&dev->mt76.sdio.net_worker);
117*e89d025dSWang Zhao 	mt76_worker_enable(&dev->mt76.sdio.stat_worker);
118ca74b9b9SSean Wang 
119ca74b9b9SSean Wang 	dev->fw_assert = false;
120ca74b9b9SSean Wang 	clear_bit(MT76_MCU_RESET, &dev->mphy.state);
121ca74b9b9SSean Wang 	mt7921s_enable_irq(&dev->mt76);
122ca74b9b9SSean Wang 
123ca74b9b9SSean Wang 	err = mt7921_run_firmware(dev);
124ca74b9b9SSean Wang 	if (err)
125ca74b9b9SSean Wang 		goto out;
126ca74b9b9SSean Wang 
127ca74b9b9SSean Wang 	err = mt7921_mcu_set_eeprom(dev);
128ca74b9b9SSean Wang 	if (err)
129ca74b9b9SSean Wang 		goto out;
130ca74b9b9SSean Wang 
131ca74b9b9SSean Wang 	err = mt7921_mac_init(dev);
132ca74b9b9SSean Wang 	if (err)
133ca74b9b9SSean Wang 		goto out;
134ca74b9b9SSean Wang 
135ca74b9b9SSean Wang 	err = __mt7921_start(&dev->phy);
136ca74b9b9SSean Wang out:
137ca74b9b9SSean Wang 
138ca74b9b9SSean Wang 	mt76_worker_enable(&dev->mt76.tx_worker);
139ca74b9b9SSean Wang 
140ca74b9b9SSean Wang 	return err;
141ca74b9b9SSean Wang }
142