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); 28118425d7dSWang Yufen of_node_put(np); 28299ad32a4SBo Jiao if (!rmem) 28399ad32a4SBo Jiao return -EINVAL; 28499ad32a4SBo Jiao 28599ad32a4SBo Jiao val = (rmem->base >> 16) & MT_TOP_MCU_EMI_BASE_MASK; 28699ad32a4SBo Jiao 28799ad32a4SBo Jiao /* Set conninfra subsys PLL check */ 28899ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS, 28999ad32a4SBo Jiao MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1); 29099ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS, 29199ad32a4SBo Jiao MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1); 29299ad32a4SBo Jiao 29399ad32a4SBo Jiao mt76_rmw_field(dev, MT_TOP_MCU_EMI_BASE, 29499ad32a4SBo Jiao MT_TOP_MCU_EMI_BASE_MASK, val); 29599ad32a4SBo Jiao 29699ad32a4SBo Jiao mt76_wr(dev, MT_INFRA_BUS_EMI_START, rmem->base); 29799ad32a4SBo Jiao mt76_wr(dev, MT_INFRA_BUS_EMI_END, rmem->size); 29899ad32a4SBo Jiao 29999ad32a4SBo Jiao mt76_rr(dev, MT_CONN_INFRA_EFUSE); 30099ad32a4SBo Jiao 30199ad32a4SBo Jiao /* Set conninfra sysram */ 30299ad32a4SBo Jiao mt76_wr(dev, MT_TOP_RGU_SYSRAM_PDN, 0); 30399ad32a4SBo Jiao mt76_wr(dev, MT_TOP_RGU_SYSRAM_SLP, 1); 30499ad32a4SBo Jiao 30599ad32a4SBo Jiao return 0; 30699ad32a4SBo Jiao } 30799ad32a4SBo Jiao 30899ad32a4SBo Jiao static int mt7986_wmac_sku_setup(struct mt7915_dev *dev, u32 *adie_type) 30999ad32a4SBo Jiao { 31099ad32a4SBo Jiao int ret; 31199ad32a4SBo Jiao u32 adie_main, adie_ext; 31299ad32a4SBo Jiao 31399ad32a4SBo Jiao mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET, 31499ad32a4SBo Jiao MT_CONN_INFRA_ADIE1_RESET_MASK, 0x1); 31599ad32a4SBo Jiao mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET, 31699ad32a4SBo Jiao MT_CONN_INFRA_ADIE2_RESET_MASK, 0x1); 31799ad32a4SBo Jiao 31899ad32a4SBo Jiao mt76_wmac_spi_lock(dev); 31999ad32a4SBo Jiao 32099ad32a4SBo Jiao ret = mt76_wmac_spi_read(dev, 0, MT_ADIE_CHIP_ID, &adie_main); 32199ad32a4SBo Jiao if (ret) 32299ad32a4SBo Jiao goto out; 32399ad32a4SBo Jiao 32499ad32a4SBo Jiao ret = mt76_wmac_spi_read(dev, 1, MT_ADIE_CHIP_ID, &adie_ext); 32599ad32a4SBo Jiao if (ret) 32699ad32a4SBo Jiao goto out; 32799ad32a4SBo Jiao 32899ad32a4SBo Jiao *adie_type = FIELD_GET(MT_ADIE_CHIP_ID_MASK, adie_main) | 32999ad32a4SBo Jiao (MT_ADIE_CHIP_ID_MASK & adie_ext); 33099ad32a4SBo Jiao 33199ad32a4SBo Jiao out: 33299ad32a4SBo Jiao mt76_wmac_spi_unlock(dev); 33399ad32a4SBo Jiao 33499ad32a4SBo Jiao return 0; 33599ad32a4SBo Jiao } 33699ad32a4SBo Jiao 33799ad32a4SBo Jiao static inline u16 mt7986_adie_idx(u8 adie, u32 adie_type) 33899ad32a4SBo Jiao { 33999ad32a4SBo Jiao if (adie == 0) 34099ad32a4SBo Jiao return u32_get_bits(adie_type, MT_ADIE_IDX0); 34199ad32a4SBo Jiao else 34299ad32a4SBo Jiao return u32_get_bits(adie_type, MT_ADIE_IDX1); 34399ad32a4SBo Jiao } 34499ad32a4SBo Jiao 34599ad32a4SBo Jiao static inline bool is_7975(struct mt7915_dev *dev, u8 adie, u32 adie_type) 34699ad32a4SBo Jiao { 34799ad32a4SBo Jiao return mt7986_adie_idx(adie, adie_type) == 0x7975; 34899ad32a4SBo Jiao } 34999ad32a4SBo Jiao 35099ad32a4SBo Jiao static inline bool is_7976(struct mt7915_dev *dev, u8 adie, u32 adie_type) 35199ad32a4SBo Jiao { 35299ad32a4SBo Jiao return mt7986_adie_idx(adie, adie_type) == 0x7976; 35399ad32a4SBo Jiao } 35499ad32a4SBo Jiao 35599ad32a4SBo Jiao static int mt7986_wmac_adie_thermal_cal(struct mt7915_dev *dev, u8 adie) 35699ad32a4SBo Jiao { 35799ad32a4SBo Jiao int ret; 35899ad32a4SBo Jiao u32 data, val; 35999ad32a4SBo Jiao 36099ad32a4SBo Jiao ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_THADC_ANALOG, 36199ad32a4SBo Jiao &data); 36299ad32a4SBo Jiao if (ret || FIELD_GET(MT_ADIE_ANA_EN_MASK, data)) { 36399ad32a4SBo Jiao val = FIELD_GET(MT_ADIE_VRPI_SEL_EFUSE_MASK, data); 36499ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_RG_TOP_THADC_BG, 36599ad32a4SBo Jiao MT_ADIE_VRPI_SEL_CR_MASK, 36699ad32a4SBo Jiao FIELD_PREP(MT_ADIE_VRPI_SEL_CR_MASK, val)); 36799ad32a4SBo Jiao if (ret) 36899ad32a4SBo Jiao return ret; 36999ad32a4SBo Jiao 37099ad32a4SBo Jiao val = FIELD_GET(MT_ADIE_PGA_GAIN_EFUSE_MASK, data); 37199ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_RG_TOP_THADC, 37299ad32a4SBo Jiao MT_ADIE_PGA_GAIN_MASK, 37399ad32a4SBo Jiao FIELD_PREP(MT_ADIE_PGA_GAIN_MASK, val)); 37499ad32a4SBo Jiao if (ret) 37599ad32a4SBo Jiao return ret; 37699ad32a4SBo Jiao } 37799ad32a4SBo Jiao 37899ad32a4SBo Jiao ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_THADC_SLOP, 37999ad32a4SBo Jiao &data); 38099ad32a4SBo Jiao if (ret || FIELD_GET(MT_ADIE_ANA_EN_MASK, data)) { 38199ad32a4SBo Jiao val = FIELD_GET(MT_ADIE_LDO_CTRL_EFUSE_MASK, data); 38299ad32a4SBo Jiao 38399ad32a4SBo Jiao return mt76_wmac_spi_rmw(dev, adie, MT_ADIE_RG_TOP_THADC, 38499ad32a4SBo Jiao MT_ADIE_LDO_CTRL_MASK, 38599ad32a4SBo Jiao FIELD_PREP(MT_ADIE_LDO_CTRL_MASK, val)); 38699ad32a4SBo Jiao } 38799ad32a4SBo Jiao 38899ad32a4SBo Jiao return 0; 38999ad32a4SBo Jiao } 39099ad32a4SBo Jiao 39199ad32a4SBo Jiao static int 39299ad32a4SBo Jiao mt7986_read_efuse_xo_trim_7976(struct mt7915_dev *dev, u8 adie, 39399ad32a4SBo Jiao bool is_40m, int *result) 39499ad32a4SBo Jiao { 39599ad32a4SBo Jiao int ret; 39699ad32a4SBo Jiao u32 data, addr; 39799ad32a4SBo Jiao 39899ad32a4SBo Jiao addr = is_40m ? MT_ADIE_XTAL_AXM_40M_OSC : MT_ADIE_XTAL_AXM_80M_OSC; 39999ad32a4SBo Jiao ret = mt7986_wmac_adie_efuse_read(dev, adie, addr, &data); 40099ad32a4SBo Jiao if (ret) 40199ad32a4SBo Jiao return ret; 40299ad32a4SBo Jiao 40399ad32a4SBo Jiao if (!FIELD_GET(MT_ADIE_XO_TRIM_EN_MASK, data)) { 40499ad32a4SBo Jiao *result = 64; 40599ad32a4SBo Jiao } else { 40699ad32a4SBo Jiao *result = FIELD_GET(MT_ADIE_TRIM_MASK, data); 40799ad32a4SBo Jiao addr = is_40m ? MT_ADIE_XTAL_TRIM1_40M_OSC : 40899ad32a4SBo Jiao MT_ADIE_XTAL_TRIM1_80M_OSC; 40999ad32a4SBo Jiao ret = mt7986_wmac_adie_efuse_read(dev, adie, addr, &data); 41099ad32a4SBo Jiao if (ret) 41199ad32a4SBo Jiao return ret; 41299ad32a4SBo Jiao 41399ad32a4SBo Jiao if (FIELD_GET(MT_ADIE_XO_TRIM_EN_MASK, data) && 41499ad32a4SBo Jiao FIELD_GET(MT_ADIE_XTAL_DECREASE_MASK, data)) 41599ad32a4SBo Jiao *result -= FIELD_GET(MT_ADIE_EFUSE_TRIM_MASK, data); 41699ad32a4SBo Jiao else if (FIELD_GET(MT_ADIE_XO_TRIM_EN_MASK, data)) 41799ad32a4SBo Jiao *result += FIELD_GET(MT_ADIE_EFUSE_TRIM_MASK, data); 41899ad32a4SBo Jiao 41999ad32a4SBo Jiao *result = max(0, min(127, *result)); 42099ad32a4SBo Jiao } 42199ad32a4SBo Jiao 42299ad32a4SBo Jiao return 0; 42399ad32a4SBo Jiao } 42499ad32a4SBo Jiao 42599ad32a4SBo Jiao static int mt7986_wmac_adie_xtal_trim_7976(struct mt7915_dev *dev, u8 adie) 42699ad32a4SBo Jiao { 42799ad32a4SBo Jiao int ret, trim_80m, trim_40m; 42899ad32a4SBo Jiao u32 data, val, mode; 42999ad32a4SBo Jiao 43099ad32a4SBo Jiao ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_XO_TRIM_FLOW, 43199ad32a4SBo Jiao &data); 43299ad32a4SBo Jiao if (ret || !FIELD_GET(BIT(1), data)) 43399ad32a4SBo Jiao return 0; 43499ad32a4SBo Jiao 43599ad32a4SBo Jiao ret = mt7986_read_efuse_xo_trim_7976(dev, adie, false, &trim_80m); 43699ad32a4SBo Jiao if (ret) 43799ad32a4SBo Jiao return ret; 43899ad32a4SBo Jiao 43999ad32a4SBo Jiao ret = mt7986_read_efuse_xo_trim_7976(dev, adie, true, &trim_40m); 44099ad32a4SBo Jiao if (ret) 44199ad32a4SBo Jiao return ret; 44299ad32a4SBo Jiao 44399ad32a4SBo Jiao ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_RG_STRAP_PIN_IN, &val); 44499ad32a4SBo Jiao if (ret) 44599ad32a4SBo Jiao return ret; 44699ad32a4SBo Jiao 44799ad32a4SBo Jiao mode = FIELD_PREP(GENMASK(6, 4), val); 44899ad32a4SBo Jiao if (!mode || mode == 0x2) { 44999ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C1, 45099ad32a4SBo Jiao GENMASK(31, 24), 45199ad32a4SBo Jiao FIELD_PREP(GENMASK(31, 24), trim_80m)); 45299ad32a4SBo Jiao if (ret) 45399ad32a4SBo Jiao return ret; 45499ad32a4SBo Jiao 45599ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C2, 45699ad32a4SBo Jiao GENMASK(31, 24), 45799ad32a4SBo Jiao FIELD_PREP(GENMASK(31, 24), trim_80m)); 45899ad32a4SBo Jiao } else if (mode == 0x3 || mode == 0x4 || mode == 0x6) { 45999ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C1, 46099ad32a4SBo Jiao GENMASK(23, 16), 46199ad32a4SBo Jiao FIELD_PREP(GENMASK(23, 16), trim_40m)); 46299ad32a4SBo Jiao if (ret) 46399ad32a4SBo Jiao return ret; 46499ad32a4SBo Jiao 46599ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_XTAL_C2, 46699ad32a4SBo Jiao GENMASK(23, 16), 46799ad32a4SBo Jiao FIELD_PREP(GENMASK(23, 16), trim_40m)); 46899ad32a4SBo Jiao } 46999ad32a4SBo Jiao 47099ad32a4SBo Jiao return ret; 47199ad32a4SBo Jiao } 47299ad32a4SBo Jiao 47399ad32a4SBo Jiao static int mt7986_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie) 47499ad32a4SBo Jiao { 475b5509983SPeter Chiu u32 id, version, rg_xo_01, rg_xo_03; 47699ad32a4SBo Jiao int ret; 47799ad32a4SBo Jiao 478b5509983SPeter Chiu ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_CHIP_ID, &id); 479b5509983SPeter Chiu if (ret) 480b5509983SPeter Chiu return ret; 481b5509983SPeter Chiu 482b5509983SPeter Chiu version = FIELD_GET(MT_ADIE_VERSION_MASK, id); 483b5509983SPeter Chiu 48499ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_TOP_THADC, 0x4a563b00); 48599ad32a4SBo Jiao if (ret) 48699ad32a4SBo Jiao return ret; 48799ad32a4SBo Jiao 488b5509983SPeter Chiu if (version == 0x8a00 || version == 0x8a10 || version == 0x8b00) { 489b5509983SPeter Chiu rg_xo_01 = 0x1d59080f; 490b5509983SPeter Chiu rg_xo_03 = 0x34c00fe0; 491b5509983SPeter Chiu } else { 492b5509983SPeter Chiu rg_xo_01 = 0x1959f80f; 493b5509983SPeter Chiu rg_xo_03 = 0x34d00fe0; 494b5509983SPeter Chiu } 495b5509983SPeter Chiu 496b5509983SPeter Chiu ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_01, rg_xo_01); 49799ad32a4SBo Jiao if (ret) 49899ad32a4SBo Jiao return ret; 49999ad32a4SBo Jiao 500b5509983SPeter Chiu return mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_03, rg_xo_03); 50199ad32a4SBo Jiao } 50299ad32a4SBo Jiao 50399ad32a4SBo Jiao static int 50499ad32a4SBo Jiao mt7986_read_efuse_xo_trim_7975(struct mt7915_dev *dev, u8 adie, 50599ad32a4SBo Jiao u32 addr, u32 *result) 50699ad32a4SBo Jiao { 50799ad32a4SBo Jiao int ret; 50899ad32a4SBo Jiao u32 data; 50999ad32a4SBo Jiao 51099ad32a4SBo Jiao ret = mt7986_wmac_adie_efuse_read(dev, adie, addr, &data); 51199ad32a4SBo Jiao if (ret) 51299ad32a4SBo Jiao return ret; 51399ad32a4SBo Jiao 51499ad32a4SBo Jiao if ((data & MT_ADIE_XO_TRIM_EN_MASK)) { 51599ad32a4SBo Jiao if ((data & MT_ADIE_XTAL_DECREASE_MASK)) 51699ad32a4SBo Jiao *result -= (data & MT_ADIE_EFUSE_TRIM_MASK); 51799ad32a4SBo Jiao else 51899ad32a4SBo Jiao *result += (data & MT_ADIE_EFUSE_TRIM_MASK); 51999ad32a4SBo Jiao 52099ad32a4SBo Jiao *result = (*result & MT_ADIE_TRIM_MASK); 52199ad32a4SBo Jiao } 52299ad32a4SBo Jiao 52399ad32a4SBo Jiao return 0; 52499ad32a4SBo Jiao } 52599ad32a4SBo Jiao 52699ad32a4SBo Jiao static int mt7986_wmac_adie_xtal_trim_7975(struct mt7915_dev *dev, u8 adie) 52799ad32a4SBo Jiao { 52899ad32a4SBo Jiao int ret; 52999ad32a4SBo Jiao u32 data, result = 0, value; 53099ad32a4SBo Jiao 53199ad32a4SBo Jiao ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_7975_XTAL_EN, 53299ad32a4SBo Jiao &data); 53399ad32a4SBo Jiao if (ret || !(data & BIT(1))) 53499ad32a4SBo Jiao return 0; 53599ad32a4SBo Jiao 53699ad32a4SBo Jiao ret = mt7986_wmac_adie_efuse_read(dev, adie, MT_ADIE_7975_XTAL_CAL, 53799ad32a4SBo Jiao &data); 53899ad32a4SBo Jiao if (ret) 53999ad32a4SBo Jiao return ret; 54099ad32a4SBo Jiao 54199ad32a4SBo Jiao if (data & MT_ADIE_XO_TRIM_EN_MASK) 54299ad32a4SBo Jiao result = (data & MT_ADIE_TRIM_MASK); 54399ad32a4SBo Jiao 54499ad32a4SBo Jiao ret = mt7986_read_efuse_xo_trim_7975(dev, adie, MT_ADIE_7975_XO_TRIM2, 54599ad32a4SBo Jiao &result); 54699ad32a4SBo Jiao if (ret) 54799ad32a4SBo Jiao return ret; 54899ad32a4SBo Jiao 54999ad32a4SBo Jiao ret = mt7986_read_efuse_xo_trim_7975(dev, adie, MT_ADIE_7975_XO_TRIM3, 55099ad32a4SBo Jiao &result); 55199ad32a4SBo Jiao if (ret) 55299ad32a4SBo Jiao return ret; 55399ad32a4SBo Jiao 55499ad32a4SBo Jiao ret = mt7986_read_efuse_xo_trim_7975(dev, adie, MT_ADIE_7975_XO_TRIM4, 55599ad32a4SBo Jiao &result); 55699ad32a4SBo Jiao if (ret) 55799ad32a4SBo Jiao return ret; 55899ad32a4SBo Jiao 55999ad32a4SBo Jiao /* Update trim value to C1 and C2*/ 56099ad32a4SBo Jiao value = FIELD_GET(MT_ADIE_7975_XO_CTRL2_C1_MASK, result) | 56199ad32a4SBo Jiao FIELD_GET(MT_ADIE_7975_XO_CTRL2_C2_MASK, result); 56299ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_XO_CTRL2, 56399ad32a4SBo Jiao MT_ADIE_7975_XO_CTRL2_MASK, value); 56499ad32a4SBo Jiao if (ret) 56599ad32a4SBo Jiao return ret; 56699ad32a4SBo Jiao 56799ad32a4SBo Jiao ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_7975_XTAL, &value); 56899ad32a4SBo Jiao if (ret) 56999ad32a4SBo Jiao return ret; 57099ad32a4SBo Jiao 57199ad32a4SBo Jiao if (value & MT_ADIE_7975_XTAL_EN_MASK) { 57299ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_XO_2, 57399ad32a4SBo Jiao MT_ADIE_7975_XO_2_FIX_EN, 0x0); 57499ad32a4SBo Jiao if (ret) 57599ad32a4SBo Jiao return ret; 57699ad32a4SBo Jiao } 57799ad32a4SBo Jiao 57899ad32a4SBo Jiao return mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_XO_CTRL6, 57999ad32a4SBo Jiao MT_ADIE_7975_XO_CTRL6_MASK, 0x1); 58099ad32a4SBo Jiao } 58199ad32a4SBo Jiao 58299ad32a4SBo Jiao static int mt7986_wmac_adie_patch_7975(struct mt7915_dev *dev, u8 adie) 58399ad32a4SBo Jiao { 58499ad32a4SBo Jiao int ret; 58599ad32a4SBo Jiao 58699ad32a4SBo Jiao /* disable CAL LDO and fine tune RFDIG LDO */ 58799ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x348, 0x00000002); 58899ad32a4SBo Jiao if (ret) 58999ad32a4SBo Jiao return ret; 59099ad32a4SBo Jiao 59199ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x378, 0x00000002); 59299ad32a4SBo Jiao if (ret) 59399ad32a4SBo Jiao return ret; 59499ad32a4SBo Jiao 59599ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x3a8, 0x00000002); 59699ad32a4SBo Jiao if (ret) 59799ad32a4SBo Jiao return ret; 59899ad32a4SBo Jiao 59999ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x3d8, 0x00000002); 60099ad32a4SBo Jiao if (ret) 60199ad32a4SBo Jiao return ret; 60299ad32a4SBo Jiao 60399ad32a4SBo Jiao /* set CKA driving and filter */ 60499ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0xa1c, 0x30000aaa); 60599ad32a4SBo Jiao if (ret) 60699ad32a4SBo Jiao return ret; 60799ad32a4SBo Jiao 60899ad32a4SBo Jiao /* set CKB LDO to 1.4V */ 60999ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0xa84, 0x8470008a); 61099ad32a4SBo Jiao if (ret) 61199ad32a4SBo Jiao return ret; 61299ad32a4SBo Jiao 61399ad32a4SBo Jiao /* turn on SX0 LTBUF */ 61499ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x074, 0x00000002); 61599ad32a4SBo Jiao if (ret) 61699ad32a4SBo Jiao return ret; 61799ad32a4SBo Jiao 61899ad32a4SBo Jiao /* CK_BUF_SW_EN = 1 (all buf in manual mode.) */ 61999ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0xaa4, 0x01001fc0); 62099ad32a4SBo Jiao if (ret) 62199ad32a4SBo Jiao return ret; 62299ad32a4SBo Jiao 62399ad32a4SBo Jiao /* BT mode/WF normal mode 00000005 */ 62499ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x070, 0x00000005); 62599ad32a4SBo Jiao if (ret) 62699ad32a4SBo Jiao return ret; 62799ad32a4SBo Jiao 62899ad32a4SBo Jiao /* BG thermal sensor offset update */ 62999ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x344, 0x00000088); 63099ad32a4SBo Jiao if (ret) 63199ad32a4SBo Jiao return ret; 63299ad32a4SBo Jiao 63399ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x374, 0x00000088); 63499ad32a4SBo Jiao if (ret) 63599ad32a4SBo Jiao return ret; 63699ad32a4SBo Jiao 63799ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x3a4, 0x00000088); 63899ad32a4SBo Jiao if (ret) 63999ad32a4SBo Jiao return ret; 64099ad32a4SBo Jiao 64199ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x3d4, 0x00000088); 64299ad32a4SBo Jiao if (ret) 64399ad32a4SBo Jiao return ret; 64499ad32a4SBo Jiao 64599ad32a4SBo Jiao /* set WCON VDD IPTAT to "0000" */ 64699ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0xa80, 0x44d07000); 64799ad32a4SBo Jiao if (ret) 64899ad32a4SBo Jiao return ret; 64999ad32a4SBo Jiao 65099ad32a4SBo Jiao /* change back LTBUF SX3 drving to default value */ 65199ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0xa88, 0x3900aaaa); 65299ad32a4SBo Jiao if (ret) 65399ad32a4SBo Jiao return ret; 65499ad32a4SBo Jiao 65599ad32a4SBo Jiao /* SM input cap off */ 65699ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 0x2c4, 0x00000000); 65799ad32a4SBo Jiao if (ret) 65899ad32a4SBo Jiao return ret; 65999ad32a4SBo Jiao 66099ad32a4SBo Jiao /* set CKB driving and filter */ 66199ad32a4SBo Jiao return mt76_wmac_spi_write(dev, adie, 0x2c8, 0x00000072); 66299ad32a4SBo Jiao } 66399ad32a4SBo Jiao 66499ad32a4SBo Jiao static int mt7986_wmac_adie_cfg(struct mt7915_dev *dev, u8 adie, u32 adie_type) 66599ad32a4SBo Jiao { 66699ad32a4SBo Jiao int ret; 66799ad32a4SBo Jiao 66899ad32a4SBo Jiao mt76_wmac_spi_lock(dev); 66999ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_CLK_EN, ~0); 67099ad32a4SBo Jiao if (ret) 67199ad32a4SBo Jiao goto out; 67299ad32a4SBo Jiao 67399ad32a4SBo Jiao if (is_7975(dev, adie, adie_type)) { 67499ad32a4SBo Jiao ret = mt76_wmac_spi_rmw(dev, adie, MT_ADIE_7975_COCLK, 67599ad32a4SBo Jiao BIT(1), 0x1); 67699ad32a4SBo Jiao if (ret) 67799ad32a4SBo Jiao goto out; 67899ad32a4SBo Jiao 67999ad32a4SBo Jiao ret = mt7986_wmac_adie_thermal_cal(dev, adie); 68099ad32a4SBo Jiao if (ret) 68199ad32a4SBo Jiao goto out; 68299ad32a4SBo Jiao 68399ad32a4SBo Jiao ret = mt7986_wmac_adie_xtal_trim_7975(dev, adie); 68499ad32a4SBo Jiao if (ret) 68599ad32a4SBo Jiao goto out; 68699ad32a4SBo Jiao 68799ad32a4SBo Jiao ret = mt7986_wmac_adie_patch_7975(dev, adie); 68899ad32a4SBo Jiao } else if (is_7976(dev, adie, adie_type)) { 68999ad32a4SBo Jiao if (mt7986_wmac_check_adie_type(dev) == ADIE_DBDC) { 69099ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 69199ad32a4SBo Jiao MT_ADIE_WRI_CK_SEL, 0x1c); 69299ad32a4SBo Jiao if (ret) 69399ad32a4SBo Jiao goto out; 69499ad32a4SBo Jiao } 69599ad32a4SBo Jiao 69699ad32a4SBo Jiao ret = mt7986_wmac_adie_thermal_cal(dev, adie); 69799ad32a4SBo Jiao if (ret) 69899ad32a4SBo Jiao goto out; 69999ad32a4SBo Jiao 70099ad32a4SBo Jiao ret = mt7986_wmac_adie_xtal_trim_7976(dev, adie); 70199ad32a4SBo Jiao if (ret) 70299ad32a4SBo Jiao goto out; 70399ad32a4SBo Jiao 70499ad32a4SBo Jiao ret = mt7986_wmac_adie_patch_7976(dev, adie); 70599ad32a4SBo Jiao } 70699ad32a4SBo Jiao out: 70799ad32a4SBo Jiao mt76_wmac_spi_unlock(dev); 70899ad32a4SBo Jiao 70999ad32a4SBo Jiao return ret; 71099ad32a4SBo Jiao } 71199ad32a4SBo Jiao 71299ad32a4SBo Jiao static int 71399ad32a4SBo Jiao mt7986_wmac_afe_cal(struct mt7915_dev *dev, u8 adie, bool dbdc, u32 adie_type) 71499ad32a4SBo Jiao { 71599ad32a4SBo Jiao int ret; 71699ad32a4SBo Jiao u8 idx; 71799ad32a4SBo Jiao 71899ad32a4SBo Jiao mt76_wmac_spi_lock(dev); 71999ad32a4SBo Jiao if (is_7975(dev, adie, adie_type)) 72099ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 72199ad32a4SBo Jiao MT_AFE_RG_ENCAL_WBTAC_IF_SW, 72299ad32a4SBo Jiao 0x80000000); 72399ad32a4SBo Jiao else 72499ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, 72599ad32a4SBo Jiao MT_AFE_RG_ENCAL_WBTAC_IF_SW, 72699ad32a4SBo Jiao 0x88888005); 72799ad32a4SBo Jiao if (ret) 72899ad32a4SBo Jiao goto out; 72999ad32a4SBo Jiao 73099ad32a4SBo Jiao idx = dbdc ? ADIE_DBDC : adie; 73199ad32a4SBo Jiao 73299ad32a4SBo Jiao mt76_rmw_field(dev, MT_AFE_DIG_EN_01(idx), 73399ad32a4SBo Jiao MT_AFE_RG_WBG_EN_RCK_MASK, 0x1); 73499ad32a4SBo Jiao usleep_range(60, 100); 73599ad32a4SBo Jiao 73699ad32a4SBo Jiao mt76_rmw(dev, MT_AFE_DIG_EN_01(idx), 73799ad32a4SBo Jiao MT_AFE_RG_WBG_EN_RCK_MASK, 0x0); 73899ad32a4SBo Jiao 73999ad32a4SBo Jiao mt76_rmw_field(dev, MT_AFE_DIG_EN_03(idx), 74099ad32a4SBo Jiao MT_AFE_RG_WBG_EN_BPLL_UP_MASK, 0x1); 74199ad32a4SBo Jiao usleep_range(30, 100); 74299ad32a4SBo Jiao 74399ad32a4SBo Jiao mt76_rmw_field(dev, MT_AFE_DIG_EN_03(idx), 74499ad32a4SBo Jiao MT_AFE_RG_WBG_EN_WPLL_UP_MASK, 0x1); 74599ad32a4SBo Jiao usleep_range(60, 100); 74699ad32a4SBo Jiao 74799ad32a4SBo Jiao mt76_rmw_field(dev, MT_AFE_DIG_EN_01(idx), 74899ad32a4SBo Jiao MT_AFE_RG_WBG_EN_TXCAL_MASK, 0x1f); 74999ad32a4SBo Jiao usleep_range(800, 1000); 75099ad32a4SBo Jiao 75199ad32a4SBo Jiao mt76_rmw(dev, MT_AFE_DIG_EN_01(idx), 75299ad32a4SBo Jiao MT_AFE_RG_WBG_EN_TXCAL_MASK, 0x0); 75399ad32a4SBo Jiao mt76_rmw(dev, MT_AFE_DIG_EN_03(idx), 75499ad32a4SBo Jiao MT_AFE_RG_WBG_EN_PLL_UP_MASK, 0x0); 75599ad32a4SBo Jiao 75699ad32a4SBo Jiao ret = mt76_wmac_spi_write(dev, adie, MT_AFE_RG_ENCAL_WBTAC_IF_SW, 75799ad32a4SBo Jiao 0x5); 75899ad32a4SBo Jiao 75999ad32a4SBo Jiao out: 76099ad32a4SBo Jiao mt76_wmac_spi_unlock(dev); 76199ad32a4SBo Jiao 76299ad32a4SBo Jiao return ret; 76399ad32a4SBo Jiao } 76499ad32a4SBo Jiao 76599ad32a4SBo Jiao static void mt7986_wmac_subsys_pll_initial(struct mt7915_dev *dev, u8 band) 76699ad32a4SBo Jiao { 76799ad32a4SBo Jiao mt76_rmw(dev, MT_AFE_PLL_STB_TIME(band), 76899ad32a4SBo Jiao MT_AFE_PLL_STB_TIME_MASK, MT_AFE_PLL_STB_TIME_VAL); 76999ad32a4SBo Jiao 77099ad32a4SBo Jiao mt76_rmw(dev, MT_AFE_DIG_EN_02(band), 77199ad32a4SBo Jiao MT_AFE_PLL_CFG_MASK, MT_AFE_PLL_CFG_VAL); 77299ad32a4SBo Jiao 77399ad32a4SBo Jiao mt76_rmw(dev, MT_AFE_DIG_TOP_01(band), 77499ad32a4SBo Jiao MT_AFE_DIG_TOP_01_MASK, MT_AFE_DIG_TOP_01_VAL); 77599ad32a4SBo Jiao } 77699ad32a4SBo Jiao 77799ad32a4SBo Jiao static void mt7986_wmac_subsys_setting(struct mt7915_dev *dev) 77899ad32a4SBo Jiao { 77999ad32a4SBo Jiao /* Subsys pll init */ 78099ad32a4SBo Jiao mt7986_wmac_subsys_pll_initial(dev, 0); 78199ad32a4SBo Jiao mt7986_wmac_subsys_pll_initial(dev, 1); 78299ad32a4SBo Jiao 78399ad32a4SBo Jiao /* Set legacy OSC control stable time*/ 78499ad32a4SBo Jiao mt76_rmw(dev, MT_CONN_INFRA_OSC_RC_EN, 78599ad32a4SBo Jiao MT_CONN_INFRA_OSC_RC_EN_MASK, 0x0); 78699ad32a4SBo Jiao mt76_rmw(dev, MT_CONN_INFRA_OSC_CTRL, 78799ad32a4SBo Jiao MT_CONN_INFRA_OSC_STB_TIME_MASK, 0x80706); 78899ad32a4SBo Jiao 78999ad32a4SBo Jiao /* prevent subsys from power on/of in a short time interval */ 79099ad32a4SBo Jiao mt76_rmw(dev, MT_TOP_WFSYS_PWR, 79199ad32a4SBo Jiao MT_TOP_PWR_ACK_MASK | MT_TOP_PWR_KEY_MASK, 79299ad32a4SBo Jiao MT_TOP_PWR_KEY); 79399ad32a4SBo Jiao } 79499ad32a4SBo Jiao 79599ad32a4SBo Jiao static int mt7986_wmac_bus_timeout(struct mt7915_dev *dev) 79699ad32a4SBo Jiao { 79799ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_BUS_OFF_TIMEOUT, 79899ad32a4SBo Jiao MT_INFRA_BUS_TIMEOUT_LIMIT_MASK, 0x2); 79999ad32a4SBo Jiao 80099ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_BUS_OFF_TIMEOUT, 80199ad32a4SBo Jiao MT_INFRA_BUS_TIMEOUT_EN_MASK, 0xf); 80299ad32a4SBo Jiao 80399ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_BUS_ON_TIMEOUT, 80499ad32a4SBo Jiao MT_INFRA_BUS_TIMEOUT_LIMIT_MASK, 0xc); 80599ad32a4SBo Jiao 80699ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_BUS_ON_TIMEOUT, 80799ad32a4SBo Jiao MT_INFRA_BUS_TIMEOUT_EN_MASK, 0xf); 80899ad32a4SBo Jiao 80999ad32a4SBo Jiao return mt7986_wmac_coninfra_check(dev); 81099ad32a4SBo Jiao } 81199ad32a4SBo Jiao 81299ad32a4SBo Jiao static void mt7986_wmac_clock_enable(struct mt7915_dev *dev, u32 adie_type) 81399ad32a4SBo Jiao { 81499ad32a4SBo Jiao u32 cur; 81599ad32a4SBo Jiao 81699ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_1, 81799ad32a4SBo Jiao MT_INFRA_CKGEN_DIV_SEL_MASK, 0x1); 81899ad32a4SBo Jiao 81999ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_2, 82099ad32a4SBo Jiao MT_INFRA_CKGEN_DIV_SEL_MASK, 0x1); 82199ad32a4SBo Jiao 82299ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_1, 82399ad32a4SBo Jiao MT_INFRA_CKGEN_DIV_EN_MASK, 0x1); 82499ad32a4SBo Jiao 82599ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS_WPLL_DIV_2, 82699ad32a4SBo Jiao MT_INFRA_CKGEN_DIV_EN_MASK, 0x1); 82799ad32a4SBo Jiao 82899ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_RFSPI_WPLL_DIV, 82999ad32a4SBo Jiao MT_INFRA_CKGEN_DIV_SEL_MASK, 0x8); 83099ad32a4SBo Jiao 83199ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_RFSPI_WPLL_DIV, 83299ad32a4SBo Jiao MT_INFRA_CKGEN_DIV_EN_MASK, 0x1); 83399ad32a4SBo Jiao 83499ad32a4SBo Jiao mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS, 83599ad32a4SBo Jiao MT_INFRA_CKGEN_BUS_CLK_SEL_MASK, 0x0); 83699ad32a4SBo Jiao 83799ad32a4SBo Jiao mt76_rmw_field(dev, MT_CONN_INFRA_HW_CTRL, 83899ad32a4SBo Jiao MT_CONN_INFRA_HW_CTRL_MASK, 0x1); 83999ad32a4SBo Jiao 84099ad32a4SBo Jiao mt76_rmw(dev, MT_TOP_CONN_INFRA_WAKEUP, 84199ad32a4SBo Jiao MT_TOP_CONN_INFRA_WAKEUP_MASK, 0x1); 84299ad32a4SBo Jiao 84399ad32a4SBo Jiao usleep_range(900, 1000); 84499ad32a4SBo Jiao 84599ad32a4SBo Jiao mt76_wmac_spi_lock(dev); 84699ad32a4SBo Jiao if (is_7975(dev, 0, adie_type) || is_7976(dev, 0, adie_type)) { 84799ad32a4SBo Jiao mt76_rmw_field(dev, MT_ADIE_SLP_CTRL_CK0(0), 84899ad32a4SBo Jiao MT_SLP_CTRL_EN_MASK, 0x1); 84999ad32a4SBo Jiao 85099ad32a4SBo Jiao read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_CTRL_BSY_MASK), 85199ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, 85299ad32a4SBo Jiao dev, MT_ADIE_SLP_CTRL_CK0(0)); 85399ad32a4SBo Jiao } 85499ad32a4SBo Jiao if (is_7975(dev, 1, adie_type) || is_7976(dev, 1, adie_type)) { 85599ad32a4SBo Jiao mt76_rmw_field(dev, MT_ADIE_SLP_CTRL_CK0(1), 85699ad32a4SBo Jiao MT_SLP_CTRL_EN_MASK, 0x1); 85799ad32a4SBo Jiao 85899ad32a4SBo Jiao read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_CTRL_BSY_MASK), 85999ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, 86099ad32a4SBo Jiao dev, MT_ADIE_SLP_CTRL_CK0(0)); 86199ad32a4SBo Jiao } 86299ad32a4SBo Jiao mt76_wmac_spi_unlock(dev); 86399ad32a4SBo Jiao 86499ad32a4SBo Jiao mt76_rmw(dev, MT_TOP_CONN_INFRA_WAKEUP, 86599ad32a4SBo Jiao MT_TOP_CONN_INFRA_WAKEUP_MASK, 0x0); 86699ad32a4SBo Jiao usleep_range(900, 1000); 86799ad32a4SBo Jiao } 86899ad32a4SBo Jiao 86999ad32a4SBo Jiao static int mt7986_wmac_top_wfsys_wakeup(struct mt7915_dev *dev, bool enable) 87099ad32a4SBo Jiao { 87199ad32a4SBo Jiao mt76_rmw_field(dev, MT_TOP_WFSYS_WAKEUP, 87299ad32a4SBo Jiao MT_TOP_WFSYS_WAKEUP_MASK, enable); 87399ad32a4SBo Jiao 87499ad32a4SBo Jiao usleep_range(900, 1000); 87599ad32a4SBo Jiao 87699ad32a4SBo Jiao if (!enable) 87799ad32a4SBo Jiao return 0; 87899ad32a4SBo Jiao 87999ad32a4SBo Jiao return mt7986_wmac_coninfra_check(dev); 88099ad32a4SBo Jiao } 88199ad32a4SBo Jiao 88299ad32a4SBo Jiao static int mt7986_wmac_wm_enable(struct mt7915_dev *dev, bool enable) 88399ad32a4SBo Jiao { 88499ad32a4SBo Jiao u32 cur; 88599ad32a4SBo Jiao 886*0ad6b97eSPeter Chiu mt76_wr(dev, MT_CONNINFRA_SKU_DEC_ADDR, 0); 887*0ad6b97eSPeter Chiu 88899ad32a4SBo Jiao mt76_rmw_field(dev, MT7986_TOP_WM_RESET, 88999ad32a4SBo Jiao MT7986_TOP_WM_RESET_MASK, enable); 89099ad32a4SBo Jiao if (!enable) 89199ad32a4SBo Jiao return 0; 89299ad32a4SBo Jiao 89399ad32a4SBo Jiao return read_poll_timeout(mt76_rr, cur, (cur == 0x1d1e), 89499ad32a4SBo Jiao USEC_PER_MSEC, 5000 * USEC_PER_MSEC, false, 89599ad32a4SBo Jiao dev, MT_TOP_CFG_ON_ROM_IDX); 89699ad32a4SBo Jiao } 89799ad32a4SBo Jiao 89899ad32a4SBo Jiao static int mt7986_wmac_wfsys_poweron(struct mt7915_dev *dev, bool enable) 89999ad32a4SBo Jiao { 90099ad32a4SBo Jiao u32 mask = MT_TOP_PWR_EN_MASK | MT_TOP_PWR_KEY_MASK; 90199ad32a4SBo Jiao u32 cur; 90299ad32a4SBo Jiao 90399ad32a4SBo Jiao mt76_rmw(dev, MT_TOP_WFSYS_PWR, mask, 90499ad32a4SBo Jiao MT_TOP_PWR_KEY | FIELD_PREP(MT_TOP_PWR_EN_MASK, enable)); 90599ad32a4SBo Jiao 90699ad32a4SBo Jiao return read_poll_timeout(mt76_rr, cur, 90799ad32a4SBo Jiao (FIELD_GET(MT_TOP_WFSYS_RESET_STATUS_MASK, cur) == enable), 90899ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, 90999ad32a4SBo Jiao dev, MT_TOP_WFSYS_RESET_STATUS); 91099ad32a4SBo Jiao } 91199ad32a4SBo Jiao 91299ad32a4SBo Jiao static int mt7986_wmac_wfsys_setting(struct mt7915_dev *dev) 91399ad32a4SBo Jiao { 91499ad32a4SBo Jiao int ret; 91599ad32a4SBo Jiao u32 cur; 91699ad32a4SBo Jiao 91799ad32a4SBo Jiao /* Turn off wfsys2conn bus sleep protect */ 91899ad32a4SBo Jiao mt76_rmw(dev, MT_CONN_INFRA_WF_SLP_PROT, 91999ad32a4SBo Jiao MT_CONN_INFRA_WF_SLP_PROT_MASK, 0x0); 92099ad32a4SBo Jiao 92199ad32a4SBo Jiao ret = mt7986_wmac_wfsys_poweron(dev, true); 92299ad32a4SBo Jiao if (ret) 92399ad32a4SBo Jiao return ret; 92499ad32a4SBo Jiao 92599ad32a4SBo Jiao /* Check bus sleep protect */ 92699ad32a4SBo Jiao 92799ad32a4SBo Jiao ret = read_poll_timeout(mt76_rr, cur, 92899ad32a4SBo Jiao !(cur & MT_CONN_INFRA_CONN_WF_MASK), 92999ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, 93099ad32a4SBo Jiao dev, MT_CONN_INFRA_WF_SLP_PROT_RDY); 93199ad32a4SBo Jiao if (ret) 93299ad32a4SBo Jiao return ret; 93399ad32a4SBo Jiao 93499ad32a4SBo Jiao ret = read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_WFDMA2CONN_MASK), 93599ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, 93699ad32a4SBo Jiao dev, MT_SLP_STATUS); 93799ad32a4SBo Jiao if (ret) 93899ad32a4SBo Jiao return ret; 93999ad32a4SBo Jiao 94099ad32a4SBo Jiao return read_poll_timeout(mt76_rr, cur, (cur == 0x02060000), 94199ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, 94299ad32a4SBo Jiao dev, MT_TOP_CFG_IP_VERSION_ADDR); 94399ad32a4SBo Jiao } 94499ad32a4SBo Jiao 94599ad32a4SBo Jiao static void mt7986_wmac_wfsys_set_timeout(struct mt7915_dev *dev) 94699ad32a4SBo Jiao { 94799ad32a4SBo Jiao u32 mask = MT_MCU_BUS_TIMEOUT_SET_MASK | 94899ad32a4SBo Jiao MT_MCU_BUS_TIMEOUT_CG_EN_MASK | 94999ad32a4SBo Jiao MT_MCU_BUS_TIMEOUT_EN_MASK; 95099ad32a4SBo Jiao u32 val = FIELD_PREP(MT_MCU_BUS_TIMEOUT_SET_MASK, 1) | 95199ad32a4SBo Jiao FIELD_PREP(MT_MCU_BUS_TIMEOUT_CG_EN_MASK, 1) | 95299ad32a4SBo Jiao FIELD_PREP(MT_MCU_BUS_TIMEOUT_EN_MASK, 1); 95399ad32a4SBo Jiao 95499ad32a4SBo Jiao mt76_rmw(dev, MT_MCU_BUS_TIMEOUT, mask, val); 95599ad32a4SBo Jiao 95699ad32a4SBo Jiao mt76_wr(dev, MT_MCU_BUS_REMAP, 0x810f0000); 95799ad32a4SBo Jiao 95899ad32a4SBo Jiao mask = MT_MCU_BUS_DBG_TIMEOUT_SET_MASK | 95999ad32a4SBo Jiao MT_MCU_BUS_DBG_TIMEOUT_CK_EN_MASK | 96099ad32a4SBo Jiao MT_MCU_BUS_DBG_TIMEOUT_EN_MASK; 96199ad32a4SBo Jiao val = FIELD_PREP(MT_MCU_BUS_DBG_TIMEOUT_SET_MASK, 0x3aa) | 96299ad32a4SBo Jiao FIELD_PREP(MT_MCU_BUS_DBG_TIMEOUT_CK_EN_MASK, 1) | 96399ad32a4SBo Jiao FIELD_PREP(MT_MCU_BUS_DBG_TIMEOUT_EN_MASK, 1); 96499ad32a4SBo Jiao 96599ad32a4SBo Jiao mt76_rmw(dev, MT_MCU_BUS_DBG_TIMEOUT, mask, val); 96699ad32a4SBo Jiao } 96799ad32a4SBo Jiao 96899ad32a4SBo Jiao static int mt7986_wmac_sku_update(struct mt7915_dev *dev, u32 adie_type) 96999ad32a4SBo Jiao { 97099ad32a4SBo Jiao u32 val; 97199ad32a4SBo Jiao 97299ad32a4SBo Jiao if (is_7976(dev, 0, adie_type) && is_7976(dev, 1, adie_type)) 97399ad32a4SBo Jiao val = 0xf; 97499ad32a4SBo Jiao else if (is_7975(dev, 0, adie_type) && is_7975(dev, 1, adie_type)) 97599ad32a4SBo Jiao val = 0xd; 97699ad32a4SBo Jiao else if (is_7976(dev, 0, adie_type)) 97799ad32a4SBo Jiao val = 0x7; 97899ad32a4SBo Jiao else if (is_7975(dev, 1, adie_type)) 97999ad32a4SBo Jiao val = 0x8; 98099ad32a4SBo Jiao else if (is_7976(dev, 1, adie_type)) 98199ad32a4SBo Jiao val = 0xa; 98299ad32a4SBo Jiao else 98399ad32a4SBo Jiao return -EINVAL; 98499ad32a4SBo Jiao 98599ad32a4SBo Jiao mt76_wmac_rmw(dev->sku, MT_TOP_POS_SKU, MT_TOP_POS_SKU_MASK, 98699ad32a4SBo Jiao FIELD_PREP(MT_TOP_POS_SKU_MASK, val)); 98799ad32a4SBo Jiao 98899ad32a4SBo Jiao mt76_wr(dev, MT_CONNINFRA_SKU_DEC_ADDR, val); 98999ad32a4SBo Jiao 99099ad32a4SBo Jiao return 0; 99199ad32a4SBo Jiao } 99299ad32a4SBo Jiao 99399ad32a4SBo Jiao static int 99499ad32a4SBo Jiao mt7986_wmac_adie_setup(struct mt7915_dev *dev, u8 adie, u32 adie_type) 99599ad32a4SBo Jiao { 99699ad32a4SBo Jiao int ret; 99799ad32a4SBo Jiao 99899ad32a4SBo Jiao if (!(is_7975(dev, adie, adie_type) || is_7976(dev, adie, adie_type))) 99999ad32a4SBo Jiao return 0; 100099ad32a4SBo Jiao 100199ad32a4SBo Jiao ret = mt7986_wmac_adie_cfg(dev, adie, adie_type); 100299ad32a4SBo Jiao if (ret) 100399ad32a4SBo Jiao return ret; 100499ad32a4SBo Jiao 100599ad32a4SBo Jiao ret = mt7986_wmac_afe_cal(dev, adie, false, adie_type); 100699ad32a4SBo Jiao if (ret) 100799ad32a4SBo Jiao return ret; 100899ad32a4SBo Jiao 100999ad32a4SBo Jiao if (!adie && (mt7986_wmac_check_adie_type(dev) == ADIE_DBDC)) 101099ad32a4SBo Jiao ret = mt7986_wmac_afe_cal(dev, adie, true, adie_type); 101199ad32a4SBo Jiao 101299ad32a4SBo Jiao return ret; 101399ad32a4SBo Jiao } 101499ad32a4SBo Jiao 101599ad32a4SBo Jiao static int mt7986_wmac_subsys_powerup(struct mt7915_dev *dev, u32 adie_type) 101699ad32a4SBo Jiao { 101799ad32a4SBo Jiao int ret; 101899ad32a4SBo Jiao 101999ad32a4SBo Jiao mt7986_wmac_subsys_setting(dev); 102099ad32a4SBo Jiao 102199ad32a4SBo Jiao ret = mt7986_wmac_bus_timeout(dev); 102299ad32a4SBo Jiao if (ret) 102399ad32a4SBo Jiao return ret; 102499ad32a4SBo Jiao 102599ad32a4SBo Jiao mt7986_wmac_clock_enable(dev, adie_type); 102699ad32a4SBo Jiao 102799ad32a4SBo Jiao return 0; 102899ad32a4SBo Jiao } 102999ad32a4SBo Jiao 103099ad32a4SBo Jiao static int mt7986_wmac_wfsys_powerup(struct mt7915_dev *dev) 103199ad32a4SBo Jiao { 103299ad32a4SBo Jiao int ret; 103399ad32a4SBo Jiao 103499ad32a4SBo Jiao ret = mt7986_wmac_wm_enable(dev, false); 103599ad32a4SBo Jiao if (ret) 103699ad32a4SBo Jiao return ret; 103799ad32a4SBo Jiao 103899ad32a4SBo Jiao ret = mt7986_wmac_wfsys_setting(dev); 103999ad32a4SBo Jiao if (ret) 104099ad32a4SBo Jiao return ret; 104199ad32a4SBo Jiao 104299ad32a4SBo Jiao mt7986_wmac_wfsys_set_timeout(dev); 104399ad32a4SBo Jiao 104499ad32a4SBo Jiao return mt7986_wmac_wm_enable(dev, true); 104599ad32a4SBo Jiao } 104699ad32a4SBo Jiao 104799ad32a4SBo Jiao int mt7986_wmac_enable(struct mt7915_dev *dev) 104899ad32a4SBo Jiao { 104999ad32a4SBo Jiao int ret; 105099ad32a4SBo Jiao u32 adie_type; 105199ad32a4SBo Jiao 105299ad32a4SBo Jiao ret = mt7986_wmac_consys_reset(dev, true); 105399ad32a4SBo Jiao if (ret) 105499ad32a4SBo Jiao return ret; 105599ad32a4SBo Jiao 105699ad32a4SBo Jiao ret = mt7986_wmac_gpio_setup(dev); 105799ad32a4SBo Jiao if (ret) 105899ad32a4SBo Jiao return ret; 105999ad32a4SBo Jiao 106099ad32a4SBo Jiao ret = mt7986_wmac_consys_lockup(dev, false); 106199ad32a4SBo Jiao if (ret) 106299ad32a4SBo Jiao return ret; 106399ad32a4SBo Jiao 106499ad32a4SBo Jiao ret = mt7986_wmac_coninfra_check(dev); 106599ad32a4SBo Jiao if (ret) 106699ad32a4SBo Jiao return ret; 106799ad32a4SBo Jiao 106899ad32a4SBo Jiao ret = mt7986_wmac_coninfra_setup(dev); 106999ad32a4SBo Jiao if (ret) 107099ad32a4SBo Jiao return ret; 107199ad32a4SBo Jiao 107299ad32a4SBo Jiao ret = mt7986_wmac_sku_setup(dev, &adie_type); 107399ad32a4SBo Jiao if (ret) 107499ad32a4SBo Jiao return ret; 107599ad32a4SBo Jiao 107699ad32a4SBo Jiao ret = mt7986_wmac_adie_setup(dev, 0, adie_type); 107799ad32a4SBo Jiao if (ret) 107899ad32a4SBo Jiao return ret; 107999ad32a4SBo Jiao 108099ad32a4SBo Jiao ret = mt7986_wmac_adie_setup(dev, 1, adie_type); 108199ad32a4SBo Jiao if (ret) 108299ad32a4SBo Jiao return ret; 108399ad32a4SBo Jiao 108499ad32a4SBo Jiao ret = mt7986_wmac_subsys_powerup(dev, adie_type); 108599ad32a4SBo Jiao if (ret) 108699ad32a4SBo Jiao return ret; 108799ad32a4SBo Jiao 108899ad32a4SBo Jiao ret = mt7986_wmac_top_wfsys_wakeup(dev, true); 108999ad32a4SBo Jiao if (ret) 109099ad32a4SBo Jiao return ret; 109199ad32a4SBo Jiao 109299ad32a4SBo Jiao ret = mt7986_wmac_wfsys_powerup(dev); 109399ad32a4SBo Jiao if (ret) 109499ad32a4SBo Jiao return ret; 109599ad32a4SBo Jiao 109699ad32a4SBo Jiao return mt7986_wmac_sku_update(dev, adie_type); 109799ad32a4SBo Jiao } 109899ad32a4SBo Jiao 109999ad32a4SBo Jiao void mt7986_wmac_disable(struct mt7915_dev *dev) 110099ad32a4SBo Jiao { 110199ad32a4SBo Jiao u32 cur; 110299ad32a4SBo Jiao 110399ad32a4SBo Jiao mt7986_wmac_top_wfsys_wakeup(dev, true); 110499ad32a4SBo Jiao 110599ad32a4SBo Jiao /* Turn on wfsys2conn bus sleep protect */ 110699ad32a4SBo Jiao mt76_rmw_field(dev, MT_CONN_INFRA_WF_SLP_PROT, 110799ad32a4SBo Jiao MT_CONN_INFRA_WF_SLP_PROT_MASK, 0x1); 110899ad32a4SBo Jiao 110999ad32a4SBo Jiao /* Check wfsys2conn bus sleep protect */ 111099ad32a4SBo Jiao read_poll_timeout(mt76_rr, cur, !(cur ^ MT_CONN_INFRA_CONN), 111199ad32a4SBo Jiao USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, 111299ad32a4SBo Jiao dev, MT_CONN_INFRA_WF_SLP_PROT_RDY); 111399ad32a4SBo Jiao 111499ad32a4SBo Jiao mt7986_wmac_wfsys_poweron(dev, false); 111599ad32a4SBo Jiao 111699ad32a4SBo Jiao /* Turn back wpll setting */ 111799ad32a4SBo Jiao mt76_rmw_field(dev, MT_AFE_DIG_EN_02(0), MT_AFE_MCU_BPLL_CFG_MASK, 0x2); 111899ad32a4SBo Jiao mt76_rmw_field(dev, MT_AFE_DIG_EN_02(0), MT_AFE_WPLL_CFG_MASK, 0x2); 111999ad32a4SBo Jiao 112099ad32a4SBo Jiao /* Reset EMI */ 112199ad32a4SBo Jiao mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ, 112299ad32a4SBo Jiao MT_CONN_INFRA_EMI_REQ_MASK, 0x1); 112399ad32a4SBo Jiao mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ, 112499ad32a4SBo Jiao MT_CONN_INFRA_EMI_REQ_MASK, 0x0); 112599ad32a4SBo Jiao mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ, 112699ad32a4SBo Jiao MT_CONN_INFRA_INFRA_REQ_MASK, 0x1); 112799ad32a4SBo Jiao mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ, 112899ad32a4SBo Jiao MT_CONN_INFRA_INFRA_REQ_MASK, 0x0); 112999ad32a4SBo Jiao 113099ad32a4SBo Jiao mt7986_wmac_top_wfsys_wakeup(dev, false); 113199ad32a4SBo Jiao mt7986_wmac_consys_lockup(dev, true); 113299ad32a4SBo Jiao mt7986_wmac_consys_reset(dev, false); 113399ad32a4SBo Jiao } 113499ad32a4SBo Jiao 113599ad32a4SBo Jiao static int mt7986_wmac_init(struct mt7915_dev *dev) 113699ad32a4SBo Jiao { 113799ad32a4SBo Jiao struct device *pdev = dev->mt76.dev; 113899ad32a4SBo Jiao struct platform_device *pfdev = to_platform_device(pdev); 1139cd85efdfSLorenzo Bianconi struct clk *mcu_clk, *ap_conn_clk; 1140cd85efdfSLorenzo Bianconi 1141cd85efdfSLorenzo Bianconi mcu_clk = devm_clk_get(pdev, "mcu"); 1142cd85efdfSLorenzo Bianconi if (IS_ERR(mcu_clk)) 1143cd85efdfSLorenzo Bianconi dev_err(pdev, "mcu clock not found\n"); 1144cd85efdfSLorenzo Bianconi else if (clk_prepare_enable(mcu_clk)) 1145cd85efdfSLorenzo Bianconi dev_err(pdev, "mcu clock configuration failed\n"); 1146cd85efdfSLorenzo Bianconi 1147cd85efdfSLorenzo Bianconi ap_conn_clk = devm_clk_get(pdev, "ap2conn"); 1148cd85efdfSLorenzo Bianconi if (IS_ERR(ap_conn_clk)) 1149cd85efdfSLorenzo Bianconi dev_err(pdev, "ap2conn clock not found\n"); 1150cd85efdfSLorenzo Bianconi else if (clk_prepare_enable(ap_conn_clk)) 1151cd85efdfSLorenzo Bianconi dev_err(pdev, "ap2conn clock configuration failed\n"); 115299ad32a4SBo Jiao 115399ad32a4SBo Jiao dev->dcm = devm_platform_ioremap_resource(pfdev, 1); 115499ad32a4SBo Jiao if (IS_ERR(dev->dcm)) 115599ad32a4SBo Jiao return PTR_ERR(dev->dcm); 115699ad32a4SBo Jiao 115799ad32a4SBo Jiao dev->sku = devm_platform_ioremap_resource(pfdev, 2); 115899ad32a4SBo Jiao if (IS_ERR(dev->sku)) 115999ad32a4SBo Jiao return PTR_ERR(dev->sku); 116099ad32a4SBo Jiao 116199ad32a4SBo Jiao dev->rstc = devm_reset_control_get(pdev, "consys"); 116299ad32a4SBo Jiao if (IS_ERR(dev->rstc)) 116399ad32a4SBo Jiao return PTR_ERR(dev->rstc); 116499ad32a4SBo Jiao 11655beadb27SRyder Lee return 0; 116699ad32a4SBo Jiao } 116799ad32a4SBo Jiao 116899ad32a4SBo Jiao static int mt7986_wmac_probe(struct platform_device *pdev) 116999ad32a4SBo Jiao { 117099ad32a4SBo Jiao void __iomem *mem_base; 117199ad32a4SBo Jiao struct mt7915_dev *dev; 117299ad32a4SBo Jiao struct mt76_dev *mdev; 117399ad32a4SBo Jiao int irq, ret; 117499ad32a4SBo Jiao u32 chip_id; 117599ad32a4SBo Jiao 117699ad32a4SBo Jiao chip_id = (uintptr_t)of_device_get_match_data(&pdev->dev); 117799ad32a4SBo Jiao 117899ad32a4SBo Jiao mem_base = devm_platform_ioremap_resource(pdev, 0); 117999ad32a4SBo Jiao if (IS_ERR(mem_base)) { 118099ad32a4SBo Jiao dev_err(&pdev->dev, "Failed to get memory resource\n"); 118199ad32a4SBo Jiao return PTR_ERR(mem_base); 118299ad32a4SBo Jiao } 118399ad32a4SBo Jiao 118499ad32a4SBo Jiao dev = mt7915_mmio_probe(&pdev->dev, mem_base, chip_id); 118599ad32a4SBo Jiao if (IS_ERR(dev)) 118699ad32a4SBo Jiao return PTR_ERR(dev); 118799ad32a4SBo Jiao 118899ad32a4SBo Jiao mdev = &dev->mt76; 1189eebb7097SLorenzo Bianconi ret = mt7915_mmio_wed_init(dev, pdev, false, &irq); 1190eebb7097SLorenzo Bianconi if (ret < 0) 1191eebb7097SLorenzo Bianconi goto free_device; 1192eebb7097SLorenzo Bianconi 1193eebb7097SLorenzo Bianconi if (!ret) { 1194eebb7097SLorenzo Bianconi irq = platform_get_irq(pdev, 0); 1195eebb7097SLorenzo Bianconi if (irq < 0) { 1196eebb7097SLorenzo Bianconi ret = irq; 1197eebb7097SLorenzo Bianconi goto free_device; 1198eebb7097SLorenzo Bianconi } 1199eebb7097SLorenzo Bianconi } 1200eebb7097SLorenzo Bianconi 120199ad32a4SBo Jiao ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler, 120299ad32a4SBo Jiao IRQF_SHARED, KBUILD_MODNAME, dev); 120399ad32a4SBo Jiao if (ret) 120499ad32a4SBo Jiao goto free_device; 120599ad32a4SBo Jiao 120699ad32a4SBo Jiao ret = mt7986_wmac_init(dev); 120799ad32a4SBo Jiao if (ret) 120899ad32a4SBo Jiao goto free_irq; 120999ad32a4SBo Jiao 12105beadb27SRyder Lee mt7915_wfsys_reset(dev); 12115beadb27SRyder Lee 121299ad32a4SBo Jiao ret = mt7915_register_device(dev); 121399ad32a4SBo Jiao if (ret) 121499ad32a4SBo Jiao goto free_irq; 121599ad32a4SBo Jiao 121699ad32a4SBo Jiao return 0; 121799ad32a4SBo Jiao 121899ad32a4SBo Jiao free_irq: 121999ad32a4SBo Jiao devm_free_irq(mdev->dev, irq, dev); 122099ad32a4SBo Jiao free_device: 1221eebb7097SLorenzo Bianconi if (mtk_wed_device_active(&mdev->mmio.wed)) 1222eebb7097SLorenzo Bianconi mtk_wed_device_detach(&mdev->mmio.wed); 1223eebb7097SLorenzo Bianconi mt76_free_device(mdev); 122499ad32a4SBo Jiao 122599ad32a4SBo Jiao return ret; 122699ad32a4SBo Jiao } 122799ad32a4SBo Jiao 122899ad32a4SBo Jiao static int mt7986_wmac_remove(struct platform_device *pdev) 122999ad32a4SBo Jiao { 123099ad32a4SBo Jiao struct mt7915_dev *dev = platform_get_drvdata(pdev); 123199ad32a4SBo Jiao 123299ad32a4SBo Jiao mt7915_unregister_device(dev); 123399ad32a4SBo Jiao 123499ad32a4SBo Jiao return 0; 123599ad32a4SBo Jiao } 123699ad32a4SBo Jiao 123799ad32a4SBo Jiao static const struct of_device_id mt7986_wmac_of_match[] = { 123899ad32a4SBo Jiao { .compatible = "mediatek,mt7986-wmac", .data = (u32 *)0x7986 }, 123999ad32a4SBo Jiao {}, 124099ad32a4SBo Jiao }; 124199ad32a4SBo Jiao 124299ad32a4SBo Jiao struct platform_driver mt7986_wmac_driver = { 124399ad32a4SBo Jiao .driver = { 124499ad32a4SBo Jiao .name = "mt7986-wmac", 124599ad32a4SBo Jiao .of_match_table = mt7986_wmac_of_match, 124699ad32a4SBo Jiao }, 124799ad32a4SBo Jiao .probe = mt7986_wmac_probe, 124899ad32a4SBo Jiao .remove = mt7986_wmac_remove, 124999ad32a4SBo Jiao }; 125099ad32a4SBo Jiao 125199ad32a4SBo Jiao MODULE_FIRMWARE(MT7986_FIRMWARE_WA); 125299ad32a4SBo Jiao MODULE_FIRMWARE(MT7986_FIRMWARE_WM); 125399ad32a4SBo Jiao MODULE_FIRMWARE(MT7986_FIRMWARE_WM_MT7975); 125499ad32a4SBo Jiao MODULE_FIRMWARE(MT7986_ROM_PATCH); 125599ad32a4SBo Jiao MODULE_FIRMWARE(MT7986_ROM_PATCH_MT7975); 1256