xref: /freebsd/sys/contrib/dev/mediatek/mt76/mt7921/sdio_mac.c (revision 8ba4d145d351db26e07695b8e90697398c5dfec2)
16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC
26c92544dSBjoern A. Zeeb /* Copyright (C) 2021 MediaTek Inc. */
36c92544dSBjoern A. Zeeb 
46c92544dSBjoern A. Zeeb #include <linux/iopoll.h>
56c92544dSBjoern A. Zeeb #include <linux/mmc/sdio_func.h>
66c92544dSBjoern A. Zeeb #include "mt7921.h"
7cbb3ec25SBjoern A. Zeeb #include "../mt76_connac2_mac.h"
86c92544dSBjoern A. Zeeb #include "../sdio.h"
96c92544dSBjoern A. Zeeb 
mt7921s_enable_irq(struct mt76_dev * dev)106c92544dSBjoern A. Zeeb static void mt7921s_enable_irq(struct mt76_dev *dev)
116c92544dSBjoern A. Zeeb {
126c92544dSBjoern A. Zeeb 	struct mt76_sdio *sdio = &dev->sdio;
136c92544dSBjoern A. Zeeb 
146c92544dSBjoern A. Zeeb 	sdio_claim_host(sdio->func);
156c92544dSBjoern A. Zeeb 	sdio_writel(sdio->func, WHLPCR_INT_EN_SET, MCR_WHLPCR, NULL);
166c92544dSBjoern A. Zeeb 	sdio_release_host(sdio->func);
176c92544dSBjoern A. Zeeb }
186c92544dSBjoern A. Zeeb 
mt7921s_disable_irq(struct mt76_dev * dev)196c92544dSBjoern A. Zeeb static void mt7921s_disable_irq(struct mt76_dev *dev)
206c92544dSBjoern A. Zeeb {
216c92544dSBjoern A. Zeeb 	struct mt76_sdio *sdio = &dev->sdio;
226c92544dSBjoern A. Zeeb 
236c92544dSBjoern A. Zeeb 	sdio_claim_host(sdio->func);
246c92544dSBjoern A. Zeeb 	sdio_writel(sdio->func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, NULL);
256c92544dSBjoern A. Zeeb 	sdio_release_host(sdio->func);
266c92544dSBjoern A. Zeeb }
276c92544dSBjoern A. Zeeb 
mt7921s_read_whcr(struct mt76_dev * dev)286c92544dSBjoern A. Zeeb static u32 mt7921s_read_whcr(struct mt76_dev *dev)
296c92544dSBjoern A. Zeeb {
306c92544dSBjoern A. Zeeb 	return sdio_readl(dev->sdio.func, MCR_WHCR, NULL);
316c92544dSBjoern A. Zeeb }
326c92544dSBjoern A. Zeeb 
mt7921s_wfsys_reset(struct mt792x_dev * dev)33cbb3ec25SBjoern A. Zeeb int mt7921s_wfsys_reset(struct mt792x_dev *dev)
346c92544dSBjoern A. Zeeb {
356c92544dSBjoern A. Zeeb 	struct mt76_sdio *sdio = &dev->mt76.sdio;
366c92544dSBjoern A. Zeeb 	u32 val, status;
376c92544dSBjoern A. Zeeb 
386c92544dSBjoern A. Zeeb 	mt7921s_mcu_drv_pmctrl(dev);
396c92544dSBjoern A. Zeeb 
406c92544dSBjoern A. Zeeb 	sdio_claim_host(sdio->func);
416c92544dSBjoern A. Zeeb 
426c92544dSBjoern A. Zeeb 	val = sdio_readl(sdio->func, MCR_WHCR, NULL);
436c92544dSBjoern A. Zeeb 	val &= ~WF_WHOLE_PATH_RSTB;
446c92544dSBjoern A. Zeeb 	sdio_writel(sdio->func, val, MCR_WHCR, NULL);
456c92544dSBjoern A. Zeeb 
466c92544dSBjoern A. Zeeb 	msleep(50);
476c92544dSBjoern A. Zeeb 
486c92544dSBjoern A. Zeeb 	val = sdio_readl(sdio->func, MCR_WHCR, NULL);
496c92544dSBjoern A. Zeeb 	val &= ~WF_SDIO_WF_PATH_RSTB;
506c92544dSBjoern A. Zeeb 	sdio_writel(sdio->func, val, MCR_WHCR, NULL);
516c92544dSBjoern A. Zeeb 
526c92544dSBjoern A. Zeeb 	usleep_range(1000, 2000);
536c92544dSBjoern A. Zeeb 
546c92544dSBjoern A. Zeeb 	val = sdio_readl(sdio->func, MCR_WHCR, NULL);
556c92544dSBjoern A. Zeeb 	val |= WF_WHOLE_PATH_RSTB;
566c92544dSBjoern A. Zeeb 	sdio_writel(sdio->func, val, MCR_WHCR, NULL);
576c92544dSBjoern A. Zeeb 
586c92544dSBjoern A. Zeeb 	readx_poll_timeout(mt7921s_read_whcr, &dev->mt76, status,
596c92544dSBjoern A. Zeeb 			   status & WF_RST_DONE, 50000, 2000000);
606c92544dSBjoern A. Zeeb 
616c92544dSBjoern A. Zeeb 	sdio_release_host(sdio->func);
626c92544dSBjoern A. Zeeb 
636c92544dSBjoern A. Zeeb 	clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
646c92544dSBjoern A. Zeeb 
656c92544dSBjoern A. Zeeb 	/* activate mt7921s again */
666c92544dSBjoern A. Zeeb 	mt7921s_mcu_drv_pmctrl(dev);
676c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_CONN_STATUS, MT_WIFI_PATCH_DL_STATE);
686c92544dSBjoern A. Zeeb 	mt7921s_mcu_fw_pmctrl(dev);
696c92544dSBjoern A. Zeeb 	mt7921s_mcu_drv_pmctrl(dev);
706c92544dSBjoern A. Zeeb 
716c92544dSBjoern A. Zeeb 	return 0;
726c92544dSBjoern A. Zeeb }
736c92544dSBjoern A. Zeeb 
mt7921s_init_reset(struct mt792x_dev * dev)74cbb3ec25SBjoern A. Zeeb int mt7921s_init_reset(struct mt792x_dev *dev)
756c92544dSBjoern A. Zeeb {
766c92544dSBjoern A. Zeeb 	set_bit(MT76_MCU_RESET, &dev->mphy.state);
776c92544dSBjoern A. Zeeb 
786c92544dSBjoern A. Zeeb 	wake_up(&dev->mt76.mcu.wait);
796c92544dSBjoern A. Zeeb 	skb_queue_purge(&dev->mt76.mcu.res_q);
806c92544dSBjoern A. Zeeb 	wait_event_timeout(dev->mt76.sdio.wait,
816c92544dSBjoern A. Zeeb 			   mt76s_txqs_empty(&dev->mt76), 5 * HZ);
826c92544dSBjoern A. Zeeb 	mt76_worker_disable(&dev->mt76.sdio.txrx_worker);
836c92544dSBjoern A. Zeeb 
846c92544dSBjoern A. Zeeb 	mt7921s_disable_irq(&dev->mt76);
856c92544dSBjoern A. Zeeb 	mt7921s_wfsys_reset(dev);
866c92544dSBjoern A. Zeeb 
876c92544dSBjoern A. Zeeb 	mt76_worker_enable(&dev->mt76.sdio.txrx_worker);
886c92544dSBjoern A. Zeeb 	clear_bit(MT76_MCU_RESET, &dev->mphy.state);
896c92544dSBjoern A. Zeeb 	mt7921s_enable_irq(&dev->mt76);
906c92544dSBjoern A. Zeeb 
916c92544dSBjoern A. Zeeb 	return 0;
926c92544dSBjoern A. Zeeb }
936c92544dSBjoern A. Zeeb 
mt7921s_mac_reset(struct mt792x_dev * dev)94cbb3ec25SBjoern A. Zeeb int mt7921s_mac_reset(struct mt792x_dev *dev)
956c92544dSBjoern A. Zeeb {
966c92544dSBjoern A. Zeeb 	int err;
976c92544dSBjoern A. Zeeb 
986c92544dSBjoern A. Zeeb 	mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
996c92544dSBjoern A. Zeeb 	mt76_txq_schedule_all(&dev->mphy);
1006c92544dSBjoern A. Zeeb 	mt76_worker_disable(&dev->mt76.tx_worker);
1016c92544dSBjoern A. Zeeb 	set_bit(MT76_MCU_RESET, &dev->mphy.state);
1026c92544dSBjoern A. Zeeb 	wake_up(&dev->mt76.mcu.wait);
1036c92544dSBjoern A. Zeeb 	skb_queue_purge(&dev->mt76.mcu.res_q);
1046c92544dSBjoern A. Zeeb 	wait_event_timeout(dev->mt76.sdio.wait,
1056c92544dSBjoern A. Zeeb 			   mt76s_txqs_empty(&dev->mt76), 5 * HZ);
1066c92544dSBjoern A. Zeeb 	mt76_worker_disable(&dev->mt76.sdio.txrx_worker);
1076c92544dSBjoern A. Zeeb 	mt76_worker_disable(&dev->mt76.sdio.status_worker);
1086c92544dSBjoern A. Zeeb 	mt76_worker_disable(&dev->mt76.sdio.net_worker);
109*8ba4d145SBjoern A. Zeeb 	mt76_worker_disable(&dev->mt76.sdio.stat_worker);
1106c92544dSBjoern A. Zeeb 
1116c92544dSBjoern A. Zeeb 	mt7921s_disable_irq(&dev->mt76);
1126c92544dSBjoern A. Zeeb 	mt7921s_wfsys_reset(dev);
1136c92544dSBjoern A. Zeeb 
1146c92544dSBjoern A. Zeeb 	mt76_worker_enable(&dev->mt76.sdio.txrx_worker);
1156c92544dSBjoern A. Zeeb 	mt76_worker_enable(&dev->mt76.sdio.status_worker);
1166c92544dSBjoern A. Zeeb 	mt76_worker_enable(&dev->mt76.sdio.net_worker);
117*8ba4d145SBjoern A. Zeeb 	mt76_worker_enable(&dev->mt76.sdio.stat_worker);
1186c92544dSBjoern A. Zeeb 
1196c92544dSBjoern A. Zeeb 	dev->fw_assert = false;
1206c92544dSBjoern A. Zeeb 	clear_bit(MT76_MCU_RESET, &dev->mphy.state);
1216c92544dSBjoern A. Zeeb 	mt7921s_enable_irq(&dev->mt76);
1226c92544dSBjoern A. Zeeb 
1236c92544dSBjoern A. Zeeb 	err = mt7921_run_firmware(dev);
1246c92544dSBjoern A. Zeeb 	if (err)
1256c92544dSBjoern A. Zeeb 		goto out;
1266c92544dSBjoern A. Zeeb 
1276c92544dSBjoern A. Zeeb 	err = mt7921_mcu_set_eeprom(dev);
1286c92544dSBjoern A. Zeeb 	if (err)
1296c92544dSBjoern A. Zeeb 		goto out;
1306c92544dSBjoern A. Zeeb 
1316c92544dSBjoern A. Zeeb 	err = mt7921_mac_init(dev);
1326c92544dSBjoern A. Zeeb 	if (err)
1336c92544dSBjoern A. Zeeb 		goto out;
1346c92544dSBjoern A. Zeeb 
1356c92544dSBjoern A. Zeeb 	err = __mt7921_start(&dev->phy);
1366c92544dSBjoern A. Zeeb out:
1376c92544dSBjoern A. Zeeb 
1386c92544dSBjoern A. Zeeb 	mt76_worker_enable(&dev->mt76.tx_worker);
1396c92544dSBjoern A. Zeeb 
1406c92544dSBjoern A. Zeeb 	return err;
1416c92544dSBjoern A. Zeeb }
142