199ad32a4SBo Jiao // SPDX-License-Identifier: ISC
299ad32a4SBo Jiao /* Copyright (C) 2022 MediaTek Inc. */
399ad32a4SBo Jiao 
499ad32a4SBo Jiao #include <linux/kernel.h>
599ad32a4SBo Jiao #include <linux/module.h>
699ad32a4SBo Jiao #include <linux/platform_device.h>
799ad32a4SBo Jiao #include <linux/pinctrl/consumer.h>
899ad32a4SBo Jiao #include <linux/of.h>
999ad32a4SBo Jiao #include <linux/of_device.h>
1099ad32a4SBo Jiao #include <linux/of_reserved_mem.h>
1199ad32a4SBo Jiao #include <linux/of_gpio.h>
1299ad32a4SBo Jiao #include <linux/iopoll.h>
1399ad32a4SBo Jiao #include <linux/reset.h>
1499ad32a4SBo Jiao #include <linux/of_net.h>
15cd85efdfSLorenzo Bianconi #include <linux/clk.h>
1699ad32a4SBo Jiao 
1799ad32a4SBo Jiao #include "mt7915.h"
1899ad32a4SBo Jiao 
1999ad32a4SBo Jiao /* INFRACFG */
2099ad32a4SBo Jiao #define MT_INFRACFG_CONN2AP_SLPPROT	0x0d0
2199ad32a4SBo Jiao #define MT_INFRACFG_AP2CONN_SLPPROT	0x0d4
2299ad32a4SBo Jiao 
2399ad32a4SBo Jiao #define MT_INFRACFG_RX_EN_MASK		BIT(16)
2499ad32a4SBo Jiao #define MT_INFRACFG_TX_RDY_MASK		BIT(4)
2599ad32a4SBo Jiao #define MT_INFRACFG_TX_EN_MASK		BIT(0)
2699ad32a4SBo Jiao 
2799ad32a4SBo Jiao /* TOP POS */
2899ad32a4SBo Jiao #define MT_TOP_POS_FAST_CTRL		0x114
2999ad32a4SBo Jiao #define MT_TOP_POS_FAST_EN_MASK		BIT(3)
3099ad32a4SBo Jiao 
3199ad32a4SBo Jiao #define MT_TOP_POS_SKU			0x21c
3299ad32a4SBo Jiao #define MT_TOP_POS_SKU_MASK		GENMASK(31, 28)
3399ad32a4SBo Jiao #define MT_TOP_POS_SKU_ADIE_DBDC_MASK	BIT(2)
3499ad32a4SBo Jiao 
3599ad32a4SBo Jiao enum {
3699ad32a4SBo Jiao 	ADIE_SB,
3799ad32a4SBo Jiao 	ADIE_DBDC
3899ad32a4SBo Jiao };
3999ad32a4SBo Jiao 
4099ad32a4SBo Jiao static int
4199ad32a4SBo Jiao mt76_wmac_spi_read(struct mt7915_dev *dev, u8 adie, u32 addr, u32 *val)
4299ad32a4SBo Jiao {
4399ad32a4SBo Jiao 	int ret;
4499ad32a4SBo Jiao 	u32 cur;
4599ad32a4SBo Jiao 
4699ad32a4SBo Jiao 	ret = read_poll_timeout(mt76_rr, cur, !(cur & MT_TOP_SPI_POLLING_BIT),
4799ad32a4SBo Jiao 				USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
4899ad32a4SBo Jiao 				dev, MT_TOP_SPI_BUSY_CR(adie));
4999ad32a4SBo Jiao 	if (ret)
5099ad32a4SBo Jiao 		return ret;
5199ad32a4SBo Jiao 
5299ad32a4SBo Jiao 	mt76_wr(dev, MT_TOP_SPI_ADDR_CR(adie),
5399ad32a4SBo Jiao 		MT_TOP_SPI_READ_ADDR_FORMAT | addr);
5499ad32a4SBo Jiao 	mt76_wr(dev, MT_TOP_SPI_WRITE_DATA_CR(adie), 0);
5599ad32a4SBo Jiao 
5699ad32a4SBo Jiao 	ret = read_poll_timeout(mt76_rr, cur, !(cur & MT_TOP_SPI_POLLING_BIT),
5799ad32a4SBo Jiao 				USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
5899ad32a4SBo Jiao 				dev, MT_TOP_SPI_BUSY_CR(adie));
5999ad32a4SBo Jiao 	if (ret)
6099ad32a4SBo Jiao 		return ret;
6199ad32a4SBo Jiao 
6299ad32a4SBo Jiao 	*val = mt76_rr(dev, MT_TOP_SPI_READ_DATA_CR(adie));
6399ad32a4SBo Jiao 
6499ad32a4SBo Jiao 	return 0;
6599ad32a4SBo Jiao }
6699ad32a4SBo Jiao 
6799ad32a4SBo Jiao static int
6899ad32a4SBo Jiao mt76_wmac_spi_write(struct mt7915_dev *dev, u8 adie, u32 addr, u32 val)
6999ad32a4SBo Jiao {
7099ad32a4SBo Jiao 	int ret;
7199ad32a4SBo Jiao 	u32 cur;
7299ad32a4SBo Jiao 
7399ad32a4SBo Jiao 	ret = read_poll_timeout(mt76_rr, cur, !(cur & MT_TOP_SPI_POLLING_BIT),
7499ad32a4SBo Jiao 				USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
7599ad32a4SBo Jiao 				dev, MT_TOP_SPI_BUSY_CR(adie));
7699ad32a4SBo Jiao 	if (ret)
7799ad32a4SBo Jiao 		return ret;
7899ad32a4SBo Jiao 
7999ad32a4SBo Jiao 	mt76_wr(dev, MT_TOP_SPI_ADDR_CR(adie),
8099ad32a4SBo Jiao 		MT_TOP_SPI_WRITE_ADDR_FORMAT | addr);
8199ad32a4SBo Jiao 	mt76_wr(dev, MT_TOP_SPI_WRITE_DATA_CR(adie), val);
8299ad32a4SBo Jiao 
8399ad32a4SBo Jiao 	return read_poll_timeout(mt76_rr, cur, !(cur & MT_TOP_SPI_POLLING_BIT),
8499ad32a4SBo Jiao 				 USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
8599ad32a4SBo Jiao 				 dev, MT_TOP_SPI_BUSY_CR(adie));
8699ad32a4SBo Jiao }
8799ad32a4SBo Jiao 
8899ad32a4SBo Jiao static int
8999ad32a4SBo Jiao mt76_wmac_spi_rmw(struct mt7915_dev *dev, u8 adie,
9099ad32a4SBo Jiao 		  u32 addr, u32 mask, u32 val)
9199ad32a4SBo Jiao {
9299ad32a4SBo Jiao 	u32 cur, ret;
9399ad32a4SBo Jiao 
9499ad32a4SBo Jiao 	ret = mt76_wmac_spi_read(dev, adie, addr, &cur);
9599ad32a4SBo Jiao 	if (ret)
9699ad32a4SBo Jiao 		return ret;
9799ad32a4SBo Jiao 
9899ad32a4SBo Jiao 	cur &= ~mask;
9999ad32a4SBo Jiao 	cur |= val;
10099ad32a4SBo Jiao 
10199ad32a4SBo Jiao 	return mt76_wmac_spi_write(dev, adie, addr, cur);
10299ad32a4SBo Jiao }
10399ad32a4SBo Jiao 
10499ad32a4SBo Jiao static int
10599ad32a4SBo Jiao mt7986_wmac_adie_efuse_read(struct mt7915_dev *dev, u8 adie,
10699ad32a4SBo Jiao 			    u32 addr, u32 *data)
10799ad32a4SBo Jiao {
10899ad32a4SBo Jiao 	int ret, temp;
10999ad32a4SBo Jiao 	u32 val, mask;
11099ad32a4SBo Jiao 
11199ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_EFUSE_CFG,
11299ad32a4SBo Jiao 				  MT_ADIE_EFUSE_CTRL_MASK);
11399ad32a4SBo Jiao 	if (ret)
11499ad32a4SBo Jiao 		return ret;
11599ad32a4SBo Jiao 
11699ad32a4SBo Jiao 	ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_EFUSE2_CTRL, BIT(30), 0x0);
11799ad32a4SBo Jiao 	if (ret)
11899ad32a4SBo Jiao 		return ret;
11999ad32a4SBo Jiao 
12099ad32a4SBo Jiao 	mask = (MT_ADIE_EFUSE_MODE_MASK | MT_ADIE_EFUSE_ADDR_MASK |
12199ad32a4SBo Jiao 		MT_ADIE_EFUSE_KICK_MASK);
12299ad32a4SBo Jiao 	val = FIELD_PREP(MT_ADIE_EFUSE_MODE_MASK, 0) |
12399ad32a4SBo Jiao 	      FIELD_PREP(MT_ADIE_EFUSE_ADDR_MASK, addr) |
12499ad32a4SBo Jiao 	      FIELD_PREP(MT_ADIE_EFUSE_KICK_MASK, 1);
12599ad32a4SBo Jiao 	ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_EFUSE2_CTRL, mask, val);
12699ad32a4SBo Jiao 	if (ret)
12799ad32a4SBo Jiao 		return ret;
12899ad32a4SBo Jiao 
12999ad32a4SBo Jiao 	ret = read_poll_timeout(mt76_wmac_spi_read, temp,
13099ad32a4SBo Jiao 				!temp && !FIELD_GET(MT_ADIE_EFUSE_KICK_MASK, val),
13199ad32a4SBo Jiao 				USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
13299ad32a4SBo Jiao 				dev, adie, MT_ADIE_EFUSE2_CTRL, &val);
13399ad32a4SBo Jiao 	if (ret)
13499ad32a4SBo Jiao 		return ret;
13599ad32a4SBo Jiao 
13699ad32a4SBo Jiao 	ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_EFUSE2_CTRL, &val);
13799ad32a4SBo Jiao 	if (ret)
13899ad32a4SBo Jiao 		return ret;
13999ad32a4SBo Jiao 
14099ad32a4SBo Jiao 	if (FIELD_GET(MT_ADIE_EFUSE_VALID_MASK, val) == 1)
14199ad32a4SBo Jiao 		ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_EFUSE_RDATA0,
14299ad32a4SBo Jiao 					 data);
14399ad32a4SBo Jiao 
14499ad32a4SBo Jiao 	return ret;
14599ad32a4SBo Jiao }
14699ad32a4SBo Jiao 
14799ad32a4SBo Jiao static inline void mt76_wmac_spi_lock(struct mt7915_dev *dev)
14899ad32a4SBo Jiao {
14999ad32a4SBo Jiao 	u32 cur;
15099ad32a4SBo Jiao 
15199ad32a4SBo Jiao 	read_poll_timeout(mt76_rr, cur,
15299ad32a4SBo Jiao 			  FIELD_GET(MT_SEMA_RFSPI_STATUS_MASK, cur),
15399ad32a4SBo Jiao 			  1000, 1000 * MSEC_PER_SEC, false, dev,
15499ad32a4SBo Jiao 			  MT_SEMA_RFSPI_STATUS);
15599ad32a4SBo Jiao }
15699ad32a4SBo Jiao 
15799ad32a4SBo Jiao static inline void mt76_wmac_spi_unlock(struct mt7915_dev *dev)
15899ad32a4SBo Jiao {
15999ad32a4SBo Jiao 	mt76_wr(dev, MT_SEMA_RFSPI_RELEASE, 1);
16099ad32a4SBo Jiao }
16199ad32a4SBo Jiao 
16299ad32a4SBo Jiao static u32 mt76_wmac_rmw(void __iomem *base, u32 offset, u32 mask, u32 val)
16399ad32a4SBo Jiao {
16499ad32a4SBo Jiao 	val |= readl(base + offset) & ~mask;
16599ad32a4SBo Jiao 	writel(val, base + offset);
16699ad32a4SBo Jiao 
16799ad32a4SBo Jiao 	return val;
16899ad32a4SBo Jiao }
16999ad32a4SBo Jiao 
17099ad32a4SBo Jiao static u8 mt7986_wmac_check_adie_type(struct mt7915_dev *dev)
17199ad32a4SBo Jiao {
17299ad32a4SBo Jiao 	u32 val;
17399ad32a4SBo Jiao 
17499ad32a4SBo Jiao 	val = readl(dev->sku + MT_TOP_POS_SKU);
17599ad32a4SBo Jiao 
17699ad32a4SBo Jiao 	return FIELD_GET(MT_TOP_POS_SKU_ADIE_DBDC_MASK, val);
17799ad32a4SBo Jiao }
17899ad32a4SBo Jiao 
17999ad32a4SBo Jiao static int mt7986_wmac_consys_reset(struct mt7915_dev *dev, bool enable)
18099ad32a4SBo Jiao {
18199ad32a4SBo Jiao 	if (!enable)
18299ad32a4SBo Jiao 		return reset_control_assert(dev->rstc);
18399ad32a4SBo Jiao 
18499ad32a4SBo Jiao 	mt76_wmac_rmw(dev->sku, MT_TOP_POS_FAST_CTRL,
18599ad32a4SBo Jiao 		      MT_TOP_POS_FAST_EN_MASK,
18699ad32a4SBo Jiao 		      FIELD_PREP(MT_TOP_POS_FAST_EN_MASK, 0x1));
18799ad32a4SBo Jiao 
18899ad32a4SBo Jiao 	return reset_control_deassert(dev->rstc);
18999ad32a4SBo Jiao }
19099ad32a4SBo Jiao 
19199ad32a4SBo Jiao static int mt7986_wmac_gpio_setup(struct mt7915_dev *dev)
19299ad32a4SBo Jiao {
19399ad32a4SBo Jiao 	struct pinctrl_state *state;
19499ad32a4SBo Jiao 	struct pinctrl *pinctrl;
19599ad32a4SBo Jiao 	int ret;
19699ad32a4SBo Jiao 	u8 type;
19799ad32a4SBo Jiao 
19899ad32a4SBo Jiao 	type = mt7986_wmac_check_adie_type(dev);
19999ad32a4SBo Jiao 	pinctrl = devm_pinctrl_get(dev->mt76.dev);
20001318bc0SDan Carpenter 	if (IS_ERR(pinctrl))
20101318bc0SDan Carpenter 		return PTR_ERR(pinctrl);
20299ad32a4SBo Jiao 
20399ad32a4SBo Jiao 	switch (type) {
20499ad32a4SBo Jiao 	case ADIE_SB:
20599ad32a4SBo Jiao 		state = pinctrl_lookup_state(pinctrl, "default");
20699ad32a4SBo Jiao 		if (IS_ERR_OR_NULL(state))
20799ad32a4SBo Jiao 			return -EINVAL;
20899ad32a4SBo Jiao 		break;
20999ad32a4SBo Jiao 	case ADIE_DBDC:
21099ad32a4SBo Jiao 		state = pinctrl_lookup_state(pinctrl, "dbdc");
21199ad32a4SBo Jiao 		if (IS_ERR_OR_NULL(state))
21299ad32a4SBo Jiao 			return -EINVAL;
21399ad32a4SBo Jiao 		break;
2149bd6823fSLorenzo Bianconi 	default:
2159bd6823fSLorenzo Bianconi 		return -EINVAL;
21699ad32a4SBo Jiao 	}
21799ad32a4SBo Jiao 
21899ad32a4SBo Jiao 	ret = pinctrl_select_state(pinctrl, state);
21999ad32a4SBo Jiao 	if (ret)
22099ad32a4SBo Jiao 		return ret;
22199ad32a4SBo Jiao 
22299ad32a4SBo Jiao 	usleep_range(500, 1000);
22399ad32a4SBo Jiao 
22499ad32a4SBo Jiao 	return 0;
22599ad32a4SBo Jiao }
22699ad32a4SBo Jiao 
22799ad32a4SBo Jiao static int mt7986_wmac_consys_lockup(struct mt7915_dev *dev, bool enable)
22899ad32a4SBo Jiao {
22999ad32a4SBo Jiao 	int ret;
23099ad32a4SBo Jiao 	u32 cur;
23199ad32a4SBo Jiao 
23299ad32a4SBo Jiao 	mt76_wmac_rmw(dev->dcm, MT_INFRACFG_AP2CONN_SLPPROT,
23399ad32a4SBo Jiao 		      MT_INFRACFG_RX_EN_MASK,
23499ad32a4SBo Jiao 		      FIELD_PREP(MT_INFRACFG_RX_EN_MASK, enable));
23599ad32a4SBo Jiao 	ret = read_poll_timeout(readl, cur, !(cur & MT_INFRACFG_RX_EN_MASK),
23699ad32a4SBo Jiao 				USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
23799ad32a4SBo Jiao 				dev->dcm + MT_INFRACFG_AP2CONN_SLPPROT);
23899ad32a4SBo Jiao 	if (ret)
23999ad32a4SBo Jiao 		return ret;
24099ad32a4SBo Jiao 
24199ad32a4SBo Jiao 	mt76_wmac_rmw(dev->dcm, MT_INFRACFG_AP2CONN_SLPPROT,
24299ad32a4SBo Jiao 		      MT_INFRACFG_TX_EN_MASK,
24399ad32a4SBo Jiao 		      FIELD_PREP(MT_INFRACFG_TX_EN_MASK, enable));
24499ad32a4SBo Jiao 	ret = read_poll_timeout(readl, cur, !(cur & MT_INFRACFG_TX_RDY_MASK),
24599ad32a4SBo Jiao 				USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
24699ad32a4SBo Jiao 				dev->dcm + MT_INFRACFG_AP2CONN_SLPPROT);
24799ad32a4SBo Jiao 	if (ret)
24899ad32a4SBo Jiao 		return ret;
24999ad32a4SBo Jiao 
25099ad32a4SBo Jiao 	mt76_wmac_rmw(dev->dcm, MT_INFRACFG_CONN2AP_SLPPROT,
25199ad32a4SBo Jiao 		      MT_INFRACFG_RX_EN_MASK,
25299ad32a4SBo Jiao 		      FIELD_PREP(MT_INFRACFG_RX_EN_MASK, enable));
25399ad32a4SBo Jiao 	mt76_wmac_rmw(dev->dcm, MT_INFRACFG_CONN2AP_SLPPROT,
25499ad32a4SBo Jiao 		      MT_INFRACFG_TX_EN_MASK,
25599ad32a4SBo Jiao 		      FIELD_PREP(MT_INFRACFG_TX_EN_MASK, enable));
25699ad32a4SBo Jiao 
25799ad32a4SBo Jiao 	return 0;
25899ad32a4SBo Jiao }
25999ad32a4SBo Jiao 
26099ad32a4SBo Jiao static int mt7986_wmac_coninfra_check(struct mt7915_dev *dev)
26199ad32a4SBo Jiao {
26299ad32a4SBo Jiao 	u32 cur;
26399ad32a4SBo Jiao 
26499ad32a4SBo Jiao 	return read_poll_timeout(mt76_rr, cur, (cur == 0x02070000),
26599ad32a4SBo Jiao 				 USEC_PER_MSEC, 50 * USEC_PER_MSEC,
26699ad32a4SBo Jiao 				 false, dev, MT_CONN_INFRA_BASE);
26799ad32a4SBo Jiao }
26899ad32a4SBo Jiao 
26999ad32a4SBo Jiao static int mt7986_wmac_coninfra_setup(struct mt7915_dev *dev)
27099ad32a4SBo Jiao {
27199ad32a4SBo Jiao 	struct device *pdev = dev->mt76.dev;
27299ad32a4SBo Jiao 	struct reserved_mem *rmem;
27399ad32a4SBo Jiao 	struct device_node *np;
27499ad32a4SBo Jiao 	u32 val;
27599ad32a4SBo Jiao 
27699ad32a4SBo Jiao 	np = of_parse_phandle(pdev->of_node, "memory-region", 0);
27799ad32a4SBo Jiao 	if (!np)
27899ad32a4SBo Jiao 		return -EINVAL;
27999ad32a4SBo Jiao 
28099ad32a4SBo Jiao 	rmem = of_reserved_mem_lookup(np);
28199ad32a4SBo Jiao 	if (!rmem)
28299ad32a4SBo Jiao 		return -EINVAL;
28399ad32a4SBo Jiao 
28499ad32a4SBo Jiao 	val = (rmem->base >> 16) & MT_TOP_MCU_EMI_BASE_MASK;
28599ad32a4SBo Jiao 
28699ad32a4SBo Jiao 	/* Set conninfra subsys PLL check */
28799ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS,
28899ad32a4SBo Jiao 		       MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1);
28999ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS,
29099ad32a4SBo Jiao 		       MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1);
29199ad32a4SBo Jiao 
29299ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_TOP_MCU_EMI_BASE,
29399ad32a4SBo Jiao 		       MT_TOP_MCU_EMI_BASE_MASK, val);
29499ad32a4SBo Jiao 
29599ad32a4SBo Jiao 	mt76_wr(dev, MT_INFRA_BUS_EMI_START, rmem->base);
29699ad32a4SBo Jiao 	mt76_wr(dev, MT_INFRA_BUS_EMI_END, rmem->size);
29799ad32a4SBo Jiao 
29899ad32a4SBo Jiao 	mt76_rr(dev, MT_CONN_INFRA_EFUSE);
29999ad32a4SBo Jiao 
30099ad32a4SBo Jiao 	/* Set conninfra sysram */
30199ad32a4SBo Jiao 	mt76_wr(dev, MT_TOP_RGU_SYSRAM_PDN, 0);
30299ad32a4SBo Jiao 	mt76_wr(dev, MT_TOP_RGU_SYSRAM_SLP, 1);
30399ad32a4SBo Jiao 
30499ad32a4SBo Jiao 	return 0;
30599ad32a4SBo Jiao }
30699ad32a4SBo Jiao 
30799ad32a4SBo Jiao static int mt7986_wmac_sku_setup(struct mt7915_dev *dev, u32 *adie_type)
30899ad32a4SBo Jiao {
30999ad32a4SBo Jiao 	int ret;
31099ad32a4SBo Jiao 	u32 adie_main, adie_ext;
31199ad32a4SBo Jiao 
31299ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET,
31399ad32a4SBo Jiao 		       MT_CONN_INFRA_ADIE1_RESET_MASK, 0x1);
31499ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET,
31599ad32a4SBo Jiao 		       MT_CONN_INFRA_ADIE2_RESET_MASK, 0x1);
31699ad32a4SBo Jiao 
31799ad32a4SBo Jiao 	mt76_wmac_spi_lock(dev);
31899ad32a4SBo Jiao 
31999ad32a4SBo Jiao 	ret = mt76_wmac_spi_read(dev, 0, MT_ADIE_CHIP_ID, &adie_main);
32099ad32a4SBo Jiao 	if (ret)
32199ad32a4SBo Jiao 		goto out;
32299ad32a4SBo Jiao 
32399ad32a4SBo Jiao 	ret = mt76_wmac_spi_read(dev, 1, MT_ADIE_CHIP_ID, &adie_ext);
32499ad32a4SBo Jiao 	if (ret)
32599ad32a4SBo Jiao 		goto out;
32699ad32a4SBo Jiao 
32799ad32a4SBo Jiao 	*adie_type = FIELD_GET(MT_ADIE_CHIP_ID_MASK, adie_main) |
32899ad32a4SBo Jiao 		     (MT_ADIE_CHIP_ID_MASK & adie_ext);
32999ad32a4SBo Jiao 
33099ad32a4SBo Jiao out:
33199ad32a4SBo Jiao 	mt76_wmac_spi_unlock(dev);
33299ad32a4SBo Jiao 
33399ad32a4SBo Jiao 	return 0;
33499ad32a4SBo Jiao }
33599ad32a4SBo Jiao 
33699ad32a4SBo Jiao static inline u16 mt7986_adie_idx(u8 adie, u32 adie_type)
33799ad32a4SBo Jiao {
33899ad32a4SBo Jiao 	if (adie == 0)
33999ad32a4SBo Jiao 		return u32_get_bits(adie_type, MT_ADIE_IDX0);
34099ad32a4SBo Jiao 	else
34199ad32a4SBo Jiao 		return u32_get_bits(adie_type, MT_ADIE_IDX1);
34299ad32a4SBo Jiao }
34399ad32a4SBo Jiao 
34499ad32a4SBo Jiao static inline bool is_7975(struct mt7915_dev *dev, u8 adie, u32 adie_type)
34599ad32a4SBo Jiao {
34699ad32a4SBo Jiao 	return mt7986_adie_idx(adie, adie_type) == 0x7975;
34799ad32a4SBo Jiao }
34899ad32a4SBo Jiao 
34999ad32a4SBo Jiao static inline bool is_7976(struct mt7915_dev *dev, u8 adie, u32 adie_type)
35099ad32a4SBo Jiao {
35199ad32a4SBo Jiao 	return mt7986_adie_idx(adie, adie_type) == 0x7976;
35299ad32a4SBo Jiao }
35399ad32a4SBo Jiao 
35499ad32a4SBo Jiao static int mt7986_wmac_adie_thermal_cal(struct mt7915_dev *dev, u8 adie)
35599ad32a4SBo Jiao {
35699ad32a4SBo Jiao 	int ret;
35799ad32a4SBo Jiao 	u32 data, val;
35899ad32a4SBo Jiao 
35999ad32a4SBo Jiao 	ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_THADC_ANALOG,
36099ad32a4SBo Jiao 					  &data);
36199ad32a4SBo Jiao 	if (ret || FIELD_GET(MT_ADIE_ANA_EN_MASK, data)) {
36299ad32a4SBo Jiao 		val = FIELD_GET(MT_ADIE_VRPI_SEL_EFUSE_MASK, data);
36399ad32a4SBo Jiao 		ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_RG_TOP_THADC_BG,
36499ad32a4SBo Jiao 					MT_ADIE_VRPI_SEL_CR_MASK,
36599ad32a4SBo Jiao 					FIELD_PREP(MT_ADIE_VRPI_SEL_CR_MASK, val));
36699ad32a4SBo Jiao 		if (ret)
36799ad32a4SBo Jiao 			return ret;
36899ad32a4SBo Jiao 
36999ad32a4SBo Jiao 		val = FIELD_GET(MT_ADIE_PGA_GAIN_EFUSE_MASK, data);
37099ad32a4SBo Jiao 		ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_RG_TOP_THADC,
37199ad32a4SBo Jiao 					MT_ADIE_PGA_GAIN_MASK,
37299ad32a4SBo Jiao 					FIELD_PREP(MT_ADIE_PGA_GAIN_MASK, val));
37399ad32a4SBo Jiao 		if (ret)
37499ad32a4SBo Jiao 			return ret;
37599ad32a4SBo Jiao 	}
37699ad32a4SBo Jiao 
37799ad32a4SBo Jiao 	ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_THADC_SLOP,
37899ad32a4SBo Jiao 					  &data);
37999ad32a4SBo Jiao 	if (ret || FIELD_GET(MT_ADIE_ANA_EN_MASK, data)) {
38099ad32a4SBo Jiao 		val = FIELD_GET(MT_ADIE_LDO_CTRL_EFUSE_MASK, data);
38199ad32a4SBo Jiao 
38299ad32a4SBo Jiao 		return mt76_wmac_spi_rmw(dev, adie, MT_ADIE_RG_TOP_THADC,
38399ad32a4SBo Jiao 					 MT_ADIE_LDO_CTRL_MASK,
38499ad32a4SBo Jiao 					 FIELD_PREP(MT_ADIE_LDO_CTRL_MASK, val));
38599ad32a4SBo Jiao 	}
38699ad32a4SBo Jiao 
38799ad32a4SBo Jiao 	return 0;
38899ad32a4SBo Jiao }
38999ad32a4SBo Jiao 
39099ad32a4SBo Jiao static int
39199ad32a4SBo Jiao mt7986_read_efuse_xo_trim_7976(struct mt7915_dev *dev, u8 adie,
39299ad32a4SBo Jiao 			       bool is_40m, int *result)
39399ad32a4SBo Jiao {
39499ad32a4SBo Jiao 	int ret;
39599ad32a4SBo Jiao 	u32 data, addr;
39699ad32a4SBo Jiao 
39799ad32a4SBo Jiao 	addr = is_40m ? MT_ADIE_XTAL_AXM_40M_OSC : MT_ADIE_XTAL_AXM_80M_OSC;
39899ad32a4SBo Jiao 	ret = mt7986_wmac_adie_efuse_read(dev, adie, addr, &data);
39999ad32a4SBo Jiao 	if (ret)
40099ad32a4SBo Jiao 		return ret;
40199ad32a4SBo Jiao 
40299ad32a4SBo Jiao 	if (!FIELD_GET(MT_ADIE_XO_TRIM_EN_MASK, data)) {
40399ad32a4SBo Jiao 		*result = 64;
40499ad32a4SBo Jiao 	} else {
40599ad32a4SBo Jiao 		*result = FIELD_GET(MT_ADIE_TRIM_MASK, data);
40699ad32a4SBo Jiao 		addr = is_40m ? MT_ADIE_XTAL_TRIM1_40M_OSC :
40799ad32a4SBo Jiao 				MT_ADIE_XTAL_TRIM1_80M_OSC;
40899ad32a4SBo Jiao 		ret = mt7986_wmac_adie_efuse_read(dev, adie, addr, &data);
40999ad32a4SBo Jiao 		if (ret)
41099ad32a4SBo Jiao 			return ret;
41199ad32a4SBo Jiao 
41299ad32a4SBo Jiao 		if (FIELD_GET(MT_ADIE_XO_TRIM_EN_MASK, data) &&
41399ad32a4SBo Jiao 		    FIELD_GET(MT_ADIE_XTAL_DECREASE_MASK, data))
41499ad32a4SBo Jiao 			*result -= FIELD_GET(MT_ADIE_EFUSE_TRIM_MASK, data);
41599ad32a4SBo Jiao 		else if (FIELD_GET(MT_ADIE_XO_TRIM_EN_MASK, data))
41699ad32a4SBo Jiao 			*result += FIELD_GET(MT_ADIE_EFUSE_TRIM_MASK, data);
41799ad32a4SBo Jiao 
41899ad32a4SBo Jiao 		*result = max(0, min(127, *result));
41999ad32a4SBo Jiao 	}
42099ad32a4SBo Jiao 
42199ad32a4SBo Jiao 	return 0;
42299ad32a4SBo Jiao }
42399ad32a4SBo Jiao 
42499ad32a4SBo Jiao static int mt7986_wmac_adie_xtal_trim_7976(struct mt7915_dev *dev, u8 adie)
42599ad32a4SBo Jiao {
42699ad32a4SBo Jiao 	int ret, trim_80m, trim_40m;
42799ad32a4SBo Jiao 	u32 data, val, mode;
42899ad32a4SBo Jiao 
42999ad32a4SBo Jiao 	ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_XO_TRIM_FLOW,
43099ad32a4SBo Jiao 					  &data);
43199ad32a4SBo Jiao 	if (ret || !FIELD_GET(BIT(1), data))
43299ad32a4SBo Jiao 		return 0;
43399ad32a4SBo Jiao 
43499ad32a4SBo Jiao 	ret = mt7986_read_efuse_xo_trim_7976(dev, adie, false, &trim_80m);
43599ad32a4SBo Jiao 	if (ret)
43699ad32a4SBo Jiao 		return ret;
43799ad32a4SBo Jiao 
43899ad32a4SBo Jiao 	ret = mt7986_read_efuse_xo_trim_7976(dev, adie, true, &trim_40m);
43999ad32a4SBo Jiao 	if (ret)
44099ad32a4SBo Jiao 		return ret;
44199ad32a4SBo Jiao 
44299ad32a4SBo Jiao 	ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_RG_STRAP_PIN_IN, &val);
44399ad32a4SBo Jiao 	if (ret)
44499ad32a4SBo Jiao 		return ret;
44599ad32a4SBo Jiao 
44699ad32a4SBo Jiao 	mode = FIELD_PREP(GENMASK(6, 4), val);
44799ad32a4SBo Jiao 	if (!mode || mode == 0x2) {
44899ad32a4SBo Jiao 		ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C1,
44999ad32a4SBo Jiao 					GENMASK(31, 24),
45099ad32a4SBo Jiao 					FIELD_PREP(GENMASK(31, 24), trim_80m));
45199ad32a4SBo Jiao 		if (ret)
45299ad32a4SBo Jiao 			return ret;
45399ad32a4SBo Jiao 
45499ad32a4SBo Jiao 		ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C2,
45599ad32a4SBo Jiao 					GENMASK(31, 24),
45699ad32a4SBo Jiao 					FIELD_PREP(GENMASK(31, 24), trim_80m));
45799ad32a4SBo Jiao 	} else if (mode == 0x3 || mode == 0x4 || mode == 0x6) {
45899ad32a4SBo Jiao 		ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C1,
45999ad32a4SBo Jiao 					GENMASK(23, 16),
46099ad32a4SBo Jiao 					FIELD_PREP(GENMASK(23, 16), trim_40m));
46199ad32a4SBo Jiao 		if (ret)
46299ad32a4SBo Jiao 			return ret;
46399ad32a4SBo Jiao 
46499ad32a4SBo Jiao 		ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C2,
46599ad32a4SBo Jiao 					GENMASK(23, 16),
46699ad32a4SBo Jiao 					FIELD_PREP(GENMASK(23, 16), trim_40m));
46799ad32a4SBo Jiao 	}
46899ad32a4SBo Jiao 
46999ad32a4SBo Jiao 	return ret;
47099ad32a4SBo Jiao }
47199ad32a4SBo Jiao 
47299ad32a4SBo Jiao static int mt7986_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie)
47399ad32a4SBo Jiao {
474b5509983SPeter Chiu 	u32 id, version, rg_xo_01, rg_xo_03;
47599ad32a4SBo Jiao 	int ret;
47699ad32a4SBo Jiao 
477b5509983SPeter Chiu 	ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_CHIP_ID, &id);
478b5509983SPeter Chiu 	if (ret)
479b5509983SPeter Chiu 		return ret;
480b5509983SPeter Chiu 
481b5509983SPeter Chiu 	version = FIELD_GET(MT_ADIE_VERSION_MASK, id);
482b5509983SPeter Chiu 
48399ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_TOP_THADC, 0x4a563b00);
48499ad32a4SBo Jiao 	if (ret)
48599ad32a4SBo Jiao 		return ret;
48699ad32a4SBo Jiao 
487b5509983SPeter Chiu 	if (version == 0x8a00 || version == 0x8a10 || version == 0x8b00) {
488b5509983SPeter Chiu 		rg_xo_01 = 0x1d59080f;
489b5509983SPeter Chiu 		rg_xo_03 = 0x34c00fe0;
490b5509983SPeter Chiu 	} else {
491b5509983SPeter Chiu 		rg_xo_01 = 0x1959f80f;
492b5509983SPeter Chiu 		rg_xo_03 = 0x34d00fe0;
493b5509983SPeter Chiu 	}
494b5509983SPeter Chiu 
495b5509983SPeter Chiu 	ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_01, rg_xo_01);
49699ad32a4SBo Jiao 	if (ret)
49799ad32a4SBo Jiao 		return ret;
49899ad32a4SBo Jiao 
499b5509983SPeter Chiu 	return mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_03, rg_xo_03);
50099ad32a4SBo Jiao }
50199ad32a4SBo Jiao 
50299ad32a4SBo Jiao static int
50399ad32a4SBo Jiao mt7986_read_efuse_xo_trim_7975(struct mt7915_dev *dev, u8 adie,
50499ad32a4SBo Jiao 			       u32 addr, u32 *result)
50599ad32a4SBo Jiao {
50699ad32a4SBo Jiao 	int ret;
50799ad32a4SBo Jiao 	u32 data;
50899ad32a4SBo Jiao 
50999ad32a4SBo Jiao 	ret = mt7986_wmac_adie_efuse_read(dev, adie, addr, &data);
51099ad32a4SBo Jiao 	if (ret)
51199ad32a4SBo Jiao 		return ret;
51299ad32a4SBo Jiao 
51399ad32a4SBo Jiao 	if ((data & MT_ADIE_XO_TRIM_EN_MASK)) {
51499ad32a4SBo Jiao 		if ((data & MT_ADIE_XTAL_DECREASE_MASK))
51599ad32a4SBo Jiao 			*result -= (data & MT_ADIE_EFUSE_TRIM_MASK);
51699ad32a4SBo Jiao 		else
51799ad32a4SBo Jiao 			*result += (data & MT_ADIE_EFUSE_TRIM_MASK);
51899ad32a4SBo Jiao 
51999ad32a4SBo Jiao 		*result = (*result & MT_ADIE_TRIM_MASK);
52099ad32a4SBo Jiao 	}
52199ad32a4SBo Jiao 
52299ad32a4SBo Jiao 	return 0;
52399ad32a4SBo Jiao }
52499ad32a4SBo Jiao 
52599ad32a4SBo Jiao static int mt7986_wmac_adie_xtal_trim_7975(struct mt7915_dev *dev, u8 adie)
52699ad32a4SBo Jiao {
52799ad32a4SBo Jiao 	int ret;
52899ad32a4SBo Jiao 	u32 data, result = 0, value;
52999ad32a4SBo Jiao 
53099ad32a4SBo Jiao 	ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_7975_XTAL_EN,
53199ad32a4SBo Jiao 					  &data);
53299ad32a4SBo Jiao 	if (ret || !(data & BIT(1)))
53399ad32a4SBo Jiao 		return 0;
53499ad32a4SBo Jiao 
53599ad32a4SBo Jiao 	ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_7975_XTAL_CAL,
53699ad32a4SBo Jiao 					  &data);
53799ad32a4SBo Jiao 	if (ret)
53899ad32a4SBo Jiao 		return ret;
53999ad32a4SBo Jiao 
54099ad32a4SBo Jiao 	if (data & MT_ADIE_XO_TRIM_EN_MASK)
54199ad32a4SBo Jiao 		result = (data & MT_ADIE_TRIM_MASK);
54299ad32a4SBo Jiao 
54399ad32a4SBo Jiao 	ret = mt7986_read_efuse_xo_trim_7975(dev, adie, MT_ADIE_7975_XO_TRIM2,
54499ad32a4SBo Jiao 					     &result);
54599ad32a4SBo Jiao 	if (ret)
54699ad32a4SBo Jiao 		return ret;
54799ad32a4SBo Jiao 
54899ad32a4SBo Jiao 	ret = mt7986_read_efuse_xo_trim_7975(dev, adie, MT_ADIE_7975_XO_TRIM3,
54999ad32a4SBo Jiao 					     &result);
55099ad32a4SBo Jiao 	if (ret)
55199ad32a4SBo Jiao 		return ret;
55299ad32a4SBo Jiao 
55399ad32a4SBo Jiao 	ret = mt7986_read_efuse_xo_trim_7975(dev, adie, MT_ADIE_7975_XO_TRIM4,
55499ad32a4SBo Jiao 					     &result);
55599ad32a4SBo Jiao 	if (ret)
55699ad32a4SBo Jiao 		return ret;
55799ad32a4SBo Jiao 
55899ad32a4SBo Jiao 	/* Update trim value to C1 and C2*/
55999ad32a4SBo Jiao 	value = FIELD_GET(MT_ADIE_7975_XO_CTRL2_C1_MASK, result) |
56099ad32a4SBo Jiao 		FIELD_GET(MT_ADIE_7975_XO_CTRL2_C2_MASK, result);
56199ad32a4SBo Jiao 	ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_XO_CTRL2,
56299ad32a4SBo Jiao 				MT_ADIE_7975_XO_CTRL2_MASK, value);
56399ad32a4SBo Jiao 	if (ret)
56499ad32a4SBo Jiao 		return ret;
56599ad32a4SBo Jiao 
56699ad32a4SBo Jiao 	ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_7975_XTAL, &value);
56799ad32a4SBo Jiao 	if (ret)
56899ad32a4SBo Jiao 		return ret;
56999ad32a4SBo Jiao 
57099ad32a4SBo Jiao 	if (value & MT_ADIE_7975_XTAL_EN_MASK) {
57199ad32a4SBo Jiao 		ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_XO_2,
57299ad32a4SBo Jiao 					MT_ADIE_7975_XO_2_FIX_EN, 0x0);
57399ad32a4SBo Jiao 		if (ret)
57499ad32a4SBo Jiao 			return ret;
57599ad32a4SBo Jiao 	}
57699ad32a4SBo Jiao 
57799ad32a4SBo Jiao 	return mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_XO_CTRL6,
57899ad32a4SBo Jiao 				 MT_ADIE_7975_XO_CTRL6_MASK, 0x1);
57999ad32a4SBo Jiao }
58099ad32a4SBo Jiao 
58199ad32a4SBo Jiao static int mt7986_wmac_adie_patch_7975(struct mt7915_dev *dev, u8 adie)
58299ad32a4SBo Jiao {
58399ad32a4SBo Jiao 	int ret;
58499ad32a4SBo Jiao 
58599ad32a4SBo Jiao 	/* disable CAL LDO and fine tune RFDIG LDO */
58699ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, 0x348, 0x00000002);
58799ad32a4SBo Jiao 	if (ret)
58899ad32a4SBo Jiao 		return ret;
58999ad32a4SBo Jiao 
59099ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, 0x378, 0x00000002);
59199ad32a4SBo Jiao 	if (ret)
59299ad32a4SBo Jiao 		return ret;
59399ad32a4SBo Jiao 
59499ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, 0x3a8, 0x00000002);
59599ad32a4SBo Jiao 	if (ret)
59699ad32a4SBo Jiao 		return ret;
59799ad32a4SBo Jiao 
59899ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, 0x3d8, 0x00000002);
59999ad32a4SBo Jiao 	if (ret)
60099ad32a4SBo Jiao 		return ret;
60199ad32a4SBo Jiao 
60299ad32a4SBo Jiao 	/* set CKA driving and filter */
60399ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, 0xa1c, 0x30000aaa);
60499ad32a4SBo Jiao 	if (ret)
60599ad32a4SBo Jiao 		return ret;
60699ad32a4SBo Jiao 
60799ad32a4SBo Jiao 	/* set CKB LDO to 1.4V */
60899ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, 0xa84, 0x8470008a);
60999ad32a4SBo Jiao 	if (ret)
61099ad32a4SBo Jiao 		return ret;
61199ad32a4SBo Jiao 
61299ad32a4SBo Jiao 	/* turn on SX0 LTBUF */
61399ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, 0x074, 0x00000002);
61499ad32a4SBo Jiao 	if (ret)
61599ad32a4SBo Jiao 		return ret;
61699ad32a4SBo Jiao 
61799ad32a4SBo Jiao 	/* CK_BUF_SW_EN = 1 (all buf in manual mode.) */
61899ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, 0xaa4, 0x01001fc0);
61999ad32a4SBo Jiao 	if (ret)
62099ad32a4SBo Jiao 		return ret;
62199ad32a4SBo Jiao 
62299ad32a4SBo Jiao 	/* BT mode/WF normal mode 00000005 */
62399ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, 0x070, 0x00000005);
62499ad32a4SBo Jiao 	if (ret)
62599ad32a4SBo Jiao 		return ret;
62699ad32a4SBo Jiao 
62799ad32a4SBo Jiao 	/* BG thermal sensor offset update */
62899ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, 0x344, 0x00000088);
62999ad32a4SBo Jiao 	if (ret)
63099ad32a4SBo Jiao 		return ret;
63199ad32a4SBo Jiao 
63299ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, 0x374, 0x00000088);
63399ad32a4SBo Jiao 	if (ret)
63499ad32a4SBo Jiao 		return ret;
63599ad32a4SBo Jiao 
63699ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, 0x3a4, 0x00000088);
63799ad32a4SBo Jiao 	if (ret)
63899ad32a4SBo Jiao 		return ret;
63999ad32a4SBo Jiao 
64099ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, 0x3d4, 0x00000088);
64199ad32a4SBo Jiao 	if (ret)
64299ad32a4SBo Jiao 		return ret;
64399ad32a4SBo Jiao 
64499ad32a4SBo Jiao 	/* set WCON VDD IPTAT to "0000" */
64599ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, 0xa80, 0x44d07000);
64699ad32a4SBo Jiao 	if (ret)
64799ad32a4SBo Jiao 		return ret;
64899ad32a4SBo Jiao 
64999ad32a4SBo Jiao 	/* change back LTBUF SX3 drving to default value */
65099ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, 0xa88, 0x3900aaaa);
65199ad32a4SBo Jiao 	if (ret)
65299ad32a4SBo Jiao 		return ret;
65399ad32a4SBo Jiao 
65499ad32a4SBo Jiao 	/* SM input cap off */
65599ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, 0x2c4, 0x00000000);
65699ad32a4SBo Jiao 	if (ret)
65799ad32a4SBo Jiao 		return ret;
65899ad32a4SBo Jiao 
65999ad32a4SBo Jiao 	/* set CKB driving and filter */
66099ad32a4SBo Jiao 	return mt76_wmac_spi_write(dev, adie, 0x2c8, 0x00000072);
66199ad32a4SBo Jiao }
66299ad32a4SBo Jiao 
66399ad32a4SBo Jiao static int mt7986_wmac_adie_cfg(struct mt7915_dev *dev, u8 adie, u32 adie_type)
66499ad32a4SBo Jiao {
66599ad32a4SBo Jiao 	int ret;
66699ad32a4SBo Jiao 
66799ad32a4SBo Jiao 	mt76_wmac_spi_lock(dev);
66899ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_CLK_EN, ~0);
66999ad32a4SBo Jiao 	if (ret)
67099ad32a4SBo Jiao 		goto out;
67199ad32a4SBo Jiao 
67299ad32a4SBo Jiao 	if (is_7975(dev, adie, adie_type)) {
67399ad32a4SBo Jiao 		ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_COCLK,
67499ad32a4SBo Jiao 					BIT(1), 0x1);
67599ad32a4SBo Jiao 		if (ret)
67699ad32a4SBo Jiao 			goto out;
67799ad32a4SBo Jiao 
67899ad32a4SBo Jiao 		ret = mt7986_wmac_adie_thermal_cal(dev, adie);
67999ad32a4SBo Jiao 		if (ret)
68099ad32a4SBo Jiao 			goto out;
68199ad32a4SBo Jiao 
68299ad32a4SBo Jiao 		ret = mt7986_wmac_adie_xtal_trim_7975(dev, adie);
68399ad32a4SBo Jiao 		if (ret)
68499ad32a4SBo Jiao 			goto out;
68599ad32a4SBo Jiao 
68699ad32a4SBo Jiao 		ret = mt7986_wmac_adie_patch_7975(dev, adie);
68799ad32a4SBo Jiao 	} else if (is_7976(dev, adie, adie_type)) {
68899ad32a4SBo Jiao 		if (mt7986_wmac_check_adie_type(dev) == ADIE_DBDC) {
68999ad32a4SBo Jiao 			ret = mt76_wmac_spi_write(dev, adie,
69099ad32a4SBo Jiao 						  MT_ADIE_WRI_CK_SEL, 0x1c);
69199ad32a4SBo Jiao 			if (ret)
69299ad32a4SBo Jiao 				goto out;
69399ad32a4SBo Jiao 		}
69499ad32a4SBo Jiao 
69599ad32a4SBo Jiao 		ret = mt7986_wmac_adie_thermal_cal(dev, adie);
69699ad32a4SBo Jiao 		if (ret)
69799ad32a4SBo Jiao 			goto out;
69899ad32a4SBo Jiao 
69999ad32a4SBo Jiao 		ret = mt7986_wmac_adie_xtal_trim_7976(dev, adie);
70099ad32a4SBo Jiao 		if (ret)
70199ad32a4SBo Jiao 			goto out;
70299ad32a4SBo Jiao 
70399ad32a4SBo Jiao 		ret = mt7986_wmac_adie_patch_7976(dev, adie);
70499ad32a4SBo Jiao 	}
70599ad32a4SBo Jiao out:
70699ad32a4SBo Jiao 	mt76_wmac_spi_unlock(dev);
70799ad32a4SBo Jiao 
70899ad32a4SBo Jiao 	return ret;
70999ad32a4SBo Jiao }
71099ad32a4SBo Jiao 
71199ad32a4SBo Jiao static int
71299ad32a4SBo Jiao mt7986_wmac_afe_cal(struct mt7915_dev *dev, u8 adie, bool dbdc, u32 adie_type)
71399ad32a4SBo Jiao {
71499ad32a4SBo Jiao 	int ret;
71599ad32a4SBo Jiao 	u8 idx;
71699ad32a4SBo Jiao 
71799ad32a4SBo Jiao 	mt76_wmac_spi_lock(dev);
71899ad32a4SBo Jiao 	if (is_7975(dev, adie, adie_type))
71999ad32a4SBo Jiao 		ret = mt76_wmac_spi_write(dev, adie,
72099ad32a4SBo Jiao 					  MT_AFE_RG_ENCAL_WBTAC_IF_SW,
72199ad32a4SBo Jiao 					  0x80000000);
72299ad32a4SBo Jiao 	else
72399ad32a4SBo Jiao 		ret = mt76_wmac_spi_write(dev, adie,
72499ad32a4SBo Jiao 					  MT_AFE_RG_ENCAL_WBTAC_IF_SW,
72599ad32a4SBo Jiao 					  0x88888005);
72699ad32a4SBo Jiao 	if (ret)
72799ad32a4SBo Jiao 		goto out;
72899ad32a4SBo Jiao 
72999ad32a4SBo Jiao 	idx = dbdc ? ADIE_DBDC : adie;
73099ad32a4SBo Jiao 
73199ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_AFE_DIG_EN_01(idx),
73299ad32a4SBo Jiao 		       MT_AFE_RG_WBG_EN_RCK_MASK, 0x1);
73399ad32a4SBo Jiao 	usleep_range(60, 100);
73499ad32a4SBo Jiao 
73599ad32a4SBo Jiao 	mt76_rmw(dev, MT_AFE_DIG_EN_01(idx),
73699ad32a4SBo Jiao 		 MT_AFE_RG_WBG_EN_RCK_MASK, 0x0);
73799ad32a4SBo Jiao 
73899ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_AFE_DIG_EN_03(idx),
73999ad32a4SBo Jiao 		       MT_AFE_RG_WBG_EN_BPLL_UP_MASK, 0x1);
74099ad32a4SBo Jiao 	usleep_range(30, 100);
74199ad32a4SBo Jiao 
74299ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_AFE_DIG_EN_03(idx),
74399ad32a4SBo Jiao 		       MT_AFE_RG_WBG_EN_WPLL_UP_MASK, 0x1);
74499ad32a4SBo Jiao 	usleep_range(60, 100);
74599ad32a4SBo Jiao 
74699ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_AFE_DIG_EN_01(idx),
74799ad32a4SBo Jiao 		       MT_AFE_RG_WBG_EN_TXCAL_MASK, 0x1f);
74899ad32a4SBo Jiao 	usleep_range(800, 1000);
74999ad32a4SBo Jiao 
75099ad32a4SBo Jiao 	mt76_rmw(dev, MT_AFE_DIG_EN_01(idx),
75199ad32a4SBo Jiao 		 MT_AFE_RG_WBG_EN_TXCAL_MASK, 0x0);
75299ad32a4SBo Jiao 	mt76_rmw(dev, MT_AFE_DIG_EN_03(idx),
75399ad32a4SBo Jiao 		 MT_AFE_RG_WBG_EN_PLL_UP_MASK, 0x0);
75499ad32a4SBo Jiao 
75599ad32a4SBo Jiao 	ret = mt76_wmac_spi_write(dev, adie, MT_AFE_RG_ENCAL_WBTAC_IF_SW,
75699ad32a4SBo Jiao 				  0x5);
75799ad32a4SBo Jiao 
75899ad32a4SBo Jiao out:
75999ad32a4SBo Jiao 	mt76_wmac_spi_unlock(dev);
76099ad32a4SBo Jiao 
76199ad32a4SBo Jiao 	return ret;
76299ad32a4SBo Jiao }
76399ad32a4SBo Jiao 
76499ad32a4SBo Jiao static void mt7986_wmac_subsys_pll_initial(struct mt7915_dev *dev, u8 band)
76599ad32a4SBo Jiao {
76699ad32a4SBo Jiao 	mt76_rmw(dev, MT_AFE_PLL_STB_TIME(band),
76799ad32a4SBo Jiao 		 MT_AFE_PLL_STB_TIME_MASK, MT_AFE_PLL_STB_TIME_VAL);
76899ad32a4SBo Jiao 
76999ad32a4SBo Jiao 	mt76_rmw(dev, MT_AFE_DIG_EN_02(band),
77099ad32a4SBo Jiao 		 MT_AFE_PLL_CFG_MASK, MT_AFE_PLL_CFG_VAL);
77199ad32a4SBo Jiao 
77299ad32a4SBo Jiao 	mt76_rmw(dev, MT_AFE_DIG_TOP_01(band),
77399ad32a4SBo Jiao 		 MT_AFE_DIG_TOP_01_MASK, MT_AFE_DIG_TOP_01_VAL);
77499ad32a4SBo Jiao }
77599ad32a4SBo Jiao 
77699ad32a4SBo Jiao static void mt7986_wmac_subsys_setting(struct mt7915_dev *dev)
77799ad32a4SBo Jiao {
77899ad32a4SBo Jiao 	/* Subsys pll init */
77999ad32a4SBo Jiao 	mt7986_wmac_subsys_pll_initial(dev, 0);
78099ad32a4SBo Jiao 	mt7986_wmac_subsys_pll_initial(dev, 1);
78199ad32a4SBo Jiao 
78299ad32a4SBo Jiao 	/* Set legacy OSC control stable time*/
78399ad32a4SBo Jiao 	mt76_rmw(dev, MT_CONN_INFRA_OSC_RC_EN,
78499ad32a4SBo Jiao 		 MT_CONN_INFRA_OSC_RC_EN_MASK, 0x0);
78599ad32a4SBo Jiao 	mt76_rmw(dev, MT_CONN_INFRA_OSC_CTRL,
78699ad32a4SBo Jiao 		 MT_CONN_INFRA_OSC_STB_TIME_MASK, 0x80706);
78799ad32a4SBo Jiao 
78899ad32a4SBo Jiao 	/* prevent subsys from power on/of in a short time interval */
78999ad32a4SBo Jiao 	mt76_rmw(dev, MT_TOP_WFSYS_PWR,
79099ad32a4SBo Jiao 		 MT_TOP_PWR_ACK_MASK | MT_TOP_PWR_KEY_MASK,
79199ad32a4SBo Jiao 		 MT_TOP_PWR_KEY);
79299ad32a4SBo Jiao }
79399ad32a4SBo Jiao 
79499ad32a4SBo Jiao static int mt7986_wmac_bus_timeout(struct mt7915_dev *dev)
79599ad32a4SBo Jiao {
79699ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_INFRA_BUS_OFF_TIMEOUT,
79799ad32a4SBo Jiao 		       MT_INFRA_BUS_TIMEOUT_LIMIT_MASK, 0x2);
79899ad32a4SBo Jiao 
79999ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_INFRA_BUS_OFF_TIMEOUT,
80099ad32a4SBo Jiao 		       MT_INFRA_BUS_TIMEOUT_EN_MASK, 0xf);
80199ad32a4SBo Jiao 
80299ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_INFRA_BUS_ON_TIMEOUT,
80399ad32a4SBo Jiao 		       MT_INFRA_BUS_TIMEOUT_LIMIT_MASK, 0xc);
80499ad32a4SBo Jiao 
80599ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_INFRA_BUS_ON_TIMEOUT,
80699ad32a4SBo Jiao 		       MT_INFRA_BUS_TIMEOUT_EN_MASK, 0xf);
80799ad32a4SBo Jiao 
80899ad32a4SBo Jiao 	return mt7986_wmac_coninfra_check(dev);
80999ad32a4SBo Jiao }
81099ad32a4SBo Jiao 
81199ad32a4SBo Jiao static void mt7986_wmac_clock_enable(struct mt7915_dev *dev, u32 adie_type)
81299ad32a4SBo Jiao {
81399ad32a4SBo Jiao 	u32 cur;
81499ad32a4SBo Jiao 
81599ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_1,
81699ad32a4SBo Jiao 		       MT_INFRA_CKGEN_DIV_SEL_MASK, 0x1);
81799ad32a4SBo Jiao 
81899ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_2,
81999ad32a4SBo Jiao 		       MT_INFRA_CKGEN_DIV_SEL_MASK, 0x1);
82099ad32a4SBo Jiao 
82199ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_1,
82299ad32a4SBo Jiao 		       MT_INFRA_CKGEN_DIV_EN_MASK, 0x1);
82399ad32a4SBo Jiao 
82499ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_2,
82599ad32a4SBo Jiao 		       MT_INFRA_CKGEN_DIV_EN_MASK, 0x1);
82699ad32a4SBo Jiao 
82799ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_INFRA_CKGEN_RFSPI_WPLL_DIV,
82899ad32a4SBo Jiao 		       MT_INFRA_CKGEN_DIV_SEL_MASK, 0x8);
82999ad32a4SBo Jiao 
83099ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_INFRA_CKGEN_RFSPI_WPLL_DIV,
83199ad32a4SBo Jiao 		       MT_INFRA_CKGEN_DIV_EN_MASK, 0x1);
83299ad32a4SBo Jiao 
83399ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS,
83499ad32a4SBo Jiao 		       MT_INFRA_CKGEN_BUS_CLK_SEL_MASK, 0x0);
83599ad32a4SBo Jiao 
83699ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_CONN_INFRA_HW_CTRL,
83799ad32a4SBo Jiao 		       MT_CONN_INFRA_HW_CTRL_MASK, 0x1);
83899ad32a4SBo Jiao 
83999ad32a4SBo Jiao 	mt76_rmw(dev, MT_TOP_CONN_INFRA_WAKEUP,
84099ad32a4SBo Jiao 		 MT_TOP_CONN_INFRA_WAKEUP_MASK, 0x1);
84199ad32a4SBo Jiao 
84299ad32a4SBo Jiao 	usleep_range(900, 1000);
84399ad32a4SBo Jiao 
84499ad32a4SBo Jiao 	mt76_wmac_spi_lock(dev);
84599ad32a4SBo Jiao 	if (is_7975(dev, 0, adie_type) || is_7976(dev, 0, adie_type)) {
84699ad32a4SBo Jiao 		mt76_rmw_field(dev, MT_ADIE_SLP_CTRL_CK0(0),
84799ad32a4SBo Jiao 			       MT_SLP_CTRL_EN_MASK, 0x1);
84899ad32a4SBo Jiao 
84999ad32a4SBo Jiao 		read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_CTRL_BSY_MASK),
85099ad32a4SBo Jiao 				  USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
85199ad32a4SBo Jiao 				  dev, MT_ADIE_SLP_CTRL_CK0(0));
85299ad32a4SBo Jiao 	}
85399ad32a4SBo Jiao 	if (is_7975(dev, 1, adie_type) || is_7976(dev, 1, adie_type)) {
85499ad32a4SBo Jiao 		mt76_rmw_field(dev, MT_ADIE_SLP_CTRL_CK0(1),
85599ad32a4SBo Jiao 			       MT_SLP_CTRL_EN_MASK, 0x1);
85699ad32a4SBo Jiao 
85799ad32a4SBo Jiao 		read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_CTRL_BSY_MASK),
85899ad32a4SBo Jiao 				  USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
85999ad32a4SBo Jiao 				  dev, MT_ADIE_SLP_CTRL_CK0(0));
86099ad32a4SBo Jiao 	}
86199ad32a4SBo Jiao 	mt76_wmac_spi_unlock(dev);
86299ad32a4SBo Jiao 
86399ad32a4SBo Jiao 	mt76_rmw(dev, MT_TOP_CONN_INFRA_WAKEUP,
86499ad32a4SBo Jiao 		 MT_TOP_CONN_INFRA_WAKEUP_MASK, 0x0);
86599ad32a4SBo Jiao 	usleep_range(900, 1000);
86699ad32a4SBo Jiao }
86799ad32a4SBo Jiao 
86899ad32a4SBo Jiao static int mt7986_wmac_top_wfsys_wakeup(struct mt7915_dev *dev, bool enable)
86999ad32a4SBo Jiao {
87099ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_TOP_WFSYS_WAKEUP,
87199ad32a4SBo Jiao 		       MT_TOP_WFSYS_WAKEUP_MASK, enable);
87299ad32a4SBo Jiao 
87399ad32a4SBo Jiao 	usleep_range(900, 1000);
87499ad32a4SBo Jiao 
87599ad32a4SBo Jiao 	if (!enable)
87699ad32a4SBo Jiao 		return 0;
87799ad32a4SBo Jiao 
87899ad32a4SBo Jiao 	return mt7986_wmac_coninfra_check(dev);
87999ad32a4SBo Jiao }
88099ad32a4SBo Jiao 
88199ad32a4SBo Jiao static int mt7986_wmac_wm_enable(struct mt7915_dev *dev, bool enable)
88299ad32a4SBo Jiao {
88399ad32a4SBo Jiao 	u32 cur;
88499ad32a4SBo Jiao 
88599ad32a4SBo Jiao 	mt76_rmw_field(dev, MT7986_TOP_WM_RESET,
88699ad32a4SBo Jiao 		       MT7986_TOP_WM_RESET_MASK, enable);
88799ad32a4SBo Jiao 	if (!enable)
88899ad32a4SBo Jiao 		return 0;
88999ad32a4SBo Jiao 
89099ad32a4SBo Jiao 	return read_poll_timeout(mt76_rr, cur, (cur == 0x1d1e),
89199ad32a4SBo Jiao 				 USEC_PER_MSEC, 5000 * USEC_PER_MSEC, false,
89299ad32a4SBo Jiao 				 dev, MT_TOP_CFG_ON_ROM_IDX);
89399ad32a4SBo Jiao }
89499ad32a4SBo Jiao 
89599ad32a4SBo Jiao static int mt7986_wmac_wfsys_poweron(struct mt7915_dev *dev, bool enable)
89699ad32a4SBo Jiao {
89799ad32a4SBo Jiao 	u32 mask = MT_TOP_PWR_EN_MASK | MT_TOP_PWR_KEY_MASK;
89899ad32a4SBo Jiao 	u32 cur;
89999ad32a4SBo Jiao 
90099ad32a4SBo Jiao 	mt76_rmw(dev, MT_TOP_WFSYS_PWR, mask,
90199ad32a4SBo Jiao 		 MT_TOP_PWR_KEY | FIELD_PREP(MT_TOP_PWR_EN_MASK, enable));
90299ad32a4SBo Jiao 
90399ad32a4SBo Jiao 	return read_poll_timeout(mt76_rr, cur,
90499ad32a4SBo Jiao 		(FIELD_GET(MT_TOP_WFSYS_RESET_STATUS_MASK, cur) == enable),
90599ad32a4SBo Jiao 		USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
90699ad32a4SBo Jiao 		dev, MT_TOP_WFSYS_RESET_STATUS);
90799ad32a4SBo Jiao }
90899ad32a4SBo Jiao 
90999ad32a4SBo Jiao static int mt7986_wmac_wfsys_setting(struct mt7915_dev *dev)
91099ad32a4SBo Jiao {
91199ad32a4SBo Jiao 	int ret;
91299ad32a4SBo Jiao 	u32 cur;
91399ad32a4SBo Jiao 
91499ad32a4SBo Jiao 	/* Turn off wfsys2conn bus sleep protect */
91599ad32a4SBo Jiao 	mt76_rmw(dev, MT_CONN_INFRA_WF_SLP_PROT,
91699ad32a4SBo Jiao 		 MT_CONN_INFRA_WF_SLP_PROT_MASK, 0x0);
91799ad32a4SBo Jiao 
91899ad32a4SBo Jiao 	ret = mt7986_wmac_wfsys_poweron(dev, true);
91999ad32a4SBo Jiao 	if (ret)
92099ad32a4SBo Jiao 		return ret;
92199ad32a4SBo Jiao 
92299ad32a4SBo Jiao 	/* Check bus sleep protect */
92399ad32a4SBo Jiao 
92499ad32a4SBo Jiao 	ret = read_poll_timeout(mt76_rr, cur,
92599ad32a4SBo Jiao 				!(cur & MT_CONN_INFRA_CONN_WF_MASK),
92699ad32a4SBo Jiao 				USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
92799ad32a4SBo Jiao 				dev, MT_CONN_INFRA_WF_SLP_PROT_RDY);
92899ad32a4SBo Jiao 	if (ret)
92999ad32a4SBo Jiao 		return ret;
93099ad32a4SBo Jiao 
93199ad32a4SBo Jiao 	ret = read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_WFDMA2CONN_MASK),
93299ad32a4SBo Jiao 				USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
93399ad32a4SBo Jiao 				dev, MT_SLP_STATUS);
93499ad32a4SBo Jiao 	if (ret)
93599ad32a4SBo Jiao 		return ret;
93699ad32a4SBo Jiao 
93799ad32a4SBo Jiao 	return read_poll_timeout(mt76_rr, cur, (cur == 0x02060000),
93899ad32a4SBo Jiao 				 USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
93999ad32a4SBo Jiao 				 dev, MT_TOP_CFG_IP_VERSION_ADDR);
94099ad32a4SBo Jiao }
94199ad32a4SBo Jiao 
94299ad32a4SBo Jiao static void mt7986_wmac_wfsys_set_timeout(struct mt7915_dev *dev)
94399ad32a4SBo Jiao {
94499ad32a4SBo Jiao 	u32 mask = MT_MCU_BUS_TIMEOUT_SET_MASK |
94599ad32a4SBo Jiao 		   MT_MCU_BUS_TIMEOUT_CG_EN_MASK |
94699ad32a4SBo Jiao 		   MT_MCU_BUS_TIMEOUT_EN_MASK;
94799ad32a4SBo Jiao 	u32 val = FIELD_PREP(MT_MCU_BUS_TIMEOUT_SET_MASK, 1) |
94899ad32a4SBo Jiao 		  FIELD_PREP(MT_MCU_BUS_TIMEOUT_CG_EN_MASK, 1) |
94999ad32a4SBo Jiao 		  FIELD_PREP(MT_MCU_BUS_TIMEOUT_EN_MASK, 1);
95099ad32a4SBo Jiao 
95199ad32a4SBo Jiao 	mt76_rmw(dev, MT_MCU_BUS_TIMEOUT, mask, val);
95299ad32a4SBo Jiao 
95399ad32a4SBo Jiao 	mt76_wr(dev, MT_MCU_BUS_REMAP, 0x810f0000);
95499ad32a4SBo Jiao 
95599ad32a4SBo Jiao 	mask = MT_MCU_BUS_DBG_TIMEOUT_SET_MASK |
95699ad32a4SBo Jiao 	       MT_MCU_BUS_DBG_TIMEOUT_CK_EN_MASK |
95799ad32a4SBo Jiao 	       MT_MCU_BUS_DBG_TIMEOUT_EN_MASK;
95899ad32a4SBo Jiao 	val = FIELD_PREP(MT_MCU_BUS_DBG_TIMEOUT_SET_MASK, 0x3aa) |
95999ad32a4SBo Jiao 	      FIELD_PREP(MT_MCU_BUS_DBG_TIMEOUT_CK_EN_MASK, 1) |
96099ad32a4SBo Jiao 	      FIELD_PREP(MT_MCU_BUS_DBG_TIMEOUT_EN_MASK, 1);
96199ad32a4SBo Jiao 
96299ad32a4SBo Jiao 	mt76_rmw(dev, MT_MCU_BUS_DBG_TIMEOUT, mask, val);
96399ad32a4SBo Jiao }
96499ad32a4SBo Jiao 
96599ad32a4SBo Jiao static int mt7986_wmac_sku_update(struct mt7915_dev *dev, u32 adie_type)
96699ad32a4SBo Jiao {
96799ad32a4SBo Jiao 	u32 val;
96899ad32a4SBo Jiao 
96999ad32a4SBo Jiao 	if (is_7976(dev, 0, adie_type) && is_7976(dev, 1, adie_type))
97099ad32a4SBo Jiao 		val = 0xf;
97199ad32a4SBo Jiao 	else if (is_7975(dev, 0, adie_type) && is_7975(dev, 1, adie_type))
97299ad32a4SBo Jiao 		val = 0xd;
97399ad32a4SBo Jiao 	else if (is_7976(dev, 0, adie_type))
97499ad32a4SBo Jiao 		val = 0x7;
97599ad32a4SBo Jiao 	else if (is_7975(dev, 1, adie_type))
97699ad32a4SBo Jiao 		val = 0x8;
97799ad32a4SBo Jiao 	else if (is_7976(dev, 1, adie_type))
97899ad32a4SBo Jiao 		val = 0xa;
97999ad32a4SBo Jiao 	else
98099ad32a4SBo Jiao 		return -EINVAL;
98199ad32a4SBo Jiao 
98299ad32a4SBo Jiao 	mt76_wmac_rmw(dev->sku, MT_TOP_POS_SKU, MT_TOP_POS_SKU_MASK,
98399ad32a4SBo Jiao 		      FIELD_PREP(MT_TOP_POS_SKU_MASK, val));
98499ad32a4SBo Jiao 
98599ad32a4SBo Jiao 	mt76_wr(dev, MT_CONNINFRA_SKU_DEC_ADDR, val);
98699ad32a4SBo Jiao 
98799ad32a4SBo Jiao 	return 0;
98899ad32a4SBo Jiao }
98999ad32a4SBo Jiao 
99099ad32a4SBo Jiao static int
99199ad32a4SBo Jiao mt7986_wmac_adie_setup(struct mt7915_dev *dev, u8 adie, u32 adie_type)
99299ad32a4SBo Jiao {
99399ad32a4SBo Jiao 	int ret;
99499ad32a4SBo Jiao 
99599ad32a4SBo Jiao 	if (!(is_7975(dev, adie, adie_type) || is_7976(dev, adie, adie_type)))
99699ad32a4SBo Jiao 		return 0;
99799ad32a4SBo Jiao 
99899ad32a4SBo Jiao 	ret = mt7986_wmac_adie_cfg(dev, adie, adie_type);
99999ad32a4SBo Jiao 	if (ret)
100099ad32a4SBo Jiao 		return ret;
100199ad32a4SBo Jiao 
100299ad32a4SBo Jiao 	ret = mt7986_wmac_afe_cal(dev, adie, false, adie_type);
100399ad32a4SBo Jiao 	if (ret)
100499ad32a4SBo Jiao 		return ret;
100599ad32a4SBo Jiao 
100699ad32a4SBo Jiao 	if (!adie && (mt7986_wmac_check_adie_type(dev) == ADIE_DBDC))
100799ad32a4SBo Jiao 		ret = mt7986_wmac_afe_cal(dev, adie, true, adie_type);
100899ad32a4SBo Jiao 
100999ad32a4SBo Jiao 	return ret;
101099ad32a4SBo Jiao }
101199ad32a4SBo Jiao 
101299ad32a4SBo Jiao static int mt7986_wmac_subsys_powerup(struct mt7915_dev *dev, u32 adie_type)
101399ad32a4SBo Jiao {
101499ad32a4SBo Jiao 	int ret;
101599ad32a4SBo Jiao 
101699ad32a4SBo Jiao 	mt7986_wmac_subsys_setting(dev);
101799ad32a4SBo Jiao 
101899ad32a4SBo Jiao 	ret = mt7986_wmac_bus_timeout(dev);
101999ad32a4SBo Jiao 	if (ret)
102099ad32a4SBo Jiao 		return ret;
102199ad32a4SBo Jiao 
102299ad32a4SBo Jiao 	mt7986_wmac_clock_enable(dev, adie_type);
102399ad32a4SBo Jiao 
102499ad32a4SBo Jiao 	return 0;
102599ad32a4SBo Jiao }
102699ad32a4SBo Jiao 
102799ad32a4SBo Jiao static int mt7986_wmac_wfsys_powerup(struct mt7915_dev *dev)
102899ad32a4SBo Jiao {
102999ad32a4SBo Jiao 	int ret;
103099ad32a4SBo Jiao 
103199ad32a4SBo Jiao 	ret = mt7986_wmac_wm_enable(dev, false);
103299ad32a4SBo Jiao 	if (ret)
103399ad32a4SBo Jiao 		return ret;
103499ad32a4SBo Jiao 
103599ad32a4SBo Jiao 	ret = mt7986_wmac_wfsys_setting(dev);
103699ad32a4SBo Jiao 	if (ret)
103799ad32a4SBo Jiao 		return ret;
103899ad32a4SBo Jiao 
103999ad32a4SBo Jiao 	mt7986_wmac_wfsys_set_timeout(dev);
104099ad32a4SBo Jiao 
104199ad32a4SBo Jiao 	return mt7986_wmac_wm_enable(dev, true);
104299ad32a4SBo Jiao }
104399ad32a4SBo Jiao 
104499ad32a4SBo Jiao int mt7986_wmac_enable(struct mt7915_dev *dev)
104599ad32a4SBo Jiao {
104699ad32a4SBo Jiao 	int ret;
104799ad32a4SBo Jiao 	u32 adie_type;
104899ad32a4SBo Jiao 
104999ad32a4SBo Jiao 	ret = mt7986_wmac_consys_reset(dev, true);
105099ad32a4SBo Jiao 	if (ret)
105199ad32a4SBo Jiao 		return ret;
105299ad32a4SBo Jiao 
105399ad32a4SBo Jiao 	ret = mt7986_wmac_gpio_setup(dev);
105499ad32a4SBo Jiao 	if (ret)
105599ad32a4SBo Jiao 		return ret;
105699ad32a4SBo Jiao 
105799ad32a4SBo Jiao 	ret = mt7986_wmac_consys_lockup(dev, false);
105899ad32a4SBo Jiao 	if (ret)
105999ad32a4SBo Jiao 		return ret;
106099ad32a4SBo Jiao 
106199ad32a4SBo Jiao 	ret = mt7986_wmac_coninfra_check(dev);
106299ad32a4SBo Jiao 	if (ret)
106399ad32a4SBo Jiao 		return ret;
106499ad32a4SBo Jiao 
106599ad32a4SBo Jiao 	ret = mt7986_wmac_coninfra_setup(dev);
106699ad32a4SBo Jiao 	if (ret)
106799ad32a4SBo Jiao 		return ret;
106899ad32a4SBo Jiao 
106999ad32a4SBo Jiao 	ret = mt7986_wmac_sku_setup(dev, &adie_type);
107099ad32a4SBo Jiao 	if (ret)
107199ad32a4SBo Jiao 		return ret;
107299ad32a4SBo Jiao 
107399ad32a4SBo Jiao 	ret = mt7986_wmac_adie_setup(dev, 0, adie_type);
107499ad32a4SBo Jiao 	if (ret)
107599ad32a4SBo Jiao 		return ret;
107699ad32a4SBo Jiao 
107799ad32a4SBo Jiao 	ret = mt7986_wmac_adie_setup(dev, 1, adie_type);
107899ad32a4SBo Jiao 	if (ret)
107999ad32a4SBo Jiao 		return ret;
108099ad32a4SBo Jiao 
108199ad32a4SBo Jiao 	ret = mt7986_wmac_subsys_powerup(dev, adie_type);
108299ad32a4SBo Jiao 	if (ret)
108399ad32a4SBo Jiao 		return ret;
108499ad32a4SBo Jiao 
108599ad32a4SBo Jiao 	ret = mt7986_wmac_top_wfsys_wakeup(dev, true);
108699ad32a4SBo Jiao 	if (ret)
108799ad32a4SBo Jiao 		return ret;
108899ad32a4SBo Jiao 
108999ad32a4SBo Jiao 	ret = mt7986_wmac_wfsys_powerup(dev);
109099ad32a4SBo Jiao 	if (ret)
109199ad32a4SBo Jiao 		return ret;
109299ad32a4SBo Jiao 
109399ad32a4SBo Jiao 	return mt7986_wmac_sku_update(dev, adie_type);
109499ad32a4SBo Jiao }
109599ad32a4SBo Jiao 
109699ad32a4SBo Jiao void mt7986_wmac_disable(struct mt7915_dev *dev)
109799ad32a4SBo Jiao {
109899ad32a4SBo Jiao 	u32 cur;
109999ad32a4SBo Jiao 
110099ad32a4SBo Jiao 	mt7986_wmac_top_wfsys_wakeup(dev, true);
110199ad32a4SBo Jiao 
110299ad32a4SBo Jiao 	/* Turn on wfsys2conn bus sleep protect */
110399ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_CONN_INFRA_WF_SLP_PROT,
110499ad32a4SBo Jiao 		       MT_CONN_INFRA_WF_SLP_PROT_MASK, 0x1);
110599ad32a4SBo Jiao 
110699ad32a4SBo Jiao 	/* Check wfsys2conn bus sleep protect */
110799ad32a4SBo Jiao 	read_poll_timeout(mt76_rr, cur, !(cur ^ MT_CONN_INFRA_CONN),
110899ad32a4SBo Jiao 			  USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
110999ad32a4SBo Jiao 			  dev, MT_CONN_INFRA_WF_SLP_PROT_RDY);
111099ad32a4SBo Jiao 
111199ad32a4SBo Jiao 	mt7986_wmac_wfsys_poweron(dev, false);
111299ad32a4SBo Jiao 
111399ad32a4SBo Jiao 	/* Turn back wpll setting */
111499ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_AFE_DIG_EN_02(0), MT_AFE_MCU_BPLL_CFG_MASK, 0x2);
111599ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_AFE_DIG_EN_02(0), MT_AFE_WPLL_CFG_MASK, 0x2);
111699ad32a4SBo Jiao 
111799ad32a4SBo Jiao 	/* Reset EMI */
111899ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ,
111999ad32a4SBo Jiao 		       MT_CONN_INFRA_EMI_REQ_MASK, 0x1);
112099ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ,
112199ad32a4SBo Jiao 		       MT_CONN_INFRA_EMI_REQ_MASK, 0x0);
112299ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ,
112399ad32a4SBo Jiao 		       MT_CONN_INFRA_INFRA_REQ_MASK, 0x1);
112499ad32a4SBo Jiao 	mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ,
112599ad32a4SBo Jiao 		       MT_CONN_INFRA_INFRA_REQ_MASK, 0x0);
112699ad32a4SBo Jiao 
112799ad32a4SBo Jiao 	mt7986_wmac_top_wfsys_wakeup(dev, false);
112899ad32a4SBo Jiao 	mt7986_wmac_consys_lockup(dev, true);
112999ad32a4SBo Jiao 	mt7986_wmac_consys_reset(dev, false);
113099ad32a4SBo Jiao }
113199ad32a4SBo Jiao 
113299ad32a4SBo Jiao static int mt7986_wmac_init(struct mt7915_dev *dev)
113399ad32a4SBo Jiao {
113499ad32a4SBo Jiao 	struct device *pdev = dev->mt76.dev;
113599ad32a4SBo Jiao 	struct platform_device *pfdev = to_platform_device(pdev);
1136cd85efdfSLorenzo Bianconi 	struct clk *mcu_clk, *ap_conn_clk;
1137cd85efdfSLorenzo Bianconi 
1138cd85efdfSLorenzo Bianconi 	mcu_clk = devm_clk_get(pdev, "mcu");
1139cd85efdfSLorenzo Bianconi 	if (IS_ERR(mcu_clk))
1140cd85efdfSLorenzo Bianconi 		dev_err(pdev, "mcu clock not found\n");
1141cd85efdfSLorenzo Bianconi 	else if (clk_prepare_enable(mcu_clk))
1142cd85efdfSLorenzo Bianconi 		dev_err(pdev, "mcu clock configuration failed\n");
1143cd85efdfSLorenzo Bianconi 
1144cd85efdfSLorenzo Bianconi 	ap_conn_clk = devm_clk_get(pdev, "ap2conn");
1145cd85efdfSLorenzo Bianconi 	if (IS_ERR(ap_conn_clk))
1146cd85efdfSLorenzo Bianconi 		dev_err(pdev, "ap2conn clock not found\n");
1147cd85efdfSLorenzo Bianconi 	else if (clk_prepare_enable(ap_conn_clk))
1148cd85efdfSLorenzo Bianconi 		dev_err(pdev, "ap2conn clock configuration failed\n");
114999ad32a4SBo Jiao 
115099ad32a4SBo Jiao 	dev->dcm = devm_platform_ioremap_resource(pfdev, 1);
115199ad32a4SBo Jiao 	if (IS_ERR(dev->dcm))
115299ad32a4SBo Jiao 		return PTR_ERR(dev->dcm);
115399ad32a4SBo Jiao 
115499ad32a4SBo Jiao 	dev->sku = devm_platform_ioremap_resource(pfdev, 2);
115599ad32a4SBo Jiao 	if (IS_ERR(dev->sku))
115699ad32a4SBo Jiao 		return PTR_ERR(dev->sku);
115799ad32a4SBo Jiao 
115899ad32a4SBo Jiao 	dev->rstc = devm_reset_control_get(pdev, "consys");
115999ad32a4SBo Jiao 	if (IS_ERR(dev->rstc))
116099ad32a4SBo Jiao 		return PTR_ERR(dev->rstc);
116199ad32a4SBo Jiao 
11625beadb27SRyder Lee 	return 0;
116399ad32a4SBo Jiao }
116499ad32a4SBo Jiao 
116599ad32a4SBo Jiao static int mt7986_wmac_probe(struct platform_device *pdev)
116699ad32a4SBo Jiao {
116799ad32a4SBo Jiao 	void __iomem *mem_base;
116899ad32a4SBo Jiao 	struct mt7915_dev *dev;
116999ad32a4SBo Jiao 	struct mt76_dev *mdev;
117099ad32a4SBo Jiao 	int irq, ret;
117199ad32a4SBo Jiao 	u32 chip_id;
117299ad32a4SBo Jiao 
117399ad32a4SBo Jiao 	chip_id = (uintptr_t)of_device_get_match_data(&pdev->dev);
117499ad32a4SBo Jiao 
117599ad32a4SBo Jiao 	mem_base = devm_platform_ioremap_resource(pdev, 0);
117699ad32a4SBo Jiao 	if (IS_ERR(mem_base)) {
117799ad32a4SBo Jiao 		dev_err(&pdev->dev, "Failed to get memory resource\n");
117899ad32a4SBo Jiao 		return PTR_ERR(mem_base);
117999ad32a4SBo Jiao 	}
118099ad32a4SBo Jiao 
118199ad32a4SBo Jiao 	dev = mt7915_mmio_probe(&pdev->dev, mem_base, chip_id);
118299ad32a4SBo Jiao 	if (IS_ERR(dev))
118399ad32a4SBo Jiao 		return PTR_ERR(dev);
118499ad32a4SBo Jiao 
118599ad32a4SBo Jiao 	mdev = &dev->mt76;
1186*eebb7097SLorenzo Bianconi 	ret = mt7915_mmio_wed_init(dev, pdev, false, &irq);
1187*eebb7097SLorenzo Bianconi 	if (ret < 0)
1188*eebb7097SLorenzo Bianconi 		goto free_device;
1189*eebb7097SLorenzo Bianconi 
1190*eebb7097SLorenzo Bianconi 	if (!ret) {
1191*eebb7097SLorenzo Bianconi 		irq = platform_get_irq(pdev, 0);
1192*eebb7097SLorenzo Bianconi 		if (irq < 0) {
1193*eebb7097SLorenzo Bianconi 			ret = irq;
1194*eebb7097SLorenzo Bianconi 			goto free_device;
1195*eebb7097SLorenzo Bianconi 		}
1196*eebb7097SLorenzo Bianconi 	}
1197*eebb7097SLorenzo Bianconi 
119899ad32a4SBo Jiao 	ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler,
119999ad32a4SBo Jiao 			       IRQF_SHARED, KBUILD_MODNAME, dev);
120099ad32a4SBo Jiao 	if (ret)
120199ad32a4SBo Jiao 		goto free_device;
120299ad32a4SBo Jiao 
120399ad32a4SBo Jiao 	ret = mt7986_wmac_init(dev);
120499ad32a4SBo Jiao 	if (ret)
120599ad32a4SBo Jiao 		goto free_irq;
120699ad32a4SBo Jiao 
12075beadb27SRyder Lee 	mt7915_wfsys_reset(dev);
12085beadb27SRyder Lee 
120999ad32a4SBo Jiao 	ret = mt7915_register_device(dev);
121099ad32a4SBo Jiao 	if (ret)
121199ad32a4SBo Jiao 		goto free_irq;
121299ad32a4SBo Jiao 
121399ad32a4SBo Jiao 	return 0;
121499ad32a4SBo Jiao 
121599ad32a4SBo Jiao free_irq:
121699ad32a4SBo Jiao 	devm_free_irq(mdev->dev, irq, dev);
121799ad32a4SBo Jiao free_device:
1218*eebb7097SLorenzo Bianconi 	if (mtk_wed_device_active(&mdev->mmio.wed))
1219*eebb7097SLorenzo Bianconi 		mtk_wed_device_detach(&mdev->mmio.wed);
1220*eebb7097SLorenzo Bianconi 	mt76_free_device(mdev);
122199ad32a4SBo Jiao 
122299ad32a4SBo Jiao 	return ret;
122399ad32a4SBo Jiao }
122499ad32a4SBo Jiao 
122599ad32a4SBo Jiao static int mt7986_wmac_remove(struct platform_device *pdev)
122699ad32a4SBo Jiao {
122799ad32a4SBo Jiao 	struct mt7915_dev *dev = platform_get_drvdata(pdev);
122899ad32a4SBo Jiao 
122999ad32a4SBo Jiao 	mt7915_unregister_device(dev);
123099ad32a4SBo Jiao 
123199ad32a4SBo Jiao 	return 0;
123299ad32a4SBo Jiao }
123399ad32a4SBo Jiao 
123499ad32a4SBo Jiao static const struct of_device_id mt7986_wmac_of_match[] = {
123599ad32a4SBo Jiao 	{ .compatible = "mediatek,mt7986-wmac", .data = (u32 *)0x7986 },
123699ad32a4SBo Jiao 	{},
123799ad32a4SBo Jiao };
123899ad32a4SBo Jiao 
123999ad32a4SBo Jiao struct platform_driver mt7986_wmac_driver = {
124099ad32a4SBo Jiao 	.driver = {
124199ad32a4SBo Jiao 		.name = "mt7986-wmac",
124299ad32a4SBo Jiao 		.of_match_table = mt7986_wmac_of_match,
124399ad32a4SBo Jiao 	},
124499ad32a4SBo Jiao 	.probe = mt7986_wmac_probe,
124599ad32a4SBo Jiao 	.remove = mt7986_wmac_remove,
124699ad32a4SBo Jiao };
124799ad32a4SBo Jiao 
124899ad32a4SBo Jiao MODULE_FIRMWARE(MT7986_FIRMWARE_WA);
124999ad32a4SBo Jiao MODULE_FIRMWARE(MT7986_FIRMWARE_WM);
125099ad32a4SBo Jiao MODULE_FIRMWARE(MT7986_FIRMWARE_WM_MT7975);
125199ad32a4SBo Jiao MODULE_FIRMWARE(MT7986_ROM_PATCH);
125299ad32a4SBo Jiao MODULE_FIRMWARE(MT7986_ROM_PATCH_MT7975);
1253