198944Sobrien// SPDX-License-Identifier: ISC
246283Sdfr/*
398944Sobrien * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
446283Sdfr * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
5130803Smarcel */
6130803Smarcel
7130803Smarcel#include "mt76x2.h"
898944Sobrien
946283Sdfrvoid mt76x2_mac_stop(struct mt76x02_dev *dev, bool force)
1098944Sobrien{
1198944Sobrien	bool stopped = false;
1298944Sobrien	u32 rts_cfg;
1398944Sobrien	int i;
1446283Sdfr
1598944Sobrien	mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN);
1698944Sobrien	mt76_clear(dev, MT_TXOP_HLDR_ET, MT_TXOP_HLDR_TX40M_BLK_EN);
1798944Sobrien
1898944Sobrien	mt76_wr(dev, MT_MAC_SYS_CTRL, 0);
1946283Sdfr
2098944Sobrien	rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG);
2198944Sobrien	mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg & ~MT_TX_RTS_CFG_RETRY_LIMIT);
2298944Sobrien
2398944Sobrien	/* Wait for MAC to become idle */
2498944Sobrien	for (i = 0; i < 300; i++) {
2598944Sobrien		if ((mt76_rr(dev, MT_MAC_STATUS) &
2698944Sobrien		     (MT_MAC_STATUS_RX | MT_MAC_STATUS_TX)) ||
2798944Sobrien		    mt76_rr(dev, MT_BBP(IBI, 12))) {
2898944Sobrien			udelay(1);
2998944Sobrien			continue;
3098944Sobrien		}
3198944Sobrien
3298944Sobrien		stopped = true;
3398944Sobrien		break;
3498944Sobrien	}
3598944Sobrien
3698944Sobrien	if (force && !stopped) {
3798944Sobrien		mt76_set(dev, MT_BBP(CORE, 4), BIT(1));
3846283Sdfr		mt76_clear(dev, MT_BBP(CORE, 4), BIT(1));
3998944Sobrien
4098944Sobrien		mt76_set(dev, MT_BBP(CORE, 4), BIT(0));
4146283Sdfr		mt76_clear(dev, MT_BBP(CORE, 4), BIT(0));
4298944Sobrien	}
4398944Sobrien
4446283Sdfr	mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg);
4598944Sobrien}
4646283SdfrEXPORT_SYMBOL_GPL(mt76x2_mac_stop);
4798944Sobrien