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