init.c 10.5 KB
Newer Older
S
Stanislaw Gruszka 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * (c) Copyright 2002-2010, Ralink Technology, Inc.
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include "mt76x0.h"
#include "eeprom.h"
#include "trace.h"
#include "mcu.h"
21
#include "../mt76x02_util.h"
22
#include "../mt76x02_dma.h"
S
Stanislaw Gruszka 已提交
23 24 25

#include "initvals.h"

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
static void mt76x0_vht_cap_mask(struct ieee80211_supported_band *sband)
{
	struct ieee80211_sta_vht_cap *vht_cap = &sband->vht_cap;
	u16 mcs_map = 0;
	int i;

	vht_cap->cap &= ~IEEE80211_VHT_CAP_RXLDPC;
	for (i = 0; i < 8; i++) {
		if (!i)
			mcs_map |= (IEEE80211_VHT_MCS_SUPPORT_0_7 << (i * 2));
		else
			mcs_map |=
				(IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2));
	}
	vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
	vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
}

S
Stanislaw Gruszka 已提交
44 45 46
static void
mt76x0_set_wlan_state(struct mt76x0_dev *dev, u32 val, bool enable)
{
47
	u32 mask = MT_CMB_CTRL_XTAL_RDY | MT_CMB_CTRL_PLL_LD;
S
Stanislaw Gruszka 已提交
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67

	/* Note: we don't turn off WLAN_CLK because that makes the device
	 *	 not respond properly on the probe path.
	 *	 In case anyone (PSM?) wants to use this function we can
	 *	 bring the clock stuff back and fixup the probe path.
	 */

	if (enable)
		val |= (MT_WLAN_FUN_CTRL_WLAN_EN |
			MT_WLAN_FUN_CTRL_WLAN_CLK_EN);
	else
		val &= ~(MT_WLAN_FUN_CTRL_WLAN_EN);

	mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
	udelay(20);

	/* Note: vendor driver tries to disable/enable wlan here and retry
	 *       but the code which does it is so buggy it must have never
	 *       triggered, so don't bother.
	 */
68 69
	if (enable && !mt76_poll(dev, MT_CMB_CTRL, mask, mask, 2000))
		dev_err(dev->mt76.dev, "PLL and XTAL check failed\n");
S
Stanislaw Gruszka 已提交
70 71
}

72
void mt76x0_chip_onoff(struct mt76x0_dev *dev, bool enable, bool reset)
S
Stanislaw Gruszka 已提交
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
{
	u32 val;

	mutex_lock(&dev->hw_atomic_mutex);

	val = mt76_rr(dev, MT_WLAN_FUN_CTRL);

	if (reset) {
		val |= MT_WLAN_FUN_CTRL_GPIO_OUT_EN;
		val &= ~MT_WLAN_FUN_CTRL_FRC_WL_ANT_SEL;

		if (val & MT_WLAN_FUN_CTRL_WLAN_EN) {
			val |= (MT_WLAN_FUN_CTRL_WLAN_RESET |
				MT_WLAN_FUN_CTRL_WLAN_RESET_RF);
			mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
			udelay(20);

			val &= ~(MT_WLAN_FUN_CTRL_WLAN_RESET |
				 MT_WLAN_FUN_CTRL_WLAN_RESET_RF);
		}
	}

	mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
	udelay(20);

	mt76x0_set_wlan_state(dev, val, enable);

	mutex_unlock(&dev->hw_atomic_mutex);
}
102
EXPORT_SYMBOL_GPL(mt76x0_chip_onoff);
S
Stanislaw Gruszka 已提交
103 104 105

static void mt76x0_reset_csr_bbp(struct mt76x0_dev *dev)
{
106 107 108
	mt76_wr(dev, MT_MAC_SYS_CTRL,
		MT_MAC_SYS_CTRL_RESET_CSR |
		MT_MAC_SYS_CTRL_RESET_BBP);
S
Stanislaw Gruszka 已提交
109 110 111
	msleep(200);
}

112 113 114
#define RANDOM_WRITE(dev, tab)			\
	mt76_wr_rp(dev, MT_MCU_MEMMAP_WLAN,	\
		   tab, ARRAY_SIZE(tab))
S
Stanislaw Gruszka 已提交
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

static int mt76x0_init_bbp(struct mt76x0_dev *dev)
{
	int ret, i;

	ret = mt76x0_wait_bbp_ready(dev);
	if (ret)
		return ret;

	RANDOM_WRITE(dev, mt76x0_bbp_init_tab);

	for (i = 0; i < ARRAY_SIZE(mt76x0_bbp_switch_tab); i++) {
		const struct mt76x0_bbp_switch_item *item = &mt76x0_bbp_switch_tab[i];
		const struct mt76_reg_pair *pair = &item->reg_pair;

		if (((RF_G_BAND | RF_BW_20) & item->bw_band) == (RF_G_BAND | RF_BW_20))
			mt76_wr(dev, pair->reg, pair->value);
	}

	RANDOM_WRITE(dev, mt76x0_dcoc_tab);

	return 0;
}

static void mt76x0_init_mac_registers(struct mt76x0_dev *dev)
{
	u32 reg;

	RANDOM_WRITE(dev, common_mac_reg_table);

145
	mt76x02_set_beacon_offsets(&dev->mt76);
S
Stanislaw Gruszka 已提交
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189

	/* Enable PBF and MAC clock SYS_CTRL[11:10] = 0x3 */
	RANDOM_WRITE(dev, mt76x0_mac_reg_table);

	/* Release BBP and MAC reset MAC_SYS_CTRL[1:0] = 0x0 */
	reg = mt76_rr(dev, MT_MAC_SYS_CTRL);
	reg &= ~0x3;
	mt76_wr(dev, MT_MAC_SYS_CTRL, reg);

	if (is_mt7610e(dev)) {
		/* Disable COEX_EN */
		reg = mt76_rr(dev, MT_COEXCFG0);
		reg &= 0xFFFFFFFE;
		mt76_wr(dev, MT_COEXCFG0, reg);
	}

	/* Set 0x141C[15:12]=0xF */
	reg = mt76_rr(dev, MT_EXT_CCA_CFG);
	reg |= 0x0000F000;
	mt76_wr(dev, MT_EXT_CCA_CFG, reg);

	mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN);

	/*
		TxRing 9 is for Mgmt frame.
		TxRing 8 is for In-band command frame.
		WMM_RG0_TXQMA: This register setting is for FCE to define the rule of TxRing 9.
		WMM_RG1_TXQMA: This register setting is for FCE to define the rule of TxRing 8.
	*/
	reg = mt76_rr(dev, MT_WMM_CTRL);
	reg &= ~0x000003FF;
	reg |= 0x00000201;
	mt76_wr(dev, MT_WMM_CTRL, reg);

	/* TODO: Probably not needed */
	mt76_wr(dev, 0x7028, 0);
	mt76_wr(dev, 0x7010, 0);
	mt76_wr(dev, 0x7024, 0);
	msleep(10);
}

static int mt76x0_init_wcid_mem(struct mt76x0_dev *dev)
{
	u32 *vals;
190
	int i;
S
Stanislaw Gruszka 已提交
191

192
	vals = kmalloc(sizeof(*vals) * MT76_N_WCIDS * 2, GFP_KERNEL);
S
Stanislaw Gruszka 已提交
193 194 195
	if (!vals)
		return -ENOMEM;

196
	for (i = 0; i < MT76_N_WCIDS; i++)  {
S
Stanislaw Gruszka 已提交
197 198 199 200
		vals[i * 2] = 0xffffffff;
		vals[i * 2 + 1] = 0x00ffffff;
	}

201
	mt76_wr_copy(dev, MT_WCID_ADDR_BASE, vals, MT76_N_WCIDS * 2);
S
Stanislaw Gruszka 已提交
202
	kfree(vals);
203
	return 0;
S
Stanislaw Gruszka 已提交
204 205
}

206
static void mt76x0_init_key_mem(struct mt76x0_dev *dev)
S
Stanislaw Gruszka 已提交
207 208 209
{
	u32 vals[4] = {};

210
	mt76_wr_copy(dev, MT_SKEY_MODE_BASE_0, vals, ARRAY_SIZE(vals));
S
Stanislaw Gruszka 已提交
211 212 213 214 215
}

static int mt76x0_init_wcid_attr_mem(struct mt76x0_dev *dev)
{
	u32 *vals;
216
	int i;
S
Stanislaw Gruszka 已提交
217

218
	vals = kmalloc(sizeof(*vals) * MT76_N_WCIDS * 2, GFP_KERNEL);
S
Stanislaw Gruszka 已提交
219 220 221
	if (!vals)
		return -ENOMEM;

222
	for (i = 0; i < MT76_N_WCIDS * 2; i++)
S
Stanislaw Gruszka 已提交
223 224
		vals[i] = 1;

225
	mt76_wr_copy(dev, MT_WCID_ATTR_BASE, vals, MT76_N_WCIDS * 2);
S
Stanislaw Gruszka 已提交
226
	kfree(vals);
227
	return 0;
S
Stanislaw Gruszka 已提交
228 229 230 231
}

static void mt76x0_reset_counters(struct mt76x0_dev *dev)
{
232 233 234 235 236 237
	mt76_rr(dev, MT_RX_STAT_0);
	mt76_rr(dev, MT_RX_STAT_1);
	mt76_rr(dev, MT_RX_STAT_2);
	mt76_rr(dev, MT_TX_STA_0);
	mt76_rr(dev, MT_TX_STA_1);
	mt76_rr(dev, MT_TX_STA_2);
S
Stanislaw Gruszka 已提交
238 239 240 241 242 243
}

int mt76x0_mac_start(struct mt76x0_dev *dev)
{
	mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);

244
	if (!mt76x02_wait_for_wpdma(&dev->mt76, 200000))
S
Stanislaw Gruszka 已提交
245 246
		return -ETIMEDOUT;

247
	mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter);
S
Stanislaw Gruszka 已提交
248
	mt76_wr(dev, MT_MAC_SYS_CTRL,
249
		MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
S
Stanislaw Gruszka 已提交
250

251
	return !mt76x02_wait_for_wpdma(&dev->mt76, 50) ? -ETIMEDOUT : 0;
S
Stanislaw Gruszka 已提交
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
}

static void mt76x0_mac_stop_hw(struct mt76x0_dev *dev)
{
	int i, ok;

	if (test_bit(MT76_REMOVED, &dev->mt76.state))
		return;

	mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN |
		   MT_BEACON_TIME_CFG_SYNC_MODE | MT_BEACON_TIME_CFG_TBTT_EN |
		   MT_BEACON_TIME_CFG_BEACON_TX);

	if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_BUSY, 0, 1000))
		dev_warn(dev->mt76.dev, "Warning: TX DMA did not stop!\n");

	/* Page count on TxQ */
	i = 200;
	while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) ||
		       (mt76_rr(dev, 0x0a30) & 0x000000ff) ||
		       (mt76_rr(dev, 0x0a34) & 0x00ff00ff)))
		msleep(10);

	if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_TX, 0, 1000))
		dev_warn(dev->mt76.dev, "Warning: MAC TX did not stop!\n");

	mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_RX |
					 MT_MAC_SYS_CTRL_ENABLE_TX);

	/* Page count on RxQ */
	ok = 0;
	i = 200;
	while (i--) {
		if (!(mt76_rr(dev, MT_RXQ_STA) & 0x00ff0000) &&
		    !mt76_rr(dev, 0x0a30) &&
		    !mt76_rr(dev, 0x0a34)) {
			if (ok++ > 5)
				break;
			continue;
		}
		msleep(1);
	}

	if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_RX, 0, 1000))
		dev_warn(dev->mt76.dev, "Warning: MAC RX did not stop!\n");

	if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_RX_BUSY, 0, 1000))
		dev_warn(dev->mt76.dev, "Warning: RX DMA did not stop!\n");
}

void mt76x0_mac_stop(struct mt76x0_dev *dev)
{
304 305 306
	cancel_delayed_work_sync(&dev->cal_work);
	cancel_delayed_work_sync(&dev->mac_work);
	mt76u_stop_stat_wk(&dev->mt76);
S
Stanislaw Gruszka 已提交
307 308
	mt76x0_mac_stop_hw(dev);
}
309
EXPORT_SYMBOL_GPL(mt76x0_mac_stop);
S
Stanislaw Gruszka 已提交
310 311 312 313 314

int mt76x0_init_hardware(struct mt76x0_dev *dev)
{
	int ret;

315
	if (!mt76x02_wait_for_wpdma(&dev->mt76, 1000))
316
		return -EIO;
S
Stanislaw Gruszka 已提交
317 318

	/* Wait for ASIC ready after FW load. */
319 320
	if (!mt76x02_wait_for_mac(&dev->mt76))
		return -ETIMEDOUT;
S
Stanislaw Gruszka 已提交
321 322

	mt76x0_reset_csr_bbp(dev);
323
	ret = mt76x02_mcu_function_select(&dev->mt76, Q_SELECT, 1, false);
S
Stanislaw Gruszka 已提交
324
	if (ret)
325
		return ret;
326

S
Stanislaw Gruszka 已提交
327 328
	mt76x0_init_mac_registers(dev);

329
	if (!mt76x02_wait_for_txrx_idle(&dev->mt76))
330
		return -EIO;
S
Stanislaw Gruszka 已提交
331 332 333

	ret = mt76x0_init_bbp(dev);
	if (ret)
334
		return ret;
S
Stanislaw Gruszka 已提交
335

336 337
	dev->mt76.rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG);

S
Stanislaw Gruszka 已提交
338 339
	ret = mt76x0_init_wcid_mem(dev);
	if (ret)
340 341
		return ret;

342
	mt76x0_init_key_mem(dev);
343

S
Stanislaw Gruszka 已提交
344 345
	ret = mt76x0_init_wcid_attr_mem(dev);
	if (ret)
346
		return ret;
S
Stanislaw Gruszka 已提交
347 348 349 350 351 352 353 354 355 356

	mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN |
					     MT_BEACON_TIME_CFG_SYNC_MODE |
					     MT_BEACON_TIME_CFG_TBTT_EN |
					     MT_BEACON_TIME_CFG_BEACON_TX));

	mt76x0_reset_counters(dev);

	ret = mt76x0_eeprom_init(dev);
	if (ret)
357
		return ret;
S
Stanislaw Gruszka 已提交
358 359 360

	mt76x0_phy_init(dev);

361
	return 0;
S
Stanislaw Gruszka 已提交
362
}
363
EXPORT_SYMBOL_GPL(mt76x0_init_hardware);
S
Stanislaw Gruszka 已提交
364

365 366
struct mt76x0_dev *
mt76x0_alloc_device(struct device *pdev, const struct mt76_driver_ops *drv_ops)
S
Stanislaw Gruszka 已提交
367 368
{
	struct mt76x0_dev *dev;
369
	struct mt76_dev *mdev;
S
Stanislaw Gruszka 已提交
370

371 372
	mdev = mt76_alloc_device(sizeof(*dev), &mt76x0_ops);
	if (!mdev)
S
Stanislaw Gruszka 已提交
373 374
		return NULL;

375
	mdev->dev = pdev;
376
	mdev->drv = drv_ops;
377 378

	dev = container_of(mdev, struct mt76x0_dev, mt76);
S
Stanislaw Gruszka 已提交
379 380 381 382 383 384 385 386
	mutex_init(&dev->reg_atomic_mutex);
	mutex_init(&dev->hw_atomic_mutex);
	spin_lock_init(&dev->mac_lock);
	spin_lock_init(&dev->con_mon_lock);
	atomic_set(&dev->avg_ampdu_len, 1);

	return dev;
}
387
EXPORT_SYMBOL_GPL(mt76x0_alloc_device);
S
Stanislaw Gruszka 已提交
388 389 390

int mt76x0_register_device(struct mt76x0_dev *dev)
{
391 392
	struct mt76_dev *mdev = &dev->mt76;
	struct ieee80211_hw *hw = mdev->hw;
S
Stanislaw Gruszka 已提交
393 394 395 396 397 398
	struct wiphy *wiphy = hw->wiphy;
	int ret;

	/* Reserve WCID 0 for mcast - thanks to this APs WCID will go to
	 * entry no. 1 like it does in the vendor driver.
	 */
399
	mdev->wcid_mask[0] |= 1;
S
Stanislaw Gruszka 已提交
400 401

	/* init fake wcid for monitor interfaces */
402 403
	mdev->global_wcid.idx = 0xff;
	mdev->global_wcid.hw_key_idx = -1;
S
Stanislaw Gruszka 已提交
404

405 406
	/* init antenna configuration */
	mdev->antenna_mask = 1;
S
Stanislaw Gruszka 已提交
407 408 409 410 411

	hw->queues = 4;
	hw->max_rates = 1;
	hw->max_report_rates = 7;
	hw->max_rate_tries = 1;
412
	hw->extra_tx_headroom = sizeof(struct mt76x02_txwi) + 4 + 2;
S
Stanislaw Gruszka 已提交
413

414
	hw->sta_data_size = sizeof(struct mt76x02_sta);
415
	hw->vif_data_size = sizeof(struct mt76x02_vif);
S
Stanislaw Gruszka 已提交
416 417 418 419 420

	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);

	INIT_DELAYED_WORK(&dev->mac_work, mt76x0_mac_work);

421 422
	ret = mt76_register_device(mdev, true, mt76x02_rates,
				   ARRAY_SIZE(mt76x02_rates));
S
Stanislaw Gruszka 已提交
423 424 425
	if (ret)
		return ret;

426 427 428 429
	/* overwrite unsupported features */
	if (mdev->cap.has_5ghz)
		mt76x0_vht_cap_mask(&dev->mt76.sband_5g.sband);

S
Stanislaw Gruszka 已提交
430 431 432 433
	mt76x0_init_debugfs(dev);

	return 0;
}
434
EXPORT_SYMBOL_GPL(mt76x0_register_device);