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_reserved_mem.h>
1099ad32a4SBo Jiao #include <linux/of_gpio.h>
1199ad32a4SBo Jiao #include <linux/iopoll.h>
1299ad32a4SBo Jiao #include <linux/reset.h>
1399ad32a4SBo Jiao #include <linux/of_net.h>
14cd85efdfSLorenzo Bianconi #include <linux/clk.h>
1599ad32a4SBo Jiao
1699ad32a4SBo Jiao #include "mt7915.h"
1799ad32a4SBo Jiao
18*6bad146dSAlexander Couzens #define MT7981_CON_INFRA_VERSION 0x02090000
19*6bad146dSAlexander Couzens #define MT7986_CON_INFRA_VERSION 0x02070000
20*6bad146dSAlexander Couzens
2199ad32a4SBo Jiao /* INFRACFG */
2299ad32a4SBo Jiao #define MT_INFRACFG_CONN2AP_SLPPROT 0x0d0
2399ad32a4SBo Jiao #define MT_INFRACFG_AP2CONN_SLPPROT 0x0d4
2499ad32a4SBo Jiao
2599ad32a4SBo Jiao #define MT_INFRACFG_RX_EN_MASK BIT(16)
2699ad32a4SBo Jiao #define MT_INFRACFG_TX_RDY_MASK BIT(4)
2799ad32a4SBo Jiao #define MT_INFRACFG_TX_EN_MASK BIT(0)
2899ad32a4SBo Jiao
2999ad32a4SBo Jiao /* TOP POS */
3099ad32a4SBo Jiao #define MT_TOP_POS_FAST_CTRL 0x114
3199ad32a4SBo Jiao #define MT_TOP_POS_FAST_EN_MASK BIT(3)
3299ad32a4SBo Jiao
3399ad32a4SBo Jiao #define MT_TOP_POS_SKU 0x21c
3499ad32a4SBo Jiao #define MT_TOP_POS_SKU_MASK GENMASK(31, 28)
3599ad32a4SBo Jiao #define MT_TOP_POS_SKU_ADIE_DBDC_MASK BIT(2)
3699ad32a4SBo Jiao
3799ad32a4SBo Jiao enum {
3899ad32a4SBo Jiao ADIE_SB,
3999ad32a4SBo Jiao ADIE_DBDC
4099ad32a4SBo Jiao };
4199ad32a4SBo Jiao
4299ad32a4SBo Jiao static int
mt76_wmac_spi_read(struct mt7915_dev * dev,u8 adie,u32 addr,u32 * val)4399ad32a4SBo Jiao mt76_wmac_spi_read(struct mt7915_dev *dev, u8 adie, u32 addr, u32 *val)
4499ad32a4SBo Jiao {
4599ad32a4SBo Jiao int ret;
4699ad32a4SBo Jiao u32 cur;
4799ad32a4SBo Jiao
4899ad32a4SBo Jiao ret = read_poll_timeout(mt76_rr, cur, !(cur & MT_TOP_SPI_POLLING_BIT),
4999ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
5099ad32a4SBo Jiao dev, MT_TOP_SPI_BUSY_CR(adie));
5199ad32a4SBo Jiao if (ret)
5299ad32a4SBo Jiao return ret;
5399ad32a4SBo Jiao
5499ad32a4SBo Jiao mt76_wr(dev, MT_TOP_SPI_ADDR_CR(adie),
5599ad32a4SBo Jiao MT_TOP_SPI_READ_ADDR_FORMAT | addr);
5699ad32a4SBo Jiao mt76_wr(dev, MT_TOP_SPI_WRITE_DATA_CR(adie), 0);
5799ad32a4SBo Jiao
5899ad32a4SBo Jiao ret = read_poll_timeout(mt76_rr, cur, !(cur & MT_TOP_SPI_POLLING_BIT),
5999ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
6099ad32a4SBo Jiao dev, MT_TOP_SPI_BUSY_CR(adie));
6199ad32a4SBo Jiao if (ret)
6299ad32a4SBo Jiao return ret;
6399ad32a4SBo Jiao
6499ad32a4SBo Jiao *val = mt76_rr(dev, MT_TOP_SPI_READ_DATA_CR(adie));
6599ad32a4SBo Jiao
6699ad32a4SBo Jiao return 0;
6799ad32a4SBo Jiao }
6899ad32a4SBo Jiao
6999ad32a4SBo Jiao static int
mt76_wmac_spi_write(struct mt7915_dev * dev,u8 adie,u32 addr,u32 val)7099ad32a4SBo Jiao mt76_wmac_spi_write(struct mt7915_dev *dev, u8 adie, u32 addr, u32 val)
7199ad32a4SBo Jiao {
7299ad32a4SBo Jiao int ret;
7399ad32a4SBo Jiao u32 cur;
7499ad32a4SBo Jiao
7599ad32a4SBo Jiao ret = read_poll_timeout(mt76_rr, cur, !(cur & MT_TOP_SPI_POLLING_BIT),
7699ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
7799ad32a4SBo Jiao dev, MT_TOP_SPI_BUSY_CR(adie));
7899ad32a4SBo Jiao if (ret)
7999ad32a4SBo Jiao return ret;
8099ad32a4SBo Jiao
8199ad32a4SBo Jiao mt76_wr(dev, MT_TOP_SPI_ADDR_CR(adie),
8299ad32a4SBo Jiao MT_TOP_SPI_WRITE_ADDR_FORMAT | addr);
8399ad32a4SBo Jiao mt76_wr(dev, MT_TOP_SPI_WRITE_DATA_CR(adie), val);
8499ad32a4SBo Jiao
8599ad32a4SBo Jiao return read_poll_timeout(mt76_rr, cur, !(cur & MT_TOP_SPI_POLLING_BIT),
8699ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
8799ad32a4SBo Jiao dev, MT_TOP_SPI_BUSY_CR(adie));
8899ad32a4SBo Jiao }
8999ad32a4SBo Jiao
9099ad32a4SBo Jiao static int
mt76_wmac_spi_rmw(struct mt7915_dev * dev,u8 adie,u32 addr,u32 mask,u32 val)9199ad32a4SBo Jiao mt76_wmac_spi_rmw(struct mt7915_dev *dev, u8 adie,
9299ad32a4SBo Jiao u32 addr, u32 mask, u32 val)
9399ad32a4SBo Jiao {
9499ad32a4SBo Jiao u32 cur, ret;
9599ad32a4SBo Jiao
9699ad32a4SBo Jiao ret = mt76_wmac_spi_read(dev, adie, addr, &cur);
9799ad32a4SBo Jiao if (ret)
9899ad32a4SBo Jiao return ret;
9999ad32a4SBo Jiao
10099ad32a4SBo Jiao cur &= ~mask;
10199ad32a4SBo Jiao cur |= val;
10299ad32a4SBo Jiao
10399ad32a4SBo Jiao return mt76_wmac_spi_write(dev, adie, addr, cur);
10499ad32a4SBo Jiao }
10599ad32a4SBo Jiao
10699ad32a4SBo Jiao static int
mt7986_wmac_adie_efuse_read(struct mt7915_dev * dev,u8 adie,u32 addr,u32 * data)10799ad32a4SBo Jiao mt7986_wmac_adie_efuse_read(struct mt7915_dev *dev, u8 adie,
10899ad32a4SBo Jiao u32 addr, u32 *data)
10999ad32a4SBo Jiao {
11099ad32a4SBo Jiao int ret, temp;
11199ad32a4SBo Jiao u32 val, mask;
11299ad32a4SBo Jiao
11399ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_EFUSE_CFG,
11499ad32a4SBo Jiao MT_ADIE_EFUSE_CTRL_MASK);
11599ad32a4SBo Jiao if (ret)
11699ad32a4SBo Jiao return ret;
11799ad32a4SBo Jiao
11899ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_EFUSE2_CTRL, BIT(30), 0x0);
11999ad32a4SBo Jiao if (ret)
12099ad32a4SBo Jiao return ret;
12199ad32a4SBo Jiao
12299ad32a4SBo Jiao mask = (MT_ADIE_EFUSE_MODE_MASK | MT_ADIE_EFUSE_ADDR_MASK |
12399ad32a4SBo Jiao MT_ADIE_EFUSE_KICK_MASK);
12499ad32a4SBo Jiao val = FIELD_PREP(MT_ADIE_EFUSE_MODE_MASK, 0) |
12599ad32a4SBo Jiao FIELD_PREP(MT_ADIE_EFUSE_ADDR_MASK, addr) |
12699ad32a4SBo Jiao FIELD_PREP(MT_ADIE_EFUSE_KICK_MASK, 1);
12799ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_EFUSE2_CTRL, mask, val);
12899ad32a4SBo Jiao if (ret)
12999ad32a4SBo Jiao return ret;
13099ad32a4SBo Jiao
13199ad32a4SBo Jiao ret = read_poll_timeout(mt76_wmac_spi_read, temp,
13299ad32a4SBo Jiao !temp && !FIELD_GET(MT_ADIE_EFUSE_KICK_MASK, val),
13399ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
13499ad32a4SBo Jiao dev, adie, MT_ADIE_EFUSE2_CTRL, &val);
13599ad32a4SBo Jiao if (ret)
13699ad32a4SBo Jiao return ret;
13799ad32a4SBo Jiao
13899ad32a4SBo Jiao ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_EFUSE2_CTRL, &val);
13999ad32a4SBo Jiao if (ret)
14099ad32a4SBo Jiao return ret;
14199ad32a4SBo Jiao
14299ad32a4SBo Jiao if (FIELD_GET(MT_ADIE_EFUSE_VALID_MASK, val) == 1)
14399ad32a4SBo Jiao ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_EFUSE_RDATA0,
14499ad32a4SBo Jiao data);
14599ad32a4SBo Jiao
14699ad32a4SBo Jiao return ret;
14799ad32a4SBo Jiao }
14899ad32a4SBo Jiao
mt76_wmac_spi_lock(struct mt7915_dev * dev)14999ad32a4SBo Jiao static inline void mt76_wmac_spi_lock(struct mt7915_dev *dev)
15099ad32a4SBo Jiao {
15199ad32a4SBo Jiao u32 cur;
15299ad32a4SBo Jiao
15399ad32a4SBo Jiao read_poll_timeout(mt76_rr, cur,
15499ad32a4SBo Jiao FIELD_GET(MT_SEMA_RFSPI_STATUS_MASK, cur),
15599ad32a4SBo Jiao 1000, 1000 * MSEC_PER_SEC, false, dev,
15699ad32a4SBo Jiao MT_SEMA_RFSPI_STATUS);
15799ad32a4SBo Jiao }
15899ad32a4SBo Jiao
mt76_wmac_spi_unlock(struct mt7915_dev * dev)15999ad32a4SBo Jiao static inline void mt76_wmac_spi_unlock(struct mt7915_dev *dev)
16099ad32a4SBo Jiao {
16199ad32a4SBo Jiao mt76_wr(dev, MT_SEMA_RFSPI_RELEASE, 1);
16299ad32a4SBo Jiao }
16399ad32a4SBo Jiao
mt76_wmac_rmw(void __iomem * base,u32 offset,u32 mask,u32 val)16499ad32a4SBo Jiao static u32 mt76_wmac_rmw(void __iomem *base, u32 offset, u32 mask, u32 val)
16599ad32a4SBo Jiao {
16699ad32a4SBo Jiao val |= readl(base + offset) & ~mask;
16799ad32a4SBo Jiao writel(val, base + offset);
16899ad32a4SBo Jiao
16999ad32a4SBo Jiao return val;
17099ad32a4SBo Jiao }
17199ad32a4SBo Jiao
mt798x_wmac_check_adie_type(struct mt7915_dev * dev)172*6bad146dSAlexander Couzens static u8 mt798x_wmac_check_adie_type(struct mt7915_dev *dev)
17399ad32a4SBo Jiao {
17499ad32a4SBo Jiao u32 val;
17599ad32a4SBo Jiao
176*6bad146dSAlexander Couzens /* Only DBDC A-die is used with MT7981 */
177*6bad146dSAlexander Couzens if (is_mt7981(&dev->mt76))
178*6bad146dSAlexander Couzens return ADIE_DBDC;
179*6bad146dSAlexander Couzens
18099ad32a4SBo Jiao val = readl(dev->sku + MT_TOP_POS_SKU);
18199ad32a4SBo Jiao
18299ad32a4SBo Jiao return FIELD_GET(MT_TOP_POS_SKU_ADIE_DBDC_MASK, val);
18399ad32a4SBo Jiao }
18499ad32a4SBo Jiao
mt7986_wmac_consys_reset(struct mt7915_dev * dev,bool enable)18599ad32a4SBo Jiao static int mt7986_wmac_consys_reset(struct mt7915_dev *dev, bool enable)
18699ad32a4SBo Jiao {
18799ad32a4SBo Jiao if (!enable)
18899ad32a4SBo Jiao return reset_control_assert(dev->rstc);
18999ad32a4SBo Jiao
19099ad32a4SBo Jiao mt76_wmac_rmw(dev->sku, MT_TOP_POS_FAST_CTRL,
19199ad32a4SBo Jiao MT_TOP_POS_FAST_EN_MASK,
19299ad32a4SBo Jiao FIELD_PREP(MT_TOP_POS_FAST_EN_MASK, 0x1));
19399ad32a4SBo Jiao
19499ad32a4SBo Jiao return reset_control_deassert(dev->rstc);
19599ad32a4SBo Jiao }
19699ad32a4SBo Jiao
mt7986_wmac_gpio_setup(struct mt7915_dev * dev)19799ad32a4SBo Jiao static int mt7986_wmac_gpio_setup(struct mt7915_dev *dev)
19899ad32a4SBo Jiao {
19999ad32a4SBo Jiao struct pinctrl_state *state;
20099ad32a4SBo Jiao struct pinctrl *pinctrl;
20199ad32a4SBo Jiao int ret;
20299ad32a4SBo Jiao u8 type;
20399ad32a4SBo Jiao
204*6bad146dSAlexander Couzens type = mt798x_wmac_check_adie_type(dev);
20599ad32a4SBo Jiao pinctrl = devm_pinctrl_get(dev->mt76.dev);
20601318bc0SDan Carpenter if (IS_ERR(pinctrl))
20701318bc0SDan Carpenter return PTR_ERR(pinctrl);
20899ad32a4SBo Jiao
20999ad32a4SBo Jiao switch (type) {
21099ad32a4SBo Jiao case ADIE_SB:
21199ad32a4SBo Jiao state = pinctrl_lookup_state(pinctrl, "default");
21299ad32a4SBo Jiao if (IS_ERR_OR_NULL(state))
21399ad32a4SBo Jiao return -EINVAL;
21499ad32a4SBo Jiao break;
21599ad32a4SBo Jiao case ADIE_DBDC:
21699ad32a4SBo Jiao state = pinctrl_lookup_state(pinctrl, "dbdc");
21799ad32a4SBo Jiao if (IS_ERR_OR_NULL(state))
21899ad32a4SBo Jiao return -EINVAL;
21999ad32a4SBo Jiao break;
2209bd6823fSLorenzo Bianconi default:
2219bd6823fSLorenzo Bianconi return -EINVAL;
22299ad32a4SBo Jiao }
22399ad32a4SBo Jiao
22499ad32a4SBo Jiao ret = pinctrl_select_state(pinctrl, state);
22599ad32a4SBo Jiao if (ret)
22699ad32a4SBo Jiao return ret;
22799ad32a4SBo Jiao
22899ad32a4SBo Jiao usleep_range(500, 1000);
22999ad32a4SBo Jiao
23099ad32a4SBo Jiao return 0;
23199ad32a4SBo Jiao }
23299ad32a4SBo Jiao
mt7986_wmac_consys_lockup(struct mt7915_dev * dev,bool enable)23399ad32a4SBo Jiao static int mt7986_wmac_consys_lockup(struct mt7915_dev *dev, bool enable)
23499ad32a4SBo Jiao {
23599ad32a4SBo Jiao int ret;
23699ad32a4SBo Jiao u32 cur;
23799ad32a4SBo Jiao
23899ad32a4SBo Jiao mt76_wmac_rmw(dev->dcm, MT_INFRACFG_AP2CONN_SLPPROT,
23999ad32a4SBo Jiao MT_INFRACFG_RX_EN_MASK,
24099ad32a4SBo Jiao FIELD_PREP(MT_INFRACFG_RX_EN_MASK, enable));
24199ad32a4SBo Jiao ret = read_poll_timeout(readl, cur, !(cur & MT_INFRACFG_RX_EN_MASK),
24299ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
24399ad32a4SBo Jiao dev->dcm + MT_INFRACFG_AP2CONN_SLPPROT);
24499ad32a4SBo Jiao if (ret)
24599ad32a4SBo Jiao return ret;
24699ad32a4SBo Jiao
24799ad32a4SBo Jiao mt76_wmac_rmw(dev->dcm, MT_INFRACFG_AP2CONN_SLPPROT,
24899ad32a4SBo Jiao MT_INFRACFG_TX_EN_MASK,
24999ad32a4SBo Jiao FIELD_PREP(MT_INFRACFG_TX_EN_MASK, enable));
25099ad32a4SBo Jiao ret = read_poll_timeout(readl, cur, !(cur & MT_INFRACFG_TX_RDY_MASK),
25199ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
25299ad32a4SBo Jiao dev->dcm + MT_INFRACFG_AP2CONN_SLPPROT);
25399ad32a4SBo Jiao if (ret)
25499ad32a4SBo Jiao return ret;
25599ad32a4SBo Jiao
25699ad32a4SBo Jiao mt76_wmac_rmw(dev->dcm, MT_INFRACFG_CONN2AP_SLPPROT,
25799ad32a4SBo Jiao MT_INFRACFG_RX_EN_MASK,
25899ad32a4SBo Jiao FIELD_PREP(MT_INFRACFG_RX_EN_MASK, enable));
25999ad32a4SBo Jiao mt76_wmac_rmw(dev->dcm, MT_INFRACFG_CONN2AP_SLPPROT,
26099ad32a4SBo Jiao MT_INFRACFG_TX_EN_MASK,
26199ad32a4SBo Jiao FIELD_PREP(MT_INFRACFG_TX_EN_MASK, enable));
26299ad32a4SBo Jiao
26399ad32a4SBo Jiao return 0;
26499ad32a4SBo Jiao }
26599ad32a4SBo Jiao
mt798x_wmac_coninfra_check(struct mt7915_dev * dev)266*6bad146dSAlexander Couzens static int mt798x_wmac_coninfra_check(struct mt7915_dev *dev)
26799ad32a4SBo Jiao {
26899ad32a4SBo Jiao u32 cur;
269*6bad146dSAlexander Couzens u32 con_infra_version;
27099ad32a4SBo Jiao
271*6bad146dSAlexander Couzens if (is_mt7981(&dev->mt76)) {
272*6bad146dSAlexander Couzens con_infra_version = MT7981_CON_INFRA_VERSION;
273*6bad146dSAlexander Couzens } else if (is_mt7986(&dev->mt76)) {
274*6bad146dSAlexander Couzens con_infra_version = MT7986_CON_INFRA_VERSION;
275*6bad146dSAlexander Couzens } else {
276*6bad146dSAlexander Couzens WARN_ON(1);
277*6bad146dSAlexander Couzens return -EINVAL;
278*6bad146dSAlexander Couzens }
279*6bad146dSAlexander Couzens
280*6bad146dSAlexander Couzens return read_poll_timeout(mt76_rr, cur, (cur == con_infra_version),
28199ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC,
28299ad32a4SBo Jiao false, dev, MT_CONN_INFRA_BASE);
28399ad32a4SBo Jiao }
28499ad32a4SBo Jiao
mt798x_wmac_coninfra_setup(struct mt7915_dev * dev)285*6bad146dSAlexander Couzens static int mt798x_wmac_coninfra_setup(struct mt7915_dev *dev)
28699ad32a4SBo Jiao {
28799ad32a4SBo Jiao struct device *pdev = dev->mt76.dev;
28899ad32a4SBo Jiao struct reserved_mem *rmem;
28999ad32a4SBo Jiao struct device_node *np;
29099ad32a4SBo Jiao u32 val;
29199ad32a4SBo Jiao
29299ad32a4SBo Jiao np = of_parse_phandle(pdev->of_node, "memory-region", 0);
29399ad32a4SBo Jiao if (!np)
29499ad32a4SBo Jiao return -EINVAL;
29599ad32a4SBo Jiao
29699ad32a4SBo Jiao rmem = of_reserved_mem_lookup(np);
29718425d7dSWang Yufen of_node_put(np);
29899ad32a4SBo Jiao if (!rmem)
29999ad32a4SBo Jiao return -EINVAL;
30099ad32a4SBo Jiao
30199ad32a4SBo Jiao val = (rmem->base >> 16) & MT_TOP_MCU_EMI_BASE_MASK;
30299ad32a4SBo Jiao
303*6bad146dSAlexander Couzens if (is_mt7986(&dev->mt76)) {
30499ad32a4SBo Jiao /* Set conninfra subsys PLL check */
30599ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS,
30699ad32a4SBo Jiao MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1);
30799ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS,
30899ad32a4SBo Jiao MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1);
309*6bad146dSAlexander Couzens }
31099ad32a4SBo Jiao
31199ad32a4SBo Jiao mt76_rmw_field(dev, MT_TOP_MCU_EMI_BASE,
31299ad32a4SBo Jiao MT_TOP_MCU_EMI_BASE_MASK, val);
31399ad32a4SBo Jiao
314*6bad146dSAlexander Couzens if (is_mt7981(&dev->mt76)) {
315*6bad146dSAlexander Couzens mt76_rmw_field(dev, MT_TOP_WF_AP_PERI_BASE,
316*6bad146dSAlexander Couzens MT_TOP_WF_AP_PERI_BASE_MASK, 0x300d0000 >> 16);
317*6bad146dSAlexander Couzens
318*6bad146dSAlexander Couzens mt76_rmw_field(dev, MT_TOP_EFUSE_BASE,
319*6bad146dSAlexander Couzens MT_TOP_EFUSE_BASE_MASK, 0x11f20000 >> 16);
320*6bad146dSAlexander Couzens }
321*6bad146dSAlexander Couzens
32299ad32a4SBo Jiao mt76_wr(dev, MT_INFRA_BUS_EMI_START, rmem->base);
32399ad32a4SBo Jiao mt76_wr(dev, MT_INFRA_BUS_EMI_END, rmem->size);
32499ad32a4SBo Jiao
32599ad32a4SBo Jiao mt76_rr(dev, MT_CONN_INFRA_EFUSE);
32699ad32a4SBo Jiao
32799ad32a4SBo Jiao /* Set conninfra sysram */
32899ad32a4SBo Jiao mt76_wr(dev, MT_TOP_RGU_SYSRAM_PDN, 0);
32999ad32a4SBo Jiao mt76_wr(dev, MT_TOP_RGU_SYSRAM_SLP, 1);
33099ad32a4SBo Jiao
33199ad32a4SBo Jiao return 0;
33299ad32a4SBo Jiao }
33399ad32a4SBo Jiao
mt798x_wmac_sku_setup(struct mt7915_dev * dev,u32 * adie_type)334*6bad146dSAlexander Couzens static int mt798x_wmac_sku_setup(struct mt7915_dev *dev, u32 *adie_type)
33599ad32a4SBo Jiao {
33699ad32a4SBo Jiao int ret;
337*6bad146dSAlexander Couzens u32 adie_main = 0, adie_ext = 0;
33899ad32a4SBo Jiao
33999ad32a4SBo Jiao mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET,
34099ad32a4SBo Jiao MT_CONN_INFRA_ADIE1_RESET_MASK, 0x1);
341*6bad146dSAlexander Couzens
342*6bad146dSAlexander Couzens if (is_mt7986(&dev->mt76)) {
34399ad32a4SBo Jiao mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET,
34499ad32a4SBo Jiao MT_CONN_INFRA_ADIE2_RESET_MASK, 0x1);
345*6bad146dSAlexander Couzens }
34699ad32a4SBo Jiao
34799ad32a4SBo Jiao mt76_wmac_spi_lock(dev);
34899ad32a4SBo Jiao
34999ad32a4SBo Jiao ret = mt76_wmac_spi_read(dev, 0, MT_ADIE_CHIP_ID, &adie_main);
35099ad32a4SBo Jiao if (ret)
35199ad32a4SBo Jiao goto out;
35299ad32a4SBo Jiao
353*6bad146dSAlexander Couzens if (is_mt7986(&dev->mt76)) {
35499ad32a4SBo Jiao ret = mt76_wmac_spi_read(dev, 1, MT_ADIE_CHIP_ID, &adie_ext);
35599ad32a4SBo Jiao if (ret)
35699ad32a4SBo Jiao goto out;
357*6bad146dSAlexander Couzens }
35899ad32a4SBo Jiao
35999ad32a4SBo Jiao *adie_type = FIELD_GET(MT_ADIE_CHIP_ID_MASK, adie_main) |
36099ad32a4SBo Jiao (MT_ADIE_CHIP_ID_MASK & adie_ext);
36199ad32a4SBo Jiao
36299ad32a4SBo Jiao out:
36399ad32a4SBo Jiao mt76_wmac_spi_unlock(dev);
36499ad32a4SBo Jiao
36599ad32a4SBo Jiao return 0;
36699ad32a4SBo Jiao }
36799ad32a4SBo Jiao
mt7986_adie_idx(u8 adie,u32 adie_type)36899ad32a4SBo Jiao static inline u16 mt7986_adie_idx(u8 adie, u32 adie_type)
36999ad32a4SBo Jiao {
37099ad32a4SBo Jiao if (adie == 0)
37199ad32a4SBo Jiao return u32_get_bits(adie_type, MT_ADIE_IDX0);
37299ad32a4SBo Jiao else
37399ad32a4SBo Jiao return u32_get_bits(adie_type, MT_ADIE_IDX1);
37499ad32a4SBo Jiao }
37599ad32a4SBo Jiao
is_7975(struct mt7915_dev * dev,u8 adie,u32 adie_type)37699ad32a4SBo Jiao static inline bool is_7975(struct mt7915_dev *dev, u8 adie, u32 adie_type)
37799ad32a4SBo Jiao {
37899ad32a4SBo Jiao return mt7986_adie_idx(adie, adie_type) == 0x7975;
37999ad32a4SBo Jiao }
38099ad32a4SBo Jiao
is_7976(struct mt7915_dev * dev,u8 adie,u32 adie_type)38199ad32a4SBo Jiao static inline bool is_7976(struct mt7915_dev *dev, u8 adie, u32 adie_type)
38299ad32a4SBo Jiao {
38399ad32a4SBo Jiao return mt7986_adie_idx(adie, adie_type) == 0x7976;
38499ad32a4SBo Jiao }
38599ad32a4SBo Jiao
mt7986_wmac_adie_thermal_cal(struct mt7915_dev * dev,u8 adie)38699ad32a4SBo Jiao static int mt7986_wmac_adie_thermal_cal(struct mt7915_dev *dev, u8 adie)
38799ad32a4SBo Jiao {
38899ad32a4SBo Jiao int ret;
38999ad32a4SBo Jiao u32 data, val;
39099ad32a4SBo Jiao
39199ad32a4SBo Jiao ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_THADC_ANALOG,
39299ad32a4SBo Jiao &data);
39399ad32a4SBo Jiao if (ret || FIELD_GET(MT_ADIE_ANA_EN_MASK, data)) {
39499ad32a4SBo Jiao val = FIELD_GET(MT_ADIE_VRPI_SEL_EFUSE_MASK, data);
39599ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_RG_TOP_THADC_BG,
39699ad32a4SBo Jiao MT_ADIE_VRPI_SEL_CR_MASK,
39799ad32a4SBo Jiao FIELD_PREP(MT_ADIE_VRPI_SEL_CR_MASK, val));
39899ad32a4SBo Jiao if (ret)
39999ad32a4SBo Jiao return ret;
40099ad32a4SBo Jiao
40199ad32a4SBo Jiao val = FIELD_GET(MT_ADIE_PGA_GAIN_EFUSE_MASK, data);
40299ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_RG_TOP_THADC,
40399ad32a4SBo Jiao MT_ADIE_PGA_GAIN_MASK,
40499ad32a4SBo Jiao FIELD_PREP(MT_ADIE_PGA_GAIN_MASK, val));
40599ad32a4SBo Jiao if (ret)
40699ad32a4SBo Jiao return ret;
40799ad32a4SBo Jiao }
40899ad32a4SBo Jiao
40999ad32a4SBo Jiao ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_THADC_SLOP,
41099ad32a4SBo Jiao &data);
41199ad32a4SBo Jiao if (ret || FIELD_GET(MT_ADIE_ANA_EN_MASK, data)) {
41299ad32a4SBo Jiao val = FIELD_GET(MT_ADIE_LDO_CTRL_EFUSE_MASK, data);
41399ad32a4SBo Jiao
41499ad32a4SBo Jiao return mt76_wmac_spi_rmw(dev, adie, MT_ADIE_RG_TOP_THADC,
41599ad32a4SBo Jiao MT_ADIE_LDO_CTRL_MASK,
41699ad32a4SBo Jiao FIELD_PREP(MT_ADIE_LDO_CTRL_MASK, val));
41799ad32a4SBo Jiao }
41899ad32a4SBo Jiao
41999ad32a4SBo Jiao return 0;
42099ad32a4SBo Jiao }
42199ad32a4SBo Jiao
42299ad32a4SBo Jiao static int
mt7986_read_efuse_xo_trim_7976(struct mt7915_dev * dev,u8 adie,bool is_40m,int * result)42399ad32a4SBo Jiao mt7986_read_efuse_xo_trim_7976(struct mt7915_dev *dev, u8 adie,
42499ad32a4SBo Jiao bool is_40m, int *result)
42599ad32a4SBo Jiao {
42699ad32a4SBo Jiao int ret;
42799ad32a4SBo Jiao u32 data, addr;
42899ad32a4SBo Jiao
42999ad32a4SBo Jiao addr = is_40m ? MT_ADIE_XTAL_AXM_40M_OSC : MT_ADIE_XTAL_AXM_80M_OSC;
43099ad32a4SBo Jiao ret = mt7986_wmac_adie_efuse_read(dev, adie, addr, &data);
43199ad32a4SBo Jiao if (ret)
43299ad32a4SBo Jiao return ret;
43399ad32a4SBo Jiao
43499ad32a4SBo Jiao if (!FIELD_GET(MT_ADIE_XO_TRIM_EN_MASK, data)) {
43599ad32a4SBo Jiao *result = 64;
43699ad32a4SBo Jiao } else {
43799ad32a4SBo Jiao *result = FIELD_GET(MT_ADIE_TRIM_MASK, data);
43899ad32a4SBo Jiao addr = is_40m ? MT_ADIE_XTAL_TRIM1_40M_OSC :
43999ad32a4SBo Jiao MT_ADIE_XTAL_TRIM1_80M_OSC;
44099ad32a4SBo Jiao ret = mt7986_wmac_adie_efuse_read(dev, adie, addr, &data);
44199ad32a4SBo Jiao if (ret)
44299ad32a4SBo Jiao return ret;
44399ad32a4SBo Jiao
44499ad32a4SBo Jiao if (FIELD_GET(MT_ADIE_XO_TRIM_EN_MASK, data) &&
44599ad32a4SBo Jiao FIELD_GET(MT_ADIE_XTAL_DECREASE_MASK, data))
44699ad32a4SBo Jiao *result -= FIELD_GET(MT_ADIE_EFUSE_TRIM_MASK, data);
44799ad32a4SBo Jiao else if (FIELD_GET(MT_ADIE_XO_TRIM_EN_MASK, data))
44899ad32a4SBo Jiao *result += FIELD_GET(MT_ADIE_EFUSE_TRIM_MASK, data);
44999ad32a4SBo Jiao
45099ad32a4SBo Jiao *result = max(0, min(127, *result));
45199ad32a4SBo Jiao }
45299ad32a4SBo Jiao
45399ad32a4SBo Jiao return 0;
45499ad32a4SBo Jiao }
45599ad32a4SBo Jiao
mt7986_wmac_adie_xtal_trim_7976(struct mt7915_dev * dev,u8 adie)45699ad32a4SBo Jiao static int mt7986_wmac_adie_xtal_trim_7976(struct mt7915_dev *dev, u8 adie)
45799ad32a4SBo Jiao {
45899ad32a4SBo Jiao int ret, trim_80m, trim_40m;
45999ad32a4SBo Jiao u32 data, val, mode;
46099ad32a4SBo Jiao
46199ad32a4SBo Jiao ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_XO_TRIM_FLOW,
46299ad32a4SBo Jiao &data);
46399ad32a4SBo Jiao if (ret || !FIELD_GET(BIT(1), data))
46499ad32a4SBo Jiao return 0;
46599ad32a4SBo Jiao
46699ad32a4SBo Jiao ret = mt7986_read_efuse_xo_trim_7976(dev, adie, false, &trim_80m);
46799ad32a4SBo Jiao if (ret)
46899ad32a4SBo Jiao return ret;
46999ad32a4SBo Jiao
47099ad32a4SBo Jiao ret = mt7986_read_efuse_xo_trim_7976(dev, adie, true, &trim_40m);
47199ad32a4SBo Jiao if (ret)
47299ad32a4SBo Jiao return ret;
47399ad32a4SBo Jiao
47499ad32a4SBo Jiao ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_RG_STRAP_PIN_IN, &val);
47599ad32a4SBo Jiao if (ret)
47699ad32a4SBo Jiao return ret;
47799ad32a4SBo Jiao
47899ad32a4SBo Jiao mode = FIELD_PREP(GENMASK(6, 4), val);
47999ad32a4SBo Jiao if (!mode || mode == 0x2) {
48099ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C1,
48199ad32a4SBo Jiao GENMASK(31, 24),
48299ad32a4SBo Jiao FIELD_PREP(GENMASK(31, 24), trim_80m));
48399ad32a4SBo Jiao if (ret)
48499ad32a4SBo Jiao return ret;
48599ad32a4SBo Jiao
48699ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C2,
48799ad32a4SBo Jiao GENMASK(31, 24),
48899ad32a4SBo Jiao FIELD_PREP(GENMASK(31, 24), trim_80m));
48999ad32a4SBo Jiao } else if (mode == 0x3 || mode == 0x4 || mode == 0x6) {
49099ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C1,
49199ad32a4SBo Jiao GENMASK(23, 16),
49299ad32a4SBo Jiao FIELD_PREP(GENMASK(23, 16), trim_40m));
49399ad32a4SBo Jiao if (ret)
49499ad32a4SBo Jiao return ret;
49599ad32a4SBo Jiao
49699ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C2,
49799ad32a4SBo Jiao GENMASK(23, 16),
49899ad32a4SBo Jiao FIELD_PREP(GENMASK(23, 16), trim_40m));
49999ad32a4SBo Jiao }
50099ad32a4SBo Jiao
50199ad32a4SBo Jiao return ret;
50299ad32a4SBo Jiao }
50399ad32a4SBo Jiao
mt798x_wmac_adie_patch_7976(struct mt7915_dev * dev,u8 adie)504*6bad146dSAlexander Couzens static int mt798x_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie)
50599ad32a4SBo Jiao {
506b5509983SPeter Chiu u32 id, version, rg_xo_01, rg_xo_03;
50799ad32a4SBo Jiao int ret;
50899ad32a4SBo Jiao
509b5509983SPeter Chiu ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_CHIP_ID, &id);
510b5509983SPeter Chiu if (ret)
511b5509983SPeter Chiu return ret;
512b5509983SPeter Chiu
513b5509983SPeter Chiu version = FIELD_GET(MT_ADIE_VERSION_MASK, id);
514b5509983SPeter Chiu
51599ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_TOP_THADC, 0x4a563b00);
51699ad32a4SBo Jiao if (ret)
51799ad32a4SBo Jiao return ret;
51899ad32a4SBo Jiao
519b5509983SPeter Chiu if (version == 0x8a00 || version == 0x8a10 || version == 0x8b00) {
520b5509983SPeter Chiu rg_xo_01 = 0x1d59080f;
521b5509983SPeter Chiu rg_xo_03 = 0x34c00fe0;
522b5509983SPeter Chiu } else {
523*6bad146dSAlexander Couzens if (is_mt7981(&dev->mt76)) {
524*6bad146dSAlexander Couzens rg_xo_01 = 0x1959c80f;
525*6bad146dSAlexander Couzens } else if (is_mt7986(&dev->mt76)) {
526b5509983SPeter Chiu rg_xo_01 = 0x1959f80f;
527*6bad146dSAlexander Couzens } else {
528*6bad146dSAlexander Couzens WARN_ON(1);
529*6bad146dSAlexander Couzens return -EINVAL;
530*6bad146dSAlexander Couzens }
531b5509983SPeter Chiu rg_xo_03 = 0x34d00fe0;
532b5509983SPeter Chiu }
533b5509983SPeter Chiu
534b5509983SPeter Chiu ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_01, rg_xo_01);
53599ad32a4SBo Jiao if (ret)
53699ad32a4SBo Jiao return ret;
53799ad32a4SBo Jiao
538b5509983SPeter Chiu return mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_03, rg_xo_03);
53999ad32a4SBo Jiao }
54099ad32a4SBo Jiao
54199ad32a4SBo Jiao static int
mt7986_read_efuse_xo_trim_7975(struct mt7915_dev * dev,u8 adie,u32 addr,u32 * result)54299ad32a4SBo Jiao mt7986_read_efuse_xo_trim_7975(struct mt7915_dev *dev, u8 adie,
54399ad32a4SBo Jiao u32 addr, u32 *result)
54499ad32a4SBo Jiao {
54599ad32a4SBo Jiao int ret;
54699ad32a4SBo Jiao u32 data;
54799ad32a4SBo Jiao
54899ad32a4SBo Jiao ret = mt7986_wmac_adie_efuse_read(dev, adie, addr, &data);
54999ad32a4SBo Jiao if (ret)
55099ad32a4SBo Jiao return ret;
55199ad32a4SBo Jiao
55299ad32a4SBo Jiao if ((data & MT_ADIE_XO_TRIM_EN_MASK)) {
55399ad32a4SBo Jiao if ((data & MT_ADIE_XTAL_DECREASE_MASK))
55499ad32a4SBo Jiao *result -= (data & MT_ADIE_EFUSE_TRIM_MASK);
55599ad32a4SBo Jiao else
55699ad32a4SBo Jiao *result += (data & MT_ADIE_EFUSE_TRIM_MASK);
55799ad32a4SBo Jiao
55899ad32a4SBo Jiao *result = (*result & MT_ADIE_TRIM_MASK);
55999ad32a4SBo Jiao }
56099ad32a4SBo Jiao
56199ad32a4SBo Jiao return 0;
56299ad32a4SBo Jiao }
56399ad32a4SBo Jiao
mt7986_wmac_adie_xtal_trim_7975(struct mt7915_dev * dev,u8 adie)56499ad32a4SBo Jiao static int mt7986_wmac_adie_xtal_trim_7975(struct mt7915_dev *dev, u8 adie)
56599ad32a4SBo Jiao {
56699ad32a4SBo Jiao int ret;
56799ad32a4SBo Jiao u32 data, result = 0, value;
56899ad32a4SBo Jiao
56999ad32a4SBo Jiao ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_7975_XTAL_EN,
57099ad32a4SBo Jiao &data);
57199ad32a4SBo Jiao if (ret || !(data & BIT(1)))
57299ad32a4SBo Jiao return 0;
57399ad32a4SBo Jiao
57499ad32a4SBo Jiao ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_7975_XTAL_CAL,
57599ad32a4SBo Jiao &data);
57699ad32a4SBo Jiao if (ret)
57799ad32a4SBo Jiao return ret;
57899ad32a4SBo Jiao
57999ad32a4SBo Jiao if (data & MT_ADIE_XO_TRIM_EN_MASK)
58099ad32a4SBo Jiao result = (data & MT_ADIE_TRIM_MASK);
58199ad32a4SBo Jiao
58299ad32a4SBo Jiao ret = mt7986_read_efuse_xo_trim_7975(dev, adie, MT_ADIE_7975_XO_TRIM2,
58399ad32a4SBo Jiao &result);
58499ad32a4SBo Jiao if (ret)
58599ad32a4SBo Jiao return ret;
58699ad32a4SBo Jiao
58799ad32a4SBo Jiao ret = mt7986_read_efuse_xo_trim_7975(dev, adie, MT_ADIE_7975_XO_TRIM3,
58899ad32a4SBo Jiao &result);
58999ad32a4SBo Jiao if (ret)
59099ad32a4SBo Jiao return ret;
59199ad32a4SBo Jiao
59299ad32a4SBo Jiao ret = mt7986_read_efuse_xo_trim_7975(dev, adie, MT_ADIE_7975_XO_TRIM4,
59399ad32a4SBo Jiao &result);
59499ad32a4SBo Jiao if (ret)
59599ad32a4SBo Jiao return ret;
59699ad32a4SBo Jiao
59799ad32a4SBo Jiao /* Update trim value to C1 and C2*/
59899ad32a4SBo Jiao value = FIELD_GET(MT_ADIE_7975_XO_CTRL2_C1_MASK, result) |
59999ad32a4SBo Jiao FIELD_GET(MT_ADIE_7975_XO_CTRL2_C2_MASK, result);
60099ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_XO_CTRL2,
60199ad32a4SBo Jiao MT_ADIE_7975_XO_CTRL2_MASK, value);
60299ad32a4SBo Jiao if (ret)
60399ad32a4SBo Jiao return ret;
60499ad32a4SBo Jiao
60599ad32a4SBo Jiao ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_7975_XTAL, &value);
60699ad32a4SBo Jiao if (ret)
60799ad32a4SBo Jiao return ret;
60899ad32a4SBo Jiao
60999ad32a4SBo Jiao if (value & MT_ADIE_7975_XTAL_EN_MASK) {
61099ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_XO_2,
61199ad32a4SBo Jiao MT_ADIE_7975_XO_2_FIX_EN, 0x0);
61299ad32a4SBo Jiao if (ret)
61399ad32a4SBo Jiao return ret;
61499ad32a4SBo Jiao }
61599ad32a4SBo Jiao
61699ad32a4SBo Jiao return mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_XO_CTRL6,
61799ad32a4SBo Jiao MT_ADIE_7975_XO_CTRL6_MASK, 0x1);
61899ad32a4SBo Jiao }
61999ad32a4SBo Jiao
mt7986_wmac_adie_patch_7975(struct mt7915_dev * dev,u8 adie)62099ad32a4SBo Jiao static int mt7986_wmac_adie_patch_7975(struct mt7915_dev *dev, u8 adie)
62199ad32a4SBo Jiao {
62299ad32a4SBo Jiao int ret;
62399ad32a4SBo Jiao
62499ad32a4SBo Jiao /* disable CAL LDO and fine tune RFDIG LDO */
62599ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x348, 0x00000002);
62699ad32a4SBo Jiao if (ret)
62799ad32a4SBo Jiao return ret;
62899ad32a4SBo Jiao
62999ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x378, 0x00000002);
63099ad32a4SBo Jiao if (ret)
63199ad32a4SBo Jiao return ret;
63299ad32a4SBo Jiao
63399ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x3a8, 0x00000002);
63499ad32a4SBo Jiao if (ret)
63599ad32a4SBo Jiao return ret;
63699ad32a4SBo Jiao
63799ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x3d8, 0x00000002);
63899ad32a4SBo Jiao if (ret)
63999ad32a4SBo Jiao return ret;
64099ad32a4SBo Jiao
64199ad32a4SBo Jiao /* set CKA driving and filter */
64299ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0xa1c, 0x30000aaa);
64399ad32a4SBo Jiao if (ret)
64499ad32a4SBo Jiao return ret;
64599ad32a4SBo Jiao
64699ad32a4SBo Jiao /* set CKB LDO to 1.4V */
64799ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0xa84, 0x8470008a);
64899ad32a4SBo Jiao if (ret)
64999ad32a4SBo Jiao return ret;
65099ad32a4SBo Jiao
65199ad32a4SBo Jiao /* turn on SX0 LTBUF */
652*6bad146dSAlexander Couzens if (is_mt7981(&dev->mt76)) {
653*6bad146dSAlexander Couzens ret = mt76_wmac_spi_write(dev, adie, 0x074, 0x00000007);
654*6bad146dSAlexander Couzens } else if (is_mt7986(&dev->mt76)) {
65599ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x074, 0x00000002);
656*6bad146dSAlexander Couzens } else {
657*6bad146dSAlexander Couzens WARN_ON(1);
658*6bad146dSAlexander Couzens return -EINVAL;
659*6bad146dSAlexander Couzens }
660*6bad146dSAlexander Couzens
66199ad32a4SBo Jiao if (ret)
66299ad32a4SBo Jiao return ret;
66399ad32a4SBo Jiao
66499ad32a4SBo Jiao /* CK_BUF_SW_EN = 1 (all buf in manual mode.) */
66599ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0xaa4, 0x01001fc0);
66699ad32a4SBo Jiao if (ret)
66799ad32a4SBo Jiao return ret;
66899ad32a4SBo Jiao
66999ad32a4SBo Jiao /* BT mode/WF normal mode 00000005 */
67099ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x070, 0x00000005);
67199ad32a4SBo Jiao if (ret)
67299ad32a4SBo Jiao return ret;
67399ad32a4SBo Jiao
67499ad32a4SBo Jiao /* BG thermal sensor offset update */
67599ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x344, 0x00000088);
67699ad32a4SBo Jiao if (ret)
67799ad32a4SBo Jiao return ret;
67899ad32a4SBo Jiao
67999ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x374, 0x00000088);
68099ad32a4SBo Jiao if (ret)
68199ad32a4SBo Jiao return ret;
68299ad32a4SBo Jiao
68399ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x3a4, 0x00000088);
68499ad32a4SBo Jiao if (ret)
68599ad32a4SBo Jiao return ret;
68699ad32a4SBo Jiao
68799ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x3d4, 0x00000088);
68899ad32a4SBo Jiao if (ret)
68999ad32a4SBo Jiao return ret;
69099ad32a4SBo Jiao
69199ad32a4SBo Jiao /* set WCON VDD IPTAT to "0000" */
69299ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0xa80, 0x44d07000);
69399ad32a4SBo Jiao if (ret)
69499ad32a4SBo Jiao return ret;
69599ad32a4SBo Jiao
69699ad32a4SBo Jiao /* change back LTBUF SX3 drving to default value */
69799ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0xa88, 0x3900aaaa);
69899ad32a4SBo Jiao if (ret)
69999ad32a4SBo Jiao return ret;
70099ad32a4SBo Jiao
70199ad32a4SBo Jiao /* SM input cap off */
70299ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x2c4, 0x00000000);
70399ad32a4SBo Jiao if (ret)
70499ad32a4SBo Jiao return ret;
70599ad32a4SBo Jiao
70699ad32a4SBo Jiao /* set CKB driving and filter */
707*6bad146dSAlexander Couzens if (is_mt7986(&dev->mt76))
70899ad32a4SBo Jiao return mt76_wmac_spi_write(dev, adie, 0x2c8, 0x00000072);
709*6bad146dSAlexander Couzens
710*6bad146dSAlexander Couzens return ret;
71199ad32a4SBo Jiao }
71299ad32a4SBo Jiao
mt7986_wmac_adie_cfg(struct mt7915_dev * dev,u8 adie,u32 adie_type)71399ad32a4SBo Jiao static int mt7986_wmac_adie_cfg(struct mt7915_dev *dev, u8 adie, u32 adie_type)
71499ad32a4SBo Jiao {
71599ad32a4SBo Jiao int ret;
71699ad32a4SBo Jiao
71799ad32a4SBo Jiao mt76_wmac_spi_lock(dev);
71899ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_CLK_EN, ~0);
71999ad32a4SBo Jiao if (ret)
72099ad32a4SBo Jiao goto out;
72199ad32a4SBo Jiao
72299ad32a4SBo Jiao if (is_7975(dev, adie, adie_type)) {
72399ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_COCLK,
72499ad32a4SBo Jiao BIT(1), 0x1);
72599ad32a4SBo Jiao if (ret)
72699ad32a4SBo Jiao goto out;
72799ad32a4SBo Jiao
72899ad32a4SBo Jiao ret = mt7986_wmac_adie_thermal_cal(dev, adie);
72999ad32a4SBo Jiao if (ret)
73099ad32a4SBo Jiao goto out;
73199ad32a4SBo Jiao
73299ad32a4SBo Jiao ret = mt7986_wmac_adie_xtal_trim_7975(dev, adie);
73399ad32a4SBo Jiao if (ret)
73499ad32a4SBo Jiao goto out;
73599ad32a4SBo Jiao
73699ad32a4SBo Jiao ret = mt7986_wmac_adie_patch_7975(dev, adie);
73799ad32a4SBo Jiao } else if (is_7976(dev, adie, adie_type)) {
738*6bad146dSAlexander Couzens if (mt798x_wmac_check_adie_type(dev) == ADIE_DBDC) {
73999ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie,
74099ad32a4SBo Jiao MT_ADIE_WRI_CK_SEL, 0x1c);
74199ad32a4SBo Jiao if (ret)
74299ad32a4SBo Jiao goto out;
74399ad32a4SBo Jiao }
74499ad32a4SBo Jiao
74599ad32a4SBo Jiao ret = mt7986_wmac_adie_thermal_cal(dev, adie);
74699ad32a4SBo Jiao if (ret)
74799ad32a4SBo Jiao goto out;
74899ad32a4SBo Jiao
74999ad32a4SBo Jiao ret = mt7986_wmac_adie_xtal_trim_7976(dev, adie);
75099ad32a4SBo Jiao if (ret)
75199ad32a4SBo Jiao goto out;
75299ad32a4SBo Jiao
753*6bad146dSAlexander Couzens ret = mt798x_wmac_adie_patch_7976(dev, adie);
75499ad32a4SBo Jiao }
75599ad32a4SBo Jiao out:
75699ad32a4SBo Jiao mt76_wmac_spi_unlock(dev);
75799ad32a4SBo Jiao
75899ad32a4SBo Jiao return ret;
75999ad32a4SBo Jiao }
76099ad32a4SBo Jiao
76199ad32a4SBo Jiao static int
mt7986_wmac_afe_cal(struct mt7915_dev * dev,u8 adie,bool dbdc,u32 adie_type)76299ad32a4SBo Jiao mt7986_wmac_afe_cal(struct mt7915_dev *dev, u8 adie, bool dbdc, u32 adie_type)
76399ad32a4SBo Jiao {
76499ad32a4SBo Jiao int ret;
76599ad32a4SBo Jiao u8 idx;
766*6bad146dSAlexander Couzens u32 txcal;
76799ad32a4SBo Jiao
76899ad32a4SBo Jiao mt76_wmac_spi_lock(dev);
76999ad32a4SBo Jiao if (is_7975(dev, adie, adie_type))
77099ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie,
77199ad32a4SBo Jiao MT_AFE_RG_ENCAL_WBTAC_IF_SW,
77299ad32a4SBo Jiao 0x80000000);
77399ad32a4SBo Jiao else
77499ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie,
77599ad32a4SBo Jiao MT_AFE_RG_ENCAL_WBTAC_IF_SW,
77699ad32a4SBo Jiao 0x88888005);
77799ad32a4SBo Jiao if (ret)
77899ad32a4SBo Jiao goto out;
77999ad32a4SBo Jiao
78099ad32a4SBo Jiao idx = dbdc ? ADIE_DBDC : adie;
78199ad32a4SBo Jiao
78299ad32a4SBo Jiao mt76_rmw_field(dev, MT_AFE_DIG_EN_01(idx),
78399ad32a4SBo Jiao MT_AFE_RG_WBG_EN_RCK_MASK, 0x1);
78499ad32a4SBo Jiao usleep_range(60, 100);
78599ad32a4SBo Jiao
78699ad32a4SBo Jiao mt76_rmw(dev, MT_AFE_DIG_EN_01(idx),
78799ad32a4SBo Jiao MT_AFE_RG_WBG_EN_RCK_MASK, 0x0);
78899ad32a4SBo Jiao
78999ad32a4SBo Jiao mt76_rmw_field(dev, MT_AFE_DIG_EN_03(idx),
79099ad32a4SBo Jiao MT_AFE_RG_WBG_EN_BPLL_UP_MASK, 0x1);
79199ad32a4SBo Jiao usleep_range(30, 100);
79299ad32a4SBo Jiao
79399ad32a4SBo Jiao mt76_rmw_field(dev, MT_AFE_DIG_EN_03(idx),
79499ad32a4SBo Jiao MT_AFE_RG_WBG_EN_WPLL_UP_MASK, 0x1);
79599ad32a4SBo Jiao usleep_range(60, 100);
79699ad32a4SBo Jiao
797*6bad146dSAlexander Couzens txcal = (MT_AFE_RG_WBG_EN_TXCAL_BT |
798*6bad146dSAlexander Couzens MT_AFE_RG_WBG_EN_TXCAL_WF0 |
799*6bad146dSAlexander Couzens MT_AFE_RG_WBG_EN_TXCAL_WF1 |
800*6bad146dSAlexander Couzens MT_AFE_RG_WBG_EN_TXCAL_WF2 |
801*6bad146dSAlexander Couzens MT_AFE_RG_WBG_EN_TXCAL_WF3);
802*6bad146dSAlexander Couzens if (is_mt7981(&dev->mt76))
803*6bad146dSAlexander Couzens txcal |= MT_AFE_RG_WBG_EN_TXCAL_WF4;
804*6bad146dSAlexander Couzens
805*6bad146dSAlexander Couzens mt76_set(dev, MT_AFE_DIG_EN_01(idx), txcal);
80699ad32a4SBo Jiao usleep_range(800, 1000);
80799ad32a4SBo Jiao
808*6bad146dSAlexander Couzens mt76_clear(dev, MT_AFE_DIG_EN_01(idx), txcal);
80999ad32a4SBo Jiao mt76_rmw(dev, MT_AFE_DIG_EN_03(idx),
81099ad32a4SBo Jiao MT_AFE_RG_WBG_EN_PLL_UP_MASK, 0x0);
81199ad32a4SBo Jiao
81299ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, MT_AFE_RG_ENCAL_WBTAC_IF_SW,
81399ad32a4SBo Jiao 0x5);
81499ad32a4SBo Jiao
81599ad32a4SBo Jiao out:
81699ad32a4SBo Jiao mt76_wmac_spi_unlock(dev);
81799ad32a4SBo Jiao
81899ad32a4SBo Jiao return ret;
81999ad32a4SBo Jiao }
82099ad32a4SBo Jiao
mt7986_wmac_subsys_pll_initial(struct mt7915_dev * dev,u8 band)82199ad32a4SBo Jiao static void mt7986_wmac_subsys_pll_initial(struct mt7915_dev *dev, u8 band)
82299ad32a4SBo Jiao {
82399ad32a4SBo Jiao mt76_rmw(dev, MT_AFE_PLL_STB_TIME(band),
82499ad32a4SBo Jiao MT_AFE_PLL_STB_TIME_MASK, MT_AFE_PLL_STB_TIME_VAL);
82599ad32a4SBo Jiao
82699ad32a4SBo Jiao mt76_rmw(dev, MT_AFE_DIG_EN_02(band),
82799ad32a4SBo Jiao MT_AFE_PLL_CFG_MASK, MT_AFE_PLL_CFG_VAL);
82899ad32a4SBo Jiao
82999ad32a4SBo Jiao mt76_rmw(dev, MT_AFE_DIG_TOP_01(band),
83099ad32a4SBo Jiao MT_AFE_DIG_TOP_01_MASK, MT_AFE_DIG_TOP_01_VAL);
83199ad32a4SBo Jiao }
83299ad32a4SBo Jiao
mt7986_wmac_subsys_setting(struct mt7915_dev * dev)83399ad32a4SBo Jiao static void mt7986_wmac_subsys_setting(struct mt7915_dev *dev)
83499ad32a4SBo Jiao {
83599ad32a4SBo Jiao /* Subsys pll init */
83699ad32a4SBo Jiao mt7986_wmac_subsys_pll_initial(dev, 0);
83799ad32a4SBo Jiao mt7986_wmac_subsys_pll_initial(dev, 1);
83899ad32a4SBo Jiao
83999ad32a4SBo Jiao /* Set legacy OSC control stable time*/
84099ad32a4SBo Jiao mt76_rmw(dev, MT_CONN_INFRA_OSC_RC_EN,
84199ad32a4SBo Jiao MT_CONN_INFRA_OSC_RC_EN_MASK, 0x0);
84299ad32a4SBo Jiao mt76_rmw(dev, MT_CONN_INFRA_OSC_CTRL,
84399ad32a4SBo Jiao MT_CONN_INFRA_OSC_STB_TIME_MASK, 0x80706);
84499ad32a4SBo Jiao
84599ad32a4SBo Jiao /* prevent subsys from power on/of in a short time interval */
84699ad32a4SBo Jiao mt76_rmw(dev, MT_TOP_WFSYS_PWR,
84799ad32a4SBo Jiao MT_TOP_PWR_ACK_MASK | MT_TOP_PWR_KEY_MASK,
84899ad32a4SBo Jiao MT_TOP_PWR_KEY);
84999ad32a4SBo Jiao }
85099ad32a4SBo Jiao
mt7986_wmac_bus_timeout(struct mt7915_dev * dev)85199ad32a4SBo Jiao static int mt7986_wmac_bus_timeout(struct mt7915_dev *dev)
85299ad32a4SBo Jiao {
85399ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_BUS_OFF_TIMEOUT,
85499ad32a4SBo Jiao MT_INFRA_BUS_TIMEOUT_LIMIT_MASK, 0x2);
85599ad32a4SBo Jiao
85699ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_BUS_OFF_TIMEOUT,
85799ad32a4SBo Jiao MT_INFRA_BUS_TIMEOUT_EN_MASK, 0xf);
85899ad32a4SBo Jiao
85999ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_BUS_ON_TIMEOUT,
86099ad32a4SBo Jiao MT_INFRA_BUS_TIMEOUT_LIMIT_MASK, 0xc);
86199ad32a4SBo Jiao
86299ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_BUS_ON_TIMEOUT,
86399ad32a4SBo Jiao MT_INFRA_BUS_TIMEOUT_EN_MASK, 0xf);
86499ad32a4SBo Jiao
865*6bad146dSAlexander Couzens return mt798x_wmac_coninfra_check(dev);
86699ad32a4SBo Jiao }
86799ad32a4SBo Jiao
mt7986_wmac_clock_enable(struct mt7915_dev * dev,u32 adie_type)86899ad32a4SBo Jiao static void mt7986_wmac_clock_enable(struct mt7915_dev *dev, u32 adie_type)
86999ad32a4SBo Jiao {
87099ad32a4SBo Jiao u32 cur;
87199ad32a4SBo Jiao
87299ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_1,
87399ad32a4SBo Jiao MT_INFRA_CKGEN_DIV_SEL_MASK, 0x1);
87499ad32a4SBo Jiao
87599ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_2,
87699ad32a4SBo Jiao MT_INFRA_CKGEN_DIV_SEL_MASK, 0x1);
87799ad32a4SBo Jiao
87899ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_1,
87999ad32a4SBo Jiao MT_INFRA_CKGEN_DIV_EN_MASK, 0x1);
88099ad32a4SBo Jiao
88199ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_2,
88299ad32a4SBo Jiao MT_INFRA_CKGEN_DIV_EN_MASK, 0x1);
88399ad32a4SBo Jiao
88499ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_RFSPI_WPLL_DIV,
88599ad32a4SBo Jiao MT_INFRA_CKGEN_DIV_SEL_MASK, 0x8);
88699ad32a4SBo Jiao
88799ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_RFSPI_WPLL_DIV,
88899ad32a4SBo Jiao MT_INFRA_CKGEN_DIV_EN_MASK, 0x1);
88999ad32a4SBo Jiao
89099ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS,
89199ad32a4SBo Jiao MT_INFRA_CKGEN_BUS_CLK_SEL_MASK, 0x0);
89299ad32a4SBo Jiao
89399ad32a4SBo Jiao mt76_rmw_field(dev, MT_CONN_INFRA_HW_CTRL,
89499ad32a4SBo Jiao MT_CONN_INFRA_HW_CTRL_MASK, 0x1);
89599ad32a4SBo Jiao
89699ad32a4SBo Jiao mt76_rmw(dev, MT_TOP_CONN_INFRA_WAKEUP,
89799ad32a4SBo Jiao MT_TOP_CONN_INFRA_WAKEUP_MASK, 0x1);
89899ad32a4SBo Jiao
89999ad32a4SBo Jiao usleep_range(900, 1000);
90099ad32a4SBo Jiao
90199ad32a4SBo Jiao mt76_wmac_spi_lock(dev);
90299ad32a4SBo Jiao if (is_7975(dev, 0, adie_type) || is_7976(dev, 0, adie_type)) {
90399ad32a4SBo Jiao mt76_rmw_field(dev, MT_ADIE_SLP_CTRL_CK0(0),
90499ad32a4SBo Jiao MT_SLP_CTRL_EN_MASK, 0x1);
90599ad32a4SBo Jiao
90699ad32a4SBo Jiao read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_CTRL_BSY_MASK),
90799ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
90899ad32a4SBo Jiao dev, MT_ADIE_SLP_CTRL_CK0(0));
90999ad32a4SBo Jiao }
91099ad32a4SBo Jiao if (is_7975(dev, 1, adie_type) || is_7976(dev, 1, adie_type)) {
91199ad32a4SBo Jiao mt76_rmw_field(dev, MT_ADIE_SLP_CTRL_CK0(1),
91299ad32a4SBo Jiao MT_SLP_CTRL_EN_MASK, 0x1);
91399ad32a4SBo Jiao
91499ad32a4SBo Jiao read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_CTRL_BSY_MASK),
91599ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
91699ad32a4SBo Jiao dev, MT_ADIE_SLP_CTRL_CK0(0));
91799ad32a4SBo Jiao }
91899ad32a4SBo Jiao mt76_wmac_spi_unlock(dev);
91999ad32a4SBo Jiao
92099ad32a4SBo Jiao mt76_rmw(dev, MT_TOP_CONN_INFRA_WAKEUP,
92199ad32a4SBo Jiao MT_TOP_CONN_INFRA_WAKEUP_MASK, 0x0);
92299ad32a4SBo Jiao usleep_range(900, 1000);
92399ad32a4SBo Jiao }
92499ad32a4SBo Jiao
mt7986_wmac_top_wfsys_wakeup(struct mt7915_dev * dev,bool enable)92599ad32a4SBo Jiao static int mt7986_wmac_top_wfsys_wakeup(struct mt7915_dev *dev, bool enable)
92699ad32a4SBo Jiao {
92799ad32a4SBo Jiao mt76_rmw_field(dev, MT_TOP_WFSYS_WAKEUP,
92899ad32a4SBo Jiao MT_TOP_WFSYS_WAKEUP_MASK, enable);
92999ad32a4SBo Jiao
93099ad32a4SBo Jiao usleep_range(900, 1000);
93199ad32a4SBo Jiao
93299ad32a4SBo Jiao if (!enable)
93399ad32a4SBo Jiao return 0;
93499ad32a4SBo Jiao
935*6bad146dSAlexander Couzens return mt798x_wmac_coninfra_check(dev);
93699ad32a4SBo Jiao }
93799ad32a4SBo Jiao
mt7986_wmac_wm_enable(struct mt7915_dev * dev,bool enable)93899ad32a4SBo Jiao static int mt7986_wmac_wm_enable(struct mt7915_dev *dev, bool enable)
93999ad32a4SBo Jiao {
94099ad32a4SBo Jiao u32 cur;
94199ad32a4SBo Jiao
942*6bad146dSAlexander Couzens if (is_mt7986(&dev->mt76))
9430ad6b97eSPeter Chiu mt76_wr(dev, MT_CONNINFRA_SKU_DEC_ADDR, 0);
9440ad6b97eSPeter Chiu
94599ad32a4SBo Jiao mt76_rmw_field(dev, MT7986_TOP_WM_RESET,
94699ad32a4SBo Jiao MT7986_TOP_WM_RESET_MASK, enable);
94799ad32a4SBo Jiao if (!enable)
94899ad32a4SBo Jiao return 0;
94999ad32a4SBo Jiao
95099ad32a4SBo Jiao return read_poll_timeout(mt76_rr, cur, (cur == 0x1d1e),
95199ad32a4SBo Jiao USEC_PER_MSEC, 5000 * USEC_PER_MSEC, false,
95299ad32a4SBo Jiao dev, MT_TOP_CFG_ON_ROM_IDX);
95399ad32a4SBo Jiao }
95499ad32a4SBo Jiao
mt7986_wmac_wfsys_poweron(struct mt7915_dev * dev,bool enable)95599ad32a4SBo Jiao static int mt7986_wmac_wfsys_poweron(struct mt7915_dev *dev, bool enable)
95699ad32a4SBo Jiao {
95799ad32a4SBo Jiao u32 mask = MT_TOP_PWR_EN_MASK | MT_TOP_PWR_KEY_MASK;
95899ad32a4SBo Jiao u32 cur;
95999ad32a4SBo Jiao
96099ad32a4SBo Jiao mt76_rmw(dev, MT_TOP_WFSYS_PWR, mask,
96199ad32a4SBo Jiao MT_TOP_PWR_KEY | FIELD_PREP(MT_TOP_PWR_EN_MASK, enable));
96299ad32a4SBo Jiao
96399ad32a4SBo Jiao return read_poll_timeout(mt76_rr, cur,
96499ad32a4SBo Jiao (FIELD_GET(MT_TOP_WFSYS_RESET_STATUS_MASK, cur) == enable),
96599ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
96699ad32a4SBo Jiao dev, MT_TOP_WFSYS_RESET_STATUS);
96799ad32a4SBo Jiao }
96899ad32a4SBo Jiao
mt7986_wmac_wfsys_setting(struct mt7915_dev * dev)96999ad32a4SBo Jiao static int mt7986_wmac_wfsys_setting(struct mt7915_dev *dev)
97099ad32a4SBo Jiao {
97199ad32a4SBo Jiao int ret;
97299ad32a4SBo Jiao u32 cur;
97399ad32a4SBo Jiao
97499ad32a4SBo Jiao /* Turn off wfsys2conn bus sleep protect */
97599ad32a4SBo Jiao mt76_rmw(dev, MT_CONN_INFRA_WF_SLP_PROT,
97699ad32a4SBo Jiao MT_CONN_INFRA_WF_SLP_PROT_MASK, 0x0);
97799ad32a4SBo Jiao
97899ad32a4SBo Jiao ret = mt7986_wmac_wfsys_poweron(dev, true);
97999ad32a4SBo Jiao if (ret)
98099ad32a4SBo Jiao return ret;
98199ad32a4SBo Jiao
98299ad32a4SBo Jiao /* Check bus sleep protect */
98399ad32a4SBo Jiao
98499ad32a4SBo Jiao ret = read_poll_timeout(mt76_rr, cur,
98599ad32a4SBo Jiao !(cur & MT_CONN_INFRA_CONN_WF_MASK),
98699ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
98799ad32a4SBo Jiao dev, MT_CONN_INFRA_WF_SLP_PROT_RDY);
98899ad32a4SBo Jiao if (ret)
98999ad32a4SBo Jiao return ret;
99099ad32a4SBo Jiao
99199ad32a4SBo Jiao ret = read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_WFDMA2CONN_MASK),
99299ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
99399ad32a4SBo Jiao dev, MT_SLP_STATUS);
99499ad32a4SBo Jiao if (ret)
99599ad32a4SBo Jiao return ret;
99699ad32a4SBo Jiao
99799ad32a4SBo Jiao return read_poll_timeout(mt76_rr, cur, (cur == 0x02060000),
99899ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
99999ad32a4SBo Jiao dev, MT_TOP_CFG_IP_VERSION_ADDR);
100099ad32a4SBo Jiao }
100199ad32a4SBo Jiao
mt7986_wmac_wfsys_set_timeout(struct mt7915_dev * dev)100299ad32a4SBo Jiao static void mt7986_wmac_wfsys_set_timeout(struct mt7915_dev *dev)
100399ad32a4SBo Jiao {
100499ad32a4SBo Jiao u32 mask = MT_MCU_BUS_TIMEOUT_SET_MASK |
100599ad32a4SBo Jiao MT_MCU_BUS_TIMEOUT_CG_EN_MASK |
100699ad32a4SBo Jiao MT_MCU_BUS_TIMEOUT_EN_MASK;
100799ad32a4SBo Jiao u32 val = FIELD_PREP(MT_MCU_BUS_TIMEOUT_SET_MASK, 1) |
100899ad32a4SBo Jiao FIELD_PREP(MT_MCU_BUS_TIMEOUT_CG_EN_MASK, 1) |
100999ad32a4SBo Jiao FIELD_PREP(MT_MCU_BUS_TIMEOUT_EN_MASK, 1);
101099ad32a4SBo Jiao
101199ad32a4SBo Jiao mt76_rmw(dev, MT_MCU_BUS_TIMEOUT, mask, val);
101299ad32a4SBo Jiao
101399ad32a4SBo Jiao mt76_wr(dev, MT_MCU_BUS_REMAP, 0x810f0000);
101499ad32a4SBo Jiao
101599ad32a4SBo Jiao mask = MT_MCU_BUS_DBG_TIMEOUT_SET_MASK |
101699ad32a4SBo Jiao MT_MCU_BUS_DBG_TIMEOUT_CK_EN_MASK |
101799ad32a4SBo Jiao MT_MCU_BUS_DBG_TIMEOUT_EN_MASK;
101899ad32a4SBo Jiao val = FIELD_PREP(MT_MCU_BUS_DBG_TIMEOUT_SET_MASK, 0x3aa) |
101999ad32a4SBo Jiao FIELD_PREP(MT_MCU_BUS_DBG_TIMEOUT_CK_EN_MASK, 1) |
102099ad32a4SBo Jiao FIELD_PREP(MT_MCU_BUS_DBG_TIMEOUT_EN_MASK, 1);
102199ad32a4SBo Jiao
102299ad32a4SBo Jiao mt76_rmw(dev, MT_MCU_BUS_DBG_TIMEOUT, mask, val);
102399ad32a4SBo Jiao }
102499ad32a4SBo Jiao
mt7986_wmac_sku_update(struct mt7915_dev * dev,u32 adie_type)102599ad32a4SBo Jiao static int mt7986_wmac_sku_update(struct mt7915_dev *dev, u32 adie_type)
102699ad32a4SBo Jiao {
102799ad32a4SBo Jiao u32 val;
102899ad32a4SBo Jiao
102999ad32a4SBo Jiao if (is_7976(dev, 0, adie_type) && is_7976(dev, 1, adie_type))
103099ad32a4SBo Jiao val = 0xf;
103199ad32a4SBo Jiao else if (is_7975(dev, 0, adie_type) && is_7975(dev, 1, adie_type))
103299ad32a4SBo Jiao val = 0xd;
103399ad32a4SBo Jiao else if (is_7976(dev, 0, adie_type))
103499ad32a4SBo Jiao val = 0x7;
103599ad32a4SBo Jiao else if (is_7975(dev, 1, adie_type))
103699ad32a4SBo Jiao val = 0x8;
103799ad32a4SBo Jiao else if (is_7976(dev, 1, adie_type))
103899ad32a4SBo Jiao val = 0xa;
103999ad32a4SBo Jiao else
104099ad32a4SBo Jiao return -EINVAL;
104199ad32a4SBo Jiao
104299ad32a4SBo Jiao mt76_wmac_rmw(dev->sku, MT_TOP_POS_SKU, MT_TOP_POS_SKU_MASK,
104399ad32a4SBo Jiao FIELD_PREP(MT_TOP_POS_SKU_MASK, val));
104499ad32a4SBo Jiao
104599ad32a4SBo Jiao mt76_wr(dev, MT_CONNINFRA_SKU_DEC_ADDR, val);
104699ad32a4SBo Jiao
104799ad32a4SBo Jiao return 0;
104899ad32a4SBo Jiao }
104999ad32a4SBo Jiao
105099ad32a4SBo Jiao static int
mt7986_wmac_adie_setup(struct mt7915_dev * dev,u8 adie,u32 adie_type)105199ad32a4SBo Jiao mt7986_wmac_adie_setup(struct mt7915_dev *dev, u8 adie, u32 adie_type)
105299ad32a4SBo Jiao {
105399ad32a4SBo Jiao int ret;
105499ad32a4SBo Jiao
105599ad32a4SBo Jiao if (!(is_7975(dev, adie, adie_type) || is_7976(dev, adie, adie_type)))
105699ad32a4SBo Jiao return 0;
105799ad32a4SBo Jiao
105899ad32a4SBo Jiao ret = mt7986_wmac_adie_cfg(dev, adie, adie_type);
105999ad32a4SBo Jiao if (ret)
106099ad32a4SBo Jiao return ret;
106199ad32a4SBo Jiao
106299ad32a4SBo Jiao ret = mt7986_wmac_afe_cal(dev, adie, false, adie_type);
106399ad32a4SBo Jiao if (ret)
106499ad32a4SBo Jiao return ret;
106599ad32a4SBo Jiao
1066*6bad146dSAlexander Couzens if (!adie && (mt798x_wmac_check_adie_type(dev) == ADIE_DBDC))
106799ad32a4SBo Jiao ret = mt7986_wmac_afe_cal(dev, adie, true, adie_type);
106899ad32a4SBo Jiao
106999ad32a4SBo Jiao return ret;
107099ad32a4SBo Jiao }
107199ad32a4SBo Jiao
mt7986_wmac_subsys_powerup(struct mt7915_dev * dev,u32 adie_type)107299ad32a4SBo Jiao static int mt7986_wmac_subsys_powerup(struct mt7915_dev *dev, u32 adie_type)
107399ad32a4SBo Jiao {
107499ad32a4SBo Jiao int ret;
107599ad32a4SBo Jiao
107699ad32a4SBo Jiao mt7986_wmac_subsys_setting(dev);
107799ad32a4SBo Jiao
107899ad32a4SBo Jiao ret = mt7986_wmac_bus_timeout(dev);
107999ad32a4SBo Jiao if (ret)
108099ad32a4SBo Jiao return ret;
108199ad32a4SBo Jiao
108299ad32a4SBo Jiao mt7986_wmac_clock_enable(dev, adie_type);
108399ad32a4SBo Jiao
108499ad32a4SBo Jiao return 0;
108599ad32a4SBo Jiao }
108699ad32a4SBo Jiao
mt7986_wmac_wfsys_powerup(struct mt7915_dev * dev)108799ad32a4SBo Jiao static int mt7986_wmac_wfsys_powerup(struct mt7915_dev *dev)
108899ad32a4SBo Jiao {
108999ad32a4SBo Jiao int ret;
109099ad32a4SBo Jiao
109199ad32a4SBo Jiao ret = mt7986_wmac_wm_enable(dev, false);
109299ad32a4SBo Jiao if (ret)
109399ad32a4SBo Jiao return ret;
109499ad32a4SBo Jiao
109599ad32a4SBo Jiao ret = mt7986_wmac_wfsys_setting(dev);
109699ad32a4SBo Jiao if (ret)
109799ad32a4SBo Jiao return ret;
109899ad32a4SBo Jiao
109999ad32a4SBo Jiao mt7986_wmac_wfsys_set_timeout(dev);
110099ad32a4SBo Jiao
110199ad32a4SBo Jiao return mt7986_wmac_wm_enable(dev, true);
110299ad32a4SBo Jiao }
110399ad32a4SBo Jiao
mt7986_wmac_enable(struct mt7915_dev * dev)110499ad32a4SBo Jiao int mt7986_wmac_enable(struct mt7915_dev *dev)
110599ad32a4SBo Jiao {
110699ad32a4SBo Jiao int ret;
110799ad32a4SBo Jiao u32 adie_type;
110899ad32a4SBo Jiao
110999ad32a4SBo Jiao ret = mt7986_wmac_consys_reset(dev, true);
111099ad32a4SBo Jiao if (ret)
111199ad32a4SBo Jiao return ret;
111299ad32a4SBo Jiao
111399ad32a4SBo Jiao ret = mt7986_wmac_gpio_setup(dev);
111499ad32a4SBo Jiao if (ret)
111599ad32a4SBo Jiao return ret;
111699ad32a4SBo Jiao
111799ad32a4SBo Jiao ret = mt7986_wmac_consys_lockup(dev, false);
111899ad32a4SBo Jiao if (ret)
111999ad32a4SBo Jiao return ret;
112099ad32a4SBo Jiao
1121*6bad146dSAlexander Couzens ret = mt798x_wmac_coninfra_check(dev);
112299ad32a4SBo Jiao if (ret)
112399ad32a4SBo Jiao return ret;
112499ad32a4SBo Jiao
1125*6bad146dSAlexander Couzens ret = mt798x_wmac_coninfra_setup(dev);
112699ad32a4SBo Jiao if (ret)
112799ad32a4SBo Jiao return ret;
112899ad32a4SBo Jiao
1129*6bad146dSAlexander Couzens ret = mt798x_wmac_sku_setup(dev, &adie_type);
113099ad32a4SBo Jiao if (ret)
113199ad32a4SBo Jiao return ret;
113299ad32a4SBo Jiao
113399ad32a4SBo Jiao ret = mt7986_wmac_adie_setup(dev, 0, adie_type);
113499ad32a4SBo Jiao if (ret)
113599ad32a4SBo Jiao return ret;
113699ad32a4SBo Jiao
1137*6bad146dSAlexander Couzens /* mt7981 doesn't support a second a-die */
1138*6bad146dSAlexander Couzens if (is_mt7986(&dev->mt76)) {
113999ad32a4SBo Jiao ret = mt7986_wmac_adie_setup(dev, 1, adie_type);
114099ad32a4SBo Jiao if (ret)
114199ad32a4SBo Jiao return ret;
1142*6bad146dSAlexander Couzens }
114399ad32a4SBo Jiao
114499ad32a4SBo Jiao ret = mt7986_wmac_subsys_powerup(dev, adie_type);
114599ad32a4SBo Jiao if (ret)
114699ad32a4SBo Jiao return ret;
114799ad32a4SBo Jiao
114899ad32a4SBo Jiao ret = mt7986_wmac_top_wfsys_wakeup(dev, true);
114999ad32a4SBo Jiao if (ret)
115099ad32a4SBo Jiao return ret;
115199ad32a4SBo Jiao
115299ad32a4SBo Jiao ret = mt7986_wmac_wfsys_powerup(dev);
115399ad32a4SBo Jiao if (ret)
115499ad32a4SBo Jiao return ret;
115599ad32a4SBo Jiao
115699ad32a4SBo Jiao return mt7986_wmac_sku_update(dev, adie_type);
115799ad32a4SBo Jiao }
115899ad32a4SBo Jiao
mt7986_wmac_disable(struct mt7915_dev * dev)115999ad32a4SBo Jiao void mt7986_wmac_disable(struct mt7915_dev *dev)
116099ad32a4SBo Jiao {
116199ad32a4SBo Jiao u32 cur;
116299ad32a4SBo Jiao
116399ad32a4SBo Jiao mt7986_wmac_top_wfsys_wakeup(dev, true);
116499ad32a4SBo Jiao
116599ad32a4SBo Jiao /* Turn on wfsys2conn bus sleep protect */
116699ad32a4SBo Jiao mt76_rmw_field(dev, MT_CONN_INFRA_WF_SLP_PROT,
116799ad32a4SBo Jiao MT_CONN_INFRA_WF_SLP_PROT_MASK, 0x1);
116899ad32a4SBo Jiao
116999ad32a4SBo Jiao /* Check wfsys2conn bus sleep protect */
117099ad32a4SBo Jiao read_poll_timeout(mt76_rr, cur, !(cur ^ MT_CONN_INFRA_CONN),
117199ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false,
117299ad32a4SBo Jiao dev, MT_CONN_INFRA_WF_SLP_PROT_RDY);
117399ad32a4SBo Jiao
117499ad32a4SBo Jiao mt7986_wmac_wfsys_poweron(dev, false);
117599ad32a4SBo Jiao
117699ad32a4SBo Jiao /* Turn back wpll setting */
117799ad32a4SBo Jiao mt76_rmw_field(dev, MT_AFE_DIG_EN_02(0), MT_AFE_MCU_BPLL_CFG_MASK, 0x2);
117899ad32a4SBo Jiao mt76_rmw_field(dev, MT_AFE_DIG_EN_02(0), MT_AFE_WPLL_CFG_MASK, 0x2);
117999ad32a4SBo Jiao
118099ad32a4SBo Jiao /* Reset EMI */
118199ad32a4SBo Jiao mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ,
118299ad32a4SBo Jiao MT_CONN_INFRA_EMI_REQ_MASK, 0x1);
118399ad32a4SBo Jiao mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ,
118499ad32a4SBo Jiao MT_CONN_INFRA_EMI_REQ_MASK, 0x0);
118599ad32a4SBo Jiao mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ,
118699ad32a4SBo Jiao MT_CONN_INFRA_INFRA_REQ_MASK, 0x1);
118799ad32a4SBo Jiao mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ,
118899ad32a4SBo Jiao MT_CONN_INFRA_INFRA_REQ_MASK, 0x0);
118999ad32a4SBo Jiao
119099ad32a4SBo Jiao mt7986_wmac_top_wfsys_wakeup(dev, false);
119199ad32a4SBo Jiao mt7986_wmac_consys_lockup(dev, true);
119299ad32a4SBo Jiao mt7986_wmac_consys_reset(dev, false);
119399ad32a4SBo Jiao }
119499ad32a4SBo Jiao
mt798x_wmac_init(struct mt7915_dev * dev)1195*6bad146dSAlexander Couzens static int mt798x_wmac_init(struct mt7915_dev *dev)
119699ad32a4SBo Jiao {
119799ad32a4SBo Jiao struct device *pdev = dev->mt76.dev;
119899ad32a4SBo Jiao struct platform_device *pfdev = to_platform_device(pdev);
1199cd85efdfSLorenzo Bianconi struct clk *mcu_clk, *ap_conn_clk;
1200cd85efdfSLorenzo Bianconi
1201cd85efdfSLorenzo Bianconi mcu_clk = devm_clk_get(pdev, "mcu");
1202cd85efdfSLorenzo Bianconi if (IS_ERR(mcu_clk))
1203cd85efdfSLorenzo Bianconi dev_err(pdev, "mcu clock not found\n");
1204cd85efdfSLorenzo Bianconi else if (clk_prepare_enable(mcu_clk))
1205cd85efdfSLorenzo Bianconi dev_err(pdev, "mcu clock configuration failed\n");
1206cd85efdfSLorenzo Bianconi
1207cd85efdfSLorenzo Bianconi ap_conn_clk = devm_clk_get(pdev, "ap2conn");
1208cd85efdfSLorenzo Bianconi if (IS_ERR(ap_conn_clk))
1209cd85efdfSLorenzo Bianconi dev_err(pdev, "ap2conn clock not found\n");
1210cd85efdfSLorenzo Bianconi else if (clk_prepare_enable(ap_conn_clk))
1211cd85efdfSLorenzo Bianconi dev_err(pdev, "ap2conn clock configuration failed\n");
121299ad32a4SBo Jiao
121399ad32a4SBo Jiao dev->dcm = devm_platform_ioremap_resource(pfdev, 1);
121499ad32a4SBo Jiao if (IS_ERR(dev->dcm))
121599ad32a4SBo Jiao return PTR_ERR(dev->dcm);
121699ad32a4SBo Jiao
121799ad32a4SBo Jiao dev->sku = devm_platform_ioremap_resource(pfdev, 2);
121899ad32a4SBo Jiao if (IS_ERR(dev->sku))
121999ad32a4SBo Jiao return PTR_ERR(dev->sku);
122099ad32a4SBo Jiao
122199ad32a4SBo Jiao dev->rstc = devm_reset_control_get(pdev, "consys");
122299ad32a4SBo Jiao if (IS_ERR(dev->rstc))
122399ad32a4SBo Jiao return PTR_ERR(dev->rstc);
122499ad32a4SBo Jiao
12255beadb27SRyder Lee return 0;
122699ad32a4SBo Jiao }
122799ad32a4SBo Jiao
mt798x_wmac_probe(struct platform_device * pdev)1228*6bad146dSAlexander Couzens static int mt798x_wmac_probe(struct platform_device *pdev)
122999ad32a4SBo Jiao {
123099ad32a4SBo Jiao void __iomem *mem_base;
123199ad32a4SBo Jiao struct mt7915_dev *dev;
123299ad32a4SBo Jiao struct mt76_dev *mdev;
123399ad32a4SBo Jiao int irq, ret;
123499ad32a4SBo Jiao u32 chip_id;
123599ad32a4SBo Jiao
123699ad32a4SBo Jiao chip_id = (uintptr_t)of_device_get_match_data(&pdev->dev);
123799ad32a4SBo Jiao
123899ad32a4SBo Jiao mem_base = devm_platform_ioremap_resource(pdev, 0);
123999ad32a4SBo Jiao if (IS_ERR(mem_base)) {
124099ad32a4SBo Jiao dev_err(&pdev->dev, "Failed to get memory resource\n");
124199ad32a4SBo Jiao return PTR_ERR(mem_base);
124299ad32a4SBo Jiao }
124399ad32a4SBo Jiao
124499ad32a4SBo Jiao dev = mt7915_mmio_probe(&pdev->dev, mem_base, chip_id);
124599ad32a4SBo Jiao if (IS_ERR(dev))
124699ad32a4SBo Jiao return PTR_ERR(dev);
124799ad32a4SBo Jiao
124899ad32a4SBo Jiao mdev = &dev->mt76;
1249eebb7097SLorenzo Bianconi ret = mt7915_mmio_wed_init(dev, pdev, false, &irq);
1250eebb7097SLorenzo Bianconi if (ret < 0)
1251eebb7097SLorenzo Bianconi goto free_device;
1252eebb7097SLorenzo Bianconi
1253eebb7097SLorenzo Bianconi if (!ret) {
1254eebb7097SLorenzo Bianconi irq = platform_get_irq(pdev, 0);
1255eebb7097SLorenzo Bianconi if (irq < 0) {
1256eebb7097SLorenzo Bianconi ret = irq;
1257eebb7097SLorenzo Bianconi goto free_device;
1258eebb7097SLorenzo Bianconi }
1259eebb7097SLorenzo Bianconi }
1260eebb7097SLorenzo Bianconi
126199ad32a4SBo Jiao ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler,
126299ad32a4SBo Jiao IRQF_SHARED, KBUILD_MODNAME, dev);
126399ad32a4SBo Jiao if (ret)
126499ad32a4SBo Jiao goto free_device;
126599ad32a4SBo Jiao
1266*6bad146dSAlexander Couzens ret = mt798x_wmac_init(dev);
126799ad32a4SBo Jiao if (ret)
126899ad32a4SBo Jiao goto free_irq;
126999ad32a4SBo Jiao
12705beadb27SRyder Lee mt7915_wfsys_reset(dev);
12715beadb27SRyder Lee
127299ad32a4SBo Jiao ret = mt7915_register_device(dev);
127399ad32a4SBo Jiao if (ret)
127499ad32a4SBo Jiao goto free_irq;
127599ad32a4SBo Jiao
127699ad32a4SBo Jiao return 0;
127799ad32a4SBo Jiao
127899ad32a4SBo Jiao free_irq:
127999ad32a4SBo Jiao devm_free_irq(mdev->dev, irq, dev);
128099ad32a4SBo Jiao free_device:
1281eebb7097SLorenzo Bianconi if (mtk_wed_device_active(&mdev->mmio.wed))
1282eebb7097SLorenzo Bianconi mtk_wed_device_detach(&mdev->mmio.wed);
1283eebb7097SLorenzo Bianconi mt76_free_device(mdev);
128499ad32a4SBo Jiao
128599ad32a4SBo Jiao return ret;
128699ad32a4SBo Jiao }
128799ad32a4SBo Jiao
mt798x_wmac_remove(struct platform_device * pdev)1288*6bad146dSAlexander Couzens static int mt798x_wmac_remove(struct platform_device *pdev)
128999ad32a4SBo Jiao {
129099ad32a4SBo Jiao struct mt7915_dev *dev = platform_get_drvdata(pdev);
129199ad32a4SBo Jiao
129299ad32a4SBo Jiao mt7915_unregister_device(dev);
129399ad32a4SBo Jiao
129499ad32a4SBo Jiao return 0;
129599ad32a4SBo Jiao }
129699ad32a4SBo Jiao
1297*6bad146dSAlexander Couzens static const struct of_device_id mt798x_wmac_of_match[] = {
1298*6bad146dSAlexander Couzens { .compatible = "mediatek,mt7981-wmac", .data = (u32 *)0x7981 },
129999ad32a4SBo Jiao { .compatible = "mediatek,mt7986-wmac", .data = (u32 *)0x7986 },
130099ad32a4SBo Jiao {},
130199ad32a4SBo Jiao };
130299ad32a4SBo Jiao
1303*6bad146dSAlexander Couzens MODULE_DEVICE_TABLE(of, mt798x_wmac_of_match);
130490fb6921SLorenz Brun
1305*6bad146dSAlexander Couzens struct platform_driver mt798x_wmac_driver = {
130699ad32a4SBo Jiao .driver = {
1307*6bad146dSAlexander Couzens .name = "mt798x-wmac",
1308*6bad146dSAlexander Couzens .of_match_table = mt798x_wmac_of_match,
130999ad32a4SBo Jiao },
1310*6bad146dSAlexander Couzens .probe = mt798x_wmac_probe,
1311*6bad146dSAlexander Couzens .remove = mt798x_wmac_remove,
131299ad32a4SBo Jiao };
131399ad32a4SBo Jiao
131499ad32a4SBo Jiao MODULE_FIRMWARE(MT7986_FIRMWARE_WA);
131599ad32a4SBo Jiao MODULE_FIRMWARE(MT7986_FIRMWARE_WM);
131699ad32a4SBo Jiao MODULE_FIRMWARE(MT7986_FIRMWARE_WM_MT7975);
131799ad32a4SBo Jiao MODULE_FIRMWARE(MT7986_ROM_PATCH);
131899ad32a4SBo Jiao MODULE_FIRMWARE(MT7986_ROM_PATCH_MT7975);
1319*6bad146dSAlexander Couzens
1320*6bad146dSAlexander Couzens MODULE_FIRMWARE(MT7981_FIRMWARE_WA);
1321*6bad146dSAlexander Couzens MODULE_FIRMWARE(MT7981_FIRMWARE_WM);
1322*6bad146dSAlexander Couzens MODULE_FIRMWARE(MT7981_ROM_PATCH);
1323